Skip to content

AWS Config

Chapter 44: AWS Config & Resource Compliance

Section titled “Chapter 44: AWS Config & Resource Compliance”

Resource Configuration Management and Compliance

Section titled “Resource Configuration Management and Compliance”

AWS Config is a fully managed service that provides AWS resource inventory, configuration history, and configuration change notifications to enable security and governance.

AWS Config Overview
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | AWS Config | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | | |
| v v v v |
| +----------+ +----------+ +----------+ +----------+ |
| | Resource | | Config | | Rules | | Compliance| |
| | Inventory| | History | | | | | |
| | | | | | | | | |
| | - Track | | - Changes| | - Custom | | - Audit | |
| | - Record | | - Timeline| | - Managed| | - Report | |
| | - Query | | - Version | | - Lambda | | - Remediate| |
| +----------+ +----------+ +----------+ +----------+ |
| |
+------------------------------------------------------------------+
FeatureDescription
Resource InventoryTrack all AWS resources
Configuration HistoryRecord changes over time
Config RulesEvaluate resource compliance
Compliance DashboardVisual compliance reporting

AWS Config Architecture
+------------------------------------------------------------------+
| |
| AWS Account |
| +----------------------------------------------------------+ |
| | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | EC2 | | S3 | | RDS | | IAM | | |
| | | Resources| | Buckets | | Databases| | Roles | | |
| | +----+-----+ +----+-----+ +----+-----+ +----+-----+ | |
| | | | | | | |
| +-------+------------+------------+------------+------------+ |
| | |
| v |
| +----------------------------------------------------------+ |
| | AWS Config Service | |
| | +------------------------------------------------------+ | |
| | | Configuration Recorder | | |
| | | - Records resource changes | | |
| | | - Stores in S3 bucket | | |
| | +------------------------------------------------------+ | |
| | +------------------------------------------------------+ | |
| | | Config Rules | | |
| | | - Evaluate compliance | | |
| | | - Trigger on changes | | |
| | +------------------------------------------------------+ | |
| | +------------------------------------------------------+ | |
| | | Delivery Channel | | |
| | | - SNS notifications | | |
| | | - S3 delivery | | |
| | +------------------------------------------------------+ | |
| +----------------------------------------------------------+ |
| | |
| v |
| +----------------------------------------------------------+ |
| | S3 Bucket | |
| | - Configuration snapshots | |
| | - Configuration history | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Configuration Recording
+------------------------------------------------------------------+
| |
| Recording Process |
| +----------------------------------------------------------+ |
| | | |
| | 1. Resource Created/Changed | |
| | +-------------------------------------------------+ | |
| | | EC2 instance launched | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 2. Config Service Detects Change | |
| | +-------------------------------------------------+ | |
| | | API call recorded via CloudTrail | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 3. Configuration Item Created | |
| | +-------------------------------------------------+ | |
| | | Resource details captured | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 4. Configuration History Updated | |
| | +-------------------------------------------------+ | |
| | | Change stored in S3 | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 5. Rules Evaluated | |
| | +-------------------------------------------------+ | |
| | | Compliance status updated | | |
| | +-------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Terminal window
# Using AWS CLI
aws configservice put-configuration-recorder \
--configuration-recorder name=default,roleARN=arn:aws:iam::123456789012:role/ConfigRole
aws configservice put-delivery-channel \
--delivery-channel name=default,s3BucketName=config-bucket,snsTopicARN=arn:aws:sns:us-east-1:123456789012:config-topic
aws configservice start-configuration-recorder \
--configuration-recorder-name default
{
"name": "default",
"roleARN": "arn:aws:iam::123456789012:role/ConfigRole",
"recordingGroup": {
"allSupported": true,
"includeGlobalResourceTypes": true,
"resourceTypes": [
"AWS::EC2::Instance",
"AWS::EC2::SecurityGroup",
"AWS::S3::Bucket",
"AWS::IAM::Role"
]
}
}
{
"name": "default",
"s3BucketName": "config-bucket",
"s3KeyPrefix": "config/",
"snsTopicARN": "arn:aws:sns:us-east-1:123456789012:config-topic",
"configSnapshotDeliveryProperties": {
"deliveryFrequency": "Twelve_Hours"
}
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutDeliveryChannel",
"s3:PutConfigurationRecorder",
"s3:GetBucketAcl",
"s3:ListBucket"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:*:*:config-topic"
}
]
}

