Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/opentofu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ jobs:
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
uses: makeitworkcloud/shared-workflows/.github/workflows/opentofu.yml@main
with:
aws-region: us-west-2
aws-role-to-assume: arn:aws:iam::332355796717:role/github-actions-twilio-state
secrets:
CHART_UPDATER_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CHART_UPDATER_GITHUB_APP_PRIVATE_KEY }}
19 changes: 13 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
SHELL := /bin/bash
TERRAFORM := $(shell which tofu)
S3_BUCKET := mitw-tf-twilio-infra
S3_REGION := us-west-2
S3_KEY := tofu/twilio/terraform.tfstate

.PHONY: clean init plan apply test pre-commit-config pre-commit-check-deps pre-commit-install-hooks

clean:
@find . -name .terraform -type d | xargs -r rm -rf

# Bootstrap deliberately uses no remote backend until the encrypted backend
# contract and least-privilege CI access are established in a later PR.
# tfroot-aws owns this private, versioned state bucket and the GitHub OIDC role
# that CI assumes. The backend needs no static AWS credentials.
init: clean
@${TERRAFORM} init -backend=false -upgrade -input=false
@${TERRAFORM} init -reconfigure -upgrade -input=false \
-backend-config="bucket=${S3_BUCKET}" \
-backend-config="key=${S3_KEY}" \
-backend-config="region=${S3_REGION}" \
-backend-config="use_lockfile=true"

plan: init
@${TERRAFORM} plan -refresh=false -input=false -lock=false -compact-warnings
@${TERRAFORM} plan -refresh=false -input=false -compact-warnings

# There are intentionally no provider configurations or Twilio resources in
# this bootstrap, so the main-branch apply has no provider-side effect.
# this root, so backend selection is the only stateful behavior on main.
apply: init
@${TERRAFORM} apply -auto-approve -refresh=false -input=false -lock=false -compact-warnings
@${TERRAFORM} apply -auto-approve -refresh=false -input=false -compact-warnings

test: pre-commit-config pre-commit-install-hooks
@pre-commit run -a
Expand Down
12 changes: 4 additions & 8 deletions docs/bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@

## Scope

This initial root validates the OpenTofu toolchain and provider installation only. It creates, imports, updates, or deletes **no** Twilio resources. In particular, it does not purchase or configure phone numbers, webhooks, credentials, messaging services, or runtime routing.
This root validates the OpenTofu toolchain, remote state backend, and provider installation only. It creates, imports, updates, or deletes **no** Twilio resources. In particular, it does not purchase or configure phone numbers, webhooks, credentials, messaging services, or runtime routing.

The evaluated provider is `RJPearson94/twilio` `0.27.1`. Registry documentation confirms it supports Twilio phone-number resources and inbound `messaging` webhook fields, but it is community-maintained and requires existing account credentials. The bootstrap intentionally declares no provider configuration, so CI receives no Twilio credentials and performs no provider-side API call.
The evaluated provider is `RJPearson94/twilio` `0.27.1`. Registry documentation confirms it supports Twilio phone-number resources and inbound `messaging` webhook fields, but it is community-maintained and requires existing account credentials. The root intentionally declares no provider configuration, so CI receives no Twilio credentials and performs no provider-side API call.

## Ownership boundary

The future root may own only Twilio phone-number inventory and inbound messaging-webhook configuration. `kustomize-cluster` remains the owner of the OpenCode bridge workload, workload `TunnelBinding`/DNS, fixed number-to-agent map, approved-source allowlist, runtime secrets, and state-encryption inputs. The root must never create a bridge-worker API key or duplicate a runtime owner.

## Backend and credential contract

The checked-in `.sops.yaml` identifies the approved encryption recipient but no encrypted secret file exists yet. A later, separately reviewed change must:
[`tfroot-aws` PR #43](https://github.com/makeitworkcloud/tfroot-aws/pull/43) created the canonical backend producer: a dedicated private, encrypted, versioned bucket and an exact-repository GitHub OIDC role restricted to the state object, lockfile, and SOPS KMS decrypt/describe access. This root selects that backend through the reusable workflow's `aws-role-to-assume` input and uses S3 native locking. No static AWS backend credential is stored in source or GitHub Actions secrets.

1. establish least-privilege GitHub Actions OIDC access for this exact repository to decrypt SOPS material;
2. add an encrypted backend configuration for a dedicated Twilio state object; and
3. define an existing Twilio credential delivery path that cannot expose a token in source, CI logs, or OpenTofu state.

Only after those prerequisites pass pull-request validation may a later root change add provider configuration or Twilio inventory. Any actual Twilio provisioning or webhook update still requires explicit owner confirmation before merge because `main` invokes the environment-gated apply path.
The checked-in `.sops.yaml` identifies the approved encryption recipient but no encrypted secret file exists yet. A later, separately reviewed change must define a Twilio credential delivery path that cannot expose a token in source, CI logs, or OpenTofu state. Only after that prerequisite passes pull-request validation may a later root change add provider configuration or Twilio inventory. Any actual Twilio provisioning or webhook update still requires explicit owner confirmation before merge because `main` invokes the environment-gated apply path.

## Central generated files

Expand Down
7 changes: 4 additions & 3 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Bootstrap intentionally contains no Twilio resources, data sources, provider
# configuration, or secret material. The next root change must first establish
# the encrypted backend and credential-delivery contract described in docs/bootstrap.md.
# This root has a selected remote backend but intentionally contains no Twilio
# resources, data sources, provider configuration, or secret material. A later
# reviewed change must establish encrypted credential delivery before adding a
# provider block or managing Twilio inventory.
11 changes: 4 additions & 7 deletions providers.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
terraform {
required_version = "> 1.3"

backend "s3" {}

required_providers {
twilio = {
source = "RJPearson94/twilio"
Expand All @@ -9,10 +11,5 @@ terraform {
}
}

# The permanent S3 backend is intentionally omitted until its encrypted
# contract and least-privilege CI access are reviewed in a follow-up PR.
# The bootstrap Makefile initializes with -backend=false.

# No provider block is declared during bootstrap. The candidate provider is
# installed and syntax-validated without receiving credentials or managing
# Twilio resources.
# No provider block is declared. The selected backend is independent of Twilio
# credentials and resource management; those remain separate follow-up gates.
Loading