AWS Config Conformance Packs: Continuous Compliance Guards for Coding-Agent Accounts

2 views

Agents that can create infrastructure will create interesting infrastructure. A single “temporary” public artifact bucket or Action:"*" tool role is enough to ruin a quarter. AWS Config Conformance Packs bundle Config rules (and optional remediation) into a versioned pack you deploy per account/OU — so encryption, public-access blocks, and IAM hygiene stay evaluated every change, not once a year in an audit spreadsheet. Pair with CloudFormation Hooks to fail closed at deploy time and Security Hub to aggregate findings.

⚡ TL;DR: Enable Config recording in every coding-agent account; deploy a conformance pack (Operational Best Practices + your custom agent rules) to the OU; tag agent resources workload=coding-agent; wire noncompliance to EventBridge → ticket/Slack; optional SSM remediation for safe autos. Related: GuardDuty compromised credentials, S3 Object Lock artifacts, VPC Lattice tool auth.

Hooks vs SCPs vs Conformance Packs

Control When it fires Strength
CFN Hooks Before create/update via CloudFormation/CDK Prevent specific bad templates
SCPs Every API call (org ceiling) Hard deny classes of actions
Config Conformance Packs Continuous evaluation of resource state Detect drift + report + remediate
Security Hub Aggregates findings Prioritize / assign

Use all three layers. Packs catch drift after a Break Glass console click that Hooks never saw.

Baseline pack for coding-agent OUs

bash
# ✅ ensure Config recorder + delivery channel exist (per account)
aws configservice put-configuration-recorder \
  --configuration-recorder name=default,roleARN=arn:aws:iam::111122223333:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig \
  --recording-group allSupported=true,includeGlobalResourceTypes=true

aws configservice put-delivery-channel \
  --delivery-channel name=default,s3BucketName=org-config-snapshot-111122223333

aws configservice start-configuration-recorder --configuration-recorder-name default
bash
# ✅ deploy a conformance pack from a template URL or local YAML
aws configservice put-conformance-pack \
  --conformance-pack-name coding-agent-baseline \
  --template-body file://coding-agent-conformance-pack.yaml \
  --delivery-s3-bucket org-config-snapshot-111122223333
yaml
# ✅ coding-agent-conformance-pack.yaml (illustrative managed + custom rules)
Resources:
  S3PublicReadProhibited:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: agent-s3-public-read-prohibited
      Source:
        Owner: AWS
        SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED

  S3SslRequestsOnly:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: agent-s3-ssl-only
      Source:
        Owner: AWS
        SourceIdentifier: S3_BUCKET_SSL_REQUESTS_ONLY

  EncryptedVolumes:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: agent-encrypted-volumes
      Source:
        Owner: AWS
        SourceIdentifier: ENCRYPTED_VOLUMES

  IamUserMfa:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: agent-root-mfa
      Source:
        Owner: AWS
        SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED

  # Custom: tool roles must not allow iam:PassRole to *
  AgentNoWildcardPassRole:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: agent-no-wildcard-passrole
      Source:
        Owner: CUSTOM_LAMBDA
        SourceDetails:
          - EventSource: aws.config
            MessageType: ConfigurationItemChangeNotification
            MaximumExecutionFrequency: TwentyFour_Hours
        # SourceIdentifier set to your custom rule Lambda ARN in real packs

❌ Copy-pasting the entire CIS pack into a sandbox OU without exclusions — you will drown in noise from intentionally ephemeral agent resources. Scope with tags and resource types.

Custom rule: deny wildcard tool roles

python
# ✅ Config custom rule Lambda — NON_COMPLIANT if IAM policy has Action "*"
import json
import boto3

config = boto3.client("config")
iam = boto3.client("iam")

def evaluate(role_name: str) -> str:
    pols = iam.list_attached_role_policies(RoleName=role_name)["AttachedPolicies"]
    for p in pols:
        doc = iam.get_policy_version(
            PolicyArn=p["PolicyArn"],
            VersionId=iam.get_policy(PolicyArn=p["PolicyArn"])["Policy"]["DefaultVersionId"],
        )["PolicyVersion"]["Document"]
        if isinstance(doc, str):
            doc = json.loads(doc)
        for stmt in doc.get("Statement", []):
            actions = stmt.get("Action", [])
            if isinstance(actions, str):
                actions = [actions]
            if "*" in actions and stmt.get("Effect") == "Allow":
                return "NON_COMPLIANT"
    return "COMPLIANT"

def handler(event, _ctx):
    invoking = event["invokingEvent"]
    if isinstance(invoking, str):
        invoking = json.loads(invoking)
    item = invoking.get("configurationItem") or {}
    if item.get("resourceType") != "AWS::IAM::Role":
        return
    tags = {t["key"]: t["value"] for t in item.get("tags", [])}
    if tags.get("workload") != "coding-agent":
        # ✅ only police agent roles
        annotation = "skipped_non_agent"
        compliance = "NOT_APPLICABLE"
    else:
        compliance = evaluate(item["resourceName"])
        annotation = "wildcard_action" if compliance == "NON_COMPLIANT" else "ok"
    config.put_evaluations(
        Evaluations=[{
            "ComplianceResourceType": item["resourceType"],
            "ComplianceResourceId": item["resourceId"],
            "ComplianceType": compliance,
            "Annotation": annotation,
            "OrderingTimestamp": item["configurationItemCaptureTime"],
        }],
        ResultToken=event["resultToken"],
    )

Alerting and remediation

bash
# ✅ EventBridge rule: Config compliance change → SNS / ticket
aws events put-rule \
  --name coding-agent-config-noncompliant \
  --event-pattern '{
    "source": ["aws.config"],
    "detail-type": ["Config Rules Compliance Change"],
    "detail": {
      "newEvaluationResult": {"complianceType": ["NON_COMPLIANT"]},
      "resourceType": ["AWS::S3::Bucket", "AWS::IAM::Role", "AWS::EC2::SecurityGroup"]
    }
  }'

Optional SSM Automation remediation is great for safe fixes (block public access). Never auto-delete IAM roles your agents still need — page a human.

Production checklist

  • [ ] Config recorder ON in every agent account (including sandboxes)
  • [ ] Conformance pack versioned in git; deployed via StackSets / Pipeline
  • [ ] Custom rules scoped by workload=coding-agent tags
  • [ ] NON_COMPLIANT → EventBridge → on-call within minutes
  • [ ] Hooks block known-bad templates; packs catch drift
  • [ ] Security Hub ingests Config findings for one pane of glass
  • [ ] Exclusions documented (ephemeral FIS experiments, etc.)
  • [ ] Monthly pack review: new managed rules for Bedrock/S3/IAM

FAQ

Q: Is a conformance pack enough without SCPs?
A: No. Packs observe. SCPs prevent org-wide classes of API calls. Agents need both.

Q: How is this different from Security Hub standards?
A: Security Hub can enable standards that create Config rules under the hood. Conformance Packs are how you ship a custom, versioned agent baseline (including custom Lambda rules) as code.

Q: Will packs slow agent deploys?
A: Evaluation is async. Deploy latency comes from Hooks/SCPs — packs add visibility, not a synchronous gate (unless you add a gate in CI that queries compliance).

Related reading

Ship the pack with the OU, tag every agent role, and treat NON_COMPLIANT the way you treat a failing integration test — not a quarterly surprise.

Last updated on October 2, 2026

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.