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!
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!
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