Home› Blog› Week 12 - AWS Config Compliance Automation: The Dr…
AWS Weekly Lab AWS Terraform

AWS Config Compliance Automation: The Drift Security Hub Never Sees

Security Hub (Week 11) is very good at catching security misconfigurations. It has no concept of a missing cost-allocation tag or a data bucket that was never versioned — those aren't security findings, so nothing watches for them. This week closes that gap with a self-contained AWS Config conformance pack: two rules auto-remediate through AWS-managed SSM documents, one is deliberately notify-only because a tag value can't be safely invented, and a daily Lambda digest reports on all three. Along the way, the account's Config recorder vanished mid-build — not from anything this stack did — and that turned into the week's real lesson.

AWS Platform Engineering Lab · Week 12

Lab Overview

Security Hub's FSBP standard checks roughly 300 controls, and by Week 11 it already covered nearly every security-relevant misconfiguration in this account — open ports, public buckets, disabled encryption defaults.

The problem. It has no concept of governance drift. A bucket created without a cost-center tag, or one that was never versioned, is not a security finding — Security Hub simply has no control for either. Nothing watches for it. That kind of drift does not announce itself; it accumulates quietly until a cost-allocation report has a chunk of unattributed spend, or until someone deletes an object from an unversioned bucket and there is no previous version to recover.

The objective. A conformance pack that evaluates governance rules continuously, auto-remediates the safe ones through AWS-managed automation, and reports the rest to a human daily.

The outcome. It works — and produced an unusually dense run of real bugs, none of which terraform validate or the documentation caught.

DifficultyAdvanced
Lab runtimeNot recorded
CostEstimated — roughly $1–5/month, and the recorder is the line that matters
DeploymentTerraform via HCP Terraform with OIDC
Full lab guideGitHub — prerequisites, Terraform, commands, validation, cleanup

Cloud Services and Concepts

ServicePurpose in this lab
AWS ConfigRecords configuration changes for every supported resource type, continuously, account-wide. The recorder is the foundation — and the billing line.
Conformance packA self-contained bundle of three rules. It defines its rules rather than wrapping externally-created ones.
SSM AutomationThe remediation substrate. AWS-managed documents, not custom code.
AWS Lambda + EventBridgeA scheduled reporter that reads the pack's own compliance status daily.
SNS + SQSThe digest to a human inbox, and a dead-letter queue so a failed report is never silent.

Governance drift is not a security finding. That distinction is the whole week: Security Hub answers "is this dangerous", Config answers "is this how we said it should be". The second question has no owner unless you give it one.

Config's Scope is either-or. Resource-type filtering and tag filtering cannot combine in one rule. When you need both a type and a tag constraint, scope on the tag alone and let the rule's own logic handle the type.

Architecture and Workflow

Week 12 architecture: a Config recorder feeds a conformance pack of 3 rules; two auto-remediate via SSM Automation to S3, one notifies via a daily Lambda digest to SNS AWS Config Recorder Records all resource types this Lab's own, since Jul 2026 Conformance Pack — week12-cfgcompliance-pack self-contained: defines its own rules, no standalone Config-rule resources required-tags environment / owner / cost-center scope: broad (no tag filter) notify only s3-bucket-versioning-enabled scope: tag auto-remediate=true not covered by Security Hub FSBP auto-remediate s3-bucket-sse-enabled scope: tag auto-remediate=true not covered by Security Hub FSBP auto-remediate daily read, all 3 rules auto-fix (2 rules) compliance_reporter daily EventBridge schedule discovers rules via the pack SNS Digest Topic plain-text summary, all 3 rules Subscribed Inbox confirmed email subscription SSM Automation AWS-Configure/EnableS3Bucket* AWS-managed, not custom code S3 Bucket versioning + SSE enabled tagged auto-remediate=true notify-only (no auto-fix) tag-scoped auto-remediate
  1. An AWS Config recorder captures configuration changes for every supported resource type, continuously and account-wide.
  2. A conformance pack containing three rules evaluates against those configuration items.
  3. required-tags checks everything broadly and is notify-only — it never invents a value.
  4. Two S3 rules evaluate only buckets carrying auto-remediate=true, and auto-remediate through SSM Automation when they fail.
  5. Remediation runs an AWS-managed SSM document, verified live against this account before use.
  6. A scheduled Lambda reads the pack's own compliance status daily and emails a digest — scoped to these three rules, never the account's other ~300.
  7. A failed reporter invocation lands in a 14-day dead-letter queue that alarms.

