Home / AWS

AWSHow-toIntermediate

AWS Config non-compliant resources - finding them across accounts and setting up automatic remediation

Use AWS Config to list non-compliant resources per rule and account, query them with advanced queries, and attach SSM Automation remediation, manual first and automatic once proven.

Deepak Bhardwaj3 min read

Applies toAWS Config rules and conformance packs; Config aggregators; AWS Systems Manager Automation; AWS CLI v2

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:

  1. Get an accurate list, by rule and account.
  2. Fix the source: the template, pipeline or default that creates bad resources.
  3. 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