feat(auth): Add Azure OIDC/Workload Identity Federation provider#1894
feat(auth): Add Azure OIDC/Workload Identity Federation provider#1894
Conversation
|
Warning Changelog Entry RequiredThis PR is labeled Action needed: Add a new blog post in Example filename: Alternatively: If this change doesn't require a changelog entry, remove the |
|
Warning This PR exceeds the recommended limit of 1,000 lines.Large PRs are difficult to review and may be rejected due to their size. Please verify that this PR does not address multiple issues. |
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
📝 WalkthroughWalkthroughAdds a new Azure OIDC (Workload Identity Federation) auth provider, registers it in the provider factory, implements federated-token sourcing (file/env/GitHub Actions) and Azure AD token exchange, extends Azure MSAL/CLI environment wiring and token cache for service principals, updates tests, and adds docs and a small CLI tweak. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor CLI as Atmos CLI
participant Provider as Azure OIDC Provider
participant TokenSource as Token Source (File / Env / GitHub Actions)
participant AzureAD as Azure AD Token Endpoint
participant Runtime as Runtime (Terraform / ARM)
CLI->>Provider: Authenticate(ctx)
Provider->>TokenSource: ReadFederatedToken()
alt token_file_path configured
TokenSource-->>Provider: federated_token (file)
else AZURE_FEDERATED_TOKEN_FILE set
TokenSource-->>Provider: federated_token (env path)
else GitHub Actions detected
Provider->>TokenSource: Fetch GitHub Actions ID token (audience if set)
TokenSource-->>Provider: federated_token (GH OIDC)
end
Provider->>AzureAD: POST /token (grant_type=jwt-bearer, assertion, client_id, scope)
AzureAD-->>Provider: access_token / expires_in / error
alt success
Provider-->>CLI: AzureCredentials (+ClientID, IsServicePrincipal, TokenFilePath, FederatedToken)
CLI->>Runtime: Run with env (ARM_USE_OIDC, ARM_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, ...)
else error
Provider-->>CLI: authentication error
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (4)
🧰 Additional context used📓 Path-based instructions (4)website/**📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
website/docs/cli/commands/**/*.mdx📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
**/*_test.go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
🧠 Learnings (13)📚 Learning: 2024-12-01T00:33:20.298ZApplied to files:
📚 Learning: 2025-04-25T20:54:19.701ZApplied to files:
📚 Learning: 2025-01-19T22:30:27.600ZApplied to files:
📚 Learning: 2025-12-16T18:20:55.630ZApplied to files:
📚 Learning: 2025-09-07T18:07:00.549ZApplied to files:
📚 Learning: 2025-10-07T00:25:16.333ZApplied to files:
📚 Learning: 2025-09-10T17:34:52.568ZApplied to files:
📚 Learning: 2025-09-05T14:57:37.360ZApplied to files:
📚 Learning: 2025-11-07T14:52:55.217ZApplied to files:
📚 Learning: 2025-09-13T16:39:20.007ZApplied to files:
📚 Learning: 2025-12-16T18:20:55.630ZApplied to files:
📚 Learning: 2025-12-21T04:10:29.030ZApplied to files:
📚 Learning: 2025-12-13T06:10:25.156ZApplied to files:
🧬 Code graph analysis (1)pkg/auth/cloud/azure/setup_test.go (3)
🪛 Gitleaks (8.30.0)pkg/auth/cloud/azure/setup_test.go[high] 919-919: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) ⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
🔇 Additional comments (13)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1894 +/- ##
==========================================
+ Coverage 73.47% 73.59% +0.11%
==========================================
Files 633 634 +1
Lines 58652 59027 +375
==========================================
+ Hits 43097 43443 +346
- Misses 12587 12596 +9
- Partials 2968 2988 +20
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
📝 WalkthroughWalkthroughThis PR introduces Azure OIDC/workload identity federation authentication support. It adds a new provider kind to the authentication factory, implements the full Azure OIDC provider with token exchange logic, covers it with comprehensive unit tests, and includes blog documentation explaining the feature. Changes
Sequence DiagramsequenceDiagram
participant App as Application
participant Provider as Azure OIDC Provider
participant TokenSrc as Token Source<br/>(File/GitHub/Env)
participant AzureAD as Azure AD
participant Creds as Credentials
App->>Provider: Authenticate(ctx)
Provider->>Provider: Validate config (tenant_id, client_id)
rect rgb(200, 220, 255)
Note over Provider,TokenSrc: Federated Token Retrieval
Provider->>TokenSrc: Read token (priority: file → env → GitHub)
alt GitHub Actions
TokenSrc->>TokenSrc: Detect GITHUB_ACTIONS env var
TokenSrc->>AzureAD: Request token from ACTIONS_ID_TOKEN_REQUEST_URL
AzureAD-->>TokenSrc: OIDC token
else Environment/File
TokenSrc-->>Provider: Token from env var or file
end
TokenSrc-->>Provider: Federated token
end
rect rgb(220, 240, 200)
Note over Provider,AzureAD: Token Exchange
Provider->>AzureAD: POST token endpoint (client_credentials)
Note over AzureAD: OAuth2 exchange: federated token → access token
AzureAD-->>Provider: Access token + expiration
end
Provider->>Creds: Build Azure credentials
Creds-->>App: Return ICredentials
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–30 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
website/blog/2025-12-19-azure-oidc-provider.mdx (1)
43-55: Consider enhancing the workflow example.The workflow snippet correctly shows
id-token: writepermission. You might consider adding a brief note that Atmos automatically detects the GitHub Actions environment and usesACTIONS_ID_TOKEN_REQUEST_URL/ACTIONS_ID_TOKEN_REQUEST_TOKENwhen notoken_file_pathis configured.pkg/auth/providers/azure/oidc_test.go (1)
685-693: ExchangeToken test validates patterns but doesn't exercise the actual function.The comment correctly notes the limitation - since the token endpoint is a constant, the actual
exchangeTokenfunction isn't called here. This scaffolding validates request/response patterns. Consider introducing an HTTP client interface for full testability in a follow-up.pkg/auth/providers/azure/oidc.go (1)
276-276: Consider propagating context through the call chain.
context.Background()works fine here given the 30s timeout on the HTTP client. For consistency and proper cancellation support, you could refactorreadFederatedTokento accept context fromAuthenticate. Not blocking.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
pkg/auth/factory/factory.go(1 hunks)pkg/auth/providers/azure/oidc.go(1 hunks)pkg/auth/providers/azure/oidc_test.go(1 hunks)website/blog/2025-12-19-azure-oidc-provider.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in thewebsite/directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
website/blog/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...
Files:
pkg/auth/factory/factory.gopkg/auth/providers/azure/oidc_test.gopkg/auth/providers/azure/oidc.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Files:
pkg/auth/providers/azure/oidc_test.go
🧠 Learnings (5)
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Define interfaces for all major functionality and use dependency injection for testability; generate mocks with go.uber.org/mock/mockgen
Applied to files:
pkg/auth/providers/azure/oidc_test.go
🧬 Code graph analysis (3)
pkg/auth/factory/factory.go (1)
pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(102-133)
pkg/auth/providers/azure/oidc_test.go (2)
errors/errors.go (4)
ErrInvalidProviderConfig(537-537)ErrInvalidProviderKind(536-536)ErrLogoutNotSupported(618-618)ErrAuthenticationFailed(538-538)pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(102-133)
pkg/auth/providers/azure/oidc.go (5)
pkg/perf/perf.go (1)
Track(121-138)errors/errors.go (2)
ErrInvalidProviderConfig(537-537)ErrLogoutNotSupported(618-618)pkg/logger/log.go (1)
Debug(24-26)pkg/auth/types/azure_credentials.go (1)
AzureCredentials(16-27)pkg/auth/cloud/azure/env.go (1)
PrepareEnvironmentConfig(46-51)
🪛 Gitleaks (8.30.0)
pkg/auth/providers/azure/oidc_test.go
[high] 497-497: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 507-507: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Summary
🔇 Additional comments (12)
pkg/auth/factory/factory.go (1)
34-35: LGTM!Clean integration following the established factory pattern. The new
azure/oidccase is correctly positioned alphabetically and properly delegates toNewOIDCProvider.website/blog/2025-12-19-azure-oidc-provider.mdx (1)
1-6: Front matter looks good.The structure follows the required blog format with proper YAML front matter, truncate marker, and valid tag. As per coding guidelines, "feature" is a valid tag from tags.yml.
pkg/auth/providers/azure/oidc_test.go (3)
492-507: Static analysis false positives - test tokens are fine.Gitleaks flagged these JWT-like test tokens as "Generic API Key." These are intentionally crafted test fixtures, not real secrets. The format resembles JWTs for realistic testing.
596-602: Environment handling works but has a subtlety.The
t.Setenv+os.Unsetenvpattern is intentional to truly unset the variable (sincet.Setenv("VAR", "")sets it to empty string, not unset). This works correctly for testing absence of environment variables.
19-161: Comprehensive table-driven tests for provider construction.Good coverage of valid configs, missing required fields, nil/empty specs, and wrong provider kind. Error assertions use
errors.Iscorrectly per guidelines.pkg/auth/providers/azure/oidc.go (7)
22-37: Constants are well-defined and appropriately scoped.Good use of constants for timeout, endpoints, and OAuth parameters. This makes the code maintainable and self-documenting.
152-194: Authentication flow is solid.Clean three-step process: read federated token, exchange for Azure token, return credentials. Debug logging appropriately avoids sensitive data.
227-230: Error wrapping with multiple %w is valid.Go 1.20+ supports multiple
%wverbs for wrapping multiple errors. This correctly wraps bothErrAuthenticationFailedand the underlying OS error forerrors.Is()checks.
397-434: Environment preparation correctly configures OIDC mode.Good use of shared
azureCloud.PrepareEnvironmentfor common setup, then OIDC-specific overrides. Explicitly removingARM_USE_CLIand settingARM_USE_OIDC=trueensures Terraform uses the right auth method.
436-441: Logout behavior is correct for ephemeral credentials.OIDC tokens are short-lived and not cached locally, so logout is appropriately a no-op. The
ErrLogoutNotSupportedreturn follows the pattern used by other providers.
225-238: Token file reading is straightforward and secure.File reads use standard library, tokens are trimmed and validated for non-empty. For CI/CD environments, file permissions are typically managed externally. The implementation correctly avoids logging token contents.
1-20: Well-organized imports and package structure.Imports follow the three-group pattern (stdlib, third-party, atmos). The package-level organization is clean with constants, types, then functions.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
pkg/auth/providers/azure/oidc.go (2)
276-279: Consider propagating context to GitHub Actions token fetch.
fetchGitHubActionsTokenusescontext.Background()rather than accepting a context parameter. This means cancellation/timeout from the caller won't apply to this HTTP request.Proposed fix
-// fetchGitHubActionsToken fetches an OIDC token from GitHub Actions. -func (p *oidcProvider) fetchGitHubActionsToken() (string, error) { +// fetchGitHubActionsToken fetches an OIDC token from GitHub Actions. +func (p *oidcProvider) fetchGitHubActionsToken(ctx context.Context) (string, error) { defer perf.Track(nil, "azure.oidcProvider.fetchGitHubActionsToken")() // ... - req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, reqURL.String(), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL.String(), nil)Then update the caller at line 219:
- return p.fetchGitHubActionsToken() + return p.fetchGitHubActionsToken(context.Background())Or better, thread context through
readFederatedTokenas well.
225-238: Double-wrapped error sentinel.Line 229 wraps
ErrAuthenticationFailedand then wraps the OS error with%wagain. This creates a chain with two%wverbs which can cause issues witherrors.Is()in some scenarios.Proposed fix
- if err != nil { - return "", fmt.Errorf("%w: failed to read federated token file %q: %w", errUtils.ErrAuthenticationFailed, path, err) - } + if err != nil { + return "", fmt.Errorf("%w: failed to read federated token file %q: %v", errUtils.ErrAuthenticationFailed, path, err) + }Use
%vfor the nested OS error to avoid double-wrapping, or useerrors.Joinfor multiple wrapped errors per coding guidelines.pkg/auth/providers/azure/oidc_test.go (2)
596-606:os.Unsetenvaftert.Setenvmay not behave as expected.
t.Setenvcaptures the original value and restores it after the test. Callingos.Unsetenvafterward modifies the environment, but cleanup still restores the original. Consider using onlyt.Setenv("")or restructuring to avoid the double-handling.Simplified approach
- if tt.unsetEnv { - t.Setenv("GITHUB_ACTIONS", "") - // Clear the env var entirely. - os.Unsetenv("GITHUB_ACTIONS") - } else { - t.Setenv("GITHUB_ACTIONS", tt.envValue) - } + if tt.unsetEnv { + os.Unsetenv("GITHUB_ACTIONS") + } else { + t.Setenv("GITHUB_ACTIONS", tt.envValue) + }If
t.Setenvis needed for cleanup, manually save and restore instead.
609-694: ExchangeToken test validates server setup but doesn't invokeexchangeToken.The test comment acknowledges this limitation. Since the token endpoint URL is a constant, the actual
exchangeTokenmethod isn't called. Consider introducing an interface or making the HTTP client/endpoint injectable for full unit test coverage.Based on learnings, prefer interfaces + dependency injection for testability.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
pkg/auth/factory/factory.go(1 hunks)pkg/auth/providers/azure/oidc.go(1 hunks)pkg/auth/providers/azure/oidc_test.go(1 hunks)website/blog/2025-12-19-azure-oidc-provider.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in thewebsite/directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
website/blog/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...
Files:
pkg/auth/factory/factory.gopkg/auth/providers/azure/oidc_test.gopkg/auth/providers/azure/oidc.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Files:
pkg/auth/providers/azure/oidc_test.go
🧠 Learnings (4)
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/auth/providers/azure/oidc_test.go
🧬 Code graph analysis (2)
pkg/auth/factory/factory.go (1)
pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(102-133)
pkg/auth/providers/azure/oidc_test.go (2)
errors/errors.go (4)
ErrInvalidProviderConfig(537-537)ErrInvalidProviderKind(536-536)ErrLogoutNotSupported(618-618)ErrAuthenticationFailed(538-538)pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(102-133)
🪛 Gitleaks (8.30.0)
pkg/auth/providers/azure/oidc_test.go
[high] 497-497: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 507-507: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Summary
🔇 Additional comments (9)
pkg/auth/factory/factory.go (1)
34-35: LGTM!Clean integration. The new case follows the established pattern and properly delegates validation to the provider constructor.
pkg/auth/providers/azure/oidc.go (2)
152-194: Solid authentication flow.Token retrieval, exchange, and credential construction are well-structured. Error propagation is clear and expiration calculation is straightforward.
397-434: Environment preparation looks good.Properly clears
ARM_USE_CLI, setsARM_USE_OIDC=true, and handles token file path from both config and environment. Integration with the sharedazureCloud.PrepareEnvironmentis clean.pkg/auth/providers/azure/oidc_test.go (4)
489-508: Static analysis false positive - test JWT tokens are safe.Gitleaks flagged these as "Generic API Key" but they're clearly test fixture JWT tokens (
eyJhbGciOiJSUzI1NiJ9.test.signature). No action needed.
19-161: Excellent table-driven test coverage forNewOIDCProvider.Covers valid configs, missing required fields, nil/empty specs, and wrong provider kinds. Uses
errors.Is()for error checking per guidelines.
328-437: ThoroughPrepareEnvironmenttests.Good coverage of OIDC-specific behavior:
ARM_USE_OIDC=true,ARM_USE_CLIremoval, token file path propagation, and credential clearing. Assertions are clear.
790-871: Token source priority tests are solid.Validates config file path > env var > GitHub Actions fallback chain correctly.
website/blog/2025-12-19-azure-oidc-provider.mdx (2)
1-6: Front matter is correct. Bothjamengualandfeatureare properly defined in their respective YAML files.
59-60: Documentation link is correct.The link
/stacks/authon line 59 resolves properly to the existingwebsite/docs/stacks/auth.mdxfile. No changes needed.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pkg/auth/providers/azure/oidc.go (1)
271-335: Consider accepting context parameter for cancellation support.The
fetchGitHubActionsTokenmethod creates a newcontext.Background()on line 302, but the parentAuthenticatemethod receives acontext.Contextparameter that could be passed down. This would allow proper cancellation and timeout propagation.🔎 Suggested refactor
Update the method signature and use the passed context:
-func (p *oidcProvider) fetchGitHubActionsToken() (string, error) { +func (p *oidcProvider) fetchGitHubActionsToken(ctx context.Context) (string, error) { defer perf.Track(nil, "azure.oidcProvider.fetchGitHubActionsToken")() // ... existing code ... - req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, reqURL.String(), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL.String(), nil)And update the call site in
Authenticate:- return p.fetchGitHubActionsToken() + return p.fetchGitHubActionsToken(ctx)Similar consideration for
readFederatedTokenif it needs to callfetchGitHubActionsToken.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
pkg/auth/factory/factory.go(1 hunks)pkg/auth/providers/azure/oidc.go(1 hunks)pkg/auth/providers/azure/oidc_test.go(1 hunks)website/blog/2025-12-19-azure-oidc-provider.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in thewebsite/directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
website/blog/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...
Files:
pkg/auth/factory/factory.gopkg/auth/providers/azure/oidc_test.gopkg/auth/providers/azure/oidc.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Files:
pkg/auth/providers/azure/oidc_test.go
🧠 Learnings (5)
📓 Common learnings
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: internal/auth/providers/github/oidc.go:83-90
Timestamp: 2025-09-09T16:38:11.538Z
Learning: For GitHub OIDC provider implementations, the audience field is required in the provider spec configuration. The audience claim in OIDC tokens specifies the intended recipient and is essential for proper token validation and security.
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Applied to files:
pkg/auth/providers/azure/oidc_test.go
🧬 Code graph analysis (2)
pkg/auth/factory/factory.go (1)
pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(112-143)
pkg/auth/providers/azure/oidc_test.go (3)
errors/errors.go (4)
ErrInvalidProviderConfig(537-537)ErrInvalidProviderKind(536-536)ErrLogoutNotSupported(618-618)ErrAuthenticationFailed(538-538)pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(112-143)pkg/auth/types/azure_credentials.go (1)
AzureCredentials(16-27)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Summary
🔇 Additional comments (2)
pkg/auth/factory/factory.go (1)
34-35: LGTM!The factory integration for the new Azure OIDC provider is clean and follows the established pattern. The provider kind is correctly ordered alphabetically with other Azure providers.
pkg/auth/providers/azure/oidc_test.go (1)
1-1168: Excellent test coverage!The test suite is comprehensive and well-structured:
- Table-driven tests for multiple scenarios ✓
- HTTP interactions tested with httptest ✓
- Error cases verified with errors.Is() ✓
- Dependency injection tested (httpClient, tokenEndpoint) ✓
- Edge cases covered (whitespace, empty values, missing env vars) ✓
- End-to-end authentication flow validated ✓
This clearly meets the >80% coverage requirement and tests behavior rather than implementation.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
pkg/auth/providers/azure/oidc.go (2)
39-42: Consider reusing existing HTTP client interface.
HTTPDoerduplicatespkg/http/client.Client. You could import the existing interface for consistency, though local definition works fine for testing.
301-305: Consider accepting context parameter.
fetchGitHubActionsTokenusescontext.Background()but could accept a context for cancellation/timeout propagation. Low priority since the HTTP client already has a timeout.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
pkg/auth/factory/factory.go(1 hunks)pkg/auth/providers/azure/oidc.go(1 hunks)pkg/auth/providers/azure/oidc_test.go(1 hunks)website/blog/2025-12-19-azure-oidc-provider.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in thewebsite/directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in thewebsite/directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
website/blog/**/*.mdx
📄 CodeRabbit inference engine (CLAUDE.md)
website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags
Files:
website/blog/2025-12-19-azure-oidc-provider.mdx
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...
Files:
pkg/auth/factory/factory.gopkg/auth/providers/azure/oidc_test.gopkg/auth/providers/azure/oidc.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Files:
pkg/auth/providers/azure/oidc_test.go
🧠 Learnings (6)
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Define interfaces for all major functionality and use dependency injection for testability; generate mocks with go.uber.org/mock/mockgen
Applied to files:
pkg/auth/providers/azure/oidc_test.go
🧬 Code graph analysis (2)
pkg/auth/factory/factory.go (1)
pkg/auth/providers/azure/oidc.go (1)
NewOIDCProvider(112-143)
pkg/auth/providers/azure/oidc.go (8)
pkg/perf/perf.go (1)
Track(121-138)errors/errors.go (3)
ErrInvalidProviderConfig(537-537)ErrInvalidProviderKind(536-536)ErrLogoutNotSupported(618-618)pkg/http/client.go (1)
Client(19-22)pkg/auth/types/azure_credentials.go (1)
AzureCredentials(16-27)website/src/theme/BlogPostItem/Header/index.tsx (1)
Header(8-10)pkg/schema/schema.go (1)
Validate(240-242)pkg/auth/cloud/azure/env.go (1)
PrepareEnvironmentConfig(46-51)pkg/auth/types/interfaces.go (1)
Path(31-53)
🪛 Gitleaks (8.30.0)
pkg/auth/providers/azure/oidc_test.go
[high] 499-499: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 509-509: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Summary
🔇 Additional comments (28)
website/blog/2025-12-19-azure-oidc-provider.mdx (2)
8-60: LGTM!Good structure - truncate marker in place, clear sections, practical examples. The GitHub Actions workflow snippet correctly shows
id-token: writepermission which is essential for OIDC.
1-6: Front matter is correct. The author "jamengual" exists inwebsite/blog/authors.ymland the "feature" tag is valid perwebsite/blog/tags.yml. All required fields are present and properly configured.pkg/auth/factory/factory.go (1)
34-35: LGTM!Clean integration following the established factory pattern. Correctly routes to
NewOIDCProvideralongside existing Azure providers.pkg/auth/providers/azure/oidc_test.go (11)
21-163: LGTM!Solid table-driven tests covering the constructor's happy path and error cases. Good use of
checkProvidercallbacks for detailed assertions.
165-212: LGTM!Clean tests for simple accessor methods. Appropriately concise.
214-328: LGTM!Good validation and environment generation tests with proper boundary cases.
330-439: LGTM!Thorough tests for environment preparation - good coverage of credential isolation and OIDC flag propagation.
491-559: Gitleaks false positive - test tokens are fine.The static analysis flagged lines 499 and 509 as potential API keys, but these are intentionally fake JWT-like strings (
eyJhbGciOiJSUzI1NiJ9.test.signature) for testing token file reading. No real secrets here.
561-609: LGTM!Good coverage of environment variable detection edge cases.
611-719: LGTM!Solid HTTP mock testing for token exchange. Good request verification and error case coverage.
721-854: LGTM!Thorough GitHub Actions OIDC token fetch testing with proper environment setup.
856-936: LGTM!Good integration test for the full authentication flow with type verification.
938-1084: LGTM!Good coverage of helper methods and config extraction with type safety tests.
1086-1168: LGTM!Token source priority tests correctly verify the documented precedence: config file > env var > GitHub Actions.
pkg/auth/providers/azure/oidc.go (14)
1-37: LGTM!Clean imports and well-documented constants for OAuth2 OIDC flow.
44-79: LGTM!Good struct design with DI fields for testability.
81-109: LGTM!Defensive config extraction with proper type assertions.
111-143: LGTM!Clean constructor with proper validation and error wrapping.
145-174: LGTM!Clean accessors and DI-friendly helpers.
176-220: LGTM!Solid authentication flow with proper token exchange and credential construction.
222-249: LGTM!Clear token source priority with helpful error messaging.
251-264: LGTM!Clean file reading with proper whitespace handling.
266-335: LGTM!Good GitHub Actions OIDC integration with proper validation and error handling.
337-390: LGTM!Correct OAuth2 client credentials flow implementation with proper context propagation and error handling.
392-401: LGTM!Consistent validation with constructor requirements.
403-419: LGTM!Clean environment variable generation with proper null checks.
421-458: LGTM!Good reuse of shared Azure environment prep with proper OIDC overrides.
460-476: LGTM!Correct no-op implementations for ephemeral OIDC credentials.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
pkg/auth/providers/azure/oidc_test.go (2)
195-212: Consider removing this stub function test.Per coding guidelines, tests should focus on behavior rather than implementation, and stub functions shouldn't be tested. Since
PreAuthenticateis documented as a no-op, this test adds no value.
494-495: Optional: Silence Gitleaks false positives on test JWT tokens.Static analysis flagged these test JWT tokens as potential secrets. You can add inline
gitleaks:allowcomments to silence these false positives:err := os.WriteFile(tokenPath, []byte("eyJhbGciOiJSUzI1NiJ9.test.signature"), 0o600) // gitleaks:allowAlso applies to: 504-505
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
pkg/auth/providers/azure/oidc_test.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging
**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Adddefer perf.Track(atmosConfig, "pkg.FuncName")()+ blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...
Files:
pkg/auth/providers/azure/oidc_test.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Files:
pkg/auth/providers/azure/oidc_test.go
🧠 Learnings (5)
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Applies to **/*_test.go : Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures
Applied to files:
pkg/auth/providers/azure/oidc_test.go
📚 Learning: 2025-12-16T18:20:55.630Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.630Z
Learning: Define interfaces for all major functionality and use dependency injection for testability; generate mocks with go.uber.org/mock/mockgen
Applied to files:
pkg/auth/providers/azure/oidc_test.go
🧬 Code graph analysis (1)
pkg/auth/providers/azure/oidc_test.go (3)
errors/errors.go (4)
ErrInvalidProviderConfig(537-537)ErrInvalidProviderKind(536-536)ErrLogoutNotSupported(618-618)ErrAuthenticationFailed(538-538)pkg/http/client.go (1)
Client(19-22)pkg/auth/types/azure_credentials.go (1)
AzureCredentials(16-27)
🪛 Gitleaks (8.30.0)
pkg/auth/providers/azure/oidc_test.go
[high] 499-499: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
[high] 509-509: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Acceptance Tests (linux)
- GitHub Check: Acceptance Tests (windows)
- GitHub Check: Acceptance Tests (macos)
- GitHub Check: Summary
🔇 Additional comments (1)
pkg/auth/providers/azure/oidc_test.go (1)
1-1306: Excellent test coverage and implementation.The test suite demonstrates strong quality:
- Comprehensive table-driven tests covering valid configs, edge cases, and error paths
- Proper use of
errors.Is()for error checking throughout- Good HTTP mocking with
httptestfor token exchange flows- Proper environment variable isolation with
t.Setenv()- Clear test organization by functionality (construction, validation, environment prep, token handling, GitHub Actions integration, authentication)
- Edge case coverage for empty tokens, invalid JSON, missing files, and priority logic
This achieves the >90% coverage target mentioned in the PR objectives and follows the coding guidelines well.
|
These changes were released in v1.203.0-test.4. |
Implement the azure/oidc provider for CI/CD environments (GitHub Actions,
Azure DevOps, etc.) where a federated identity token is exchanged for
Azure credentials without storing long-lived secrets.
Key features:
- Federated token exchange with Azure AD
- GitHub Actions OIDC token support
- Environment variable configuration (AZURE_FEDERATED_TOKEN_FILE)
- Token file path configuration
- ARM_USE_OIDC=true for Terraform providers
- Comprehensive unit tests with >90% coverage
Configuration example:
```yaml
auth:
providers:
azure-oidc:
kind: azure/oidc
spec:
tenant_id: "xxx"
client_id: "yyy"
subscription_id: "zzz"
```
|
These changes were released in v1.203.0-test.14. |
This commit adds comprehensive OIDC (Workload Identity Federation) support for both Terraform and Azure CLI when using Azure OIDC authentication. Changes: 1. AzureAuthContext schema (schema.go): - Added UseOIDC, ClientID, TokenFilePath fields for OIDC state 2. AzureCredentials (azure_credentials.go): - Added TokenFilePath field to propagate token file through auth chain 3. OIDC Provider (oidc.go): - Set TokenFilePath in credentials from config or AZURE_FEDERATED_TOKEN_FILE 4. Subscription Identity (subscription.go): - Preserve TokenFilePath through identity chain 5. SetAuthContext (setup.go): - Populate OIDC fields in auth context from credentials 6. PrepareEnvironment (env.go): - Added OIDC support with ARM_USE_OIDC, ARM_CLIENT_ID, AZURE_CLIENT_ID - Set AZURE_FEDERATED_TOKEN_FILE and ARM_OIDC_TOKEN_FILE_PATH when available - Conditionally use ARM_USE_CLI (device-code) or ARM_USE_OIDC (OIDC) 7. SetEnvironmentVariables (setup.go): - Pass OIDC fields to PrepareEnvironment for Terraform execution 8. service_principal_entries.json (setup.go): - Added updateServicePrincipalEntries() for Azure CLI compatibility - Writes client_assertion_file_path pointing to OIDC token file - Enables `az group list` and other CLI commands in CI workflows This follows the AWS implementation pattern where credentials and auth mode are stored in the auth context and propagated to environment variables for Terraform execution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…ries.json Fixed field names to match Azure CLI's ServicePrincipalStore expectations: - client_id (was: servicePrincipalId) - tenant (was: servicePrincipalTenant) - client_assertion (was: client_assertion_file_path) Also fixed to read the actual token content from the file instead of storing the file path, since Azure CLI expects the JWT token value directly in the client_assertion field. Reference: Azure CLI identity.py constants: - _CLIENT_ID = 'client_id' - _TENANT = 'tenant' - _CLIENT_ASSERTION = 'client_assertion' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
These changes were released in v1.203.0-test.15. |
…al entries The previous code tried to read the token from TokenFilePath, but in GitHub Actions the federated token is obtained dynamically via ACTIONS_ID_TOKEN_REQUEST_URL, not from a file. This caused the condition `TokenFilePath != ""` to fail, and service_principal_entries.json was never written. Changes: - Added FederatedToken field to AzureCredentials (not persisted - ephemeral) - OIDC provider stores the federated token during authentication - Subscription identity preserves the federated token through chain - UpdateAzureCLIFiles uses FederatedToken directly instead of reading from file This ensures service_principal_entries.json is written correctly for Azure CLI commands to work after `atmos auth login`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
These changes were released in v1.203.0-test.17. |
Documentation: - Add Azure workflow examples to auth-env (device-code and OIDC) - Add Azure environment variables section (AZURE_*, ARM_* vars) - Add Azure CLI examples to auth-exec command docs - Add CI/CD examples for Azure OIDC authentication Tests: - Add TestCreateServicePrincipalEntry for Azure CLI field names - Add TestUpdateServicePrincipalEntries for service_principal_entries.json - Add TestSetAuthContext_OIDCFields for OIDC field propagation - Add TestSetEnvironmentVariables_OIDC for ARM_USE_OIDC env vars - Add TestUpdateMSALCache_ServicePrincipal for SP cache format - Add FederatedToken preservation test to subscription identity 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
These changes were released in v1.203.0-test.18. |
|
These changes were released in v1.203.0-rc.2. |
what
azure/oidcprovider for CI/CD environments (GitHub Actions, Azure DevOps, etc.)why
azure/cliandazure/device-codeprovidersKey Features
AZURE_FEDERATED_TOKEN_FILEenvironment variabletoken_file_pathin specARM_USE_OIDC=truefor Terraform azurerm/azapi/azuread providersConfiguration Example
references
azure/cliandazure/device-codeprovidersSummary by CodeRabbit
New Features
Documentation
Tests
Bug Fixes
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.