Skip to main content

Automated

An Automated system needs no human effort for repetitive operations: provisioning, deployment, validation, secret distribution, remediation. In the AWS Baseline and the blueprints the pipeline, not a laptop, is the only writer to shared environments. If deployment requires a hero, it is not automated.

The infrastructure pipeline

Three workflows ship with the landing zone, and the two blueprint infrastructure repositories carry the first two:

WorkflowTriggerWhat it does
plan.ymlPull request touching environments/, units/, stacks/, modules/, root.hcl, common.hcl, scripts/, the VPC maps or itselfGenerates the stacks, runs the guardrail scripts, tofu fmt, tflint, Checkov and Trivy, then terragrunt run --all plan and posts the result. One plan per pull request; a new push supersedes the running one
apply.ymlMerge to mainApplies every unit in dependency order behind a GitHub Environment. Applies queue per ref and are never cancelled, so two merges cannot apply against the same state at once. Blueprints run a dev, staging, prod matrix, each under the Environment of the same name
drift-detection.yml01:00 UTC Tuesday to Friday for the network, identity and active workload accounts; Monday and on demand for all fourteenterragrunt run --all plan -detailed-exitcode per account directory, all regions plus global; exit code 2 opens a drift issue with the plan output

Both plan and apply write a JSON run report that CI uploads as an artifact. The GitHub Actions explainer describes the runners and the OIDC step every workflow starts with.

Guardrails that run before a plan

The same checks run locally in pre-commit and again in CI, so a contributor without hooks is still caught:

CheckProtects against
check-stack-layout.pyA region folder without a stack file, a hand-written unit under environments/, an unreferenced unit definition
check-no-hardcoded-cidrs.pyA private IP range typed anywhere but the VPC map
check-vpc-maps.pyInvalid, overlapping or mis-nested ranges, or a unit whose address lookup has no map entry
check-mock-outputs.pyA dependency that cannot be planned because its outputs are not mocked
check-required-inputs.pyA unit that does not supply every required input of its module
check-module-versions.pyA module whose provider pins differ from root.hcl
tofu fmt, tflint, Checkov, TrivyMalformed, non-idiomatic or insecure configuration

The policy as code page explains why conventions checked by machine stay true; the Checkov, Trivy and tflint explainer covers the scanners.

Application delivery

The Web App Blueprint builds each image once and never rebuilds it for a later stage:

  1. ci.yml on a pull request: lint, tests, Docker build, Trivy scan.
  2. cd-integration.yml on merge to main: build, push main-<short sha> to ECR in the artifacts account, open a pull request against envs/dev in the GitOps repository, auto-merged; ArgoCD auto-syncs dev.
  3. cd-release.yml on a GitHub Release: add the vX.Y.Z tag to the same image, open a pull request against envs/stg, auto-merged; ArgoCD auto-syncs staging.
  4. promote-prod.yml on demand with a release tag: verify the tag exists in ECR, open the envs/prd pull request with no auto-merge, behind the prod Environment; a person merges it and ArgoCD prod is synced manually.
  5. cd-frontend.yml: build the React application, sync to S3, invalidate CloudFront.

No workflow pushes to the GitOps repository directly; each mints a short-lived token for the acme-runner GitHub App and opens a pull request. ECR rejects tag overwrites, so latest does not exist. The Data and ETL Blueprint follows the same build-once rule and records the deployed Lambda image tag in an SSM parameter that the infrastructure reads back, so a plan never rolls the function to an older tag. The GitOps, immutable artifacts and ArgoCD pages cover each part.

Everything else that runs without a person

  • Secrets: a merge to the secrets repository decrypts each stage's SOPS file with that stage's KMS key and writes SSM Parameter Store SecureStrings in the target account; the External Secrets Operator refreshes Kubernetes secrets hourly.
  • DNS and certificates: ExternalDNS writes public and internal records; ACM certificates are validated through DNS and renewed by AWS; the cross-account Route 53 role lets workload accounts write only the records they need.
  • Remediation: EventBridge rules remove public access from an S3 bucket reported public and route high-severity findings to SNS.
  • Security services: organization-wide enrollment of GuardDuty, Security Hub, Inspector and Macie is a per-service flag, applied once after delegation.
  • Runners: optional self-hosted runners start per job on Spot instances and terminate when the job ends.

Review is part of the automation

CODEOWNERS routes reviews by blast radius: environments/core/, units/, .github/, root.hcl, common.hcl, the VPC maps and scripts/ to the infra admins; stacks/ and modules/ to the infra admins and platform leads; security.hcl to the infra admins and the security team; environments/plat/prod/ to platform leads and the security team. An approval from any one listed owner satisfies the rule for a path. The prod GitHub Environment holds required reviewers everywhere. A change reaches AWS only through pull request, plan, review, merge and apply.

How you verify it

  • The Actions tab of your landing-zone repository: a plan run on every pull request, an apply run on every merge, drift runs on the schedule above.
  • ECR in the artifacts account: repositories with tag immutability on and no latest tag.
  • The GitOps repository: envs/<stage>/values.yaml changed only by pull requests from the acme-runner App.
  • Settings of each repository: Environments dev, staging and prod, with required reviewers on prod.