Create a Windows AMI with packer and ansible on AWS
ansible, packer, windows, winrm
Solution
You need follow the instructions in the documentation for using the ansible provisioner with WinRM.
This is a working example running Windows 2016 Server Base:
{
"builders": [
{
"type": "amazon-ebs",
"region": "eu-west-1",
"instance_type": "m3.medium",
"source_ami": "ami-0983b56f",
"ami_name": "packer-demo-{{timestamp}}",
"user_data_file": "windows-userdata.txt",
"communicator": "winrm",
"winrm_username": "Administrator"
}],
"provisioners": [
{
"type": "ansible",
"playbook_file": "./win-playbook.yml",
"extra_arguments": [
"--connection", "packer", "-vvv",
"--extra-vars", "ansible_shell_type=powershell ansible_shell_executable=None"
]
}]
}
windows-userdata.txt
<powershell>
winrm quickconfig -q
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow
netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow
net stop winrm
sc config winrm start=auto
net start winrm
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine
</powershell>
win-playbook.yml
---
- hosts: all
tasks:
- win_ping:
#- ping:
connection_plugins/packer.py
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.plugins.connection.ssh import Connection as SSHConnection
class Connection(SSHConnection):
''' ssh based connections for powershell via packer'''
transport = 'packer'
has_pipelining = True
become_methods = []
allow_executable = False
module_implementation_preferences = ('.ps1', '')
def __init__(self, *args, **kwargs):
super(Connection, self).__init__(*args, **kwargs)
Unfortunatley there seems to be a problem with the latest (2.3.0) version Ansible and Packer, see #4904
Problem
I want to create an aws windows AMI with packer and ansible. I have tried many configuration, but I have still a problem of connection to the instance. Here is my packer conf : ``` { "builders": [{ "type": "amazon-ebs", "access_key": "{{user `aws_access_key`}}", "secret_key": "{{user `aws_secret_key`}}", "region": "eu-west-1", "source_ami": "ami-58a1a73e", "instance_type": "m3.medium", "ami_name": "aaa-windows-ami {{timestamp}}", "user_data_file":"./test.ps", "communicator": "winrm", "winrm_username": "Administrator", "winrm_use_ssl": true, "winrm_insecure": true }], "provisioners": [ { "type": "ansible", "playbook_file": "./playbook.yml", "extra_arguments": [ "--extra-vars", "ansible_user=Administrator ansible_connection=winrm ansible_ssh_port=5986 ansible_winrm_server_cert_validation=ignore ansible_shell_type=powershell ansible_shell_executable=None" ] }, { "type": "powershell", "script": "./init.ps1" } ] } ``` The User data script is activating winrm on the AWS instance. ``` <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 Set-Item WSMan:\localhost\MaxTimeoutms 1800000 Set-Item WSMan:\localhost\Service\Auth\Basic $true $Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer" New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -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" cmd.exe /c net stop winrm cmd.exe /c sc config winrm start= auto cmd.exe /c net start winrm </powershell> ``` The error is. ``` ==> amazon-ebs: Provisioning with Ansible... amazon-ebs: amazon-ebs: PLAY [all] ********************************************************************* amazon-ebs: amazon-ebs: TASK [setup] ******************************************************************* amazon-ebs: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ssl: auth method ssl requires a password", "unreachable": true} amazon-ebs: to retry, use: --limit @/home/elhostis/repo/vagrant/playbook.retry amazon-ebs: amazon-ebs: PLAY RECAP ********************************************************************* amazon-ebs: default : ok=0 changed=0 unreachable=1 failed=0 amazon-ebs: ==> amazon-ebs: Terminating the source AWS instance... ==> amazon-ebs: Cleaning up any extra volumes... ==> amazon-ebs: No volumes to clean up, skipping ==> amazon-ebs: Deleting temporary security group... ==> amazon-ebs: Deleting temporary keypair... ``` I have also tried to create manually an AMI with a known username/password. Then, I have configured ansible with theses credentials, but I have this error. ``` ==> amazon-ebs: Timeout waiting for password. ==> amazon-ebs: Terminating the source AWS instance... ==> amazon-ebs: Cleaning up any extra volumes... ==> amazon-ebs: No volumes to clean up, skipping ==> amazon-ebs: Deleting temporary security group... ==> amazon-ebs: Deleting temporary keypair... Build 'amazon-ebs' errored: Timeout waiting for password. ``` Someone have an example to do that ? Thanks a lot. Eric