EC2 Windows Server: can't make winrm remote-exec provisioner to work with the auto-generated Administrator password

I’m trying to set up a Windows Server on EC2 using Packer to create the AMI and Terraform to deploy it, but I can’t make the Terraform remote-exec provisioner to work with the auto-generated Administrator password, while it works with a fixed passord.

Packer file

packer {
  required_plugins {
    amazon = {
      version = ">= 0.0.1"
      source  = "github.com/hashicorp/amazon"
    }
  }
}

variable "image_name" {
  type = string
}

variable "password" {
  type = string
}

source "amazon-ebs" "windows" {
  ami_name       = var.image_name
  communicator   = "winrm"
  instance_type  = "t2.micro"
  winrm_insecure = true
  #winrm_password = var.password
  winrm_port     = 5986
  winrm_use_ssl  = true
  winrm_username = "Administrator"

  source_ami_filter {
    filters = {
      #name                = "Windows_Server-2019*English-Full-Base*"
      name                = "Windows_Server-2016-English-Full-Base-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = ["amazon"]
  }

  user_data = <<EOUD
<powershell>
# Set administrator password
#net user Administrator ${var.password}
#wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE

Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore

# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"

# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse

# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force

# WinRM
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}'
cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}'
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm
</powershell>
EOUD
}

build {
  name    = "build-win"
  sources = ["source.amazon-ebs.windows"]

  provisioner "file" {
    destination = "C:\\"
    source      = "./data"
  }

  provisioner "powershell" {
    script  = "./setup.ps1"
    timeout = "10m"
  }

  provisioner "powershell" {
    inline = [
      "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
      "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\SysprepInstance.ps1 -NoShutdown"
    ]
  }

  post-processor "manifest" {
    output     = "manifest.json"
    strip_path = true
  }
}

Setup.ps1

try {
    # Set display file extension
    reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /v HideFileExt /t REG_DWORD /d 0 /f

    # Enable multiple Remote Desktop connections
    Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fdenyTSConnections" -Value 0
    Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fSingleSessionPerUser" -Value 0

    # Install chocolatey
    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

    # Set non interactive chocolatey
    choco feature enable -n allowGlobalConfirmation
}
catch {
    Exit 1
}

Packer works fine: winrm connects using the generated password.

Terraform file

resource "aws_instance" "it" {
  ami                    = var.ami
  get_password_data      = true
  instance_type          = "t3.micro"
  key_name               = "my_key"
  subnet_id              = var.subnet_id
  vpc_security_group_ids = var.security_groups

  connection {
    agent    = false
    insecure = true
    host     = self.public_ip
    https    = true
    #password = var.password
    password = rsadecrypt(self.password_data, file("my_key/id_rsa"))
    port     = 5986
    type     = "winrm"
    user     = "Administrator"
  }

  provisioner "remote-exec" {
    inline     = var.inline
    on_failure = continue
  }
}

resource "local_file" "foo" {
  content  = rsadecrypt(aws_instance.it.password_data, file("my_key/id_rsa"))
  filename = "${path.module}/foo.bar"
}

… but the remote-exec does not connect! :frowning:

Please note that I had to add the on_failure = continue to create the instance regardless from the remote-exec error, and through the resource "local_file" "foo" I verify that the Administrator passowrd I get is the correct one! (I can connect to the instance through Remote Desktop using it).

If I uncomment the lines to use a fixed password… everything works perfectly! :frowning:

To be more specific, these are the lines I uncomment to use a fixed passwoprd.

Packer file

...

source "amazon-ebs" "windows" {
  ...
  #winrm_password = var.password
  ...

  user_data = <<EOUD
<powershell>
...
#net user Administrator ${var.password}
#wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE

...
</powershell>
EOUD
}

...

Terraform file

resource "aws_instance" "it" {
  ...

  connection {
    ...
    #password = var.password
    ...
  }

  ...
}

Can you see something wrong in my code to use the auto-generated Administrator password?

Thank you

Please confirm your winrm is listning

To check if winrm is listening:
curl --header "Content-Type: application/soap+xml;charset=UTF-8" --header "WSMANIDENTIFY: unauthenticated" --insecure https://<ip-address>:5986/wsman --data '&lt;s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"&gt;&lt;s:Header/&gt;&lt;s:Body&gt;&lt;wsmid:Identify/&gt;&lt;/s:Body&gt;&lt;/s:Envelope&gt;'

Auto-generated password can be long to retrive several mn.
if you output password … Is it correct ? or empty ?
Do you try to use null_ressource for remote-exec ?
like this sample
https://stackoverflow.com/questions/62403030/terraform-wait-till-the-instance-is-reachable