Skip to content

feat: add credential provider chain concept#275

Open
cloudsmith-iduffy wants to merge 3 commits intoiduffy/pre-release-clifrom
iduffy/credential-provider-chain
Open

feat: add credential provider chain concept#275
cloudsmith-iduffy wants to merge 3 commits intoiduffy/pre-release-clifrom
iduffy/credential-provider-chain

Conversation

@cloudsmith-iduffy
Copy link
Contributor

@cloudsmith-iduffy cloudsmith-iduffy commented Mar 13, 2026

Description

The goal here is to introduce a credential provider chain similar to https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html to give us a pluggable system for inserting various methods of authentication, such as api keys in envvars, cli params, config, automatic discovery of the environment you're running on, OIDC exchange, running an external process, etc.

Type of Change

  • Bug fix
  • [] New feature
  • Breaking change
  • Documentation update
  • Refactoring
  • Other (please describe)

Additional Notes

I manually tested this to a large extent the results of this are below

Credential Provider Chain — Test Results

Comparison of published CLI (uvx --from=cloudsmith-cli) vs this branch.


API Key Scenarios

Scenario 1: Anonymous (no credentials)

Published CLI:

$ cloudsmith whoami --verbose
You are authenticated as:
Nobody (i.e. anonymous user)

Local CLI (this branch):

$ cloudsmith whoami --verbose
You are authenticated as:
Nobody (i.e. anonymous user)

Scenario 2: API key via CLOUDSMITH_API_KEY env var

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 3: API key via --api-key flag

Published CLI:

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLI --api-key flag
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLI --api-key flag
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 4: API key via -k short flag

Published CLI:

$ cloudsmith whoami --verbose -k <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLI --api-key flag
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose -k <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLI --api-key flag
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 5: API key via credentials.ini (~/.cloudsmith/)

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 6: API key via credentials.ini (app dir)

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/Library/Application Support/cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/Library/Application Support/cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 7: API key via credentials.ini (current dir)

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (./credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (./credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 8: API key via --credentials-file flag

Published CLI:

$ cloudsmith whoami --verbose --credentials-file /tmp/.../custom_credentials.ini

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (/var/folders/8p/268x_b410gq6x6985r821bkr0000gq/T/tmp.xBCCrGw1sJ/custom_credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose --credentials-file /tmp/.../custom_credentials.ini

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (/var/folders/8p/268x_b410gq6x6985r821bkr0000gq/T/tmp.xBCCrGw1sJ/custom_credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 9: API key via CLOUDSMITH_CREDENTIALS_FILE env var

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (/var/folders/8p/268x_b410gq6x6985r821bkr0000gq/T/tmp.xBCCrGw1sJ/envvar_credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (/var/folders/8p/268x_b410gq6x6985r821bkr0000gq/T/tmp.xBCCrGw1sJ/envvar_credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 10: Profile via -P flag

credentials.ini has empty [default] and key in [profile:staging]

Published CLI:

$ cloudsmith whoami --verbose -P staging

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose -P staging

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 11: Profile via CLOUDSMITH_PROFILE env var

credentials.ini has empty [default] and key in [profile:staging]

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Priority / Override Scenarios

Scenario 12: Priority: --api-key flag vs env var

Both set. Source should show CLI flag.

Published CLI:

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 13: Priority: env var vs credentials.ini

Both set. Source should show env var.

Published CLI:

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 14: Priority: --api-key flag vs credentials.ini

Both set. Source should show CLI flag.

Published CLI:

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Scenario 15: Priority: flag + env var + config (all set)

All three set. CLI flag should win.

Published CLI:

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

Local CLI (this branch):

$ cloudsmith whoami --verbose --api-key <API_KEY>

User: cli-testing (slug: <REDACTED>)

Authentication Method: API Key
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Token Slug: <REDACTED>
  Created: 2026-03-13T17:19:27.780684Z

SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)

SSO / Keyring Scenarios

Removed SSO tokens from system keyring.
Note: credentials.ini was not modified (--keyring-only).

Scenario 16: SSO token via keyring (whoami)

After cloudsmith auth -o iduffy-demo — SSO token stored in system keyring.

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: <REDACTED> (slug: <REDACTED>, email: <REDACTED>)

Authentication Method: SSO Token (primary)
  Source: System Keyring
  Last Refreshed: 2026-03-13T17:54:44.741045 (refreshes every 30 min)

Scenario 17: Priority: SSO token vs env var

SSO token in keyring + CLOUDSMITH_API_KEY set. SSO token should take priority.

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: <REDACTED> (slug: <REDACTED>, email: <REDACTED>)

Authentication Method: SSO Token (primary)
  Source: System Keyring
  Last Refreshed: 2026-03-13T17:54:44.741045 (refreshes every 30 min)

API Key: Also configured
  Source: CLOUDSMITH_API_KEY env var (ends with ...lyrw)
  Note: SSO token is being used instead

Scenario 18: Priority: SSO token vs credentials.ini

SSO token in keyring + API key in credentials.ini. SSO token should take priority.

Local CLI (this branch):

$ cloudsmith whoami --verbose

User: <REDACTED> (slug: <REDACTED>, email: <REDACTED>)

Authentication Method: SSO Token (primary)
  Source: System Keyring
  Last Refreshed: 2026-03-13T17:54:44.741045 (refreshes every 30 min)

API Key: Also configured
  Source: credentials.ini (~/.cloudsmith/credentials.ini)
  Note: SSO token is being used instead

Scenario 19: CLOUDSMITH_NO_KEYRING=1 bypasses SSO

SSO token in keyring but CLOUDSMITH_NO_KEYRING=1. Should fall through to anonymous.

Local CLI (this branch):

$ cloudsmith whoami --verbose
You are authenticated as:
Nobody (i.e. anonymous user)

Scenario 20: Logout clears SSO token

After cloudsmith logout --keyring-only, SSO token should be cleared.

Logout output:

$ cloudsmith logout --keyring-only
Removed SSO tokens from system keyring.
Note: credentials.ini was not modified (--keyring-only).

Local CLI (this branch) — whoami after logout:

$ cloudsmith whoami --verbose
You are authenticated as:
Nobody (i.e. anonymous user)

@cloudsmith-iduffy cloudsmith-iduffy requested a review from a team as a code owner March 13, 2026 18:02
@cloudsmith-iduffy cloudsmith-iduffy force-pushed the iduffy/credential-provider-chain branch 8 times, most recently from 6e1792c to 8862812 Compare March 14, 2026 14:43
@cloudsmith-iduffy cloudsmith-iduffy marked this pull request as draft March 14, 2026 14:48
@cloudsmith-iduffy cloudsmith-iduffy force-pushed the iduffy/credential-provider-chain branch from 8862812 to 368db92 Compare March 15, 2026 01:05
@cloudsmith-iduffy cloudsmith-iduffy force-pushed the iduffy/credential-provider-chain branch from 368db92 to a60887d Compare March 15, 2026 10:34
cloudsmith-iduffy and others added 2 commits March 15, 2026 21:43
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cloudsmith-iduffy cloudsmith-iduffy marked this pull request as ready for review March 15, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant