schemaVersion: '0.3' description: Cloned from AWS-UpdateWindowsAmi. Removed steps such that this document works with Windows Server 2025. 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}} TargetImageDescription: type: String description: (Optional) The description of the new AMI that will be created. default: Updated Windows Ami 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 t3.medium. default: t3.medium SecurityGroupIds: type: StringList description: (Optional) A comma separated list of security group IDs with the required Inbound and Outbound connectivity rules. allowedPattern: ^sg-[a-z0-9]{8,17}$ default: [] SubnetId: type: String description: (Optional) Specify the SubnetId if you want to launch into a specific subnet. default: '' 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: '' MetadataOptions: type: StringMap description: (Optional) The metadata options for the instance. default: HttpEndpoint: enabled HttpTokens: optional mainSteps: - name: LaunchInstance action: aws:runInstances maxAttempts: 3 timeoutSeconds: 1800 nextStep: RunPreUpdateScript isEnd: false onFailure: Abort inputs: ImageId: '{{ SourceAmiId }}' InstanceType: '{{ InstanceType }}' MinInstanceCount: 1 MaxInstanceCount: 1 IamInstanceProfileName: '{{ IamInstanceProfileName }}' SubnetId: '{{ SubnetId }}' SecurityGroupIds: '{{SecurityGroupIds}}' MetadataOptions: '{{MetadataOptions}}' TagSpecifications: - ResourceType: instance Tags: - Key: Name Value: SSM-TempInstanceForPatching-{{global:DATE_TIME}} - Key: SSMDocumentName Value: HJ-UpdateWindows2025Ami - name: RunPreUpdateScript action: aws:runCommand maxAttempts: 3 timeoutSeconds: 1800 nextStep: UpdateEC2Config isEnd: false onFailure: Abort inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ LaunchInstance.InstanceIds }}' Parameters: commands: '{{ PreUpdateScript }}' - name: UpdateEC2Config action: aws:runCommand maxAttempts: 3 timeoutSeconds: 7200 nextStep: InstallUpdatesAndReboot isEnd: false onFailure: Abort inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ LaunchInstance.InstanceIds }}' Parameters: commands: - $zipFilename = 'AWSUpdateWindowsInstance.zip' - $zipFileHash = '0BD8C683CEFD69D975D2F3AE3B9EAFB533F6037D58427B65DB36934D7B6B70FD' - $moduleName = 'AWSUpdateWindowsInstance' - $tempPath = $env:TEMP - $moduleDirectory = Join-Path $tempPath -ChildPath $moduleName - $nonOptInRegions = @('ap-northeast-1', 'ap-northeast-2', 'ap-northeast-3', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1', 'eu-north-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2') - $moduleZipFilePath = Join-Path $tempPath -ChildPath $zipFilename - $moduleManifestPath = Join-Path $moduleDirectory -ChildPath ('{0}.psd1' -f $moduleName) - '' - $ssmAgentService = Get-ItemProperty 'HKLM:SYSTEM\CurrentControlSet\Services\AmazonSSMAgent\' -ErrorAction SilentlyContinue - $region = $env:AWS_SSM_REGION_NAME - '' - function Main { - ' $ec2launchV2 = "$($env:ProgramFiles)\Amazon\EC2Launch\EC2Launch.exe"' - '' - ' if (Test-Path $ec2launchV2) {' - ' return' - ' }' - '' - ' if ([Environment]::OSVersion.Version.Major -ge 10) {' - ' Invoke-UpdateEC2Launch' - ' } else {' - ' Invoke-UpdateEC2Config' - ' }' - '}' - '' - function Invoke-UpdateEC2Config { - ' try {' - ' Import-Module $moduleManifestPath' - ' $command = "Install-AwsUwiEC2Config -Region $region"' - ' if($id) { $command += " -Id $($id)"}' - ' Invoke-Expression $command' - ' } catch {' - ' Write-Host ''Executing Invoke-AwsUwiEC2Config resulted in error: $($_)''' - ' Exit -1' - ' }' - '}' - '' - function Invoke-UpdateEC2Launch { - ' try {' - ' Import-Module $moduleManifestPath' - ' $command = ''Install-AwsUwiEC2Launch''' - ' if($id) { $command += " -Id $($id)" }' - ' Invoke-Expression $command' - ' } catch {' - ' Write-Host ''Executing Invoke-AwsUwiEC2Launch resulted in error: $($_)''' - ' Exit -1' - ' }' - '}' - '' - Main - name: InstallUpdatesAndReboot action: aws:runCommand nextStep: WaitForInstanceOnline isEnd: false onFailure: step:TerminateInstance inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ LaunchInstance.InstanceIds }}' Parameters: commands: - | net stop bits net stop wuauserv Remove-Item -Recurse -Force "$env:SystemRoot\SoftwareDistribution\*" -ErrorAction SilentlyContinue Remove-Item -Recurse -Force "$env:SystemRoot\System32\catroot2\*" -ErrorAction SilentlyContinue net start bits net start wuauserv Install-Module PSWindowsUpdate -Force -Scope AllUsers Import-Module PSWindowsUpdate Install-WindowsUpdate -AcceptAll -Confirm:$false -AutoReboot - name: WaitForInstanceOnline action: aws:waitForAwsResourceProperty timeoutSeconds: 600 nextStep: RunPostUpdateScript isEnd: false inputs: Service: ssm Api: DescribeInstanceInformation InstanceInformationFilterList: - key: InstanceIds valueSet: - '{{ LaunchInstance.InstanceIds }}' PropertySelector: $.InstanceInformationList[0].PingStatus DesiredValues: - Online - name: RunPostUpdateScript action: aws:runCommand maxAttempts: 3 timeoutSeconds: 1800 nextStep: RunSysprepGeneralize isEnd: false onFailure: Abort inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{ LaunchInstance.InstanceIds }}' Parameters: commands: '{{ PostUpdateScript }}' - name: RunSysprepGeneralize action: aws:runCommand maxAttempts: 3 timeoutSeconds: 600 nextStep: StopInstance isEnd: false onFailure: Abort inputs: DocumentName: AWSEC2-RunSysprep InstanceIds: - '{{LaunchInstance.InstanceIds}}' Parameters: Id: '{{automation:EXECUTION_ID}}' - name: StopInstance action: aws:changeInstanceState maxAttempts: 3 timeoutSeconds: 7200 nextStep: CreateImage isEnd: false onFailure: Abort inputs: InstanceIds: - '{{ LaunchInstance.InstanceIds }}' CheckStateOnly: false DesiredState: stopped - name: CreateImage action: aws:createImage maxAttempts: 3 nextStep: TerminateInstance isEnd: false onFailure: Abort inputs: InstanceId: '{{ LaunchInstance.InstanceIds }}' ImageName: '{{ TargetAmiName }}' NoReboot: true ImageDescription: '{{ TargetImageDescription }}' - name: TerminateInstance action: aws:changeInstanceState maxAttempts: 3 isEnd: true onFailure: Abort inputs: InstanceIds: - '{{ LaunchInstance.InstanceIds }}' DesiredState: terminated outputs: - CreateImage.ImageId