fix: respect customized OIDC subject claims in azd pipeline config#7705
fix: respect customized OIDC subject claims in azd pipeline config#7705
Conversation
When GitHub organizations customize their OIDC subject claim format (e.g. using repository_owner_id and repository_id instead of the default repo:owner/name format), azd pipeline config now queries the GitHub OIDC customization API to determine the actual subject format before creating federated identity credentials. Changes: - Add GetOIDCSubjectConfig() and GetRepoInfo() methods to github.Cli - Add BuildOIDCSubject() helper to construct correct subject strings - Update credentialOptions() to query OIDC config and build subjects - Add user confirmation prompt with option for manual subject override - Graceful fallback to default format when OIDC API is unavailable Based on initial work in PR #7551 by @charris-msft, with fixes for: - Correct repo vs org fallback (only on 404) - No type assertions to concrete struct - Single repo info fetch (no duplicate API calls) - Error on unknown/empty claim keys - Full unit test coverage Fixes #7374 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates azd pipeline config’s GitHub federated credential generation to respect GitHub Actions OIDC subject-claim customizations (including ID-based subject formats) by querying GitHub’s OIDC customization endpoints and constructing subjects accordingly.
Changes:
- Add GitHub OIDC customization support (
GetOIDCSubjectConfig,GetRepoInfo,BuildOIDCSubject) and unit tests for these helpers. - Update GitHub pipeline credential creation to use detected OIDC subjects, with an interactive confirmation/override prompt (and auto-use in
--no-promptmode). - Add/adjust pipeline tests to cover OIDC-aware credential option behavior and mocking of the OIDC API.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/pkg/tools/github/oidc.go | Implements OIDC customization discovery + subject construction helpers. |
| cli/azd/pkg/tools/github/oidc_test.go | Adds unit tests for OIDC helpers and API fallback logic. |
| cli/azd/pkg/pipeline/github_provider.go | Uses detected OIDC subjects when creating federated credentials; adds optional prompt/override flow. |
| cli/azd/pkg/pipeline/github_provider_test.go | Adds tests validating default/custom/fallback OIDC subject behavior. |
| cli/azd/pkg/pipeline/pipeline_helpers_test.go | Updates existing credentialOptions tests to mock OIDC API behavior. |
| cli/azd/pkg/pipeline/pipeline_coverage3_test.go | Updates branch-special-chars test setup to account for new OIDC API calls. |
- Remove unused params from promptForSubjects - Sort branch names for deterministic display/prompt ordering - Use int64 for RepoInfo IDs to avoid overflow - Add nil-check for repoInfo in BuildOIDCSubject - Fix misleading comment about skip option - Use t.Context() instead of context.Background() in tests - Fix import ordering in pipeline_helpers_test.go Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Tighten isGitHubNotFoundError to match only HTTP 404 signals - Use MessageUxItem with ux.WarningMessage for OIDC fallback warning - Use t.Context() instead of context.Background() in test helpers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix import ordering in oidc_test.go (stdlib → external → azd internal) - Only call GetRepoInfo when ID-based claim keys are present Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Validate custom subject inputs: trim whitespace, reject empty values Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
jongio
left a comment
There was a problem hiding this comment.
Solid work. The repo-to-org-to-default fallback chain is well layered, BuildOIDCSubject correctly constructs the {key}:{value}:...:{context} format matching GitHub's token output, and the explicit error on unsupported claim keys is the right incremental approach. All prior review comments are addressed.
A few optional notes for future consideration:
-
Test gap: org-level non-404 error -
TestGetOIDCSubjectConfigcovers repo 404 falling back to org (success) and repo non-404 error (hard fail), but doesn't cover repo 404 then org returning a non-404 error (e.g. 403). That path exists inGetOIDCSubjectConfigand would be good to verify. -
Test gap:
GetRepoInfoerror path - Only the happy path is tested. A test for API failure or malformed JSON would round out the coverage. -
detectOIDCConfigfallback in--no-promptmode - Any OIDC API error (including 403 permission denied) falls back to default subjects with a warning. In CI (--no-prompt), this could silently create credentials that don't match the org's actual OIDC tokens. Consider either failing hard on non-recoverable errors in--no-promptmode, or logging at a higher severity so it's harder to miss in CI output.
Description
Fixes #7374
Supersedes #7551 (based on initial work by @charris-msft)
When GitHub organizations customize their OIDC subject claim format (e.g. using
repository_owner_idandrepository_idinstead of the defaultrepo:owner/nameformat),azd pipeline confignow queries the GitHub OIDC customization API to determine the actual subject format before creating federated identity credentials.Problem
azd pipeline configalways created federated credentials with the default subject format:But organizations like
microsoftandAzure-Samplesuse customized OIDC subject claims, producing tokens with subjects like:This mismatch caused
AADSTS700213: No matching federated identity record founderrors.Changes
cli/azd/pkg/tools/github/oidc.go(new):OIDCSubjectConfigandRepoInfotypesGetOIDCSubjectConfig()— queries repo-level OIDC API first, falls back to org-level only on 404GetRepoInfo()— fetches numeric repo/owner IDs for ID-based claim keysBuildOIDCSubject()— pure function to construct subject strings from configcli/azd/pkg/pipeline/github_provider.go:credentialOptions()to query OIDC config and build correct subjects--no-promptmode, auto-detected subjects are used without promptingcli/azd/pkg/tools/github/oidc_test.go(new):BuildOIDCSubject,GetOIDCSubjectConfig, andGetRepoInfocli/azd/pkg/pipeline/github_provider_test.go:Improvements over #7551
use_default=trueCliuse_default=false— prevents dangerously broad subjects