Category: Azure

Jun 23

AWS VPN to Libreswan

AWS VPN to Azure VM with Libreswan

NOTE: As of this article AWS Site to Site VPN gateway can generate an Openswan configuration but not Libreswan. This is a test to use Libreswan.

Using an Azure Virtual Machine on the left and AWS VPN gateway on the right but of course can also use Azure VPN service

For reference OCI to Libreswan from a while back

Setup right side in AWS Console

  • Create Customer Gateway > azure-gw01 using Static Routing and specify Azure VM IP Address - Create Virtual Private Gateway az-vpg01 Amazon default ASN
  • Attach VPG to VPC
    For Site-to-Site VPN
  • Create VPN Connection > iqonda-aws-azure pick VPG and CG Routing Static leave all defaults for now and no Static IP Prefixes for the moment
  • Record Tunnel1 IP Address

Setup left side in Azure

Create a Centos VM in Azure

  • Virtual machines > Add
    | test01 | CentOS-based 8.1 | Standard_B1ls 1 vcpu, 0.5 GiB memory ($3.80/month) | AzureUser
    * I used a password for AzureUser and sort out SSH keys after logged in.

  • I used | Standard HDD | myVnet | mySubnet(10.0.0.0/24)

  • record public IP

  • Network add inbound rules for ipsec. I did an all traffic for the AWS endpoint IP address but you want to be more specific on ipsec ports.

software

# cat /etc/centos-release
CentOS Linux release 8.1.1911 (Core) 

# yum install libreswan

# echo "net.ipv4.ip_forward=1" > /usr/lib/sysctl.d/60-ipsec.conf
# sysctl -p /usr/lib/sysctl.d/60-ipsec.conf
net.ipv4.ip_forward = 1

# for s in /proc/sys/net/ipv4/conf/*; do echo 0 > $s/send_redirects; echo 0 > $s/accept_redirects; done

# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

# ipsec verify
Verifying installed system and configuration files

Version check and ipsec on-path                     [OK]
Libreswan 3.29 (netkey) on 4.18.0-147.8.1.el8_1.x86_64
Checking for IPsec support in kernel                [OK]
 NETKEY: Testing XFRM related proc values
         ICMP default/send_redirects                [OK]
         ICMP default/accept_redirects              [OK]
         XFRM larval drop                           [OK]
Pluto ipsec.conf syntax                             [OK]
Checking rp_filter                                  [OK]
Checking that pluto is running                      [OK]
 Pluto listening for IKE on udp 500                 [OK]
 Pluto listening for IKE/NAT-T on udp 4500          [OK]
 Pluto ipsec.secret syntax                          [OK]
Checking 'ip' command                               [OK]
Checking 'iptables' command                         [OK]
Checking 'prelink' command does not interfere with FIPS [OK]
Checking for obsolete ipsec.conf options            [OK]

NOTE: skipping firewalld and rules. this instance did not have firewalld enabled and iptables -L is open.

Download openswan config in AWS console to see the PSK

I had issues bringing the tunnel up but after reboot it works

post tunnel UP

  • add static route(s) to VPN
  • check route table for subnet
  • enable subnet association to route table
  • enable route propagation

ping test both ways works...

source

[root@test01 ipsec.d]# cat aws-az-vpn.conf 
conn Tunnel1
        authby=secret
        auto=start
        encapsulation=yes
        left=%defaultroute
        leftid=[Azure VM IP]
        right=[AWS VPN Tunnel 1 IP]
        type=tunnel
        phase2alg=aes128-sha1;modp1024
        ike=aes128-sha1;modp1024
        leftsubnet=10.0.1.0/16
        rightsubnet=172.31.0.0/16

conn Tunnel2
        authby=secret
        auto=add
        encapsulation=yes
        left=%defaultroute
        leftid=[Azure VM IP]
        right=[AWS VPN Tunnel 2 IP]
        type=tunnel
        phase2alg=aes128-sha1;modp1024
        ike=aes128-sha1;modp1024
        leftsubnet=10.0.1.0/16
        rightsubnet=172.31.0.0/16

[root@test01 ipsec.d]# cat aws-az-vpn.secrets 
52.188.118.56 18.214.218.99: PSK "Qgn...............mn"
52.188.118.56 52.3.140.122: PSK "cWu..................87"

Tunnel switch

Although Libreswan can't manage two tunnels to the same right side without something like Quagga at least I did a very quick and dirty switchover script. It works and very minimal pings missed.

[root@test01 ~]# cat switch-aws-tunnel.sh 
#!/bin/bash
echo "Current Tunnel Status"
ipsec status | grep routed

active=$(ipsec status | grep erouted | cut -d \" -f2)
inactive=$(ipsec status | grep unrouted | cut -d \" -f2)

echo "Showing active and inactive in tunnels"
echo "active: $active"
echo "inactive: $inactive"

echo "down tunnels...."
ipsec auto --down $active
ipsec auto --down $inactive

echo "adding tunnels...."
ipsec auto --add Tunnel1
ipsec auto --add Tunnel2

echo "up the tunnel that was inactive before...."
ipsec auto --up $inactive

echo "Current Tunnel Status"
ipsec status | grep routed

Comments Off on AWS VPN to Libreswan
comments

May 20

Traefik Wildcard Certificate using Azure DNS

dns challenge letsencrypt Azure DNS

Using Traefik as edge router(reverse proxy) to http sites and enabling a Lets Encrypt ACME v2 wildcard certificate on the docker Traefik container. Verify ourselves using DNS, specifically the dns-01 method, because DNS verification doesn’t interrupt your web server and it works even if your server is unreachable from the outside world. Our DNS provider is Azure DNS.

Azure Configuration

Pre-req

  • azure cli setup
  • Wildcard DNS entry *.my.domain

Get subscription id

$ az account list | jq '.[] | .id'
"masked..."

Create role

$ az role definition create --role-definition role.json 
  {
    "assignableScopes": [
      "/subscriptions/masked..."
    ],
    "description": "Can manage DNS TXT records only.",
    "id": "/subscriptions/masked.../providers/Microsoft.Authorization/roleDefinitions/masked...",
    "name": "masked...",
    "permissions": [
      {
        "actions": [
          "Microsoft.Network/dnsZones/TXT/*",
          "Microsoft.Network/dnsZones/read",
          "Microsoft.Authorization/*/read",
          "Microsoft.Insights/alertRules/*",
          "Microsoft.ResourceHealth/availabilityStatuses/read",
          "Microsoft.Resources/deployments/read",
          "Microsoft.Resources/subscriptions/resourceGroups/read"
        ],
        "dataActions": [],
        "notActions": [],
        "notDataActions": []
      }
    ],
    "roleName": "DNS TXT Contributor",
    "roleType": "CustomRole",
    "type": "Microsoft.Authorization/roleDefinitions"
  }

NOTE: If you screwed up and need to delete do like like this:
az role definition delete --name "DNS TXT Contributor"

Create json file with correct subscription and create role definition

$ cat role.json
  {
    "Name":"DNS TXT Contributor",
    "Id":"",
    "IsCustom":true,
    "Description":"Can manage DNS TXT records only.",
    "Actions":[
      "Microsoft.Network/dnsZones/TXT/*",
      "Microsoft.Network/dnsZones/read",
      "Microsoft.Authorization/*/read",
      "Microsoft.Insights/alertRules/*",
      "Microsoft.ResourceHealth/availabilityStatuses/read",
      "Microsoft.Resources/deployments/read",
      "Microsoft.Resources/subscriptions/resourceGroups/read"
    ],
    "NotActions":[

    ],
    "AssignableScopes":[
      "/subscriptions/masked..."
    ]
  }

  $ az role definition create --role-definition role.json 
  {
    "assignableScopes": [
      "/subscriptions/masked..."
    ],
    "description": "Can manage DNS TXT records only.",
    "id": "/subscriptions/masked.../providers/Microsoft.Authorization/roleDefinitions/masked...",
    "name": "masked...",
    "permissions": [
      {
        "actions": [
          "Microsoft.Network/dnsZones/TXT/*",
          "Microsoft.Network/dnsZones/read",
          "Microsoft.Authorization/*/read",
          "Microsoft.Insights/alertRules/*",
          "Microsoft.ResourceHealth/availabilityStatuses/read",
          "Microsoft.Resources/deployments/read",
          "Microsoft.Resources/subscriptions/resourceGroups/read"
        ],
        "dataActions": [],
        "notActions": [],
        "notDataActions": []
      }
    ],
    "roleName": "DNS TXT Contributor",
    "roleType": "CustomRole",
    "type": "Microsoft.Authorization/roleDefinitions"
  }

Checking DNS and resource group

$ az network dns zone list
  [
    {
      "etag": "masked...",
      "id": "/subscriptions/masked.../resourceGroups/sites/providers/Microsoft.Network/dnszones/iqonda.net",
      "location": "global",
      "maxNumberOfRecordSets": 10000,
      "name": "masked...",
      "nameServers": [
        "ns1-09.azure-dns.com.",
        "ns2-09.azure-dns.net.",
        "ns3-09.azure-dns.org.",
        "ns4-09.azure-dns.info."
      ],
      "numberOfRecordSets": 14,
      "registrationVirtualNetworks": null,
      "resolutionVirtualNetworks": null,
      "resourceGroup": "masked...",
      "tags": {},
      "type": "Microsoft.Network/dnszones",
      "zoneType": "Public"
    }
  ]

$ az network dns zone list --output table
  ZoneName    ResourceGroup    RecordSets    MaxRecordSets
  ----------  ---------------  ------------  ---------------
  masked...  masked...            14            10000

$ az group list --output table
  Name                                Location        Status
  ----------------------------------  --------------  ---------
  cloud-shell-storage-southcentralus  southcentralus  Succeeded
  masked...                    eastus          Succeeded
  masked...                    eastus          Succeeded
  masked...                    eastus          Succeeded

role assign

  $ az ad sp create-for-rbac --name "Acme2DnsValidator" --role "DNS TXT Contributor" --scopes "/subscriptions/masked.../resourceGroups/sites/providers/Microsoft.Network/dnszones/masked..."
  Changing "Acme2DnsValidator" to a valid URI of "http://Acme2DnsValidator", which is the required format used for service principal names
  Found an existing application instance of "masked...". We will patch it
  Creating a role assignment under the scope of "/subscriptions/masked.../resourceGroups/sites/providers/Microsoft.Network/dnszones/masked..."
  {
    "appId": "masked...",
    "displayName": "Acme2DnsValidator",
    "name": "http://Acme2DnsValidator",
    "password": "masked...",
    "tenant": "masked..."
  }

  $ az ad sp create-for-rbac --name "Acme2DnsValidator" --role "DNS TXT Contributor" --scopes "/subscriptions/masked.../resourceGroups/masked..."
  Changing "Acme2DnsValidator" to a valid URI of "http://Acme2DnsValidator", which is the required format used for service principal names
  Found an existing application instance of "masked...". We will patch it
  Creating a role assignment under the scope of "/subscriptions/masked.../resourceGroups/masked..."
  {
    "appId": "masked...",
    "displayName": "Acme2DnsValidator",
    "name": "http://Acme2DnsValidator",
    "password": "masked...",
    "tenant": "masked..."
  }

  $ az role assignment list --all | jq -r '.[] | [.principalName,.roleDefinitionName,.scope]'
  [
    "http://Acme2DnsValidator",
    "DNS TXT Contributor",
    "/subscriptions/masked.../resourceGroups/masked..."
  ]
  [
    "masked...",
    "Owner",
    "/subscriptions/masked.../resourcegroups/masked.../providers/Microsoft.Storage/storageAccounts/masked..."
  ]
  [
    "http://Acme2DnsValidator",
    "DNS TXT Contributor",
    "/subscriptions/masked.../resourceGroups/masked.../providers/Microsoft.Network/dnszones/masked..."
  ]

$ az ad sp list | jq -r '.[] | [.displayName,.appId]'
  The result is not complete. You can still use '--all' to get all of them with long latency expected, or provide a filter through command arguments
...

  [
    "AzureDnsFrontendApp",
    "masked..."
  ]

  [
    "Azure DNS",
    "masked..."
  ]

Traefik Configuration

reference

Azure Credentials in environment file

$ cat .env
    AZURE_CLIENT_ID=masked...
    AZURE_CLIENT_SECRET=masked...
    AZURE_SUBSCRIPTION_ID=masked...
    AZURE_TENANT_ID=masked...
    AZURE_RESOURCE_GROUP=masked...
    #AZURE_METADATA_ENDPOINT=

Traefik Files

    $ cat traefik.yml 
    ## STATIC CONFIGURATION
    log:
      level: INFO

    api:
      insecure: true
      dashboard: true

    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"

    providers:
      docker:
        endpoint: "unix:///var/run/docker.sock"
        exposedByDefault: false

    certificatesResolvers:
      lets-encr:
        acme:
          #caServer: https://acme-staging-v02.api.letsencrypt.org/directory
          storage: acme.json
          email: admin@my.doman
          dnsChallenge:
            provider: azure

        $ cat docker-compose.yml 
        version: "3.3"

        services:

            traefik:
              image: "traefik:v2.2"
              container_name: "traefik"
              restart: always
              env_file:
                - .env
              command:
                #- "--log.level=DEBUG"
                - "--api.insecure=true"
                - "--providers.docker=true"
                - "--providers.docker.exposedbydefault=false"
              labels:
                 ## DNS CHALLENGE
                 - "traefik.http.routers.traefik.tls.certresolver=lets-encr"
                 - "traefik.http.routers.traefik.tls.domains[0].main=*.iqonda.net"
                 - "traefik.http.routers.traefik.tls.domains[0].sans=iqonda.net"
                 ## HTTP REDIRECT
                 #- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
                 #- "traefik.http.routers.redirect-https.rule=hostregexp({host:.+})"
                 #- "traefik.http.routers.redirect-https.entrypoints=web"
                 #- "traefik.http.routers.redirect-https.middlewares=redirect-to-https"
              ports:
                - "80:80"
                - "8080:8080" #Web UI
                - "443:443"
              volumes:
                - "/var/run/docker.sock:/var/run/docker.sock:ro"
                - "./traefik.yml:/traefik.yml:ro"
                - "./acme.json:/acme.json"
              networks:
                - external_network

            whoami:
              image: "containous/whoami"
              container_name: "whoami"
              restart: always
              labels:
                - "traefik.enable=true"
                - "traefik.http.routers.whoami.entrypoints=web"
                - "traefik.http.routers.whoami.rule=Host(whoami.iqonda.net)"
                #- "traefik.http.routers.whoami.tls.certresolver=lets-encr"
                #- "traefik.http.routers.whoami.tls=true"
              networks:
                - external_network

            db:
              image: mariadb
              container_name: "db"
              volumes:
                - db_data:/var/lib/mysql
              restart: always
              environment:
                MYSQL_ROOT_PASSWORD: somewordpress
                MYSQL_DATABASE: wordpress
                MYSQL_USER: wordpress
                MYSQL_PASSWORD: wordpress
              networks:
                - internal_network

            wpsites:
              depends_on:
                - db
              ports:
                - 8002:80
              image: wordpress:latest
              container_name: "wpsites"
              volumes:
                - /d01/html/wpsites.my.domain:/var/www/html
              restart: always
              environment:
                WORDPRESS_DB_HOST: db:3306
                WORDPRESS_DB_USER: wpsites
                WORDPRESS_DB_NAME: wpsites
              labels:
                 - "traefik.enable=true"
                 - "traefik.http.routers.wpsites.rule=Host(wpsites.my.domain)"
                 - "traefik.http.routers.wpsites.entrypoints=websecure"
                 - "traefik.http.routers.wpsites.tls.certresolver=lets-encr"
                 - "traefik.http.routers.wpsites.service=wpsites-svc"
                 - "traefik.http.services.wpsites-svc.loadbalancer.server.port=80"
              networks:
                - external_network
                - internal_network

        volumes:
              db_data: {}

        networks:
          external_network:
          internal_network:
            internal: true

WARNING: If you are not using the staging endpoint for LetsEncrypt strongly reconside doing that while working on this. You can get blocked for a week.

Start Containers

$ docker-compose up -d --build
whoami is up-to-date
Recreating traefik ... 
db is up-to-date
...
Recreating traefik ... done

Showing some log issues you may see

$ docker logs traefik -f
    ...
    time="2020-05-17T21:17:40Z" level=info msg="Testing certificate renew..." providerName=lets-encr.acme
    ...
    time="2020-05-17T21:17:51Z" level=error msg="Unable to obtain ACME certificate for domains
    ..."AADSTS7000215: Invalid client secret is provided.

$ docker logs traefik -f
    ...
    \"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"azure\"},\"ResolverName\":\"lets-encr\",\"store\":{},\"ChallengeStore\":{}}"
     acme: error presenting token: azure: dns.ZonesClient#Get: Invalid input:     autorest/validation: validation failed: parameter=resourceGroupName constraint=Pattern value=\"\\\"sites\\\"\" details: value 

$ docker logs traefik -f
    ...
    time="2020-05-17T22:23:38Z" level=info msg="Starting provider *acme.Provider {\"email\":\"admin@iqonda.com\",\"caServer\":\"https://acme-staging-v02.api.letsencrypt.org/   directory\",\"storage\":\"acme.json\",\"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"azure\"},\"ResolverName\":\"lets-encr\",\"store\":{},\"ChallengeStore\":{}}"
    time="2020-05-17T22:23:38Z" level=info msg="Testing certificate renew..." providerName=lets-encr.acme
    time="2020-05-17T22:23:38Z" level=info msg="Starting provider *traefik.Provider {}"
    time="2020-05-17T22:23:38Z" level=info msg="Starting provider *docker.Provider {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host({{  normalize .Name }})\",\"swarmModeRefreshSeconds\":15000000000}"
    time="2020-05-17T22:23:48Z" level=info msg=Register... providerName=lets-encr.acme

In a browser looking at cert this means working but still stage url: CN=Fake LE Intermediate X1

NOTE: In Azure DNS activity log i can see TXT record was created and deleted. Record will be something like this: _acme-challenge.my.domain

Browser still not showing lock. Test with https://www.whynopadlock.com and in my case was just a hardcoded image on the page making it insecure.

Comments Off on Traefik Wildcard Certificate using Azure DNS
comments

Sep 15

Terraform with Azure

Azure provides a cloud shell with Terraform already installed and even an editor aware of Terraform source. I tested creating a network and VM using the cloud shell in the browser.

REF: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/terraform-install-configure

Note: I am not showing dry run (terraform plan) but you should always be in the habit of plan before apply.

###################################################################
Using cloud shell prompts for a storage account tied to your shell.
###################################################################

Your cloud drive has been created in:

Subscription Id: b[..]b
Resource group:  cloud-shell-storage-southcentralus
Storage account: c[..]4
File share:      cs-[..]2

Initializing your account for Cloud Shell...\
Requesting a Cloud Shell.Succeeded.
Connecting terminal...

Welcome to Azure Cloud Shell

Type "az" to use Azure CLI 2.0
Type "help" to learn about Cloud Shell

#######
Test az
#######

riaan@Azure:~$ az vm list
[
  {
    "availabilitySet": null,
    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": true,
        "storageUri": "https://sitesdiag.blob.core.windows.net/"
      }
    },
    "hardwareProfile": {
      "vmSize": "Standard_B1s"
    },
 [..]
  }
]

###################################################################################################################
Check folder and space available
###################################################################################################################

riaan@Azure:~$ ls
clouddrive
riaan@Azure:~$ df -h .
Filesystem      Size  Used Avail Use% Mounted on
/dev/loop0      5.0G   11M  4.7G   1% /home/riaan

riaan@Azure:~$ az account show --query "{subscriptionId:id, tenantId:tenantId}"
{
  "subscriptionId": "b[..]",
  "tenantId": "f[..]"
}

###################################################################################################################
Simple terraform test add a resource group
###################################################################################################################

riaan@Azure:~$ mkdir sites
riaan@Azure:~$ cd sites
riaan@Azure:~/sites$ vi test.tf
riaan@Azure:~/sites$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "azurerm" (1.15.0)...
[..]
* provider.azurerm: version = "~> 1.15"
Terraform has been successfully initialized!

riaan@Azure:~/sites$ terraform apply
[..]
  + create

Terraform will perform the following actions:

  + azurerm_resource_group.rg
      id:       <computed>
      location: "centralus"
      name:     "testResourceGroup"
      tags.%:   <computed>

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.rg: Creating...
  location: "" => "centralus"
  name:     "" => "testResourceGroup"
  tags.%:   "" => "<computed>"
azurerm_resource_group.rg: Creation complete after 0s (ID: /subscriptions/b[..]/resourceGroups/testResourceGroup)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

