Search code examples
terraformterraform-provider-azure

Use file() in remote-exec


I successfully created an Azure Ubuntu VM in Terraform that runs a remote-exec provisioner after the creation has been completed. Within this remote-exec block I create user accounts that can be accessed via SSH. Since I have the public keys, I also want to add each public key to their respective authorized_keys file. My approach is this:

"sudo adduser --quiet --disabled-password --shell /bin/bash --home /home/username--gecos \"Firstname Lastname\" username", 
"sudo mkdir ~/../username/.ssh",
"sudo chmod 700 ~/../username/.ssh/",
"sudo touch ~/../username/.ssh/authorized_keys",
"sudo echo ${file("userKeys/username.pub")} > ~/../username/.ssh/authorized_keys",
"sudo chmod 600 ~/../username/.ssh/authorized_keys",
"sudo chown -R username.username ~/../username/"

Unfortunately, this causes Terraform to crash after applying, probably due to the double quotes within file. So I also tried

"echo ${file("userKeys/username.pub")}"

which works perfectly fine.

At this point I don't really know how to solve this problem. Maybe using file() within remote-exec is the wrong approach anyway?


Solution

  • In this case, you can use the Provisioner Connection to create an SSH connection and use Provisioner File to copy the local file to the remote machine.

    Here is a working sample on my side with the following configuration environment.

    Terraform v0.15.0
    on windows_amd64
    + provider registry.terraform.io/hashicorp/azurerm v2.57.0
    + provider registry.terraform.io/hashicorp/null v3.1.0
    

    For example,

    resource "null_resource" "example_provisioner" {
    
      triggers = {
        public_ip = azurerm_public_ip.example.ip_address
      }
    
      connection {
        type  = "ssh"
        host  = azurerm_public_ip.example.ip_address
        user  = "testadmin"
        private_key = "${file("~/.ssh/id_rsa")}"
        # password = "${var.root_password}"
        }
    
      provisioner "file" {
        source  = "test.pub"  # local public key
        destination  = "/tmp/test.pub"  # will copy to remote VM as /tmp/test.pub
      }
    
      provisioner "remote-exec" {
        inline = [
    "sudo adduser --quiet --disabled-password --shell /bin/bash --home /home/username --gecos \"Firstname Lastname\" username", 
    "sudo mkdir ~/../username/.ssh",
    "sudo chmod 700 ~/../username/.ssh/",
    "sudo touch ~/../username/.ssh/authorized_keys",
    "sudo cp /tmp/test.pub ~/../username/.ssh/authorized_keys",
    "sudo chmod 600 ~/../username/.ssh/authorized_keys",
    "sudo chown -R username.username ~/../username/"
    
        ]
      }
    
    }
    

    enter image description here