Context
Track: B — Org/infrastructure governance
Pillar: 3 — Modern Secret Management & Identity Federation
Parent: (see GitHub Actions platform security parent)
Why static credentials are the wrong model
A static AWS access key stored as a GitHub secret is valid until someone manually rotates it. If it leaks — via a log, a compromised runner, or a supply chain attack — it remains exploitable until noticed. OIDC eliminates the credential entirely: the workflow exchanges its GitHub-signed identity token for a short-lived cloud token scoped to the exact job.
What we already have (partial coverage)
This issue extends the same pattern to cloud provider authentication.
OIDC for cloud providers
AWS
jobs:
deploy:
permissions:
id-token: write # required for OIDC
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/github-actions-deploy
aws-region: ca-central-1
role-session-name: ${{ github.repository }}-${{ github.run_id }}
AWS trust policy — bind to specific repo and branch, not the whole org:
{
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:sparkgeo/prescient-platform:ref:refs/heads/main"
}
}
}
Custom property claims (org-level fine-graining)
GitHub org custom properties can be included in the OIDC token, enabling trust policies that filter on org metadata rather than repo name lists:
{
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:environment": "production"
}
}
}
This means a production deployment role is only assumable from a workflow running against a production GitHub environment — not from any arbitrary branch or fork.
Environment-scoped secrets
Replace broadly inherited org/repo secrets with environment-scoped secrets:
- Org secrets: only for non-sensitive shared config (
AWS_ACCOUNT_ID, SONAR_HOST_URL)
- Environment secrets (
production, staging): sensitive values scoped to their environment — a staging workflow cannot access production credentials
- Reusable workflow secrets: must be explicitly passed by the caller; they no longer inherit automatically (GitHub policy change)
# Caller must explicitly pass secrets to reusable workflow
jobs:
deploy:
uses: sparkgeo/github-actions/.github/workflows/deploy.yml@main
secrets:
AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }} # explicit, not implicit
Migration checklist
Cross-references
Context
Track: B — Org/infrastructure governance
Pillar: 3 — Modern Secret Management & Identity Federation
Parent: (see GitHub Actions platform security parent)
Why static credentials are the wrong model
A static AWS access key stored as a GitHub secret is valid until someone manually rotates it. If it leaks — via a log, a compromised runner, or a supply chain attack — it remains exploitable until noticed. OIDC eliminates the credential entirely: the workflow exchanges its GitHub-signed identity token for a short-lived cloud token scoped to the exact job.
What we already have (partial coverage)
actions/create-github-app-token@v1— GitHub App short-lived tokens, not static PATsThis issue extends the same pattern to cloud provider authentication.
OIDC for cloud providers
AWS
AWS trust policy — bind to specific repo and branch, not the whole org:
{ "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:sparkgeo/prescient-platform:ref:refs/heads/main" } } }Custom property claims (org-level fine-graining)
GitHub org custom properties can be included in the OIDC token, enabling trust policies that filter on org metadata rather than repo name lists:
{ "Condition": { "StringEquals": { "token.actions.githubusercontent.com:environment": "production" } } }This means a production deployment role is only assumable from a workflow running against a
productionGitHub environment — not from any arbitrary branch or fork.Environment-scoped secrets
Replace broadly inherited org/repo secrets with environment-scoped secrets:
AWS_ACCOUNT_ID,SONAR_HOST_URL)production,staging): sensitive values scoped to their environment — a staging workflow cannot access production credentialsMigration checklist
productionandstagingGitHub environments with environment protection rules (required reviewers, deployment branches)docs/oidc-trust-policies.mdin this repoCross-references
permissions: id-token: writeis required at job level for OIDC and is part of the authoring standard