Skip to content

Commit

Permalink
fix(core): windows cloudwatch agent install script
Browse files Browse the repository at this point in the history
Fixes #295

This fixes a bug that is preventing the deployment of any worker
instance that is using an AMI with a Windows OS.
  • Loading branch information
horsmand committed Jan 22, 2021
1 parent b4f1d15 commit c1136e8
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,62 +16,105 @@ param (

$ErrorActionPreference = "Stop"

$file = "$env:temp\amazon-cloudwatch-agent.msi"
Write-Output "Starting CloudWatch installation and configuration script."

# We hardcode the version number here since the verification below is tightly coupled with this specific version
$is_cloudwatch_installed = $False
try {
Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/1.242486.0/amazon-cloudwatch-agent.msi -File $file -Region us-east-1
# If this command doesn't throw an error, we have the CloudWatch agent installed already
$status = & $Env:ProgramFiles\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1 -m ec2 -a status
$is_cloudwatch_installed = $True
Write-Output "Found CloudWatch agent already installed, skipping installation."
} catch {
# Fallback to the latest version (this is the case when the above version is currently "latest")
Write-Output "Initial attempt to download Amazon CloudWatch agent failed. Falling back to the latest version."
Write-Output "CloudWatch agent is not already installed, proceeding with installation."
}

if (-Not $is_cloudwatch_installed) {
$cwa_installer = "$env:temp\amazon-cloudwatch-agent.msi"
try {
Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/latest/amazon-cloudwatch-agent.msi -File $file -Region us-east-1
Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/latest/amazon-cloudwatch-agent.msi -File $cwa_installer -Region us-east-1
} catch {
Write-Output "Failed to download CloudWatchAgent installer."
Write-Output "Failed to download CloudWatch agent installer."
Exit 1
}
}

# The below verification is tied to the version of the msi installer
# If the installer version changes, the below verification could break and should be updated accordingly.
# See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/verify-CloudWatch-Agent-Package-Signature.html
if (-Not $s) {
$sig = Get-AuthenticodeSignature $file
$status = $sig | Select-Object -ExpandProperty 'Status'
if ( $status -ne 'Valid' ) {
Write-Output "CloudWatchAgent installer does not have a valid signature."
$cwa_installer_sig = "$env:temp\amazon-cloudwatch-agent.msi.sig"
try {
Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/latest/amazon-cloudwatch-agent.msi.sig -File $cwa_installer_sig -Region us-east-1
} catch {
Write-Output "Failed to download CloudWatch agent installer signature file."
Exit 1
}

# CA Certificate is:
# - Subject: CN=DigiCert Timestamp Responder, O=DigiCert, C=US
# - Valid: [Not After] 10/21/2024 7:00:00 PM
# - Thumbprint: 614D271D9102E30169822487FDE5DE00A352B01D
$ca = $sig | Select-Object -ExpandProperty 'TimeStamperCertificate'
$ca_thumbprint = $ca | Select-Object -ExpandProperty 'Thumbprint'
if ( $ca_thumbprint -ne '614D271D9102E30169822487FDE5DE00A352B01D' ) {
Write-Output "CA Thumbprint failed verification. Has the CA certificate been changed? If so, then please submit a PR to fix this."
Write-Output $( $ca | Format-List )
Exit 1
}
if (-Not $s) {
$gpg_keyring = "$env:temp\keyring.gpg"

# Amazon.com certificate is:
# - Subject: 'CN=Amazon.com Services LLC, OU=Software Services, O=Amazon.com Services LLC, L=Seattle, S=Washington, C=US'
# We do not check the Thumbprint because it will change when the certificate is rotated. This seems to be yearly.
$cert = $sig | Select-Object -ExpandProperty 'SignerCertificate'
$cert_subject = $cert | Select-Object -ExpandProperty 'Subject'
if ( $cert_subject -ne 'CN=Amazon.com Services LLC, OU=Software Services, O=Amazon.com Services LLC, L=Seattle, S=Washington, C=US' ) {
Write-Output "Amazon.com is not the issuer of this installer. If this is the correct then please submit a PR to fix this."
Write-Output $( $cert | Format-List )
Exit 1
# Download GPG
$gpg_installer = "$env:temp\gnupg-w32-2.2.27_20210111.exe"
wget https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.2.27_20210111.exe -OutFile $gpg_installer

# Verify GPG
$gpg_sig = Get-AuthenticodeSignature $gpg_installer
$status = $gpg_sig | Select-Object -ExpandProperty 'Status'
if ( $status -ne 'Valid' ) {
Write-Output "GPG installer does not have a valid signature."
Exit 1
}
$sha256_expected = '5D89E239790822711EAE2899467A764879D21440AB68E9413452FA96CEDEBA50'
$sha256 = Get-FileHash $gpg_installer -Algorithm SHA256
if ( $sha256 -inotmatch $sha256_expected) {
Write-Output "GPG failed checksum verification. Expected sha256 to equal $sha256_expected but got:"
Write-Output $sha256
Exit 1
}

# Install GPG
Start-Process -Wait -FilePath $gpg_installer -ArgumentList "/S /v/qn" -PassThru

# Refresh the PATH so gpg is available
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")

# Download Amazon's public key and import it to GPG's keyring
$cloudwatch_pub_key = "$env:temp\amazon-cloudwatch-agent.gpg"
Read-S3Object -BucketName amazoncloudwatch-agent -Key assets/amazon-cloudwatch-agent.gpg -File $cloudwatch_pub_key -Region us-east-1
gpg --no-default-keyring --keyring $gpg_keyring --import $cloudwatch_pub_key

# Verify that the imported key has the correct fingerprint
$fingerprint = '937616F3450B7D806CBD9725D58167303B789C72'
$keys = gpg --no-default-keyring --keyring $gpg_keyring -k
$keys = ($keys | Out-String).Trim() -replace "\r", "" -replace "\n", "" -replace "\[", "" -replace "\]", ""

if ($keys -inotlike "*$fingerprint*") {
Write-Output "Expected CloudWatch agent's public key to equal $fingerprint but got:"
Get-Content $keys
Exit 1
}

# Now that we have the public key on the keyring, we can use gpg to perform the verification of the installer with the signature file.
# We will write the output to file and then perform a text search to make sure there's a good signature present in it
$gpg_output = "$env:temp\gpg_out.txt"
Start-Process gpg -ArgumentList " --no-default-keyring --keyring $gpg_keyring --verify $cwa_installer_sig $cwa_installer" `
-wait -NoNewWindow -PassThru -RedirectStandardError $gpg_output

$verification = Select-String -Path $gpg_output -Pattern 'Good signature from "Amazon CloudWatch Agent"' | Select-Object -ExpandProperty Matches -First 1
if (-Not $verification) {
Write-Output "Could not verify CloudWatch agent's signature file with GPG."
Get-Content $gpg_output
Exit 1
}
}
}

# Install the agent
Start-Process "msiexec.exe" -ArgumentList "/i $env:temp\amazon-cloudwatch-agent.msi /qn /norestart" -Wait -Passthru -NoNewWindow
# Install the agent
Start-Process "msiexec.exe" -ArgumentList "/i $cwa_installer /qn /norestart" -Wait -Passthru -NoNewWindow

Remove-Item -Path $cloudwatch_pub_key -Force
Remove-Item -Path $cwa_installer -Force
Remove-Item -Path $cwa_installer_sig -Force
Remove-Item -Path $gpg_installer -Force
Remove-Item -Path $gpg_output -Force
Remove-Item -Path $gpg_keyring -Force
}

# Configure the agent from an ssm parameter-store parameter.
& 'C:/Program Files/Amazon/AmazonCloudWatchAgent/amazon-cloudwatch-agent-ctl.ps1' -a append-config -m ec2 -c ssm:$ssmParameterName -s

Remove-Item -Path $file -Force
Write-Output "CloudWatchAgent has been successfully installed and configured"
Write-Output "CloudWatch agent has been successfully installed and configured"
4 changes: 2 additions & 2 deletions packages/aws-rfdk/lib/core/test/asset-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const CWA_ASSET_LINUX = {

// ConfigureCloudWatchAgent.ps1
export const CWA_ASSET_WINDOWS = {
Bucket: 'AssetParameters05415690a7593cdde72555787eaac1d784dd3173e6083f23f83dc795bfe1741fS3Bucket0E53698F',
Key: 'AssetParameters05415690a7593cdde72555787eaac1d784dd3173e6083f23f83dc795bfe1741fS3VersionKeyE92C9DEB',
Bucket: 'AssetParametersec9cf6c4433ba693c529f90d2cb0b5ed3373147653006871b49a3bd37d388a44S3BucketBBDC41D8',
Key: 'AssetParametersec9cf6c4433ba693c529f90d2cb0b5ed3373147653006871b49a3bd37d388a44S3VersionKeyAA5BD7E4',
};

// mountEbsBlockVolume.sh + metadataUtilities.sh + ec2-certificates.crt
Expand Down

0 comments on commit c1136e8

Please sign in to comment.