AWS Config Managed Rules
+------------------------------------------------------------------+
| |
| Security Rules |
| +------------------+ +------------------+ +------------------+ |
| | root-account-mfa | | iam-mfa-policy | | access-keys-rotated| |
| | | | | | | |
| | Checks MFA on | | Checks MFA for | | Checks key | |
| | root account | | IAM users | | rotation | |
| +------------------+ +------------------+ +------------------+ |
| |
| Encryption Rules |
| +------------------+ +------------------+ +------------------+ |
| | s3-bucket-server| | rds-storage- | | ebs-encryption- | |
| | -side-encryption| | encrypted | | by-default | |
| | | | | | | |
| | Checks S3 | | Checks RDS | | Checks EBS | |
| | encryption | | encryption | | encryption | |
| +------------------+ +------------------+ +------------------+ |
| |
| Network Rules |
| +------------------+ +------------------+ +------------------+ |
| | vpc-sg-open-only| | restricted-ssh | | no-ingress-sg | |
| | -to-restricted-ports| | | | |
| | | | Checks SSH | | Checks no | |
| | Checks port | | restrictions | | public ingress | |
| | restrictions | | | | | |
| +------------------+ +------------------+ +------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# Enable managed rule
aws configservice put-config-rule \
--config-rule '{
"ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
"Description": "Checks that S3 buckets have server-side encryption enabled",
"Scope": {
"ComplianceResourceTypes": ["AWS::S3::Bucket"]
},
"Source": {
"Owner": "AWS",
"SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
}
}'
# Enable managed rule with parameters
aws configservice put-config-rule \
--config-rule '{
"ConfigRuleName": "required-tags",
"Description": "Checks for required tags on resources",
"Scope": {
"ComplianceResourceTypes": [
"AWS::EC2::Instance",
"AWS::S3::Bucket"
]
},
"InputParameters": "{\"tag1Key\":\"Environment\",\"tag2Key\":\"Owner\"}",
"Source": {
"Owner": "AWS",
"SourceIdentifier": "REQUIRED_TAGS"
}
}'
# List of commonly used managed rules
Security:
- root-account-mfa-required
- iam-user-mfa-enabled
- access-keys-rotated
- iam-password-policy
- multi-region-cloudtrail-enabled
Encryption:
- s3-bucket-server-side-encryption-enabled
- s3-bucket-default-lock-enabled
- rds-storage-encrypted
- ebs-volume-in-backup-plan
- cloudtrail-s3-dataevents-enabled
Network:
- vpc-default-security-group-closed
- restricted-ssh
- vpc-sg-open-only-to-restricted-ports
- no-ingress-sg-rules
- internet-gateway-authorized-vpc-only
Tagging:
- required-tags
- allowed-resource-tags
- ec2-instance-profile-attached

lambda_function.py
import json
import boto3
from datetime import datetime
def lambda_handler(event, context):
"""
Custom Config Rule: Check EC2 instance type compliance
"""
config = boto3.client('config')
# Parse invoking event
invoking_event = json.loads(event['invokingEvent'])
rule_parameters = json.loads(event.get('ruleParameters', '{}'))
# Get allowed instance types from parameters
allowed_types = rule_parameters.get('allowedInstanceTypes', ['t3.micro', 't3.small'])
# Get configuration item
configuration_item = invoking_event.get('configurationItem', {})
resource_type = configuration_item.get('resourceType')
# Only evaluate EC2 instances
if resource_type != 'AWS::EC2::Instance':
return build_evaluation(
configuration_item,
'NOT_APPLICABLE',
'Rule only applies to EC2 instances'
)
# Get instance type
instance_type = configuration_item.get('configuration', {}).get('instanceType')
# Evaluate compliance
if instance_type in allowed_types:
compliance_type = 'COMPLIANT'
annotation = f'Instance type {instance_type} is allowed'
else:
compliance_type = 'NON_COMPLIANT'
annotation = f'Instance type {instance_type} is not in allowed list: {allowed_types}'
return build_evaluation(configuration_item, compliance_type, annotation)
def build_evaluation(configuration_item, compliance_type, annotation):
"""Build evaluation result"""
return {
'evaluations': [
{
'complianceResourceType': configuration_item.get('resourceType'),
'complianceResourceId': configuration_item.get('resourceId'),
'complianceType': compliance_type,
'annotation': annotation,
'orderingTimestamp': datetime.now().isoformat()
}
]
}
Terminal window
# Create Lambda function
aws lambda create-function \
--function-name ConfigRule-InstanceTypeCheck \
--runtime python3.9 \
--role arn:aws:iam::123456789012:role/ConfigLambdaRole \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip
# Create Config rule using Lambda
aws configservice put-config-rule \
--config-rule '{
"ConfigRuleName": "custom-instance-type-check",
"Description": "Checks that EC2 instances use allowed types",
"Scope": {
"ComplianceResourceTypes": ["AWS::EC2::Instance"]
},
"InputParameters": "{\"allowedInstanceTypes\":[\"t3.micro\",\"t3.small\",\"t3.medium\"]}",
"Source": {
"Owner": "CUSTOM_LAMBDA",
"SourceIdentifier": "arn:aws:lambda:us-east-1:123456789012:function:ConfigRule-InstanceTypeCheck",
"SourceDetails": [
{
"EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification"
},
{
"EventSource": "aws.config",
"MessageType": "ScheduledNotification"
}
]
}
}'
periodic_rule.py
import json
import boto3
from datetime import datetime
def lambda_handler(event, context):
"""
Periodic Config Rule: Check for unencrypted EBS volumes
"""
ec2 = boto3.client('ec2')
config = boto3.client('config')
# Get all EBS volumes
result_token = None
non_compliant_resources = []
while True:
if result_token:
response = ec2.describe_volumes(NextToken=result_token)
else:
response = ec2.describe_volumes()
for volume in response['Volumes']:
if not volume['Encrypted']:
non_compliant_resources.append({
'resourceId': volume['VolumeId'],
'resourceType': 'AWS::EC2::Volume'
})
result_token = response.get('NextToken')
if not result_token:
break
# Build evaluations
evaluations = []
for resource in non_compliant_resources:
evaluations.append({
'complianceResourceType': resource['resourceType'],
'complianceResourceId': resource['resourceId'],
'complianceType': 'NON_COMPLIANT',
'annotation': 'EBS volume is not encrypted',
'orderingTimestamp': datetime.now().isoformat()
})
# If no non-compliant resources, mark as compliant
if not evaluations:
evaluations.append({
'complianceResourceType': 'AWS::EC2::Volume',
'complianceResourceId': 'ALL',
'complianceType': 'COMPLIANT',
'annotation': 'All EBS volumes are encrypted',
'orderingTimestamp': datetime.now().isoformat()
})
# Send evaluations to Config
config.put_evaluations(
Evaluations=evaluations,
ResultToken=event['resultToken']
)
return {
'statusCode': 200,
'body': json.dumps({
'nonCompliantCount': len(non_compliant_resources)
})
}

AWS Config Remediation
+------------------------------------------------------------------+
| |
| Remediation Workflow |
| +----------------------------------------------------------+ |
| | | |
| | 1. Non-Compliant Resource Detected | |
| | +-------------------------------------------------+ | |
| | | Config rule evaluates resource | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 2. Remediation Triggered | |
| | +-------------------------------------------------+ | |
| | | SSM Automation document executed | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 3. Remediation Action | |
| | +-------------------------------------------------+ | |
| | | Resource modified to compliant state | | |
| | +-------------------------------------------------+ | |
| | | | |
| | v | |
| | 4. Re-evaluation | |
| | +-------------------------------------------------+ | |
| | | Config rule re-evaluates resource | | |
| | +-------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# Create remediation configuration
aws configservice put-remediation-configurations \
--remediation-configurations '[
{
"ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
"TargetId": "AWS-EnableS3BucketEncryption",
"TargetType": "SSM_DOCUMENT",
"TargetVersion": "1",
"Parameters": {
"BucketName": {
"ResourceValue": {
"Value": "RESOURCE_ID"
}
},
"SSEType": {
"StaticValue": {
"Values": ["AES256"]
}
}
},
"Automatic": true,
"ExecutionControls": {
"SsmControls": {
"ConcurrentExecutionRatePercentage": 10,
"ErrorPercentage": 5
}
},
"RetryAttemptSeconds": 60,
"MaximumAutomaticAttempts": 3
}
]'
AWS-EnableS3BucketEncryption.yaml
schemaVersion: '0.3'
description: Enable S3 bucket encryption
parameters:
BucketName:
type: String
description: S3 bucket name
SSEType:
type: String
description: Server-side encryption type
allowedValues:
- AES256
- aws:kms
default: AES256
mainSteps:
- name: EnableEncryption
action: 'aws:executeAwsApi'
inputs:
Service: s3
Api: PutBucketEncryption
BucketName: '{{ BucketName }}'
ServerSideEncryptionConfiguration:
Rules:
- ApplyServerSideEncryptionByDefault:
SSEAlgorithm: '{{ SSEType }}'
outputs:
- Name: Response
Selector: '$'
Type: StringMap
- name: VerifyEncryption
action: 'aws:executeAwsApi'
inputs:
Service: s3
Api: GetBucketEncryption
BucketName: '{{ BucketName }}'
outputs:
- Name: EncryptionStatus
Selector: '$.ServerSideEncryptionConfiguration.Rules[0].ApplyServerSideEncryptionByDefault.SSEAlgorithm'
Type: String
- name: VerifySuccess
action: 'aws:assertAwsResourceProperty'
inputs:
Service: s3
Api: GetBucketEncryption
BucketName: '{{ BucketName }}'
PropertySelector: '$.ServerSideEncryptionConfiguration.Rules[0].ApplyServerSideEncryptionByDefault.SSEAlgorithm'
DesiredValues:
- '{{ SSEType }}'
Terminal window
# Start remediation execution
aws configservice start-remediation-execution \
--config-rule-name s3-bucket-server-side-encryption-enabled \
--resource-keys '[{"resourceId":"my-bucket","resourceType":"AWS::S3::Bucket"}]'
# Describe remediation executions
aws configservice describe-remediation-executions \
--config-rule-name s3-bucket-server-side-encryption-enabled \
--resource-keys '[{"resourceId":"my-bucket","resourceType":"AWS::S3::Bucket"}]'

