Skip to content

Conversation

nishkersh
Copy link

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:

  • High-Availability: Creates a VPC with public and private subnets distributed across multiple Availability Zones.
  • Security:
    • Implements a single, resilient NAT Gateway for controlled and monitored egress from private subnets.
    • Provisions a public Application Load Balancer (ALB) with a security group that enforces HTTPS.
    • Includes a listener that automatically redirects all HTTP traffic to HTTPS.
  • Modularity: The module is self-contained with a clean interface (variables.tf and outputs.tf) and is ready to be consumed by other modules (like compute and database).

Next Steps:

Once this foundational network is approved and merged, I will proceed with the database and storage modules as planned.

Looking forward to your feedback!

Checklist

  • I've read and followed the contributing guidelines.
  • I've run make check-test locally; all checks and tests passed.

…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.
Copy link
Contributor

coderabbitai bot commented Sep 24, 2025

Summary by CodeRabbit

  • New Features
    • Added Terraform networking module: VPC with public/private subnets, single NAT, routing, and an Application Load Balancer with HTTP→HTTPS redirect and secure default 404. Environment-aware deletion protection for production. Exposes key outputs (VPC, subnets, ALB details) for integration.
  • Documentation
    • Introduced Terraform Operational Guide covering multi-environment setup, prerequisites, remote state, secrets handling, rollout plan, and workflow commands.
  • Chores
    • Integrated Terraform pre-commit hooks (format, validate, lint, security scan) to improve consistency and quality.

Walkthrough

Adds a Terraform network module (VPC, subnets, NAT, ALB with HTTP→HTTPS redirect and HTTPS listener), its variables and outputs. Introduces an operational guide for Terraform workflows. Updates pre-commit config to include Terraform format/validate/lint/security scanning hooks.

Changes

Cohort / File(s) Summary
Pre-commit integration
\.pre-commit-config.yaml
Adds Terraform hooks (terraform_fmt, terraform_validate, terraform_tflint, terraform_trivy) with file filter \.tf$.
Documentation
Terraform/Operational-Guide.md
New ops guide covering prerequisites, state/locking setup, secrets handling, module rollout plan, environments, and workflow (init/plan/apply).
Terraform network module
Terraform/modules/01-Network/main.tf, Terraform/modules/01-Network/variables.tf, Terraform/modules/01-Network/outputs.tf
New VPC module: VPC, IGW, public/private subnets, single EIP/NAT, route tables/associations, ALB + SG, HTTP→HTTPS redirect, HTTPS listener, conditional deletion protection, variables, and outputs (VPC/subnets/ALB identifiers).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The PR partially satisfies the linked issue by delivering a modular, reusable network Terraform module and an operational guide, addressing the "IaC code is modular, reusable, and version-controlled" goal, but it does not implement the full PoC required by #2215: there is no documented tool-comparison, nor are the other required infrastructure components present (Lambda, ECS/Fargate, S3, RDS/Postgres, ElastiCache, and scheduled EC2 jobs), so the acceptance criteria for a complete working PoC are not met. To satisfy the linked issue, add the remaining modules (Lambda, ECS/Fargate, S3, RDS/Postgres, ElastiCache, and EC2 batch jobs), provide the IaC tools comparison if required, and include a top-level example or root module that provisions the full PoC in a sandbox with deployment and teardown instructions and basic validation steps (CLI/CI plan/apply checks).
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely and accurately summarizes the primary change: adding IaC scaffolding for a foundational network module; it names the feature and scope so a reviewer scanning history understands the main intent. The "Feature/iac scaffolding" prefix is a minor branch-style artifact but does not make the title misleading.
Out of Scope Changes Check ✅ Passed All changes in the provided summary (pre-commit Terraform hooks, Operational Guide, and the modules/01-Network Terraform module with variables/outputs) are relevant to the IaC PoC objectives and there are no unrelated or out-of-scope files or functionality introduced in this diff.
Description Check ✅ Passed The PR description clearly describes the addition of a reusable Terraform network module, lists architectural features, references the linked issue (#2215), and outlines next steps and a checklist, which aligns with the changes in the diff.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the docs Improvements or additions to documentation label Sep 24, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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:
+          - terraform
Terraform/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

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6ec86 and 60f9aab.

📒 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.

Comment on lines +65 to +80
resource "aws_eip" "nat" {
# Only one EIP is needed for the single NAT Gateway.
tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-nat-eip"
}
)
}

