AWS Systems Manager Patch Manager automates the process of patching managed instances with security-related updates and other types of updates. This guide covers configuring patch baselines, setting up maintenance windows, organizing patch groups, and monitoring compliance across your infrastructure.
This article is part of our comprehensive Cloud Security Tips for 2026 guide covering essential practices for protecting your cloud environment.
Prerequisites
Before using Patch Manager, ensure:
- SSM Agent is installed and running on all target instances
- Instances have an IAM instance profile with
AmazonSSMManagedInstanceCorepolicy - Instances can reach Systems Manager endpoints (via internet or VPC endpoints)
- For Windows, ensure Windows Update service is running
# Verify SSM Agent status on Linux
sudo systemctl status amazon-ssm-agent
# Verify SSM Agent status on Windows (PowerShell)
Get-Service AmazonSSMAgentUnderstanding Patch Baselines
Patch baselines define approval rules for patches:
| Component | Description |
|---|---|
| Approval Rules | Auto-approve patches by classification, severity, after X days |
| Approved Patches | Explicitly approved patch IDs |
| Rejected Patches | Explicitly blocked patch IDs |
| Compliance Level | Severity assigned when patches are missing |
View Default Baselines
# List all patch baselines
aws ssm describe-patch-baselines \
--query 'BaselineIdentities[*].[BaselineId,Name,OperatingSystem,DefaultBaseline]' \
--output table
# Get default baseline for Amazon Linux 2
aws ssm describe-patch-baselines \
--filters 'Key=OPERATING_SYSTEM,Values=AMAZON_LINUX_2' \
--filters 'Key=DEFAULT_BASELINE,Values=true'Create Custom Patch Baseline
Linux Patch Baseline
# Create Amazon Linux 2 baseline with 7-day auto-approval
aws ssm create-patch-baseline \
--name "Production-AmazonLinux2-Baseline" \
--description "Production baseline - security patches auto-approved after 7 days" \
--operating-system AMAZON_LINUX_2 \
--approval-rules 'PatchRules=[{
PatchFilterGroup={
PatchFilters=[
{Key=PRODUCT,Values=AmazonLinux2},
{Key=CLASSIFICATION,Values=Security},
{Key=SEVERITY,Values=Critical,Important}
]
},
ApproveAfterDays=7,
ComplianceLevel=CRITICAL,
EnableNonSecurity=false
}]' \
--approved-patches-compliance-level CRITICAL \
--tags Key=Environment,Value=ProductionWindows Patch Baseline
# Create Windows Server baseline
aws ssm create-patch-baseline \
--name "Production-Windows-Baseline" \
--description "Windows Server production baseline" \
--operating-system WINDOWS \
--approval-rules 'PatchRules=[
{
PatchFilterGroup={
PatchFilters=[
{Key=PRODUCT,Values=WindowsServer2019,WindowsServer2022},
{Key=CLASSIFICATION,Values=CriticalUpdates,SecurityUpdates},
{Key=MSRC_SEVERITY,Values=Critical,Important}
]
},
ApproveAfterDays=7,
ComplianceLevel=CRITICAL
},
{
PatchFilterGroup={
PatchFilters=[
{Key=PRODUCT,Values=WindowsServer2019,WindowsServer2022},
{Key=CLASSIFICATION,Values=Updates}
]
},
ApproveAfterDays=14,
ComplianceLevel=MEDIUM
}
]' \
--rejected-patches "KB5000871" \
--rejected-patches-action BLOCKConfigure Patch Groups
Patch groups associate instances with specific baselines using tags:
# Tag instances with patch group
aws ec2 create-tags \
--resources i-1234567890abcdef0 i-0987654321fedcba0 \
--tags Key=Patch Group,Value=Production-Linux
# Register baseline with patch group
aws ssm register-patch-baseline-for-patch-group \
--baseline-id pb-0123456789abcdef0 \
--patch-group "Production-Linux"
# List patch group registrations
aws ssm describe-patch-groupsRecommended Patch Group Structure
| Patch Group | Environment | Patching Schedule |
|---|---|---|
| Dev-Linux | Development | Daily, auto-approve immediate |
| Staging-Linux | Staging | Weekly, 3-day approval delay |
| Production-Linux | Production | Bi-weekly, 7-day approval delay |
| Production-Critical | Critical Systems | Monthly, manual approval |
Create Maintenance Windows
Maintenance windows schedule when patching operations run:
# Create maintenance window for production patching
aws ssm create-maintenance-window \
--name "Production-Patching-Window" \
--description "Weekly production server patching" \
--schedule "cron(0 2 ? * SUN *)" \
--schedule-timezone "America/New_York" \
--duration 4 \
--cutoff 1 \
--allow-unassociated-targets \
--tags Key=Environment,Value=Production
# Output includes WindowId like: mw-0123456789abcdef0Register Targets with Maintenance Window
# Register patch group as target
aws ssm register-target-with-maintenance-window \
--window-id mw-0123456789abcdef0 \
--resource-type INSTANCE \
--targets 'Key=tag:Patch Group,Values=Production-Linux' \
--name "Production-Linux-Servers" \
--description "All production Linux servers"Create Patching Task
# Create Run Command task for patching
aws ssm register-task-with-maintenance-window \
--window-id mw-0123456789abcdef0 \
--task-type RUN_COMMAND \
--task-arn "AWS-RunPatchBaseline" \
--targets 'Key=WindowTargetIds,Values=' \
--service-role-arn arn:aws:iam::123456789012:role/MaintenanceWindowRole \
--task-invocation-parameters '{
"RunCommand": {
"Parameters": {
"Operation": ["Install"],
"RebootOption": ["RebootIfNeeded"]
}
}
}' \
--max-concurrency "25%" \
--max-errors "10%" \
--priority 1 \
--name "Patch-Production-Linux" Scan for Missing Patches
Run a scan without installing patches:
# Scan specific instances
aws ssm send-command \
--document-name "AWS-RunPatchBaseline" \
--targets 'Key=tag:Patch Group,Values=Production-Linux' \
--parameters 'Operation=Scan' \
--timeout-seconds 600 \
--max-concurrency "50" \
--max-errors "0"
# Scan and output to S3
aws ssm send-command \
--document-name "AWS-RunPatchBaseline" \
--targets 'Key=tag:Patch Group,Values=Production-Linux' \
--parameters 'Operation=Scan' \
--output-s3-bucket-name my-patch-logs \
--output-s3-key-prefix patch-scan-resultsInstall Patches
# Install patches with reboot if needed
aws ssm send-command \
--document-name "AWS-RunPatchBaseline" \
--targets 'Key=tag:Patch Group,Values=Production-Linux' \
--parameters 'Operation=Install,RebootOption=RebootIfNeeded' \
--timeout-seconds 3600 \
--max-concurrency "10%" \
--max-errors "5%"
# Install with no reboot (reboot manually later)
aws ssm send-command \
--document-name "AWS-RunPatchBaseline" \
--targets 'Key=InstanceIds,Values=i-1234567890abcdef0' \
--parameters 'Operation=Install,RebootOption=NoReboot'Monitor Patch Compliance
View Compliance Summary
# Get patch compliance summary
aws ssm list-compliance-summaries \
--filters 'Key=ComplianceType,Values=Patch'
# Get detailed compliance for an instance
aws ssm list-compliance-items \
--resource-ids i-1234567890abcdef0 \
--resource-types ManagedInstance \
--filters 'Key=ComplianceType,Values=Patch'
# List non-compliant instances
aws ssm describe-instance-patch-states \
--query 'InstancePatchStates[?MissingCount>`0`].[InstanceId,MissingCount,InstalledCount]' \
--output tableGet Patch State for Instance
# Detailed patch information
aws ssm describe-instance-patches \
--instance-id i-1234567890abcdef0 \
--query 'Patches[?State==`Missing`].[Title,KBId,Severity]' \
--output table
# Export compliance to S3
aws ssm get-compliance-summary-by-resource-type \
--resource-type ManagedInstanceSet Up Compliance Notifications
# Create SNS topic for notifications
aws sns create-topic --name patch-compliance-alerts
# Create EventBridge rule for non-compliant instances
aws events put-rule \
--name "PatchComplianceAlert" \
--event-pattern '{
"source": ["aws.ssm"],
"detail-type": ["Configuration Compliance State Change"],
"detail": {
"compliance-type": ["Patch"],
"compliance-status": ["non_compliant"]
}
}'
# Add SNS target
aws events put-targets \
--rule PatchComplianceAlert \
--targets Id=1,Arn=arn:aws:sns:us-east-1:123456789012:patch-compliance-alertsAutomation: Patch and Verify
Use Automation documents for complex patching workflows:
# Example: Patch with pre and post validation
aws ssm start-automation-execution \
--document-name "AWS-PatchInstanceWithRollback" \
--parameters '{
"InstanceId": ["i-1234567890abcdef0"],
"ReportS3Bucket": ["my-patch-logs"],
"WaitForReboot": ["PT5M"],
"WaitForInstance": ["PT10M"]
}'
# Custom automation with health check
aws ssm create-document \
--name "PatchWithHealthCheck" \
--document-type Automation \
--content '{
"schemaVersion": "0.3",
"description": "Patch instance with health validation",
"mainSteps": [
{
"name": "CreateAMIBackup",
"action": "aws:createImage",
"inputs": {
"InstanceId": "{{ InstanceId }}",
"ImageName": "backup-before-patch-{{ global:DATE }}"
}
},
{
"name": "InstallPatches",
"action": "aws:runCommand",
"inputs": {
"DocumentName": "AWS-RunPatchBaseline",
"InstanceIds": ["{{ InstanceId }}"],
"Parameters": {"Operation": ["Install"]}
}
},
{
"name": "ValidateHealth",
"action": "aws:executeScript",
"inputs": {
"Runtime": "python3.8",
"Script": "# Health check logic here"
}
}
]
}'Best Practices
| Practice | Recommendation |
|---|---|
| Testing | Always patch dev/staging before production |
| Approval Delays | Use 7-14 day delays for production baselines |
| Maintenance Windows | Schedule during low-traffic periods |
| Rate Controls | Limit concurrent patching to 10-25% |
| Backups | Create AMI/snapshots before patching |
| Monitoring | Set up compliance alerts for missing patches |
| Documentation | Track rejected patches with justification |
Common Pitfalls
- Missing SSM Agent - Ensure agent is installed and running on all instances
- IAM permissions - Instance profiles need SSM and S3 permissions
- Network connectivity - Instances need access to SSM endpoints
- Disk space - Ensure adequate space for patch downloads
- Reboot handling - Plan for reboot requirements in stateful applications