1
votes

I followed the following guide to set up a Linux Virtual Machine using Terraform:

https://docs.microsoft.com/en-us/azure/developer/terraform/create-linux-virtual-machine-with-infrastructure

Everything was sucessfully created in Azure. I am having trouble with the last step of being able to ssh into the virtual machine. I use the following command in Windows powershell:

ssh azureuser@public_ip_here

It gives me the following error:

azureuser@52.186.144.190: Permission denied (publickey).

I've tried using the RDP file from the Azure portal by downloading the RDP file and importing it in RDP but I get the following error:

Doesn't work with RDP either

Things I've tried:

  1. Using the normal ssh command as above
  2. Trying to put the private key in a .pem file and assigning it restricted permissions. Then passing this key in using the ssh -i command. This doesn't work either
  3. Using RDP file downloaded from Azure portal (error shown below)
  4. Ran the test connection feature for the Virtual Machine in the Azure portal and that shows connection successful but I'm still not able to access the VM.

I'm wondering if I have to somehow configure the Azure portal to allow myself to be able to ssh in the VM.

My main.tf code is:

provider "azurerm" {
    # The "feature" block is required for AzureRM provider 2.x. 
    # If you're using version 1.x, the "features" block is not allowed.
    version = "~>2.0"
    features {}
}

resource "azurerm_resource_group" "myterraformgroup" {
    name     = "myResourceGroup"
    location = "eastus"

    tags = {
        environment = "Terraform Demo"
    }
}

resource "azurerm_virtual_network" "myterraformnetwork" {
    name                = "myVnet"
    address_space       = ["10.0.0.0/16"]
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    tags = {
        environment = "Terraform Demo"
    }
}

resource "azurerm_subnet" "myterraformsubnet" {
    name                 = "mySubnet"
    resource_group_name  = azurerm_resource_group.myterraformgroup.name
    virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
    address_prefixes       = ["10.0.1.0/24"]
}

resource "azurerm_public_ip" "myterraformpublicip" {
    name                         = "myPublicIP"
    location                     = "eastus"
    resource_group_name          = azurerm_resource_group.myterraformgroup.name
    allocation_method            = "Dynamic"

    tags = {
        environment = "Terraform Demo"
    }
}

resource "azurerm_network_security_group" "myterraformnsg" {
    name                = "myNetworkSecurityGroup"
    location            = "eastus"
    resource_group_name = azurerm_resource_group.myterraformgroup.name

    security_rule {
        name                       = "SSH"
        priority                   = 1001
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "22"
        source_address_prefix      = "*"
        destination_address_prefix = "*"
    }

    tags = {
        environment = "Terraform Demo"
    }
}

resource "azurerm_network_interface" "myterraformnic" {
    name                      = "myNIC"
    location                  = "eastus"
    resource_group_name       = azurerm_resource_group.myterraformgroup.name

    ip_configuration {
        name                          = "myNicConfiguration"
        subnet_id                     = azurerm_subnet.myterraformsubnet.id
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.myterraformpublicip.id
    }

    tags = {
        environment = "Terraform Demo"
    }
}

resource "azurerm_network_interface_security_group_association" "example" {
    network_interface_id      = azurerm_network_interface.myterraformnic.id
    network_security_group_id = azurerm_network_security_group.myterraformnsg.id
}

resource "random_id" "randomId" {
    keepers = {
        # Generate a new ID only when a new resource group is defined
        resource_group = azurerm_resource_group.myterraformgroup.name
    }

    byte_length = 8
}

resource "azurerm_storage_account" "mystorageaccount" {
    name                        = "diag${random_id.randomId.hex}"
    resource_group_name         = azurerm_resource_group.myterraformgroup.name
    location                    = "eastus"
    account_tier                = "Standard"
    account_replication_type    = "LRS"

    tags = {
        environment = "Terraform Demo"
    }
}

resource "tls_private_key" "example_ssh" {
  algorithm = "RSA"
  rsa_bits = 4096
}
output "tls_private_key" { value = tls_private_key.example_ssh.private_key_pem }

resource "azurerm_linux_virtual_machine" "myterraformvm" {
    name                  = "myVM"
    location              = "eastus"
    resource_group_name   = azurerm_resource_group.myterraformgroup.name
    network_interface_ids = [azurerm_network_interface.myterraformnic.id]
    size                  = "Standard_DS1_v2"

    os_disk {
        name              = "myOsDisk"
        caching           = "ReadWrite"
        storage_account_type = "Premium_LRS"
    }

    source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }

    computer_name  = "myvm"
    admin_username = "azureuser"
    disable_password_authentication = true

    admin_ssh_key {
        username       = "azureuser"
        public_key     = tls_private_key.example_ssh.public_key_openssh
    }

    boot_diagnostics {
        storage_account_uri = azurerm_storage_account.mystorageaccount.primary_blob_endpoint
    }

    tags = {
        environment = "Terraform Demo"
    }
}

Any help/pointers would be greatly appreciated!

2
Curious, why are you using RDP to login to a linux VM? You should be using SSHRoadRunner
Could you run ssh azureuser@public_ip_here in a bash?Nancy Xiong
@RoadRunner I did that just as a test to see if it would work. As I mentioned earlier in my thread, I have been using ssh but it isn't working.tt1997
@NancyXiong it says Permission denied (publickey).tt1997
@NancyXiong Yes your suggestion helped! Thank you!tt1997

2 Answers

1
votes

After my validation, you could save the output private pem key to a file named key.pem in the home directory. for example, C:\Users\username\ in Windows 10 or /home/username/ in Linux.

enter image description here

Then you can access the Azure VM via the command in the shell.

ssh -i "C:\Users\username\key.pem"  azureuser@23.x.x.x

Result

enter image description here

In addition, the private key generated by tls_private_key will be stored unencrypted in your Terraform state file. It's recommended to generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run.

You can use ssh-keygen in PowerShell in Windows 10 to create the key pair on the client machine. The key pair is saved into the directory C:\Users\username\.ssh.

For example, then you can send the public key to the Azure VM with Terraform function file:

admin_ssh_key {
    username       = "azureuser"
    public_key     = file("C:\\Users\\someusername\\.ssh\\id_rsa.pub")     
    #tls_private_key.example_ssh.public_key_openssh
}
0
votes
  • First create the key.

    ssh-keygen -t rsa -b 2048 -C email@example.com

  • Second add the path of key.

    admin_ssh_key {

     username       = "azureuser"
     public_key     = file("C:\\Users\\someusername\\.ssh\\id_rsa.pub")
    

    }

  • Finally login.

    ssh -i "C:\Users\someusername.ssh\id_rsa" azureuser@20.x.x.x