Where to start
AWS Config records resource configurations and evaluates them against rules (managed or custom). Teams often have hundreds of non-compliant results and no plan for them. Approach it in this order:
- Get an accurate list, by rule and account.
- Fix the source: the template, pipeline or default that creates bad resources.
- Remediate existing resources, manually first and automatically once proven.
1. List non-compliant rules and resources
In one account and region:
aws configservice describe-compliance-by-config-rule --compliance-types NON_COMPLIANT \
--query "ComplianceByConfigRules[].ConfigRuleName" --output table
aws configservice get-compliance-details-by-config-rule \
--config-rule-name s3-bucket-server-side-encryption-enabled \
--compliance-types NON_COMPLIANT \
--query "EvaluationResults[].EvaluationResultIdentifier.EvaluationResultQualifier.ResourceId" --output text
Across the organisation, use an aggregator in the delegated admin account:
aws configservice describe-aggregate-compliance-by-config-rules \
--configuration-aggregator-name org-aggregator \
--filters ComplianceType=NON_COMPLIANT \
--query "AggregateComplianceByConfigRules[].{rule:ConfigRuleName,acct:AccountId,region:AwsRegion}" --output table
2. Advanced queries (SQL over the configuration inventory)
Advanced queries search the current configuration of resources, which is useful when no rule exists yet.
aws configservice select-aggregate-resource-config --configuration-aggregator-name org-aggregator \
--expression "SELECT accountId, awsRegion, resourceId, configuration.instanceType
WHERE resourceType = 'AWS::EC2::Instance'
AND configuration.state.name = 'running'"
More examples:
-- Security groups open to the world on SSH
SELECT accountId, resourceId, resourceName
WHERE resourceType = 'AWS::EC2::SecurityGroup'
AND configuration.ipPermissions.fromPort = 22
AND configuration.ipPermissions.ipRanges = '0.0.0.0/0'
-- Unattached EBS volumes
SELECT accountId, awsRegion, resourceId, configuration.size
WHERE resourceType = 'AWS::EC2::Volume' AND configuration.state = 'available'
Advanced query syntax is a subset of SQL. Some operators aren't supported, so check the documentation if a query is rejected.
3. Triage
Export the list and add an owner and a decision per finding:
| Decision | Meaning |
|---|---|
| Fix | Remediate the resource and fix its template |
| Exception | Documented reason and expiry date; tag the resource |
| Rule wrong | Adjust the rule parameters or scope |
Fix the source first. If a Terraform module creates unencrypted buckets, remediating buckets every day doesn't help.
4. Remediation with SSM Automation
Many managed rules have matching AWS-owned automation documents (for example AWS-EnableS3BucketEncryption, AWS-DisablePublicAccessForSecurityGroup). Attach one as manual remediation first:
aws configservice put-remediation-configurations --remediation-configurations '[{
"ConfigRuleName": "s3-bucket-server-side-encryption-enabled",
"TargetType": "SSM_DOCUMENT",
"TargetId": "AWS-EnableS3BucketEncryption",
"Parameters": {
"AutomationAssumeRole": {"StaticValue": {"Values": ["arn:aws:iam::111122223333:role/ConfigRemediationRole"]}},
"BucketName": {"ResourceValue": {"Value": "RESOURCE_ID"}},
"SSEAlgorithm": {"StaticValue": {"Values": ["AES256"]}}
},
"Automatic": false
}]'
Document parameter names differ per document. Check them with aws ssm describe-document --name AWS-EnableS3BucketEncryption --query "Document.Parameters".
Run it for specific resources:
aws configservice start-remediation-execution \
--config-rule-name s3-bucket-server-side-encryption-enabled \
--resource-keys resourceType=AWS::S3::Bucket,resourceId=my-legacy-bucket
aws configservice describe-remediation-execution-status \
--config-rule-name s3-bucket-server-side-encryption-enabled
The remediation role needs permission for the actions in the document, plus a trust policy for ssm.amazonaws.com.
5. Going automatic
Once manual runs succeed and owners agree, set "Automatic": true with retry settings:
"Automatic": true,
"MaximumAutomaticAttempts": 3,
"RetryAttemptSeconds": 60
Warning
Automatic remediation changes production resources without a human in the loop. Start with low-risk, reversible fixes (encryption, logging, tags). Don't auto-remediate things that can cause outages, such as closing security group rules or stopping instances, until the owners have agreed.
6. Conformance packs
Group related rules (for example a CIS or operational best practice pack) and deploy them across the organisation:
aws configservice put-organization-conformance-pack \
--organization-conformance-pack-name baseline \
--template-s3-uri s3://my-config-templates/baseline-pack.yaml
Prevent it next time
- Put preventive controls in front: SCPs, IaC policy checks (cfn-guard, Checkov) in CI, and service-level defaults such as S3 Block Public Access.
- Review compliance weekly per owner, not as one big monthly report.
- Track exceptions with expiry dates.
Checklist
- Aggregator covering all accounts and regions
- Non-compliant list with owners and decisions
- Source templates fixed
- Manual remediation tested per rule
- Automatic remediation only for agreed low-risk rules
- Preventive controls in CI and SCPs