#######################################################################
Simple terraform test. Destroy a resource group. I just comment it out.
#######################################################################

riaan@Azure:~/sites$ vi test.tf
riaan@Azure:~/sites$ terraform apply
azurerm_resource_group.rg: Refreshing state... (ID: /subscriptions/b[..]/resourceGroups/testResourceGroup)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - azurerm_resource_group.rg

Plan: 0 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.rg: Destroying... (ID: /subscriptions/b[..]/resourceGroups/testResourceGroup)
azurerm_resource_group.rg: Still destroying... (ID: /subscriptions/b[..]/resourceGroups/testResourceGroup, 10s elapsed)
[..]
azurerm_resource_group.rg: Destruction complete after 45s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

###################################################################################################################
Create VM plus network
https://docs.microsoft.com/en-us/azure/virtual-machines/linux/terraform-create-complete-vm
###################################################################################################################

riaan@Azure:~/sites$ rm test.tf
riaan@Azure:~/sites$ vi main.tf
riaan@Azure:~/sites$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + azurerm_network_interface.myterraformnic
      id:                                                                    <computed>
      applied_dns_servers.#:                                                 <computed>
      dns_servers.#:                                                         <computed>
      enable_accelerated_networking:                                         "false"
      enable_ip_forwarding:                                                  "false"
      internal_dns_name_label:                                               <computed>
      internal_fqdn:                                                         <computed>
      ip_configuration.#:                                                    "1"
      ip_configuration.0.application_gateway_backend_address_pools_ids.#:    <computed>
      ip_configuration.0.application_security_group_ids.#:                   <computed>
      ip_configuration.0.load_balancer_backend_address_pools_ids.#:          <computed>
      ip_configuration.0.load_balancer_inbound_nat_rules_ids.#:              <computed>
      ip_configuration.0.name:                                               "myNicConfiguration"
      ip_configuration.0.primary:                                            <computed>
      ip_configuration.0.private_ip_address_allocation:                      "dynamic"
      ip_configuration.0.public_ip_address_id:                               "${azurerm_public_ip.myterraformpublicip.id}"
      ip_configuration.0.subnet_id:                                          "${azurerm_subnet.myterraformsubnet.id}"
      location:                                                              "eastus"
      mac_address:                                                           <computed>
      name:                                                                  "myNIC"
      network_security_group_id:                                             "${azurerm_network_security_group.myterraformnsg.id}"
      private_ip_address:                                                    <computed>
      private_ip_addresses.#:                                                <computed>
      resource_group_name:                                                   "myResourceGroup"
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"
      virtual_machine_id:                                                    <computed>

  + azurerm_network_security_group.myterraformnsg
      id:                                                                    <computed>
      location:                                                              "eastus"
      name:                                                                  "myNetworkSecurityGroup"
      resource_group_name:                                                   "myResourceGroup"
      security_rule.#:                                                       "1"
      security_rule.2090309246.access:                                       "Allow"
      security_rule.2090309246.description:                                  ""
      security_rule.2090309246.destination_address_prefix:                   "*"
      security_rule.2090309246.destination_address_prefixes.#:               "0"
      security_rule.2090309246.destination_application_security_group_ids.#: "0"
      security_rule.2090309246.destination_port_range:                       "22"
      security_rule.2090309246.destination_port_ranges.#:                    "0"
      security_rule.2090309246.direction:                                    "Inbound"
      security_rule.2090309246.name:                                         "SSH"
      security_rule.2090309246.priority:                                     "1001"
      security_rule.2090309246.protocol:                                     "Tcp"
      security_rule.2090309246.source_address_prefix:                        "*"
      security_rule.2090309246.source_address_prefixes.#:                    "0"
      security_rule.2090309246.source_application_security_group_ids.#:      "0"
      security_rule.2090309246.source_port_range:                            "*"
      security_rule.2090309246.source_port_ranges.#:                         "0"
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"

  + azurerm_public_ip.myterraformpublicip
      id:                                                                    <computed>
      fqdn:                                                                  <computed>
      ip_address:                                                            <computed>
      location:                                                              "eastus"
      name:                                                                  "myPublicIP"
      public_ip_address_allocation:                                          "dynamic"
      resource_group_name:                                                   "myResourceGroup"
      sku:                                                                   "Basic"
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"

  + azurerm_resource_group.myterraformgroup
      id:                                                                    <computed>
      location:                                                              "eastus"
      name:                                                                  "myResourceGroup"
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"

  + azurerm_storage_account.mystorageaccount
      id:                                                                    <computed>
      access_tier:                                                           <computed>
      account_encryption_source:                                             "Microsoft.Storage"
      account_kind:                                                          "Storage"
      account_replication_type:                                              "LRS"
      account_tier:                                                          "Standard"
      enable_blob_encryption:                                                "true"
      enable_file_encryption:                                                "true"
      identity.#:                                                            <computed>
      location:                                                              "eastus"
      name:                                                                  "diag${random_id.randomId.hex}"
      primary_access_key:                                                    <computed>
      primary_blob_connection_string:                                        <computed>
      primary_blob_endpoint:                                                 <computed>
      primary_connection_string:                                             <computed>
      primary_file_endpoint:                                                 <computed>
      primary_location:                                                      <computed>
      primary_queue_endpoint:                                                <computed>
      primary_table_endpoint:                                                <computed>
      resource_group_name:                                                   "myResourceGroup"
      secondary_access_key:                                                  <computed>
      secondary_blob_connection_string:                                      <computed>
      secondary_blob_endpoint:                                               <computed>
      secondary_connection_string:                                           <computed>
      secondary_location:                                                    <computed>
      secondary_queue_endpoint:                                              <computed>
      secondary_table_endpoint:                                              <computed>
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"

  + azurerm_subnet.myterraformsubnet
      id:                                                                    <computed>
      address_prefix:                                                        "10.0.1.0/24"
      ip_configurations.#:                                                   <computed>
      name:                                                                  "mySubnet"
      resource_group_name:                                                   "myResourceGroup"
      virtual_network_name:                                                  "myVnet"

  + azurerm_virtual_machine.myterraformvm
      id:                                                                    <computed>
      availability_set_id:                                                   <computed>
      boot_diagnostics.#:                                                    "1"
      boot_diagnostics.0.enabled:                                            "true"
      boot_diagnostics.0.storage_uri:                                        "${azurerm_storage_account.mystorageaccount.primary_blob_endpoint}"
      delete_data_disks_on_termination:                                      "false"
      delete_os_disk_on_termination:                                         "false"
      identity.#:                                                            <computed>
      location:                                                              "eastus"
      name:                                                                  "myVM"
      network_interface_ids.#:                                               <computed>
      os_profile.#:                                                          "1"
      os_profile.1770182618.admin_password:                                  <sensitive>
      os_profile.1770182618.admin_username:                                  "azureuser"
      os_profile.1770182618.computer_name:                                   "myvm"
      os_profile.1770182618.custom_data:                                     <computed>
      os_profile_linux_config.#:                                             "1"
      os_profile_linux_config.69840937.disable_password_authentication:      "true"
      os_profile_linux_config.69840937.ssh_keys.#:                           "1"
      os_profile_linux_config.69840937.ssh_keys.0.key_data:                  "ssh-rsa AAAAB3Nz{snip}hwhqT9h"
      os_profile_linux_config.69840937.ssh_keys.0.path:                      "/home/azureuser/.ssh/authorized_keys"
      resource_group_name:                                                   "myResourceGroup"
      storage_data_disk.#:                                                   <computed>
      storage_image_reference.#:                                             "1"
      storage_image_reference.363552096.id:                                  ""
      storage_image_reference.363552096.offer:                               "UbuntuServer"
      storage_image_reference.363552096.publisher:                           "Canonical"
      storage_image_reference.363552096.sku:                                 "16.04.0-LTS"
      storage_image_reference.363552096.version:                             "latest"
      storage_os_disk.#:                                                     "1"
      storage_os_disk.0.caching:                                             "ReadWrite"
      storage_os_disk.0.create_option:                                       "FromImage"
      storage_os_disk.0.disk_size_gb:                                        <computed>
      storage_os_disk.0.managed_disk_id:                                     <computed>
      storage_os_disk.0.managed_disk_type:                                   "Premium_LRS"
      storage_os_disk.0.name:                                                "myOsDisk"
      storage_os_disk.0.write_accelerator_enabled:                           "false"
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"
      vm_size:                                                               "Standard_DS1_v2"

  + azurerm_virtual_network.myterraformnetwork
      id:                                                                    <computed>
      address_space.#:                                                       "1"
      address_space.0:                                                       "10.0.0.0/16"
      location:                                                              "eastus"
      name:                                                                  "myVnet"
      resource_group_name:                                                   "myResourceGroup"
      subnet.#:                                                              <computed>
      tags.%:                                                                "1"
      tags.environment:                                                      "Terraform Demo"

  + random_id.randomId
      id:                                                                    <computed>
      b64:                                                                   <computed>
      b64_std:                                                               <computed>
      b64_url:                                                               <computed>
      byte_length:                                                           "8"
      dec:                                                                   <computed>
      hex:                                                                   <computed>
      keepers.%:                                                             "1"
      keepers.resource_group:                                                "myResourceGroup"


Plan: 9 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.myterraformgroup: Creating...
  location:         "" => "eastus"
  name:             "" => "myResourceGroup"
  tags.%:           "" => "1"
  tags.environment: "" => "Terraform Demo"
azurerm_resource_group.myterraformgroup: Creation complete after 0s (ID: /subscriptions/b[..]/resourceGroups/myResourceGroup)
azurerm_virtual_network.myterraformnetwork: Creating...
  address_space.#:     "" => "1"
  address_space.0:     "" => "10.0.0.0/16"
  location:            "" => "eastus"
  name:                "" => "myVnet"
  resource_group_name: "" => "myResourceGroup"
  subnet.#:            "" => "<computed>"
  tags.%:              "" => "1"
  tags.environment:    "" => "Terraform Demo"
azurerm_public_ip.myterraformpublicip: Creating...
  fqdn:                         "" => "<computed>"
  ip_address:                   "" => "<computed>"
  location:                     "" => "eastus"
  name:                         "" => "myPublicIP"
  public_ip_address_allocation: "" => "dynamic"
  resource_group_name:          "" => "myResourceGroup"
  sku:                          "" => "Basic"
  tags.%:                       "" => "1"
  tags.environment:             "" => "Terraform Demo"
random_id.randomId: Creating...
  b64:                    "" => "<computed>"
  b64_std:                "" => "<computed>"
  b64_url:                "" => "<computed>"
  byte_length:            "" => "8"
  dec:                    "" => "<computed>"
  hex:                    "" => "<computed>"
  keepers.%:              "" => "1"
  keepers.resource_group: "" => "myResourceGroup"
random_id.randomId: Creation complete after 0s (ID: ZZic4bhOapM)
azurerm_network_security_group.myterraformnsg: Creating...
  location:                                                              "" => "eastus"
  name:                                                                  "" => "myNetworkSecurityGroup"
  resource_group_name:                                                   "" => "myResourceGroup"
  security_rule.#:                                                       "" => "1"
  security_rule.2090309246.access:                                       "" => "Allow"
  security_rule.2090309246.description:                                  "" => ""
  security_rule.2090309246.destination_address_prefix:                   "" => "*"
  security_rule.2090309246.destination_address_prefixes.#:               "" => "0"
  security_rule.2090309246.destination_application_security_group_ids.#: "" => "0"
  security_rule.2090309246.destination_port_range:                       "" => "22"
  security_rule.2090309246.destination_port_ranges.#:                    "" => "0"
  security_rule.2090309246.direction:                                    "" => "Inbound"
  security_rule.2090309246.name:                                         "" => "SSH"
  security_rule.2090309246.priority:                                     "" => "1001"
  security_rule.2090309246.protocol:                                     "" => "Tcp"
  security_rule.2090309246.source_address_prefix:                        "" => "*"
  security_rule.2090309246.source_address_prefixes.#:                    "" => "0"
  security_rule.2090309246.source_application_security_group_ids.#:      "" => "0"
  security_rule.2090309246.source_port_range:                            "" => "*"
  security_rule.2090309246.source_port_ranges.#:                         "" => "0"
  tags.%:                                                                "" => "1"
  tags.environment:                                                      "" => "Terraform Demo"
azurerm_storage_account.mystorageaccount: Creating...
  access_tier:                      "" => "<computed>"
  account_encryption_source:        "" => "Microsoft.Storage"
  account_kind:                     "" => "Storage"
  account_replication_type:         "" => "LRS"
  account_tier:                     "" => "Standard"
  enable_blob_encryption:           "" => "true"
  enable_file_encryption:           "" => "true"
  identity.#:                       "" => "<computed>"
  location:                         "" => "eastus"
  name:                             "" => "diag6[..]"
  primary_access_key:               "<sensitive>" => "<sensitive>"
  primary_blob_connection_string:   "<sensitive>" => "<sensitive>"
  primary_blob_endpoint:            "" => "<computed>"
  primary_connection_string:        "<sensitive>" => "<sensitive>"
  primary_file_endpoint:            "" => "<computed>"
  primary_location:                 "" => "<computed>"
  primary_queue_endpoint:           "" => "<computed>"
  primary_table_endpoint:           "" => "<computed>"
  resource_group_name:              "" => "myResourceGroup"
  secondary_access_key:             "<sensitive>" => "<sensitive>"
  secondary_blob_connection_string: "<sensitive>" => "<sensitive>"
  secondary_blob_endpoint:          "" => "<computed>"
  secondary_connection_string:      "<sensitive>" => "<sensitive>"
  secondary_location:               "" => "<computed>"
  secondary_queue_endpoint:         "" => "<computed>"
  secondary_table_endpoint:         "" => "<computed>"
  tags.%:                           "" => "1"
  tags.environment:                 "" => "Terraform Demo"
azurerm_public_ip.myterraformpublicip: Creation complete after 2s (ID: /subscriptions/b[..]-...t.Network/publicIPAddresses/myPublicIP)
azurerm_network_security_group.myterraformnsg: Creation complete after 2s (ID: /subscriptions/b[..]-...kSecurityGroups/myNetworkSecurityGroup)
azurerm_virtual_network.myterraformnetwork: Still creating... (10s elapsed)
azurerm_storage_account.mystorageaccount: Still creating... (10s elapsed)
azurerm_storage_account.mystorageaccount: Creation complete after 19s (ID: /subscriptions/b[..]-...e/storageAccounts/diag6[..])
azurerm_virtual_network.myterraformnetwork: Still creating... (20s elapsed)
azurerm_virtual_network.myterraformnetwork: Creation complete after 22s (ID: /subscriptions/b[..]-...crosoft.Network/virtualNetworks/myVnet)
azurerm_subnet.myterraformsubnet: Creating...
  address_prefix:       "" => "10.0.1.0/24"
  ip_configurations.#:  "" => "<computed>"
  name:                 "" => "mySubnet"
  resource_group_name:  "" => "myResourceGroup"
  virtual_network_name: "" => "myVnet"
