-
-
Save bombel2/50ed0289ab29d5d4597c120045afff4a to your computer and use it in GitHub Desktop.
aws-updatewindowsami in yaml
This file contains 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
--- | |
schemaVersion: '0.3' | |
description: Updates a Microsoft Windows AMI. By default it will install all Windows | |
updates, Amazon software, and Amazon drivers. It will then sysprep and create a | |
new AMI. Supports Windows Server 2008 R2 and greater. | |
assumeRole: "{{ AutomationAssumeRole }}" | |
parameters: | |
SourceAmiId: | |
type: String | |
description: "(Required) The source Amazon Machine Image ID." | |
IamInstanceProfileName: | |
type: String | |
description: "(Required) The name of the role that enables Systems Manager to | |
manage the instance." | |
default: ManagedInstanceProfile | |
AutomationAssumeRole: | |
type: String | |
description: "(Required) The ARN of the role that allows Automation to perform | |
the actions on your behalf." | |
default: arn:aws:iam::{{global:ACCOUNT_ID}}:role/AutomationServiceRole | |
TargetAmiName: | |
type: String | |
description: "(Optional) The name of the new AMI that will be created. Default | |
is a system-generated string including the source AMI id, and the creation time | |
and date." | |
default: UpdateWindowsAmi_from_{{SourceAmiId}}_on_{{global:DATE_TIME}} | |
InstanceType: | |
type: String | |
description: "(Optional) Type of instance to launch as the workspace host. Instance | |
types vary by region. Default is t2.medium." | |
default: t2.medium | |
IncludeKbs: | |
type: String | |
description: "(Optional) Specify one or more Microsoft Knowledge Base (KB) article | |
IDs to include. You can install multiple IDs using comma-separated values. Valid | |
formats: KB9876543 or 9876543." | |
default: '' | |
ExcludeKbs: | |
type: String | |
description: "(Optional) Specify one or more Microsoft Knowledge Base (KB) article | |
IDs to exclude. You can exclude multiple IDs using comma-separated values. Valid | |
formats: KB9876543 or 9876543." | |
default: '' | |
Categories: | |
type: String | |
description: "(Optional) Specify one or more update categories. You can filter | |
categories using comma-separated values. Options: Application, Connectors, CriticalUpdates, | |
DefinitionUpdates, DeveloperKits, Drivers, FeaturePacks, Guidance, Microsoft, | |
SecurityUpdates, ServicePacks, Tools, UpdateRollups, Updates. Valid formats | |
include a single entry, for example: CriticalUpdates. Or you can specify a comma | |
separated list: CriticalUpdates,SecurityUpdates. NOTE: There cannot be any spaces | |
around the commas." | |
default: '' | |
SeverityLevels: | |
type: String | |
description: "(Optional) Specify one or more MSRC severity levels associated with | |
an update. You can filter severity levels using comma-separated values. By default | |
patches for all security levels are selected. If value supplied, the update | |
list is filtered by those values. Options: Critical, Important, Low, Moderate | |
or Unspecified. Valid formats include a single entry, for example: Critical. | |
Or, you can specify a comma separated list: Critical,Important,Low." | |
default: '' | |
PublishedDaysOld: | |
type: String | |
default: '' | |
description: "(Optional) Specify the amount of days old the updates must be from | |
the published date. For example, if 10 is specified, any updates that were | |
found during the Windows Update search that have been published 10 or more days | |
ago will be returned." | |
PublishedDateAfter: | |
type: String | |
default: '' | |
description: "(Optional) Specify the date that the updates should be published | |
after. For example, if 01/01/2017 is specified, any updates that were found | |
during the Windows Update search that have been published on or after 01/01/2017 | |
will be returned." | |
PublishedDateBefore: | |
type: String | |
default: '' | |
description: "(Optional) Specify the date that the updates should be published | |
before. For example, if 01/01/2017 is specified, any updates that were found | |
during the Windows Update search that have been published on or before 01/01/2017 | |
will be returned." | |
PreUpdateScript: | |
type: String | |
description: "(Optional) A script provided as a string. It will execute prior | |
to installing OS updates." | |
default: '' | |
PostUpdateScript: | |
type: String | |
description: "(Optional) A script provided as a string. It will execute after | |
installing OS updates." | |
default: '' | |
mainSteps: | |
- name: LaunchInstance | |
action: aws:runInstances | |
timeoutSeconds: 1800 | |
maxAttempts: 3 | |
onFailure: Abort | |
inputs: | |
ImageId: "{{ SourceAmiId }}" | |
InstanceType: "{{ InstanceType }}" | |
MinInstanceCount: 1 | |
MaxInstanceCount: 1 | |
IamInstanceProfileName: "{{ IamInstanceProfileName }}" | |
- name: OSCompatibilityCheck | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 7200 | |
inputs: | |
DocumentName: AWS-RunPowerShellScript | |
InstanceIds: | |
- "{{LaunchInstance.InstanceIds}}" | |
Parameters: | |
executionTimeout: '7200' | |
commands: | |
[System.Version]$osversion = [System.Environment]::OSVersion.Version | |
if(($osversion.Major -eq 6 -and $osversion.Minor -ge 1) -or ($osversion.Major -ge 10)) { | |
Write-Host 'This OS is supported for use with this automation document.' | |
} else { | |
Write-Host 'This OS is not supported for use with this automation document.' | |
exit -1 | |
} | |
- name: RunPreUpdateScript | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 1800 | |
inputs: | |
DocumentName: AWS-RunPowerShellScript | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
Parameters: | |
commands: "{{ PreUpdateScript }}" | |
- name: UpdateEC2Config | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 7200 | |
inputs: | |
DocumentName: AWS-RunPowerShellScript | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
Parameters: | |
commands: | |
$moduleName = 'AWSUpdateWindowsInstance' | |
$zipFilename = 'AWSUpdateWindowsInstance.zip' | |
$tempPath = $env:TEMP | |
$moduleDirectory = Join-Path $tempPath -ChildPath $moduleName | |
$moduleZipFilePath = Join-Path $tempPath -ChildPath $zipFilename | |
$moduleManifestPath = Join-Path $moduleDirectory -ChildPath ('{0}.psd1' -f $moduleName) | |
$id = '{{automation:EXECUTION_ID}}' | |
$regionUrl = 'http://169.254.169.254/latest/dynamic/instance-identity/document/region' | |
$metadata = (New-Object Net.WebClient).DownloadString($regionUrl) | |
$region = (ConvertFrom-JSON $metadata).region | |
function Main { | |
Clear-WindowsUpdateModule | |
Get-WindowsUpdateModule | |
Expand-WindowsUpdateModule | |
if ([Environment]::OSVersion.Version.Major -ge 10) { | |
Invoke-UpdateEC2Launch | |
} else { | |
Invoke-UpdateEC2Config | |
} | |
} | |
function Clear-WindowsUpdateModule { | |
try { | |
if (Test-Path $moduleDirectory) { | |
Remove-Item $moduleDirectory -Force -Recurse | |
} | |
if (Test-Path $moduleZipFilePath) { | |
Remove-Item $moduleZipFilePath -Force | |
} | |
} catch { | |
Write-Host "Cleaning Windows update module resulted in error: $($_)" | |
} | |
} | |
function Get-WindowsUpdateModule { | |
try { | |
if ($region.StartsWith('cn-')) { | |
$s3Location = 'https://s3.{0}.amazonaws.com.cn/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} elseif($region.StartsWith('us-gov-')) { | |
$s3Location = 'https://s3-fips-{0}.amazonaws.com/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} elseif($region -eq 'us-east-1') { | |
$s3Location = 'https://s3.amazonaws.com/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} else { | |
$s3Location = 'https://aws-windows-downloads-{0}.s3.amazonaws.com/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} | |
$moduleS3Location = $s3Location -f $region, $zipFilename | |
$moduleLocalPath = Join-Path $tempPath -ChildPath $zipFilename | |
(New-Object Net.WebClient).DownloadFile($moduleS3Location, $moduleLocalPath) | |
$fileStream = New-Object System.IO.FileStream($moduleLocalPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) | |
$sha256 = [System.Security.Cryptography.HashAlgorithm]::Create('System.Security.Cryptography.SHA256CryptoServiceProvider') | |
$currentHash = [System.BitConverter]::ToString($sha256.ComputeHash($fileStream), 0).Replace('-', '').ToLowerInvariant() | |
$sha256.Dispose() | |
$fileStream.Dispose() | |
if ($currentHash -ne 'B32D397AAA312E5EB0B2E0E0BC7146FB716AED3867A73FA650E0F222DF1079AE') | |
{ | |
Write-Host 'The SHA hash of the module does not match the expected value.' | |
Exit -1 | |
} | |
} catch { | |
Write-Host ('Error encountered while getting the module: {0}.' -f $_.Exception.Message) | |
Exit -1 | |
} | |
} | |
function Expand-WindowsUpdateModule { | |
try { | |
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null | |
$zip = [System.IO.Compression.ZipFile]::OpenRead($moduleZipFilePath) | |
foreach ($item in $zip.Entries) { | |
$extractPath = Join-Path $tempPath -ChildPath $item.FullName | |
if ($item.Length -eq 0) { | |
if (-not (Test-Path $extractPath)) { | |
New-Item $extractPath -ItemType Directory | Out-Null | |
} | |
} else { | |
$parentPath = Split-Path $extractPath | |
if (-not (Test-Path $parentPath)) { | |
New-Item $parentPath -ItemType Directory | Out-Null | |
} | |
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($item, $extractPath, $true) | |
} | |
} | |
} catch { | |
Write-Host ('Error encountered when extracting module file: {0}.' -f $_.Exception.Message) | |
Exit -1 | |
} finally { | |
$zip.Dispose() | |
} | |
} | |
function Invoke-UpdateEC2Config { | |
Import-Module $moduleManifestPath | |
$command = "Install-AwsUwiEC2Config -Region $region" | |
if($id) { $command += " -Id $($id)"} | |
Invoke-Expression $command | |
} | |
function Invoke-UpdateEC2Launch { | |
Import-Module $moduleManifestPath | |
$command = 'Install-AwsUwiEC2Launch' | |
if($id) { $command += " -Id $($id)" } | |
Invoke-Expression $command | |
} | |
Main | |
- name: UpdateSSMAgent | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 600 | |
inputs: | |
DocumentName: AWS-UpdateSSMAgent | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
- name: UpdateAWSPVDriver | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 600 | |
inputs: | |
DocumentName: AWS-ConfigureAWSPackage | |
InstanceIds: | |
- "{{LaunchInstance.InstanceIds}}" | |
Parameters: | |
name: AWSPVDriver | |
action: Install | |
- name: UpdateAWSEnaNetworkDriver | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 600 | |
inputs: | |
DocumentName: AWS-ConfigureAWSPackage | |
InstanceIds: | |
- "{{LaunchInstance.InstanceIds}}" | |
Parameters: | |
name: AwsEnaNetworkDriver | |
action: Install | |
- name: InstallWindowsUpdates | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 14400 | |
inputs: | |
DocumentName: AWS-InstallWindowsUpdates | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
Parameters: | |
Action: Install | |
IncludeKbs: "{{ IncludeKbs }}" | |
ExcludeKbs: "{{ ExcludeKbs }}" | |
Categories: "{{ Categories }}" | |
SeverityLevels: "{{ SeverityLevels }}" | |
PublishedDaysOld: "{{ PublishedDaysOld }}" | |
PublishedDateAfter: "{{ PublishedDateAfter }}" | |
PublishedDateBefore: "{{ PublishedDateBefore }}" | |
- name: RunPostUpdateScript | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 1800 | |
inputs: | |
DocumentName: AWS-RunPowerShellScript | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
Parameters: | |
commands: "{{ PostUpdateScript }}" | |
- name: RunSysprepGeneralize | |
action: aws:runCommand | |
maxAttempts: 3 | |
onFailure: Abort | |
timeoutSeconds: 7200 | |
inputs: | |
DocumentName: AWS-RunPowerShellScript | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
Parameters: | |
commands: | | |
$moduleName = 'AWSUpdateWindowsInstance' | |
$zipFilename = 'AWSUpdateWindowsInstance.zip' | |
$tempPath = $env:TEMP | |
$moduleDirectory = Join-Path $tempPath -ChildPath $moduleName | |
$moduleZipFilePath = Join-Path $tempPath -ChildPath $zipFilename | |
$moduleManifestPath = Join-Path $moduleDirectory -ChildPath ('{0}.psd1' -f $moduleName) | |
$id = '{{automation:EXECUTION_ID}}' | |
function Main { | |
Test-PreCondition | |
Clear-WindowsUpdateModule | |
Get-WindowsUpdateModule | |
Expand-WindowsUpdateModule | |
Invoke-RunSysprep | |
} | |
function Test-PreCondition { | |
$osversion = [Environment]::OSVersion.Version | |
if ($osversion.Major -le 5) { | |
Write-Host 'This document is not supported on Windows Server 2003 or earlier.' | |
Exit -1 | |
} | |
if ($osversion.Version -ge '10.0') { | |
$sku = (Get-CimInstance -ClassName Win32_OperatingSystem).OperatingSystemSKU | |
if ($sku -eq 143 -or $sku -eq 144) { | |
Write-Host 'This document is not supported on Windows 2016 Nano Server.' | |
Exit -1 | |
} | |
} | |
$ssmAgentService = Get-ItemProperty 'HKLM:SYSTEM\\CurrentControlSet\\Services\\AmazonSSMAgent\\' -ErrorAction SilentlyContinue | |
if (-not $ssmAgentService -or $ssmAgentService.Version -lt '2.0.533.0') | |
{ | |
Write-Host 'This document is not supported with SSM Agent version less than 2.0.533.0.' | |
exit -1 | |
} | |
} | |
function Clear-WindowsUpdateModule { | |
try { | |
if (Test-Path $moduleDirectory) { | |
Remove-Item $moduleDirectory -Force -Recurse | |
} | |
if (Test-Path $moduleZipFilePath) { | |
Remove-Item $moduleZipFilePath -Force | |
} | |
} catch { | |
Write-Host "Cleaning Windows update module resulted in error: $($_)" | |
} | |
} | |
function Get-WindowsUpdateModule { | |
try { | |
$region = $env:AWS_SSM_REGION_NAME | |
if ($region.StartsWith('cn-')) { | |
$s3Location = 'https://s3.{0}.amazonaws.com.cn/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} elseif($region.StartsWith('us-gov-')) { | |
$s3Location = 'https://s3-fips-{0}.amazonaws.com/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} elseif($region -eq 'us-east-1') { | |
$s3Location = 'https://s3.amazonaws.com/aws-windows-downloads-{0}/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} else { | |
$s3Location = 'https://aws-windows-downloads-{0}.s3.amazonaws.com/PSModules/AWSUpdateWindowsInstance/Latest/{1}' | |
} | |
$moduleS3Location = $s3Location -f $region, $zipFilename | |
$moduleLocalPath = Join-Path $tempPath -ChildPath $zipFilename | |
(New-Object Net.WebClient).DownloadFile($moduleS3Location, $moduleLocalPath) | |
$fileStream = New-Object System.IO.FileStream($moduleLocalPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) | |
$sha256 = [System.Security.Cryptography.HashAlgorithm]::Create('System.Security.Cryptography.SHA256CryptoServiceProvider') | |
$currentHash = [System.BitConverter]::ToString($sha256.ComputeHash($fileStream), 0).Replace('-', '').ToLowerInvariant() | |
$sha256.Dispose() | |
$fileStream.Dispose() | |
if ($currentHash -ne 'B32D397AAA312E5EB0B2E0E0BC7146FB716AED3867A73FA650E0F222DF1079AE') | |
{ | |
Write-Host 'The SHA hash of the module does not match the expected value.' | |
Exit -1 | |
} | |
} catch { | |
Write-Host ('Error encountered while getting the module: {0}.' -f $_.Exception.Message) | |
Exit -1 | |
} | |
} | |
function Expand-WindowsUpdateModule { | |
try { | |
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null | |
$zip = [System.IO.Compression.ZipFile]::OpenRead($moduleZipFilePath) | |
foreach ($item in $zip.Entries) { | |
$extractPath = Join-Path $tempPath -ChildPath $item.FullName | |
if ($item.Length -eq 0) { | |
if (-not (Test-Path $extractPath)) { | |
New-Item $extractPath -ItemType Directory | Out-Null | |
} | |
} else { | |
$parentPath = Split-Path $extractPath | |
if (-not (Test-Path $parentPath)) { | |
New-Item $parentPath -ItemType Directory | Out-Null | |
} | |
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($item, $extractPath, $true) | |
} | |
} | |
} catch { | |
Write-Host ('Error encountered when extracting module file: {0}.' -f $_.Exception.Message) | |
Exit -1 | |
} finally { | |
$zip.Dispose() | |
} | |
} | |
function Invoke-RunSysprep { | |
Import-Module $moduleManifestPath | |
$command = 'Start-AwsUwiSysprep' | |
if($id) { $command += " -Id $($id)"} | |
Invoke-Expression $command | |
} | |
Main | |
- name: StopInstance | |
action: aws:changeInstanceState | |
maxAttempts: 3 | |
timeoutSeconds: 7200 | |
onFailure: Abort | |
inputs: | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
CheckStateOnly: false | |
DesiredState: stopped | |
- name: CreateImage | |
action: aws:createImage | |
maxAttempts: 3 | |
onFailure: Abort | |
inputs: | |
InstanceId: "{{ LaunchInstance.InstanceIds }}" | |
ImageName: "{{ TargetAmiName }}" | |
NoReboot: true | |
ImageDescription: Test CreateImage Description | |
- name: TerminateInstance | |
action: aws:changeInstanceState | |
maxAttempts: 3 | |
onFailure: Abort | |
inputs: | |
InstanceIds: | |
- "{{ LaunchInstance.InstanceIds }}" | |
DesiredState: terminated | |
outputs: | |
- CreateImage.ImageId |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment