Infrastructure as Code (IaC) repository for managing AWS Organizations, Organizational Units (OUs), Service Control Policies (SCPs), and governance controls across multiple AWS accounts.
- tfenv — Terraform version manager
- AWS CLI configured with management account credentials
- Python 3.x (for pre-commit hooks)
- shellcheck, shellharden, gitleaks, zizmor (for local hooks)
- Git
brew install tfenv
tfenv install 1.14.5
tfenv use 1.14.5
terraform versionpython3 -m venv .venv
source .venv/bin/activate
pip install pre-commit
pre-commit install
pre-commit install --hook-type commit-msg
pre-commit run --all-filesPre-commit checks (26 hooks):
- Formatting: trailing-whitespace, end-of-file-fixer, terraform_fmt, markdownlint
- Validation: check-yaml, check-json, check-merge-conflict, terraform_validate
- Security: detect-secrets, detect-private-key, gitleaks
- Terraform: terraform_tflint, terrascan
- Shell: shellcheck, shellharden
- Hygiene: check-executables-have-shebangs, check-shebang-scripts-are-executable, check-symlinks, check-case-conflict
- Workflow: actionlint, no-commit-to-branch
- Commits: conventional-pre-commit
aws configure
aws sts get-caller-identity.
├── .github/
│ ├── actions/
│ │ ├── terraform-composite/ # Plan/apply/destroy
│ │ ├── drift-detection-composite/ # Scheduled drift checks
│ │ ├── post-deploy-validation-composite/ # Post-apply AWS validation
│ │ ├── lint-and-security-composite/ # PR lint + security scans
│ │ └── update-pre-commit-composite/ # Weekly hook autoupdate
│ ├── scripts/
│ │ ├── terraform-plan.sh # Plan with markdown summary
│ │ ├── drift-plan.sh # Drift detection plan
│ │ ├── drift-check.sh # Evaluate drift exit code
│ │ ├── drift-issue.sh # Create GitHub issue on drift
│ │ ├── get-terraform-outputs.sh # Read Terraform outputs
│ │ ├── validate-deployment.sh # Post-apply validation
│ │ └── validate-destroy.sh # Post-destroy validation
│ ├── workflows/
│ │ ├── terraform-cicd.yml # Main CI/CD pipeline
│ │ ├── terraform-pr.yml # PR checks (lint + security + plan)
│ │ ├── drift-detection.yml # Daily drift detection
│ │ └── update-pre-commit-hooks.yml # Weekly pre-commit autoupdate
│ └── dependabot.yml # GitHub Actions + Terraform updates
├── terraform/scps/
│ ├── backend.tf # S3 backend with native locking
│ ├── versions.tf # Terraform & provider versions
│ ├── providers.tf # AWS provider configuration
│ ├── variables.tf # Input variables
│ ├── terraform.tfvars.example # Variable template
│ ├── main.tf # Data source + SCPs
│ ├── outputs.tf # Output values
│ └── tests/ # Native terraform test files (mocked)
├── terraform/cleanup/
│ └── tests/ # Native terraform test files (mocked)
├── tests/ # Terratest Go integration tests
├── docs/
│ ├── adr/ # Architecture Decision Records
│ ├── architecture.md # Architecture & design decisions
│ ├── github-oidc-setup.md # OIDC authentication setup
│ ├── github-variables-setup.md # GitHub Variables configuration
│ └── prerequisites.md # One-time SCP enablement
├── .claude/
│ ├── settings.json # Claude Code hooks configuration
│ ├── hooks/ # Hook scripts (post-edit, protect-generated)
│ └── skills/new-scp/ # SCP scaffolding skill
├── .coderabbit.yaml # CodeRabbit AI review config
├── .tflint.hcl # TFLint configuration
├── .pre-commit-config.yaml # Pre-commit hook configuration
├── .secrets.baseline # Detect-secrets baseline
├── CLAUDE.md # Claude Code project instructions
├── CODEOWNERS # Default code ownership
├── CONTRIBUTING.md # Contribution guidelines
├── SECURITY.md # Security disclosure policy
└── README.md
| SCP | Target | Purpose |
|---|---|---|
| DevEnvironmentRestrictions | Dev OU | Instance type limits, block root user, protect CloudTrail, block admin policies |
| DevTaggingAndAbusePrevention | Dev OU | Required tagging, crypto-mining prevention, storage limits, data exposure protection |
| ProtectSSOTrustedAccess | Org root | Prevents disabling IAM Identity Center trusted access |
| RegionRestriction | Org root | Restricts all accounts to approved regions (us-east-1), exempts global services |
- Bucket: S3 with native locking (Terraform 1.10+, no DynamoDB)
- Encryption: AES256
- Versioning: Enabled
- Terraform: 1.14.5
- AWS Provider: ~> 6.0
-
Clone and setup dev environment (see above)
-
Enable SCPs (one-time)
-
Configure local tfvars:
cd terraform/scps cp terraform.tfvars.example terraform.tfvars # Edit with your values
-
Initialize:
terraform init
graph LR
A[Feature branch] --> B[PR]
B --> C[Checks pass]
C --> D[Merge]
D --> E[Auto plan]
E --> F[Approve]
F --> G[Auto apply]
- Create feature branch, make changes, commit (pre-commit hooks run)
- Push and create PR — automated checks: lint, security scan, plan preview
- CodeRabbit + Copilot provide AI-powered code review
- Merge to main — plan runs automatically, apply job pauses at environment gate
- Click "Review deployments" → Approve → apply runs using the same plan (no re-run)
| Workflow | Trigger | Purpose |
|---|---|---|
terraform-cicd.yml |
Push to main, manual | Plan → environment approval → apply (artifact reuse), manual destroy |
terraform-pr.yml |
PR | Lint (fmt, tflint), security (checkov), terraform test (mocked), plan |
ci-checks.yml |
PR, push to main | Quality + security: markdownlint, shellcheck, yamllint, zizmor, Semgrep, Trivy (step summaries) |
drift-detection.yml |
Daily 9 AM UTC | Detects config drift, creates GitHub issue |
update-pre-commit-hooks.yml |
Weekly Sunday | Auto-updates hook versions, creates PR |
OIDC — no long-lived credentials. Temporary tokens via AWS STS.
- Role:
GitHubActions-OrganizationGovernance - Inline policies:
SCPManagement(scoped org access with explicit deny on dangerous actions) +TerraformStateAccess(S3 bucket)
| Layer | Mechanism |
|---|---|
| Pre-commit (local) | 26 hooks — formatting, validation, security, linting |
| PR checks (CI) | TFLint, Checkov, plan, quality checks, security scanning, CodeRabbit + Copilot AI review |
| Branch protection | PR required, status checks must pass, no direct pushes |
| Deployment gate | production environment with required reviewer approval |
| Post-deploy validation | AWS CLI checks — SCPs exist, attached correctly, content verified |
| AI deployment analysis | Claude via Bedrock — security posture, SCP conflicts, recommendations |
| Post-destroy validation | AWS CLI checks — SCPs removed, no orphaned policies |
| Drift detection | Daily scheduled plan, auto-creates issue on drift |
| Automated updates | Dependabot + pre-commit autoupdate |
| Diagram | Description |
|---|---|
| SCP Architecture | Organization hierarchy, SCP attachments, OIDC auth flow |
| CI/CD Pipeline | PR checks, environment gate, apply/destroy/drift flows |
| Defense in Depth | 6 security layers from local hooks to continuous monitoring |
See Architecture for full details.
- Architecture
- Architecture Decision Records
- GitHub OIDC Setup
- GitHub Variables Setup
- Prerequisites
- GitHub Actions
MIT License — see LICENSE file for details.
Created by Alex Garcia
Disclaimer: All views and opinions expressed in this repository are my own and do not represent the opinions of my employer.