A Patch Baseline in AWS Systems Manager is not just a list of approved patches; it’s a declarative policy that defines how and when your instances get patched, acting as a gatekeeper for your entire fleet.
Let’s see this in action. Imagine we have a fleet of EC2 instances running Amazon Linux 2 that we want to keep updated with critical and security patches.
First, we define our Patch Baseline. We’ll create one named MyLinux2-CriticalSecurity that targets the Amazon Linux 2 operating system.
{
"Name": "MyLinux2-CriticalSecurity",
"Description": "Applies Critical and Security updates for Amazon Linux 2",
"OperatingSystem": "AMAZON_LINUX_2",
"PatchFilterGroup": {
"PatchSetFilters": [
{
"Key": "PRODUCT",
"Values": [
"AMAZON"
]
},
{
"Key": "UPDATE_CLASSIFICATION",
"Values": [
"Security",
"Critical"
]
},
{
"Key": "SEVERITY",
"Values": [
"Critical",
"Important"
]
}
]
},
"ApprovalRules": {
"PatchRules": [
{
"PatchRuleType": "PRODUCT",
"Values": [
"Amazon Linux 2"
]
},
{
"PatchRuleType": "CLASSIFICATION",
"Values": [
"Security",
"Critical"
]
},
{
"PatchRuleType": "OPERATING_SYSTEM",
"Values": [
"Amazon Linux 2"
]
}
]
},
"Replace": false,
"SetAsDefault": false
}
This baseline specifies that we’re interested in patches for the Amazon Linux 2 product, specifically those classified as Security or Critical, and with severities of Critical or Important.
Next, we associate this Patch Baseline with a Patching Compliance configuration for our instances. We can do this by creating a Patching Compliance association.
schemaVersion: '0.3'
description: 'Patching Compliance for MyLinux2 instances'
parameters:
InstanceIds:
type: 'AWS::EC2::Instance::Id'
description: 'Instance IDs'
default: []
Operation:
type: 'String'
description: 'Operation type (Scan, Install)'
allowedValues:
- 'Scan'
- 'Install'
default: 'Install'
RebootOption:
type: 'String'
description: 'Reboot option'
allowedValues:
- 'RebootIfNeeded'
- 'NoReboot'
default: 'RebootIfNeeded'
MaxConcurrency:
type: 'String'
description: 'Max concurrency'
default: '50'
MaxErrors:
type: 'String'
description: 'Max errors'
default: '10'
PatchBaseline:
type: 'String'
description: 'Patch Baseline ID'
default: 'pb-0123456789abcdef0' # Replace with your actual Patch Baseline ID
SnapshotId:
type: 'String'
description: 'Snapshot ID for Windows instances'
default: ''
OperationS3Bucket:
type: 'String'
description: 'S3 bucket for output'
default: 'my-ssm-output-bucket' # Replace with your actual bucket name
OperationS3KeyPrefix:
type: 'String'
description: 'S3 key prefix for output'
default: 'patching-compliance'
mainSteps:
- action: 'aws:runDocument'
name: 'RunPatchingCompliance'
onFailure: 'Abort'
inputs:
DocumentName: 'AWS-RunPatchBaseline'
InstanceIds: '{{ InstanceIds }}'
Parameters:
Operation: '{{ Operation }}'
RebootOption: '{{ RebootOption }}'
MaxConcurrency: '{{ MaxConcurrency }}'
MaxErrors: '{{ MaxErrors }}'
PatchBaseline: '{{ PatchBaseline }}'
SnapshotId: '{{ SnapshotId }}'
OutputS3BucketName: '{{ OperationS3Bucket }}'
OutputS3KeyPrefix: '{{ OperationS3KeyPrefix }}'
This association, when executed, will instruct the SSM Agent on the target instances to check their compliance against the MyLinux2-CriticalSecurity Patch Baseline. If the Operation is set to Install, it will then proceed to install any missing patches that meet the baseline’s criteria. The RebootIfNeeded option ensures that instances are restarted only if a patch requires it.
The power of this system lies in its declarative nature and the separation of what to patch from when and how. You define your desired state (the Patch Baseline) once, and then you can apply this policy across your entire fleet, even to new instances as they are launched. You can also schedule these Patching Compliance associations to run periodically, ensuring continuous compliance.
Consider a common scenario: you have a newly discovered critical vulnerability. Instead of manually identifying every server that needs patching and then executing individual commands, you can simply update your Patch Baseline to include the new vulnerability (or ensure it’s already covered by your existing filters) and then trigger your scheduled Patching Compliance association. The system will then automatically scan and remediate all compliant instances.
What most people don’t realize is that the AWS-RunPatchBaseline document itself has a built-in PatchFilterGroup that can be overridden. While we’ve defined our filtering in the Patch Baseline resource, the AWS-RunPatchBaseline document also accepts parameters like Classification, Severity, and Operation. If you were to specify these parameters directly in the aws:runDocument step of your association, they would override the settings in the Patch Baseline for that specific execution. This offers a powerful way to create exceptions or perform targeted, ad-hoc patching runs without altering your default baseline.
Once your patching is configured, the next logical step is to monitor the patch compliance status across your fleet, which can be done using Systems Manager Compliance.