How to create a Packer Windows image with winrm enabled ? (azure)

1,171 views
Skip to first unread message

Sim

unread,
Aug 28, 2019, 2:41:40 AM8/28/19
to Packer
Hi, 

I am currently running into an issue that my Terraform could not connect back to the VM it provisioned in order to connect to Chef server (via chef provisioner) because it could not establish a connection to the VM. I think it might be because the Packer image that I used in Terraform has not been enabled for the winrm. I have looked around on the internet, but still could not find out a good way to enable winrm in the packer. 
I have tried to call a powershell file in the Packer template. The PS script has a bunch of PS commands that enable winrm. But it didnt work when I ran Packer build. 

What I have tried:
#bootstrap-winrm.ps1
# Set administrator password
net user admin admin12
wmic useraccount where "name='admin'" set PasswordExpires=FALSE

# First, make sure WinRM can't be connected to
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block

# Delete any existing WinRM listeners
winrm delete winrm/config/listener?Address=*+Transport=HTTP  2>$Null
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null

# Create a new WinRM listener and configure
winrm create winrm/config/listener?Address=*+Transport=HTTP
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
winrm set winrm/config '@{MaxTimeoutms="7200000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/client/auth '@{Basic="true"}'

# Configure UAC to allow privilege elevation in remote shells
$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
$Setting = 'LocalAccountTokenFilterPolicy'
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force

# Configure and restart the WinRM Service; Enable the required firewall exception
Stop-Service -Name WinRM
Set-Service -Name WinRM -StartupType Automatic
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
Start-Service -Name WinRM



Packer template
{
   "variables": {
     "client_id": "",
     "client_secret": "",
     "tenant_id": "",
     "subscription_id": "",
     "object_id": "",
     "managed_image_resource_group_name": "",
     "managed_image_name": "",
     "virtual_network_name": "",
     "virtual_network_subnet_name": "",
     "virtual_network_resource_group_name": "",
     "file_source": "",
     "packer_ado_pat": ""
     },
   "builders": [{
     "type": "azure-arm",
 
     "client_id": "{{user `client_id`}}",
     "client_secret": "{{user `client_secret`}}",
     "tenant_id": "{{user `tenant_id`}}",
     "subscription_id": "{{user `subscription_id`}}",
     "object_id": "{{user `object_id`}}",
 
     "managed_image_resource_group_name": "{{user `managed_image_resource_group_name`}}",
     "managed_image_name": "{{user `managed_image_name`}}",
 
     "virtual_network_name": "{{user `virtual_network_name`}}",              
      "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}",      
      "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}",
 
     "os_type": "Windows",
     "image_publisher": "MicrosoftWindowsServer",
     "image_offer": "WindowsServer",
     "image_sku": "2016-Datacenter",
 
     "user_data_file": "{{user `file_source`}}/Bootstrap-Winrm.ps1",

      "communicator": "winrm",
     "winrm_use_ssl": "true",
     "winrm_insecure": "true",
     "winrm_timeout": "5m",
     "winrm_username": "admin",
     "winrm_password": "admin12",

     
     "location": "australiasoutheast",
     "vm_size": "Standard_A4m_v2"
   }],
   "provisioners": [
     {
       "type": "powershell",
       "inline": ["mkdir c:\\Packer"]
     },{
       "type": "file",
       "source": "{{user `file_source`}}",
       "destination": "c:\\Packer"
     },{
       "type": "powershell",
       "scripts": "{{user `file_source`}}/Bootstrap-winrm.ps1"
     },{
     "type": "powershell",
     "inline": [
       "Add-WindowsFeature Web-Server",
       "if( Test-Path $Env:SystemRoot\\windows\\system32\\Sysprep\\unattend.xml ){ rm $Env:SystemRoot\\windows\\system32\\Sysprep\\unattend.xml -Force}",
       "& $Env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit"
     ]
   }]
 }


Could anyone please link me or give me any better suggestions of what should I do to achieve this? if winrm seems to be so difficult, would ssh another better approach (but again I am not sure how could packer set up ssh and generate the key here in the image again, that can be used later in the Terraform template). 

Thanks. 

Sébastien Barthélémy

unread,
Oct 16, 2019, 4:27:14 AM10/16/19
to Packer
Hello,

I've been running successfully packer and terraform with WinRM on AWS with this script

An important part was to undo the setup at the end in a tear-down step. (I'm not sure it applies to you, maybe it matters when certificates are used).
You can see the template here

This other script was also useful when debugging:

Hope it helps!

Jimster

unread,
Oct 16, 2019, 4:40:01 AM10/16/19
to Packer
Have you also checked your firewalls are open for the relevant winRM ports being used?  Both on the server being provisioned (Windows Firewall) and in your corp infrastructure and security group?  (I am AWS but the therory is the same)

I am using the following userdata file for WinRM and this is working well:
<powershell>

write-output "Running User Data Script"
write-host "(host) Running User Data Script"

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

$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force

#Create Folder for Package Source Files (AMI Install Version)
Write-Host "Doing Temp File Folder Creation"
New-Item -Path "c:\" -name "temp" -itemType "directory" -force

# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up 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"
Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 2048
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm

</powershell>

This is called from my builder .json files as so:
    "builders": [{
        "type":             "amazon-ebs",
        "vpc_id":           "vpc-xxx",
        "subnet_id":        "subnet-xxx",
        "region":           "xxx",
        "source_ami":       "xxx",
        "ami_name":         "my-ami-name-{{timestamp}}",
        "user_data_file":   "./USERDATA2.0.txt",  <=== CALL IT HERE
        "communicator":     "winrm",
        "winrm_username":   "Administrator",
        "instance_type":    "t2.large",
        "winrm_use_ssl":    true,
        "winrm_insecure":   true
    }],


See how you go.

Jimster

unread,
Oct 16, 2019, 5:04:25 AM10/16/19
to Packer
Also - you are calling your Bootstrap twice.

Once in the Builders section (because you have user_data_file set) and then again in the Provisioners section:
{
        "type": "powershell",
        "scripts": "{{user `file_source`}}/Bootstrap-winrm.ps1"
},{...

You don't need to do it twice, it will probably interrupt any WinRM chat you were doing in the user_data_file connection.

On Wednesday, 28 August 2019 07:41:40 UTC+1, Sim wrote:
Reply all
Reply to author
Forward
0 new messages