Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: "Test"

on:
pull_request:
paths:
- "**/*.tf"
- "**/*.tfvars"
- ".github/workflows/test.yml"
workflow_dispatch:

jobs:
terraform-test:
name: Test Terraform
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.25'

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "~1.8.0"

- name: Install TFLint
uses: terraform-linters/setup-tflint@v4
with:
tflint_version: latest

- name: Install Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin

- name: Run all tests
run: make test


- name: Summary
if: always()
run: |
echo "## Terraform Lint Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Modules Checked" >> $GITHUB_STEP_SUMMARY
modules=$(find . -name "*.tf" -type f | xargs dirname | sort -u)
echo "The following Terraform modules were validated:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
for module in $modules; do
echo "- \`$module\`" >> $GITHUB_STEP_SUMMARY
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Checks Performed" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Terraform Format Check" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Terraform Validation" >> $GITHUB_STEP_SUMMARY
echo "- ✅ TFLint Analysis" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Security Scan (Trivy)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Local Development" >> $GITHUB_STEP_SUMMARY
echo "Run the same checks locally with:" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
echo "make test # Run all tests" >> $GITHUB_STEP_SUMMARY
echo "make format # Auto-format files" >> $GITHUB_STEP_SUMMARY
echo "make scan # Run security scan" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

.terraform/
.terraform.lock.hcl

# Dependency directories (remove the comment below to include it)
# vendor/

Expand Down
64 changes: 64 additions & 0 deletions .tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
config {
# Set minimum Terraform version to support provider functions
terraform_version = "~> 1.8.0"
}

plugin "terraform" {
enabled = true
preset = "recommended"
version = "0.9.1"
source = "github.com/terraform-linters/tflint-ruleset-terraform"
}

plugin "google" {
enabled = true
}

rule "terraform_comment_syntax" {
enabled = true
}

rule "terraform_deprecated_index" {
enabled = true
}

rule "terraform_deprecated_interpolation" {
enabled = false # Disable to allow provider function syntax
}

rule "terraform_documented_outputs" {
enabled = true
}

rule "terraform_documented_variables" {
enabled = true
}

rule "terraform_naming_convention" {
enabled = true
format = "snake_case"
}

rule "terraform_required_providers" {
enabled = true
}

rule "terraform_required_version" {
enabled = true
}

rule "terraform_standard_module_structure" {
enabled = true
}

rule "terraform_typed_variables" {
enabled = true
}

rule "terraform_unused_declarations" {
enabled = true
}

rule "terraform_unused_required_providers" {
enabled = true
}
22 changes: 22 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Trivy ignore file for Suga GCP Plugins
# https://aquasecurity.github.io/trivy/latest/docs/configuration/filtering/

# AVD-AWS-0030: Image scanning is not enabled
# We've added a variable to control this, which default to `true`
AVD-AWS-0030

# TODO: we'll need to avoid use the `latest` tag, then enable this
AVD-AWS-0031

# TODO: Enable bucket encryption and add a key resource/plugin
AVD-AWS-0132
AVD-AWS-0088

# TODO: Enable load balancer HTTPS
AVD-AWS-0054

# Ignore directories
.git/
.terraform/
node_modules/
security-reports/
16 changes: 16 additions & 0 deletions DEVELOPERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Developer Guide

## Prerequisites

