Skip to main content

Command Palette

Search for a command to run...

Setting Up AWS Governance with Terraform

Published
3 min read

In my last Terraform project, I wanted to see how we can use Terraform to integrate security and governance into our infrastructure. Here is a look at what I built:

Repo link.

Blocking with IAM

The first thing I focused on was setting up strict security policies. It is one thing to say "be secure," but it is much better to enforce it through code.

I implemented an MFA (Multi-Factor Authentication) requirement for deleting S3 objects. It is a simple but powerful safety net. If someone tries to delete a file and they have not authenticated with MFA, AWS simply says no. Here is how that looks in Terraform:

resource "aws_iam_policy" "mfa_delete_policy" {
  name        = "project-mfa-delete-policy"
  description = "Policy that requires MFA to delete S3 objects"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "DenyDeleteWithoutMFA"
        Effect   = "Deny"
        Action   = "s3:DeleteObject"
        Resource = "*"
        Condition = {
          BoolIfExists = {
            "aws:MultiFactorAuthPresent" = "false"
          }
        }
      }
    ]
  })
}

I also added a policy to ensure that data is always encrypted while moving to S3. It denies any upload that does not use a secure connection. This ensures your data isn't exposed in transit.

Securing S3 Buckets

To secure the S3 bucket itself, I set up server-side encryption and public access blocks. This ensures that all data in the bucket is encrypted and that public access is strictly prohibited. Here is the relevant Terraform code:

resource "aws_s3_bucket_server_side_encryption_configuration" "config_bucket_encryption" {
  bucket = aws_s3_bucket.config_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_public_access_block" "config_bucket_public_access" {
  bucket = aws_s3_bucket.config_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

You can customise the encryption settings by checking the official documentation. Restricting public access is a critical step for protecting your data.

Keeping an Eye on Things with AWS Config

I set up AWS Config to record configuration changes for all supported AWS resources, including global resources, using a specific IAM role for permissions. The recorded data is sent to an S3 bucket, ensuring that all tracked changes are stored securely. Here is the Terraform configuration:

resource "aws_config_configuration_recorder" "main" {
  name     = "${var.project_name}-recorder"
  role_arn = aws_iam_role.config_role.arn

  recording_group {
    all_supported                 = true
    include_global_resource_types = true
  }
}

resource "aws_config_delivery_channel" "main" {
  name           = "${var.project_name}-delivery-channel"
  s3_bucket_name = aws_s3_bucket.config_bucket.bucket
  depends_on     = [aws_config_configuration_recorder.main]
}

resource "aws_config_configuration_recorder_status" "main" {
  name       = aws_config_configuration_recorder.main.name
  is_enabled = true
  depends_on = [aws_config_delivery_channel.main]
}

Enforcing Compliance with AWS Config Rules

I set up a few global compliance rules to monitor the environment continuously. For example, I wanted to make sure that no S3 bucket is ever set to "public write" and that all EBS volumes are encrypted. Setting up a rule for S3 public access looks like this:

resource "aws_config_config_rule" "s3_public_write_prohibited" {
  name = "s3-bucket-public-write-prohibited"

  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_PUBLIC_WRITE_PROHIBITED"
  }
}

I even added a rule to check for tags. If an EC2 instance or an S3 bucket is missing tags like "Environment" or "Owner," AWS Config flags it. This is a lifesaver for governance when you need to know who owns what and which environment a resource belongs to.

Why This Matters

By the end of this project, I had a system that doesn't just build resources but also watches over them.

  • If someone forgets to encrypt a volume, AWS Config will let me know.

  • If someone tries to delete a critical file without MFA, the policy stops them.

  • If a new bucket is created without the right tags, I can see it immediately in the compliance dashboard.

Moving from "just building" to "building with governance" is a huge step toward professional cloud management. It gives you peace of mind knowing that your code is acting as a constant watchdog for your infrastructure.


Video reference:


Arigato!

More from this blog

Code Companions

32 posts