-- Find all EC2 instances
SELECT
resourceId,
resourceName,
configuration.instanceType,
configuration.state.name as state,
tags
WHERE
resourceType = 'AWS::EC2::Instance'
-- Find unencrypted S3 buckets
SELECT
resourceId,
resourceName,
region
WHERE
resourceType = 'AWS::S3::Bucket'
AND configuration.bucketEncryption IS NULL
-- Find security groups with SSH open to world
SELECT
resourceId,
resourceName,
configuration.ipPermissions
WHERE
resourceType = 'AWS::EC2::SecurityGroup'
AND configuration.ipPermissions[*].ipRanges[*].cidrIp = '0.0.0.0/0'
AND configuration.ipPermissions[*].fromPort = 22
-- Find instances without required tags
SELECT
resourceId,
resourceName,
tags
WHERE
resourceType = 'AWS::EC2::Instance'
AND tags.Environment IS NULL
-- Find all resources with specific tag
SELECT
resourceId,
resourceName,
resourceType,
tags
WHERE
tags.Project = 'Production'
-- Count resources by type
SELECT
resourceType,
COUNT(*) as count
GROUP BY
resourceType
ORDER BY
count DESC
Terminal window
# Run aggregation query
aws configservice select-aggregate-resource-config \
--expression "SELECT resourceId, resourceName, resourceType WHERE resourceType = 'AWS::EC2::Instance'"
# Run query with aggregation
aws configservice select-aggregate-resource-config \
--expression "SELECT resourceType, COUNT(*) as count GROUP BY resourceType"
# Query specific account/region
aws configservice select-aggregate-resource-config \
--expression "SELECT resourceId, resourceName WHERE resourceType = 'AWS::S3::Bucket'" \
--configuration-aggregator-name my-aggregator

Configuration Aggregator
+------------------------------------------------------------------+
| |
| Organization Aggregator |
| +----------------------------------------------------------+ |
| | | |
| | Management Account | |
| | +------------------------------------------------------+ | |
| | | Config Aggregator | | |
| | | +--------------------------------------------------+ | | |
| | | | Aggregated Data from All Accounts | | | |
| | | +--------------------------------------------------+ | | |
| | +------------------------------------------------------+ | |
| | | |
| +--------------------------+-------------------------------+ |
| | |
| +------------------+------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Account A| | Account B| | Account C| |
| | Dev | | Staging | | Prod | |
| +----------+ +----------+ +----------+ |
| | | | |
| v v v |
| Config Data Config Data Config Data |
| |
+------------------------------------------------------------------+
Terminal window
# Create aggregator for organization
aws configservice put-configuration-aggregator \
--configuration-aggregator-name organization-aggregator \
--organization-aggregation-source \
'{"RoleArn":"arn:aws:iam::123456789012:role/ConfigAggregatorRole","AllAwsRegions":true}'
# Create aggregator for specific accounts
aws configservice put-configuration-aggregator \
--configuration-aggregator-name multi-account-aggregator \
--account-aggregation-sources \
'[{"AccountIds":["111111111111","222222222222"],"AllAwsRegions":true}]'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"organizations:ListAccounts",
"organizations:DescribeOrganization",
"organizations:ListAWSServiceAccessForOrganization"
],
"Resource": "*"
}
]
}

