Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save petemounce/11099158 to your computer and use it in GitHub Desktop.

Select an option

Save petemounce/11099158 to your computer and use it in GitHub Desktop.
# install 7-zip, curl and vim
# (Windows 2012 comes with .NET 4.5 out-of-the-box)
# Then use the EC2 tools to create a new AMI from the result, and you have a system
# that will execute user-data as a PowerShell script after the instance fires up!
# This has been tested on Windows 2012 64bits AMIs provided by Amazon (eu-west-1 ami-a1867dd6)
#
# Inject this as user-data of a Windows 2012 AMI, like this (edit the adminPassword to your needs):
#
# <powershell>
# Set-ExecutionPolicy Unrestricted
# icm $executioncontext.InvokeCommand.NewScriptBlock((New-Object Net.WebClient).DownloadString('https://gist.githubusercontent.com/petemounce/11099158/raw/Bootstrap-EC2-Windows-CloudInit.ps1')) -ArgumentList "adminPassword"
# </powershell>
#
param(
[Parameter(Mandatory=$true)]
[string]
$AdminPassword
)
Start-Transcript -Path 'c:\bootstrap-transcript.log' -Force
Set-StrictMode -Version Latest
Set-ExecutionPolicy Unrestricted
$log = 'c:\Bootstrap.log'
while (($AdminPassword -eq $null) -or ($AdminPassword -eq ''))
{
$AdminPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((Read-Host "Enter a non-null / non-empty Administrator password" -AsSecureString)))
}
$systemPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::System)
$sysNative = [IO.Path]::Combine($env:windir, "sysnative")
#http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx
$Is32Bit = (($Env:PROCESSOR_ARCHITECTURE -eq 'x86') -and ($Env:PROCESSOR_ARCHITEW6432 -eq $null))
Add-Content $log -value "Is 32-bit [$Is32Bit]"
#http://msdn.microsoft.com/en-us/library/ms724358.aspx
$coreEditions = @(0x0c,0x27,0x0e,0x29,0x2a,0x0d,0x28,0x1d)
$IsCore = $coreEditions -contains (Get-WmiObject -Query "Select OperatingSystemSKU from Win32_OperatingSystem" | Select -ExpandProperty OperatingSystemSKU)
Add-Content $log -value "Is Core [$IsCore]"
# move to home, PS is incredibly complex :)
cd $Env:USERPROFILE
Set-Location -Path $Env:USERPROFILE
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
#change admin password
net user Administrator $AdminPassword
Add-Content $log -value "Changed Administrator password"
$client = new-object System.Net.WebClient
#check winrm id, if it's not valid and LocalAccountTokenFilterPolicy isn't established, do it
$id = &winrm id
if (($id -eq $null) -and (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue) -eq $null)
{
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name LocalAccountTokenFilterPolicy -value 1 -propertyType dword
Add-Content $log -value "Added LocalAccountTokenFilterPolicy since winrm id could not be executed"
}
#enable powershell servermanager cmdlets (only for 2008 r2 + above)
if ($IsCore)
{
DISM /Online /Enable-Feature /FeatureName:MicrosoftWindowsPowerShell /FeatureName:ServerManager-PSH-Cmdlets /FeatureName:BestPractices-PSH-Cmdlets
Add-Content $log -value "Enabled ServerManager and BestPractices Cmdlets"
#enable .NET flavors - on server core only -- errors on regular 2008
DISM /Online /Enable-Feature /FeatureName:NetFx2-ServerCore /FeatureName:NetFx2-ServerCore-WOW64 /FeatureName:NetFx3-ServerCore /FeatureName:NetFx3-ServerCore-WOW64
Add-Content $log -value "Enabled .NET frameworks 2 and 3 for x86 and x64"
}
#7zip
$7zUri = if ($Is32Bit) { 'http://sourceforge.net/projects/sevenzip/files/7-Zip/9.22/7z922.msi/download' } `
else { 'http://sourceforge.net/projects/sevenzip/files/7-Zip/9.22/7z922-x64.msi/download' }
$client.DownloadFile( $7zUri, '7z922.msi')
Start-Process -FilePath "msiexec.exe" -ArgumentList '/i 7z922.msi /norestart /q INSTALLDIR="c:\program files\7-zip"' -Wait
SetX Path "${Env:Path};C:\Program Files\7-zip" /m
$Env:Path += ';C:\Program Files\7-Zip'
del 7z922.msi
Add-Content $log -value "Installed 7-zip from $7zUri and updated path"
#curl
$curlUri = if ($Is32Bit) { 'http://www.paehl.com/open_source/?download=curl_724_0_ssl.zip' } `
else { 'http://curl.haxx.se/download/curl-7.23.1-win64-ssl-sspi.zip' }
$client.DownloadFile( $curlUri, 'curl.zip')
&7z e curl.zip `-o`"c:\program files\curl`"
if ($Is32Bit)
{
$client.DownloadFile( 'http://www.paehl.com/open_source/?download=libssl.zip', 'libssl.zip')
&7z e libssl.zip `-o`"c:\program files\curl`"
del libssl.zip
}
SetX Path "${Env:Path};C:\Program Files\Curl" /m
$Env:Path += ';C:\Program Files\Curl'
del curl.zip
Add-Content $log -value "Installed Curl from $curlUri and updated path"
#vim
curl -# -G -k -L ftp://ftp.vim.org/pub/vim/pc/vim73_46rt.zip -o vim73_46rt.zip 2>&1 > "$log"
curl -# -G -k -L ftp://ftp.vim.org/pub/vim/pc/vim73_46w32.zip -o vim73_46w32.zip 2>&1 > "$log"
Get-ChildItem -Filter vim73*.zip |
% { &7z x `"$($_.FullName)`"; del $_.FullName; }
SetX Path "${Env:Path};C:\Program Files\Vim" /m
$Env:Path += ';C:\Program Files\Vim'
Move-Item .\vim\vim73 -Destination "${Env:ProgramFiles}\Vim"
Add-Content $log -value "Installed Vim text editor and updated path"
#chocolatey - standard one line installer doesn't work on Core b/c Shell.Application can't unzip
if (-not $IsCore)
{
Invoke-Expression ((new-object net.webclient).DownloadString('http://bit.ly/psChocInstall'))
}
else
{
#[Environment]::SetEnvironmentVariable('ChocolateyInstall', 'c:\nuget', [System.EnvironmentVariableTarget]::User)
#if (![System.IO.Directory]::Exists('c:\nuget')) {[System.IO.Directory]::CreateDirectory('c:\nuget')}
$tempDir = Join-Path $env:TEMP "chocInstall"
if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)}
$file = Join-Path $tempDir "chocolatey.zip"
$client.DownloadFile("http://chocolatey.org/api/v1/package/chocolatey", $file)
&7z x $file `-o`"$tempDir`"
Add-Content $log -value 'Extracted Chocolatey'
$chocInstallPS1 = Join-Path (Join-Path $tempDir 'tools') 'chocolateyInstall.ps1'
& $chocInstallPS1
Add-Content $log -value 'Installed Chocolatey / Verifying Paths'
}
Add-Content $log -value "Installed Chocolatey"
# install puppet
#https://downloads.puppetlabs.com/windows/puppet-3.5.1.msi
curl -# -G -k -L https://downloads.puppetlabs.com/windows/puppet-3.5.1.msi -o puppet-3.5.1.msi 2>&1 > "$log"
Start-Process -FilePath "msiexec.exe" -ArgumentList '/qn /passive /i puppet-3.5.1.msi /norestart' -Wait
SetX Path "${Env:Path};C:\Program Files\Puppet Labs\Puppet\bin" /m
&sc.exe config puppet start= demand
Add-Content $log -value "Installed Puppet"
&netsh firewall set portopening tcp 445 smb enable
Add-Content $log -value "Ran firewall config to allow incoming smb/tcp"
#run SMRemoting script to enable event log management, etc - available only on R2
$remotingScript = [IO.Path]::Combine($systemPath, 'Configure-SMRemoting.ps1')
if (-not (Test-Path $remotingScript)) { $remotingScript = [IO.Path]::Combine($sysNative, 'Configure-SMRemoting.ps1') }
Add-Content $log -value "Found Remoting Script: [$(Test-Path $remotingScript)] at $remotingScript"
if (Test-Path $remotingScript)
{
. $remotingScript -force -enable
Add-Content $log -value 'Ran Configure-SMRemoting.ps1'
}
#wait a bit, it's windows after all
Start-Sleep -m 10000
#Write-Host "Press any key to reboot and finish image configuration"
#[void]$host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
Restart-Computer
# As much of https://github.com/WinRb/vagrant-windows#creating-a-base-box as possible
# * Windows AMIs don't have WinRM enabled by default -- this script will enable WinRM
# * vagrant user
# * disable UAC
#
# <powershell>
# set-executionpolicy unrestricted
# icm $executioncontext.InvokeCommand.NewScriptBlock((New-Object Net.WebClient).DownloadString('https://gist.githubusercontent.com/petemounce/11099158/raw/Enable-Vagrant.ps1')) -ArgumentList "Abcd1234$"
# </powershell>
param(
[Parameter(Mandatory=$true)]
[string]
$AdminPassword
)
Start-Transcript -Path 'c:\vagrant-transcript.log' -Force
Set-StrictMode -Version Latest
Set-ExecutionPolicy Unrestricted
$log = 'c:\vagrant.log'
$systemPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::System)
$sysNative = [IO.Path]::Combine($env:windir, "sysnative")
#http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx
$Is32Bit = (($Env:PROCESSOR_ARCHITECTURE -eq 'x86') -and ($Env:PROCESSOR_ARCHITEW6432 -eq $null))
Add-Content $log -value "Is 32-bit [$Is32Bit]"
#http://msdn.microsoft.com/en-us/library/ms724358.aspx
$coreEditions = @(0x0c,0x27,0x0e,0x29,0x2a,0x0d,0x28,0x1d)
$IsCore = $coreEditions -contains (Get-WmiObject -Query "Select OperatingSystemSKU from Win32_OperatingSystem" | Select -ExpandProperty OperatingSystemSKU)
Add-Content $log -value "Is Core [$IsCore]"
# move to home, PS is incredibly complex :)
cd $Env:USERPROFILE
Set-Location -Path $Env:USERPROFILE
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
#check winrm id, if it's not valid and LocalAccountTokenFilterPolicy isn't established, do it
$id = &winrm id
if (($id -eq $null) -and (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue) -eq $null)
{
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name LocalAccountTokenFilterPolicy -value 1 -propertyType dword
Add-Content $log -value "Added LocalAccountTokenFilterPolicy since winrm id could not be executed"
}
#enable powershell servermanager cmdlets (only for 2008 r2 + above)
if ($IsCore)
{
DISM /Online /Enable-Feature /FeatureName:MicrosoftWindowsPowerShell /FeatureName:ServerManager-PSH-Cmdlets /FeatureName:BestPractices-PSH-Cmdlets
Add-Content $log -value "Enabled ServerManager and BestPractices Cmdlets"
#enable .NET flavors - on server core only -- errors on regular 2008
DISM /Online /Enable-Feature /FeatureName:NetFx2-ServerCore /FeatureName:NetFx2-ServerCore-WOW64 /FeatureName:NetFx3-ServerCore /FeatureName:NetFx3-ServerCore-WOW64
Add-Content $log -value "Enabled .NET frameworks 2 and 3 for x86 and x64"
}
# Disable Complex Passwords
# Reference: http://vlasenko.org/2011/04/27/removing-password-complexity-requirements-from-windows-server-2008-core/
$seccfg = [IO.Path]::GetTempFileName()
secedit /export /cfg $seccfg
(Get-Content $seccfg) | Foreach-Object {$_ -replace "PasswordComplexity\s*=\s*1", "PasswordComplexity=0"} | Set-Content $seccfg
secedit /configure /db $env:windir\security\new.sdb /cfg $seccfg /areas SECURITYPOLICY
del $seccfg
Add-Content $log -value "Complex Passwords have been disabled."
#change admin password
net user Administrator $AdminPassword
Add-Content $log -value "Changed Administrator password"
#create vagrant user
net user vagrant vagrant /add
Add-Content $log -value "Created vagrant user"
net localgroup administrators vagrant /add
Add-Content $log -value "Added vagrant user to local administrators"
# http://www.howtogeek.com/howto/windows-vista/enable-or-disable-uac-from-the-windows-vista-command-line/
# $env:windir\System32\reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
# http://stackoverflow.com/a/9573204/20971
New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -PropertyType DWord -Value 0 -Force
Add-Content $log -value "Turned off UAC"
# Disable Shutdown Tracker on Windows 2008/2012 Servers (except Core).
# Step 3: Disable the shutdown tracker
# Reference: http://www.askvg.com/how-to-disable-remove-annoying-shutdown-event-tracker-in-windows-server-2003-2008/
If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability")) {
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability"
}
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name "ShutdownReasonOn" -PropertyType DWord -Value 0 -Force -ErrorAction continue
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name "ShutdownReasonUI" -PropertyType DWord -Value 0 -Force -ErrorAction continue
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name "ShutdownReasonOn" -Value 0
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name "ShutdownReasonUI" -Value 0
Add-Content $log -value "Shutdown Tracker has been disabled."
# Disable "Server Manager" Starting at login on Windows 2008/2012 Servers (except Core).
# TODO.
# Disable Automatic Updates
# Reference: http://www.benmorris.me/2012/05/1st-test-blog-post.html
$AutoUpdate = (New-Object -com "Microsoft.Update.AutoUpdate").Settings
$AutoUpdate.NotificationLevel = 1
$AutoUpdate.Save()
Add-Content $log -value "Windows Update has been disabled."
# Enable and configure WinRM (see below)
&winrm quickconfig `-q
&winrm set winrm/config/client/auth '@{Basic="true"}'
&winrm set winrm/config/service/auth '@{Basic="true"}'
&winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="512"}'
&winrm set winrm/config '@{MaxTimeoutms="1800000"}'
&winrm set winrm/config/service '@{AllowUnencrypted="true"}'
Add-Content $log -value "Ran quickconfig for winrm"
Set-Service winrm -startuptype "auto"
Add-Content $log -value "Started winrm"
&netsh firewall set portopening TCP 5985 "Port 5985: winrm"
Add-Content $log -value "Ran firewall config to allow incoming winrm/tcp:5985"
&netsh firewall set portopening tcp 445 smb enable
Add-Content $log -value "Ran firewall config to allow incoming smb/tcp:445"
#chocolatey - standard one line installer doesn't work on Core b/c Shell.Application can't unzip
iex $client.DownloadString('https://chocolatey.org/install.ps1')
#SetX Path "${Env:Path};%systemdrive%\chocolatey\bin" /m
#$env:Path += ';%systemdrive%\chocolatey\bin'
Add-Content $log -value "Installed Chocolatey"
Add-Content $log -value "Upgrading to windows core..."
# http://www.danielclasson.com/how-to-change-between-a-full-installation-gui-and-server-core-in-windows-server-2012/
Uninstall-WindowsFeature Server-Gui-Shell,Server-Gui-Mgmt-Infra
Add-Content $log -value "Upgraded to Windows Core from GUI"
Add-Content $log -value "Restarting"
Restart-Computer
@colegatron
Copy link
Copy Markdown

Brilliant! Fantástico! Chapeau! Fantastisch!

All in one gist:
Vagrant file for Windows EC2 AMI, userdata to call the gist, changes the password to avoid issues with the credentials and autogenerated one, sets up winrm, provisions standard software and provisions puppet itself.

Congratulations

@stevekodra
Copy link
Copy Markdown

How does this script makes a call from userdata cloudformations ? can any one please give some tips how to bootstrap this script on userdata cloudfromations - as you know json does not like few characters so i can to put on json WINRM?

Thank you guys

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment