Found during the independent review of PR #1657. Pre-existing, and identical before and after that PR — filed rather than folded in. One line to fix.
What
.github/workflows/deploy-all.yml declares no permissions: block — not at workflow level, and not on any of its four caller jobs (deploy-aws-lambda :118, deploy-aws-fargate :132, deploy-gcp :144, deploy-azure :156), each of which invokes a reusable workflow via uses:.
deploy-aws-lambda:
name: Deploy AWS Lambda
needs: determine-deployment
if: needs.determine-deployment.outputs.deploy-aws-lambda == 'true'
uses: ./.github/workflows/deploy-aws-lambda.yml # <- no permissions:
with:
environment: ${{ needs.determine-deployment.outputs.environment }}
Why it matters
A called workflow's permissions: block cannot escalate beyond the caller's — the caller's GITHUB_TOKEN permissions are the ceiling, and the effective set is the intersection. id-token: write is never in the default GITHUB_TOKEN set; it must be requested explicitly.
So when deploy-aws-lambda.yml (or any of the other three) is invoked through deploy-all.yml, it very likely cannot obtain an OIDC token at all, and configure-aws-credentials / azure/login / google-github-actions/auth fails. The multi-cloud "deploy everything" path is the one most likely to be used for a real release, and it is the one that cannot authenticate.
Dispatching deploy-aws-lambda.yml directly still works — that path requests its own permissions and is not capped by a caller.
Not caused by #1657
Worth stating explicitly so nobody bisects to it: deploy-aws-lambda.yml previously declared permissions: id-token: write at workflow level and #1657 moved it to job level. Both forms are equally subject to the caller-intersection cap, so the deploy-all.yml path was already broken before that change and is no more or less broken after it. The defect is entirely in the caller.
Fix
Add the permission to each caller job in deploy-all.yml:
deploy-aws-lambda:
...
permissions:
id-token: write
contents: read
uses: ./.github/workflows/deploy-aws-lambda.yml
Repeat for the other three. Prefer per-job over a workflow-level block, so determine-deployment and notify — neither of which authenticates — do not receive id-token: write; that is the same least-privilege split #1657 applied inside deploy-aws-lambda.yml, and it avoids recreating the ungated-credentialed shape tracked in LeanerCloud/cloud-commitments-platform#140.
Verification note
I have not confirmed this empirically — doing so means dispatching a real multi-cloud deploy. It is inferred from documented GitHub behaviour (reusable-workflow permission intersection, and id-token being absent from the default token). Worth a cheap confirmation on a dev-only dispatch before or alongside the fix.
Related: #1657 / #1649, LeanerCloud/cloud-commitments-platform#140 (ungated credentialed jobs in the sibling deploy workflows), #1646.
Found during the independent review of PR #1657. Pre-existing, and identical before and after that PR — filed rather than folded in. One line to fix.
What
.github/workflows/deploy-all.ymldeclares nopermissions:block — not at workflow level, and not on any of its four caller jobs (deploy-aws-lambda:118,deploy-aws-fargate:132,deploy-gcp:144,deploy-azure:156), each of which invokes a reusable workflow viauses:.Why it matters
A called workflow's
permissions:block cannot escalate beyond the caller's — the caller'sGITHUB_TOKENpermissions are the ceiling, and the effective set is the intersection.id-token: writeis never in the defaultGITHUB_TOKENset; it must be requested explicitly.So when
deploy-aws-lambda.yml(or any of the other three) is invoked throughdeploy-all.yml, it very likely cannot obtain an OIDC token at all, andconfigure-aws-credentials/azure/login/google-github-actions/authfails. The multi-cloud "deploy everything" path is the one most likely to be used for a real release, and it is the one that cannot authenticate.Dispatching
deploy-aws-lambda.ymldirectly still works — that path requests its own permissions and is not capped by a caller.Not caused by #1657
Worth stating explicitly so nobody bisects to it:
deploy-aws-lambda.ymlpreviously declaredpermissions: id-token: writeat workflow level and #1657 moved it to job level. Both forms are equally subject to the caller-intersection cap, so thedeploy-all.ymlpath was already broken before that change and is no more or less broken after it. The defect is entirely in the caller.Fix
Add the permission to each caller job in
deploy-all.yml:Repeat for the other three. Prefer per-job over a workflow-level block, so
determine-deploymentandnotify— neither of which authenticates — do not receiveid-token: write; that is the same least-privilege split #1657 applied insidedeploy-aws-lambda.yml, and it avoids recreating the ungated-credentialed shape tracked in LeanerCloud/cloud-commitments-platform#140.Verification note
I have not confirmed this empirically — doing so means dispatching a real multi-cloud deploy. It is inferred from documented GitHub behaviour (reusable-workflow permission intersection, and
id-tokenbeing absent from the default token). Worth a cheap confirmation on a dev-only dispatch before or alongside the fix.Related: #1657 / #1649, LeanerCloud/cloud-commitments-platform#140 (ungated credentialed jobs in the sibling deploy workflows), #1646.