Last active
January 28, 2016 02:56
-
-
Save alex-williams/dac25d83e24816194dcc to your computer and use it in GitHub Desktop.
Bootstrapping a Windows 2008 R2, 2012 or 2012 R2 Server in an EC2 VPC with Chef
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| This gist allows you to bootstrap a new Windows 2008 R2, 2012, or 2012 R2 Server in | |
| EC2, with Chef, dynamically, without the AMI knowing anything about Chef at all when launched. | |
| You will need to 'pre-bake' an AMI, as ideally, you'll want the Windows Management Framework 4 | |
| installed on it, to give you Powershell 4. This hasn't been tested using anything less than | |
| Powershell 4, so that's my 'minimum requirement recommendation'. I've also only done this with | |
| Chef 12, as it's been out a long time now and I see no reason to go backwards with it. The other | |
| reason you'll need to pre-bake the AMI, is that you'll need to configure EC2-Config on the machine | |
| to run user-data at the next boot (Be aware, setting this feature only persists one reboot, | |
| subsequent reboots will not run user-data code) and you'll need to open up the Powershell tools | |
| for AWS console, at least once and run through the setup, so that our S3 download works in the | |
| user-data and Bootstrap scripts. My personal recommendation, is to secure the S3 bucket with a | |
| policy and assign an IAM role to your server, however, provided you haven't stored anything in | |
| the bucket with passwords, or secret information stored within, you can also just make the bucket | |
| public if you're not interested in securing it. | |
| Combining this gist with the 'windows_ad' chef community cookbook, you can have a Windows server | |
| launched, bootstrapped and on the domain, within 12 minutes (If using an appropriate instance | |
| size and SSD drives). I've made a few edits to the windows_ad cookbook, to facilitate adding | |
| directly to an OU and changing the machine name in the command that joins the domain, requiring | |
| only a single reboot (It normally takes at least 2 to rename and add to the domain), on Windows | |
| Server 2008 R2, 2012 and 2012 R2. I'm just cleaning up the code, before doing a pull request to | |
| the maintainers. Hopefully they pull it in :) At present though, that cookbook will allow you to | |
| join the domain, rename the instance and add the machine to an ou, with separate actions. | |
| You'll need to go through the other files in this gist with find and replace, to change the following: | |
| 'your-company-name' to whatever your organisation name is in your Chef server | |
| 'yourdomain' to whatever your chef server domain name is | |
| 'sandbox' to whatever environment you intend to use on your chef server (Remove completely if none) | |
| 'windows-server' to an appropriate role name | |
| 'your-chef-bucket' to whatever your chef bucket name is. | |
| You may also need to change the version number of the chef-client, but at the time of writing, it | |
| was the latest stable release. I recommend putting the chef client msi in your chef bucket, so that | |
| you're reliant on your own stable msi, in your own S3 bucket :) I prefer the approach of using a | |
| stable version, than constantly grabbing latest and ending up with a mix-and-match situation on | |
| my servers and this also mitigates any errors with someone accidentally putting the wrong msi in | |
| an S3 bucket you don't control. | |
| To execute these files, you'll need to put first-boot.json and Bootstrap-EC2-Windows.ps1 in your | |
| chef bucket, along with your chef validator.pem, then copy the entire contents of ec2-user-data.ps1 | |
| into the 'user-data' field of a fresh Amazon server. Provided you've set EC2-Config on the Windows | |
| Server, to run EC2 user data at boot, before making your AMI, it should run, download the Bootstrap | |
| script and run it, which in turn, should run everything else. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Bootstrapping Windows 2008/2008 R2/2012/2012 R2 in EC2, using Chef | |
| # Copyright 2015, Brighter Technology Ltd | |
| # Licence GPLv3 | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 3 of the License, or | |
| # (at your option) any later version. | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # A parameter you can pass an environment variable to for Chef, when we run Chef for the | |
| # first time, we will pass this environment variable to Chef. Comment out if not using | |
| # Environments in Chef, or using Chef Solo, etc. Note you will also need to edit the line | |
| # near the bottom of the script, which calls Chef for the first time. | |
| param([string]$chefEnvironment = "environment") | |
| # Setting up log files for this bootstrap script and the Chef initial run. | |
| $log = 'c:\Bootstrap.log' | |
| $chefbootstrap = 'c:\Chef-Bootstrap.log' | |
| #Create directory to download our installers to. | |
| New-Item -ItemType Directory -Path "C:\Scratch" | |
| Set-Location -Path "C:\Scratch" | |
| # Download and install chef, as a service, so that it starts up automatically on reboot | |
| Add-Content $log -value "Downloading Chef Installer" | |
| Read-S3Object -BucketName your-chef-bucket -Key 'chef-client-12.2.1-1.msi' -File 'C:\Scratch\chef-client-12.2.1-1.msi' | |
| Add-Content $log -value "Running Chef Installer" | |
| Start-Process -FilePath "msiexec.exe" -ArgumentList '/qn /i C:\Scratch\chef-client-12.2.1-1.msi ADDLOCAL="ChefClientFeature,ChefServiceFeature" /norestart' -Wait | |
| SetX Path "${Env:Path};C:\opscode\chef\bin" /m | |
| $Env:Path += ';C:\opscode\chef\bin' | |
| Add-Content $log -value "Installed Chef" | |
| # Get the validator key from S3 | |
| Read-S3Object -BucketName your-chef-bucket -Key 'your-company-validator.pem' -File 'C:\chef\your-company-validator.pem' | |
| # Create required Chef files | |
| # client.rb sets the ENVIRONMENT of the node, along with some basics. | |
| New-Item c:\chef\client.rb -type file -force | |
| Add-Content C:\chef\client.rb "log_level :info" | |
| Add-Content C:\chef\client.rb "log_location STDOUT" | |
| Add-Content C:\chef\client.rb "chef_server_url 'https://chef.yourdomain.com/organizations/your-company'" | |
| Add-Content C:\chef\client.rb "validation_client_name 'your-company-validator'" | |
| Add-Content C:\chef\client.rb "validation_key 'c:\chef\your-company-validator.pem'" | |
| # The following works out a unique name for the instance, based on its IP address. If the instance has an IP of | |
| # 10.0.0.1 for example, with this code, its name will be worked out as IP-10-0-0-1. This bit of code only works it | |
| # out for the Chef Node Name property, but you can also then use the node name, to change the machine name of | |
| # the instance before adding to the domain and/or even change the 'name' tag of the instance in EC2. | |
| $newCompName = "IP" | |
| $ip = ((Test-Connection $env:computername -Count 1).ipv4address).ipaddresstostring | |
| $octets = $ip -split '\.' | |
| foreach ($octet in $octets) | |
| { | |
| $newCompName = $newCompName + "-" + $octet | |
| } | |
| # Add the new machine name to client.rb so that it shows up properly in chef and doesn't conflict on bootstrap with an existing node. | |
| Add-Content C:\chef\client.rb "node_name '$newCompName'" | |
| # create knife.rb and add in the chef_server_url value, so we can bypass ssl verification. | |
| New-Item c:\chef\knife.rb -type file -force | |
| Add-Content C:\chef\knife.rb "chef_server_url 'https://chef.yourdomain.com/organizations/your-company'" | |
| #Set the DNS servers so that we can join the Domain. If you're not adding the instance to a domain, comment it out. | |
| #If Windows 6.2 (Windows 2012/Windows 8) or above, we can use Set-DnsClientServerAddress, if it's 2008R2/Windows 7 or below, we can't and must use wmi. | |
| if([Environment]::OSVersion.Version -ge (new-object 'Version' 6,2)){ | |
| Set-DnsClientServerAddress -InterfaceAlias Ethernet -ServerAddresses 10.0.1.10,10.0.2.10 | |
| } else { | |
| $newDNS = "10.0.1.10","10.0.2.10" | |
| $NetworkAdapterConfig = Get-WMIObject -Class Win32_NetworkAdapterConfiguration -Filter "ipenabled = 'true'" | |
| $NetworkAdapterConfig.SetDNSServerSearchOrder($newDNS) | |
| # In 2008 R2, we need to set the DNS suffix list to include our domain, or our server will struggle to join the | |
| # domain and rename the server at the same time (Meaning only one reboot, not two) | |
| $suffixList = $NetworkAdapterConfig.DNSDomainSuffixSearchOrder | |
| $NetworkAdapterConfig.DNSDomainSuffixSearchOrder = $suffixList + "spotmain.com" | |
| } | |
| Add-Content $log -value 'Setting DNS servers to 10.0.1.10 and 10.0.2.10' | |
| # Are you using self signed SSL? This will get around the SSL verification issue with a self signed cert. | |
| cd c:\chef | |
| knife ssl check | |
| knife ssl fetch | |
| # Launch chef client, telling it which environment to use and pointing it at it's first-boot.json to get its role. | |
| & 'C:\opscode\chef\bin\chef-client.bat' -E $chefEnvironment -j C:\chef\first-boot.json 2>&1 > "$chefbootstrap" | |
| # Bootstrapping is done, we will need to reboot now to complete domain joins and machine re-name actions. If you | |
| # did not add to a domain, or rename, you probably still want a reboot, just to set everything off as normal and | |
| # verify the machine will survive future reboots. | |
| Restart-Computer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <powershell> | |
| while (-Not (Test-Connection -ComputerName 8.8.8.8 -Count 1 -ErrorAction SilentlyContinue)) | |
| { | |
| Start-Sleep -Seconds 5 | |
| } | |
| Read-S3Object -BucketName your-chef-bucket -Key Bootstrap-EC2-Windows.ps1 -File C:\Bootstrap-EC2-Windows.ps1 | |
| while (-Not (Get-Item -Path "C:\Bootstrap-EC2-Windows.ps1" -ErrorAction SilentlyContinue)) | |
| { | |
| Start-Sleep -Seconds 1 | |
| } | |
| Read-S3Object -BucketName your-chef-bucket -Key first-boot.json -File C:\chef\first-boot.json | |
| Invoke-Expression "C:\Bootstrap-EC2-Windows.ps1 sandbox" | |
| </powershell> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "run_list": ["role[windows-server]"] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment