fix: Improve AWS credential isolation and auth error propagation#1712
fix: Improve AWS credential isolation and auth error propagation#1712
Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
📝 WalkthroughWalkthroughThread authContext through Terraform output/template/hook paths; introduce XDG-based AWS credential storage and env preparation; extend auth interfaces with cached credential and environment APIs; simplify noop keyring; add credential-loading helpers, mocks and tests; Make ExecuteTerraform return early on TerraformPreHook errors. Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI Command
participant Manager as Auth Manager
participant Cache as Keyring/File Cache
participant Identity as Identity Storage
participant AWS as AWS SDK
participant TF as Terraform Output
CLI->>Manager: GetCachedCredentials(identity)
Manager->>Cache: Retrieve(identity)
alt cache hit valid
Cache-->>Manager: creds
Manager-->>CLI: WhoamiInfo (cached)
else cache miss or expired
Manager->>Identity: CredentialsExist()
alt exists
Identity-->>Manager: true
Identity->>AWS: LoadCredentials(ctx)
AWS-->>Identity: ICredentials (with Expiration)
Manager->>Cache: Store(identity, creds)
Manager-->>CLI: WhoamiInfo (from storage)
else no creds
Manager-->>CLI: ErrNoCredentialsFound
end
end
CLI->>TF: Request !terraform.output (includes stackInfo)
TF->>Manager: build authContext from stackInfo
TF->>TF: execTerraformOutput(..., authContext)
TF->>AWS: LoadAtmosManagedAWSConfig(ctx) via authContext
AWS-->>TF: AWS env & credentials
TF->>TF: Run terraform and return output
sequenceDiagram
participant Init as pkg/xdg init
participant XDG as adrg/xdg
Init->>Init: detect runtime.GOOS
alt darwin
Init->>XDG: set ConfigHome = ~/.config
Init->>XDG: set DataHome = ~/.local/share
Init->>XDG: set CacheHome = ~/.cache
else
XDG-->>XDG: keep defaults
end
Note over Init,XDG: ensures CLI-style XDG paths on macOS
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Areas needing extra attention:
Possibly related PRs
Suggested labels
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 (1)
🧰 Additional context used📓 Path-based instructions (2)**/*.go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
**/!(*_test).go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
🧬 Code graph analysis (1)internal/exec/shell_utils.go (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
🔇 Additional comments (4)
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: 1
📜 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 (8)
internal/exec/terraform.go(1 hunks)internal/exec/terraform_test.go(2 hunks)pkg/auth/cloud/aws/env.go(2 hunks)pkg/auth/credentials/keyring_noop.go(2 hunks)pkg/auth/identities/aws/user.go(1 hunks)pkg/auth/manager.go(3 hunks)pkg/auth/types/aws_credentials.go(1 hunks)tests/fixtures/scenarios/atmos-auth-invalid/atmos.yaml(1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Generate mocks with go.uber.org/mock/mockgen using //go:generate directives; never write manual mocks
Use functional options pattern instead of functions with many parameters
Use context.Context only for cancellation, deadlines, and narrowly-scoped request values; never for config or dependencies; context should be the first parameter
All comments must end with periods (godot linter)
Organize imports in three groups with blank lines (stdlib, third-party, then Atmos packages) and sort alphabetically; keep aliases: cfg, log, u, errUtils
Error handling: wrap with static errors from errors/errors.go, combine with errors.Join, add context with fmt.Errorf("%w: msg", err), check with errors.Is; never compare strings or create dynamic error types
Use //go:generate go run go.uber.org/mock/mockgen@latest -source= -destination=test.go for mocks
Keep files small and focused (<600 lines), one command/impl per file; co-locate tests; never use //revive:disable:file-length-limit
Bind environment variables with viper.BindEnv and use ATMOS prefix
UI (prompts/status) must write to stderr; data outputs to stdout; logging only for system events, not UI
Ensure cross-platform compatibility: prefer SDKs over binaries and use filepath.Join() instead of hardcoded separators
Files:
internal/exec/terraform.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/cloud/aws/env.gopkg/auth/manager.gopkg/auth/credentials/keyring_noop.gointernal/exec/terraform_test.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
internal/exec/terraform.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/cloud/aws/env.gopkg/auth/manager.gopkg/auth/credentials/keyring_noop.go
{internal,pkg}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
{internal,pkg}/**/*.go: Use interface-driven design: define interfaces, inject dependencies for testability, and prefer DI over concrete coupling
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + a blank line at the start of all public functions (use nil if no atmosConfig)
Files:
internal/exec/terraform.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/cloud/aws/env.gopkg/auth/manager.gopkg/auth/credentials/keyring_noop.gointernal/exec/terraform_test.go
internal/exec/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Implement command business logic in internal/exec/ (not in cmd/)
Files:
internal/exec/terraform.gointernal/exec/terraform_test.go
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/cloud/aws/env.gopkg/auth/manager.gopkg/auth/credentials/keyring_noop.go
pkg/**
📄 CodeRabbit inference engine (CLAUDE.md)
Create purpose-built, focused packages under pkg/ instead of adding to utils; co-locate tests with clear responsibilities
Files:
pkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/cloud/aws/env.gopkg/auth/manager.gopkg/auth/credentials/keyring_noop.go
{**/*_test.go,tests/**}
📄 CodeRabbit inference engine (CLAUDE.md)
Prefer unit tests with mocks over integration; table-driven tests; keep integration tests under tests/; target >80% coverage
Files:
tests/fixtures/scenarios/atmos-auth-invalid/atmos.yamlinternal/exec/terraform_test.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios
**/*_test.go: Test behavior, not implementation; avoid tautological tests; use DI to make behavior testable
Tests must exercise production code paths; do not duplicate logic in tests
Use t.Skipf("reason") with clear context when skipping tests
Files:
internal/exec/terraform_test.go
🧠 Learnings (2)
📚 Learning: 2025-10-03T18:02:08.535Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
Applied to files:
internal/exec/terraform.gointernal/exec/terraform_test.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
pkg/auth/manager.go
🧬 Code graph analysis (4)
pkg/auth/cloud/aws/env.go (1)
errors/errors.go (1)
ErrLoadAwsConfig(74-74)
pkg/auth/manager.go (5)
pkg/auth/credentials/keyring_file.go (1)
ErrCredentialsNotFound(36-36)pkg/logger/log.go (1)
Debug(24-26)errors/errors.go (1)
ErrNoCredentialsFound(386-386)pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/auth/types/interfaces.go (2)
Provider(13-42)Identity(45-69)
pkg/auth/credentials/keyring_noop.go (2)
pkg/perf/perf.go (1)
Track(121-138)pkg/auth/cloud/aws/env.go (1)
LoadAtmosManagedAWSConfig(142-176)
internal/exec/terraform_test.go (3)
pkg/perf/perf.go (1)
Track(121-138)pkg/schema/schema.go (1)
ConfigAndStacksInfo(488-567)internal/exec/terraform.go (1)
ExecuteTerraform(33-623)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build (windows)
- GitHub Check: Build (linux)
- GitHub Check: autofix
- GitHub Check: Lint (golangci)
- GitHub Check: Analyze (go)
- GitHub Check: Review Dependency Licenses
- GitHub Check: Summary
🔇 Additional comments (12)
tests/fixtures/scenarios/atmos-auth-invalid/atmos.yaml (1)
26-26: LGTM!The
name_patternaddition properly extends the test fixture to support the new auth error propagation test scenario.pkg/auth/identities/aws/user.go (1)
181-182: Good documentation improvement.The comment clarifies the credential loading approach, which is helpful given the new
LoadAtmosManagedAWSConfigfunction introduced elsewhere in this PR.pkg/auth/cloud/aws/env.go (1)
96-98: Excellent documentation enhancement.The updated comments clearly distinguish between
LoadIsolatedAWSConfigfor initial authentication andLoadAtmosManagedAWSConfigfor working with Atmos-managed credential files. This helps developers choose the appropriate function.pkg/auth/types/aws_credentials.go (1)
61-63: Good explanatory comments.The notes about circular dependency avoidance and validation approach help clarify the design decisions in this validation method.
pkg/auth/credentials/keyring_noop.go (2)
11-11: Import update aligns with the new config loading strategy.The addition of the
awsCloudpackage import enables use ofLoadAtmosManagedAWSConfigfor credential validation, which is the intended behavior change in this PR.
137-147: Config loading update properly implements the noop keyring isolation strategy.The switch to
LoadAtmosManagedAWSConfigcorrectly enables validation of credentials from Atmos-managed files while preventing interference from external AWS environment variables. The updated comments accurately describe this behavior.pkg/auth/manager.go (3)
14-14: Import addition enables noop keyring detection.The credentials package import is necessary to check for
ErrCredentialsNotFoundin the updated Whoami logic.
180-188: Noop keyring support properly implemented.The updated logic correctly distinguishes between the noop keyring scenario (credentials validated but not stored) and genuinely missing credentials. The use of
errors.Isfor error checking and the fallback tobuildWhoamiInfoFromEnvironmentaligns with the PR's goal of supporting containerized environments with externally-managed credentials.
754-779: Environment-based WhoamiInfo construction correctly handles noop keyring scenario.The function properly constructs a WhoamiInfo when credentials are managed externally. The implementation is clean, and the comments clearly explain the limitations (no credentials/expiration from keyring). Since this is a private function, the absence of godoc and perf tracking is acceptable per the coding guidelines.
internal/exec/terraform.go (1)
236-236: Auth pre-hook error propagation properly implemented.This change correctly ensures that Terraform execution aborts when authentication fails, rather than continuing with potentially invalid credentials. This is a deliberate fix to the previous behavior where errors were only logged, addressing scenarios like user cancellation during SSO authentication.
The change aligns with the new test coverage in
terraform_test.go(TestExecuteTerraform_AuthPreHookErrorPropagation).internal/exec/terraform_test.go (2)
12-12: Import additions support the new test.The
requireandperfimports are appropriately added for the new test function's assertions and performance tracking.Also applies to: 16-16
791-859: Auth pre-hook error propagation test properly implemented.The test effectively verifies that auth pre-hook errors abort Terraform execution. Good practices include performance tracking, cleanup with defer, stderr suppression for cleaner test output, and appropriate use of
requirefor setup andassertfor verification.The error message check (lines 854-858) uses a broad set of keywords which reduces brittleness. Consider using
assert.ErrorContainsif a specific substring is always expected, though the current approach is acceptable.
This commit addresses multiple authentication issues when using Atmos in containerized environments with mounted credential files: ## Changes ### 1. Auth Pre-Hook Error Propagation (terraform.go:236) - **Problem**: Errors from auth pre-hook were logged but not returned, causing terraform execution to continue even when authentication failed (e.g., user presses Ctrl+C during SSO) - **Fix**: Added `return err` after logging auth pre-hook errors - **Impact**: Terraform commands now properly abort on auth failures ### 2. AWS Credential Loading Strategy (pkg/auth/cloud/aws/env.go) - **Problem**: SDK's default config loading allowed IMDS access and was affected by external AWS_PROFILE, causing conflicts in containers - **Solution**: Created `LoadAtmosManagedAWSConfig()` function that: - Clears credential env vars (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) - Preserves profile/path vars (AWS_PROFILE, AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE) - Allows SDK to load from Atmos-managed credential files - **Impact**: Proper isolation while still using Atmos-managed profiles ### 3. Noop Keyring Credential Validation (pkg/auth/credentials/keyring_noop.go) - **Problem**: Used unrestricted `config.LoadDefaultConfig()` which allowed IMDS access and was affected by external AWS_PROFILE - **Fix**: Changed to use `LoadAtmosManagedAWSConfig()` - **Impact**: Container auth now properly isolated from external env vars ### 4. Whoami with Noop Keyring (pkg/auth/manager.go) - **Problem**: `Whoami()` expected credentials from keyring, but noop keyring returns `ErrCredentialsNotFound` by design - **Fix**: Added check for `ErrCredentialsNotFound` and fallback to `buildWhoamiInfoFromEnvironment()` - **Impact**: `atmos auth whoami` now works in containerized environments ### 5. Test Coverage (internal/exec/terraform_test.go) - Added `TestExecuteTerraform_AuthPreHookErrorPropagation` to verify auth errors properly abort execution - Test validates that terraform doesn't continue on auth failure - Updated test fixture to include required `name_pattern` configuration ## Technical Details The key insight is that Atmos sets `AWS_PROFILE=identity-name` but the previous isolation approach cleared ALL AWS env vars including AWS_PROFILE. This caused the SDK to look for a non-existent `[default]` section. The new `LoadAtmosManagedAWSConfig` preserves AWS_PROFILE while still preventing external credential conflicts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
75a252f to
1c1e414
Compare
…ta to AWS credentials files - Added ValidationInfo struct to capture validation results (ARN, account, expiration) from cloud provider APIs - Updated ICredentials.Validate() to return ValidationInfo instead of just expiration time - Enhanced whoami command to validate credentials and display principal (ARN) and account information - Fixed buildWhoamiInfo to preserve credentials in memory for validation (they're excluded from JSON/YAML via tags) - Added x_atmos_expiration metadata key to AWS credentials files for expiration tracking - Implemented LoadCredentials() for all AWS identity types to support noop keyring credential loading - Added comprehensive tests for metadata reading/writing and credential loading - Fixed whoami output formatting (removed extra newline) This enables whoami to show green checkmark when credentials are valid and display full authentication status including ARN, account, region, and expiration time. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
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. |
The test script was consolidated into test-geodesic-prebuilt.sh which is already committed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
website/docs/cli/commands/auth/logout.mdx (1)
198-202: Update documentation: macOS paths use~/.config, not~/Library/Application Support.The implementation in
pkg/xdg/xdg.gooverrides adrg/xdg defaults and applies CLI tool conventions across all platforms including macOS—settingxdg.ConfigHometo~/.config(lines 18-24). This contradicts the documented paths.Update these three sections in
website/docs/cli/commands/auth/logout.mdx:
- Line 198–202: Change macOS path from
~/Library/Application Support/atmos/aws/to~/.config/atmos/aws/- Line 316–327: Troubleshooting example should use
~/.config/atmos/instead of~/Library/Application\ Support/atmos/- Line 401–402: Precedence/default section should reflect
~/.config/atmos/aws/for macOSpkg/auth/types/aws_credentials.go (1)
43-47: Fix double “%w” in fmt.Errorf (compile error).fmt.Errorf allows only one %w. Use %v for the inner error (or errors.Join when appropriate).
Apply this diff:
@@ - return nil, fmt.Errorf("%w: failed parsing AWS credential expiration: %w", errUtils.ErrInvalidAuthConfig, err) + return nil, fmt.Errorf("%w: failed parsing AWS credential expiration: %v", errUtils.ErrInvalidAuthConfig, err) @@ - return nil, fmt.Errorf("%w: failed to validate AWS credentials: %w", errUtils.ErrAuthenticationFailed, err) + return nil, fmt.Errorf("%w: failed to validate AWS credentials: %v", errUtils.ErrAuthenticationFailed, err)As per coding guidelines.
Also applies to: 79-80
website/docs/cli/commands/auth/usage.mdx (1)
49-57: Add terminal punctuation (doc lint).End the “Key Configuration Details” lead‑in with a period to satisfy MD/godot styles.
-**Key Configuration Details:** +**Key Configuration Details:** + +.pkg/auth/manager.go (1)
1-1074: Fix double%wpatterns in error wrapping—eachfmt.Errorfcall supports only one%wplaceholder.The scan confirmed 21 instances in
pkg/auth/manager.gowherefmt.Errorfincorrectly uses two%wplaceholders (lines 140, 149, 170, 204, 214, 228, 292, 327, 340, 539, 611, 654, 854, 872, 887, 905, 998, 1005, 1016, 1042, 1069). This causes compile-time errors.Use
fmt.Errorf("context: %w", err)for wrapping a single error, orerrors.Join(err1, err2)when combining multiple independent errors (per coding guidelines in CLAUDE.md).
🧹 Nitpick comments (36)
internal/exec/yaml_func_terraform_output_test.go (1)
3-14: Fix import grouping (stdlib | third‑party | Atmos).Move testify into third‑party group and keep Atmos imports together. Keeps golangci-lint happy.
import ( "os" "path/filepath" "testing" - log "github.com/cloudposse/atmos/pkg/logger" - "github.com/stretchr/testify/assert" - - cfg "github.com/cloudposse/atmos/pkg/config" - "github.com/cloudposse/atmos/pkg/schema" - u "github.com/cloudposse/atmos/pkg/utils" + "github.com/stretchr/testify/assert" + + cfg "github.com/cloudposse/atmos/pkg/config" + log "github.com/cloudposse/atmos/pkg/logger" + "github.com/cloudposse/atmos/pkg/schema" + u "github.com/cloudposse/atmos/pkg/utils" )internal/exec/template_funcs_component.go (1)
3-13: Tidy import groups.Keep groups ordered and separated: stdlib, third‑party, then Atmos. Move logger with other Atmos imports.
import ( "fmt" "sync" - log "github.com/cloudposse/atmos/pkg/logger" "github.com/samber/lo" cfg "github.com/cloudposse/atmos/pkg/config" + log "github.com/cloudposse/atmos/pkg/logger" "github.com/cloudposse/atmos/pkg/schema" u "github.com/cloudposse/atmos/pkg/utils" )internal/exec/terraform_output_getter.go (1)
42-43: Avoid test races when swapping the global getter.Provide a setter that returns a restore func and guard the variable with a lock. This prevents flakiness in parallel tests.
package exec -// Global variable that can be overridden in tests. -var outputGetter TerraformOutputGetter = &defaultOutputGetter{} +// Global variable that can be overridden in tests. +// Use SetTerraformOutputGetter to change it safely. +var outputGetter TerraformOutputGetter = &defaultOutputGetter{} + +// Protects outputGetter in concurrent scenarios (e.g., parallel tests). +var outputGetterMu sync.RWMutex + +// SetTerraformOutputGetter swaps the global getter and returns a restore function. +func SetTerraformOutputGetter(g TerraformOutputGetter) func() { + outputGetterMu.Lock() + old := outputGetter + outputGetter = g + outputGetterMu.Unlock() + return func() { + outputGetterMu.Lock() + outputGetter = old + outputGetterMu.Unlock() + } +}And add the stdlib import:
-import ( - "github.com/cloudposse/atmos/pkg/perf" - "github.com/cloudposse/atmos/pkg/schema" -) +import ( + "sync" + + "github.com/cloudposse/atmos/pkg/perf" + "github.com/cloudposse/atmos/pkg/schema" +)internal/exec/yaml_func_terraform_output_authcontext_test.go (3)
12-25: Fix godot: comment lines should end with periods.Several comment lines end with “:” instead of “.”, which will trip the godot linter per guidelines. Please add trailing periods.
32-36: Prefer t.Cleanup for global restoration.Use t.Cleanup to restore outputGetter; it ties cleanup to the test lifecycle and avoids surprises if subtests fail early.
- originalGetter := outputGetter - outputGetter = mockOutputGetter - defer func() { outputGetter = originalGetter }() + originalGetter := outputGetter + outputGetter = mockOutputGetter + t.Cleanup(func() { outputGetter = originalGetter })Also applies to: 95-98, 176-179, 222-225
128-212: Add error-path coverage for GetOutput failures.Current tests hit happy paths and exists=false. Please add a case where outputGetter returns an error and assert that ProcessCustomYamlTags propagates it.
+func TestAuthContextPropagatesGetOutputError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockOutputGetter := NewMockTerraformOutputGetter(ctrl) + original := outputGetter + outputGetter = mockOutputGetter + t.Cleanup(func() { outputGetter = original }) + + atmosConfig := &schema.AtmosConfiguration{BasePath: t.TempDir()} + stackInfo := &schema.ConfigAndStacksInfo{ + AuthContext: &schema.AuthContext{AWS: &schema.AWSAuthContext{Profile: "p"}}, + Stack: "s", + } + mockErr := fmt.Errorf("boom") + mockOutputGetter.EXPECT(). + GetOutput(atmosConfig, "s", "c", "o", false, gomock.Any()). + Return(nil, false, mockErr) + + input := schema.AtmosSectionMapType{"value": "!terraform.output c s o"} + _, err := ProcessCustomYamlTags(atmosConfig, input, "s", nil, stackInfo) + assert.Error(t, err) + assert.Contains(t, err.Error(), "boom") +}internal/exec/terraform_output_utils.go (2)
380-381: Style: add blank line after perf.Track for public functions.Matches the project pattern (see ProcessCustomYamlTags).
func GetTerraformOutput( @@ ) (any, bool, error) { - defer perf.Track(atmosConfig, "exec.GetTerraformOutput")() + defer perf.Track(atmosConfig, "exec.GetTerraformOutput")() +
358-372: Doc polish: end bullets with periods.Godot linter requires sentence-ending periods; please add them to the parameter/returns bullets.
pkg/auth/cloud/aws/env.go (1)
147-189: Consider reducing debug logging verbosity.The function includes extensive debug logging that logs file paths, environment variables, and file existence checks. While helpful during development, this level of logging in production code can be noisy. Consider:
- Removing or gating the "=== UPDATED CODE ===" marker (line 147)
- Consolidating the debug statements or moving them behind a higher verbosity level
website/blog/2025-10-24-macos-xdg-cli-conventions.md (3)
142-150: Clarify snippet: define homeDir for completeness.Add a line to show how homeDir is obtained so readers can copy-paste.
func init() { if runtime.GOOS == "darwin" { + homeDir, _ := os.UserHomeDir() xdg.ConfigHome = filepath.Join(homeDir, ".config") xdg.DataHome = filepath.Join(homeDir, ".local", "share") xdg.CacheHome = filepath.Join(homeDir, ".cache") } }
61-64: Tighten phrasing (“prior to” → “before”).Small readability tweak.
-If you're upgrading from versions **prior to v1.195.0**, you're not affected because: +If you're upgrading from versions **before v1.195.0**, you're not affected because:
158-159: Add terminal punctuation to list items.One bullet lacks a trailing period; keep list consistent.
-- [Auth Usage Guide](/cli/commands/auth/usage) - Updated with correct macOS paths +- [Auth Usage Guide](/cli/commands/auth/usage) - Updated with correct macOS paths.pkg/auth/identities/aws/assume_role_test.go (2)
576-622: Harden existence check against ambient env.Seed AWS_* credential env vars with sentinel values to ensure CredentialsExist is purely file-based.
t.Run(tt.name, func(t *testing.T) { + // Ensure ambient credential env vars don't influence existence checks. + t.Setenv("AWS_ACCESS_KEY_ID", "ENV_SHOULD_BE_IGNORED") + t.Setenv("AWS_SECRET_ACCESS_KEY", "ENV_SHOULD_BE_IGNORED") + t.Setenv("AWS_SESSION_TOKEN", "ENV_SHOULD_BE_IGNORED")Optionally add a case where the profile section is missing in the credentials file to assert false.
624-698: Verify LoadCredentials ignores in-process AWS_ env.*This PR introduces LoadAtmosManagedAWSConfig() which clears credential env vars. Assert we load from files even if AWS_* are set.
if tt.setupFiles { t.Setenv("ATMOS_XDG_CONFIG_HOME", tmpDir) + // Set ambient env that must be ignored by the loader. + t.Setenv("AWS_ACCESS_KEY_ID", "ENV_VALUE_SHOULD_NOT_LEAK") + t.Setenv("AWS_SECRET_ACCESS_KEY", "ENV_VALUE_SHOULD_NOT_LEAK") + t.Setenv("AWS_SESSION_TOKEN", "ENV_VALUE_SHOULD_NOT_LEAK")This makes the test validate the isolation behavior end-to-end.
pkg/auth/identities/aws/permission_set_test.go (2)
229-275: Make existence checks resilient to ambient AWS_ env.*Mirror the isolation pattern to avoid false positives.
t.Run(tt.name, func(t *testing.T) { + // Guard against ambient env credentials affecting existence checks. + t.Setenv("AWS_ACCESS_KEY_ID", "ENV_SHOULD_BE_IGNORED") + t.Setenv("AWS_SECRET_ACCESS_KEY", "ENV_SHOULD_BE_IGNORED") + t.Setenv("AWS_SESSION_TOKEN", "ENV_SHOULD_BE_IGNORED")
277-352: Assert LoadCredentials ignores AWS_ env and prefers files.*Strengthen the test to validate the new managed config loader’s isolation.
if tt.setupFiles { t.Setenv("ATMOS_XDG_CONFIG_HOME", tmpDir) + // Seed ambient env to ensure loader ignores in-process credentials. + t.Setenv("AWS_ACCESS_KEY_ID", "ENV_VALUE_SHOULD_NOT_LEAK") + t.Setenv("AWS_SECRET_ACCESS_KEY", "ENV_VALUE_SHOULD_NOT_LEAK") + t.Setenv("AWS_SESSION_TOKEN", "ENV_VALUE_SHOULD_NOT_LEAK")cmd/auth_env.go (2)
62-82: Normalize envVars to avoid JSON null and keep outputs predictable.If GetEnvironmentVariables returns nil, json mode prints null. Guard once before the switch.
- } else { + } else { // Get environment variables WITHOUT authentication/validation // This allows users to see what environment variables would be set // even if they don't have valid credentials yet envVars, err = authManager.GetEnvironmentVariables(identityName) if err != nil { return fmt.Errorf("failed to get environment variables: %w", err) } } + // Ensure stable empty output shape across formats. + if envVars == nil { + envVars = map[string]string{} + }
35-37: Bind --login to Viper and env for consistency.Follow CLI guidelines so users can control via ATMOS_AUTH_ENV_LOGIN.
authEnvCmd.Flags().Bool("login", false, "Trigger authentication if credentials are missing or expired (default: false)") +// Bind login flag and env (flags > env). +if err := viper.BindPFlag("auth_env_login", authEnvCmd.Flags().Lookup("login")); err != nil { + log.Trace("Failed to bind auth_env_login flag", "error", err) +} +viper.MustBindEnv("auth_env_login", "ATMOS_AUTH_ENV_LOGIN")Optionally, read it via viper in RunE to allow env-driven defaults:
- login, _ := cmd.Flags().GetBool("login") + login := viper.GetBool("auth_env_login")As per coding guidelines.
Also applies to: 136-139
pkg/auth/cloud/aws/files_test.go (3)
378-417: Avoid homedir cache pitfalls; set HOME before resolving.Prevent stale home detection when checking legacy paths.
- // Override home directory for this test. - originalDir, _ := homedir.Dir() - defer func() { - // Restore original home directory (not possible with homedir package, but test isolation ensures cleanup). - _ = originalDir - }() - t.Setenv("HOME", tempHome) + // Override home directory for this test and disable homedir cache. + t.Setenv("HOME", tempHome) + homedir.DisableCache = true + defer func() { homedir.DisableCache = false }()This ensures any homedir lookups inside NewAWSFileManager see the test HOME.
458-461: Make absolute path test cross‑platform.Avoid hardcoded “/tmp”.
- basePath: "/tmp/custom-aws-creds", - expectedBasePath: "/tmp/custom-aws-creds", + basePath: filepath.Join(os.TempDir(), "custom-aws-creds"), + expectedBasePath: filepath.Join(os.TempDir(), "custom-aws-creds"),
552-576: Don’t rely on env var ordering; assert by key.GetEnvironmentVariables order isn’t guaranteed. Map by key before asserting.
- envVars := fm.GetEnvironmentVariables(providerName, identityName) - - // Verify environment variables point to custom base path. - expectedCredsPath := filepath.Join(customBasePath, providerName, "credentials") - expectedConfigPath := filepath.Join(customBasePath, providerName, "config") - - assert.Equal(t, expectedCredsPath, envVars[0].Value, "AWS_SHARED_CREDENTIALS_FILE should use custom base_path") - assert.Equal(t, expectedConfigPath, envVars[1].Value, "AWS_CONFIG_FILE should use custom base_path") - assert.Equal(t, identityName, envVars[2].Value, "AWS_PROFILE should be identity name") + envVars := fm.GetEnvironmentVariables(providerName, identityName) + env := map[string]string{} + for _, kv := range envVars { + env[kv.Key] = kv.Value + } + + // Verify environment variables point to custom base path. + expectedCredsPath := filepath.Join(customBasePath, providerName, "credentials") + expectedConfigPath := filepath.Join(customBasePath, providerName, "config") + + assert.Equal(t, expectedCredsPath, env["AWS_SHARED_CREDENTIALS_FILE"]) + assert.Equal(t, expectedConfigPath, env["AWS_CONFIG_FILE"]) + assert.Equal(t, identityName, env["AWS_PROFILE"])pkg/auth/providers/mock/identity.go (1)
106-119: Optional: make mock expiration deterministic to avoid flakiness.Returning time.Now().Add(1h) can cause snapshot/test drift. Consider a fixed timestamp like in Authenticate for stability.
pkg/auth/cloud/aws/files.go (4)
27-39: Centralize error sentinels and preserve causes.These package-local errors diverge from “static errors from errors/errors.go”. Recommend moving/using shared sentinels (e.g., ErrAwsFilesCreateCredentials, etc.) and wrap causes: fmt.Errorf("%w: %v", Err..., err) or errors.Join where independent. Current pattern returns only the sentinel after printing, losing the original error for callers/tests.
169-178: Preserve original error on write failures.Return a wrapped error so callers can inspect root cause instead of just the sentinel. Same for SetConfigFilePermissions below.
- if err := cfg.SaveTo(credentialsPath); err != nil { - errUtils.CheckErrorAndPrint(ErrWriteCredentialsFile, identityName, "failed to write credentials file") - return ErrWriteCredentialsFile - } + if err := cfg.SaveTo(credentialsPath); err != nil { + errUtils.CheckErrorAndPrint(ErrWriteCredentialsFile, identityName, "failed to write credentials file") + return fmt.Errorf("%w: %v", ErrWriteCredentialsFile, err) + }
268-275: Path display: prefer filepath.Rel for cross‑platform correctness.strings.HasPrefix can mis-detect on case-insensitive filesystems or similar prefixes. Use filepath.Rel to decide if baseDir is under home, then join "~".
- func (m *AWSFileManager) GetDisplayPath() string { - homeDir, err := homedir.Dir() - if err == nil && homeDir != "" && strings.HasPrefix(m.baseDir, homeDir) { - return strings.Replace(m.baseDir, homeDir, "~", 1) - } - return m.baseDir - } + func (m *AWSFileManager) GetDisplayPath() string { + homeDir, err := homedir.Dir() + if err == nil && homeDir != "" { + if rel, rerr := filepath.Rel(homeDir, m.baseDir); rerr == nil && !strings.HasPrefix(rel, "..") { + return filepath.Join("~", rel) + } + } + return m.baseDir + }
46-56: Doc comments: end sentences with periods (godot).A few lines in the NewAWSFileManager doc block end without periods (e.g., headings/ bullets). Tweak to satisfy the linter.
Also applies to: 67-78, 85-109
pkg/auth/types/aws_credentials.go (1)
64-71: Guard missing region for STS (optional).If c.Region is empty, STS will error. Either validate and return a clear error or default to a safe region.
Example:
cfg := aws.Config{ - Region: c.Region, + Region: c.Region, Credentials: credentials.NewStaticCredentialsProvider( @@ } +if cfg.Region == "" { + return nil, fmt.Errorf("%w: missing AWS region for credential validation", errUtils.ErrInvalidAuthConfig) +}Based on coding guidelines.
Also applies to: 74-80
cmd/auth_whoami.go (1)
51-59: Use cmd.Context() instead of context.Background().Propagate CLI cancellations/timeouts.
- ctx := context.Background() + ctx := cmd.Context()As per coding guidelines.
Also applies to: 64-66
pkg/auth/manager.go (2)
206-210: Pass context into buildWhoamiInfoFromEnvironment.Avoid context.Background(); thread the caller’s ctx for consistency.
- return m.buildWhoamiInfoFromEnvironment(identityName), nil + return m.buildWhoamiInfoFromEnvironment(ctx, identityName), nil @@ -func (m *manager) buildWhoamiInfoFromEnvironment(identityName string) *types.WhoamiInfo { +func (m *manager) buildWhoamiInfoFromEnvironment(ctx context.Context, identityName string) *types.WhoamiInfo { @@ - ctx := context.Background() - creds, err := identity.LoadCredentials(ctx) + creds, err := identity.LoadCredentials(ctx)Based on learnings.
Also applies to: 776-825
395-404: Modernize default files display path.Legacy fallback points to ~/.aws/atmos. Suggest XDG‑compliant default to match docs.
- return "~/.aws/atmos" + return "~/.config/atmos"As per coding guidelines.
pkg/auth/identities/aws/credentials_loader.go (1)
20-67: Avoid process-wide env mutation; load with SDK options.Temporarily setting AWS_* env vars is global and racy. Use aws-sdk-go-v2 LoadOptions to target files/profile and avoid IMDS.
-func loadAWSCredentialsFromEnvironment(ctx context.Context, env map[string]string) (*types.AWSCredentials, error) { +func loadAWSCredentialsFromEnvironment(ctx context.Context, env map[string]string) (*types.AWSCredentials, error) { credsFile, hasCredsFile := env["AWS_SHARED_CREDENTIALS_FILE"] configFile, hasConfigFile := env["AWS_CONFIG_FILE"] profile, hasProfile := env["AWS_PROFILE"] region := env["AWS_REGION"] // Optional. if !hasCredsFile || !hasConfigFile || !hasProfile { - return nil, fmt.Errorf("missing required AWS environment variables (AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE, AWS_PROFILE)") + return nil, fmt.Errorf("%w: missing required AWS environment variables (AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE, AWS_PROFILE)", errUtils.ErrInvalidAuthConfig) } - // Temporarily set environment variables... - // (removed) - // Load AWS config using SDK (which will read from the files via env vars). - cfg, err := awsConfig.LoadDefaultConfig(ctx) + // Load AWS config explicitly from provided files/profile; avoids touching process env and IMDS. + cfg, err := awsConfig.LoadDefaultConfig( + ctx, + awsConfig.WithSharedConfigProfile(profile), + awsConfig.WithSharedCredentialsFiles([]string{credsFile}), + awsConfig.WithSharedConfigFiles([]string{configFile}), + ) if err != nil { - return nil, fmt.Errorf("failed to load AWS config from files: %w", err) + return nil, fmt.Errorf("%w: failed to load AWS config from files: %v", errUtils.ErrInvalidAuthConfig, err) } awsCreds, err := cfg.Credentials.Retrieve(ctx) if err != nil { - return nil, fmt.Errorf("failed to retrieve AWS credentials from files: %w", err) + return nil, fmt.Errorf("%w: failed to retrieve AWS credentials from files: %v", errUtils.ErrAuthenticationFailed, err) }As per coding guidelines.
Also applies to: 68-76, 88-101, 116-156
pkg/auth/types/interfaces.go (1)
79-89: Clarify LoadCredentials not-supported contract.Returning (nil, nil) when unsupported can be ambiguous at call sites. Consider mirroring Validate’s pattern by returning a sentinel (e.g., ErrNotImplemented) to keep behavior consistent and easier to check with errors.Is.
pkg/auth/manager_test.go (4)
232-236: Populate ValidationInfo for stronger assertions.Set Principal/Account to non-empty values so downstream paths are exercised.
-func (c *testCreds) Validate(ctx context.Context) (*types.ValidationInfo, error) { - return &types.ValidationInfo{Expiration: c.exp}, nil -} +func (c *testCreds) Validate(ctx context.Context) (*types.ValidationInfo, error) { + return &types.ValidationInfo{ + Principal: "arn:aws:iam::123456789012:user/test", + Account: "123456789012", + Expiration: c.exp, + }, nil +}
482-485: Add a negative-path whoami test.CredentialsExist always true; consider a case where it’s false (or LoadCredentials returns creds) to cover the fallback branches.
556-561: Mirror negative-path coverage for permission-set stub.Same as above: one test where CredentialsExist=false or LoadCredentials returns non-nil to assert manager fallback.
804-807: Unify stub defaults.To reduce repetition across stubs, consider a small embedded base struct providing default Logout/CredentialsExist/LoadCredentials. Optional.
📜 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 (50)
README.md(1 hunks)cmd/auth_console_test.go(2 hunks)cmd/auth_env.go(3 hunks)cmd/auth_whoami.go(3 hunks)docs/prd/xdg-base-directory-specification.md(5 hunks)internal/aws_utils/aws_utils.go(2 hunks)internal/exec/mock_terraform_output_getter.go(1 hunks)internal/exec/template_funcs_component.go(1 hunks)internal/exec/terraform_output_getter.go(1 hunks)internal/exec/terraform_output_utils.go(5 hunks)internal/exec/yaml_func_terraform_output.go(3 hunks)internal/exec/yaml_func_terraform_output_authcontext_test.go(1 hunks)internal/exec/yaml_func_terraform_output_test.go(2 hunks)internal/exec/yaml_func_utils.go(1 hunks)pkg/auth/cloud/aws/env.go(3 hunks)pkg/auth/cloud/aws/files.go(6 hunks)pkg/auth/cloud/aws/files_test.go(1 hunks)pkg/auth/cloud/aws/setup_test.go(7 hunks)pkg/auth/credentials/keyring_file_test.go(1 hunks)pkg/auth/credentials/keyring_noop.go(2 hunks)pkg/auth/credentials/store_test.go(2 hunks)pkg/auth/hooks_test.go(1 hunks)pkg/auth/identities/aws/assume_role.go(2 hunks)pkg/auth/identities/aws/assume_role_test.go(2 hunks)pkg/auth/identities/aws/credentials_loader.go(1 hunks)pkg/auth/identities/aws/credentials_loader_test.go(1 hunks)pkg/auth/identities/aws/permission_set.go(2 hunks)pkg/auth/identities/aws/permission_set_test.go(3 hunks)pkg/auth/identities/aws/user.go(4 hunks)pkg/auth/identities/aws/user_test.go(6 hunks)pkg/auth/manager.go(5 hunks)pkg/auth/manager_test.go(4 hunks)pkg/auth/providers/aws/saml_test.go(2 hunks)pkg/auth/providers/aws/sso_test.go(1 hunks)pkg/auth/providers/mock/credentials.go(1 hunks)pkg/auth/providers/mock/identity.go(1 hunks)pkg/auth/providers/mock/identity_test.go(1 hunks)pkg/auth/types/aws_credentials.go(2 hunks)pkg/auth/types/github_oidc_credentials.go(1 hunks)pkg/auth/types/interfaces.go(3 hunks)pkg/auth/types/mock_interfaces.go(5 hunks)pkg/xdg/xdg.go(1 hunks)pkg/xdg/xdg_test.go(2 hunks)scripts/test-geodesic-prebuilt.sh(1 hunks)website/blog/2025-10-21-auth-context-implementation.md(2 hunks)website/blog/2025-10-24-macos-xdg-cli-conventions.md(1 hunks)website/docs/cli/commands/auth/auth-shell.mdx(1 hunks)website/docs/cli/commands/auth/logout.mdx(9 hunks)website/docs/cli/commands/auth/tutorials/configuring-geodesic.mdx(6 hunks)website/docs/cli/commands/auth/usage.mdx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/identities/aws/permission_set.gopkg/auth/credentials/keyring_noop.gopkg/xdg/xdg.gopkg/auth/providers/mock/identity_test.gopkg/auth/identities/aws/assume_role_test.gopkg/auth/providers/aws/sso_test.gopkg/auth/providers/mock/credentials.gopkg/xdg/xdg_test.gopkg/auth/identities/aws/user_test.gopkg/auth/identities/aws/credentials_loader_test.gopkg/auth/cloud/aws/env.gopkg/auth/credentials/store_test.gopkg/auth/providers/mock/identity.gopkg/auth/identities/aws/permission_set_test.gopkg/auth/types/github_oidc_credentials.gopkg/auth/manager.gopkg/auth/cloud/aws/files.gopkg/auth/providers/aws/saml_test.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/cloud/aws/setup_test.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gopkg/auth/hooks_test.gopkg/auth/credentials/keyring_file_test.gopkg/auth/identities/aws/assume_role.gopkg/auth/cloud/aws/files_test.gopkg/auth/types/mock_interfaces.gopkg/auth/types/interfaces.gopkg/auth/manager_test.go
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Define interfaces for major functionality and use dependency injection to enable testability.
Generate mocks using go.uber.org/mock/mockgen via //go:generate directives (never manual mocks).
Prefer functional Options pattern instead of functions with many parameters for configuration.
Use context.Context only for cancellation, deadlines/timeouts, and request-scoped values; never for configuration or dependencies; context should be the first parameter.
All comments must end with periods (godot linter).
Preserve helpful existing comments; update them to match code when refactoring; only remove when incorrect, redundant, or code removed.
Organize imports in three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically; maintain aliases cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Use static errors from errors/errors.go; wrap with fmt.Errorf("%w") for chaining; use errors.Join for independent errors; avoid dynamic errors and string comparison; use errors.Is for checks.
Never use //revive:disable:file-length-limit to bypass file size limits; keep files small and focused (<600 lines).
Environment variables must be bound with viper.BindEnv using ATMOS_ prefix (e.g., viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")).
Ensure cross-platform compatibility: use filepath.Join instead of hardcoded path separators and prefer SDKs over shelling out to binaries.
Files:
pkg/auth/identities/aws/permission_set.gopkg/auth/credentials/keyring_noop.gopkg/xdg/xdg.gointernal/exec/yaml_func_terraform_output_test.gopkg/auth/providers/mock/identity_test.gopkg/auth/identities/aws/assume_role_test.gopkg/auth/providers/aws/sso_test.gopkg/auth/providers/mock/credentials.gopkg/xdg/xdg_test.gopkg/auth/identities/aws/user_test.gointernal/exec/terraform_output_utils.gointernal/aws_utils/aws_utils.gopkg/auth/identities/aws/credentials_loader_test.gointernal/exec/yaml_func_utils.gopkg/auth/cloud/aws/env.gopkg/auth/credentials/store_test.gocmd/auth_console_test.gocmd/auth_whoami.gopkg/auth/providers/mock/identity.gopkg/auth/identities/aws/permission_set_test.gopkg/auth/types/github_oidc_credentials.gointernal/exec/mock_terraform_output_getter.gointernal/exec/template_funcs_component.gopkg/auth/manager.gopkg/auth/cloud/aws/files.gointernal/exec/yaml_func_terraform_output_authcontext_test.gopkg/auth/providers/aws/saml_test.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/cloud/aws/setup_test.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gocmd/auth_env.gopkg/auth/hooks_test.gointernal/exec/terraform_output_getter.gopkg/auth/credentials/keyring_file_test.gopkg/auth/identities/aws/assume_role.gointernal/exec/yaml_func_terraform_output.gopkg/auth/cloud/aws/files_test.gopkg/auth/types/mock_interfaces.gopkg/auth/types/interfaces.gopkg/auth/manager_test.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
pkg/auth/identities/aws/permission_set.gopkg/auth/credentials/keyring_noop.gopkg/xdg/xdg.gopkg/auth/providers/mock/credentials.gointernal/exec/terraform_output_utils.gointernal/aws_utils/aws_utils.gointernal/exec/yaml_func_utils.gopkg/auth/cloud/aws/env.gocmd/auth_whoami.gopkg/auth/providers/mock/identity.gopkg/auth/types/github_oidc_credentials.gointernal/exec/mock_terraform_output_getter.gointernal/exec/template_funcs_component.gopkg/auth/manager.gopkg/auth/cloud/aws/files.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/identities/aws/user.gopkg/auth/types/aws_credentials.gocmd/auth_env.gointernal/exec/terraform_output_getter.gopkg/auth/identities/aws/assume_role.gointernal/exec/yaml_func_terraform_output.gopkg/auth/types/mock_interfaces.gopkg/auth/types/interfaces.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases
Files:
website/docs/cli/commands/auth/auth-shell.mdxwebsite/docs/cli/commands/auth/logout.mdxwebsite/docs/cli/commands/auth/usage.mdxwebsite/blog/2025-10-24-macos-xdg-cli-conventions.mdwebsite/blog/2025-10-21-auth-context-implementation.mdwebsite/docs/cli/commands/auth/tutorials/configuring-geodesic.mdx
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + DI; table-driven tests for coverage; target >80% coverage.
Tests must exercise production code paths; avoid duplicating implementation logic in tests.
Use t.Skipf("reason") with clear context when skipping tests; CLI tests may auto-build temp binaries.
Files:
internal/exec/yaml_func_terraform_output_test.gopkg/auth/providers/mock/identity_test.gopkg/auth/identities/aws/assume_role_test.gopkg/auth/providers/aws/sso_test.gopkg/xdg/xdg_test.gopkg/auth/identities/aws/user_test.gopkg/auth/identities/aws/credentials_loader_test.gopkg/auth/credentials/store_test.gocmd/auth_console_test.gopkg/auth/identities/aws/permission_set_test.gointernal/exec/yaml_func_terraform_output_authcontext_test.gopkg/auth/providers/aws/saml_test.gopkg/auth/cloud/aws/setup_test.gopkg/auth/hooks_test.gopkg/auth/credentials/keyring_file_test.gopkg/auth/cloud/aws/files_test.gopkg/auth/manager_test.go
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate
cmd/**/*.go: New CLI commands must use the command registry pattern via CommandProvider and register through the command registry (see cmd/internal/registry.go).
Commands should embed *_usage.md via //go:embed and render with utils.PrintfMarkdown().
UI (prompts/status) must write to stderr; data outputs to stdout; logging only for system events (never for UI).
For non-standard execution paths, capture telemetry with telemetry.CaptureCmd(); normal paths are auto-enabled via RootCmd.ExecuteC(). Never capture user data.
Files:
cmd/auth_console_test.gocmd/auth_whoami.gocmd/auth_env.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use cmd.NewTestKit(t) for any tests that touch RootCmd to auto-clean RootCmd state.
Files:
cmd/auth_console_test.go
{cmd,pkg/ui}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use theme colors from pkg/ui/theme/colors.go for UI elements.
Files:
cmd/auth_console_test.gocmd/auth_whoami.gocmd/auth_env.go
README.md
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Update README.md when adding new commands and features
Files:
README.md
website/blog/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-*.md
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled minor or major must include a blog post with filename date prefix and feature name; include and proper tags.
Files:
website/blog/2025-10-24-macos-xdg-cli-conventions.mdwebsite/blog/2025-10-21-auth-context-implementation.md
docs/prd/[a-z0-9-]*.md
📄 CodeRabbit inference engine (CLAUDE.md)
All PRDs must be placed under docs/prd/ with kebab-case filenames.
Files:
docs/prd/xdg-base-directory-specification.md
🧠 Learnings (17)
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: XDG Base Directory Specification compliance implementation for atmos toolchain is complete: created toolchain/xdg_cache.go with GetXDGCacheDir() and GetXDGTempCacheDir() functions, updated toolchain/installer.go and cmd/toolchain_clean.go to use these XDG helpers, and changed all cache paths from hardcoded ~/.cache/tools-cache to XDG-compliant ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback).
Applied to files:
pkg/xdg/xdg.gopkg/xdg/xdg_test.gowebsite/blog/2025-10-24-macos-xdg-cli-conventions.mddocs/prd/xdg-base-directory-specification.mdwebsite/blog/2025-10-21-auth-context-implementation.mdpkg/auth/cloud/aws/setup_test.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain XDG compliance implementation is complete with GetXDGCacheDir() and GetXDGTempCacheDir() functions in toolchain/xdg_cache.go, updated installer.go and toolchain_clean.go to use these helpers, and changed cache paths from ~/.cache/tools-cache to ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain when XDG_CACHE_HOME is not set).
Applied to files:
pkg/xdg/xdg.gopkg/xdg/xdg_test.gowebsite/blog/2025-10-24-macos-xdg-cli-conventions.mddocs/prd/xdg-base-directory-specification.mdwebsite/blog/2025-10-21-auth-context-implementation.mdpkg/auth/cloud/aws/setup_test.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Applied to files:
pkg/xdg/xdg.gowebsite/blog/2025-10-24-macos-xdg-cli-conventions.mddocs/prd/xdg-base-directory-specification.mdwebsite/blog/2025-10-21-auth-context-implementation.mdpkg/auth/cloud/aws/setup_test.gowebsite/docs/cli/commands/auth/tutorials/configuring-geodesic.mdx
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: Final XDG Base Directory Specification implementation for atmos toolchain is complete and verified: toolchain/xdg_cache.go provides GetXDGCacheDir() and GetXDGTempCacheDir() functions, all hardcoded ~/.cache/tools-cache paths have been replaced with XDG-compliant paths using ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback), and tests have been updated to expect the new path structure.
Applied to files:
pkg/xdg/xdg.gopkg/xdg/xdg_test.gowebsite/blog/2025-10-24-macos-xdg-cli-conventions.mddocs/prd/xdg-base-directory-specification.mdwebsite/blog/2025-10-21-auth-context-implementation.mdpkg/auth/cloud/aws/setup_test.go
📚 Learning: 2024-12-13T15:33:34.159Z
Learnt from: Listener430
PR: cloudposse/atmos#844
File: pkg/config/cache.go:17-31
Timestamp: 2024-12-13T15:33:34.159Z
Learning: In `pkg/config/cache.go`, when `XDG_CACHE_HOME` is not set, falling back to `.` (current directory) is acceptable and aligns with the requirement to primarily use `XDG_CACHE_HOME` for the cache directory.
Applied to files:
pkg/xdg/xdg.godocs/prd/xdg-base-directory-specification.md
📚 Learning: 2025-09-10T17:34:52.568Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/providers/github/oidc.go:96-100
Timestamp: 2025-09-10T17:34:52.568Z
Learning: The ATMOS_ environment variable binding guideline applies to Atmos configuration variables, not external service-required environment variables like GitHub Actions OIDC variables (GITHUB_ACTIONS, ACTIONS_ID_TOKEN_*) which must use their standard names.
Applied to files:
website/docs/cli/commands/auth/auth-shell.mdx
📚 Learning: 2024-12-17T07:08:41.288Z
Learnt from: aknysh
PR: cloudposse/atmos#863
File: internal/exec/yaml_func_terraform_output.go:34-38
Timestamp: 2024-12-17T07:08:41.288Z
Learning: In the `processTagTerraformOutput` function within `internal/exec/yaml_func_terraform_output.go`, parameters are separated by spaces and do not contain spaces. Therefore, using `strings.Fields()` for parsing is acceptable, and there's no need to handle parameters with spaces.
Applied to files:
internal/exec/yaml_func_terraform_output_test.gointernal/exec/yaml_func_utils.go
📚 Learning: 2024-11-30T22:07:08.610Z
Learnt from: aknysh
PR: cloudposse/atmos#810
File: internal/exec/yaml_func_terraform_output.go:35-40
Timestamp: 2024-11-30T22:07:08.610Z
Learning: In the Go function `processTagTerraformOutput` in `internal/exec/yaml_func_terraform_output.go`, parameters cannot contain spaces. The code splits the input by spaces, and if the parameters contain spaces, `len(parts) != 3` will fail and show an error to the user.
Applied to files:
internal/exec/yaml_func_terraform_output_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: The atmos codebase has a custom extension to *testing.T that provides a Chdir method, allowing test functions to call t.Chdir() to change working directories during tests. This is used consistently across test files in the codebase.
Applied to files:
pkg/xdg/xdg_test.go
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Applied to files:
website/docs/cli/commands/auth/usage.mdx
📚 Learning: 2025-10-24T14:51:19.340Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-24T14:51:19.340Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Applied to files:
pkg/auth/cloud/aws/env.go
📚 Learning: 2025-09-09T02:14:36.708Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1452
File: internal/auth/types/whoami.go:14-15
Timestamp: 2025-09-09T02:14:36.708Z
Learning: The WhoamiInfo struct in internal/auth/types/whoami.go requires the Credentials field to be JSON-serializable for keystore unmarshaling operations, despite security concerns about credential exposure.
Applied to files:
cmd/auth_whoami.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain should follow XDG Base Directory Specification like the rest of atmos core, using XDG_CACHE_HOME environment variable when available and falling back to ~/.cache when not set, instead of hardcoding ~/.cache/tools-cache paths.
Applied to files:
docs/prd/xdg-base-directory-specification.md
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
PR: cloudposse/atmos#844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.
Applied to files:
docs/prd/xdg-base-directory-specification.md
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
PR: cloudposse/atmos#775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.
Applied to files:
internal/exec/template_funcs_component.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-08-15T14:43:41.030Z
Learnt from: aknysh
PR: cloudposse/atmos#1352
File: pkg/store/artifactory_store_test.go:108-113
Timestamp: 2025-08-15T14:43:41.030Z
Learning: In test files for the atmos project, it's acceptable to ignore errors from os.Setenv/Unsetenv operations during test environment setup and teardown, as these are controlled test scenarios.
Applied to files:
pkg/auth/cloud/aws/setup_test.go
🧬 Code graph analysis (30)
pkg/auth/identities/aws/permission_set.go (3)
pkg/perf/perf.go (1)
Track(121-138)pkg/auth/cloud/aws/files.go (1)
NewAWSFileManager(56-83)pkg/auth/types/interfaces.go (1)
ICredentials(187-198)
pkg/auth/credentials/keyring_noop.go (3)
pkg/auth/types/interfaces.go (1)
ICredentials(187-198)pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (1)
Debug(24-26)
pkg/auth/providers/mock/identity_test.go (4)
pkg/auth/providers/mock/identity.go (2)
Identity(14-17)NewIdentity(20-27)pkg/auth/types/interfaces.go (1)
Identity(54-89)pkg/schema/schema_auth.go (1)
Identity(45-53)pkg/auth/providers/mock/credentials.go (1)
Credentials(11-17)
pkg/auth/identities/aws/assume_role_test.go (4)
pkg/auth/identities/aws/assume_role.go (1)
NewAssumeRoleIdentity(111-126)pkg/auth/types/interfaces.go (2)
Identity(54-89)Provider(13-42)pkg/schema/schema_auth.go (3)
Identity(45-53)IdentityVia(56-59)Provider(18-32)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
pkg/auth/providers/mock/credentials.go (1)
pkg/auth/types/interfaces.go (1)
ValidationInfo(201-216)
pkg/xdg/xdg_test.go (1)
pkg/xdg/xdg.go (1)
GetXDGConfigDir(46-48)
pkg/auth/identities/aws/user_test.go (3)
pkg/auth/types/interfaces.go (2)
ICredentials(187-198)Identity(54-89)pkg/auth/identities/aws/user.go (1)
NewUserIdentity(39-51)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
internal/exec/terraform_output_utils.go (3)
pkg/schema/schema.go (1)
AuthContext(498-506)pkg/logger/log.go (1)
Debug(24-26)pkg/config/const.go (1)
EnvSectionName(61-61)
internal/aws_utils/aws_utils.go (2)
pkg/logger/log.go (1)
Debug(24-26)errors/errors.go (1)
ErrLoadAwsConfig(74-74)
pkg/auth/cloud/aws/env.go (2)
pkg/logger/log.go (2)
Debug(24-26)Errorf(59-61)errors/errors.go (1)
ErrLoadAwsConfig(74-74)
pkg/auth/credentials/store_test.go (1)
pkg/auth/types/interfaces.go (1)
ValidationInfo(201-216)
cmd/auth_whoami.go (5)
errors/error_funcs.go (1)
CheckErrorPrintAndExit(58-81)pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/auth/providers/mock/credentials.go (1)
Credentials(11-17)pkg/logger/log.go (1)
Debug(24-26)pkg/auth/types/interfaces.go (2)
Identity(54-89)ValidationInfo(201-216)
pkg/auth/providers/mock/identity.go (3)
pkg/auth/types/interfaces.go (2)
Identity(54-89)ICredentials(187-198)pkg/perf/perf.go (1)
Track(121-138)pkg/auth/providers/mock/credentials.go (1)
Credentials(11-17)
pkg/auth/identities/aws/permission_set_test.go (4)
pkg/auth/identities/aws/permission_set.go (1)
NewPermissionSetIdentity(36-45)pkg/auth/types/interfaces.go (2)
Identity(54-89)Provider(13-42)pkg/schema/schema_auth.go (3)
Identity(45-53)IdentityVia(56-59)Provider(18-32)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
pkg/auth/types/github_oidc_credentials.go (1)
pkg/auth/types/interfaces.go (1)
ValidationInfo(201-216)
internal/exec/mock_terraform_output_getter.go (1)
pkg/schema/schema.go (2)
AtmosConfiguration(27-65)AuthContext(498-506)
pkg/auth/manager.go (6)
pkg/logger/log.go (1)
Debug(24-26)pkg/auth/credentials/keyring_file.go (1)
ErrCredentialsNotFound(36-36)errors/errors.go (3)
ErrNoCredentialsFound(386-386)ErrIdentityNotFound(393-393)ErrInvalidAuthConfig(370-370)pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/auth/types/interfaces.go (2)
Provider(13-42)Identity(54-89)pkg/perf/perf.go (1)
Track(121-138)
pkg/auth/cloud/aws/files.go (4)
pkg/xdg/xdg.go (1)
GetXDGConfigDir(46-48)pkg/logger/log.go (3)
Errorf(59-61)Warn(44-46)Debug(24-26)pkg/config/homedir/homedir.go (1)
Dir(36-63)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
internal/exec/yaml_func_terraform_output_authcontext_test.go (3)
internal/exec/mock_terraform_output_getter.go (1)
NewMockTerraformOutputGetter(32-36)pkg/schema/schema.go (5)
AuthContext(498-506)AWSAuthContext(510-525)ConfigAndStacksInfo(527-610)AtmosConfiguration(27-65)AtmosSectionMapType(14-14)internal/exec/yaml_func_utils.go (1)
ProcessCustomYamlTags(13-30)
pkg/auth/identities/aws/credentials_loader.go (2)
pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)pkg/logger/log.go (2)
Errorf(59-61)Debug(24-26)
pkg/auth/cloud/aws/setup_test.go (3)
pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)pkg/auth/cloud/aws/setup.go (1)
SetupFiles(17-45)pkg/schema/schema.go (2)
AuthContext(498-506)AWSAuthContext(510-525)
pkg/auth/identities/aws/user.go (3)
pkg/perf/perf.go (1)
Track(121-138)pkg/auth/cloud/aws/files.go (1)
NewAWSFileManager(56-83)pkg/auth/types/interfaces.go (1)
ICredentials(187-198)
pkg/auth/types/aws_credentials.go (2)
pkg/auth/types/interfaces.go (1)
ValidationInfo(201-216)errors/errors.go (1)
ErrAuthenticationFailed(375-375)
internal/exec/terraform_output_getter.go (3)
pkg/schema/schema.go (2)
AtmosConfiguration(27-65)AuthContext(498-506)pkg/perf/perf.go (1)
Track(121-138)internal/exec/terraform_output_utils.go (1)
GetTerraformOutput(372-448)
pkg/auth/credentials/keyring_file_test.go (1)
pkg/auth/types/interfaces.go (1)
ValidationInfo(201-216)
pkg/auth/identities/aws/assume_role.go (3)
pkg/perf/perf.go (1)
Track(121-138)pkg/auth/cloud/aws/files.go (1)
NewAWSFileManager(56-83)pkg/auth/types/interfaces.go (1)
ICredentials(187-198)
internal/exec/yaml_func_terraform_output.go (1)
pkg/schema/schema.go (3)
AtmosConfiguration(27-65)ConfigAndStacksInfo(527-610)AuthContext(498-506)
pkg/auth/cloud/aws/files_test.go (3)
pkg/config/homedir/homedir.go (1)
Dir(36-63)pkg/auth/cloud/aws/files.go (1)
NewAWSFileManager(56-83)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
pkg/auth/types/mock_interfaces.go (1)
pkg/auth/types/interfaces.go (2)
ICredentials(187-198)ConsoleURLOptions(230-247)
pkg/auth/manager_test.go (2)
pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/auth/types/interfaces.go (2)
ValidationInfo(201-216)ICredentials(187-198)
🪛 LanguageTool
website/blog/2025-10-24-macos-xdg-cli-conventions.md
[style] ~52-52: This phrase is redundant (‘OS’ stands for ‘operating system’). Use simply “macOS”./Library/Caches` - Provides better macOS system integration - Standard for applications...
Context: ...,
(ACRONYM_TAUTOLOGY)
[style] ~61-~61: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...ed If you're upgrading from versions prior to v1.195.0, you're not affected because...
(EN_WORDINESS_PREMIUM_PRIOR_TO)
[style] ~81-~81: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...eps credentials in the old location but affects all Atmos XDG paths (config, cache,...
(EN_REPEATEDWORDS_AFFECT)
[grammar] ~158-~158: Please add a punctuation mark at the end of paragraph.
Context: ...uth/usage) - Updated with correct macOS paths ## Migration Support If you encounter...
(PUNCTUATION_PARAGRAPH_END)
docs/prd/xdg-base-directory-specification.md
[typographical] ~39-~39: Consider using a typographic opening quote here.
Context: ...| | Testing with hermetic isolation |t.Setenv("XDG_DATA_HOME")|/tmp/test-xyz/data/a...
(EN_QUOTES)
[typographical] ~51-~51: In American English, use a period after an abbreviation.
Context: ... creation for visibility ### CLI Tools vs GUI Applications The XDG Base Director...
(MISSING_PERIOD_AFTER_ABBREVIATION)
[style] ~63-~63: This phrase is redundant (‘OS’ stands for ‘operating system’). Use simply “macOS”.
Context: ...- This provides better integration with macOS system features - Used by native macOS applica...
(ACRONYM_TAUTOLOGY)
[grammar] ~69-~69: Please add a punctuation mark at the end of paragraph.
Context: ...aths for users working across Linux and macOS ## Technical Specification ### Archit...
(PUNCTUATION_PARAGRAPH_END)
[style] ~550-~550: Consider using a different verb to strengthen your wording.
Context: ... compatibility. Rationale: Research showed that CLI tools (gh, git, packer, stripe...
(SHOW_INDICATE)
[style] ~564-~564: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ... not be affected** because: 1. Versions prior to v1.195.0 used ~/.aws/atmos/ (legacy p...
(EN_WORDINESS_PREMIUM_PRIOR_TO)
website/blog/2025-10-21-auth-context-implementation.md
[grammar] ~22-~22: Please add a punctuation mark at the end of paragraph.
Context: ...tion** for consistency with other Atmos data ## Why This Matters **The core proble...
(PUNCTUATION_PARAGRAPH_END)
website/docs/cli/commands/auth/tutorials/configuring-geodesic.mdx
[grammar] ~52-~52: Please add a punctuation mark at the end of paragraph.
Context: ... this - ❌ AWS_PROFILE - Atmos manages this Key Configuration Details: - **`A...
(PUNCTUATION_PARAGRAPH_END)
🪛 markdownlint-cli2 (0.18.1)
docs/prd/xdg-base-directory-specification.md
69-69: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build (windows)
- GitHub Check: Analyze (go)
- GitHub Check: Summary
… custom key Changed from using x_atmos_expiration key to using section comments for storing expiration metadata in AWS credentials files. This approach is cleaner and more standards-compliant: - Updated WriteCredentials to set section.Comment with expiration - Updated readExpirationFromMetadata to use ini.LoadSources with IgnoreInlineComment: false - Added proper comment prefix handling (; and #) - Updated all tests to use comment format - Added ErrAwsMissingEnvVars static error Format: ; atmos: expiration=2025-10-24T23:42:49Z The ini library properly preserves comments when loading/saving, making this a more robust solution than relying on undocumented x_ prefix behavior. Also fixed hooks package to match new GetTerraformOutput signature with authContext parameter. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Removed references to /docs/prd/xdg-base-directory-specification which doesn't exist in published docs. PRD files are internal development documentation not published to the website. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (7)
pkg/hooks/store_cmd.go (1)
15-28: Document the authContext parameter.The doc comment should describe the new
authContextparameter to maintain complete documentation of the function type's contract.Consider adding to the doc comment:
// TerraformOutputGetter retrieves terraform outputs. // This enables dependency injection for testing. +// Parameters: +// - authContext: Optional authentication context for credential-aware operations (may be nil) // Returns: // - value: The output value (may be nil if the output exists but has a null value) // - exists: Whether the output key exists in the terraform outputs // - error: Any error that occurred during retrieval (SDK errors, network issues, etc.)website/blog/2025-10-24-macos-xdg-cli-conventions.md (4)
128-136: Specify language for code block.The configuration example lacks a language identifier for syntax highlighting. Change
```bashto enable proper rendering.-\`\`\` +\`\`\`bash ~/.config/
142-150: Specify language for Go code block.This code block shows Go syntax but lacks a language identifier. Add
goto the fence.-\`\`\` +\`\`\`go func init() {
156-157: Add missing documentation link verification and punctuation.Line 157 lacks ending punctuation. Also, verify that the referenced documentation pages exist and are updated consistently with this breaking change (per coding guidelines about keeping website code in sync).
-[Configuring Geodesic with Atmos Auth](/docs/cli/commands/auth/tutorials/configuring-geodesic) - Simplified configuration (no setup needed!) -[Auth Usage Guide](/docs/cli/commands/auth/usage) - Updated with correct macOS paths +[Configuring Geodesic with Atmos Auth](/docs/cli/commands/auth/tutorials/configuring-geodesic) - Simplified configuration (no setup needed!). +[Auth Usage Guide](/docs/cli/commands/auth/usage) - Updated with correct macOS paths.
171-176: Wrap bare URLs in markdown link syntax.Lines 173–175 contain bare URLs. Wrap them in markdown link format for consistency and better rendering.
-## References - -- XDG Base Directory Specification: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -- Stack Overflow Discussion: https://stackoverflow.com/questions/3373948/equivalents-of-xdg-config-home-and-xdg-data-home-on-mac-os-x -- Geodesic: https://github.com/cloudposse/geodesic +## References + +- [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) +- [Stack Overflow Discussion](https://stackoverflow.com/questions/3373948/equivalents-of-xdg-config-home-and-xdg-data-home-on-mac-os-x) +- [Geodesic](https://github.com/cloudposse/geodesic)pkg/auth/identities/aws/credentials_loader_test.go (2)
13-100: Nice table-driven test with good edge case coverage.The test structure is clean and covers the important scenarios. A couple of minor suggestions:
Lines 24, 37, 49, 62, 75 ignore errors from
NewSectionwith_, while line 116 (in the round-trip test) properly checks them. For consistency, you might want to check these in the setup functions too—though NewSection rarely fails with simple names, checking keeps things uniform.Consider adding a doc comment to explain what the test covers (coding guidelines encourage doc comments on test functions).
107-143: Solid end-to-end test.The round-trip flow is well-structured—writes metadata, reads it back, validates the timestamp format. Good to see proper error handling throughout and the 0o600 permissions for the credentials file.
One optional thought: you might consider adding a test case for when the expiration is in the past, to verify how expired credentials are handled. But that may be beyond the scope here.
📜 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 (8)
errors/errors.go(1 hunks)pkg/auth/cloud/aws/files.go(6 hunks)pkg/auth/identities/aws/credentials_loader.go(1 hunks)pkg/auth/identities/aws/credentials_loader_test.go(1 hunks)pkg/hooks/store_cmd.go(2 hunks)pkg/hooks/store_cmd_nil_handling_test.go(9 hunks)pkg/hooks/store_cmd_test.go(1 hunks)website/blog/2025-10-24-macos-xdg-cli-conventions.md(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- pkg/auth/cloud/aws/files.go
- pkg/auth/identities/aws/credentials_loader.go
🧰 Additional context used
📓 Path-based instructions (6)
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Define interfaces for major functionality and use dependency injection to enable testability.
Generate mocks using go.uber.org/mock/mockgen via //go:generate directives (never manual mocks).
Prefer functional Options pattern instead of functions with many parameters for configuration.
Use context.Context only for cancellation, deadlines/timeouts, and request-scoped values; never for configuration or dependencies; context should be the first parameter.
All comments must end with periods (godot linter).
Preserve helpful existing comments; update them to match code when refactoring; only remove when incorrect, redundant, or code removed.
Organize imports in three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically; maintain aliases cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Use static errors from errors/errors.go; wrap with fmt.Errorf("%w") for chaining; use errors.Join for independent errors; avoid dynamic errors and string comparison; use errors.Is for checks.
Never use //revive:disable:file-length-limit to bypass file size limits; keep files small and focused (<600 lines).
Environment variables must be bound with viper.BindEnv using ATMOS_ prefix (e.g., viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")).
Ensure cross-platform compatibility: use filepath.Join instead of hardcoded path separators and prefer SDKs over shelling out to binaries.
Files:
errors/errors.gopkg/hooks/store_cmd.gopkg/hooks/store_cmd_nil_handling_test.gopkg/auth/identities/aws/credentials_loader_test.gopkg/hooks/store_cmd_test.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
errors/errors.gopkg/hooks/store_cmd.go
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/hooks/store_cmd.gopkg/hooks/store_cmd_nil_handling_test.gopkg/auth/identities/aws/credentials_loader_test.gopkg/hooks/store_cmd_test.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases
Files:
website/blog/2025-10-24-macos-xdg-cli-conventions.md
website/blog/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-*.md
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled minor or major must include a blog post with filename date prefix and feature name; include and proper tags.
Files:
website/blog/2025-10-24-macos-xdg-cli-conventions.md
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + DI; table-driven tests for coverage; target >80% coverage.
Tests must exercise production code paths; avoid duplicating implementation logic in tests.
Use t.Skipf("reason") with clear context when skipping tests; CLI tests may auto-build temp binaries.
Files:
pkg/hooks/store_cmd_nil_handling_test.gopkg/auth/identities/aws/credentials_loader_test.gopkg/hooks/store_cmd_test.go
🧠 Learnings (2)
📓 Common learnings
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Applied to files:
website/blog/2025-10-24-macos-xdg-cli-conventions.md
🧬 Code graph analysis (3)
pkg/hooks/store_cmd.go (1)
pkg/schema/schema.go (1)
AuthContext(498-506)
pkg/hooks/store_cmd_nil_handling_test.go (1)
pkg/schema/schema.go (2)
AtmosConfiguration(27-65)AuthContext(498-506)
pkg/hooks/store_cmd_test.go (1)
pkg/schema/schema.go (2)
AtmosConfiguration(27-65)AuthContext(498-506)
🪛 LanguageTool
website/blog/2025-10-24-macos-xdg-cli-conventions.md
[style] ~52-52: This phrase is redundant (‘OS’ stands for ‘operating system’). Use simply “macOS”./Library/Caches` - Provides better macOS system integration - Standard for applications...
Context: ...,
(ACRONYM_TAUTOLOGY)
[style] ~61-~61: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...ed If you're upgrading from versions prior to v1.195.0, you're not affected because...
(EN_WORDINESS_PREMIUM_PRIOR_TO)
[style] ~81-~81: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...eps credentials in the old location but affects all Atmos XDG paths (config, cache,...
(EN_REPEATEDWORDS_AFFECT)
[grammar] ~157-~157: Please add a punctuation mark at the end of paragraph.
Context: ...uth/usage) - Updated with correct macOS paths ## Migration Support If you encounter...
(PUNCTUATION_PARAGRAPH_END)
🪛 markdownlint-cli2 (0.18.1)
website/blog/2025-10-24-macos-xdg-cli-conventions.md
69-69: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
83-83: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
128-128: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
173-173: Bare URL used
(MD034, no-bare-urls)
174-174: Bare URL used
(MD034, no-bare-urls)
175-175: Bare URL used
(MD034, no-bare-urls)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: autofix
- GitHub Check: Build (windows)
- GitHub Check: Build (linux)
- GitHub Check: Build (macos)
- GitHub Check: website-deploy-preview
- GitHub Check: Review Dependency Licenses
- GitHub Check: Analyze (go)
- GitHub Check: Summary
🔇 Additional comments (8)
errors/errors.go (1)
382-382: LGTM!The new error sentinel follows the established naming convention and is appropriately placed with other AWS authentication errors.
pkg/hooks/store_cmd.go (1)
75-82: Clean integration of authContext parameter.The nil authContext is correctly passed through, maintaining existing behavior while enabling future credential-aware operations.
pkg/hooks/store_cmd_test.go (1)
130-137: Test correctly adapted to new signature.The mock signature update maintains test coverage while supporting the extended contract.
pkg/hooks/store_cmd_nil_handling_test.go (2)
66-77: Signature update maintains nil handling test coverage.The authContext parameter addition doesn't affect the test's validation of nil/missing output scenarios.
149-421: Comprehensive test updates align with new signature.All mock getter functions correctly updated to include authContext parameter. Test coverage for rate limits, intermittent failures, and error handling remains intact.
website/blog/2025-10-24-macos-xdg-cli-conventions.md (1)
1-179: Blog post structure and content alignment look solid.The post clearly documents the breaking change and aligns well with the PR's XDG path improvements. Migration guidance is practical with three concrete options. The Geodesic integration specifics (lines 102–111) directly support the containerized auth isolation goals from PR #1712.
Verify that the documentation pages referenced at line 156–157 have been updated in this PR to reflect the macOS path changes. If they weren't, either update them or remove/defer the reference in this blog post (per coding guidelines about keeping website docs in sync).
pkg/auth/identities/aws/credentials_loader_test.go (2)
1-11: Imports look solid.Clean organization—stdlib, then third-party, alphabetically sorted. Has everything needed for the tests.
102-105: Good check for the missing file case.Simple and effective—verifies graceful handling when the credentials file doesn't exist.
- Add performance tracking to LoadAtmosManagedAWSConfig - Fix os.UserHomeDir() error handling in aws_utils and env.go to avoid misleading paths - Clear AWS credential env vars when authContext is provided to prevent conflicts - Set AWS_SDK_LOAD_CONFIG=1 and AWS_EC2_METADATA_DISABLED=true for better isolation - Add AWS_DEFAULT_REGION alongside AWS_REGION for compatibility These changes improve credential isolation and ensure Atmos-managed credentials are not overridden by ambient environment variables or instance metadata. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to show macOS uses ~/.config/atmos/ instead of ~/Library/Application Support/atmos/. This aligns with the XDG Base Directory changes where macOS now follows CLI tool conventions (same as Linux) rather than GUI application conventions. Fixes blog post and auth-shell.mdx documentation. 🤖 Generated with [Claude Code](https://claude.com/claude.code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
pkg/auth/cloud/aws/env.go (3)
3-14: Fix build: import perf (and keep imports grouped/sorted).Build fails with undefined: perf. Add perf import in the Atmos group and keep groups sorted.
Apply:
import ( "context" + "errors" "fmt" "os" "path/filepath" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" errUtils "github.com/cloudposse/atmos/errors" log "github.com/cloudposse/atmos/pkg/logger" + "github.com/cloudposse/atmos/pkg/perf" )
104-109: Shared-config not actually disabled. Use empty file lists instead of empty profile.config.WithSharedConfigProfile("") does not prevent loading ~/.aws/{config,credentials}. Use empty file lists to truly isolate.
Apply:
- // Prepend config.WithSharedConfigProfile("") to disable loading from shared config files. - // This prevents the SDK from loading user's ~/.aws/config and ~/.aws/credentials files. - isolatedOptFns := make([]func(*config.LoadOptions) error, 0, len(optFns)+1) - isolatedOptFns = append(isolatedOptFns, config.WithSharedConfigProfile("")) + // Disable reading any shared config/credentials files for full isolation. + isolatedOptFns := make([]func(*config.LoadOptions) error, 0, len(optFns)+2) + isolatedOptFns = append(isolatedOptFns, + config.WithSharedConfigFiles([]string{}), + config.WithSharedCredentialsFiles([]string{}), + ) isolatedOptFns = append(isolatedOptFns, optFns...)
115-121: Invalid use of multiple %w in fmt.Errorf; wrap correctly and keep sentinel.Multiple %w in a single fmt.Errorf triggers vet/lint and loses proper chaining. Wrap the cause once and join with the sentinel.
Apply:
- if isolateErr != nil { - return aws.Config{}, fmt.Errorf("%w: %w", errUtils.ErrLoadAwsConfig, isolateErr) - } + if isolateErr != nil { + return aws.Config{}, errors.Join( + errUtils.ErrLoadAwsConfig, + fmt.Errorf("load isolated AWS config: %w", isolateErr), + ) + } - if err != nil { - return aws.Config{}, fmt.Errorf("%w: %w", errUtils.ErrLoadAwsConfig, err) - } + // (no second error check needed; isolateErr already captures loader error)- if err != nil { - log.Debug("Failed to load AWS SDK config", "error", err) - return aws.Config{}, fmt.Errorf("%w: %w", errUtils.ErrLoadAwsConfig, err) - } + if err != nil { + log.Debug("Failed to load AWS SDK config", "error", err) + return aws.Config{}, errors.Join( + errUtils.ErrLoadAwsConfig, + fmt.Errorf("load AWS SDK config: %w", err), + ) + }Also applies to: 229-232
🧹 Nitpick comments (3)
pkg/auth/cloud/aws/env.go (3)
119-121: Remove redundant error check.err is the same error returned from the closure into isolateErr; the second check is dead code after the previous return.
Apply:
- if err != nil { - return aws.Config{}, fmt.Errorf("%w: %w", errUtils.ErrLoadAwsConfig, err) - } + // Redundant check removed.
149-151: Drop noisy debug marker.The "=== UPDATED CODE" log is a leftover and adds noise.
Apply:
- log.Debug("=== UPDATED CODE: LoadAtmosManagedAWSConfig called ===")
16-39: Godot: end comments with periods.Several comment lines lack trailing periods; golangci-lint godot will flag them. Quick audit/fix across these blocks.
Would you like me to push a patch normalizing punctuation across the file?
Also applies to: 88-100, 126-143
📜 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 (5)
internal/aws_utils/aws_utils.go(2 hunks)internal/exec/terraform_output_utils.go(5 hunks)pkg/auth/cloud/aws/env.go(3 hunks)website/blog/2025-10-21-auth-context-implementation.md(2 hunks)website/docs/cli/commands/auth/auth-shell.mdx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- website/docs/cli/commands/auth/auth-shell.mdx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Define interfaces for major functionality and use dependency injection to enable testability.
Generate mocks using go.uber.org/mock/mockgen via //go:generate directives (never manual mocks).
Prefer functional Options pattern instead of functions with many parameters for configuration.
Use context.Context only for cancellation, deadlines/timeouts, and request-scoped values; never for configuration or dependencies; context should be the first parameter.
All comments must end with periods (godot linter).
Preserve helpful existing comments; update them to match code when refactoring; only remove when incorrect, redundant, or code removed.
Organize imports in three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically; maintain aliases cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Use static errors from errors/errors.go; wrap with fmt.Errorf("%w") for chaining; use errors.Join for independent errors; avoid dynamic errors and string comparison; use errors.Is for checks.
Never use //revive:disable:file-length-limit to bypass file size limits; keep files small and focused (<600 lines).
Environment variables must be bound with viper.BindEnv using ATMOS_ prefix (e.g., viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")).
Ensure cross-platform compatibility: use filepath.Join instead of hardcoded path separators and prefer SDKs over shelling out to binaries.
Files:
internal/aws_utils/aws_utils.gopkg/auth/cloud/aws/env.gointernal/exec/terraform_output_utils.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
internal/aws_utils/aws_utils.gopkg/auth/cloud/aws/env.gointernal/exec/terraform_output_utils.go
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/cloud/aws/env.go
website/**
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases
Files:
website/blog/2025-10-21-auth-context-implementation.md
website/blog/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-*.md
📄 CodeRabbit inference engine (CLAUDE.md)
PRs labeled minor or major must include a blog post with filename date prefix and feature name; include and proper tags.
Files:
website/blog/2025-10-21-auth-context-implementation.md
🧠 Learnings (6)
📓 Common learnings
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
📚 Learning: 2025-10-24T14:51:19.340Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-24T14:51:19.340Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Applied to files:
pkg/auth/cloud/aws/env.go
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain has been updated to follow XDG Base Directory Specification with helper functions GetXDGCacheDir() and GetXDGTempCacheDir() in toolchain/xdg_cache.go, using XDG_CACHE_HOME when set and falling back to ~/.cache/atmos-toolchain, making it consistent with atmos core's XDG compliance.
Applied to files:
website/blog/2025-10-21-auth-context-implementation.md
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: XDG Base Directory Specification compliance implementation for atmos toolchain is complete: created toolchain/xdg_cache.go with GetXDGCacheDir() and GetXDGTempCacheDir() functions, updated toolchain/installer.go and cmd/toolchain_clean.go to use these XDG helpers, and changed all cache paths from hardcoded ~/.cache/tools-cache to XDG-compliant ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback).
Applied to files:
website/blog/2025-10-21-auth-context-implementation.md
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: Final XDG Base Directory Specification implementation for atmos toolchain is complete and verified: toolchain/xdg_cache.go provides GetXDGCacheDir() and GetXDGTempCacheDir() functions, all hardcoded ~/.cache/tools-cache paths have been replaced with XDG-compliant paths using ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain fallback), and tests have been updated to expect the new path structure.
Applied to files:
website/blog/2025-10-21-auth-context-implementation.md
📚 Learning: 2025-09-08T01:25:44.958Z
Learnt from: osterman
PR: cloudposse/atmos#1466
File: website/docs/cli/commands/toolchain/usage.mdx:117-121
Timestamp: 2025-09-08T01:25:44.958Z
Learning: The atmos toolchain XDG compliance implementation is complete with GetXDGCacheDir() and GetXDGTempCacheDir() functions in toolchain/xdg_cache.go, updated installer.go and toolchain_clean.go to use these helpers, and changed cache paths from ~/.cache/tools-cache to ${XDG_CACHE_HOME}/atmos-toolchain (or ~/.cache/atmos-toolchain when XDG_CACHE_HOME is not set).
Applied to files:
website/blog/2025-10-21-auth-context-implementation.md
🧬 Code graph analysis (3)
internal/aws_utils/aws_utils.go (2)
pkg/logger/log.go (1)
Debug(24-26)errors/errors.go (1)
ErrLoadAwsConfig(74-74)
pkg/auth/cloud/aws/env.go (4)
pkg/schema/schema.go (1)
Context(409-424)pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (2)
Debug(24-26)Errorf(59-61)errors/errors.go (1)
ErrLoadAwsConfig(74-74)
internal/exec/terraform_output_utils.go (3)
pkg/schema/schema.go (1)
AuthContext(498-506)pkg/logger/log.go (1)
Debug(24-26)pkg/config/const.go (1)
EnvSectionName(61-61)
🪛 GitHub Check: Build (macos)
pkg/auth/cloud/aws/env.go
[failure] 144-144:
undefined: perf
🪛 LanguageTool
website/blog/2025-10-21-auth-context-implementation.md
[grammar] ~22-~22: Please add a punctuation mark at the end of paragraph.
Context: ...tion** for consistency with other Atmos data ## Why This Matters **The core proble...
(PUNCTUATION_PARAGRAPH_END)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Build (windows)
- GitHub Check: Build (linux)
- GitHub Check: Analyze (go)
- GitHub Check: website-deploy-preview
- GitHub Check: autofix
- GitHub Check: Review Dependency Licenses
- GitHub Check: Summary
🔇 Additional comments (8)
internal/aws_utils/aws_utils.go (3)
88-91: Good fix – error handling improved.The error from
os.UserHomeDir()is now properly captured and logged, addressing the previous review concern. Skipping the default path checks when the home directory can't be determined is the right approach.
92-120: Solid debugging instrumentation.The detailed logging of default paths, profile, and environment variables will help diagnose credential resolution issues. Using
filepath.Joinensures cross-platform compatibility, and the file existence checks add useful context without changing behavior.
125-136: Debug logging additions look good.The lifecycle logging around region handling and config loading will make it easier to trace SDK initialization issues. All debug-level, so no production noise.
internal/exec/terraform_output_utils.go (5)
63-69: LGTM: authContext parameter added correctly.The signature update cleanly threads authentication context through the execution path.
189-206: Solid isolation setup.The Atmos-managed credential paths, SDK config forcing, region handling, and IMDS disabling are all properly configured to prevent external auth interference.
208-221: LGTM: improved logging clarity.The "Adding" terminology and count logging make the env var merge behavior clearer.
223-232: Good guard and logging.The len check avoids an unnecessary SetEnv call when the map is empty, and the final count log helps with debugging.
376-396: LGTM: authContext properly threaded through.The signature update, documentation, and propagation to execTerraformOutput are all correct. Performance tracking is appropriately included for the public function.
Also applies to: 448-448
Error message improvements: - Add ErrUserAborted for clean user abort handling - Change error formatting from backticked quotes to backticks only - Add provider and credential store type to "no credentials found" errors CredentialStore.Type() implementation: - Add Type() method to CredentialStore interface - Implement Type() in all credential store implementations - Regenerate MockCredentialStore with Type() method Lint fixes: - Add constants for repeated string literals (logKeyProvider, logKeyIdentity, logKeyProfile, errFormatWrapTwo) - Remove non-essential debug logging using os.Getenv (forbidigo violations) - Reduce cyclomatic complexity in loadAWSCredentialsFromEnvironment by extracting helper functions - Fix function-result-limit by using awsEnvVars struct instead of multiple return values - Fix hugeParam by passing aws.Credentials by pointer - Reduce nestif complexity in validateCredentials using early return pattern - Split manager.go to reduce file length: - Extract logout functions to manager_logout.go - Extract whoami functions to manager_whoami.go - Split printWhoamiHuman into smaller functions Note: manager_logout.go has pre-existing complexity issues (gocognit, nestif, cyclomatic) that were moved from manager.go. These will be addressed in a separate commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add CredentialStoreType* constants to avoid magic strings: - CredentialStoreTypeSystemKeyring = "system-keyring" - CredentialStoreTypeNoop = "noop" - CredentialStoreTypeMemory = "memory" - CredentialStoreTypeFile = "file" Update all Type() method implementations to use these constants. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive tests for the helper functions extracted during cyclomatic complexity refactoring: - TestExtractAWSEnvVars: Tests environment variable extraction and validation with all combinations of present/missing required vars - TestSetupAWSEnv: Tests environment variable setup/cleanup with: * New environment vars (none existing) * Restoring original environment vars * Optional region parameter handling - TestPopulateExpiration: Tests credential expiration logic with: * SDK-provided expiration timestamps * Non-session credentials (no expiration) * Session tokens with zero/missing SDK expiration These tests verify behavior in isolation, making it easier to catch regressions and understand expected behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
When credentials are not found in the keyring, whoami should fallback to loading from identity-managed storage (AWS credential files, etc.). Previously, this only worked for noop keyring. Now it works for all keyring types, including system-keyring. This handles the common case where: 1. User authenticates via AWS CLI or other tools 2. Credentials are stored in ~/.aws/credentials 3. Atmos hasn't cached them in the keyring yet 4. User runs 'atmos auth whoami' to check credential status The fix moves the LoadCredentials fallback to apply to all keyring types when ErrCredentialsNotFound is returned, not just noop keyring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
pkg/auth/cloud/aws/env.go (2)
54-86: Add perf tracking to exported helper.WithIsolatedAWSEnv is public; add perf tracking per guidelines.
As per coding guidelines.
-func WithIsolatedAWSEnv(fn func() error) error { +func WithIsolatedAWSEnv(fn func() error) error { + defer perf.Track(nil, "pkg/auth/cloud/aws.WithIsolatedAWSEnv")()
100-124: I need to verify the AWS SDK isolation approach before finalizing:Add perf.Track and strengthen AWS config isolation.
- Add
defer perf.Track(nil, "pkg/auth/cloud/aws.LoadIsolatedAWSConfig")()to the start of the function per coding guidelines.- Strengthen isolation by explicitly disabling shared config and credentials file reads (not just the profile):
func LoadIsolatedAWSConfig(ctx context.Context, optFns ...func(*config.LoadOptions) error) (aws.Config, error) { + defer perf.Track(nil, "pkg/auth/cloud/aws.LoadIsolatedAWSConfig")() + - // Prepend config.WithSharedConfigProfile("") to disable loading from shared config files. - // This prevents the SDK from loading user's ~/.aws/config and ~/.aws/credentials files. - isolatedOptFns := make([]func(*config.LoadOptions) error, 0, len(optFns)+1) - isolatedOptFns = append(isolatedOptFns, config.WithSharedConfigProfile("")) + // Explicitly disable shared config/credentials files to prevent ~/.aws fallback loads. + isolatedOptFns := make([]func(*config.LoadOptions) error, 0, len(optFns)+3) + isolatedOptFns = append(isolatedOptFns, + config.WithSharedConfigFiles([]string{}), + config.WithSharedCredentialsFiles([]string{}), + config.WithSharedConfigProfile(""), + ) isolatedOptFns = append(isolatedOptFns, optFns...)Setting the shared config profile to an empty string only results in the profile value being ignored. Setting shared credentials files to an empty slice results in those files being ignored. This three-option approach closes potential fallback paths.
pkg/auth/cloud/aws/files.go (3)
61-88: Add perf tracking to constructor.NewAWSFileManager is exported; add perf tracking.
As per coding guidelines.
func NewAWSFileManager(basePath string) (*AWSFileManager, error) { + defer perf.Track(nil, "aws.files.NewAWSFileManager")()
117-191: Add perf tracking to exported write methods.WriteCredentials is exported; add perf tracking.
As per coding guidelines.
func (m *AWSFileManager) WriteCredentials(providerName, identityName string, creds *types.AWSCredentials) error { + defer perf.Track(nil, "aws.files.WriteCredentials")()
194-265: Add perf tracking to WriteConfig.WriteConfig is exported; add perf tracking.
As per coding guidelines.
func (m *AWSFileManager) WriteConfig(providerName, identityName, region, outputFormat string) error { + defer perf.Track(nil, "aws.files.WriteConfig")()
♻️ Duplicate comments (1)
pkg/auth/types/mock_interfaces.go (1)
837-850: Validate mock signature correctly updated.The previous review comment flagged that this mock returned
(*time.Time, error)instead of(*ValidationInfo, error). This has been corrected - the mock now properly returns(*ValidationInfo, error).
🧹 Nitpick comments (9)
pkg/auth/cloud/aws/env.go (1)
157-181: Process-wide env mutation is racy; prefer file/options over unset/restore.Unsetting env vars then restoring is not concurrency-safe. Prefer passing explicit shared config/credentials file options and profile via LoadOptions so no env changes are needed.
Would you like a version that accepts explicit files/profile and avoids os.Unsetenv/os.Setenv?
pkg/auth/manager.go (1)
413-419: Default files display path—align with new XDG location.Fallback to "~/.aws/atmos" is legacy. Consider delegating to provider (if available) or computing the XDG display path to reflect new defaults.
Do you want a small helper to fetch the XDG display path here?
pkg/auth/credentials/keyring_system.go (1)
143-146: Consider adding performance tracking for consistency.While this is a simple accessor, other methods in this file include
defer perf.Track(...). Consider adding it here for consistency:// Type returns the type of this credential store. func (s *systemKeyringStore) Type() string { + defer perf.Track(nil, "credentials.systemKeyringStore.Type")() + return types.CredentialStoreTypeSystemKeyring }As per coding guidelines: "Add defer perf.Track at the start of all public functions."
pkg/auth/credentials/keyring_memory.go (1)
137-140: Consider adding performance tracking for consistency.Similar to the system keyring, consider adding performance tracking:
// Type returns the type of this credential store. func (s *memoryKeyringStore) Type() string { + defer perf.Track(nil, "credentials.memoryKeyringStore.Type")() + return types.CredentialStoreTypeMemory }pkg/auth/credentials/keyring_file.go (1)
319-322: Consider adding performance tracking for consistency.For consistency with other methods in this file:
// Type returns the type of this credential store. func (s *fileKeyringStore) Type() string { + defer perf.Track(nil, "credentials.fileKeyringStore.Type")() + return types.CredentialStoreTypeFile }pkg/auth/manager_whoami.go (2)
11-44: Add performance tracking.The buildWhoamiInfo function should include performance tracking per coding guidelines:
// buildWhoamiInfo creates a WhoamiInfo struct from identity and credentials. func (m *manager) buildWhoamiInfo(identityName string, creds types.ICredentials) *types.WhoamiInfo { + defer perf.Track(nil, "auth.manager.buildWhoamiInfo")() + providerName := m.getProviderForIdentity(identityName)
46-95: Add performance tracking.The buildWhoamiInfoFromEnvironment function should include performance tracking:
func (m *manager) buildWhoamiInfoFromEnvironment(identityName string) *types.WhoamiInfo { + defer perf.Track(nil, "auth.manager.buildWhoamiInfoFromEnvironment")() + providerName := m.getProviderForIdentity(identityName)pkg/auth/identities/aws/credentials_loader.go (1)
24-59: Add performance tracking.Per coding guidelines, add performance tracking to this function:
func loadAWSCredentialsFromEnvironment(ctx context.Context, env map[string]string) (*types.AWSCredentials, error) { + defer perf.Track(nil, "aws.loadAWSCredentialsFromEnvironment")() + // Extract and validate AWS environment variables.Even unexported functions should include performance tracking for observability.
pkg/auth/identities/aws/credentials_loader_test.go (1)
240-380: Consider simplifying environment management.The test manually saves/unsets environment variables (lines 319-336) before using
t.Setenv(line 340), then registers a manual cleanup (lines 343-351). Sincet.Setenvalready handles cleanup, you could simplify by either:
- Using only
t.Setenvfor all env operations (it saves/restores automatically), or- Using only manual save/restore without
t.SetenvThe current approach works but mixes two cleanup strategies, making it harder to follow.
📜 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 (18)
cmd/auth_whoami.go(4 hunks)errors/errors.go(1 hunks)internal/aws_utils/aws_utils.go(1 hunks)pkg/auth/cloud/aws/env.go(3 hunks)pkg/auth/cloud/aws/files.go(6 hunks)pkg/auth/credentials/keyring_file.go(1 hunks)pkg/auth/credentials/keyring_memory.go(1 hunks)pkg/auth/credentials/keyring_noop.go(3 hunks)pkg/auth/credentials/keyring_system.go(1 hunks)pkg/auth/identities/aws/credentials_loader.go(1 hunks)pkg/auth/identities/aws/credentials_loader_test.go(1 hunks)pkg/auth/manager.go(7 hunks)pkg/auth/manager_logout.go(1 hunks)pkg/auth/manager_test.go(5 hunks)pkg/auth/manager_whoami.go(1 hunks)pkg/auth/types/interfaces.go(5 hunks)pkg/auth/types/mock_interfaces.go(6 hunks)pkg/auth/types/whoami_test.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- internal/aws_utils/aws_utils.go
- pkg/auth/manager_test.go
🧰 Additional context used
📓 Path-based instructions (6)
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/credentials/keyring_system.gopkg/auth/credentials/keyring_file.gopkg/auth/manager_logout.gopkg/auth/types/interfaces.gopkg/auth/manager_whoami.gopkg/auth/identities/aws/credentials_loader_test.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/credentials/keyring_memory.gopkg/auth/types/whoami_test.gopkg/auth/manager.gopkg/auth/cloud/aws/files.gopkg/auth/types/mock_interfaces.gopkg/auth/credentials/keyring_noop.gopkg/auth/cloud/aws/env.go
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Define interfaces for major functionality and use dependency injection to enable testability.
Generate mocks using go.uber.org/mock/mockgen via //go:generate directives (never manual mocks).
Prefer functional Options pattern instead of functions with many parameters for configuration.
Use context.Context only for cancellation, deadlines/timeouts, and request-scoped values; never for configuration or dependencies; context should be the first parameter.
All comments must end with periods (godot linter).
Preserve helpful existing comments; update them to match code when refactoring; only remove when incorrect, redundant, or code removed.
Organize imports in three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically; maintain aliases cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Use static errors from errors/errors.go; wrap with fmt.Errorf("%w") for chaining; use errors.Join for independent errors; avoid dynamic errors and string comparison; use errors.Is for checks.
Never use //revive:disable:file-length-limit to bypass file size limits; keep files small and focused (<600 lines).
Environment variables must be bound with viper.BindEnv using ATMOS_ prefix (e.g., viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")).
Ensure cross-platform compatibility: use filepath.Join instead of hardcoded path separators and prefer SDKs over shelling out to binaries.
Files:
pkg/auth/credentials/keyring_system.gopkg/auth/credentials/keyring_file.gopkg/auth/manager_logout.gopkg/auth/types/interfaces.gocmd/auth_whoami.gopkg/auth/manager_whoami.gopkg/auth/identities/aws/credentials_loader_test.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/credentials/keyring_memory.gopkg/auth/types/whoami_test.gopkg/auth/manager.goerrors/errors.gopkg/auth/cloud/aws/files.gopkg/auth/types/mock_interfaces.gopkg/auth/credentials/keyring_noop.gopkg/auth/cloud/aws/env.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
pkg/auth/credentials/keyring_system.gopkg/auth/credentials/keyring_file.gopkg/auth/manager_logout.gopkg/auth/types/interfaces.gocmd/auth_whoami.gopkg/auth/manager_whoami.gopkg/auth/identities/aws/credentials_loader.gopkg/auth/credentials/keyring_memory.gopkg/auth/manager.goerrors/errors.gopkg/auth/cloud/aws/files.gopkg/auth/types/mock_interfaces.gopkg/auth/credentials/keyring_noop.gopkg/auth/cloud/aws/env.go
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate
cmd/**/*.go: New CLI commands must use the command registry pattern via CommandProvider and register through the command registry (see cmd/internal/registry.go).
Commands should embed *_usage.md via //go:embed and render with utils.PrintfMarkdown().
UI (prompts/status) must write to stderr; data outputs to stdout; logging only for system events (never for UI).
For non-standard execution paths, capture telemetry with telemetry.CaptureCmd(); normal paths are auto-enabled via RootCmd.ExecuteC(). Never capture user data.
Files:
cmd/auth_whoami.go
{cmd,pkg/ui}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use theme colors from pkg/ui/theme/colors.go for UI elements.
Files:
cmd/auth_whoami.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + DI; table-driven tests for coverage; target >80% coverage.
Tests must exercise production code paths; avoid duplicating implementation logic in tests.
Use t.Skipf("reason") with clear context when skipping tests; CLI tests may auto-build temp binaries.
Files:
pkg/auth/identities/aws/credentials_loader_test.gopkg/auth/types/whoami_test.go
🧠 Learnings (8)
📓 Common learnings
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
📚 Learning: 2025-09-09T02:14:36.708Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1452
File: internal/auth/types/whoami.go:14-15
Timestamp: 2025-09-09T02:14:36.708Z
Learning: The WhoamiInfo struct in internal/auth/types/whoami.go requires the Credentials field to be JSON-serializable for keystore unmarshaling operations, despite security concerns about credential exposure.
Applied to files:
cmd/auth_whoami.go
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
PR: cloudposse/atmos#1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-10-24T14:51:19.340Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-24T14:51:19.340Z
Learning: Applies to **/*.go : Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Applied to files:
pkg/auth/cloud/aws/env.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
PR: cloudposse/atmos#1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.
Applied to files:
pkg/auth/cloud/aws/env.go
🧬 Code graph analysis (13)
pkg/auth/credentials/keyring_system.go (1)
pkg/auth/types/interfaces.go (1)
CredentialStoreTypeSystemKeyring(14-14)
pkg/auth/credentials/keyring_file.go (1)
pkg/auth/types/interfaces.go (1)
CredentialStoreTypeFile(17-17)
pkg/auth/manager_logout.go (4)
pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (3)
Errorf(59-61)Debug(24-26)Info(34-36)errors/errors.go (8)
ErrIdentityNotInConfig(428-428)ErrKeyringDeletion(425-425)ErrLogoutNotSupported(423-423)ErrProviderLogout(426-426)ErrIdentityLogout(427-427)ErrPartialLogout(422-422)ErrLogoutFailed(421-421)ErrProviderNotInConfig(429-429)pkg/auth/types/interfaces.go (2)
Provider(21-50)Identity(62-97)
cmd/auth_whoami.go (4)
pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/logger/log.go (1)
Debug(24-26)pkg/auth/types/interfaces.go (2)
Identity(62-97)ValidationInfo(212-227)pkg/ui/theme/colors.go (1)
ColorRed(16-16)
pkg/auth/manager_whoami.go (3)
pkg/auth/types/interfaces.go (3)
ICredentials(198-209)Provider(21-50)Identity(62-97)pkg/auth/types/whoami.go (1)
WhoamiInfo(6-22)pkg/logger/log.go (1)
Debug(24-26)
pkg/auth/identities/aws/credentials_loader_test.go (2)
errors/errors.go (1)
ErrAwsMissingEnvVars(382-382)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
pkg/auth/identities/aws/credentials_loader.go (3)
pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)pkg/logger/log.go (1)
Debug(24-26)errors/errors.go (1)
ErrAwsMissingEnvVars(382-382)
pkg/auth/credentials/keyring_memory.go (1)
pkg/auth/types/interfaces.go (1)
CredentialStoreTypeMemory(16-16)
pkg/auth/manager.go (4)
pkg/logger/log.go (2)
Errorf(59-61)Debug(24-26)errors/errors.go (6)
ErrIdentityNotFound(395-395)ErrNoCredentialsFound(388-388)ErrExpiredCredentials(389-389)ErrMultipleDefaultIdentities(399-399)ErrUserAborted(384-384)ErrInvalidAuthConfig(370-370)pkg/auth/credentials/keyring_file.go (1)
ErrCredentialsNotFound(36-36)pkg/perf/perf.go (1)
Track(121-138)
pkg/auth/cloud/aws/files.go (4)
pkg/xdg/xdg.go (1)
GetXDGConfigDir(46-48)pkg/logger/log.go (3)
Errorf(59-61)Warn(44-46)Debug(24-26)pkg/config/homedir/homedir.go (1)
Dir(36-63)pkg/auth/types/aws_credentials.go (1)
AWSCredentials(16-23)
pkg/auth/types/mock_interfaces.go (1)
pkg/auth/types/interfaces.go (3)
ICredentials(198-209)ValidationInfo(212-227)ConsoleURLOptions(241-258)
pkg/auth/credentials/keyring_noop.go (3)
pkg/auth/types/interfaces.go (2)
ICredentials(198-209)CredentialStoreTypeNoop(15-15)pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (1)
Debug(24-26)
pkg/auth/cloud/aws/env.go (3)
pkg/perf/perf.go (1)
Track(121-138)pkg/logger/log.go (2)
Debug(24-26)Errorf(59-61)errors/errors.go (1)
ErrLoadAwsConfig(74-74)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Build (linux)
- GitHub Check: Build (macos)
- GitHub Check: Build (windows)
- GitHub Check: autofix
- GitHub Check: Analyze (go)
- GitHub Check: Lint (golangci)
- GitHub Check: website-deploy-preview
- GitHub Check: Review Dependency Licenses
- GitHub Check: Summary
🔇 Additional comments (41)
pkg/auth/types/whoami_test.go (1)
21-21: Stub now satisfies interface surface.Adding Type() keeps the stub aligned with CredentialStore. Looks good.
errors/errors.go (1)
382-385: Useful new error sentinels.ErrAwsMissingEnvVars and ErrUserAborted align with flows added in auth. No issues.
pkg/auth/cloud/aws/files.go (2)
120-126: Good structured logging on credential writes.Pre-write debug fields are helpful. No change needed.
197-204: Good config write logging.Clear visibility into region/output. LGTM.
pkg/auth/types/interfaces.go (6)
12-18: Credential store type constants—nice taxonomy.Clear, self-explanatory constants. LGTM.
155-160: AuthManager.GetEnvironmentVariables—useful foratmos env.API shape looks right.
179-181: CredentialStore.Type—good for diagnostics.This unblocks better error messages (used in Whoami). LGTM.
211-227: ValidationInfo shape looks solid.Fields cover principal/account/expiration across clouds. LGTM.
205-209: No issues found—mocks and signatures are consistent.All stale signatures are gone, mocks have been properly regenerated with the correct
Validate(ctx context.Context) (*ValidationInfo, error)signature, and ValidationInfo is correctly imported and used throughout call sites.
88-97: All Identity implementations and mocks updated—verification complete.Confirmed all Identity implementations (assumeRoleIdentity, userIdentity, permissionSetIdentity, mock.Identity, MockIdentity) now have both CredentialsExist and LoadCredentials methods. Generated mocks also include both methods with proper EXPECT recorders.
pkg/auth/manager.go (3)
197-221: Whoami noop-keyring fallback—exactly what containers need.Handling ErrCredentialsNotFound by building from environment is the right behavior. Nice touch including credential_store type in errors.
301-306: Map TUI aborts to ErrUserAborted.Clean UX; keeps CLI semantics predictable.
756-775: New manager.GetEnvironmentVariables—API and perf tracking look good.Straightforward pass-through with identity existence check. LGTM.
pkg/auth/manager_logout.go (6)
14-15: Add performance tracking with nil atmosConfig.The defer statement calls perf.Track with nil, which aligns with the coding guidelines for manager methods. However, ensure this is intentional.
110-150: LGTM on provider resolution logic.The cycle detection and safe fallback handling are well-implemented. The function correctly traverses the identity chain to find the root provider.
152-214: LogoutProvider implementation looks solid.The use of context values to skip nested provider logout during per-identity cleanup is a clean approach. Error aggregation maintains best-effort semantics.
216-239: LogoutAll implementation is clean.Straightforward iteration over all identities with proper error aggregation.
40-40: No issues found—constant is defined at package scope.The search confirms
errFormatWrapTwois defined inpkg/auth/manager.goat line 31 as a package-scoped constant. Sincemanager_logout.gois in the same package, it has full access to this constant. The code is correct.
48-48: No action needed—skipProviderLogoutKey is properly defined.The verification confirms that
skipProviderLogoutKeyis defined at the package level inpkg/auth/manager.go:39as a constant of typecontextKey. The code at line 48 correctly references this package-level definition.Likely an incorrect or invalid review comment.
pkg/auth/types/mock_interfaces.go (1)
198-211: New mock methods properly generated.The additions for CredentialsExist, LoadCredentials, GetEnvironmentVariables, Type, and ConsoleAccessProvider follow correct gomock patterns and align with the interface updates described in the PR objectives.
Also applies to: 257-270, 382-395, 678-690, 852-904
pkg/auth/identities/aws/credentials_loader.go (5)
69-86: Environment variable validation looks good.Clean validation with descriptive error message listing all required variables.
88-118: Environment setup and cleanup pattern is solid.The save/restore pattern with cleanup function ensures environment variables are properly reset after credential loading.
120-146: SDK credential loading implementation is correct.Proper use of AWS SDK with good error messages and context handling.
148-163: Expiration population logic handles both SDK and metadata sources.Good fallback strategy when SDK doesn't provide expiration but session token exists.
165-227: Metadata parsing logic is robust.The function safely handles missing or malformed metadata, returning empty string as fallback. RFC3339 validation ensures only valid timestamps are used.
cmd/auth_whoami.go (7)
55-68: Credential validation integration looks clean.The validation flow is well-integrated, with results properly passed to the output functions.
72-105: Validation logic handles multiple credential types gracefully.The type assertion pattern with fallback to expiration check provides good coverage. Populating whoami with validation info maintains data consistency.
107-121: Population helper is straightforward and safe.Proper nil checks ensure no panics when validation info is incomplete.
165-179: Human output correctly uses stderr and theme colors.The status indicator with colored checkmark/X provides immediate visual feedback. Using os.Stderr for UI output aligns with coding guidelines.
181-209: Table row builder is clean and conditional.The function properly handles optional fields and delegates expiration formatting.
211-225: Expiration formatting provides clear urgency signals.The threshold-based color coding (red for expiring soon, gray otherwise) gives users immediate visual feedback about credential freshness.
227-245: Table styling is consistent with UI theme.The use of theme colors and clean borders creates professional output aligned with the rest of the CLI.
pkg/auth/identities/aws/credentials_loader_test.go (5)
18-105: Solid test coverage for metadata parsing.Table-driven approach covers the key scenarios well: valid expiration, missing metadata, invalid format, wrong prefix, and profile-not-found cases.
107-110: LGTM.Verifies graceful degradation when the credentials file doesn't exist.
112-148: Good end-to-end validation.The round-trip test ensures metadata write and read operations work correctly, and the RFC3339 parsing confirms the timestamp format is valid.
150-238: Comprehensive environment variable validation.All required/optional combinations are tested, and error checking properly uses
ErrorIsto verify the specific error type.
382-453: Expiration logic well tested.Covers SDK-provided expiration, non-session credentials (no expiration), and fallback behavior when metadata is unavailable.
pkg/auth/credentials/keyring_noop.go (4)
9-18: Clear documentation of noop store semantics.The comments effectively explain that this store is for containerized environments where credentials are externally managed, and that it doesn't store or validate credentials.
20-45: Retrieve semantics are well-explained.The extensive comments (lines 30-43) clearly document why validation isn't performed and why
ErrCredentialsNotFoundis returned, making the design intent obvious.
47-67: Consistent no-op implementations.All methods properly signal that credentials aren't managed by this store, with appropriate return values for each contract.
68-85: Type() method properly documented.The godoc comment follows the standard format, and the implementation correctly returns the noop store type constant.
Enable `findFirstValidCachedCredentials` to find credentials stored in AWS files (not just keyring) when validating the authentication chain. This fixes the issue where: 1. User authenticates with a provider (e.g., core-identity/managers-team-access) 2. Provider credentials are stored in AWS credential files 3. Derived identities that depend on that provider fail to authenticate because the chain validation only checked the keyring The fix adds a fallback to load credentials from identity storage (AWS files, etc.) when the keyring returns `ErrCredentialsNotFound`, mirroring the same pattern used in the Whoami command. This enables chained authentication scenarios where provider credentials exist in standard AWS credential files created by AWS CLI, SSO, or other external tools, without requiring those credentials to be cached in the system keyring first. Refactored nested if/else blocks to use early returns for better readability and to satisfy golangci-lint revive rules. Note: Pre-existing lint violations in manager_logout.go (gocognit, nestif, cyclomatic) are unrelated to this change and will be addressed separately. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses multiple issues with credential validation in the
authentication chain:
1. **System keyring ErrCredentialsNotFound detection**: Updated
systemKeyringStore.Retrieve() to return ErrCredentialsNotFound when
the underlying keyring returns keyring.ErrNotFound. This ensures
consistent error handling across all credential store implementations
and enables proper fallback logic.
2. **Credential validation based on actual expiration**: Fixed
isCredentialValid() to check expiration from the credentials object
itself, rather than querying the keyring. This allows validation of
credentials loaded from any source (keyring, AWS files, etc.) based
on their actual expiration time.
3. **Credential reloading for expired/invalid cached credentials**: Added
logic to findFirstValidCachedCredentials() to attempt reloading from
identity storage when cached credentials are expired or missing
expiration metadata. This handles cases where:
- Keyring has stale credentials without expiration info
- AWS credential files have fresher credentials with valid expiration
- External tools have updated credentials that aren't yet in keyring
4. **Enhanced Whoami fallback logic**: Updated Whoami() to:
- First try loading from identity storage when keyring lookup fails
- Fall back to chain authentication if direct loading fails
- This enables whoami to work even when target identity credentials
aren't directly available but can be derived through the chain
These changes improve the robustness of credential resolution, especially
in scenarios where credentials exist in AWS files but not in the system
keyring, or where keyring credentials are stale compared to file-based
credentials.
Note: Pre-existing lint violations in manager_logout.go (gocognit,
nestif, cyclomatic) are unrelated to these changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The `atmos auth logout` command was accepting the `--identity` flag inherited from the parent `auth` command, but silently ignoring it and falling through to interactive mode. This caused confusing UX where users would type: atmos auth logout --identity plat-dev/admin And instead of logging out that specific identity, they would see an interactive prompt asking what to logout, potentially logging out all identities if they selected the wrong option. **Changes:** 1. Added validation to detect when `--identity` flag is used with logout 2. Display clear error message explaining the correct usage: - Use positional argument: `atmos auth logout <identity-name>` - Not the flag: `atmos auth logout --identity <identity-name>` 3. Added test to ensure this validation stays in place 4. Added `logKeyChainIndex` constant to fix linter warning **Root Cause:** The `--identity` flag is a PersistentFlag on the parent `auth` command, making it available to all subcommands (whoami, login, exec, etc.). However, `logout` was designed to use positional arguments for identity names, not the `--identity` flag. The flag was silently accepted but unused, causing the confusing interactive prompt behavior. **Related Issues:** This also clarifies the distinction between identity logout (removes one identity's credentials) vs provider logout (removes provider + all derived identities). Note: Pre-existing lint violations in manager_logout.go (gocognit, nestif, cyclomatic) are unrelated to this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
cmd/auth_logout_test.go (1)
341-345: Remove redundant cleanup - TestKit handles state restoration.
NewTestKit(t)already registers cleanup viat.Cleanup()to restore RootCmd state. The manualtk.Cleanup()call and flag reset are unnecessary and redundant.Apply this diff:
tk := NewTestKit(t) - defer tk.Cleanup(func() { - // Reset the flag after test. - authLogoutCmd.Flags().Set("identity", "") - })cmd/auth_logout.go (1)
63-74: Consider moving flag validation earlier for efficiency.The validation logic is solid and provides clear user guidance. However, since it doesn't depend on
atmosConfigorauthManager, consider moving it earlier (after line 61) to fail fast before expensive config loading.Optional refactor to move validation earlier:
// Get flags. providerFlag, _ := cmd.Flags().GetString("provider") dryRun, _ := cmd.Flags().GetBool("dry-run") + + // Check if the inherited --identity flag was used (common mistake). + identityFlag, _ := cmd.Flags().GetString("identity") + if identityFlag != "" { + u.PrintfMarkdownToTUI("**Error:** The `--identity` flag is not supported by `atmos auth logout`.\n\n") + u.PrintfMarkdownToTUI("**Usage:**\n") + u.PrintfMessageToTUI(" Logout specific identity: atmos auth logout <identity-name>\n") + u.PrintfMessageToTUI(" Logout specific provider: atmos auth logout --provider <provider-name>\n") + u.PrintfMessageToTUI(" Logout all: atmos auth logout\n\n") + u.PrintfMarkdownToTUI("**Example:**\n") + u.PrintfMessageToTUI(" atmos auth logout plat-dev/admin\n\n") + return fmt.Errorf("%w: use positional argument instead of --identity flag", errUtils.ErrInvalidFlag) + } - // Check if the inherited --identity flag was used (common mistake). - identityFlag, _ := cmd.Flags().GetString("identity") - if identityFlag != "" { - u.PrintfMarkdownToTUI("**Error:** The `--identity` flag is not supported by `atmos auth logout`.\n\n") - u.PrintfMarkdownToTUI("**Usage:**\n") - u.PrintfMessageToTUI(" Logout specific identity: atmos auth logout <identity-name>\n") - u.PrintfMessageToTUI(" Logout specific provider: atmos auth logout --provider <provider-name>\n") - u.PrintfMessageToTUI(" Logout all: atmos auth logout\n\n") - u.PrintfMarkdownToTUI("**Example:**\n") - u.PrintfMessageToTUI(" atmos auth logout plat-dev/admin\n\n") - return fmt.Errorf("%w: use positional argument instead of --identity flag", errUtils.ErrInvalidFlag) - } - ctx := context.Background()However, current placement is acceptable if you prefer to validate after config initialization.
pkg/auth/manager.go (2)
32-32: Remove unused constant.The
errFormatWrapTwoconstant is defined but never used in this file. Dead code should be removed to keep the codebase clean.Apply this diff:
- errFormatWrapTwo = "%w for %q: %w"
506-579: Good enhancement for external credential file support.The dual-source credential loading (keyring + identity storage) correctly handles credentials created outside Atmos. The validity checking and reload logic are sound.
Optional: Consider extracting the credential retrieval/validation logic into helper methods to reduce the length of this function. The current implementation works well but could be more maintainable.
📜 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)
cmd/auth_logout.go(1 hunks)cmd/auth_logout_test.go(1 hunks)pkg/auth/credentials/keyring_system.go(2 hunks)pkg/auth/manager.go(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- pkg/auth/credentials/keyring_system.go
🧰 Additional context used
📓 Path-based instructions (7)
cmd/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate
cmd/**/*.go: New CLI commands must use the command registry pattern via CommandProvider and register through the command registry (see cmd/internal/registry.go).
Commands should embed *_usage.md via //go:embed and render with utils.PrintfMarkdown().
UI (prompts/status) must write to stderr; data outputs to stdout; logging only for system events (never for UI).
For non-standard execution paths, capture telemetry with telemetry.CaptureCmd(); normal paths are auto-enabled via RootCmd.ExecuteC(). Never capture user data.
Files:
cmd/auth_logout.gocmd/auth_logout_test.go
**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments
**/*.go: Define interfaces for major functionality and use dependency injection to enable testability.
Generate mocks using go.uber.org/mock/mockgen via //go:generate directives (never manual mocks).
Prefer functional Options pattern instead of functions with many parameters for configuration.
Use context.Context only for cancellation, deadlines/timeouts, and request-scoped values; never for configuration or dependencies; context should be the first parameter.
All comments must end with periods (godot linter).
Preserve helpful existing comments; update them to match code when refactoring; only remove when incorrect, redundant, or code removed.
Organize imports in three groups (stdlib, third-party, Atmos) separated by blank lines and sorted alphabetically; maintain aliases cfg, log, u, errUtils.
Add defer perf.Track(atmosConfig, "pkg.FuncName")() (or nil if no atmosConfig) plus a blank line at the start of all public functions for performance tracking.
Use static errors from errors/errors.go; wrap with fmt.Errorf("%w") for chaining; use errors.Join for independent errors; avoid dynamic errors and string comparison; use errors.Is for checks.
Never use //revive:disable:file-length-limit to bypass file size limits; keep files small and focused (<600 lines).
Environment variables must be bound with viper.BindEnv using ATMOS_ prefix (e.g., viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")).
Ensure cross-platform compatibility: use filepath.Join instead of hardcoded path separators and prefer SDKs over shelling out to binaries.
Files:
cmd/auth_logout.gocmd/auth_logout_test.gopkg/auth/manager.go
**/!(*_test).go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Document all exported functions, types, and methods with Go doc comments
Files:
cmd/auth_logout.gopkg/auth/manager.go
{cmd,pkg/ui}/**/*.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use theme colors from pkg/ui/theme/colors.go for UI elements.
Files:
cmd/auth_logout.gocmd/auth_logout_test.go
**/*_test.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios
**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + DI; table-driven tests for coverage; target >80% coverage.
Tests must exercise production code paths; avoid duplicating implementation logic in tests.
Use t.Skipf("reason") with clear context when skipping tests; CLI tests may auto-build temp binaries.
Files:
cmd/auth_logout_test.go
cmd/**/*_test.go
📄 CodeRabbit inference engine (CLAUDE.md)
Use cmd.NewTestKit(t) for any tests that touch RootCmd to auto-clean RootCmd state.
Files:
cmd/auth_logout_test.go
pkg/**/*.go
📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Place business logic in pkg rather than in cmd
Files:
pkg/auth/manager.go
🧠 Learnings (5)
📓 Common learnings
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: internal/exec/terraform.go:269-272
Timestamp: 2025-10-03T18:02:08.535Z
Learning: In internal/exec/terraform.go, when auth.TerraformPreHook fails, the error is logged but execution continues. This is a deliberate design choice to allow Terraform commands to proceed even if authentication setup fails, rather than failing fast.
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
PR: cloudposse/atmos#1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: The user confirmed that the errors package has an error string wrapping format, contradicting the previous learning about ErrWrappingFormat being invalid. The current usage of fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) appears to be the correct pattern.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
PR: cloudposse/atmos#1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.
Applied to files:
pkg/auth/manager.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.
Applied to files:
pkg/auth/manager.go
🧬 Code graph analysis (3)
cmd/auth_logout.go (3)
pkg/utils/markdown_utils.go (1)
PrintfMarkdownToTUI(89-93)pkg/utils/log_utils.go (1)
PrintfMessageToTUI(33-35)errors/errors.go (1)
ErrInvalidFlag(108-108)
cmd/auth_logout_test.go (2)
cmd/testkit_test.go (1)
NewTestKit(55-65)errors/errors.go (1)
ErrInvalidFlag(108-108)
pkg/auth/manager.go (5)
pkg/logger/log.go (2)
Errorf(59-61)Debug(24-26)errors/errors.go (6)
ErrIdentityNotFound(395-395)ErrNoCredentialsFound(388-388)ErrExpiredCredentials(389-389)ErrMultipleDefaultIdentities(399-399)ErrUserAborted(384-384)ErrInvalidAuthConfig(370-370)pkg/auth/credentials/keyring_file.go (1)
ErrCredentialsNotFound(36-36)pkg/auth/types/interfaces.go (1)
ICredentials(198-209)pkg/perf/perf.go (1)
Track(121-138)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Build (windows)
- GitHub Check: Build (macos)
- GitHub Check: prepare
- GitHub Check: validate-codeowners
- GitHub Check: website-deploy-preview
- GitHub Check: PR Size Labeler
- GitHub Check: Check for changelog entry
- GitHub Check: PR Semver Labels
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Summary
🔇 Additional comments (4)
cmd/auth_logout_test.go (1)
348-356: Solid test coverage for flag validation.The test correctly verifies that
--identityflag usage triggers validation with appropriate error type and message. Clean assertions withErrorIsandContains.cmd/auth_logout.go (1)
63-74: Clean validation with helpful user guidance.The implementation correctly prevents
--identityflag usage and provides clear examples directing users to the right approach. Error handling follows guidelines with proper wrapping and static error types.pkg/auth/manager.go (2)
198-245: Solid fallback strategy for containerized environments.The three-tier fallback (keyring → identity storage → chain auth) handles the noop keyring case well and aligns with the PR objectives. The extensive debug logging will help troubleshoot credential loading issues.
834-853: Clean implementation of environment variable retrieval.The method follows coding guidelines with proper performance tracking and error wrapping. The delegation to
identity.Environment()is appropriate.
…h commands The `auth shell`, `auth exec`, `auth console`, and `auth env` commands were calling `Authenticate()` directly, which forces a full authentication flow (including SSO device prompts) even when valid cached credentials already exist. This caused poor UX where users would run `auth whoami` and see valid credentials, then run `auth shell` and be prompted to login again despite having 1+ hours remaining on their session. **Changes:** 1. Updated all auth commands to call `Whoami()` first 2. Only fallback to `Authenticate()` if `Whoami()` fails (no cached creds) 3. Added debug logging to show when fallback authentication is triggered 4. Added missing log import to `auth_exec.go` **Behavior:** - `auth login` - Still forces fresh authentication (correct behavior) - `auth whoami` - Already used `Whoami()` (no change needed) - `auth shell` - Now checks cache first ✓ - `auth exec` - Now checks cache first ✓ - `auth console` - Now checks cache first ✓ - `auth env --login` - Now checks cache first ✓ **Benefits:** - Eliminates unnecessary SSO prompts when credentials are valid - Provides seamless experience across auth commands - Reduces authentication latency (cached lookup vs full flow) - Consistent behavior: all commands respect cached credentials **Testing:** Verified that `auth shell` with valid cached credentials (38 min remaining) successfully uses the cache without triggering authentication flow. Note: Pre-existing lint violations in manager_logout.go (gocognit, nestif, cyclomatic) are unrelated to this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
These changes were released in v1.196.0-test.3. |
|
These changes were released in v1.196.0-rc.4. |
Summary
This PR addresses multiple authentication issues when using Atmos in containerized environments with mounted credential files:
LoadAtmosManagedAWSConfig()function provides proper isolation while preserving Atmos-managed profile selectionatmos auth whoaminow works in containerized environmentsChanges
1. Auth Pre-Hook Error Propagation (
internal/exec/terraform.go:236)return errafter logging auth pre-hook errors2. AWS Credential Loading Strategy (
pkg/auth/cloud/aws/env.go)AWS_PROFILE, causing conflicts in containersLoadAtmosManagedAWSConfig()function that:AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN)AWS_PROFILE,AWS_SHARED_CREDENTIALS_FILE,AWS_CONFIG_FILE)3. Noop Keyring Credential Validation (
pkg/auth/credentials/keyring_noop.go)config.LoadDefaultConfig()which allowed IMDS access and was affected by externalAWS_PROFILELoadAtmosManagedAWSConfig()4. Whoami with Noop Keyring (
pkg/auth/manager.go)Whoami()expected credentials from keyring, but noop keyring returnsErrCredentialsNotFoundby designErrCredentialsNotFoundand fallback tobuildWhoamiInfoFromEnvironment()atmos auth whoaminow works in containerized environments5. Test Coverage (
internal/exec/terraform_test.go)TestExecuteTerraform_AuthPreHookErrorPropagationto verify auth errors properly abort executionname_patternconfigurationTechnical Details
The key insight is that Atmos sets
AWS_PROFILE=identity-name(inpkg/auth/cloud/aws/setup.go:59) but the previous isolation approach cleared ALL AWS env vars includingAWS_PROFILE. This caused the SDK to look for a non-existent[default]section.The new
LoadAtmosManagedAWSConfigpreservesAWS_PROFILEwhile still preventing external credential conflicts.Test Plan
go build .- Build succeedsgo test ./internal/exec -run TestExecuteTerraform- All terraform tests passTestExecuteTerraform_AuthPreHookErrorPropagation- New test passesReferences
Fixes authentication issues in containerized environments with mounted credentials.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests