skip to Main Content

I need to deploy azure custom script extension.My script is powershell i want to use terraform variable in powershell script. my script works perfectly when i use null resource but i can sent value in azure custom script extension.

my terraform script is below

resource "azurerm_virtual_machine_extension" "example_extension" {
  name                 = "exampleExtension"
  virtual_machine_id   = azurerm_virtual_machine.example_vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.10"

  settings = <<SETTINGS
    {
      "commandToExecute": "powershell -command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(file("testing.ps1"))}')) | Out-File -filepath testing.ps1" && powershell -ExecutionPolicy Unrestricted -File testing.ps1 -example_variable '${var.example_variable}'"
     
    }
SETTINGS
}

Powershell script

Param(
    [Parameter(Mandatory=$true)]
    [string]$example_variable
)

Write-Host "The value of example_variable is: $example_variable"

Getting error on extension

[
    {
        "code": "ComponentStatus/StdOut/succeeded",
        "level": "Info",
        "displayStatus": "Provisioning succeeded",
        "message": "The value of example_variable is: rnrnrn    Directory: C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.15\Downloads\0rnrnrnMode                LastWriteTime         Length Name                                                                  rn----                -------------         ------ ----                                                                  rn-a----         5/8/2023   1:10 AM              0 .txt                                                                  rnrnrn"
    },
    {
        "code": "ComponentStatus/StdErr/succeeded",
        "level": "Info",
        "displayStatus": "Provisioning succeeded",
        "message": "?Param : The term '?Param' is not recognized as the name of a cmdlet, function, script file, or operable program. rnCheck the spelling of the name, or if a path was included, verify that the path is correct and try again.rnAt C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\1.10.15\Downloads\0\testing.ps1:1 char:1rn+ ?Param(rn+ ~~~~~~rn    + CategoryInfo          : ObjectNotFound: (?Param:String) [], CommandNotFoundExceptionrn    + FullyQualifiedErrorId : CommandNotFoundExceptionrn rn"
    }
]

i am not using ?param as it is showing me.
Is there any solution to deploy terraform variable in powershell script using microsoft extension.

2

Answers


  1. Check if the file content after powershell execution is fetched properly .

    Use

     data "template_file" "tf" {
        template = "${file("mypscript.ps1")}"
    }
    

    to fetch the powershell file.

    Code:

    resource "azurerm_virtual_machine" "example" {
      name                  = "kaaaacctvm"
      location              = data.azurerm_resource_group.example.location
      resource_group_name   = data.azurerm_resource_group.example.name
     ....
    
      storage_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "16.04-LTS"
        version   = "latest"
      }
    
      ...
      os_profile {
        computer_name  = "hostname"
        admin_username = "testadmin"
        admin_password = "Password1234!"
      }
    
      ...
    
    }
    
    resource "azurerm_virtual_machine_extension" "example" {
      name                 = "vmextnname"
      virtual_machine_id   = azurerm_virtual_machine.example.id
      publisher            = "Microsoft.Azure.Extensions"
      type                 = "CustomScript"
      type_handler_version = "2.0"
    settings = <<SETTINGS
        {
          "commandToExecute": "powershell -command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.tf.rendered)}'))  | Out-File -filepath mypscript.ps1" && powershell -ExecutionPolicy Unrestricted -File mypscript.ps1 -example_variable '${var.example_variable}'"
         
        }
    SETTINGS
    
     
    }
    
    data "template_file" "tempfile" {
        template = "${file("mypscript.ps1")}"
    }
    

    enter image description here

    Reference: Terraform azurerm_virtual_machine_extension, run local PowerShell Script using CustomScriptExtension – Stack Overflow

    Login or Signup to reply.
  2. Here, I am storing the required files in storage account and getting the required secrets from keyvault(in my case).

    # In my data.tf file
    data "azurerm_key_vault" "commonkv" {
      name                = var.common_kv_name
      resource_group_name = var.common_rg_name
    }
    
    # Non-Domain admin user name
    data "azurerm_key_vault_secret" "vmusername" {
      name         = "vm-admin-user-name"
      key_vault_id = data.azurerm_key_vault.commonkv.id
    }
    
    # Non-Domain admin user Password
    data "azurerm_key_vault_secret" "vmuserpwd" {
      name         = "vm-admin-user-pwd"
      key_vault_id = data.azurerm_key_vault.commonkv.id
    }
    
    # In my main.tf file
    resource "azurerm_virtual_machine_extension" "winvmcse" {
      name                       = "wincse"
      virtual_machine_id         = azurerm_windows_virtual_machine.winvm.id
      publisher                  = "Microsoft.Compute"
      type                       = "CustomScriptExtension"
      type_handler_version       = "1.9"
      auto_upgrade_minor_version = true
      automatic_upgrade_enabled  = false
      settings                   = <<SETTINGS
      {
      "fileUris": ["https://mystorageaccount.blob.core.windows.net/packages/file1.zip","https://mystorageaccount.blob.core.windows.net/packages/file2.ps1"],
      "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File ./file2.ps1 ${data.azurerm_key_vault_secret.vmusername.value} ${data.azurerm_key_vault_secret.vmuserpwd.value}",
      "timestamp" : "2"
      }
    SETTINGS
      timeouts {
        create = "1h30m"
        delete = "1h15m"
      }
      tags = var.tags
    }
    

    in my file2.ps1, I get those values by

    $username = $args[0]
    $password = $args[1]
    

    This method works for both linux and windows, and the only change is you have to modify your execution script, according to the os. Hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search