Design decisions

Tag-scoped opt-in, enforced by Config itself. An untagged bucket is never flagged non-compliant, so remediation never fires for it. No custom code decides this — the scope is the control.

Notify, never invent. required-tags does not auto-tag. A human has to supply the actual cost-center value; automation only reports what is missing.

A conformance pack, not standalone rules. A pack is self-contained. Build standalone Config rules or a pack — never both for the same rule.

Prerequisites

RequirementDetail
AWS accountPermission for Config, S3, SSM, Lambda, EventBridge, SNS, SQS
Terraform>= 1.10
HCP TerraformTwo workspace variables: TFC_AWS_PROVIDER_AUTH=true and TFC_AWS_RUN_ROLE_ARN. Remote runners have no AWS credentials by default
Regionus-east-1

The recorder is the dependency that will surprise you. An account can have exactly one Config recorder. This stack owns it, which means destroying this week also removes the account's only recorder — and anything else relying on Config, Security Hub included, loses its evidence source. Confirm nothing else depends on it before you deploy, and again before you destroy.

"Reuse the centrally-managed recorder" is only safe if you actually control it. During this build an unrelated project's cleanup script deleted the shared recorder mid-apply.

Implementation

A Config recorder and delivery channel, a three-rule conformance pack, an SSM remediation role, and a scheduled reporter with its DLQ and alarm. The lab guide carries the full Terraform and the pack YAML.

week-12-config-compliance-automation/
|
+-- terraform/
|   +-- environments/dev/   HCP backend, OIDC, wires the modules
|   +-- modules/recorder/   Config recorder, delivery channel, S3 bucket
|   +-- modules/pack/       the conformance pack and its three rules
|   +-- modules/reporter/   Lambda, schedule, SNS, DLQ, alarm
|
+-- scripts/                test-bucket creation and teardown checks
Only the directories that matter. The full repository is on GitHub.

Never hardcode a name AWS generates for you. Conformance-pack rule names get a real generated suffix — discover them at runtime rather than writing them down.

AWS Config conformance pack detail page showing 3 rules: required-tags noncompliant, s3-bucket-sse-enabled compliant, s3-bucket-versioning-enabled compliant
One pack, three rules, real compliance status — not INSUFFICIENT_DATA placeholders.

Validation and Evidence

A deployed pack is not an enforcing one. Each rule was tested against a deliberately non-compliant bucket.