azurerm_subnet.myterraformsubnet: Still creating... (10s elapsed)
azurerm_subnet.myterraformsubnet: Creation complete after 11s (ID: /subscriptions/b[..]-...irtualNetworks/myVnet/subnets/mySubnet)
azurerm_network_interface.myterraformnic: Creating...
  applied_dns_servers.#:                                              "" => "<computed>"
  dns_servers.#:                                                      "" => "<computed>"
  enable_accelerated_networking:                                      "" => "false"
  enable_ip_forwarding:                                               "" => "false"
  internal_dns_name_label:                                            "" => "<computed>"
  internal_fqdn:                                                      "" => "<computed>"
  ip_configuration.#:                                                 "" => "1"
  ip_configuration.0.application_gateway_backend_address_pools_ids.#: "" => "<computed>"
  ip_configuration.0.application_security_group_ids.#:                "" => "<computed>"
  ip_configuration.0.load_balancer_backend_address_pools_ids.#:       "" => "<computed>"
  ip_configuration.0.load_balancer_inbound_nat_rules_ids.#:           "" => "<computed>"
  ip_configuration.0.name:                                            "" => "myNicConfiguration"
  ip_configuration.0.primary:                                         "" => "<computed>"
  ip_configuration.0.private_ip_address_allocation:                   "" => "dynamic"
  ip_configuration.0.public_ip_address_id:                            "" => "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/publicIPAddresses/myPublicIP"
  ip_configuration.0.subnet_id:                                       "" => "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVnet/subnets/mySubnet"
  location:                                                           "" => "eastus"
  mac_address:                                                        "" => "<computed>"
  name:                                                               "" => "myNIC"
  network_security_group_id:                                          "" => "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/myNetworkSecurityGroup"
  private_ip_address:                                                 "" => "<computed>"
  private_ip_addresses.#:                                             "" => "<computed>"
  resource_group_name:                                                "" => "myResourceGroup"
  tags.%:                                                             "" => "1"
  tags.environment:                                                   "" => "Terraform Demo"
  virtual_machine_id:                                                 "" => "<computed>"
azurerm_network_interface.myterraformnic: Creation complete after 1s (ID: /subscriptions/b[..]-...rosoft.Network/networkInterfaces/myNIC)
azurerm_virtual_machine.myterraformvm: Creating...
  availability_set_id:                                              "" => "<computed>"
  boot_diagnostics.#:                                               "" => "1"
  boot_diagnostics.0.enabled:                                       "" => "true"
  boot_diagnostics.0.storage_uri:                                   "" => "https://diag[..].blob.core.windows.net/"
  delete_data_disks_on_termination:                                 "" => "false"
  delete_os_disk_on_termination:                                    "" => "false"
  identity.#:                                                       "" => "<computed>"
  location:                                                         "" => "eastus"
  name:                                                             "" => "myVM"
  network_interface_ids.#:                                          "" => "1"
  network_interface_ids.0:                                          "" => "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC"
  os_profile.#:                                                     "" => "1"
  os_profile.1770182618.admin_password:                             "<sensitive>" => "<sensitive>"
  os_profile.1770182618.admin_username:                             "" => "azureuser"
  os_profile.1770182618.computer_name:                              "" => "myvm"
  os_profile.1770182618.custom_data:                                "" => "<computed>"
  os_profile_linux_config.#:                                        "" => "1"
  os_profile_linux_config.69840937.disable_password_authentication: "" => "true"
  os_profile_linux_config.69840937.ssh_keys.#:                      "" => "1"
  os_profile_linux_config.69840937.ssh_keys.0.key_data:             "" => "ssh-rsa AAAAB3Nz{snip}hwhqT9h"
  os_profile_linux_config.69840937.ssh_keys.0.path:                 "" => "/home/azureuser/.ssh/authorized_keys"
  resource_group_name:                                              "" => "myResourceGroup"
  storage_data_disk.#:                                              "" => "<computed>"
  storage_image_reference.#:                                        "" => "1"
  storage_image_reference.363552096.id:                             "" => ""
  storage_image_reference.363552096.offer:                          "" => "UbuntuServer"
  storage_image_reference.363552096.publisher:                      "" => "Canonical"
  storage_image_reference.363552096.sku:                            "" => "16.04.0-LTS"
  storage_image_reference.363552096.version:                        "" => "latest"
  storage_os_disk.#:                                                "" => "1"
  storage_os_disk.0.caching:                                        "" => "ReadWrite"
  storage_os_disk.0.create_option:                                  "" => "FromImage"
  storage_os_disk.0.disk_size_gb:                                   "" => "<computed>"
  storage_os_disk.0.managed_disk_id:                                "" => "<computed>"
  storage_os_disk.0.managed_disk_type:                              "" => "Premium_LRS"
  storage_os_disk.0.name:                                           "" => "myOsDisk"
  storage_os_disk.0.write_accelerator_enabled:                      "" => "false"
  tags.%:                                                           "" => "1"
  tags.environment:                                                 "" => "Terraform Demo"
  vm_size:                                                          "" => "Standard_DS1_v2"

Error: Error applying plan:

1 error(s) occurred:

* azurerm_virtual_machine.myterraformvm: 1 error(s) occurred:

* azurerm_virtual_machine.myterraformvm: compute.VirtualMachinesClient#CreateOrUpdate: Failure sending request: StatusCode=0 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidParameter" Message="The value of parameter linuxConfiguration.ssh.publicKeys.keyData is invalid." Target="linuxConfiguration.ssh.publicKeys.keyData"

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

######################################################
Add a valid ssh public key to continue creating the VM
######################################################

