department-of-veterans-affairs / notification-api

Notification API
MIT License
16 stars 9 forks source link

BUG: Twistlock instance failure #670

Closed k-macmillan closed 1 year ago

k-macmillan commented 2 years ago

Description

As a VANotify team member I want to have a stable EC2 instance running twistlock So that I have confidence that it will actually run on deploys

Twistlock intermittently fails status checks and is no longer reachable. In the Twistlock action, this looks like: Screen Shot 2023-04-17 at 12.29.16 PM.jpg

AWS EC2 instance is rebooted but it still fails sometimes. It may be as simple as beefing up the server, but a review of the logs for the instance would be worthwhile.

image.png

Screen Shot 2023-04-17 at 12.29.03 PM.jpg

Steps to Reproduce

A system log from the most recent failure is linked here.

Impact/Urgency

Medium

Expected behavior

Workaround

Manually stop and restart the instance. Re-run any failed Twistlock action.

QA Considerations

Additional Info & Resources

I added an alarm that will auto reboot it if it fails for 5 consecutive minutes. edit: update - if this alarm was added, the auto reboot does not appear to work.

mjones-oddball commented 2 years ago

Hey team! Please add your planning poker estimate with ZenHub @EvanParish @ianperera @jakehova @jessecanderson @k-macmillan @kalbfled @maham360

cris-oddball commented 1 year ago

Logs show a number of ssm errors. Sadly, I cannot attach CSV files to these issues.

cris-oddball commented 1 year ago

from messages:

Mar 15 21:24:57 ip-10-247-142-247 journalbeat: 2023-03-15T21:24:57.369Z#011INFO#011[publisher_pipeline_output]#011pipeline/output.go:151#011Connection to backoff(async(tcp://aws-logstash-west.ecs.vaec.va.gov:5044)) established
Mar 15 21:25:00 ip-10-247-142-247 dhclient[5484]: XMT: Solicit on eth0, interval 116910ms.
Mar 15 21:25:00 ip-10-247-142-247 dhclient[5484]: send_packet6: Operation not permitted
Mar 15 21:25:00 ip-10-247-142-247 dhclient[5484]: dhc6: send_packet6() sent -1 of 52 bytes
Mar 15 21:25:09 ip-10-247-142-247 filebeat: {"log.level":"info","@timestamp":"2023-03-15T21:25:09.614Z","log.logger":"input.harvester","log.origin":{"file.name":"log/harvester.go","file.line":341},"message":"File is inactive. Closing because close_inactive of 5m0s reached.","service.name":"filebeat","input_id":"4bae04f0-13f9-4668-8fc2-dfd0b53deb61","source_file":"/var/log/cron","state_id":"native::833-64770","finished":false,"os_id":"833-64770","old_source":"/var/log/cron","old_finished":true,"old_os_id":"833-64770","harvester_id":"2213ae12-38bc-4879-bd56-4d7d6ce437ac","ecs.version":"1.6.0"}

ssm-errors

2023-03-15 14:44:51 ERROR [New @ errors.go.59] [ssm-agent-worker] [MessageService] [EngineProcessor] [BasicExecuter] [fba21165-f17b-4960-97d6-313bbf14fcec] received timedout signal!
2023-03-15 14:44:51 ERROR [messaging @ master.go.131] [ssm-agent-worker] [MessageService] [EngineProcessor] [BasicExecuter] [fba21165-f17b-4960-97d6-313bbf14fcec] messaging worker encountered error: document worker timed out

ssm-agent

