npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
When to Use
- When establishing continuous compliance monitoring for AWS resources against regulatory standards
- When implementing automated detection and remediation of configuration drift
- When building a compliance dashboard across multiple AWS accounts using AWS Organizations
- When audit teams require evidence of continuous compliance rather than point-in-time assessments
- When deploying guardrails that detect non-compliant resources within minutes of creation
Do not use for real-time threat detection (use GuardDuty), for application vulnerability scanning (use Inspector), or for one-time compliance assessments (use Prowler for faster ad-hoc audits).
Prerequisites
- AWS Config recording enabled in all target accounts and regions
- IAM role with
config:*,ssm:*, andlambda:*permissions for rule management - AWS Organizations with delegated administrator for Config aggregation
- S3 bucket for Config delivery channel and SNS topic for notifications
- CloudFormation StackSets or Terraform for multi-account rule deployment
Workflow
Step 1: Enable AWS Config Recording
Set up the Config recorder and delivery channel in each target account.
# Create S3 bucket for Config data
aws s3api create-bucket \
--bucket config-compliance-data-ACCOUNT_ID \
--region us-east-1
# Create Config service role
aws iam create-service-linked-role --aws-service-name config.amazonaws.com
# Start the Config recorder
aws configservice put-configuration-recorder \
--configuration-recorder name=default,roleARN=arn:aws:iam::ACCOUNT:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig \
--recording-group allSupported=true,includeGlobalResourceTypes=true
# Set up delivery channel
aws configservice put-delivery-channel \
--delivery-channel '{
"name": "default",
"s3BucketName": "config-compliance-data-ACCOUNT_ID",
"snsTopicARN": "arn:aws:sns:us-east-1:ACCOUNT:config-notifications",
"configSnapshotDeliveryProperties": {"deliveryFrequency": "TwentyFour_Hours"}
}'
# Start recording
aws configservice start-configuration-recorder --configuration-recorder-name defaultStep 2: Deploy Managed Config Rules for CIS Compliance
Enable AWS-managed Config rules that map to CIS AWS Foundations Benchmark controls.
# S3 bucket security rules
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "s3-bucket-public-read-prohibited",
"Source": {"Owner": "AWS", "SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "s3-bucket-ssl-requests-only",
"Source": {"Owner": "AWS", "SourceIdentifier": "S3_BUCKET_SSL_REQUESTS_ONLY"}
}'
# IAM security rules
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "iam-root-access-key-check",
"Source": {"Owner": "AWS", "SourceIdentifier": "IAM_ROOT_ACCESS_KEY_CHECK"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "mfa-enabled-for-iam-console-access",
"Source": {"Owner": "AWS", "SourceIdentifier": "MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "iam-password-policy",
"Source": {"Owner": "AWS", "SourceIdentifier": "IAM_PASSWORD_POLICY"},
"InputParameters": "{\"RequireUppercaseCharacters\":\"true\",\"RequireLowercaseCharacters\":\"true\",\"RequireSymbols\":\"true\",\"RequireNumbers\":\"true\",\"MinimumPasswordLength\":\"14\"}"
}'
# Network security rules
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "restricted-ssh",
"Source": {"Owner": "AWS", "SourceIdentifier": "INCOMING_SSH_DISABLED"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "vpc-flow-logs-enabled",
"Source": {"Owner": "AWS", "SourceIdentifier": "VPC_FLOW_LOGS_ENABLED"}
}'
# Encryption rules
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "rds-storage-encrypted",
"Source": {"Owner": "AWS", "SourceIdentifier": "RDS_STORAGE_ENCRYPTED"}
}'
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "encrypted-volumes",
"Source": {"Owner": "AWS", "SourceIdentifier": "ENCRYPTED_VOLUMES"}
}'Step 3: Create Custom Config Rules with Lambda
Build custom rules for organization-specific compliance requirements.
# custom_config_rule.py - Ensure EC2 instances have required tags
import json
import boto3
config = boto3.client('config')
REQUIRED_TAGS = ['Environment', 'Owner', 'CostCenter', 'Project']
def lambda_handler(event, context):
invoking_event = json.loads(event['invokingEvent'])
configuration_item = invoking_event.get('configurationItem', {})
if configuration_item['resourceType'] != 'AWS::EC2::Instance':
return
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 = 'NON_COMPLIANT'
annotation = f"Missing required tags: {', '.join(missing_tags)}"
else:
compliance = 'COMPLIANT'
annotation = 'All required tags present'
config.put_evaluations(
Evaluations=[{
'ComplianceResourceType': configuration_item['resourceType'],
'ComplianceResourceId': configuration_item['resourceId'],
'ComplianceType': compliance,
'Annotation': annotation,
'OrderingTimestamp': configuration_item['configurationItemCaptureTime']
}],
ResultToken=event['resultToken']
)# Deploy the custom rule
aws configservice put-config-rule --config-rule '{
"ConfigRuleName": "ec2-required-tags",
"Source": {
"Owner": "CUSTOM_LAMBDA",
"SourceIdentifier": "arn:aws:lambda:us-east-1:ACCOUNT:function:config-required-tags",
"SourceDetails": [{
"EventSource": "aws.config",
"MessageType": "ConfigurationItemChangeNotification"
}]
},
"Scope": {"ComplianceResourceTypes": ["AWS::EC2::Instance"]}
}'Step 4: Configure Automatic Remediation
Set up SSM Automation documents for automatic remediation of non-compliant resources.
# Auto-remediate public S3 buckets
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "s3-bucket-public-read-prohibited",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-DisableS3BucketPublicReadWrite",
"Parameters": {
"S3BucketName": {"ResourceValue": {"Value": "RESOURCE_ID"}},
"AutomationAssumeRole": {"StaticValue": {"Values": ["arn:aws:iam::ACCOUNT:role/ConfigRemediationRole"]}}
},
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60
}]'
# Auto-remediate unencrypted EBS volumes
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "encrypted-volumes",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-EnableEBSEncryptionByDefault",
"Parameters": {
"AutomationAssumeRole": {"StaticValue": {"Values": ["arn:aws:iam::ACCOUNT:role/ConfigRemediationRole"]}}
},
"Automatic": true,
"MaximumAutomaticAttempts": 1,
"RetryAttemptSeconds": 300
}]'
# Auto-remediate security groups allowing SSH from 0.0.0.0/0
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "restricted-ssh",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-DisablePublicAccessForSecurityGroup",
"Parameters": {
"GroupId": {"ResourceValue": {"Value": "RESOURCE_ID"}},
"AutomationAssumeRole": {"StaticValue": {"Values": ["arn:aws:iam::ACCOUNT:role/ConfigRemediationRole"]}}
},
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60
}]'Step 5: Set Up Multi-Account Aggregation
Aggregate compliance data from all organization accounts into a central view.
# Create a Config aggregator for the organization
aws configservice put-configuration-aggregator \
--configuration-aggregator-name org-compliance-aggregator \
--organization-aggregation-source '{
"RoleArn": "arn:aws:iam::ACCOUNT:role/ConfigAggregatorRole",
"AllAwsRegions": true
}'
# Query aggregate compliance across all accounts
aws configservice get-aggregate-compliance-details-by-config-rule \
--configuration-aggregator-name org-compliance-aggregator \
--config-rule-name s3-bucket-public-read-prohibited \
--compliance-type NON_COMPLIANT \
--query 'AggregateEvaluationResults[*].[AccountId,AwsRegion,EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId,ComplianceType]' \
--output table
# Get compliance summary by account
aws configservice get-aggregate-compliance-summary-by-source \
--configuration-aggregator-name org-compliance-aggregator \
--query 'AggregateComplianceCounts[*].[GroupName,ComplianceSummary.CompliantResourceCount.CappedCount,ComplianceSummary.NonCompliantResourceCount.CappedCount]' \
--output tableKey Concepts
| Term | Definition |
|---|---|
| AWS Config Rule | A compliance check that evaluates whether AWS resource configurations meet specified requirements, either continuously or on a schedule |
| Managed Rule | AWS-provided pre-built Config rule with standardized logic for common compliance checks like encryption and public access |
| Custom Rule | Organization-specific Config rule backed by a Lambda function that evaluates custom compliance logic |
| Remediation Action | SSM Automation document or Lambda function triggered to automatically fix non-compliant resources |
| Configuration Aggregator | AWS Config feature that collects compliance data from multiple accounts and regions into a centralized view |
| Conformance Pack | Collection of Config rules and remediation actions packaged as a deployable unit for specific compliance frameworks |
Tools & Systems
- AWS Config: Continuous configuration recording and compliance evaluation service for AWS resources
- SSM Automation: AWS Systems Manager documents for executing automated remediation actions on non-compliant resources
- Config Conformance Packs: Pre-built rule collections for CIS, PCI DSS, NIST 800-53, and HIPAA compliance
- CloudFormation StackSets: Multi-account deployment mechanism for Config rules across AWS Organizations
- Config Aggregator: Cross-account and cross-region compliance data consolidation
Common Scenarios
Scenario: Deploying CIS Compliance Monitoring Across 30 AWS Accounts
Context: A financial services company needs to demonstrate continuous CIS AWS Foundations Benchmark compliance across all 30 production accounts for their annual SOC 2 audit.
Approach:
- Enable AWS Config recording in all accounts via CloudFormation StackSets
- Deploy the CIS conformance pack to all accounts using StackSets
- Set up a Config aggregator in the security account for organization-wide visibility
- Configure auto-remediation for safe-to-fix rules (public S3, unencrypted volumes)
- Create EventBridge rules to alert on new NON_COMPLIANT evaluations
- Build a weekly compliance report aggregating scores across all accounts
- Store Config snapshots in S3 with lifecycle policies for audit retention
Pitfalls: Config recording incurs costs per configuration item recorded. In accounts with many resources, costs can be significant. Use targeted recording groups to focus on compliance-relevant resource types rather than recording all resources. Auto-remediation of network rules (security groups) can disrupt applications if the rule was intentionally permissive.
Output Format
AWS Config Compliance Report
===============================
Organization: Acme Financial (30 accounts)
Framework: CIS AWS Foundations 1.4
Report Date: 2026-02-23
Config Rules Active: 48
COMPLIANCE SUMMARY:
Overall Compliance: 87%
Compliant Resources: 4,234
Non-Compliant Resources: 612
Not Applicable: 189
TOP NON-COMPLIANT RULES:
encrypted-volumes: 89 resources (14 accounts)
vpc-flow-logs-enabled: 67 resources (12 accounts)
mfa-enabled-for-iam-console: 45 resources (8 accounts)
s3-bucket-ssl-requests-only: 34 resources (6 accounts)
restricted-ssh: 28 resources (5 accounts)
AUTO-REMEDIATION (Last 30 Days):
Public S3 buckets remediated: 12
Security groups restricted: 8
EBS default encryption enabled: 6
Total auto-remediated: 26
Failed remediation attempts: 3
ACCOUNT COMPLIANCE RANKING:
1. prod-core (account-001): 96% compliant
2. prod-data (account-002): 94% compliant
...
30. dev-sandbox (account-030): 68% compliantReferences and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.3 KB
API Reference: Implementing AWS Config Rules for Compliance
Libraries
boto3 -- AWS Config Service
- Install:
pip install boto3 - Docs: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/config.html
Key Methods
| Method | Description |
|---|---|
put_configuration_recorder() |
Create/update Config recorder |
start_configuration_recorder() |
Start recording configurations |
put_delivery_channel() |
Configure S3 delivery channel |
put_config_rule() |
Deploy a managed or custom Config rule |
get_compliance_summary_by_config_rule() |
Aggregate compliance counts |
get_compliance_details_by_config_rule() |
Non-compliant resources per rule |
put_remediation_configurations() |
Set up auto-remediation actions |
put_configuration_aggregator() |
Multi-account compliance aggregation |
describe_config_rules() |
List all deployed Config rules |
get_aggregate_compliance_details_by_config_rule() |
Cross-account compliance |
Managed Rule Source Identifiers
| Rule | SourceIdentifier |
|---|---|
| S3 public read | S3_BUCKET_PUBLIC_READ_PROHIBITED |
| S3 encryption | S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED |
| IAM root key | IAM_ROOT_ACCESS_KEY_CHECK |
| MFA console | MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS |
| SSH restricted | INCOMING_SSH_DISABLED |
| VPC flow logs | VPC_FLOW_LOGS_ENABLED |
| RDS encrypted | RDS_STORAGE_ENCRYPTED |
| EBS encrypted | ENCRYPTED_VOLUMES |
| CloudTrail on | CLOUD_TRAIL_ENABLED |
SSM Remediation Documents
| Document | Purpose |
|---|---|
AWS-DisableS3BucketPublicReadWrite |
Block public S3 access |
AWS-EnableEBSEncryptionByDefault |
Enable EBS encryption |
AWS-DisablePublicAccessForSecurityGroup |
Remove 0.0.0.0/0 rules |
Conformance Packs
- CIS AWS Foundations Benchmark:
Operational-Best-Practices-for-CIS - PCI DSS:
Operational-Best-Practices-for-PCI-DSS - NIST 800-53:
Operational-Best-Practices-for-NIST-800-53-rev5
External References
- AWS Config Rules List: https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html
- Config Conformance Packs: https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html
- Config Remediation: https://docs.aws.amazon.com/config/latest/developerguide/remediation.html
Scripts 1
agent.py6.8 KB
#!/usr/bin/env python3
"""AWS Config compliance monitoring agent using boto3."""
import json
import sys
import argparse
from datetime import datetime
try:
import boto3
from botocore.exceptions import ClientError
except ImportError:
print("Install boto3: pip install boto3")
sys.exit(1)
MANAGED_RULES = {
"s3-bucket-public-read-prohibited": "S3_BUCKET_PUBLIC_READ_PROHIBITED",
"s3-bucket-server-side-encryption-enabled": "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED",
"s3-bucket-ssl-requests-only": "S3_BUCKET_SSL_REQUESTS_ONLY",
"iam-root-access-key-check": "IAM_ROOT_ACCESS_KEY_CHECK",
"mfa-enabled-for-iam-console-access": "MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS",
"restricted-ssh": "INCOMING_SSH_DISABLED",
"vpc-flow-logs-enabled": "VPC_FLOW_LOGS_ENABLED",
"rds-storage-encrypted": "RDS_STORAGE_ENCRYPTED",
"encrypted-volumes": "ENCRYPTED_VOLUMES",
"cloudtrail-enabled": "CLOUD_TRAIL_ENABLED",
"iam-password-policy": "IAM_PASSWORD_POLICY",
}
def get_config_client(region="us-east-1"):
"""Create AWS Config client."""
return boto3.client("config", region_name=region)
def check_recorder_status(client):
"""Verify AWS Config recorder is running."""
try:
recorders = client.describe_configuration_recorder_status()
for r in recorders.get("ConfigurationRecordersStatus", []):
return {"name": r["name"], "recording": r["recording"],
"lastStatus": r.get("lastStatus", "Unknown")}
except ClientError as e:
return {"error": str(e)}
return {"error": "No recorder found"}
def deploy_managed_rules(client, rules=None):
"""Deploy AWS-managed Config rules for CIS compliance."""
if rules is None:
rules = MANAGED_RULES
deployed = []
for rule_name, source_id in rules.items():
try:
client.put_config_rule(ConfigRule={
"ConfigRuleName": rule_name,
"Source": {"Owner": "AWS", "SourceIdentifier": source_id}
})
deployed.append({"rule": rule_name, "status": "deployed"})
except ClientError as e:
deployed.append({"rule": rule_name, "status": "error", "message": str(e)})
return deployed
def get_compliance_summary(client):
"""Get compliance summary across all Config rules."""
try:
response = client.get_compliance_summary_by_config_rule()
summary = response.get("ComplianceSummary", {})
compliant = summary.get("CompliantResourceCount", {}).get("CappedCount", 0)
non_compliant = summary.get("NonCompliantResourceCount", {}).get("CappedCount", 0)
return {"compliant": compliant, "non_compliant": non_compliant,
"total": compliant + non_compliant,
"compliance_pct": round(compliant / max(compliant + non_compliant, 1) * 100, 1)}
except ClientError as e:
return {"error": str(e)}
def get_non_compliant_resources(client, rule_name):
"""List non-compliant resources for a specific rule."""
try:
response = client.get_compliance_details_by_config_rule(
ConfigRuleName=rule_name, ComplianceTypes=["NON_COMPLIANT"], Limit=25)
resources = []
for result in response.get("EvaluationResults", []):
qual = result.get("EvaluationResultIdentifier", {}).get("EvaluationResultQualifier", {})
resources.append({
"resource_type": qual.get("ResourceType"),
"resource_id": qual.get("ResourceId"),
"annotation": result.get("Annotation", ""),
"timestamp": str(result.get("ResultRecordedTime", ""))
})
return resources
except ClientError as e:
return [{"error": str(e)}]
def configure_remediation(client, rule_name, ssm_document, params):
"""Set up auto-remediation for a Config rule."""
try:
client.put_remediation_configurations(RemediationConfigurations=[{
"ConfigRuleName": rule_name,
"TargetType": "SSM_DOCUMENT",
"TargetId": ssm_document,
"Parameters": params,
"Automatic": True,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60,
}])
return {"rule": rule_name, "remediation": ssm_document, "status": "configured"}
except ClientError as e:
return {"rule": rule_name, "status": "error", "message": str(e)}
def run_compliance_audit(region="us-east-1"):
"""Run a full compliance audit and generate report."""
client = get_config_client(region)
print(f"\n{'='*60}")
print(f" AWS CONFIG COMPLIANCE AUDIT")
print(f" Region: {region}")
print(f" Generated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC")
print(f"{'='*60}\n")
recorder = check_recorder_status(client)
print(f"--- CONFIG RECORDER ---")
print(f" Status: {'RECORDING' if recorder.get('recording') else 'STOPPED'}")
print(f" Last Status: {recorder.get('lastStatus', 'N/A')}\n")
summary = get_compliance_summary(client)
print(f"--- COMPLIANCE SUMMARY ---")
print(f" Compliant: {summary.get('compliant', 0)}")
print(f" Non-Compliant: {summary.get('non_compliant', 0)}")
print(f" Compliance: {summary.get('compliance_pct', 0)}%\n")
print(f"--- NON-COMPLIANT DETAILS ---")
try:
rules_resp = client.describe_config_rules()
for rule in rules_resp.get("ConfigRules", []):
name = rule["ConfigRuleName"]
resources = get_non_compliant_resources(client, name)
if resources and not resources[0].get("error"):
print(f" Rule: {name} ({len(resources)} non-compliant)")
for r in resources[:3]:
print(f" - {r['resource_type']}: {r['resource_id']}")
except ClientError as e:
print(f" Error listing rules: {e}")
print(f"\n{'='*60}\n")
return {"recorder": recorder, "summary": summary}
def main():
parser = argparse.ArgumentParser(description="AWS Config Compliance Agent")
parser.add_argument("--region", default="us-east-1", help="AWS region")
parser.add_argument("--deploy-rules", action="store_true", help="Deploy managed Config rules")
parser.add_argument("--audit", action="store_true", help="Run compliance audit")
parser.add_argument("--output", help="Save report to JSON file")
args = parser.parse_args()
if args.deploy_rules:
client = get_config_client(args.region)
results = deploy_managed_rules(client)
for r in results:
print(f" [{r['status']}] {r['rule']}")
elif args.audit:
report = run_compliance_audit(args.region)
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
else:
parser.print_help()
if __name__ == "__main__":
main()