Search code examples
azurevariablesterraform-provider-azure

How to pass Variables with Secrets (User, Password) in Terraform


Following the documentation I have created Main.tf, Terraform.tfvars, variables.tf,

###Terraform provider is Azure, what I’m intending to do? build a VM and passing the User/Password via variables to avoid expose the secrets, or write them into the Main.tf file (I have done this, and has worked for me fine, but is not a good security practice)

###main.tf, here is the relevant content that interacts with the User/Passwords I’m trying to pass to the VM to allow me to administer it:

resource "azurerm_network_interface" "nic_poc" {
  count               = 1
  name                = "nic_test_persistent${count.index}"
  location            = "North Europe"
  resource_group_name = local.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = data.terraform_remote_state.my_azure_dev.outputs.org_dev.subnet.northeurope.main.subnets["dev1-XX.XXX.XXX.X_XX"].id
    private_ip_address_allocation = "Dynamic"
  }
}
resource "azurerm_windows_virtual_machine" "vm_persistent" {
  count               = 1
  name                = "vm-persistent${count.index}"
  resource_group_name = local.rg.name
  location            = "North Europe"
  size                = "Standard_D4_v3"

# Here my variables for User/Password
  admin_username      = "var.admin_username"
  admin_password      = "var.admin_password"
  network_interface_ids = [
    element(azurerm_network_interface.nic_poc.*.id, count.index)
  ]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2019-Datacenter"
    version   = "latest"
  }
 
}

###terraform.tfvars, here declaring the value of the variable because it what I have understood from several examples (maybe misunderstood them)

###terrafrom.tfvars, here declaring the value for these variables:
TF_VAR_admin_username = "adminuser"
TF_VAR_admin_password = "OurP@**w0rd1998#"

###variables.tf, here declaring the variables without value because don’t know if I can declare it here and how

variable "admin_username" {
    type = string
}

variable "admin_password" {
    type = string
}

###Error

Error: creating Windows Virtual Machine "vm-persistent0" (Resource Group "nXXX-XXX-dev1-org-dev-XX"): compute.VirtualMachinesClient#CreateOrUpdate: Failure sending request: StatusCode=0 -- Original Error: Code="InvalidParameter" Message="The supplied password must be between 8-123 characters long and must satisfy at least 3 of password complexity requirements from the following:\r\n1) Contains an uppercase character\r\n2) Contains a lowercase character\r\n3) Contains a numeric digit\r\n4) Contains a special character\r\n5) Control characters are not allowed" Target="adminPassword"

When I run my terraform code it complains that: Password is not compliant with the requirements of, lowercase, uppercase, number, symbol

That’s not true, why? well, the same password worked perfectly when declared directly into my Main.tf file, but that is not a good practice because is fully visible and that´s why I want to pass it via a variable to keep it away to be sniff

What am i missing?


Solution

  • You are using :

    admin_username      = "var.admin_username"
      admin_password      = "var.admin_password"
    

    Instead you should use

    admin_username      = var.admin_username
      admin_password      = var.admin_password
    

    As if you are giving the value in double quotes it will take the value present inside it as shown below:

    enter image description here


    If you are using .tfvars file to keep the values then you should declare the variables with that name only as shown below:

    variable "TF_VAR_admin_username" {
        type = string
    }
    
    variable "TF_VAR_admin_password" {
        type = string
    }
    

    and then use this variable in virtual machine block like:

      admin_username      = var.TF_VAR_admin_username
      admin_password      = var.TF_VAR_admin_password
    

    enter image description here

    Or You can directly call them in variables so that you don't have to mention in .tfvars file

    Var.tf file:

    variable "admin_username" {
        type = string
        default = "adminuser"
    }
    
    variable "admin_password" {
        type = string
        default = "OurP@**w0rd1998#"
    }
    

    ** my main.tf file:**

    data "azurerm_resource_group" "example" {
      name     = "ansumantest"
    }
    
    resource "azurerm_virtual_network" "example" {
      name                = "example-network"
      address_space       = ["10.0.0.0/16"]
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
    }
    
    resource "azurerm_subnet" "example" {
      name                 = "internal"
      resource_group_name  = data.azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.2.0/24"]
    }
    
    resource "azurerm_network_interface" "example" {
      name                = "example-nic"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
    
      ip_configuration {
        name                          = "internal"
        subnet_id                     = azurerm_subnet.example.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_windows_virtual_machine" "vm_persistent" {
      name                = "vm-persistent"
      resource_group_name = data.azurerm_resource_group.example.name
      location            = data.azurerm_resource_group.example.location
      size                = "Standard_D4_v3"
    
    # Here my variables for User/Password
      admin_username      = var.admin_username
      admin_password      = var.admin_password
      network_interface_ids = [azurerm_network_interface.example.id]
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
      source_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    }
    

    Output:

    enter image description here