Conformance Packs
+------------------------------------------------------------------+
| |
| Conformance Pack Structure |
| +----------------------------------------------------------+ |
| | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | Rule 1 | | Rule 2 | | Rule 3 | | Rule N | | |
| | | | | | | | | | | |
| | | - Config | | - Config | | - Config | | - Config | | |
| | | - Params | | - Params | | - Params | | - Params | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | |
| | +------------------------------------------------------+ | |
| | | Remediation Configurations | | |
| | | - Auto-remediation actions | | |
| | | - SSM Automation documents | | |
| | +------------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
conformance-pack.yaml
Resources:
S3BucketEncryptionRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-encryption
Description: Checks S3 bucket encryption
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
S3BucketPublicReadRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-public-read
Description: Checks S3 bucket public read access
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
EC2InstanceTypeRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: ec2-instance-type
Description: Checks EC2 instance types
Scope:
ComplianceResourceTypes:
- AWS::EC2::Instance
InputParameters:
allowedInstanceTypes: t3.micro,t3.small,t3.medium
Source:
Owner: AWS
SourceIdentifier: DESIRED_INSTANCE_TYPE
S3BucketEncryptionRemediation:
Type: AWS::Config::RemediationConfiguration
Properties:
ConfigRuleName: s3-bucket-encryption
TargetId: AWS-EnableS3BucketEncryption
TargetType: SSM_DOCUMENT
Automatic: true
Parameters:
BucketName:
ResourceValue:
Value: RESOURCE_ID
SSEType:
StaticValue:
Values:
- AES256
Terminal window
# Deploy conformance pack
aws configservice put-conformance-pack \
--conformance-pack-name security-conformance-pack \
--template-body file://conformance-pack.yaml
# Deploy with delivery S3 bucket
aws configservice put-conformance-pack \
--conformance-pack-name security-conformance-pack \
--template-body file://conformance-pack.yaml \
--delivery-s3-bucket config-conformance-bucket
# Describe conformance pack
aws configservice describe-conformance-packs \
--conformance-pack-names security-conformance-pack
# Get conformance pack compliance details
aws configservice get-conformance-pack-compliance-details \
--conformance-pack-name security-conformance-pack
security-baseline.yaml
Resources:
# IAM Rules
RootMfaRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: root-mfa-enabled
Source:
Owner: AWS
SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED
IamUserMfaRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: iam-user-mfa-enabled
Source:
Owner: AWS
SourceIdentifier: IAM_USER_MFA_ENABLED
AccessKeysRotatedRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: access-keys-rotated
InputParameters:
maxAccessKeyAge: "90"
Source:
Owner: AWS
SourceIdentifier: ACCESS_KEYS_ROTATED
# Encryption Rules
S3EncryptionRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-encryption
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
RdsEncryptionRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: rds-storage-encrypted
Source:
Owner: AWS
SourceIdentifier: RDS_STORAGE_ENCRYPTED
# Network Rules
RestrictedSshRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: restricted-ssh
Source:
Owner: AWS
SourceIdentifier: INCOMING_SSH_DISABLED

# CloudWatch Events rule for Config changes
Resources:
ConfigChangeRule:
Type: AWS::Events::Rule
Properties:
Name: config-compliance-change
Description: Trigger on Config compliance changes
EventPattern:
source:
- aws.config
detail-type:
- Config Rules Compliance Change
detail:
newEvaluationResult:
complianceType:
- NON_COMPLIANT
State: ENABLED
Targets:
- Id: SnsTopic
Arn: !Ref SnsTopic
- Id: LambdaFunction
Arn: !Ref LambdaFunction
# Lambda function to process Config notifications
import json
import boto3
def lambda_handler(event, context):
"""Process Config compliance change notifications"""
sns = boto3.client('sns')
for record in event.get('Records', []):
message = json.loads(record['Sns']['Message'])
# Extract compliance details
rule_name = message.get('configRuleName')
resource_id = message.get('resourceId')
compliance = message.get('newEvaluationResult', {}).get('complianceType')
# Send alert for non-compliant resources
if compliance == 'NON_COMPLIANT':
alert_message = f"""
Compliance Alert!
Rule: {rule_name}
Resource: {resource_id}
Status: {compliance}
Action Required: Please remediate this resource.
"""
sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:config-alerts',
Subject='AWS Config Compliance Alert',
Message=alert_message
)
return {'statusCode': 200}
Terminal window
# Enable Security Hub integration
aws securityhub enable-security-hub \
--enable-default-standards
# Import Config findings to Security Hub
# (Automatic when both services are enabled)

AWS Config is essential for compliance as code and resource tracking. SREs use it to ensure infrastructure meets security and operational standards.

AWS Config in DevOps/SRE
+------------------------------------------------------------------+
| |
| SRE Compliance & Governance: |
| |
| 1. Continuous Compliance |
| +----------------------------------------------------------+ |
| | - Automated compliance checks on resource changes | |
| | - Detect non-compliant resources immediately | |
| | - Auto-remediation for common issues | |
| +----------------------------------------------------------+ |
| |
| 2. Audit & Forensics |
| +----------------------------------------------------------+ |
| | - History of all resource changes | |
| | - Who changed what and when | |
| | - Evidence for compliance audits | |
| +----------------------------------------------------------+ |
| |
| 3. Drift Detection |
| +----------------------------------------------------------+ |
| | - Compare actual state vs. desired state | |
| | - Alert on unauthorized changes | |
| | - Automated remediation | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Terminal window
# Install AWS CLI
sudo pacman -S aws-cli-v2 jq
# Get compliance status
aws configservice get-compliance-summary \
--compliance-types RESOURCE_COMPLIANCE_NON_COMPLIANT
# Query resource configuration
aws configservice select-resource-config \
--expression "SELECT * WHERE resourceType = 'AWS::EC2::Instance'"

AWS Config Anti-Patterns
+------------------------------------------------------------------+
| |
| ❌ Mistake 1: Not Recording All Resources |
| +----------------------------------------------------------+ |
| | Problem: Missing resource changes in audit trail | |
| | Impact: Incomplete compliance visibility | |
| | Fix: Enable all regions and resource types | |
| +----------------------------------------------------------+ |
| |
| ❌ Mistake 2: Not Using Conformance Packs |
| +----------------------------------------------------------+ |
| | Problem: Manual rule management | |
| | Impact: Inconsistent compliance across accounts | |
| | Fix: Use conformance packs for reusable rules | |
| +----------------------------------------------------------+ |
| |
| ❌ Mistake 3: Not Setting Up Remediation |
| +----------------------------------------------------------+ |
| | Problem: Detecting issues but not fixing them | |
| | Impact: Compliance drift remains unfixed | |
| | Fix: Configure auto-remediation with SSM documents | |
| +----------------------------------------------------------+ |
| |
| ❌ Mistake 4: Ignoring Cost |
| +----------------------------------------------------------+ |
| | Problem: Recording too many resources | |
| | Impact: High Config costs | |
| | Fix: Selectively record only critical resources | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

  1. Q: What’s the difference between AWS Config and CloudTrail?

    • A: CloudTrail records API calls (who did what). Config records resource state changes (what changed). Use both: CloudTrail for auditing actions, Config for compliance and drift detection.
  2. Q: How does Config auto-remediation work?

    • A: Use AWS Systems Manager Automation documents as remediation actions. When a rule evaluates to NON_COMPLIANT, Config can automatically trigger the SSM document to fix the issue.
  1. Q: Design a multi-account compliance strategy.
    • A: Use AWS Config in each account with aggregation in a central account. Use conformance packs for consistent rules. Enable Organization Config rules. Set up automatic remediation with SSM.

AWS Config Best Practices
+------------------------------------------------------------------+
| |
| 1. Recording Strategy |
| +--------------------------------------------------------+ |
| | - Record all supported resource types | |
| | - Include global resources (IAM) | |
| | - Use S3 lifecycle policies for cost management | |
| | - Enable in all regions | |
| +--------------------------------------------------------+ |
| |
| 2. Rules Strategy |
| +--------------------------------------------------------+ |
| | - Start with managed rules | |
| | - Add custom rules for specific requirements | |
| | - Use conformance packs for compliance frameworks | |
| | - Set appropriate remediation actions | |
| +--------------------------------------------------------+ |
| |
| 3. Multi-Account Strategy |
| +--------------------------------------------------------+ |
| | - Use configuration aggregator | |
| | - Deploy conformance packs organization-wide | |
| | - Centralize compliance reporting | |
| +--------------------------------------------------------+ |
| |
| 4. Cost Optimization |
| +--------------------------------------------------------+ |
| | - Use S3 lifecycle policies | |
| | - Limit custom rule frequency | |
| | - Review rule scope | |
| +--------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
# Recommended rules by category
Security:
- root-account-mfa-required
- iam-user-mfa-enabled
- access-keys-rotated
- cloudtrail-enabled
- multi-region-cloudtrail-enabled
Encryption:
- s3-bucket-server-side-encryption-enabled
- rds-storage-encrypted
- ebs-encrypted-volume
- cloudtrail-encryption-enabled
Network:
- vpc-default-security-group-closed
- restricted-ssh
- restricted-common-ports
- no-ingress-sg-rules
Tagging:
- required-tags
- allowed-resource-tags
Cost:
- ec2-instance-type-check
- ebs-volume-size-check
- rds-instance-type-check