resource "aws_nat_gateway" "main" {
# Only one NAT Gateway, placed in the first public subnet for simplicity.
# As AWS automatically handles failover at the infrastructure level.
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public[0].id

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix misleading NAT failover comment and note SPOF risk.

AWS does not auto-failover a single NAT Gateway across AZs; placing it in one AZ is an egress SPOF for all private subnets if that AZ or the NAT fails. Keep single NAT if cost-optimized, but document the trade-off (or add an opt-in for per‑AZ NAT).

Apply this diff to correct the comment:

 resource "aws_nat_gateway" "main" {
-  # Only one NAT Gateway, placed in the first public subnet for simplicity.
-  # As AWS automatically handles failover at the infrastructure level.
+  # Cost-optimized: a single NAT Gateway in the first public subnet.
+  # NOTE: This is a single-AZ SPOF for egress. Consider a per-AZ NAT option for higher availability.
   allocation_id = aws_eip.nat.id
   subnet_id     = aws_subnet.public[0].id
📝 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.

Suggested change
resource "aws_eip" "nat" {
# Only one EIP is needed for the single NAT Gateway.
tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-nat-eip"
}
)
}
resource "aws_nat_gateway" "main" {
# Only one NAT Gateway, placed in the first public subnet for simplicity.
# As AWS automatically handles failover at the infrastructure level.
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public[0].id
resource "aws_eip" "nat" {
# Only one EIP is needed for the single NAT Gateway.
tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-nat-eip"
}
)
}
resource "aws_nat_gateway" "main" {
# Cost-optimized: a single NAT Gateway in the first public subnet.
# NOTE: This is a single-AZ SPOF for egress. Consider a per-AZ NAT option for higher availability.
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public[0].id
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 65 to 80, the existing
comment wrongly implies AWS auto-fails over a single NAT Gateway; update the
comment to state that a single NAT Gateway is placed in the first public subnet
and that AWS does not provide cross‑AZ automatic failover, making this an egress
single point of failure for private subnets in that AZ; then either document
this trade‑off (cost vs availability) and suggest adding an opt‑in variable to
create per‑AZ NAT Gateways for high availability.

Comment on lines +179 to +195
resource "aws_lb" "main" {
name = "${var.project_prefix}-${var.environment}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id

# Deletion protection should be enabled via a variable for production.
enable_deletion_protection = var.environment == "prod" ? true : false

tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-alb"
}
)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Harden ALB: drop invalid headers.

Satisfies CKV_AWS_131 and improves security posture.

 resource "aws_lb" "main" {
   name               = "${var.project_prefix}-${var.environment}-alb"
   internal           = false
   load_balancer_type = "application"
   security_groups    = [aws_security_group.alb.id]
   subnets            = aws_subnet.public[*].id
+  drop_invalid_header_fields = 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.

Suggested change
resource "aws_lb" "main" {
name = "${var.project_prefix}-${var.environment}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
# Deletion protection should be enabled via a variable for production.
enable_deletion_protection = var.environment == "prod" ? true : false
tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-alb"
}
)
}
resource "aws_lb" "main" {
name = "${var.project_prefix}-${var.environment}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
drop_invalid_header_fields = true
# Deletion protection should be enabled via a variable for production.
enable_deletion_protection = var.environment == "prod" ? true : false
tags = merge(
var.tags,
{
Name = "${var.project_prefix}-${var.environment}-alb"
}
)
}
🧰 Tools
🪛 Checkov (3.2.334)

[medium] 179-195: Ensure that ALB drops HTTP headers

(CKV_AWS_131)

🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 179 to 195, the ALB
resource needs the HTTP attribute to drop invalid headers to satisfy
CKV_AWS_131; add a load_balancer_attributes block to aws_lb.main with the
attribute "routing.http.drop_invalid_header_fields.enabled" set to "true" (as a
string) so the ALB will drop invalid header fields, keeping existing fields and
tags unchanged.

Comment on lines +212 to +218
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.acm_certificate_arn

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enforce TLS 1.2+ on HTTPS listener.

Current policy ELBSecurityPolicy-2016-08 allows TLS 1.0/1.1. Use a TLS 1.2/1.3 policy (e.g., TLS13-1-2-2021-06).

-  ssl_policy        = "ELBSecurityPolicy-2016-08"
+  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
📝 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.

Suggested change
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.acm_certificate_arn
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = var.acm_certificate_arn
🧰 Tools
🪛 Checkov (3.2.334)

[high] 212-227: Ensure that load balancer is using at least TLS 1.2

(CKV_AWS_103)

🤖 Prompt for AI Agents
In Terraform/modules/01-Network/main.tf around lines 212 to 218, the
aws_lb_listener uses ssl_policy "ELBSecurityPolicy-2016-08" which permits TLS
1.0/1.1; update the ssl_policy to a modern TLS 1.2+ policy such as
"TLS13-1-2-2021-06" (or another AWS-managed TLS1.2/1.3 policy) to enforce TLS
1.2+; optionally make the policy configurable via a variable (e.g.,
var.ssl_policy with a sensible default) and validate that the ACM certificate
supports the chosen policy.

Comment on lines +30 to +37
variable "public_subnet_cidrs" {
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.public_subnet_cidrs) > 0
error_message = "At least one public subnet CIDR must be provided."
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate count matches availability_zones for public subnets.

Prevent index-out-of-range errors when AZs and CIDRs differ.

   validation {
-    condition     = length(var.public_subnet_cidrs) > 0
-    error_message = "At least one public subnet CIDR must be provided."
+    condition     = length(var.public_subnet_cidrs) > 0 && length(var.public_subnet_cidrs) == length(var.availability_zones)
+    error_message = "Provide at least one public subnet CIDR, and ensure its count matches availability_zones."
   }
📝 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.

Suggested change
variable "public_subnet_cidrs" {
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.public_subnet_cidrs) > 0
error_message = "At least one public subnet CIDR must be provided."
}
}
variable "public_subnet_cidrs" {
description = "A list of CIDR blocks for the public subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.public_subnet_cidrs) > 0 && length(var.public_subnet_cidrs) == length(var.availability_zones)
error_message = "Provide at least one public subnet CIDR, and ensure its count matches availability_zones."
}
}
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/variables.tf around lines 30 to 37, the
validation for public_subnet_cidrs only checks for non-empty list but must also
ensure the number of CIDRs matches the number of availability_zones to avoid
index-out-of-range errors; update the validation.condition to require
length(var.public_subnet_cidrs) == length(var.availability_zones) (or explicitly
compare to var.availability_zones length expression used in this module) and
change the validation.error_message to something like "public_subnet_cidrs must
have the same number of entries as availability_zones."

Comment on lines +39 to +46
variable "private_subnet_cidrs" {
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.private_subnet_cidrs) > 0
error_message = "At least one private subnet CIDR must be provided."
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate count matches availability_zones for private subnets.

Same rationale as public subnets.

   validation {
-    condition     = length(var.private_subnet_cidrs) > 0
-    error_message = "At least one private subnet CIDR must be provided."
+    condition     = length(var.private_subnet_cidrs) > 0 && length(var.private_subnet_cidrs) == length(var.availability_zones)
+    error_message = "Provide at least one private subnet CIDR, and ensure its count matches availability_zones."
   }
📝 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.

Suggested change
variable "private_subnet_cidrs" {
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.private_subnet_cidrs) > 0
error_message = "At least one private subnet CIDR must be provided."
}
}
variable "private_subnet_cidrs" {
description = "A list of CIDR blocks for the private subnets. The number of CIDRs must match the number of availability_zones."
type = list(string)
validation {
condition = length(var.private_subnet_cidrs) > 0 && length(var.private_subnet_cidrs) == length(var.availability_zones)
error_message = "Provide at least one private subnet CIDR, and ensure its count matches availability_zones."
}
}
🤖 Prompt for AI Agents
In Terraform/modules/01-Network/variables.tf around lines 39 to 46, the variable
private_subnet_cidrs currently only validates that at least one CIDR is
provided; add a validation to ensure the number of CIDRs equals the number of
availability_zones (same as public subnets) by updating the validation block to
check length(var.private_subnet_cidrs) == length(var.availability_zones) and
provide an appropriate error_message indicating the counts must match.

Comment on lines +49 to +53
aws s3api create-bucket \
--bucket ${TF_STATE_BUCKET} \
--region ${AWS_REGION} \
--create-bucket-configuration LocationConstraint=${AWS_REGION}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle us-east-1 S3 create-bucket special case.

In us-east-1, omit --create-bucket-configuration; otherwise the command fails.

Suggested note:

-aws s3api create-bucket \
-  --bucket ${TF_STATE_BUCKET} \
-  --region ${AWS_REGION} \
-  --create-bucket-configuration LocationConstraint=${AWS_REGION}
+if [ "${AWS_REGION}" = "us-east-1" ]; then
+  aws s3api create-bucket --bucket "${TF_STATE_BUCKET}" --region "${AWS_REGION}"
+else
+  aws s3api create-bucket \
+    --bucket "${TF_STATE_BUCKET}" \
+    --region "${AWS_REGION}" \
+    --create-bucket-configuration LocationConstraint=${AWS_REGION}
+fi
📝 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.

Suggested change
aws s3api create-bucket \
--bucket ${TF_STATE_BUCKET} \
--region ${AWS_REGION} \
--create-bucket-configuration LocationConstraint=${AWS_REGION}
if [ "${AWS_REGION}" = "us-east-1" ]; then
aws s3api create-bucket --bucket "${TF_STATE_BUCKET}" --region "${AWS_REGION}"
else
aws s3api create-bucket \
--bucket "${TF_STATE_BUCKET}" \
--region "${AWS_REGION}" \
--create-bucket-configuration LocationConstraint=${AWS_REGION}
fi
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 49 to 53, the S3 create-bucket
example always includes the --create-bucket-configuration flag which breaks in
us-east-1; update the guidance to mention the us-east-1 special case and show
two variants (one with --create-bucket-configuration for other regions and one
without it for us-east-1) or explain to conditionally omit that flag when
AWS_REGION is us-east-1.

Comment on lines +54 to +57
aws s3api put-bucket-versioning \
--bucket ${TF_STATE_BUCKET} \
--versioning-configuration Status=Enabled
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enable encryption and block public access on the state bucket.

Add SSE and public access block to meet security best practices for Terraform state.

Add after versioning:

aws s3api put-public-access-block \
  --bucket "${TF_STATE_BUCKET}" \
  --public-access-block-configuration 'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'

aws s3api put-bucket-encryption \
  --bucket "${TF_STATE_BUCKET}" \
  --server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'
🤖 Prompt for AI Agents
In Terraform/Operational-Guide.md around lines 54 to 57, the state bucket
configuration only enables versioning but omits public access blocking and
server-side encryption; update the guide to add commands after the versioning
block that call aws s3api put-public-access-block with BlockPublicAcls=true,
IgnorePublicAcls=true, BlockPublicPolicy=true, RestrictPublicBuckets=true for
the TF_STATE_BUCKET and then call aws s3api put-bucket-encryption to enable
server-side encryption (AES256) for the same bucket so the state bucket is
encrypted and not publicly accessible.

Comment on lines +111 to +113
cd terraform/environments/dev
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 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.

@nishkersh
Copy link
Author

I'm reviewing all the suggestions now and will push up a new commit with the fixes shortly.

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Research and Implement IaC PoC for OWASP Nest Infrastructure
1 participant