Skip to content

feat: add trivy scan to plan to staging #68

feat: add trivy scan to plan to staging

feat: add trivy scan to plan to staging #68

name: Plan PR updates on Staging env
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
plan-security:
name: Terraform Plan (security)
runs-on: ubuntu-latest
environment: staging
permissions:
id-token: write # OIDC
contents: read
pull-requests: write
env:
TF_VAR_region: ${{ secrets.AWS_REGION }}
TF_VAR_environment: staging
TF_VAR_app_id: trip-planner-app
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.12.2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::387836084035:role/githubTripPlannerInfraManager
aws-region: ${{ secrets.AWS_REGION }}
- name: Terraform Validate
working-directory: terraform/layers/security
run: |
terraform init \
-input=false -upgrade \
-backend-config="bucket=trip-planner-states" \
-backend-config="key=security/staging/terraform.tfstate" \
-backend-config="region=eu-central-1" \
-backend-config="dynamodb_table=staging-trip-planner-terraform-locks" \
-backend-config="encrypt=true"
terraform validate
- name: Trivy IaC Scan
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: config
scan-ref: terraform/layers/security
severity: HIGH,CRITICAL
exit-code: '1'
- name: Terraform Plan (staging)
working-directory: terraform/layers/security
run: |
terraform plan -out=tfplan -input=false
terraform show -no-color tfplan > tfplan.txt
- name: Upload plan as artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-staging-security
path: terraform/layers/security/tfplan.txt
plan-networking:
name: Terraform Plan (networking)
runs-on: ubuntu-latest
environment: staging
needs: plan-security
permissions:
id-token: write # OIDC
contents: read
pull-requests: write
env:
TF_VAR_region: ${{ secrets.AWS_REGION }}
TF_VAR_environment: staging
TF_VAR_azs: '["${{ secrets.AWS_REGION }}a", "${{ secrets.AWS_REGION }}b", "${{ secrets.AWS_REGION }}c"]'
TF_VAR_vpc_cidr: 10.0.0.0/16
TF_VAR_public_subnets_ips: '["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]'
TF_VAR_private_subnets_ips: '["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]'
TF_VAR_app_id: trip-planner-app
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.12.2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::387836084035:role/githubTripPlannerInfraManager
aws-region: ${{ secrets.AWS_REGION }}
- name: Terraform Validate
working-directory: terraform/layers/networking
run: |
terraform init \
-input=false -upgrade \
-backend-config="bucket=trip-planner-states" \
-backend-config="key=networking/staging/terraform.tfstate" \
-backend-config="region=eu-central-1" \
-backend-config="dynamodb_table=staging-trip-planner-terraform-locks" \
-backend-config="encrypt=true"
terraform validate
- name: Trivy IaC Scan
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: config
scan-ref: terraform/layers/networking
severity: HIGH,CRITICAL
exit-code: '1'
- name: Terraform Plan (staging)
working-directory: terraform/layers/networking
run: |
terraform plan -out=tfplan -input=false
terraform show -no-color tfplan > tfplan.txt
- name: Upload plan as artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-staging-networking
path: terraform/layers/networking/tfplan.txt
plan-database:
name: Terraform Plan (database)
runs-on: ubuntu-latest
environment: staging
needs: plan-networking
permissions:
id-token: write # OIDC
contents: read
pull-requests: write
env:
TF_VAR_region: ${{ secrets.AWS_REGION }}
TF_VAR_environment: staging
TF_VAR_app_id: trip-planner-app
TF_VAR_notification_email: ${{secrets.ALERT_EMAIL}}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.12.2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::387836084035:role/githubTripPlannerInfraManager # Updtate this
aws-region: ${{ secrets.AWS_REGION }}
- name: Terraform Validate
working-directory: terraform/layers/database
run: |
terraform init \
-input=false -upgrade \
-backend-config="bucket=trip-planner-states" \
-backend-config="key=database/staging/terraform.tfstate" \
-backend-config="region=eu-central-1" \
-backend-config="dynamodb_table=staging-trip-planner-terraform-locks" \
-backend-config="encrypt=true"
terraform validate
- name: Trivy IaC Scan
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: config
scan-ref: terraform/layers/database
severity: HIGH,CRITICAL
exit-code: '1'
- name: Terraform Plan (staging)
working-directory: terraform/layers/database
run: |
terraform plan -out=tfplan -input=false
terraform show -no-color tfplan > tfplan.txt
- name: Upload plan as artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-staging-database
path: terraform/layers/database/tfplan.txt
plan-backend:
name: Terraform Plan (backend)
runs-on: ubuntu-latest
environment: staging
needs: plan-database
permissions:
id-token: write # OIDC
contents: read
pull-requests: write
env:
TF_VAR_region: ${{ secrets.AWS_REGION }}
TF_VAR_environment: staging
TF_VAR_app_id: trip-planner-app
TF_VAR_alb_domain_name: staging-alb.epic-trip-planner.com
TF_VAR_hosted_zone_id: ${{secrets.HOSTED_ZONE_ID}}
TF_VAR_route53_zone_name: epic-trip-planner.com
TF_VAR_container_image: lrasata/trip-planner-backend-app:1.1.0
TF_VAR_allowed_origins: https://staging.epic-trip-planner.com
TF_VAR_notification_email: ${{secrets.ALERT_EMAIL}}
TF_VAR_api_file_upload_domain_name: staging-api-file-upload.epic-trip-planner.com
TF_VAR_backend_certificate_arn: ${{secrets.BACKEND_CERTIFICATE_ARN}}
TF_VAR_use_bucketav: false
TF_VAR_bucketav_sns_findings_topic_name: ""
TF_VAR_uploads_bucket_name: file-uploads-bucket
TF_VAR_enable_transfer_acceleration: true
TF_VAR_secret_store_name: ${{secrets.SECRET_STORE_NAME}}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.12.2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::387836084035:role/githubTripPlannerInfraManager
aws-region: ${{ secrets.AWS_REGION }}
- name: Terraform Validate
working-directory: terraform/layers/backend
run: |
terraform init \
-input=false -upgrade \
-backend-config="bucket=trip-planner-states" \
-backend-config="key=backend/staging/terraform.tfstate" \
-backend-config="region=eu-central-1" \
-backend-config="dynamodb_table=staging-trip-planner-terraform-locks" \
-backend-config="encrypt=true"
terraform validate
- name: Trivy IaC Scan
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: config
scan-ref: terraform/layers/backend
severity: HIGH,CRITICAL
exit-code: '1'
- name: Terraform Plan (staging)
working-directory: terraform/layers/backend
run: |
terraform plan -out=tfplan -input=false
terraform show -no-color tfplan > tfplan.txt
- name: Upload plan as artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-staging-backend
path: terraform/layers/backend/tfplan.txt
plan-frontend:
name: Terraform Plan (frontend)
runs-on: ubuntu-latest
environment: staging
needs: plan-security
permissions:
id-token: write # OIDC
contents: read
pull-requests: write
env:
TF_VAR_region: ${{ secrets.AWS_REGION }}
TF_VAR_environment: staging
TF_VAR_app_id: trip-planner-app
TF_VAR_cloudfront_domain_name: staging.epic-trip-planner.com
TF_VAR_cloudfront_certificate_arn: ${{secrets.CLOUDFRONT_CERTIFICATE_ARN}}
TF_VAR_backend_certificate_arn: ${{secrets.BACKEND_CERTIFICATE_ARN}}
TF_VAR_static_web_app_bucket_name: trip-planner-static-webapp-bucket
TF_VAR_api_file_upload_domain_name: staging-api-file-upload.epic-trip-planner.com
TF_VAR_api_locations_domain_name: staging-api-locations.epic-trip-planner.com
TF_VAR_API_CITIES_GEO_DB_URL: ${{secrets.API_CITIES_GEO_DB_URL}}
TF_VAR_GEO_DB_RAPID_API_HOST: ${{secrets.GEO_DB_RAPID_API_HOST}}
TF_VAR_API_COUNTRIES_GEO_DB_URL: ${{secrets.API_COUNTRIES_GEO_DB_URL}}
TF_VAR_notification_email: ${{secrets.ALERT_EMAIL}}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.12.2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::387836084035:role/githubTripPlannerInfraManager
aws-region: ${{ secrets.AWS_REGION }}
- name: Terraform Validate
working-directory: terraform/layers/frontend
run: |
terraform init \
-input=false -upgrade \
-backend-config="bucket=trip-planner-states" \
-backend-config="key=frontend/staging/terraform.tfstate" \
-backend-config="region=eu-central-1" \
-backend-config="dynamodb_table=staging-trip-planner-terraform-locks" \
-backend-config="encrypt=true"
terraform validate
- name: Trivy IaC Scan
uses: aquasecurity/trivy-action@0.20.0
with:
scan-type: config
scan-ref: terraform/layers/frontend
severity: HIGH,CRITICAL
exit-code: '1'
- name: Terraform Plan (staging)
working-directory: terraform/layers/frontend
run: |
terraform plan -out=tfplan -input=false
terraform show -no-color tfplan > tfplan.txt
- name: Upload plan as artifact
uses: actions/upload-artifact@v4
with:
name: terraform-plan-staging-frontend
path: terraform/layers/frontend/tfplan.txt
combine-and-comment:
name: Combine Plans and Comment
runs-on: ubuntu-latest
needs: [plan-security, plan-networking, plan-database, plan-backend, plan-frontend] # Wait for all sequential jobs
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
steps:
- name: Download all plan artifacts
uses: actions/download-artifact@v4
with:
path: plans/ # Download to plans/ directory
- name: Combine plans and post comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const path = require('path');
const plansDir = 'plans';
let combinedBody = '### Terraform Plan (staging - All Layers)\n\n';
const layers = ['security', 'networking', 'database', 'backend', 'frontend'];
for (const layer of layers) {
const planPath = path.join(plansDir, `terraform-plan-staging-${layer}`, 'tfplan.txt');
if (fs.existsSync(planPath)) {
const body = fs.readFileSync(planPath, 'utf8');
const MAX_LEN = 15000; // Shorter per layer to fit combined
const planPreview = body.length > MAX_LEN ? body.slice(0, MAX_LEN - 1000) + '\n\n...(truncated)' : body;
combinedBody += `#### ${layer}\n<details>\n<summary>Click to expand</summary>\n\n\`\`\`\n${planPreview}\n\`\`\`\n\n</details>\n\n`;
}
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: combinedBody
});