AWS Config Troubleshooting
+------------------------------------------------------------------+
| |
| Issue: Config Rule Not Evaluating |
| +--------------------------------------------------------+ |
| | Solutions: | |
| | - Check IAM role permissions | |
| | - Verify resource scope | |
| | - Check Lambda function logs (custom rules) | |
| | - Verify trigger configuration | |
| +--------------------------------------------------------+ |
| |
| Issue: Remediation Failing |
| +--------------------------------------------------------+ |
| | Solutions: | |
| | - Check SSM document permissions | |
| | - Verify resource exists | |
| | - Check execution controls | |
| | - Review retry settings | |
| +--------------------------------------------------------+ |
| |
| Issue: High Costs |
| +--------------------------------------------------------+ |
| | Solutions: | |
| | - Reduce recording scope | |
| | - Use S3 lifecycle policies | |
| | - Limit custom rule frequency | |
| | - Review conformance pack scope | |
| +--------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Terminal window
# Check configuration recorder status
aws configservice describe-configuration-recorders
# Check delivery channel status
aws configservice describe-delivery-channels
# Get compliance details
aws configservice get-compliance-details-by-config-rule \
--config-rule-name s3-bucket-encryption
# Get resource configuration history
aws configservice get-resource-config-history \
--resource-type AWS::EC2::Instance \
--resource-id i-1234567890abcdef0
# Describe remediation exceptions
aws configservice describe-remediation-exceptions \
--config-rule-name s3-bucket-encryption

TopicKey Points
RecordingEnable for all resources and regions
Managed RulesStart with AWS managed rules
Custom RulesUse Lambda for complex evaluations
RemediationEnable automatic remediation where safe
AggregationUse aggregator for multi-account visibility
Conformance PacksDeploy compliance frameworks as code


Exam Tip

Key Exam Points
+------------------------------------------------------------------+
| |
| 1. AWS Config records configuration changes for resources |
| |
| 2. Config Rules evaluate resource compliance |
| |
| 3. Managed Rules: AWS-provided compliance checks |
| |
| 4. Custom Rules: Lambda functions for custom logic |
| |
| 5. Remediation: Auto-fix non-compliant resources |
| |
| 6. Conformance Packs: Bundle multiple rules as YAML |
| |
| 7. Aggregator: Cross-account, cross-region compliance view |
| |
| 8. Config Timeline: History of resource changes |
| |
| 9. Relationship with CloudTrail: Config for state, Trail for |
| who made changes |
| |
| 10. Pricing: Per configuration item recorded + rule evaluation |
| |
+------------------------------------------------------------------+

Chapter 44 Summary
+------------------------------------------------------------------+
| |
| AWS Config & Resource Compliance |
| +------------------------------------------------------------+ |
| | - Continuous compliance monitoring | |
| | - Configuration change recording | |
| | - Managed and custom compliance rules | |
| | - Automatic remediation | |
| +------------------------------------------------------------+ |
| |
| Key Components |
| +------------------------------------------------------------+ |
| | - Config Recorder: Captures resource changes | |
| | - Config Rules: Compliance evaluation | |
| | - Remediation: Auto-fix non-compliant resources | |
| | - Aggregator: Multi-account/region view | |
| +------------------------------------------------------------+ |
| |
| Best Practices |
| +------------------------------------------------------------+ |
| | - Enable in all regions | |
| | - Start with managed rules | |
| | - Use conformance packs | |
| | - Enable remediation for safe rules | |
| +------------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Next Chapter: Chapter 45 - AWS Service Catalog & Provisioning