Chapter 20Lesson 04~210 minutes

OpenID Connect, Cloud Federation, Trust Policies, and Secretless Deployment: Diagnostics, Failure Modes, and Production Practices

OIDC removes a long-lived secret, but it adds a multi-system diagnostic path. This lesson separates GitHub token-request permission, workload claims, provider trust, provider authorization, and deployment target failures so troubleshooting does not accidentally widen production access.

DiagnosticsClaim mismatchProvider denialToken safetyRecovery

Learning objectives

  • Diagnose federation failure from GitHub run evidence through provider trust and target authorization.
  • Distinguish token-request failures, claim mismatches, provider permission denials, and deployment failures.
  • Preserve the first failed run/attempt and denied-policy evidence before changing trust.
  • Repair unsafe wildcard, global permission, raw-token logging, and static fallback patterns.
  • Apply the least destructive correction and rerun the smallest equivalent scope.

1. OIDC failures are layered, not one “authentication error”

A deployment can fail before a token is requested, while GitHub requests the token, while the provider validates the token, while the provider authorizes the temporary principal, or while the target API performs the deployment. Calling all of these “OIDC failed” hides the evidence needed for a safe repair.

Evidence-first federation diagnostic path
flowchart TD
A[Preserve run ID attempt SHA logs] --> B[Check job id-token permission]
B --> C[Check issuer audience subject claims]
C --> D[Check provider trust conditions]
D --> E[Check temporary principal + lifetime]
E --> F[Check provider IAM/RBAC permissions]
F --> G[Check exact deployment target + artifact]
G --> H[Apply smallest correction]
H --> I[Rerun smallest equivalent scope]

2. Diagnostic sequence

Start by recording the failed run ID and attempt, exact source SHA/ref, workflow revision, job name, environment, runner label/image, and the provider error message. Do not rerun yet. Next inspect the evaluated permissions and confirm whether the failing job was actually eligible to request an ID token.

Then compare the expected issuer/audience/subject/claims with the provider trust rule. If the provider accepted federation and issued a temporary principal, move to provider authorization: role policy, Azure RBAC, Google IAM, resource identity, and the target API. Finally verify the external target. This sequence prevents “fixes” that broaden trust when the real problem was a resource permission or wrong target.

3. Failure mode: granting id-token: write globally

# Over-broad: every job can request an OIDC token.
permissions:
  contents: read
  id-token: write

The workflow may still be safe if provider trust is narrow, but the token-request capability is unnecessarily available to build/test jobs and every action they execute. Repair by moving id-token: write to the credential-bearing job. This is a GitHub configuration correction, not a provider trust-policy change.

4. Failure mode: organization-wide wildcard trust

Unsafe intent:
"Any repository owned by acme-labs may assume production."

Repair intent:
"Only repository ID 400500600, production environment,
expected audience, and approved deployment workflow may assume production."

Do not “temporarily” widen the wildcard further to debug a denial. Compare the denied claims with the narrow intended policy. If the policy is wrong, update only the mismatched condition after confirming the expected workload identity.

5. Failure mode: confusing token minting with cloud authorization

A job can successfully request a GitHub OIDC token and still receive an AWS AccessDenied, Microsoft Entra federation error, or Google STS/IAM denial. This is expected separation. GitHub token issuance proves only that the job had id-token: write and GitHub produced a token; it does not prove the cloud trusts that identity or grants target permissions.

Evidence Likely layer Next inspection
OIDC request variables unavailable / action says ID token permission missing GitHub permissions Job/workflow permissions, reusable caller chain
Provider says audience/subject/claim mismatch Provider trust Actual claim format versus exact trust condition
Temporary principal exists but resource call is denied Provider authorization Role/RBAC/IAM permission and resource scope
Provider call succeeds but service is unhealthy Deployment/target Artifact digest, target identity, rollout health/logs

6. Failure mode: logging or artifacting a raw token

Never print the OIDC JWT to “see the claims,” and never upload it as an artifact. The token is short-lived but usable while valid. If an incident already exposed it, preserve only the surrounding run/log metadata, remove unsafe retained copies, and investigate provider audit records for use during the token's lifetime.

For learning, use the synthetic claim files from Lesson 2. For production debugging, use provider diagnostics, known claim metadata, or an approved claim-inspection mechanism that does not normalize raw credential disclosure.

7. Failure mode: retaining a static fallback key indefinitely

Teams sometimes enable OIDC but leave the old static key in repository secrets “just in case.” That means the long-lived credential risk remains, and future workflow edits may silently fall back to it. The migration is incomplete until the provider key is revoked/deleted and the corresponding GitHub secret is removed after a controlled validation window.

A temporary break-glass mechanism, if required by policy, should be independently controlled, time-bounded, audited, and not automatically available to every workflow run.

8. Failure mode: trusting a mutable branch without deployment protection

A rule that grants production federation to refs/heads/main may be acceptable only when repository governance makes that branch sufficiently controlled. If arbitrary pushes can reach it, the cloud trust boundary inherits that weakness. Environment protection, required checks, reviewed reusable workflows, and immutable artifact promotion can strengthen the path.

Do not confuse a branch name with an immutable source revision. The provider may trust the ref as an authorization condition, while the evidence packet must still record the exact GITHUB_SHA and artifact digest that deployed.

9. Intentionally broken example: immutable subject migration mismatch

Assume a repository created in August 2026 produces the synthetic immutable subject repo:acme-labs@100200300/widget-api@400500600:environment:production, but the provider still expects the older name-only subject repo:acme-labs/widget-api:environment:production. The provider correctly denies the request.

first_failed_run=912340
attempt=1
sha=0123456789abcdef0123456789abcdef01234567
expected_by_provider=repo:acme-labs/widget-api:environment:production
presented_identity=repo:acme-labs@100200300/widget-api@400500600:environment:production
provider_decision=DENY
cause=subject format mismatch

The repair is not to replace the provider subject with repo:acme-labs/*. Preserve run 912340/attempt 1, confirm the repository's actual current subject format, update the provider rule to the exact intended immutable identity, and rerun the smallest equivalent deployment-auth job. Record the new run separately.

10. Provider-specific diagnostics without weakening trust

AWS: inspect the role trust conditions, audience, documented GitHub condition keys, STS error, assumed-role identity, and CloudTrail events. Never solve a mismatch by changing the trust policy to *.

Azure: inspect the federated identity credential issuer/subject/audience, tenant/application identity, and Azure RBAC. A successful azure/login does not prove permission to deploy every Azure resource.

Google Cloud: inspect the full Workload Identity Provider resource name, attribute mappings/condition, project number versus project ID, service-account impersonation binding if used, and audit logs. Provider/IAM changes can be eventually consistent; preserve the initial denial rather than repeatedly modifying multiple layers at once.

11. Reruns can repeat side effects

If federation succeeded and the failure happened after a deployment API call, a rerun may repeat the side effect. Before rerunning, inspect whether the target was partially changed and whether the deployment operation is idempotent. OIDC changes credential acquisition; it does not make deployments automatically safe to replay.

12. Lesson summary

  • Classify failure as GitHub permission, claim/trust, provider authorization, or deployment/target failure.
  • Preserve first-failure evidence before any policy change or rerun.
  • Never broaden trust or log raw tokens as a diagnostic shortcut.
  • Remove long-lived fallback keys after successful federation migration.
  • Repair the smallest causal layer and verify target state before rerunning side effects.
Next lesson

Checkpoint Lab — OpenID Connect, Cloud Federation, Trust Policies, and Secretless Deployment

Continue with the next lesson to build on the current concepts, evidence, security boundaries, and operational practices.

Knowledge check

The provider says the OIDC subject does not match. Should you temporarily change it to repo:ORG/*?

A provider auth action succeeds but the deployment API returns 403. What layer failed?

Why is printing a raw OIDC JWT unsafe even though it is short-lived?

What must be checked before rerunning a failed deployment after federation succeeded?

An August 2026 repository is denied by a provider expecting an old name-only subject. What is the safe repair?

Official references and version notes

Version-sensitive GitHub Actions and provider behavior in this lesson was rechecked on 2026-09-10. Re-verify current OIDC subject format, provider trust syntax, action release SHAs, plan/visibility constraints, and temporary-credential lifetimes before production use.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.