Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / infra/terraform/README.md |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | bdacd9d0b4d5998d25fc74bf4007f4c3ec538c7a |
| Branch | deploy-and-ops |
| Path or archive member | infra/terraform/README.md |
| Original SHA-256 | bb435f51003006601d9f3bb6206a9a525b2e6ed180dcde7a86183c9bc691c1cf |
| Git blob SHA | a45a14f90a6c88fff420366e668e12e2612a1252 |
| Reading-copy SHA-256 | bb435f51003006601d9f3bb6206a9a525b2e6ed180dcde7a86183c9bc691c1cf |
Recovered source transcript
Download complete source text ↓76 lines · 4.0 KB
# Infrastructure as code (Terraform)
The cloud infrastructure for missionMATCH, authored for the primary target AWS GovCloud and parameterized
so the secondary target Azure Government is a tfvars and provider plus module swap, not a rewrite. The
module split mirrors the application's cloud ports one to one.
## Layout
```
infra/terraform/
versions.tf providers.tf variables.tf main.tf outputs.tf root module
environments/aws-govcloud.tfvars primary target values
environments/azure-gov.tfvars secondary target (documented stub)
modules/
network/ a private subnet VPC, the db subnet group, and the db security group
database/ managed PostgreSQL 16 (encrypted, multi AZ, force_ssl, RDS managed master secret)
object_storage/ an S3 bucket (versioned, SSE KMS, public access blocked, TLS only)
secrets/ the platform KMS key and one empty Secrets Manager container per tenant reference key
identity/ a workload OIDC provider and a least privilege app role (the identity hook)
```
## What Terraform owns, and what it deliberately does NOT
Terraform creates the network, the managed Postgres instance and its control plane database, the RDS
managed master credential, the object bucket, the KMS key, the per tenant secret containers, and the app
IAM role. It does NOT create:
- the pgvector extension or the missionmatch_app / missionmatch_migrator / missionmatch_compliance roles
or any schema or RLS: those live in goose migrations, run by the migrator, so a single tool owns the
schema and the role separation the RLS design depends on is preserved.
- any per tenant database: those are created by cmd/provision-tenant at onboarding.
- any secret VALUE: the per tenant DSNs are put into the secret containers out of band by the operator
(CLAUDE.md rule 3, keys stay on the server). A directory dump or a state file must never be a credential
dump, so the database password is the RDS managed master secret and tenant DSNs live only in the secret
store.
The outputs feed the application's existing environment: the db endpoint forms MM_DATABASE_URL,
MM_MIGRATOR_DATABASE_URL, and MM_COMPLIANCE_DATABASE_URL (with the role passwords set out of band), the
bucket name the storage port, the secret ARNs the secrets port, and MM_SECRETS_BACKEND is aws_govcloud.
## Validate (no credentials, safe to run in CI)
```
terraform -chdir=infra/terraform fmt -check -recursive
terraform -chdir=infra/terraform init -backend=false
terraform -chdir=infra/terraform validate
```
fmt and validate require no cloud credentials and run in CI alongside the Go gates.
## Plan and apply (the operator's step, requires real credentials)
terraform plan and terraform apply are NOT run automatically and never in CI. They require real AWS
GovCloud credentials and the operator's review:
```
# configure the S3 backend (an encrypted, versioned state bucket) at init:
terraform -chdir=infra/terraform init \
-backend-config="bucket=<state-bucket>" -backend-config="key=missionmatch/prod.tfstate" \
-backend-config="region=us-gov-west-1"
terraform -chdir=infra/terraform plan -var-file=environments/aws-govcloud.tfvars
terraform -chdir=infra/terraform apply -var-file=environments/aws-govcloud.tfvars # operator only
```
After apply, run goose against the new database (CREATE EXTENSION vector, the roles, the schema, and RLS),
then provision-tenant per client. See docs/RUNBOOK_ONBOARDING.md and docs/MIGRATE_TO_PER_TENANT.md.
## Notes
- ARNs are built from data.aws_partition.current so GovCloud (partition aws-us-gov) is correct; never
hardcode the aws partition.
- The state bucket is itself a secret store (state can contain sensitive values), so it must be encrypted,
versioned, and access restricted, with native S3 lockfile locking and the FIPS endpoint.
- The validation here was run with the OpenTofu compatible toolchain (tofu fmt / validate); the HCL is
Terraform compatible and the operator uses terraform.