2023-03-15 21:04:25 INFO [ECSIdentity] Agent not taking ECS identity: Could not fetch metadata endpoint
2023-03-15 21:04:41 INFO [ssm-agent-worker] [MessageService] [MGSInteractor] received message through control channel f4c45091-8908-4f3e-a415-85611e5046ef
2023-03-15 21:04:41 INFO [ssm-agent-worker] [MessageService] [MGSInteractor] Processing AgentMessage: MessageType - agent_job, Id - f4c45091-8908-4f3e-a415-85611e5046ef
"2023-03-15 21:04:41 INFO [ssm-agent-worker] [MessageService] [MGSInteractor] Parsing AgentMessage f4c45091-8908-4f3e-a415-85611e5046ef, Payload: {"schemaVersion":1,"jobId":"aws.ssm.9293d924-de8b-41e1-a707-6a0a86de43b4.i-03da12b042683cb0f","topic":"aws.ssm.sendCommand","content":"{\"OutputS3KeyPrefix\":\"\",\"CloudWatchOutputEnabled\":\"false\",\"Parameters\":{\"Operation\":\"Scan\"},\"DocumentContent\":{\"schemaVersion\":\"2.2\",\"description\":\"Scans for or installs patches from a patch baseline to a Linux, Windows or MacOS operating system.\",\"parameters\":{\"SnapshotId\":{\"default\":\"\",\"description\":\"(Optional) The snapshot ID to use to retrieve a patch baseline snapshot.\",\"type\":\"String\",\"allowedPattern\":\"(^$)|^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$\"},\"BaselineOverride\":{\"default\":\"\",\"description\":\"(Optional) An https URL or an Amazon S3 path-style URL to a list of baseline objects. These baselines override the default baseline and any baselines used by Patch Groups.\",\"type\":\"String\",\"allowedPattern\":\"(^$)|^https://([^/]+)/(.*?([^/]+))$|^s3://([^/]+)/(.*?([^/]+))$\"},\"RebootOption\":{\"allowedValues\":[\"RebootIfNeeded\",\"NoReboot\"],\"default\":\"RebootIfNeeded\",\"description\":\"(Optional) Reboot behavior after a patch Install operation. If you choose NoReboot and patches are installed, the instance is marked as non-compliant until a subsequent reboot and scan.\",\"type\":\"String\"},\"InstallOverrideList\":{\"default\":\"\",\"description\":\"(Optional) An https URL or an Amazon S3 path-style URL to the list of patches to be installed. This patch installation list overrides the patches specified by the default patch baseline.\",\"type\":\"String\",\"allowedPattern\":\"(^$)|^https://([^/]+)/(.*?([^/]+))$|^s3://([^/]+)/(.*?([^/]+))$\"},\"Operation\":{\"allowedValues\":[\"Scan\",\"Install\"],\"description\":\"(Required) The update or configuration to perform on the instance. The system checks if patches specified in the patch baseline are installed on the instance. The install operation installs patches missing from the baseline.\",\"type\":\"String\"},\"AssociationId\":{\"default\":\"\",\"description\":\"(Optional) The Association ID of the State Manager Association executing the document.\",\"type\":\"String\",\"allowedPattern\":\"^((([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}){0,1})$\"}},\"mainSteps\":[{\"inputs\":{\"timeoutSeconds\":7200,\"runCommand\":[\"# Check the OS version\",\"if ([Environment]::OSVersion.Version.Major -le 5) {\",\"    Write-Error \u0027This command is not supported on Windows 2003 or lower.\u0027\",\"    exit -1\",\"} elseif ([Environment]::OSVersion.Version.Major -ge 10) {\",\"    $sku \u003d (Get-CimInstance -ClassName Win32_OperatingSystem).OperatingSystemSKU\",\"    if ($sku -eq 143 -or $sku -eq 144) {\",\"        Write-Host \u0027This command is not supported on Windows 2016 Nano Server.\u0027\",\"        exit -1\",\"    }\",\"}\",\"# Check the SSM agent version\",\"$ssmAgentService \u003d Get-ItemProperty \u0027HKLM:SYSTEM\\\\CurrentControlSet\\\\Services\\\\AmazonSSMAgent\\\\\u0027\",\"if (-not $ssmAgentService -or $ssmAgentService.Version -lt \u00272.0.834.0\u0027) {\",\"    Write-Host \u0027This command is not supported with SSM Agent version less than 2.0.834.0.\u0027\",\"    exit -1\",\"}\",\"\",\"# Application specific constants\",\"$appName \u003d \u0027PatchBaselineOperations\u0027\",\"$psModuleFileName \u003d \u0027Amazon.PatchBaselineOperations.dll\u0027\",\"$s3FileName \u003d \u0027Amazon.PatchBaselineOperations-1.41.zip\u0027\",\"$s3LocationUsEast \u003d \u0027https://s3.amazonaws.com/aws-ssm-{0}/\u0027 + $appName.ToLower() + \u0027/\u0027 + $s3FileName\",\"$s3LocationRegular \u003d \u0027https://s3.{0}.amazonaws.com/aws-ssm-{0}/\u0027 + $appName.ToLower() + \u0027/\u0027 + $s3FileName\",\"$s3LocationCn \u003d \u0027https://s3.{0}.amazonaws.com.cn/aws-ssm-{0}/\u0027 + $appName.ToLower() + \u0027/\u0027 + $s3FileName\",\"$s3LocationNewRegion \u003d \u0027https://s3.{0}.amazonaws.com/aws-patch-manager-{0}-{1}/\u0027 + $appName.ToLower() + \u0027/\u0027 + $s3FileName\",\"$oldRegion \u003d @(\u0027ap-east-1\u0027, \u0027us-gov-east-1\u0027, \u0027us-gov-west-1\u0027, \u0027cn-northwest-1\u0027, \u0027cn-north-1\u0027, \u0027ca-central-1\u0027, \u0027ap-southeast-2\u0027, \u0027ap-southeast-1\u0027, \u0027us-west-1\u0027, \u0027us-west-2\u0027, \u0027ap-northeast-1\u0027, \u0027eu-west-2\u0027, \u0027ap-northeast-2\u0027, \u0027us-east-1\u0027, \u0027sa-east-1\u0027, \u0027eu-central-1\u0027, \u0027eu-west-1\u0027, \u0027us-east-2\u0027, \u0027eu-west-3\u0027,\u0027ap-south-1\u0027, \u0027eu-north-1\u0027)\",\"$regionsWithBucketNameAlg1 \u003d @(\u0027us-iso-west-1\u0027, \u0027us-iso-east-1\u0027, \u0027me-south-1\u0027, \u0027us-isob-east-1\u0027, \u0027eu-south-1\u0027, \u0027af-south-1\u0027, \u0027ap-southeast-3\u0027, \u0027ap-northeast-3\u0027)\",\"$s3FileHash \u003d \u002749662AE1B71FA4240B288DFA73A38F8C30567C37EE763E35725EA8CD124B2BE0\u0027\",\"$psModuleHashes \u003d @{\",\"    \u0027AWSSDK.Pinpoint.dll\u0027 \u003d \u0027300075578C54E803E596EB442136AC81B74D755E0AF90121241D566F30A964A1\u0027;\",\"\u0027AWSSDK.SecurityToken.dll\u0027 \u003d \u0027E9ABA063F4701357F14865AB4856C9D27691766BA316C0D57AB4D5E97CED8B98\u0027;\",\"\u0027YamlDotNet.dll\u0027 \u003d \u0027D59E777A42A965327FCC18FC0AB7FA6729C0BCF845D239AC2811BD78F73A7F70\u0027;\",\"\u0027AWSSDK.S3.dll\u0027 \u003d \u002723D8D52430BFD2AFC09ACEDE47C8DD2530A17DD39B9448706DE2A87FFE9ABAAF\u0027;\",\"\u0027Newtonsoft.Json.dll\u0027 \u003d \u00270516D4109263C126C779E4E8F5879349663FA0A5B23D6D44167403E14066E6F9\u0027;\",\"\u0027THIRD_PARTY_LICENSES.txt\u0027 \u003d \u00276468E28E2C9EDAF28E98B025EE95C936ED7493AEB19207C36525A5ED5AD4AA56\u0027;\",\"\u0027AWSSDK.SimpleSystemsManagement.dll\u0027 \u003d \u0027A645923106E7841F7F53412F0F311660A86AF314C169F15627CEA67EEBDB3637\u0027;\",\"\u0027Amazon.PatchBaselineOperations.dll\u0027 \u003d \u0027B7E9A4F911CB0A7122637BC383577E7F539D72476A2EA9C9A6B917533534844B\u0027;\",\"\u0027AWSSDK.Core.dll\u0027 \u003d \u00271D38F439931E2A39419EE07448F24DBE314A82D4319ECE3ADD9E12D72591E176\u0027;\",\"\u0027AWSSDK.CognitoIdentity.dll\u0027 \u003d \u0027733B334501E9EC0D1D4999910E5384D26EF7B3113D37A4078B183887EB9C0057\u0027;\",\"\",\"}\",\"\",\"# Folders and Logging\",\"$tempDirectory \u003d split-path -parent $MyInvocation.MyCommand.Definition\",\"$downloadPath \u003d [IO.Path]::Combine($tempDirectory, $s3FileName)\",\"$psModuleInstallLocation \u003d [IO.Path]::Combine([Environment]::GetEnvironmentVariable([Environment+SpecialFolder]::ProgramFiles), \u0027Amazon\u0027, $appName)\",\"$psModuleInstallFile \u003d [IO.Path]::Combine($psModuleInstallLocation, $psModuleFileName)\",\"\",\"function CheckFileHash ($filePath, $fileHash) {\",\"    if (Test-Path($filePath)) {\",\"        $fileStream \u003d New-Object System.IO.FileStream($filePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)\",\"        $sha256 \u003d [System.Security.Cryptography.HashAlgorithm]::Create(\u0027System.Security.Cryptography.SHA256CryptoServiceProvider\u0027)\",\"        $sourceHash \u003d [System.BitConverter]::ToString($sha256.ComputeHash($fileStream), 0).Replace(\u0027-\u0027, \u0027\u0027).ToLowerInvariant()\",\"        $sha256.Dispose()\",\"        $fileStream.Dispose()\",\"\",\"        if ($sourceHash -ne $fileHash) {\",\"            return $false\",\"        }\",\"        else {\",\"            return $true\",\"        }\",\"    }\",\"    else {\",\"        return $false\",\"    }\",\"}\",\"\",\"function CheckPowerShellModuleInstallation ([bool]$suppressError) {\",\"    $isInstalled \u003d $false\",\"    # Path does not exist meaning it has never been downloaded.\",\"    if (Test-Path($psModuleInstallLocation)) {\",\"        # Check if the expected number of files and directories are in the folder\",\"        if (((Get-ChildItem $psModuleInstallLocation -Directory | Measure-Object | %{$_.Count}) -eq 0) -and\",\"            ((Get-ChildItem $psModuleInstallLocation -File | Measure-Object | %{$_.Count}) -eq $psModuleHashes.Count)) {\",\"            $validFileHashes \u003d $true\",\"\",\"            # Check each file for their expected file hash.\",\"            Get-ChildItem $psModuleInstallLocation -File | ForEach-Object {\",\"                if ($psModuleHashes.ContainsKey($_.Name)) {\",\"                    $installFile \u003d [IO.Path]::Combine($psModuleInstallLocation, $_.Name)\",\"                    if (-Not (CheckFileHash $installFile $psModuleHashes[$_.Name])) {\",\"                        if (-Not $suppressError) {\",\"                            Write-Error (\u0027The SHA hash of the {0} file does not match the expected value.\u0027 -f $_.Name)\",\"                        }\",\"                        $validFileHashes \u003d $false\",\"                    }\",\"                } else {\",\"                    if (-Not $suppressError) {\",\"                        Write-Error (\u0027The PowerShellModule installation folder contains an unexpected file with name {0}.\u0027 -f $_.Name)\",\"                    }\",\"                    $validFileHashes \u003d $false\",\"                }\",\"            }\",\"            $isInstalled \u003d $validFileHashes\",\"        } else {\",\"            if (-Not $suppressError) {\",\"                Write-Error (\u0027An incorrect number of files were present in the PowerShellModule installation folder. The contents will be deleted.\u0027)\",\"            }\",\"        }\",\"        if (-Not $isInstalled) {\",\"            # Remove all files and folders as the folder contains potentially malicious software.\",\"            Remove-Item $psModuleInstallLocation -Recurse\",\"        }\",\"    }\",\"\",\"    return $isInstalled\",\"}\",\"\",\"function ExtractZipCoreOs ([string]$zipFilePath, [string]$destPath) {\",\"    try {\",\"        [System.Reflection.Assembly]::LoadWithPartialName(\u0027System.IO.Compression.FileSystem\u0027) | Out-Null\",\"        $zip \u003d [System.IO.Compression.ZipFile]::OpenRead($zipFilePath)\",\"        foreach ($item in $zip.Entries) {\",\"            $extractedPath \u003d Join-Path $destPath $item.FullName\",\"\",\"            if ($item.Length -eq 0) {\",\"                if ((Test-Path $extractedPath) -eq 0) {\",\"                    mkdir $extractedPath | Out-Null\",\"                }\",\"            } else {\",\"                $fileParent \u003d Split-Path $extractedPath\",\"\",\"                if ((Test-Path $fileParent) -eq 0) {\",\"                    mkdir $fileParent | Out-Null\",\"                }\",\"\",\"                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($item, $extractedPath, $true)\",\"            }\",\"        }\",\"    } catch {\",\"        throw \u0027Error encountered when extracting patch management zip file.`n$($_.Exception.Message)\u0027\",\"    } finally {\",\"        $zip.Dispose()\",\"    }\",\"}\",\"\",\"# Hash of bucket digest\",\"function Get-HashString([String]$InString) {\",\"  $StringBuilder \u003d New-Object System.Text.StringBuilder\",\"  [System.Security.Cryptography.HashAlgorithm]::Create(\\\"SHA256\\\").ComputeHash([System.Text.Encoding]::UTF8.GetBytes($InString)) | ForEach-Object {\",\"    [Void]$StringBuilder.Append($_.ToString(\\\"x2\\\"))\",\"  }\",\"  return $StringBuilder.ToString()\",\"}\",\"\",\"function InstallPowerShellModule {\",\"    if (-Not (CheckPowerShellModuleInstallation $true)) {\",\"        Write-Output (\\\"Preparing to download {0} PowerShell module from S3.`r`n\\\" -f $appName)\",\"\",\"        #Setup the directories if they do not exist.\",\"        if (-Not (Test-Path($psModuleInstallLocation))) {\",\"            $noOp \u003d New-Item $psModuleInstallLocation -ItemType Directory\",\"        }\",\"\",\"        if (-Not (Test-Path($tempDirectory))) {\",\"            $noOp \u003d New-Item $tempDirectory -ItemType Directory\",\"        }\",\"        $region \u003d $env:AWS_SSM_REGION_NAME\",\"        if ($region -eq \u0027us-east-1\u0027) {\",\"            $s3Location \u003d $s3LocationUsEast -f $region\",\"        } elseif (($region -eq \u0027cn-north-1\u0027) -or ($region -eq \u0027cn-northwest-1\u0027)) {\",\"            $s3Location \u003d $s3LocationCn -f $region\",\"        } elseif ($region -in $oldRegion) {\",\"            $s3Location \u003d $s3LocationRegular -f $region\",\"        } elseif ($region -in $regionsWithBucketNameAlg1) {\",\"            $suffix \u003d -join(\\\"prod-\\\", $region, \\\"-internal-patch-public-bucket\\\")\",\"            $digest \u003d Get-HashString $suffix\",\"            $s3Location \u003d $s3LocationNewRegion -f $region, $digest.subString(0,9)\",\"        } else {\",\"            $suffix \u003d -join(\\\"prod-\\\", $region + $region, \\\"-internal-patch-public-bucket\\\")\",\"            $digest \u003d Get-HashString $suffix\",\"            $s3Location \u003d $s3LocationNewRegion -f $region, $digest.subString(0,9)\",\"        }\",\"\",\"        Write-Output (\\\"Downloading {0} PowerShell module from {1} to {2}.`r`n\\\" -f $appName, $s3Location, $downloadPath)\",\"\",\"        # Add Tls 1.2 support.\",\"        [Net.ServicePointManager]::SecurityProtocol \u003d [Net.ServicePointManager]::SecurityProtocol -bOr [Net.SecurityProtocolType]::Tls12\",\"\",\"        (New-Object Net.WebClient).DownloadFile($s3Location, $downloadPath)\",\"\",\"        if (CheckFileHash $downloadPath $s3FileHash ) {\",\"            Write-Output (\\\"Extracting {0} zip file contents to temporary folder.`r`n\\\" -f $appName)\",\"            try {\",\"               (New-Object -Com Shell.Application).namespace($psModuleInstallLocation).CopyHere((New-Object -Com Shell.Application).namespace($downloadPath).Items(), 16)\",\"            } catch [Exception] {\",\"                ExtractZipCoreOs $downloadPath $psModuleInstallLocation\",\"            }\",\"        }\",\"        else {\",\"            throw (\u0027The SHA hash of the {0} S3 source file does not match the expected value.\u0027 -f $appName)\",\"        }\",\"\",\"        Write-Output (\\\"Verifying SHA 256 of the {0} PowerShell module files.`r`n\\\" -f $appName)\",\"        if (-Not (CheckPowerShellModuleInstallation $false)) {\",\"            throw (\u0027The verification of the {0} PowerShell module did not pass.\u0027 -f $appName)\",\"        }\",\"        Write-Output (\\\"Successfully downloaded and installed the {0} PowerShell module.`r`n\\\" -f $appName)\",\"    }\",\"}\",\"\",\"try {\",\"    InstallPowerShellModule\",\"} catch [Exception] {\",\"    $msg \u003d \\\"An error occurred when executing {0}: {1}`r`n\\\" -f $appName, $_.Exception.Message\",\"    Write-Error $msg\",\"    exit -1\",\"}\",\"finally {\",\"    if (Test-Path $downloadPath) {\",\"        rm $downloadPath\",\"    }\",\"}\",\"\",\"#setup the command\",\"import-module $psmoduleinstallfile\",\"$response \u003d Invoke-PatchBaselineOperation -Operation {{Operation}} -SnapshotId \u0027{{SnapshotId}}\u0027 -InstallOverrideList \u0027{{InstallOverrideList}}\u0027 -BaselineOverride \u0027{{BaselineOverride}}\u0027 -AssociationId \u0027{{AssociationId}}\u0027 -RebootOption \u0027{{RebootOption}}\u0027 -InstanceId $env:AWS_SSM_INSTANCE_ID -Region $env:AWS_SSM_REGION_NAME\",\"\",\"if ($response.exitcode -ne 3010)\",\"{\",\"    $response.tostring()\",\"}\",\"\",\"exit $response.exitcode\"]},\"name\":\"PatchWindows\",\"action\":\"aws:runPowerShellScript\",\"precondition\":{\"StringEquals\":[\"platformType\",\"Windows\"]}},{\"inputs\":{\"timeoutSeconds\":7200,\"runCommand\":[\"#!/bin/bash\",\"PYTHON_CMD\u003d\u0027\u0027\",\"\",\"check_binary() {\",\"    HAS_VAR_NAME\u003dHAS_$2\",\"    CMD_VAR_NAME\u003d$2_CMD\",\"    if [ \\\"$(eval echo \\\\${${HAS_VAR_NAME}})\\\" \u003d \\\"0\\\" ]; then return; fi\",\"    which $1 2\u003e/dev/null\",\"    RET_CODE\u003d$?\",\"    eval \\\"${HAS_VAR_NAME}\u003d${RET_CODE}\\\"\",\"    if [ ${RET_CODE} -eq 0 ]; then eval \\\"${CMD_VAR_NAME}\u003d$1\\\"; fi\",\"}\",\"\",\"check_binary python3 PYTHON3\",\"check_binary python2.6 PYTHON2_6\",\"check_binary python26 PYTHON26\",\"check_binary python2.7 PYTHON2_7\",\"check_binary python27 PYTHON27\",\"check_binary python2 PYTHON2\",\"\",\"which python 2\u003e/dev/null\",\"if [ $? -eq 0 ]; then\",\"  PYTHON_VERSION\u003d$(python --version 2\u003e\u00261 | grep -Po \u0027(?\u003c\u003dPython )[\\\\d]\u0027)\",\"  eval \\\"HAS_PYTHON${PYTHON_VERSION}\u003d0\\\"\",\"  eval \\\"PYTHON${PYTHON_VERSION}_CMD\u003d\u0027python\u0027\\\"\",\"fi\",\"\",\"check_binary apt-get APT\",\"check_binary yum YUM\",\"check_binary dnf DNF\",\"check_binary zypper ZYPP\",\"\",\"check_install_code() {\",\"    if [ $1 -ne 0 ]\",\"    then\",\"        echo \\\"WARNING: Could not install the $2, this may cause the patching operation to fail.\\\" \u003e\u00262\",\"    fi\",\"}\",\"\",\"get_env_var_hash_key() {\",\"    # Get an environment variable that is a dictionary and retrieve the provided key.\",\"    # $1 is the environment variable.\",\"    # $2 is the dictionary key.\",\"    # $3 is the python version \u0026 command found on instance.\",\"    result\u003d$(echo -e \\\"import json\\\
import os\\\
print(json.loads(os.environ[\\\\\\\"$1\\\\\\\"])[\\\\\\\"$2\\\\\\\"])\\\" | $3)\",\"    if [ -z \\\"$result\\\" ]\",\"    then\",\"        exit 1\",\"    fi\",\"    echo $result\",\"}\",\"\",\"CANDIDATES\u003d( $HAS_PYTHON2_6 $HAS_PYTHON26 $HAS_PYTHON2_7 $HAS_PYTHON27 $HAS_PYTHON2 )\",\"HAS_ANY_PYTHON2\u003d1\",\"for CANDIDATE in \\\"${CANDIDATES[@]}\\\"\",\"do\",\"    if [ $CANDIDATE -eq 0 ]\",\"    then\",\"        HAS_ANY_PYTHON2\u003d0\",\"    fi\",\"done\",\"\",\"check_instance_is_debian_8() {\",\"    if [ -f /etc/os-release ] \u0026\u0026 grep \\\"ID\u003ddebian\\\" /etc/os-release \u003e/dev/null; then\",\"        IS_DEBIAN\u003dtrue\",\"        if grep \u0027VERSION_ID\u003d\\\"8\\\"\u0027 /etc/os-release \u003e/dev/null; then\",\"            IS_DEBIAN_8\u003dtrue\",\"        fi\",\"    fi\",\"}\",\"check_if_debian_signing_key_exist() {\",\"    MISSING_KEY\u003d0\",\"    if [ \\\"$HAS_APT_KEY\\\" \u003d \\\"0\\\" ] \u0026\u0026 (apt-key list | grep -w 8AE22BA9) \u003e /dev/null; then\",\"      MISSING_KEY\u003d1\",\"    fi\",\"}\",\"prepare_instance_if_debian_8() {\",\"    KEY_IMPORTED\u003d0\",\"    COMMENTED_OUT_BACKPORTS\u003d0\",\"    check_instance_is_debian_8\",\"    if [ ! -z $IS_DEBIAN ] \u0026\u0026 [ ! -z $IS_DEBIAN_8 ]; then\",\"        HAS_APT_KEY\u003d1\",\"        check_binary apt-key APT_KEY\",\"        check_if_debian_signing_key_exist\",\"        if [ \\\"$HAS_APT_KEY\\\" \u003d \\\"0\\\" ]; then\",\"            if [ \\\"$MISSING_KEY\\\" \u003d \\\"0\\\" ]; then\",\"                apt-key adv --keyserver keyserver.ubuntu.com --recv-keys AA8E81B4331F7F50 \u003e/dev/null 2\u003e\u00261\",\"                KEY_IMPORTED\u003d1\",\"                echo \\\"Imported missing signing key: AA8E81B4331F7F50\\\"\",\"            else\",\"                echo \\\"Skip to synchronize pakcage index for DEBIAN 8 instance. \\\"\",\"            fi\",\"        else\",\"            echo \\\"Could not locate apt-key.\\\"\",\"        fi\",\"        if [ -f /etc/apt/sources.list.d/backports.list ]; then\",\"            if grep -i \\\"^#[[:space:]]*deb http://cloudfront.debian.net/debian jessie-backports main\\\" /etc/apt/sources.list.d/backports.list \u003e/dev/null;then\",\"                echo \\\"Already commented out jessie backports\\\"\",\"            else\",\"                sed -e \\\"/jessie-backports main/ s/^#*/#/\\\" -i /etc/apt/sources.list.d/backports.list\",\"                COMMENTED_OUT_BACKPORTS\u003d1\",\"            fi\",\"        fi\",\"        echo \\\"Synchronizing pakcage index for DEBIAN 8 instance\\\"\",\"        apt-get update \u003e/dev/null\",\"    fi\",\"}\",\"\",\"clean_up_instances_if_debian_8() {\",\"    if [ \\\"$KEY_IMPORTED\\\" \u003d \\\"1\\\" ]; then\",\"        apt-key del 8AE22BA9 \u003e /dev/null\",\"    fi\",\"    if [ \\\"$COMMENTED_OUT_BACKPORTS\\\" \u003d \\\"1\\\" ]; then\",\"        sudo sed -e \u0027/jessie-backports main/ s/^#//g\u0027 -i /etc/apt/sources.list.d/backports.list\",\"    fi\",\"}\",\"\",\"if [ $HAS_APT -eq 0 -a $HAS_PYTHON3 -eq 0 ]\",\"then\",\"    PYTHON_CMD\u003d${PYTHON3_CMD}\",\"    prepare_instance_if_debian_8\",\"    apt-get install python3-apt -y\",\"    check_install_code $? \\\"python3-apt\\\"\",\"\",\"elif  [ $HAS_DNF -eq 0 ] \u0026\u0026 [ $HAS_PYTHON2 -eq 0 -o $HAS_PYTHON3 -eq 0 ]\",\"then\",\"    if [ $HAS_PYTHON2 -eq 0 ]\",\"    then\",\"        PYTHON_CMD\u003d${PYTHON2_CMD}\",\"    elif [ $HAS_PYTHON3 -eq 0 ]\",\"    then\",\"        PYTHON_CMD\u003d${PYTHON3_CMD}\",\"    fi\",\"\",\"elif [ $HAS_YUM -eq 0 -a $HAS_ANY_PYTHON2 -eq 0 ]\",\"then\",\"\",\"    HAS_COMPATIBLE_YUM\u003dfalse\",\"\",\"    INSTALLED_PYTHON\u003d( $PYTHON2_7_CMD $PYTHON27_CMD $PYTHON2_CMD $PYTHON2_6_CMD $PYTHON26_CMD  )\",\"    for TEST_PYTHON_CMD in \\\"${INSTALLED_PYTHON[@]}\\\"\",\"    do\",\"        ${TEST_PYTHON_CMD} -c \\\"import yum\\\" 2\u003e/dev/null\",\"        if [ $? -ne 0 ]; then\",\"            echo \\\"Unable to import yum module on $TEST_PYTHON_CMD\\\"\",\"        else\",\"            PYTHON_CMD\u003d${TEST_PYTHON_CMD}\",\"            HAS_COMPATIBLE_YUM\u003dtrue\",\"            break\",\"        fi\",\"    done\",\"    if ! $HAS_COMPATIBLE_YUM; then\",\"        echo \\\"Unable to import yum module, please check version compatibility between Yum and Python\\\"\",\"        exit 1\",\"    else\",\"        YUM_VERSION\u003d$(yum --version 2\u003e/dev/null | sed -n 1p)\",\"        echo \\\"Using Yum version: $YUM_VERSION\\\"\",\"    fi\",\"\",\"elif [ $HAS_ZYPP -eq 0 -a $HAS_PYTHON3 -eq 0 ]\",\"then\",\"    PYTHON_CMD\u003d${PYTHON3_CMD}\",\"elif [ $HAS_ZYPP -eq 0 -a $HAS_PYTHON2 -eq 0 ]\",\"then\",\"    PYTHON_CMD\u003d${PYTHON2_CMD}\",\"else\",\"    echo \\\"An unsupported package manager and python version combination was found.\\\"\",\"    if [ $HAS_DNF -eq 0 ]\",\"    then\",\"        echo \\\"Dnf requires Python2 or Python3 to be installed.\\\"\",\"    elif [ $HAS_YUM -eq 0 ]\",\"    then\",\"        echo \\\"Yum requires Python2 to be installed.\\\"\",\"    elif [ $HAS_APT -eq 0 ]\",\"    then\",\"        echo \\\"Apt requires Python3 to be installed.\\\"\",\"    elif [ $HAS_ZYPP -eq 0 ]\",\"    then\",\"        echo \\\"ZYpp requires Python2 or Python3 to be installed.\\\"\",\"    fi\",\"    echo \\\"Python3\u003d$HAS_PYTHON3, Python2\u003d$HAS_ANY_PYTHON2, Yum\u003d$HAS_YUM, Apt\u003d$HAS_APT, Zypper\u003d$HAS_ZYPP, Dnf\u003d$HAS_DNF\\\"\",\"    echo \\\"Exiting...\\\"\",\"    exit 1\",\"fi\",\"\",\"echo \\\"Using python binary: \u0027${PYTHON_CMD}\u0027\\\"\",\"PYTHON_VERSION\u003d$(${PYTHON_CMD} --version  2\u003e\u00261)\",\"echo \\\"Using Python Version: $PYTHON_VERSION\\\"\",\"\",\"echo \u0027\",\"import errno\",\"import hashlib\",\"import json\",\"import logging\",\"import os\",\"import shutil\",\"import subprocess\",\"import tarfile\",\"import sys\",\"\",\"tmp_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations/\\\")\",\"reboot_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-194/\\\")\",\"reboot_with_failure_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-195/\\\")\",\"reboot_with_dependency_failure_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-196/\\\")\",\"\",\"# initialize logging\",\"LOGGER_FORMAT \u003d \\\"%(asctime)s %(name)s [%(levelname)s]: %(message)s\\\"\",\"LOGGER_DATEFORMAT \u003d \\\"%m/%d/%Y %X\\\"\",\"LOGGER_LEVEL \u003d logging.INFO\",\"LOGGER_STREAM \u003d sys.stdout\",\"\",\"logging.basicConfig(format\u003dLOGGER_FORMAT, datefmt\u003dLOGGER_DATEFORMAT, level\u003dLOGGER_LEVEL, stream\u003dLOGGER_STREAM)\",\"logger \u003d logging.getLogger()\",\"\",\"ERROR_CODE_MAP \u003d {\",\"    151: \\\"%s sha256 check failed, should be %s, but is %s\\\",\",\"    152: \\\"Unable to load and extract the content of payload, abort.\\\",\",\"    154: \\\"Unable to create dir: %s\\\",\",\"    155: \\\"Unable to extract tar file: %s.\\\",\",\"    156: \\\"Unable to download payload: %s.\\\"\",\"}\",\"\",\"OLD_BUCKET_REGIONS \u003d [\\\"ap-east-1\\\", \\\"us-gov-east-1\\\", \\\"us-gov-west-1\\\", \\\"cn-northwest-1\\\", \\\"cn-north-1\\\", \\\"ca-central-1\\\",\",\"             \\\"ap-southeast-2\\\", \\\"ap-southeast-1\\\", \\\"us-west-1\\\", \\\"us-west-2\\\", \\\"ap-northeast-1\\\", \\\"eu-west-2\\\", \\\"ap-northeast-2\\\",\",\"             \\\"us-east-1\\\", \\\"sa-east-1\\\", \\\"eu-central-1\\\", \\\"eu-west-1\\\", \\\"us-east-2\\\", \\\"eu-west-3\\\", \\\"ap-south-1\\\", \\\"eu-north-1\\\"]\",\"REGIONS_WITH_BUCKET_NAME_ALG_1 \u003d [\\\"us-iso-west-1\\\", \\\"us-iso-east-1\\\", \\\"me-south-1\\\", \\\"us-isob-east-1\\\", \\\"eu-south-1\\\", \\\"af-south-1\\\",\",\"              \\\"ap-southeast-3\\\", \\\"ap-northeast-3\\\"]\",\"# When an install occurs and the instance needs a reboot, the agent restarts our plugin.\",\"# Check if these folders exist to know how to succeed or fail a command after a reboot.\",\"# DO NOT remove these files here. They are cleaned in the common startup.\",\"if os.path.exists(reboot_dir) or os.path.exists(reboot_with_failure_dir) or os.path.exists(reboot_with_dependency_failure_dir):\",\"    # Reload Payload so that we remove reboot directories\",\"    if os.path.exists(tmp_dir):\",\"        shutil.rmtree(tmp_dir)\",\"\",\"def create_dir(dirpath):\",\"    dirpath \u003d os.path.abspath(dirpath)\",\"    if not os.path.exists(dirpath):\",\"        try:\",\"            os.makedirs(dirpath)\",\"        except OSError as e:  # Guard against race condition\",\"            if e.errno !\u003d errno.EEXIST:\",\"                raise e\",\"        except Exception as e:\",\"            logger.error(\\\"Unable to create dir: %s\\\", dirpath)\",\"            logger.exception(e)\",\"            abort(154, (dirpath))\",\"\",\"def use_curl():\",\"    output, has_curl \u003d shell_command([\\\"which\\\", \\\"curl\\\"])\",\"    if has_curl \u003d\u003d 0:\",\"        return True\",\"    else:\",\"        return False\",\"\",\"def download_to(url, file_path):\",\"    curl_present \u003d use_curl()\",\"    logger.info(\\\"Downloading payload from %s\\\", url)\",\"    if curl_present:\",\"        output, curl_return \u003d shell_command([\\\"curl\\\", \\\"-f\\\", \\\"-o\\\", file_path, url])\",\"    else:\",\"        output, curl_return \u003d shell_command([\\\"wget\\\", \\\"-O\\\", file_path, url])\",\"\",\"    if curl_return !\u003d 0:\",\"        download_agent \u003d \\\"curl\\\" if curl_present else \\\"wget\\\"\",\"        logger.error(\\\"Error code returned from %s is %d\\\", download_agent, curl_return)\",\"        abort(156, (url))\",\"\",\"def download(url):\",\"    if use_curl():\",\"        url_contents, curl_return \u003d shell_command([\\\"curl\\\", url])\",\"    else:\",\"        url_contents, curl_return \u003d shell_command([\\\"wget\\\", \\\"-O-\\\", url])\",\"    if curl_return \u003d\u003d 0:\",\"        return url_contents\",\"    else:\",\"        raise Exception(\\\"Could not curl %s\\\" % url)\",\"\",\"def extract_tar(path):\",\"    path \u003d os.path.abspath(path)\",\"    try:\",\"        f \u003d tarfile.open(path, \\\"r|gz\\\")\",\"        f.extractall()\",\"    except Exception as e:\",\"        logger.error(\\\"Unable to extract tar file: %s.\\\", path)\",\"        logger.exception(e)\",\"        abort(155, (path))\",\"    finally:\",\"        f.close()\",\"\",\"def shell_command(cmd_list):\",\"    with open(os.devnull, \\\"w\\\") as devnull:\",\"        p \u003d subprocess.Popen(cmd_list, stdout\u003dsubprocess.PIPE, stderr\u003ddevnull)\",\"        (std_out, _) \u003d p.communicate()\",\"        if not type(std_out) \u003d\u003d str:\",\"            std_out \u003d std_out.decode(\\\"utf-8\\\")\",\"        return (std_out, p.returncode)\",\"\",\"def abort(error_code, params \u003d ()):\",\"    if os.path.exists(tmp_dir):\",\"        shutil.rmtree(tmp_dir)\",\"    sys.stderr.write(ERROR_CODE_MAP.get(error_code) % params)\",\"    sys.exit(error_code)\",\"\",\"def sha256_checksum(filename):\",\"    sha256_hash \u003d hashlib.sha256()\",\"    with open(filename,\\\"rb\\\") as f:\",\"        # Read and update hash string value in blocks of 4K\",\"        for byte_block in iter(lambda: f.read(4096),b\\\"\\\"):\",\"            sha256_hash.update(byte_block)\",\"        return sha256_hash.hexdigest().upper()\",\"\",\"# cd into the temp directory\",\"create_dir(tmp_dir)\",\"os.chdir(tmp_dir)\",\"\",\"region \u003d os.environ[\\\"AWS_SSM_REGION_NAME\\\"]\",\"\",\"# main logic\",\"# Old bucket location\",\"s3_bucket \u003d \\\"aws-ssm-%s\\\"%(region)\",\"s3_prefix \u003d \\\"patchbaselineoperations/linux/payloads\\\"\",\"payload_name \u003d \\\"patch-baseline-operations-1.104.tar.gz\\\"\",\"payload_sha256 \u003d \\\"8CE0CAF78CC4E65ED206350DBA5CFD9C8AFAD01D3CBD2AC7107D265A5FFB8104\\\"\",\"\",\"# New bucket location\",\"if region not in OLD_BUCKET_REGIONS:\",\"    digest \u003d hashlib.sha256((\\\"-\\\".join([\\\"prod\\\", region, \\\"internal-patch-public-bucket\\\"])).encode(\\\"utf8\\\")).hexdigest()[0:9]\",\"    if region not in REGIONS_WITH_BUCKET_NAME_ALG_1  :\",\"        digest \u003d hashlib.sha256((\\\"-\\\".join([\\\"prod\\\", region + region, \\\"internal-patch-public-bucket\\\"])).encode(\\\"utf8\\\")).hexdigest()[0:9]\",\"    s3_bucket \u003d \\\"aws-patch-manager-%s-%s\\\"%(region, digest)\",\"\",\"# download payload file and do signature verification\",\"region_to_interpolate \u003d region\",\"if region.startswith(\\\"cn-\\\"):\",\"    url_template \u003d \\\"https://s3.%s.amazonaws.com.cn/%s/%s\\\"\",\"elif region.startswith(\\\"us-gov-\\\"):\",\"    url_template \u003d \\\"https://s3-fips-%s.amazonaws.com/%s/%s\\\"\",\"elif region \u003d\u003d \\\"us-isob-east-1\\\":\",\"    url_template \u003d \\\"https://s3.%s.sc2s.sgov.gov/%s/%s\\\"\",\"elif region.startswith(\\\"us-iso-\\\"):\",\"    url_template \u003d \\\"https://s3.%s.c2s.ic.gov/%s/%s\\\"\",\"else:\",\"    url_template \u003d \\\"https://s3.dualstack.%s.amazonaws.com/%s/%s\\\"\",\"\",\"download_to(url_template % (region_to_interpolate, s3_bucket, os.path.join(s3_prefix, payload_name)), payload_name)\",\"\",\"# payloads are the actual files to be used for linux patching\",\"payloads \u003d []\",\"try:\",\"    sha256_code \u003d sha256_checksum(payload_name)\",\"    if not sha256_code \u003d\u003d payload_sha256:\",\"        error_msg \u003d \\\"%s sha256 check failed, should be %s, but is %s\\\" % (payload_name, payload_sha256, sha256_code)\",\"        logger.error(error_msg)\",\"        abort(151, (payload_name, payload_sha256, sha256_code))\",\"    extract_tar(payload_name)\",\"    # Change owner \u0026 group to be root user for the payload.\",\"    shell_command([\\\"chown\\\", \\\"-R\\\", \\\"0:0\\\", tmp_dir])\",\"except Exception as e:\",\"    error_msg \u003d \\\"Unable to load and extract the content of payload, abort.\\\"\",\"    logger.error(error_msg)\",\"    logger.exception(e)\",\"    abort(152)\",\"\",\"\",\"# Document parameters.\",\"import sys\",\"try:\",\"    import common_startup_entrance\",\"    common_startup_entrance.execute(\\\"os_selector\\\", \\\"PatchLinux\\\", \\\"{{SnapshotId}}\\\",\\\\\",\"            \\\"{{Operation}}\\\", \\\"{{InstallOverrideList}}\\\", \\\\\",\"            \\\"{{RebootOption}}\\\", \\\"{{BaselineOverride}}\\\", \\\"{{AssociationId}}\\\")\",\"except Exception as e:\",\"    error_code \u003d 156\",\"    if hasattr(e, \\\"error_code\\\") and type(e.error_code) \u003d\u003d int:\",\"        error_code \u003d e.error_code;\",\"    logger.exception(e)\",\"    sys.exit(error_code)\",\"    \",\"\",\"\u0027 | $PYTHON_CMD\",\"\",\"RETURN_CODE\u003d$?\",\"\",\"clean_up_instances_if_debian_8\",\"\",\"exit $RETURN_CODE\"]},\"name\":\"PatchLinux\",\"action\":\"aws:runShellScript\",\"precondition\":{\"StringEquals\":[\"platformType\",\"Linux\"]}},{\"inputs\":{\"timeoutSeconds\":7200,\"runCommand\":[\"#!/bin/bash\",\"PYTHON_CMD\u003d\u0027\u0027\",\"\",\"check_binary() {\",\"    HAS_VAR_NAME\u003dHAS_$2\",\"    CMD_VAR_NAME\u003d$2_CMD\",\"    if [ \\\"$(eval echo \\\\${${HAS_VAR_NAME}})\\\" \u003d \\\"0\\\" ]; then return; fi\",\"    which $1 2\u003e/dev/null\",\"    RET_CODE\u003d$?\",\"    eval \\\"${HAS_VAR_NAME}\u003d${RET_CODE}\\\"\",\"    if [ ${RET_CODE} -eq 0 ]; then eval \\\"${CMD_VAR_NAME}\u003d$1\\\"; fi\",\"}\",\"\",\"check_binary python3 PYTHON3\",\"check_binary python2.6 PYTHON2_6\",\"check_binary python26 PYTHON26\",\"check_binary python2.7 PYTHON2_7\",\"check_binary python27 PYTHON27\",\"check_binary python2 PYTHON2\",\"\",\"which python 2\u003e/dev/null\",\"if [ $? -eq 0 ]; then\",\"  PYTHON_VERSION\u003d$(python --version 2\u003e\u00261 | perl -lne \u0027print $\u0026 if /(?\u003c\u003dPython )[\\\\\\\\d]/\u0027)\",\"  eval \\\"HAS_PYTHON${PYTHON_VERSION}\u003d0\\\"\",\"  eval \\\"PYTHON${PYTHON_VERSION}_CMD\u003d\u0027python\u0027\\\"\",\"fi\",\"\",\"check_install_code() {\",\"    if [ $1 -ne 0 ]\",\"    then\",\"        echo \\\"WARNING: Could not install the $2, this may cause the patching operation to fail.\\\" \u003e\u00262\",\"    fi\",\"}\",\"\",\"get_env_var_hash_key() {\",\"    # Get an environment variable that is a dictionary and retrieve the provided key.\",\"    # $1 is the environment variable.\",\"    # $2 is the dictionary key.\",\"    # $3 is the python version \u0026 command found on instance.\",\"    result\u003d$(echo -e \\\"import json\\\
import os\\\
print(json.loads(os.environ[\\\\\\\"$1\\\\\\\"])[\\\\\\\"$2\\\\\\\"])\\\" | $3)\",\"    if [ -z \\\"$result\\\" ]\",\"    then\",\"        exit 1\",\"    fi\",\"    echo $result\",\"}\",\"\",\"CANDIDATES\u003d( $HAS_PYTHON2_6 $HAS_PYTHON26 $HAS_PYTHON2_7 $HAS_PYTHON27 $HAS_PYTHON2 )\",\"HAS_ANY_PYTHON2\u003d1\",\"for CANDIDATE in \\\"${CANDIDATES[@]}\\\"\",\"do\",\"    if [ $CANDIDATE -eq 0 ]\",\"    then\",\"        HAS_ANY_PYTHON2\u003d0\",\"    fi\",\"done\",\"\",\"echo \\\"Using python binary: \u0027${PYTHON_CMD}\u0027\\\"\",\"PYTHON_VERSION\u003d$(${PYTHON_CMD} --version  2\u003e\u00261)\",\"echo \\\"Using Python Version: $PYTHON_VERSION\\\"\",\"\",\"echo \u0027\",\"import errno\",\"import hashlib\",\"import json\",\"import logging\",\"import os\",\"import shutil\",\"import subprocess\",\"import tarfile\",\"import sys\",\"\",\"tmp_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations/\\\")\",\"reboot_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-194/\\\")\",\"reboot_with_failure_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-195/\\\")\",\"reboot_with_dependency_failure_dir \u003d os.path.abspath(\\\"/var/log/amazon/ssm/patch-baseline-operations-reboot-196/\\\")\",\"\",\"# initialize logging\",\"LOGGER_FORMAT \u003d \\\"%(asctime)s %(name)s [%(levelname)s]: %(message)s\\\"\",\"LOGGER_DATEFORMAT \u003d \\\"%m/%d/%Y %X\\\"\",\"LOGGER_LEVEL \u003d logging.INFO\",\"LOGGER_STREAM \u003d sys.stdout\",\"\",\"logging.basicConfig(format\u003dLOGGER_FORMAT, datefmt\u003dLOGGER_DATEFORMAT, level\u003dLOGGER_LEVEL, stream\u003dLOGGER_STREAM)\",\"logger \u003d logging.getLogger()\",\"\",\"ERROR_CODE_MAP \u003d {\",\"    151: \\\"%s sha256 check failed, should be %s, but is %s\\\",\",\"    152: \\\"Unable to load and extract the content of payload, abort.\\\",\",\"    154: \\\"Unable to create dir: %s\\\",\",\"    155: \\\"Unable to extract tar file: %s.\\\",\",\"    156: \\\"Unable to download payload: %s.\\\"\",\"}\",\"\",\"# When an install occurs and the instance needs a reboot, the agent restarts our plugin.\",\"# Check if these folders exist to know how to succeed or fail a command after a reboot.\",\"# DO NOT remove these files here. They are cleaned in the common startup.\",\"if os.path.exists(reboot_dir) or os.path.exists(reboot_with_failure_dir) or os.path.exists(reboot_with_dependency_failure_dir):\",\"    # Reload Payload so that we remove reboot directories\",\"    if os.path.exists(tmp_dir):\",\"        shutil.rmtree(tmp_dir)\",\"\",\"def create_dir(dirpath):\",\"    dirpath \u003d os.path.abspath(dirpath)\",\"    if not os.path.exists(dirpath):\",\"        try:\",\"            os.makedirs(dirpath)\",\"        except OSError as e:  # Guard against race condition\",\"            if e.errno !\u003d errno.EEXIST:\",\"                raise e\",\"        except Exception as e:\",\"            logger.error(\\\"Unable to create dir: %s\\\", dirpath)\",\"            logger.exception(e)\",\"            abort(154, (dirpath))\",\"\",\"def use_curl():\",\"    output, has_curl \u003d shell_command([\\\"which\\\", \\\"curl\\\"])\",\"    if has_curl \u003d\u003d 0:\",\"        return True\",\"    else:\",\"        return False\",\"\",\"def download_to(url, file_path):\",\"    curl_present \u003d use_curl()\",\"    logger.info(\\\"Downloading payload from %s\\\", url)\",\"    if curl_present:\",\"        output, curl_return \u003d shell_command([\\\"curl\\\", \\\"-f\\\", \\\"-o\\\", file_path, url])\",\"    else:\",\"        output, curl_return \u003d shell_command([\\\"wget\\\", \\\"-O\\\", file_path, url])\",\"\",\"    if curl_return !\u003d 0:\",\"        download_agent \u003d \\\"curl\\\" if curl_present else \\\"wget\\\"\",\"        logger.error(\\\"Error code returned from %s is %d\\\", download_agent, curl_return)\",\"        abort(156, (url))\",\"\",\"def download(url):\",\"    if use_curl():\",\"        url_contents, curl_return \u003d shell_command([\\\"curl\\\", url])\",\"    else:\",\"        url_contents, curl_return \u003d shell_command([\\\"wget\\\", \\\"-O-\\\", url])\",\"    if curl_return \u003d\u003d 0:\",\"        return url_contents\",\"    else:\",\"        raise Exception(\\\"Could not curl %s\\\" % url)\",\"\",\"def extract_tar(path):\",\"    path \u003d os.path.abspath(path)\",\"    try:\",\"        f \u003d tarfile.open(path, \\\"r|gz\\\")\",\"        f.extractall()\",\"    except Exception as e:\",\"        logger.error(\\\"Unable to extract tar file: %s.\\\", path)\",\"        logger.exception(e)\",\"        abort(155, (path))\",\"    finally:\",\"        f.close()\",\"\",\"def shell_command(cmd_list):\",\"    with open(os.devnull, \\\"w\\\") as devnull:\",\"        p \u003d subprocess.Popen(cmd_list, stdout\u003dsubprocess.PIPE, stderr\u003ddevnull)\",\"        (std_out, _) \u003d p.communicate()\",\"        if not type(std_out) \u003d\u003d str:\",\"            std_out \u003d std_out.decode(\\\"utf-8\\\")\",\"        return (std_out, p.returncode)\",\"\",\"def abort(error_code, params \u003d ()):\",\"    if os.path.exists(tmp_dir):\",\"        shutil.rmtree(tmp_dir)\",\"    sys.stderr.write(ERROR_CODE_MAP.get(error_code) % params)\",\"    sys.exit(error_code)\",\"\",\"def sha256_checksum(filename):\",\"    sha256_hash \u003d hashlib.sha256()\",\"    with open(filename,\\\"rb\\\") as f:\",\"        # Read and update hash string value in blocks of 4K\",\"        for byte_block in iter(lambda: f.read(4096),b\\\"\\\"):\",\"            sha256_hash.update(byte_block)\",\"        return sha256_hash.hexdigest().upper()\",\"\",\"# cd into the temp directory\",\"create_dir(tmp_dir)\",\"os.chdir(tmp_dir)\",\"\",\"region \u003d os.environ[\\\"AWS_SSM_REGION_NAME\\\"]\",\"\",\"# main logic\",\"# Replace the region placeholder with correct region.\",\"digest \u003d hashlib.sha256((\\\"-\\\".join([\\\"prod\\\", region, \\\"internal-patch-public-bucket\\\"])).encode(\\\"utf8\\\")).hexdigest()[0:9]\",\"if region \u003d\u003d \\\"me-central-1\\\":\",\"    digest \u003d hashlib.sha256((\\\"-\\\".join([\\\"prod\\\", region + region, \\\"internal-patch-public-bucket\\\"])).encode(\\\"utf8\\\")).hexdigest()[0:9]\",\"\",\"s3_bucket \u003d \\\"aws-patchmanager-macos-%s-%s\\\"%(region, digest)\",\"s3_prefix \u003d \\\"patchbaselineoperations/linux/payloads\\\"\",\"payload_name \u003d \\\"patch-baseline-operations-macos-8.2.tar.gz\\\"\",\"payload_sha256 \u003d \\\"CDE542A348CF9463FA3D872BDD39384D3ED646D012D5EA72CC1214030C094CAE\\\"\",\"\",\"# download payload file and do signature verification\",\"# For new regions after CPT/MXP we will utilize s3 transfer acceleration access point\",\"# China and Gov region do not support this feature\",\"region_to_interpolate \u003d region\",\"if region.startswith(\\\"cn-\\\"):\",\"    url_template \u003d \\\"https://s3.%s.amazonaws.com.cn/%s/%s\\\"\",\"elif region.startswith(\\\"us-gov-\\\"):\",\"    url_template \u003d \\\"https://s3-fips-%s.amazonaws.com/%s/%s\\\"\",\"else:\",\"    url_template \u003d \\\"https://s3.dualstack.%s.amazonaws.com/%s/%s\\\"\",\"\",\"download_to(url_template % (region_to_interpolate, s3_bucket, os.path.join(s3_prefix, payload_name)), payload_name)\",\"\",\"# payloads are the actual files to be used for linux patching\",\"payloads \u003d []\",\"try:\",\"    sha256_code \u003d sha256_checksum(payload_name)\",\"    if not sha256_code \u003d\u003d payload_sha256:\",\"        error_msg \u003d \\\"%s sha256 check failed, should be %s, but is %s\\\" % (payload_name, payload_sha256, sha256_code)\",\"        logger.error(error_msg)\",\"        abort(151, (payload_name, payload_sha256, sha256_code))\",\"    extract_tar(payload_name)\",\"    # Change owner \u0026 group to be root user for the payload.\",\"    shell_command([\\\"chown\\\", \\\"-R\\\", \\\"0:0\\\", tmp_dir])\",\"except Exception as e:\",\"    error_msg \u003d \\\"Unable to load and extract the content of payload, abort.\\\"\",\"    logger.error(error_msg)\",\"    logger.exception(e)\",\"    abort(152)\",\"\",\"\",\"# Document parameters.\",\"import sys\",\"try:\",\"    import common_startup_entrance\",\"    common_startup_entrance.execute(\\\"os_selector\\\", \\\"PatchMacOS\\\", \\\"{{SnapshotId}}\\\",\\\\\",\"            \\\"{{Operation}}\\\", \\\"{{InstallOverrideList}}\\\", \\\\\",\"            \\\"{{RebootOption}}\\\", \\\"{{BaselineOverride}}\\\",\\\"{{AssociationId}}\\\")\",\"except Exception as e:\",\"    error_code \u003d 156\",\"    if hasattr(e, \\\"error_code\\\") and type(e.error_code) \u003d\u003d int:\",\"        error_code \u003d e.error_code;\",\"    logger.exception(e)\",\"    sys.exit(error_code)\",\"    \",\"\",\"\u0027 | $PYTHON_CMD\",\"\",\"RETURN_CODE\u003d$?\",\"\",\"exit $RETURN_CODE\"]},\"name\":\"PatchMacOS\",\"action\":\"aws:runShellScript\",\"precondition\":{\"StringEquals\":[\"platformType\",\"MacOS\"]}}]},\"CloudWatchLogGroupName\":\"\",\"OutputS3Region\":\"us-gov-west-1\",\"CommandId\":\"9293d924-de8b-41e1-a707-6a0a86de43b4\",\"OutputS3BucketName\":\"\",\"DocumentName\":\"AWS-RunPatchBaseline\"}"}"
2023-03-15 21:04:41 INFO [ssm-agent-worker] [MessageService] [MGSInteractor] Validating SSM parameters
2023-03-15 21:04:42 INFO [ssm-agent-worker] [MessageService] [EngineProcessor] document aws.ssm.9293d924-de8b-41e1-a707-6a0a86de43b4.i-03da12b042683cb0f submission started
tabinda-syed commented 1 year ago

@cris-oddball Kyle pointed me to you as the person who’d have the most info on this. He mentioned that this ticket may need a full re-write at this point in order to be ready for eventual refinement. Tagging you here to request you to please take a look when you can. Thanks!

cris-oddball commented 1 year ago

@k-macmillan @ldraney Not sure what re-write is needed here? Twistlock occasionally falls over and should be investigated - Can one of you help me understand what may have changed with Twisty that requires a re-write of this ticket, please?

cris-oddball commented 1 year ago

Ticket updated. Can we now remove the changes requested label? @k-macmillan @ldraney

k-macmillan commented 1 year ago

Upgrade planned for tomorrow. Should auto-upgrade but if we hit issues we may need to update manually. image

k-macmillan commented 1 year ago

The service is in a much healthier state now. It's still not great, but seems much better and is probably due to the upgrade we did a while back. Here's the health over the last couple months: image

mjones-oddball commented 1 year ago

We have been working to restore the Twistlock EC2 and may end up replacing Twistlock so this ticket could become irrelevant. https://app.zenhub.com/workspaces/va-notify-620d21369d810a00146ed9c8/issues/gh/department-of-veterans-affairs/vanotify-infra/626

cris-oddball commented 1 year ago

This ticket is irrelevant - whatever was the root cause was mitigated some time ago, closing ticket.