Lesson 16 of 16
Section 4: Enterprise Modular Architecture, GitOps & Production Security45 min read & walkthrough

Production GitOps: CI/CD Pipelines, TFLint, Trivy & Policy as Code

01 / GITOPS
GitHub Actions

Automate 'plan' on Pull Requests and 'apply' on main branch merge with zero local execution.

02 / OIDC AUTH
No Static Keys

Authenticate CI runners to AWS securely using short-lived OpenID Connect JWT tokens.

03 / SECURITY
Policy as Code

Enforce security standards before deployment using TFLint, Trivy, and Checkov.

The Big Idea

In an elite engineering organization, developers never run terraform apply from their personal laptops. Local execution creates security liabilities, relies on long-lived access keys, and prevents transparent peer review.

GitOps turns your git repository into the single source of truth and control plane for your infrastructure. Every modification starts as a pull request. Automated CI/CD pipelines run code formatters, static security scanners, and generate speculative plans posted as PR comments for peer review.

Once approved and merged into the main branch, a production pipeline applies the changes using short-lived OIDC (OpenID Connect) tokens: zero permanent IAM secrets stored in GitHub. Combined with lifecycle rules like prevent_destroy and create_before_destroy, your infrastructure achieves enterprise-grade resilience.

💡

Jargon Buster: Plain-English Translations

  • GitOps: An operational framework that uses Git repositories as the single source of truth for infrastructure and application code.
  • OIDC (OpenID Connect): A federated authentication protocol that allows GitHub Actions to assume AWS IAM roles using temporary, cryptographically signed tokens.
  • Policy as Code (PaC): Writing security, compliance, and cost guardrails as code (e.g. blocking any S3 bucket with public read enabled).
  • create_before_destroy: A lifecycle meta-argument that creates a replacement resource before tearing down the old one, preventing zero-downtime gaps.

Production GitHub Actions GitOps Pipeline & Lifecycle Rules

# .github/workflows/terraform.yml
name: "Terraform Production GitOps Pipeline"

on:
  pull_request:
    branches: [ "main" ]
  push:
    branches: [ "main" ]

permissions:
  id-token: write # Required for AWS OIDC authentication
  contents: read
  pull-requests: write

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Authenticate to AWS via OIDC (No Static Keys)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-tf-role
          aws-region: us-east-1

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.9.5

      - name: Lint and Format Check
        run: |
          terraform fmt -check
          
      - name: Security Vulnerability Scan
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'config'
          hide-progress: true
          severity: 'CRITICAL,HIGH'

      - name: Terraform Init
        run: terraform init

      - name: Terraform Plan (on PR)
        if: github.event_name == 'pull_request'
        run: terraform plan -no-color -out=tfplan

      - name: Terraform Apply (on Main Merge)
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve
⚠️

Beginner Traps & Gotchas

1. Storing long-lived AWS_ACCESS_KEY_ID in GitHub Secrets

The Gotcha: Generating permanent IAM admin keys and pasting them into repository secrets, risking credential theft.

The Fix: Always use OIDC role assumption. The GitHub runner exchanges an ephemeral token for a 15-minute temporary AWS session.

2. Omitting prevent_destroy on production databases

The Gotcha: Accidentally destroying production RDS instances due to refactoring or misconfigured plan.

The Fix: Add 'lifecycle { prevent_destroy = true }' to all mission-critical data stores. Terraform will reject any plan attempting to delete them.