-
-
Notifications
You must be signed in to change notification settings - Fork 216
Feature/iac scaffolding : Foundational Network Module #2310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ional structure and documentation for the new Terraform-based IaC
In this commit I introduced the initial, production-grade Terraform module for the core AWS network infrastructure. Key features of this module include: - Creates a new VPC with public and private subnets across multiple Availability Zones for high availability. - Implements a single, cost-effective, and resilient NAT Gateway for private subnet egress. - Provisions a public Application Load Balancer (ALB) with a secure default configuration and an HTTPS redirect. - Establishes a secure-by-default posture with a locked-down ALB security group.
Summary by CodeRabbit
WalkthroughAdds Terraform pre-commit hooks, a new modular network Terraform module (VPC, subnets, NAT, route tables, ALB with HTTP→HTTPS redirect and optional access logging) with variables and outputs, and a comprehensive Terraform operational guide for multi-environment deployments and remote state. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (6)
.pre-commit-config.yaml (1)
90-100
: Add terraform_docs and prefer types-based matching over regex.
- Add the terraform_docs hook to keep variables/outputs documented and in sync.
- Prefer types_or: [terraform] over files regex to catch all Terraform sources consistently (including nested paths).
Apply this diff:
- repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.92.0 + rev: v1.92.0 hooks: + - id: terraform_docs + args: + - --hook-config=--create-file-if-not-exist=true - id: terraform_fmt - files: \.tf$ + types_or: + - terraform - id: terraform_validate - files: \.tf$ + types_or: + - terraform - id: terraform_tflint - files: \.tf$ + types_or: + - terraform - id: terraform_trivy - files: \.tf$ + types_or: + - terraformTerraform/Operational-Guide.md (1)
18-21
: Fix module path to match repository structure.Doc lists modules/network but the added code resides under modules/01-Network. Align the path or rename for consistency.
Terraform/modules/01-Network/variables.tf (3)
19-23
: Validate vpc_cidr format.Add a simple CIDR validation to catch typos early.
variable "vpc_cidr" { description = "The CIDR block for the VPC." type = string default = "10.0.0.0/16" + validation { + condition = can(cidrhost(var.vpc_cidr, 0)) + error_message = "vpc_cidr must be a valid IPv4 CIDR block." + } }
25-28
: Ensure at least one AZ provided.Add length check to avoid empty lists.
variable "availability_zones" { description = "A list of Availability Zones to deploy resources into. Must match the number of subnets. e.g., [\"us-east-1a\", \"us-east-1b\"]" type = list(string) + validation { + condition = length(var.availability_zones) > 0 + error_message = "At least one availability zone must be provided." + } }
48-52
: Optionally add a toggle for per‑AZ NAT gateways.Expose a boolean to support HA NAT as an opt-in later.
variable "enable_multi_az_nat_gateways" { description = "If true, create a NAT Gateway in each public subnet (higher availability, higher cost)." type = bool default = false }Terraform/modules/01-Network/main.tf (1)
65-73
: Allocate the EIP in VPC scope explicitly.Set domain = "vpc" to ensure correct allocation context for the NAT.
resource "aws_eip" "nat" { - # Only one EIP is needed for the single NAT Gateway. + domain = "vpc" # Ensure EIP is allocated in the VPC scope + # Only one EIP is needed for the single NAT Gateway. tags = merge(
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.pre-commit-config.yaml
(1 hunks)Terraform/Operational-Guide.md
(1 hunks)Terraform/modules/01-Network/main.tf
(1 hunks)Terraform/modules/01-Network/outputs.tf
(1 hunks)Terraform/modules/01-Network/variables.tf
(1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
Terraform/modules/01-Network/main.tf
[medium] 179-195: Ensure that ALB drops HTTP headers
(CKV_AWS_131)
[high] 212-227: Ensure that load balancer is using at least TLS 1.2
(CKV_AWS_103)
🔇 Additional comments (1)
Terraform/modules/01-Network/outputs.tf (1)
1-29
: Outputs look good.Clear and minimal set to enable composition by downstream modules.
Terraform/Operational-Guide.md
Outdated
cd terraform/environments/dev | ||
``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify environment directory path/casing.
Doc uses terraform/environments/dev, while repo paths appear under Terraform/. Ensure the path exists and matches case-sensitive filesystems.
🏁 Script executed:
#!/bin/bash
# Discover environment and module paths (case-insensitive) in repo
fd -i -t d '^environments$' -d 4
fd -i -t d '01-Network' -d 6
Length of output: 53
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Listing Terraform/environments =="
ls -la Terraform/environments || true
echo
echo "== Searching for 'dev' directories under Terraform =="
fd -t d -i dev Terraform -d 4 || true
echo
echo "== Showing Operational-Guide.md around lines 100-120 =="
sed -n '100,120p' Terraform/Operational-Guide.md || true
Length of output: 991
Fix path casing and missing dev
environment in docs
Terraform/Operational-Guide.md (lines 111–113) shows cd terraform/environments/dev
, but the repo has Terraform/environments/
(only .gitkeep
— no dev
directory). Update the doc to use the correct path/casing (e.g., cd Terraform/environments/<env>
) and either document creating the environment directory or add Terraform/environments/dev/
to the repo.
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 111 to 113, the documented path
uses the wrong casing and references a non-existent dev directory; update the
path to use the actual repo casing and a placeholder (e.g., cd
Terraform/environments/<env>) and either add a short step that instructs users
to create the environment directory (mkdir -p Terraform/environments/dev &&
touch Terraform/environments/dev/.gitkeep) or add Terraform/environments/dev/ to
the repository so the example works as written; ensure the text matches the
repository layout and casing consistently.
I'm reviewing all the suggestions now and will push up a new commit with the fixes shortly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (4)
Terraform/Operational-Guide.md (1)
134-139
: Add a concrete remote backend example to avoid local state.Without a backend block, init will default to local state. Provide a sample backend to match the S3/DynamoDB created above.
Add this as backend.tf in the environment directory:
terraform { backend "s3" { bucket = env.TF_STATE_BUCKET key = "owasp-nest/${env.ENVIRONMENT}/terraform.tfstate" region = env.AWS_REGION dynamodb_table = env.TF_STATE_LOCK_TABLE encrypt = true } }Alternatively, document using a backend config file (e.g., -backend-config=backend.hcl).
Terraform/modules/01-Network/variables.tf (1)
60-70
: Expose a few config toggles to avoid hard-coding policy and behavior.Make TLS policy, ALB deletion protection, NAT topology, and ALB log retention configurable.
variable "alb_access_logs_bucket_name" { description = "The name of the S3 bucket to store ALB access logs. Must be globally unique. If left empty, a name will be generated." type = string default = "" } + +variable "alb_ssl_policy" { + description = "SSL policy for the ALB HTTPS listener." + type = string + default = "ELBSecurityPolicy-TLS13-1-2-2021-06" +} + +variable "alb_deletion_protection_enabled" { + description = "Explicitly enable ALB deletion protection. If not set, production is enabled by default in main.tf." + type = bool + default = false +} + +variable "nat_per_az" { + description = "If true, create one NAT Gateway per AZ for higher availability (higher cost). If false, use a single NAT GW." + type = bool + default = false +} + +variable "alb_logs_retention_days" { + description = "Days to retain ALB access logs in S3." + type = number + default = 90 +}Follow-up: wire these variables in main.tf where applicable.
Terraform/modules/01-Network/main.tf (2)
231-233
: Make ALB deletion protection controllable by variable with sane default.Allows overriding in non-prod and forces on in prod by default.
- enable_deletion_protection = var.environment == "prod" ? true : false + enable_deletion_protection = var.alb_deletion_protection_enabled || (var.environment == "prod")
263-269
: LGTM: TLS 1.2/1.3 policy enforced.Updated ssl_policy to a modern policy. Consider sourcing from var.alb_ssl_policy for consistency.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Terraform/Operational-Guide.md
(1 hunks)Terraform/modules/01-Network/main.tf
(1 hunks)Terraform/modules/01-Network/variables.tf
(1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
Terraform/modules/01-Network/main.tf
[medium] 141-154: Ensure that an S3 bucket has a lifecycle configuration
(CKV2_AWS_61)
🔇 Additional comments (6)
Terraform/Operational-Guide.md (1)
49-70
: Good fix: us-east-1 handling + hardened state bucket.Conditional create-bucket for us-east-1, versioning, public access block, and SSE are all correct and align with best practices.
Terraform/modules/01-Network/variables.tf (2)
34-36
: Good validation on public subnet CIDRs vs AZs.Prevents index mismatches at apply time.
43-45
: Good validation on private subnet CIDRs vs AZs.Avoids out-of-range indexing and enforces module contract.
Terraform/modules/01-Network/main.tf (3)
75-89
: Good: clear note on single-NAT SPOF trade-off.Accurately documents availability/cost implications.
223-246
: Ensure provider compatibility for “drop_invalid_header_fields”.Some provider versions require setting this via load_balancer_attributes. If your version errors on the top-level arg, switch to the attribute block below.
resource "aws_lb" "main" { @@ - drop_invalid_header_fields = true + load_balancer_attributes { + key = "routing.http.drop_invalid_header_fields.enabled" + value = "true" + }Please confirm your aws provider version supports the chosen form.
234-238
: Avoid null bucket when logging is disabled.Use a dynamic block so bucket is only referenced when enabled (prevents accidental eval of a zero-count reference).
- access_logs { - bucket = var.enable_alb_access_logs ? aws_s3_bucket.alb_access_logs[0].bucket : null - enabled = var.enable_alb_access_logs - prefix = "alb" - } + dynamic "access_logs" { + for_each = var.enable_alb_access_logs ? [1] : [] + content { + bucket = aws_s3_bucket.alb_access_logs[0].bucket + enabled = true + prefix = "alb" + } + }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
Terraform/modules/01-Network/main.tf (4)
62-64
: Fix misleading resilience claim for single NAT/single RT.Single NAT + single private route table is cost‑optimized, not more resilient. It increases AZ blast radius and adds cross‑AZ egress charges when other AZs traverse the NAT’s AZ.
Apply this diff to correct the comment:
-# We create a SINGLE NAT Gateway and a SINGLE private route table. This is more -# resilient, cost-effective, and simpler to manage than a per-AZ NAT Gateway. +# We create a SINGLE NAT Gateway and a SINGLE private route table. This is more +# cost-effective and simpler to manage than per-AZ NAT Gateways, but less resilient +# (AZ egress SPOF) and may incur cross-AZ data transfer for other AZs.
76-89
: Optional: add per‑AZ NAT support to avoid egress SPOF and cross‑AZ charges.Expose a toggle to create one NAT per AZ and per‑AZ private route tables; keep current single‑NAT as default.
Example (outside this file; minimal sketch):
variable "enable_multi_az_nat" { type = bool, default = false } resource "aws_nat_gateway" "az" { count = var.enable_multi_az_nat ? length(aws_subnet.public) : 0 allocation_id = aws_eip.nat_multi[count.index].id subnet_id = aws_subnet.public[count.index].id depends_on = [aws_internet_gateway.main] tags = merge(var.tags, { Name = "${var.project_prefix}-${var.environment}-nat-gw-${count.index}" }) } resource "aws_route_table" "private_per_az" { count = var.enable_multi_az_nat ? length(aws_subnet.private) : 0 vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.az[count.index].id } tags = merge(var.tags, { Name = "${var.project_prefix}-${var.environment}-private-rt-${count.index}" }) }
31-44
: Validate CIDR/AZ list lengths to prevent index errors.If list lengths diverge, Terraform panics at index access.
Add validations in variables.tf (outside this file):
variable "availability_zones" { type = list(string) validation { condition = length(var.availability_zones) == length(var.public_subnet_cidrs) error_message = "public_subnet_cidrs must match availability_zones length." } validation { condition = length(var.availability_zones) == length(var.private_subnet_cidrs) error_message = "private_subnet_cidrs must match availability_zones length." } }Also applies to: 46-58
108-113
: Use for_each to avoid index coupling on associations.for_each is safer and clearer than count-index ties.
-resource "aws_route_table_association" "public" { - count = length(aws_subnet.public) - subnet_id = aws_subnet.public[count.index].id - route_table_id = aws_route_table.public.id -} +resource "aws_route_table_association" "public" { + for_each = { for s in aws_subnet.public : s.id => s } + subnet_id = each.value.id + route_table_id = aws_route_table.public.id +} @@ -resource "aws_route_table_association" "private" { - count = length(aws_subnet.private) - subnet_id = aws_subnet.private[count.index].id - route_table_id = aws_route_table.private.id -} +resource "aws_route_table_association" "private" { + for_each = { for s in aws_subnet.private : s.id => s } + subnet_id = each.value.id + route_table_id = aws_route_table.private.id +}Also applies to: 132-137
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Terraform/modules/01-Network/main.tf
(1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
Terraform/modules/01-Network/main.tf
[medium] 148-161: Ensure that an S3 bucket has a lifecycle configuration
(CKV2_AWS_61)
[medium] 174-185: Ensure that an S3 bucket has a lifecycle configuration
(CKV2_AWS_61)
🔇 Additional comments (6)
Terraform/modules/01-Network/main.tf (6)
148-161
: Harden ALB logs bucket: SSE, ownership controls, lifecycle.Add SSE-S3, BucketOwnerPreferred, and lifecycle to meet checks and best practices.
resource "aws_s3_bucket" "alb_access_logs" { # Only create this bucket if logging is enabled count = var.enable_alb_access_logs ? 1 : 0 @@ ) } + +resource "aws_s3_bucket_server_side_encryption_configuration" "alb_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.alb_access_logs[0].id + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + } +} + +resource "aws_s3_bucket_ownership_controls" "alb_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.alb_access_logs[0].id + rule { object_ownership = "BucketOwnerPreferred" } +} + +resource "aws_s3_bucket_lifecycle_configuration" "alb_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.alb_access_logs[0].id + rule { + id = "expire-alb-logs" + status = "Enabled" + expiration { days = var.alb_logs_retention_days } + } +}Note: Checkov flags CKV2_AWS_61 for lifecycle. [Based on static analysis hints]
173-185
: Also harden the S3 server access logs bucket.Apply public access block, SSE, ownership, lifecycle to the target logs bucket too.
resource "aws_s3_bucket" "s3_server_access_logs" { count = var.enable_alb_access_logs ? 1 : 0 @@ ) } + +resource "aws_s3_bucket_public_access_block" "s3_server_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.s3_server_access_logs[0].id + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "s3_server_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.s3_server_access_logs[0].id + rule { + apply_server_side_encryption_by_default { sse_algorithm = "AES256" } + } +} + +resource "aws_s3_bucket_ownership_controls" "s3_server_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.s3_server_access_logs[0].id + rule { object_ownership = "BucketOwnerPreferred" } +} + +resource "aws_s3_bucket_lifecycle_configuration" "s3_server_access_logs" { + count = var.enable_alb_access_logs ? 1 : 0 + bucket = aws_s3_bucket.s3_server_access_logs[0].id + rule { + id = "expire-s3-logs" + status = "Enabled" + expiration { days = var.alb_logs_retention_days } + } +}
280-303
: ALB config looks good (HTTPS, deletion protection gating, header hardening).LGTM.
320-326
: TLS policy upgraded to TLS1.2/1.3.Good security posture.
65-73
: Set EIP domain to “vpc” for NAT Gateway.Without domain="vpc", allocation can misbehave in edge cases and fail NAT creation.
resource "aws_eip" "nat" { + domain = "vpc" # Only one EIP is needed for the single NAT Gateway. tags = merge(
196-230
: Fix ALB logs bucket policy (invalid Effect, wrong resource path, missing GetBucketAcl).Effect must be “Allow”. Resource must point to AWSLogs//*, and ALB needs s3:GetBucketAcl. Add ACL condition.
data "aws_iam_policy_document" "alb_access_logs" { count = var.enable_alb_access_logs ? 1 : 0 # This statement allows the ALB service to write logs to the bucket. statement { - effect = "AllowALBToWriteLogs" + sid = "AWSLogDeliveryWrite" + effect = "Allow" actions = ["s3:PutObject"] - resources = ["${aws_s3_bucket.alb_access_logs[0].arn}/*"] + resources = ["${aws_s3_bucket.alb_access_logs[0].arn}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"] principals { type = "AWS" - identifiers = [data.aws_elb_service_account.current.arn] + identifiers = [data.aws_elb_service_account.current.arn] } + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } } - # This statement denies any access to the bucket over insecure HTTP. + # Allow the ALB service to read bucket ACL for delivery checks. + statement { + sid = "AWSLogDeliveryCheck" + effect = "Allow" + actions = ["s3:GetBucketAcl"] + resources = [aws_s3_bucket.alb_access_logs[0].arn] + principals { + type = "AWS" + identifiers = [data.aws_elb_service_account.current.arn] + } + } + + # This statement denies any access to the bucket over insecure HTTP. statement { sid = "DenyInsecureTransport" effect = "Deny" actions = ["s3:*"] resources = ["${aws_s3_bucket.alb_access_logs[0].arn}/*"] principals { type = "*" identifiers = ["*"] } condition { test = "Bool" variable = "aws:SecureTransport" values = ["false"] } } }
This commit resolves all SonarQube security hotspots for the S3 buckets by: - Adding Public Access Block configurations to both log buckets. - Enforcing HTTPS-only access via bucket policies on both buckets. - Enabling server-access logging for both buckets. - Adding versioning, encryption, and lifecycle policies for a complete production-ready configuration.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
Terraform/modules/01-Network/main.tf (2)
65-72
: Explicitly scope the NAT EIP to the VPC domain.Setting
domain = "vpc"
avoids legacy Classic allocations and is the documented requirement for NAT gateways. Please add the explicit domain for clarity and robustness.resource "aws_eip" "nat" { + domain = "vpc" tags = merge( var.tags, { Name = "${var.project_prefix}-${var.environment}-nat-eip" } ) }
244-287
: Add abort rules for incomplete multipart uploads.Lifecycle policies should clean up failed multipart uploads to satisfy CKV_AWS_300 and prevent unbounded storage costs.
noncurrent_version_expiration { noncurrent_days = 30 } + + abort_incomplete_multipart_upload { + days_after_initiation = 7 + } } } @@ noncurrent_version_expiration { noncurrent_days = 30 } + + abort_incomplete_multipart_upload { + days_after_initiation = 7 + } } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Terraform/modules/01-Network/main.tf
(1 hunks)
🧰 Additional context used
🪛 Checkov (3.2.334)
Terraform/modules/01-Network/main.tf
[medium] 240-266: Ensure S3 lifecycle configuration sets period for aborting failed uploads
(CKV_AWS_300)
[medium] 268-289: Ensure S3 lifecycle configuration sets period for aborting failed uploads
(CKV_AWS_300)
# We create a SINGLE NAT Gateway and a SINGLE private route table. This is more | ||
# resilient, cost-effective, and simpler to manage than a per-AZ NAT Gateway. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document or mitigate the single NAT SPOF.
A single NAT gateway is not “more resilient”; it is an AZ-level SPOF for private subnets if that AZ or the NAT fails. Either expose an option for per-AZ NAT gateways or update the comment to call out the risk so operators can make an informed choice.
-# We create a SINGLE NAT Gateway and a SINGLE private route table. This is more
-# resilient, cost-effective, and simpler to manage than a per-AZ NAT Gateway.
+# We create a SINGLE NAT Gateway and a SINGLE private route table. This is a cost
+# optimization but introduces a single-AZ egress SPOF compared to per-AZ NAT gateways.
+# Scale to one NAT per AZ if higher availability is required.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
# We create a SINGLE NAT Gateway and a SINGLE private route table. This is more | |
# resilient, cost-effective, and simpler to manage than a per-AZ NAT Gateway. | |
# We create a SINGLE NAT Gateway and a SINGLE private route table. This is a cost | |
# optimization but introduces a single-AZ egress SPOF compared to per-AZ NAT gateways. | |
# Scale to one NAT per AZ if higher availability is required. |
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 62 to 64, the comment
incorrectly claims a single NAT Gateway is "more resilient" and omits the
AZ-level single point of failure; either add a module variable to allow per-AZ
NAT gateways (e.g., enable_per_az_nat boolean and count/for_each to create a NAT
per AZ and associated route tables) and wire that option into resource counts
and route table associations, or update the comment to explicitly call out the
AZ-level SPOF and recommend operators enable per-AZ NATs for high availability;
implement one of these two changes so the module documents or mitigates the
single NAT SPOF.
rule { | ||
apply_server_side_encryption_by_default { | ||
sse_algorithm = "AES256" | ||
} | ||
bucket_key_enabled = true | ||
} | ||
} | ||
|
||
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_server_access_logs" { | ||
count = var.enable_alb_access_logs ? 1 : 0 | ||
bucket = aws_s3_bucket.s3_server_access_logs[0].id | ||
|
||
rule { | ||
apply_server_side_encryption_by_default { | ||
sse_algorithm = "AES256" | ||
} | ||
bucket_key_enabled = true | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix invalid bucket key usage with SSE-S3.
Setting bucket_key_enabled = true
while sse_algorithm = "AES256"
causes AWS to reject the request (BucketKeyEnabled
only applies to KMS encryption). Apply the change below to prevent plan/apply failures.
resource "aws_s3_bucket_server_side_encryption_configuration" "alb_access_logs" {
count = var.enable_alb_access_logs ? 1 : 0
bucket = aws_s3_bucket.alb_access_logs[0].id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
- bucket_key_enabled = true
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_server_access_logs" {
count = var.enable_alb_access_logs ? 1 : 0
bucket = aws_s3_bucket.s3_server_access_logs[0].id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
- bucket_key_enabled = true
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
rule { | |
apply_server_side_encryption_by_default { | |
sse_algorithm = "AES256" | |
} | |
bucket_key_enabled = true | |
} | |
} | |
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_server_access_logs" { | |
count = var.enable_alb_access_logs ? 1 : 0 | |
bucket = aws_s3_bucket.s3_server_access_logs[0].id | |
rule { | |
apply_server_side_encryption_by_default { | |
sse_algorithm = "AES256" | |
} | |
bucket_key_enabled = true | |
} | |
} | |
resource "aws_s3_bucket_server_side_encryption_configuration" "alb_access_logs" { | |
count = var.enable_alb_access_logs ? 1 : 0 | |
bucket = aws_s3_bucket.alb_access_logs[0].id | |
rule { | |
apply_server_side_encryption_by_default { | |
sse_algorithm = "AES256" | |
} | |
} | |
} | |
resource "aws_s3_bucket_server_side_encryption_configuration" "s3_server_access_logs" { | |
count = var.enable_alb_access_logs ? 1 : 0 | |
bucket = aws_s3_bucket.s3_server_access_logs[0].id | |
rule { | |
apply_server_side_encryption_by_default { | |
sse_algorithm = "AES256" | |
} | |
} | |
} |
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 219-237, the code sets
bucket_key_enabled = true while using sse_algorithm = "AES256", which is invalid
because BucketKeyEnabled only applies to KMS encryption; to fix, either
remove/set bucket_key_enabled = false for these SSE-S3 blocks, or make
bucket_key_enabled conditional so it is true only when sse_algorithm ==
"aws:kms" (and if using KMS also ensure kms_master_key_id is provided); update
both aws_s3_bucket and aws_s3_bucket_server_side_encryption_configuration
resources accordingly.
Proposed change
This is the first major PR for the IaC PoC as discussed in Resolves #2215. It establishes the foundational, production-grade network infrastructure for the Nest application on AWS.
This PR introduces the first reusable Terraform module:
modules/01-Network
.Key Architectural Features:
variables.tf
andoutputs.tf
) and is ready to be consumed by other modules (likecompute
anddatabase
).Next Steps:
Once this foundational network is approved and merged, I will proceed with the
database
andstorage
modules as planned.Looking forward to your feedback!
Checklist
make check-test
locally; all checks and tests passed.