- [Terraform](https://www.terraform.io/downloads) >= 1.5.0
- [Docker](https://www.docker.com/get-started) (for tflint and trivy)

## Usage

```bash
make format # Format all Terraform files
make test # Run all tests (format-check, validate, lint, scan)
make clean # Clean up temp files
```

Tools run in Docker containers - no local installation needed.
47 changes: 47 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.PHONY: help format lint clean
.DEFAULT_GOAL := help

## TODO: include MEDIUM severity in security scanning.
TRIVY_SEVERITY := HIGH,CRITICAL

help: ## Show available commands
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-10s %s\n", $$1, $$2}'

trivy-severity: ## Output the Trivy severity levels for use in scripts
@echo $(TRIVY_SEVERITY)

format: ## Format all Terraform files
@find . -name "*.tf" -type f | xargs dirname | sort -u | xargs -I {} terraform fmt {}

format-check: ## Check formatting of all Terraform files
@echo "Checking format..."
@find . -name "*.tf" -type f | xargs dirname | sort -u | while read dir; do \
terraform fmt -check=true -diff=true "$$dir" || exit 1; \
done

validate: ## Validate all Terraform files
@echo "Validating..."
@find . -name "*.tf" -type f | xargs dirname | sort -u | while read dir; do \
echo " $$dir"; \
cd "$$dir" && terraform init -backend=false -get=true -upgrade=false >/dev/null && terraform validate && cd - >/dev/null || exit 1; \
done

lint: ## Lint using tflint
@echo "Running tflint..."
@find . -name "*.tf" -type f | xargs dirname | sort -u | while read dir; do \
echo " $$dir"; \
docker run --rm -v "$$(pwd)/$$dir:/data" -t ghcr.io/terraform-linters/tflint --format=compact --minimum-failure-severity=error; \
done

scan: ## Run security scan using Trivy
@echo "Running security scan..."
@docker run --rm -v "$$(pwd):/work" -w /work ghcr.io/aquasecurity/trivy:latest config . --format=table --quiet --exit-code 1 --severity $(TRIVY_SEVERITY)

test: format-check validate lint scan ## Run all tests: format-check, validate, lint, and scan
@echo "All tests passed!"

clean: ## Clean up .terraform directories and temp files
@find . -type d -name ".terraform" -exec rm -rf {} + 2>/dev/null || true
@find . -name "*.tfplan" -delete 2>/dev/null || true
@find . -name "*.tfstate*" -delete 2>/dev/null || true
@find . -name ".terraform.lock.hcl" -delete 2>/dev/null || true
1 change: 1 addition & 0 deletions cloudfront/module/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ resource "aws_lambda_permission" "allow_cloudfront_origin_request" {
action = "lambda:GetFunction"
function_name = aws_lambda_function.origin_request[0].function_name
principal = "edgelambda.amazonaws.com"
source_arn = aws_cloudfront_distribution.distribution.arn
}

resource "aws_wafv2_web_acl" "cloudfront_waf" {
Expand Down
60 changes: 30 additions & 30 deletions fargate/module/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -110,33 +110,33 @@ resource "aws_ecs_task_definition" "service" {

environment = concat([
{
name = "SUGA_SERVICE_NAME"
name = "SUGA_SERVICE_NAME"
value = var.suga.name
},
{
name = "SUGA_STACK_ID"
name = "SUGA_STACK_ID"
value = var.suga.stack_id
},
{
name = "PORT"
value = "9001"
name = "PORT"
value = "9001"
},
{
name = "FARGATE_PROXY_PORT"
name = "FARGATE_PROXY_PORT"
value = "${tostring(var.container_port)}"
}
],
[
for k, v in var.environment : {
name = k
value = "${tostring(v)}"
}
],
[
for k, v in var.suga.env : {
name = k
value = "${tostring(v)}"
}
],
[
for k, v in var.environment : {
name = k
value = "${tostring(v)}"
}
],
[
for k, v in var.suga.env : {
name = k
value = "${tostring(v)}"
}
])

logConfiguration = {
Expand Down Expand Up @@ -165,14 +165,14 @@ resource "aws_ecs_cluster" "cluster" {

# Create an ESC service for the above task definition
resource "aws_ecs_service" "service" {
name = "${var.suga.stack_id}-${var.suga.name}"
cluster = aws_ecs_cluster.cluster.id
name = "${var.suga.stack_id}-${var.suga.name}"
cluster = aws_ecs_cluster.cluster.id
task_definition = aws_ecs_task_definition.service.arn
desired_count = 1
launch_type = "FARGATE"
desired_count = 1
launch_type = "FARGATE"

network_configuration {
subnets = var.subnets
subnets = var.subnets
security_groups = concat([var.alb_security_group], var.security_groups)
}
load_balancer {
Expand All @@ -184,25 +184,25 @@ resource "aws_ecs_service" "service" {

# Create target group
resource "aws_lb_target_group" "service" {
name = local.sanitized_target_group_name
port = var.container_port
protocol = "HTTP"
vpc_id = var.vpc_id
name = local.sanitized_target_group_name
port = var.container_port
protocol = "HTTP"
vpc_id = var.vpc_id

target_type = "ip"

health_check {
path = "/${var.suga.name}/x-suga-health"
interval = 30
timeout = 10
path = "/${var.suga.name}/x-suga-health"
interval = 30
timeout = 10
healthy_threshold = 2
}
}

# Reference the shared HTTP listener created by the loadbalancer module
data "aws_lb_listener" "shared_http" {
load_balancer_arn = var.alb_arn
port = 80
port = 80
}

# Create listener rule for this service's target group
Expand Down
2 changes: 1 addition & 1 deletion fargate/module/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ variable "container_port" {
}

variable "alb_arn" {
type = string
type = string
}

variable "alb_security_group" {
Expand Down
6 changes: 3 additions & 3 deletions iamrole/module/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
output "suga" {
value = {
exports = {
"aws_iam_role" = aws_iam_role.role.arn
"aws_iam_role:id" = aws_iam_role.role.id
"aws_iam_role:arn" = aws_iam_role.role.arn
"aws_iam_role" = aws_iam_role.role.arn
"aws_iam_role:id" = aws_iam_role.role.id
"aws_iam_role:arn" = aws_iam_role.role.arn
"aws_iam_role:name" = aws_iam_role.role.name
}
}
Expand Down
2 changes: 1 addition & 1 deletion iamrole/module/variables.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
variable "suga" {
type = object({
name = string
name = string
stack_id = string
})
}
Expand Down
3 changes: 3 additions & 0 deletions lambda/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ inputs:
timeout:
type: number
description: "Maximum execution time in seconds 1-900 (e.g. `300`)"
image_scan_on_push:
type: bool
description: "Scan the image for vulnerabilities after it is pushed to Amazon ECR (e.g. `true`)"
memory:
type: number
description: "Amount of memory in MB 128-10240 (e.g. `1024`)"
Expand Down
Loading
Loading