Skip to main content

Command Palette

Search for a command to run...

End-to-End AWS Config Governance System using Terraform

Published
4 min read
End-to-End AWS Config Governance System using Terraform

As I progress in my Terraform learning journey, I’ve moved beyond just creating EC2s and S3 buckets. Today’s learning was about governance — how AWS continuously monitors resources, enforces security rules, and stores compliance evidence automatically.

This blog documents exactly what I built, how the full AWS Config system works together.

This is not theory — it’s a real working setup, written in Terraform.

What Problem Are We Solving?

In a real AWS account:

  • Developers create resources

  • Changes happen daily

  • Mistakes happen (public S3, no encryption, missing MFA)

The problem:

How do we continuously watch the account and verify security rules without humans checking manually?

The answer:
👉 AWS Config

Terraform helps us install and wire this monitoring system once, and AWS Config does the rest.

High-Level Architecture

Before jumping into code, here’s the mental model:

AWS Resources
   ↓
Configuration Recorder (watches changes)
   ↓
Config Rules (check compliance)
   ↓
Delivery Channel
   ↓
Secure S3 Bucket (stores logs & results)

Now let’s break this down resource by resource.

Part 1: Secure S3 Bucket (Foundation of AWS Config)

AWS Config needs a place to store:

  • Configuration history

  • Compliance results

  • Audit evidence

That place is S3.

S3 Bucket

resource "aws_s3_bucket" "example" {
  bucket = "my-governance-test-bucket-${random_string.name.result}"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

This bucket is not just storage — it’s an audit locker.

Bucket Policy – Who Can Access the Locker?

resource "aws_s3_bucket_policy" "config_bucket_policy" {
  bucket = aws_s3_bucket.example.id

This policy does four important things:


Allow AWS Config to check bucket permissions

Action: s3:GetBucketAcl

AWS Config verifies:

“Can I safely store logs here?”


Allow AWS Config to list bucket

Action: s3:ListBucket

Required before writing objects.


Allow AWS Config to PUT objects

Action: s3:PutObject
Condition: bucket-owner-full-control

Ensures:

  • AWS owns the data

  • No cross-account ownership issues


Deny non-HTTPS access

"aws:SecureTransport": false

This denies:

  • HTTP uploads

  • Insecure traffic

Even admins are blocked.

PART 2: IAM Role – Giving AWS Config an Identity

AWS services cannot act without identity.

So we create an IAM Role.

IAM Role for AWS Config

resource "aws_iam_role" "config_role" {
  name = "config-role"

The trust policy says:

Service: config.amazonaws.com

Meaning:

“AWS Config is allowed to assume this role.”

This answers:
WHO is allowed to act?


AWS Managed Policy Attachment

policy_arn = "arn:aws:iam::aws:policy/service-role/AWS_ConfigRole"

This gives AWS Config:

  • Permission to read AWS resources

  • Permission to evaluate configurations

  • Permission to describe services

This is mandatory.


Custom Inline Policy (S3 Access)

resource "aws_iam_role_policy" "config_s3_policy" {

Why this is needed:

  • Bucket policy controls who can access the bucket

  • IAM policy controls what AWS Config itself is allowed to do

AWS requires both to allow the action.

This is defense in depth.

PART 3: Configuration Recorder – The Camera

resource "aws_config_configuration_recorder" "foo" {

This tells AWS Config:

  • Which role to use

  • Which resources to watch

recording_group {
  all_supported = true
  include_global_resource_types = true
}

Meaning:

  • Track everything

  • Include IAM, root, global resources

Without this:
AWS Config has no idea what to record

PART 4: Delivery Channel – The Pipe

resource "aws_config_delivery_channel" "foo" {

This connects:

Recorder → S3 Bucket

Without delivery channel:

  • AWS Config records data

  • But has nowhere to store it

  • Service fails

PART 5: Recorder Status – Power Button

resource "aws_config_configuration_recorder_status" "foo" {
  is_enabled = true
}

This literally:

Turns AWS Config ON

PART 6: Config Rules – The Brain

Rules define:

“What is good?”
“What is bad?”

Encryption Rule

S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED

Checks:

  • Is encryption enabled?

  • Marks bucket compliant or not

Public Access Rules

S3_BUCKET_PUBLIC_READ_PROHIBITED
S3_BUCKET_PUBLIC_WRITE_PROHIBITED

Detects accidental exposure.

Root MFA Rule

ROOT_ACCOUNT_MFA_ENABLED

Ensures:

  • Root account is protected

Required Tags Rule

REQUIRED_TAGS

Enforces:

  • Resource hygiene

  • Ownership

  • Cost tracking

Scoped only to:

AWS::S3::Bucket

PART 7: Checking Compliance in AWS Console (Real-World Validation)

After all Terraform resources are applied, the real power of AWS Config is visible inside the AWS Console.

Now do this 👇

  1. Go to AWS Console

  2. Search for AWS Config

  3. Open Rules or Compliance dashboard

Here, you will clearly see:

  • Which rules are Compliant

  • Which rules are Non-Compliant

  • The exact AWS resource causing the violation

📺 Video That Helped Me Understand this concept:

Final Learning Outcome

This project taught me that:

Terraform + AWS Config = automated governance

I didn’t just deploy infrastructure —
I deployed continuous security enforcement.

This is exactly how real production AWS accounts are managed.