Configure Custom AWS Config Rules
AWS Config rules evaluate resource configurations for compliance. While AWS provides many managed rules, you may need custom rules for organization-specific requirements. This tutorial covers creating and deploying custom Config rules.
Overview
AWS Config supports two types of rules:
| Type | Description | Use Case |
|---|---|---|
| Managed Rules | AWS-provided, ready to use | Standard compliance checks |
| Custom Rules | User-defined using Lambda | Organization-specific requirements |
Prerequisites
- AWS Config deployed — Follow the AWS Config setup guide
- Conformance packs configured — Organization-level Config enabled
- Lambda permissions — Ability to deploy Lambda functions (for custom rules)
Using AWS Managed Rules
AWS provides 300+ managed rules for common compliance scenarios.
Add Managed Rules to Conformance Pack
1 Create Custom Conformance Pack File
Create a conformance pack YAML file in your component directory:
# components/terraform/aws-config/conformance-packs/custom-security-pack.yaml
Resources:
S3BucketPublicReadProhibited:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-public-read-prohibited
Description: Checks that S3 buckets do not allow public read access
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
S3BucketSSLRequestsOnly:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-ssl-requests-only
Description: Checks that S3 bucket policies require SSL
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SSL_REQUESTS_ONLY
Scope:
ComplianceResourceTypes:
- AWS::S3::Bucket
RDSEncryptionEnabled:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: rds-storage-encrypted
Description: Checks that RDS instances have encryption enabled
Source:
Owner: AWS
SourceIdentifier: RDS_STORAGE_ENCRYPTED
Scope:
ComplianceResourceTypes:
- AWS::RDS::DBInstance
IAMPasswordPolicy:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: iam-password-policy
Description: Checks that IAM password policy meets requirements
Source:
Owner: AWS
SourceIdentifier: IAM_PASSWORD_POLICY
InputParameters:
RequireUppercaseCharacters: "true"
RequireLowercaseCharacters: "true"
RequireSymbols: "true"
RequireNumbers: "true"
MinimumPasswordLength: "14"
PasswordReusePrevention: "24"
MaxPasswordAge: "90"
2 Reference in Stack Configuration
Add the custom conformance pack to your AWS Config stack:
# stacks/catalog/aws-config/organization.yaml
components:
terraform:
aws-config:
vars:
default_scope: organization
conformance_packs:
# AWS-managed CIS pack
- name: CIS-AWS-v1.4-Level2
conformance_pack: "https://raw.githubusercontent.com/awslabs/aws-config-rules/master/aws-config-conformance-packs/Operational-Best-Practices-for-CIS-AWS-v1.4-Level2.yaml"
parameter_overrides: {}
# Custom pack from local file
- name: Custom-Security-Pack
conformance_pack: "conformance-packs/custom-security-pack.yaml"
scope: organization
parameter_overrides: {}
3 Deploy the Configuration
Apply the AWS Config changes:
atmos terraform apply aws-config -s core-ue1-root
Creating Custom Lambda Rules
For requirements not covered by managed rules, create custom rules with Lambda.
Example: Require Specific Tags
1 Create Lambda Function
Create a Lambda function to check for required tags:
# lambda/config-rules/required-tags/handler.py
import json
import boto3
def lambda_handler(event, context):
"""Check that resources have required tags."""
config = boto3.client('config')
# Parse the invoking event
invoking_event = json.loads(event['invokingEvent'])
configuration_item = invoking_event['configurationItem']
# Get rule parameters
rule_parameters = json.loads(event.get('ruleParameters', '{}'))
required_tags = rule_parameters.get('requiredTags', 'Environment,Owner,CostCenter').split(',')
# Get resource tags
resource_tags = configuration_item.get('tags', {})
tag_keys = list(resource_tags.keys())
# Check for missing required tags
missing_tags = [tag for tag in required_tags if tag not in tag_keys]
if missing_tags:
compliance_type = 'NON_COMPLIANT'
annotation = f'Missing required tags: {", ".join(missing_tags)}'
else:
compliance_type = 'COMPLIANT'
annotation = 'All required tags present'
# Report evaluation result
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
}
2 Deploy Lambda Function
Deploy the Lambda function using Terraform:
# components/terraform/config-rules-lambda/main.tf
resource "aws_lambda_function" "required_tags" {
function_name = "${var.namespace}-config-required-tags"
role = aws_iam_role.config_rule_lambda.arn
handler = "handler.lambda_handler"
runtime = "python3.11"
timeout = 60
filename = data.archive_file.required_tags.output_path
source_code_hash = data.archive_file.required_tags.output_base64sha256
}
resource "aws_lambda_permission" "config" {
statement_id = "AllowConfigInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.required_tags.function_name
principal = "config.amazonaws.com"
}
3 Create Custom Config Rule
Add the custom rule to your conformance pack:
# conformance-packs/custom-tagging-pack.yaml
Resources:
RequiredTagsRule:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: required-tags-check
Description: Checks that resources have required tags
Source:
Owner: CUSTOM_LAMBDA
SourceIdentifier: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${Namespace}-config-required-tags"
SourceDetails:
- EventSource: aws.config
MessageType: ConfigurationItemChangeNotification
Scope:
ComplianceResourceTypes:
- AWS::EC2::Instance
- AWS::RDS::DBInstance
- AWS::S3::Bucket
InputParameters:
requiredTags: "Environment,Owner,CostCenter"
Common Rule Patterns
Check S3 Encryption
S3BucketServerSideEncryptionEnabled:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-server-side-encryption-enabled
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED
Check EBS Encryption
EBSEncryptionByDefault:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: ec2-ebs-encryption-by-default
Source:
Owner: AWS
SourceIdentifier: EC2_EBS_ENCRYPTION_BY_DEFAULT
Check VPC Flow Logs
VPCFlowLogsEnabled:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: vpc-flow-logs-enabled
Source:
Owner: AWS
SourceIdentifier: VPC_FLOW_LOGS_ENABLED
InputParameters:
trafficType: ALL
Check Root Account MFA
RootAccountMFAEnabled:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: root-account-mfa-enabled
Source:
Owner: AWS
SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED
Remediating Non-Compliant Resources
Automatic Remediation
Configure automatic remediation actions:
# Add to conformance pack
S3BucketPublicReadProhibited:
Type: AWS::Config::ConfigRule
Properties:
ConfigRuleName: s3-bucket-public-read-prohibited
Source:
Owner: AWS
SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED
S3PublicReadRemediation:
Type: AWS::Config::RemediationConfiguration
Properties:
ConfigRuleName: s3-bucket-public-read-prohibited
TargetType: SSM_DOCUMENT
TargetId: AWS-DisableS3BucketPublicReadWrite
Parameters:
S3BucketName:
ResourceValue:
Value: RESOURCE_ID
Automatic: true
MaximumAutomaticAttempts: 3
RetryAttemptSeconds: 60
Manual Remediation
Query non-compliant resources and remediate:
# List non-compliant resources
aws configservice get-compliance-details-by-config-rule \
--config-rule-name s3-bucket-public-read-prohibited \
--compliance-types NON_COMPLIANT \
--region us-east-1
# Get remediation status
aws configservice describe-remediation-execution-status \
--config-rule-name s3-bucket-public-read-prohibited \
--region us-east-1
Troubleshooting
Rule Not Evaluating
If rules aren't evaluating resources:
- Verify the resource type is in the rule's scope
- Check that Config recorder is enabled for the resource type
- Review Lambda function logs (for custom rules)
# Check recorder status
aws configservice describe-configuration-recorder-status --region us-east-1
# Check rule evaluation
aws configservice describe-config-rule-evaluation-status \
--config-rule-names s3-bucket-public-read-prohibited \
--region us-east-1
Lambda Errors
For custom Lambda rules, check CloudWatch Logs:
aws logs filter-log-events \
--log-group-name "/aws/lambda/<function-name>" \
--filter-pattern "ERROR" \
--region us-east-1
See Also
- AWS Config - Complete Config documentation
- AWS Security Hub - View Config compliance findings
- Setup Guide - Complete deployment instructions