Skip to content

Conversation

@franklouwers
Copy link

@franklouwers franklouwers commented Nov 27, 2025

CLI Provider Authentication Support for STACKIT SDK

Summary

This PR adds comprehensive support for using STACKIT CLI provider credentials directly in the SDK, enabling seamless authentication across CLI and SDK-based tools without requiring re-authentication. (requires stackitcloud/stackit-cli#1130)

Key Features

  • CLI Credential Integration: New cliauth package enables SDK applications to read and use credentials stored by the STACKIT CLI
  • Automatic Token Refresh: Built-in OAuth2 token refresh with bidirectional sync (tokens refreshed by SDK are written back to storage)
  • Multi-Profile Support: Full support for CLI profiles with automatic resolution from explicit parameters, environment variables, or config files
  • Cross-Platform Storage: Credentials stored in system keyring (macOS Keychain, Linux Secret Service, Windows Credential Manager) with automatic file fallback
  • Thread-Safe: Concurrent request handling with automatic token refresh coordination
  • Background Refresh: Optional background goroutine for proactive token refresh before expiration

Architecture

The implementation consists of four logical commits:

  1. Core Authentication Package (core/cliauth):

    • credentials.go: Credential reading from keyring/file with profile resolution
    • token_refresh.go: OAuth2 token refresh with configurable endpoints
    • flow.go: Thread-safe http.RoundTripper implementation for automatic auth injection
    • background_refresh.go: Background token refresh with context-based lifecycle
    • doc.go: Comprehensive package documentation with usage examples
  2. SDK Configuration Integration (core/config/cli_auth.go):

    • WithCLIProviderAuth(profile): Configure SDK clients to use CLI credentials
    • WithCLIBackgroundTokenRefresh(ctx): Enable background token refresh

Usage Example

// Basic usage with default profile
client, err := dns.NewAPIClient(
    config.WithCLIProviderAuth(""),
)

// With custom profile
client, err := dns.NewAPIClient(
    config.WithCLIProviderAuth("production"),
)

// With background token refresh
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

client, err := dns.NewAPIClient(
    config.WithCLIBackgroundTokenRefresh(ctx),
    config.WithCLIProviderAuth(""),
)

Storage Locations

System Keyring (preferred):

  • Service name: stackit-cli-api (default) or stackit-cli-api/{profile}
  • Platforms: macOS Keychain, Linux Secret Service, Windows Credential Manager

File Fallback:

  • Default profile: ~/.stackit/cli-api-auth-storage.txt
  • Custom profiles: ~/.stackit/profiles/{profile}/cli-api-auth-storage.txt
  • Format: Base64-encoded JSON

Profile Resolution Order

  1. Explicit profile parameter
  2. STACKIT_CLI_PROFILE environment variable
  3. ~/.config/stackit/cli-profile.txt config file
  4. "default" fallback

Backward Compatibility

  • compatible with credentials created by existing STACKIT CLI versions
  • All file paths, formats, and keyring service names match CLI exactly
  • Users can seamlessly switch between CLI and SDK-based tools

Related Issues

Checklist

  • Issue was linked above
  • No generated code was adjusted manually (check comments in file header)
  • Changelogs
    • Changelog in the root directory was adjusted (see here)
    • Changelog(s) of the service(s) were adjusted (see e.g. here)
  • VERSION file(s) of the service(s) were adjusted
  • Code format was applied: make fmt
  • Examples were added / adjusted (see examples/ directory)
  • Unit tests got implemented or updated
  • Unit tests are passing: make test (will be checked by CI)
  • No linter issues: make lint (will be checked by CI)

Add new cliauth package that enables SDK applications to use STACKIT CLI
provider credentials without direct CLI dependency. This implementation
supports:

- Reading credentials from system keyring or file fallback
- Automatic OAuth2 token refresh with configurable endpoints
- Multiple CLI profile support with profile resolution
- Bidirectional credential sync (writeback after refresh)
- Thread-safe RoundTripper implementation for HTTP clients
- Background token refresh with context-based lifecycle management

Storage locations:
- System Keyring (macOS Keychain, Linux Secret Service, Windows Credential Manager)
- File fallback: ~/.stackit/cli-api-auth-storage.txt
Add WithCLIProviderAuth and WithCLIBackgroundTokenRefresh configuration
options to the SDK config package. This enables easy integration of CLI
provider authentication into SDK clients.

Features:
- WithCLIProviderAuth: Configure SDK to use CLI credentials with profile support
- WithCLIBackgroundTokenRefresh: Enable background token refresh with context
- Profile resolution from parameter, env var, config file, or default

Usage example:
  client, err := dns.NewAPIClient(
      config.WithCLIProviderAuth(""),
  )
Add unit tests for CLI provider authentication functionality:

- credentials_test.go: Tests for credential reading, profile resolution,
  keyring/file fallback behavior
- token_refresh_test.go: Tests for token expiration check and refresh logic
- flow_test.go: Tests for RoundTripper implementation and automatic refresh
- cli_auth_test.go: Tests for SDK config integration

Tests cover:
- Profile resolution order (explicit, env var, config file, default)
- Storage location fallback (keyring -> file)
- Token refresh with mock OAuth endpoints
- Thread-safe concurrent access
- Error handling for missing credentials and expired tokens
Fix test expectations to match the actual implementation:
- Update keyring service name from 'stackit-cli-provider' to 'stackit-cli-api'
- Update file paths from 'cli-provider-auth-storage.txt' to 'cli-api-auth-storage.txt'
- Rewrite config tests to match the actual API (profile string instead of provider object)
- Fix helper functions in test files

All tests now pass successfully.
@franklouwers franklouwers requested a review from a team as a code owner November 27, 2025 22:44
@franklouwers
Copy link
Author

Please advise on versioning. Do you have conventions you use?

franklouwers added a commit to franklouwers/terraform-provider-stackit that referenced this pull request Nov 28, 2025
This commit adds support for CLI-based authentication in the Terraform
provider, enabling users to authenticate using credentials from the
STACKIT CLI without managing separate service account credentials.

Changes:
- Add cli_auth boolean attribute to enable CLI authentication
- Add cli_profile string attribute for profile selection
- Implement authentication priority: explicit credentials > CLI > env vars
- Integrate with SDK's WithCLIProviderAuth() configuration option

The implementation follows the explicit opt-in pattern requested in
RFC stackitcloud#880, requiring users to set cli_auth = true to enable the feature.
Profile resolution follows the standard precedence: explicit config >
STACKIT_CLI_PROFILE env var > ~/.config/stackit/cli-profile.txt > default.

This change depends on SDK PR stackitcloud/stackit-sdk-go#3865 which
adds the core CLI authentication functionality, and CLI PR
stackitcloud/stackit-cli#1130 which implements the provider credential
storage.

Closes stackitcloud#719
Related to stackitcloud#880
franklouwers added a commit to franklouwers/terraform-provider-stackit that referenced this pull request Nov 28, 2025
This commit adds support for CLI-based authentication in the Terraform
provider, enabling users to authenticate using credentials from the
STACKIT CLI without managing separate service account credentials.

Changes:
- Add cli_auth boolean attribute to enable CLI authentication
- Add cli_profile string attribute for profile selection
- Implement authentication priority: explicit credentials > CLI > env vars
- Integrate with SDK's WithCLIProviderAuth() configuration option

The implementation follows the explicit opt-in pattern requested in
RFC stackitcloud#880, requiring users to set cli_auth = true to enable the feature.
Profile resolution follows the standard precedence: explicit config >
STACKIT_CLI_PROFILE env var > ~/.config/stackit/cli-profile.txt > default.

This change depends on SDK PR stackitcloud/stackit-sdk-go#3865 which
adds the core CLI authentication functionality, and CLI PR
stackitcloud/stackit-cli#1130 which implements the provider credential
storage.

Closes stackitcloud#719
Related to stackitcloud#880
franklouwers added a commit to franklouwers/terraform-provider-stackit that referenced this pull request Nov 28, 2025
Add replace directive to use SDK fork with CLI authentication support
from PR stackitcloud/stackit-sdk-go#3865 until it's merged and released.

This allows the provider to be built and tested with the CLI auth
functionality before the SDK changes are officially released.

The replace directive references commit 25b6b99bd648 from
github.com/franklouwers/stackit-sdk-go/core which includes the
core/cliauth package and config.WithCLIProviderAuth() function.

Once SDK PR #3865 is merged and a new SDK version is released,
this replace directive should be removed and the provider updated
to require the new SDK version.
Add comprehensive example demonstrating how to use CLI provider
authentication to access STACKIT CLI credentials from applications.

The example covers:
- Default profile authentication
- Specific profile authentication
- Direct credential access for advanced use cases

Also updated the existing authentication example to reference the new
CLI provider authentication option.
@marceljk
Copy link
Contributor

Please advise on versioning. Do you have conventions you use?

@franklouwers Thanks for your contribution across the CLI, SDK and Terraform provider! I created internal tickets to review them soon.

Regarding versioning we do a minor bump, when something is added, like the CLI Authentication. Please adjust the version file to v0.21.0

Create a new entry in core/CHANGELOG.md and in the global CHANGELOG.md, there you can define the changes you made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Support CLI Authentication Fallback in the STACKIT Terraform Provider

2 participants