AWS Config provides a detailed view of the configuration of AWS resources in your account. It continuously monitors and records configuration changes, and evaluates them against desired configurations using rules. Think of CloudTrail as the security camera (who did what) and AWS Config as the building inspector (is the current state of the building up to code?). CloudTrail tells you “Alice modified security group sg-123 at 3 PM.” Config tells you “security group sg-123 currently allows SSH from 0.0.0.0/0, which violates rule restricted-ssh.” Together, they answer both the “who changed it” and “is it compliant” questions.
Cost awareness: Config charges per configuration item recorded (~0.003each)plusperruleevaluation(0.001 each). In a large account with 10,000+ resources and 50 rules, this can reach $500-1,000/month. Use resource type scoping to record only what you need, especially in development accounts.
# Create S3 bucket for config snapshots.# Config stores configuration history and snapshots here.# Cost tip: a typical 100-resource account generates ~1-5 GB/month.# Add S3 lifecycle rules to move old snapshots to Glacier after 90 days.aws s3 mb s3://my-config-bucket-123456789012# Create IAM role for Configaws iam create-role \ --role-name ConfigRole \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": "config.amazonaws.com"}, "Action": "sts:AssumeRole" }] }'# Attach managed policyaws iam attach-role-policy \ --role-name ConfigRole \ --policy-arn arn:aws:iam::aws:policy/service-role/AWS_ConfigRole# Create configuration recorder.# allSupported=true records ALL resource types -- the safe default.# Common mistake: recording only specific types and missing something# that causes a compliance gap during audit.# includeGlobalResourceTypes=true captures IAM (global resources).# Only enable this in ONE region to avoid duplicate recordings and double billing.aws configservice put-configuration-recorder \ --configuration-recorder name=default,roleARN=arn:aws:iam::123456789012:role/ConfigRole \ --recording-group allSupported=true,includeGlobalResourceTypes=true# Create delivery channelaws configservice put-delivery-channel \ --delivery-channel name=default,s3BucketName=my-config-bucket-123456789012# Start recordingaws configservice start-configuration-recorder --configuration-recorder-name default
AWS provides 300+ managed rules. Think of managed rules as pre-built inspections — AWS maintains the evaluation logic and keeps it updated as services evolve. You only pay per evaluation (~$0.001 per rule evaluation per resource).Common mistake: enabling every managed rule on day one. Start with the 10-15 rules that map to your compliance framework (CIS, PCI, SOC2), then expand once your team builds the discipline to respond to findings. Fifty rules generating 200 NON_COMPLIANT findings that nobody investigates is worse than 10 rules with 100% follow-through.
# custom_rule.pyimport boto3import jsondef lambda_handler(event, context): """ Custom Config Rule: Check if EC2 instances have required tags """ config = boto3.client('config') # Get configuration item invoking_event = json.loads(event['invokingEvent']) configuration_item = invoking_event['configurationItem'] # Rule parameters rule_parameters = json.loads(event.get('ruleParameters', '{}')) required_tags = rule_parameters.get('requiredTags', 'Environment,Owner,CostCenter').split(',') # Evaluate compliance. # The pattern: start optimistic (COMPLIANT) and flip to NON_COMPLIANT if any # check fails. This avoids accidentally marking resources as non-compliant # when they are simply not the resource type you care about. compliance_type = 'COMPLIANT' annotation = 'All required tags are present' if configuration_item['resourceType'] == 'AWS::EC2::Instance': tags = {t['key']: t['value'] for t in configuration_item.get('tags', [])} missing_tags = [tag for tag in required_tags if tag not in tags] if missing_tags: compliance_type = 'NON_COMPLIANT' annotation = f'Missing required tags: {", ".join(missing_tags)}' # Put evaluation config.put_evaluations( Evaluations=[{ 'ComplianceResourceType': configuration_item['resourceType'], 'ComplianceResourceId': configuration_item['resourceId'], 'ComplianceType': compliance_type, 'Annotation': annotation, 'OrderingTimestamp': configuration_item['configurationItemCaptureTime'] }], ResultToken=event['resultToken'] ) return { 'compliance_type': compliance_type, 'annotation': annotation }
The Aggregator is like a central security desk that pulls compliance data from all your accounts and regions into one view. Without it, you would need to log into each account individually to check compliance — impractical beyond a handful of accounts. A senior engineer would say: “We use a Config Aggregator in our security account so the compliance team has a single pane of glass across all 50 accounts.”Cost tip: the Aggregator itself is free. You only pay for Config recordings and rule evaluations in each source account.
CloudTrail = Who did what, when (the security camera footage)
Records API calls
Answers: “Who deleted the S3 bucket at 2 AM?”
Focus: API activity auditing
AWS Config = What is the configuration (the building inspector report)
Records resource configurations over time
Answers: “Is this S3 bucket public? When did it become public?”
Focus: Configuration compliance and drift detection
They complement each other: Config gives you the diff, CloudTrail gives you the git blame. In an incident, use Config to see what changed and CloudTrail to see who changed it.
Q2: How do you implement drift detection at scale?
Enable Config in all accounts and regions
Deploy conformance packs via Organizations
Create aggregator for centralized view
Set up notifications for non-compliant resources
Automate remediation with SSM documents
Track trends with compliance dashboards
Q3: How do you handle false positives in Config rules?
Options:
Scope rules: Limit to specific resource types or tags