riaan@Azure:~/sites$ vi main.tf
riaan@Azure:~/sites$ terraform apply
azurerm_resource_group.myterraformgroup: Refreshing state... (ID: /subscriptions/b[..]/resourceGroups/myResourceGroup)
azurerm_network_security_group.myterraformnsg: Refreshing state... (ID: /subscriptions/b[..]-...kSecurityGroups/myNetworkSecurityGroup)
random_id.randomId: Refreshing state... (ID: ZZic4bhOapM)
azurerm_virtual_network.myterraformnetwork: Refreshing state... (ID: /subscriptions/b[..]-...crosoft.Network/virtualNetworks/myVnet)
azurerm_public_ip.myterraformpublicip: Refreshing state... (ID: /subscriptions/b[..]-...t.Network/publicIPAddresses/myPublicIP)
azurerm_storage_account.mystorageaccount: Refreshing state... (ID: /subscriptions/b[..]-...e/storageAccounts/diag[..])
azurerm_subnet.myterraformsubnet: Refreshing state... (ID: /subscriptions/b[..]-...irtualNetworks/myVnet/subnets/mySubnet)
azurerm_network_interface.myterraformnic: Refreshing state... (ID: /subscriptions/b[..]-...rosoft.Network/networkInterfaces/myNIC)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + azurerm_virtual_machine.myterraformvm
      id:                                                               <computed>
      availability_set_id:                                              <computed>
      boot_diagnostics.#:                                               "1"
      boot_diagnostics.0.enabled:                                       "true"
      boot_diagnostics.0.storage_uri:                                   "https://diag[..].blob.core.windows.net/"
      delete_data_disks_on_termination:                                 "false"
      delete_os_disk_on_termination:                                    "false"
      identity.#:                                                       <computed>
      location:                                                         "eastus"
      name:                                                             "myVM"
      network_interface_ids.#:                                          "1"
      network_interface_ids.0:                                          "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC"
      os_profile.#:                                                     "1"
      os_profile.1770182618.admin_password:                             <sensitive>
      os_profile.1770182618.admin_username:                             "azureuser"
      os_profile.1770182618.computer_name:                              "myvm"
      os_profile.1770182618.custom_data:                                <computed>
      os_profile_linux_config.#:                                        "1"
      os_profile_linux_config.69840937.disable_password_authentication: "true"
      os_profile_linux_config.69840937.ssh_keys.#:                      "1"
      os_profile_linux_config.69840937.ssh_keys.0.key_data:             "ssh-rsa [..]"
      os_profile_linux_config.69840937.ssh_keys.0.path:                 "/home/azureuser/.ssh/authorized_keys"
      resource_group_name:                                              "myResourceGroup"
      storage_data_disk.#:                                              <computed>
      storage_image_reference.#:                                        "1"
      storage_image_reference.363552096.id:                             ""
      storage_image_reference.363552096.offer:                          "UbuntuServer"
      storage_image_reference.363552096.publisher:                      "Canonical"
      storage_image_reference.363552096.sku:                            "16.04.0-LTS"
      storage_image_reference.363552096.version:                        "latest"
      storage_os_disk.#:                                                "1"
      storage_os_disk.0.caching:                                        "ReadWrite"
      storage_os_disk.0.create_option:                                  "FromImage"
      storage_os_disk.0.disk_size_gb:                                   <computed>
      storage_os_disk.0.managed_disk_id:                                <computed>
      storage_os_disk.0.managed_disk_type:                              "Premium_LRS"
      storage_os_disk.0.name:                                           "myOsDisk"
      storage_os_disk.0.write_accelerator_enabled:                      "false"
      tags.%:                                                           "1"
      tags.environment:                                                 "Terraform Demo"
      vm_size:                                                          "Standard_DS1_v2"


Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_virtual_machine.myterraformvm: Creating...
  availability_set_id:                                              "" => "<computed>"
  boot_diagnostics.#:                                               "" => "1"
  boot_diagnostics.0.enabled:                                       "" => "true"
  boot_diagnostics.0.storage_uri:                                   "" => "https://diag[..].blob.core.windows.net/"
  delete_data_disks_on_termination:                                 "" => "false"
  delete_os_disk_on_termination:                                    "" => "false"
  identity.#:                                                       "" => "<computed>"
  location:                                                         "" => "eastus"
  name:                                                             "" => "myVM"
  network_interface_ids.#:                                          "" => "1"
  network_interface_ids.0:                                          "" => "/subscriptions/b[..]/resourceGroups/myResourceGroup/providers/Microsoft.Network/networkInterfaces/myNIC"
  os_profile.#:                                                     "" => "1"
  os_profile.1770182618.admin_password:                             "<sensitive>" => "<sensitive>"
  os_profile.1770182618.admin_username:                             "" => "azureuser"
  os_profile.1770182618.computer_name:                              "" => "myvm"
  os_profile.1770182618.custom_data:                                "" => "<computed>"
  os_profile_linux_config.#:                                        "" => "1"
  os_profile_linux_config.69840937.disable_password_authentication: "" => "true"
  os_profile_linux_config.69840937.ssh_keys.#:                      "" => "1"
  os_profile_linux_config.69840937.ssh_keys.0.key_data:             "" => "ssh-rsa A[..]"
  os_profile_linux_config.69840937.ssh_keys.0.path:                 "" => "/home/azureuser/.ssh/authorized_keys"
  resource_group_name:                                              "" => "myResourceGroup"
  storage_data_disk.#:                                              "" => "<computed>"
  storage_image_reference.#:                                        "" => "1"
  storage_image_reference.363552096.id:                             "" => ""
  storage_image_reference.363552096.offer:                          "" => "UbuntuServer"
  storage_image_reference.363552096.publisher:                      "" => "Canonical"
  storage_image_reference.363552096.sku:                            "" => "16.04.0-LTS"
  storage_image_reference.363552096.version:                        "" => "latest"
  storage_os_disk.#:                                                "" => "1"
  storage_os_disk.0.caching:                                        "" => "ReadWrite"
  storage_os_disk.0.create_option:                                  "" => "FromImage"
  storage_os_disk.0.disk_size_gb:                                   "" => "<computed>"
  storage_os_disk.0.managed_disk_id:                                "" => "<computed>"
  storage_os_disk.0.managed_disk_type:                              "" => "Premium_LRS"
  storage_os_disk.0.name:                                           "" => "myOsDisk"
  storage_os_disk.0.write_accelerator_enabled:                      "" => "false"
  tags.%:                                                           "" => "1"
  tags.environment:                                                 "" => "Terraform Demo"
  vm_size:                                                          "" => "Standard_DS1_v2"
azurerm_virtual_machine.myterraformvm: Still creating... (10s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (20s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (30s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (40s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (50s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (1m0s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (1m10s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (1m20s elapsed)
azurerm_virtual_machine.myterraformvm: Still creating... (1m30s elapsed)
azurerm_virtual_machine.myterraformvm: Creation complete after 1m35s (ID: /subscriptions/b[..]-...Microsoft.Compute/virtualMachines/myVM)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

##################################################################
use built-in editor(vscode?) Comment out the VM so we can destroy
##################################################################

riaan@Azure:~/sites$ terraform apply
azurerm_resource_group.myterraformgroup: Refreshing state...
[..]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - azurerm_virtual_machine.myterraformvm


Plan: 0 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_virtual_machine.myterraformvm: Destroying... (ID: /subscriptions/[..]-...Microsoft.Compute/virtualMachines/myVM)
[..]
azurerm_virtual_machine.myterraformvm: Destruction complete after 34s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

Comments Off on Terraform with Azure
comments