TestExpectedActualStatus
Untagged bucketFlagged by required-tagsFlagged, notify-onlyPass
Untagged bucket auto-tagged?No — a human supplies the valueNot taggedPass — by design
Unversioned bucket, opted inRemediated via SSMRemediatedPass
Unversioned bucket, not opted inNever evaluatedNever evaluated — Config scope alonePass
Daily digest reaches a humanEmail, scoped to these 3 rulesDeliveredPass
Tag-scoped IAM guardrail on S3Restricts bucket-level admin actionsSilently does nothingFail — see below
AWS Config rule resources-in-scope table listing EC2 instances, EBS volumes, and S3 buckets all marked noncompliant
Real drift, not a demo: these resources actually exist in the account and actually lack the required tags.
Systems Manager Automation execution detail for AWS-ConfigureS3BucketVersioning showing overall status Success and the ConfigureVersioning step succeeded
The actual remediation call: one step, one API call, Success.
Email titled Week 12 Config Compliance Digest listing 22 non-compliant resources for required-tags and INSUFFICIENT_DATA for the two S3 rules at the time this digest ran
The actual email: real non-compliant resource IDs, not placeholder text. (Captured before the recorder incident below — the two S3 rules hadn't evaluated yet at this point.)

Security and Cost

Security

Tag-scoped opt-in, enforced by Config alone. The two S3 rules only evaluate buckets tagged auto-remediate=true, via Config's native scope. An untagged bucket is never flagged, so remediation never fires for it, and no custom code decides that.

Native remediation substrate, not custom code. Both fixes are AWS-managed SSM Automation documents, verified live against this account before use.

Notify, never invent. required-tags never auto-tags a resource. Automation reports what is missing; a human supplies the value.

No silent failures. Failed reporter invocations land in a 14-day SQS dead-letter queue that alarms to SNS.

The guardrail that did not transfer. A tag-scoped IAM condition works for EC2 security groups and silently does nothing for S3 bucket-level admin actions. Verify per action rather than assuming a pattern carries.

Cost

These are rates and an estimate, not a measurement. No Cost Explorer figure was recorded for this week.

ItemEstimate
Config rule and pack evaluations ($0.001/eval, no free tier)pennies/month at this resource count
Config recorder — configuration items ($0.003/item, continuous, account-wide)~$1–5/month — bills for the whole account's inventory, not just this week's resources
Lambda, EventBridge, SNS, SQSpennies, well within free tier
S3 delivery bucket (90-day lifecycle)pennies

The recorder is the line that matters, and it is the one people forget is account-wide: it bills for every supported resource in the account, not for the handful this week created.

Troubleshooting and Lessons

HCP's remote runners have no AWS credentials by default

Problem. The first plan on a brand-new workspace errored immediately: "No valid credential sources found".
Root cause. HCP's remote execution environment is not running inside the AWS account, so nothing hands it credentials.
Resolution. Two workspace environment variables enable the dynamic-credentials (OIDC) flow: TFC_AWS_PROVIDER_AUTH=true and TFC_AWS_RUN_ROLE_ARN.
Lesson. Obvious in hindsight, and it blocks every first run on a new workspace.

A tag-scoped IAM guardrail does not transfer between services

Problem. An IAM condition that correctly restricts EC2 security-group actions by tag had no effect on S3.
Root cause. S3 bucket-level admin actions do not evaluate the same condition key.
Resolution. Verify the guardrail per action rather than assuming the pattern carries.
Lesson. It fails open and silently — the policy is accepted, and simply does not constrain anything.

The account's only Config recorder was deleted mid-build

Problem. An apply broke because the recorder had vanished.
Root cause. An unrelated project's cleanup script removed the shared recorder. Nothing in this week's Terraform owned it at the time.
Resolution. This stack now owns its recorder outright.
Lesson. "Reuse the centrally-managed recorder" is only safe if you actually control it. This is also what made Week 15 necessary — nothing could say who deleted it.

Never hardcode a name AWS generates

Problem. Remediation could not find its rule.
Root cause. Conformance-pack rule names get a generated suffix.
Resolution. Discover them at runtime.
Lesson. A generated name is not a stable identifier.

Cleanup and Key Takeaways

Queue a destroy plan on week-12-dev in the HCP UI. This removes the conformance pack, the reporter Lambda, its schedule, SNS and DLQ, the SSM automation role — and the recorder itself, since this stack owns the account's only one.

Confirm nothing else depends on it first. Destroying this week takes AWS Config out of the account, and anything using Config as an evidence source loses it. Leftover test buckets clean up separately.

Key takeaways

  • A conformance pack is self-contained. It defines its own rules rather than wrapping externally-created ones — build standalone rules or a pack, never both for the same rule.
  • Config's scope is either-or. Resource type and tag filtering cannot combine in one rule.
  • Never hardcode a name AWS generates for you. Discover it at runtime.
  • A tag-scoped IAM guardrail does not automatically transfer between services. It works for EC2 security groups and silently does nothing for S3 bucket-level admin actions.
  • "Reuse the centrally-managed recorder" is only safe if you control it. Otherwise someone else's cleanup script is in your dependency chain.

References

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent