Setting Up AWS Governance with Terraform
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:
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!