infra/scripts/tg: enforce ingress_factory auth-comment convention
Every `tg plan/apply/destroy/refresh` now runs `scripts/check-ingress-auth-comments.py` against the current stack before invoking terragrunt. The check fails closed if any `auth = "app"` or `auth = "none"` line in the stack's .tf files lacks an immediately-preceding `# auth = "<tier>": ...` comment documenting what gates the app (for "app") or why the endpoint is intentionally public (for "none"). Why tg-level (not git pre-commit): tg is the universal entry point for all infra changes. CI runs it, headless agents run it, humans run it. A pre-commit hook only catches the human path. Wiring the check into tg means the anti-exposure guard fires regardless of who or what is invoking terragrunt. Stack-scoped: each stack documents itself the next time it's edited. The 30+ existing `auth = "none"` stacks that predate this guard are not blocked from operating today; they'll need the comment added the next time someone runs `tg plan` on them — at which point the gate forces a conscious "yes, this is intentional" moment before any state change can land. Skipped on: init, fmt, validate, output, etc. — anything that doesn't read or write infra state.
This commit is contained in:
parent
b91268fef4
commit
0712a1b659
3 changed files with 149 additions and 1 deletions
24
scripts/tg
24
scripts/tg
|
|
@ -102,6 +102,30 @@ for arg in "$@"; do
|
|||
esac
|
||||
done
|
||||
|
||||
# Detect if this is a plan/apply/destroy/refresh — anything that reads or
|
||||
# writes infra state. Cheap pre-flight check below scans only the current
|
||||
# stack's .tf files for the ingress_factory auth-comment convention. Other
|
||||
# tg verbs (init, fmt, validate) skip the check.
|
||||
is_tf_op=false
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
plan|apply|destroy|refresh) is_tf_op=true ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Anti-exposure guard: every `auth = "app"` or `auth = "none"` in this stack
|
||||
# must have a preceding `# auth = "<tier>":` comment documenting what gates
|
||||
# the app or why the endpoint is intentionally public. See:
|
||||
# - infra/modules/kubernetes/ingress_factory/main.tf (variable description)
|
||||
# - infra/.claude/CLAUDE.md "Auth" section
|
||||
# Stack-scoped: untouched stacks aren't blocked from future applies until
|
||||
# they're actually edited, at which point the convention applies.
|
||||
if $is_tf_op && [ -n "$STACK_NAME" ]; then
|
||||
if ! "$REPO_ROOT/scripts/check-ingress-auth-comments.py" "$REPO_ROOT/stacks/$STACK_NAME"; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Acquire lock for mutating operations (Tier 0 only — Tier 1 uses pg_advisory_lock)
|
||||
if $is_mutating && [ -n "$STACK_NAME" ] && is_tier0 "$STACK_NAME"; then
|
||||
if command -v vault &>/dev/null && [ -n "${VAULT_TOKEN:-}" ]; then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue