Skip to content

feat: Add credential helpers for Docker and pip with custom domain support#269

Draft
cloudsmith-iduffy wants to merge 1 commit intoiduffy/automatic-oidcfrom
iduffy/credential-helper
Draft

feat: Add credential helpers for Docker and pip with custom domain support#269
cloudsmith-iduffy wants to merge 1 commit intoiduffy/automatic-oidcfrom
iduffy/credential-helper

Conversation

@cloudsmith-iduffy
Copy link
Contributor

@cloudsmith-iduffy cloudsmith-iduffy commented Feb 28, 2026

This PR adds credential helper infrastructure for Docker and pip package managers,
enabling automatic authentication to Cloudsmith registries without manual login
commands or embedding credentials in URLs.

This builds upon #267 (OIDC authentication) and extends the credential provider
chain to Docker and pip workflows.

  • Command: cloudsmith credential-helper docker

  • Binary: docker-credential-cloudsmith (for Docker CLI integration)

  • Supports standard domains: docker.cloudsmith.io, *.docker.cloudsmith.io

  • Supports custom vanity domains via API auto-discovery

  • Auto-discovered by pip/twine via keyring.backends entry point

  • Supports standard domains: python.cloudsmith.io, dl.cloudsmith.io

  • Set CLOUDSMITH_ORG=my-org to enable custom domain discovery

  • Fetches domains from GET /orgs/{org}/custom-domains/ API endpoint

  • Caches results in ~/.cloudsmith/cache/custom_domains/ for 1 hour

  • Automatic, no manual configuration needed

  • Both helpers use the same credential provider chain

  • Order: Environment Variable → Config File → Keyring → OIDC

  • Consistent authentication behavior across all package managers

  • Extensible design for future helpers (npm, cargo, maven, etc.)

  • New feature

  • Documentation update

  • ✅ Fully backward compatible

  • ✅ No breaking changes

  • ✅ Existing authentication methods unchanged

  • ✅ Optional features - enable by configuration

Environment setup:

$ env | grep CLOUDSMITH_
CLOUDSMITH_ORG=iduffy-demo
CLOUDSMITH_SERVICE_SLUG=default-v9ty

$ stat ~/.cloudsmith/config.ini
stat: cannot stat '/Users/iduffy/.cloudsmith/config.ini': No such file or directory

$ cloudsmith whoami --verbose
Retrieving your authentication status from the API ... OK

User: default (slug: default-v9ty)

Authentication Method: OIDC Auto-Discovery
  Source: OIDC auto-discovery: AWS (org: iduffy-demo)
  Token Slug: 6FmYSZVQrEho
  Created: 2025-06-07T19:43:47.840466Z

SSO Status: Not configured
  Keyring: Enabled (no tokens stored)

Before configuration:

$ cat ~/.docker/config.json
cat: /Users/iduffy/.docker/config.json: No such file or directory

$ docker pull docker.cloudsmith.io/iduffy-demo/default/library/ubuntu:latest
Error response from daemon: Head "https://docker.cloudsmith.io/v2/iduffy-demo/default/library/ubuntu/manifests/latest": unauthorized

After configuration:

$ cat ~/.docker/config.json
{
  "credHelpers": {
    "docker.cloudsmith.io": "cloudsmith"
  }
}

$ docker pull docker.cloudsmith.io/iduffy-demo/default/library/ubuntu:latest
latest: Pulling from iduffy-demo/default/library/ubuntu
cc43ec4c1381: Pull complete
Digest: sha256:9cbed754112939e914291337b5e554b07ad7c392491dba6daf25eef1332a22e8
Status: Downloaded newer image for docker.cloudsmith.io/iduffy-demo/default/library/ubuntu:latest
docker.cloudsmith.io/iduffy-demo/default/library/ubuntu:latest

Environment setup:

$ pip config list
:env:.default-timeout='100'
:env:.disable-pip-version-check='1'

$ python -c 'import keyring; print(keyring.backend.get_all_keyring())'
[<keyring.backends.fail.Keyring object at 0x1033a4460>, <cloudsmith_cli.credential_helpers.pip.CloudsmithKeyringBackend object at 0x1033a4c80>, <keyring.backends.chainer.ChainerBackend object at 0x1033a5360>, <keyring.backends.macOS.Keyring object at 0x1033a5720>]

Test installation (no credentials in URL):

$ pip install --no-cache-dir --index-url=https://dl.cloudsmith.io/basic/iduffy-demo/default/python/simple/ cloudsmith-python-native
Looking in indexes: https://dl.cloudsmith.io/basic/iduffy-demo/default/python/simple/
Collecting cloudsmith-python-native
  Downloading https://dl.cloudsmith.io/basic/iduffy-demo/default/python/cloudsmith_python_native-1.0.1050047-py2.py3-none-any.whl (2.2 kB)
Requirement already satisfied: toml in /Users/iduffy/projects/cloudsmith-cli/.venv/lib/python3.10/site-packages (from cloudsmith-python-native) (0.10.2)
Installing collected packages: cloudsmith-python-native
Successfully installed cloudsmith-python-native-1.0.1050047

Custom domains are discovered automatically when CLOUDSMITH_ORG is set:

  1. First request fetches domains from API
  2. Results cached for 1 hour in ~/.cloudsmith/cache/custom_domains/
  3. Subsequent requests use cache (no repeated API calls)

@cloudsmith-iduffy cloudsmith-iduffy requested a review from a team as a code owner February 28, 2026 14:57
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cloudsmith-iduffy added a commit that referenced this pull request Feb 28, 2026
…nd NuGet

Extend the credential helper system (from PR #269) with 5 additional
package manager integrations, each following the tool's native credential
protocol:

- Terraform: terraform-credentials-cloudsmith binary
- Cargo: cargo-credential-cloudsmith binary (JSON-line protocol)
- npm/pnpm: cloudsmith-token-helper binary (tokenHelper)
- Conda: cloudsmith-auth plugin (conda auth handler)
- NuGet: CredentialProvider.Cloudsmith binary

All helpers reuse the shared CredentialProviderChain and custom domain
discovery. Includes CLI commands for debugging and example documentation
for each package manager.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@cloudsmith-iduffy cloudsmith-iduffy force-pushed the iduffy/credential-helper branch 5 times, most recently from 6989862 to d6d8581 Compare February 28, 2026 18:59
@cloudsmith-iduffy cloudsmith-iduffy marked this pull request as draft February 28, 2026 19:10
@cloudsmith-iduffy cloudsmith-iduffy force-pushed the iduffy/credential-helper branch 6 times, most recently from eeb649d to 5c40265 Compare February 28, 2026 20:27
Add credential helpers that automatically authenticate package managers
with Cloudsmith registries using the credential provider chain
(Environment Variable → Config File → Keyring → OIDC).

Supported formats:

  Docker          docker-credential-cloudsmith
  Terraform       terraform-credentials-cloudsmith
  Cargo           cargo-credential-cloudsmith
  pnpm            cloudsmith-token-helper
  NuGet           CredentialProvider.Cloudsmith
  pip/twine       keyring backend (auto-discovered)
  Conda           conda plugin (auto-discovered)

Configure `~/.docker/config.json`:

  {
    "credHelpers": {
      "docker.cloudsmith.io": "cloudsmith"
    }
  }

Then:

  docker pull docker.cloudsmith.io/myorg/myrepo/myimage:latest

Install the helper and configure `~/.terraformrc`:

  mkdir -p ~/.terraform.d/plugins
  ln -sf "$(which terraform-credentials-cloudsmith)" ~/.terraform.d/plugins/

  credentials_helper "cloudsmith" {
    args = []
  }

Requires CLOUDSMITH_ORG and CLOUDSMITH_REPO environment variables.
Token format is org/repo/token per Cloudsmith's Terraform registry API.

Configure `~/.cargo/config.toml`:

  [registries.cloudsmith]
  index = "sparse+https://cargo.cloudsmith.io/myorg/myrepo/"
  credential-provider = ["cargo-credential-cloudsmith"]

Then:

  cargo add my-crate --registry cloudsmith

Configure `~/.npmrc` (requires absolute path to helper):

  registry=https://npm.cloudsmith.io/myorg/myrepo/
  //npm.cloudsmith.io/myorg/myrepo/:tokenHelper=/usr/local/bin/cloudsmith-token-helper

Returns "Bearer <token>" as pnpm does not auto-add the prefix.

Set NUGET_CREDENTIALPROVIDERS_PATH to the directory containing
CredentialProvider.Cloudsmith and add a package source:

  <packageSources>
    <add key="cloudsmith"
         value="https://nuget.cloudsmith.io/myorg/myrepo/v3/index.json" />
  </packageSources>

Then:

  dotnet restore

Auto-discovered via the keyring.backends entry point. No configuration
needed beyond installing cloudsmith-cli:

  pip install --index-url=https://dl.cloudsmith.io/basic/myorg/myrepo/python/simple/ mypkg

Auto-discovered via the conda plugin entry point. Install cloudsmith-cli
into conda's base Python environment. Configure `~/.condarc`:

  channel_settings:
    - channel: https://conda.cloudsmith.io/myorg/myrepo/
      auth: cloudsmith
  channels:
    - https://conda.cloudsmith.io/myorg/myrepo/
    - defaults

Then:

  conda install my-package

- cloudsmith_cli/credential_helpers/common.py: shared resolve_credentials(),
  extract_hostname(), is_cloudsmith_domain() used by all helpers
- CredentialProviderChain defaults to the standard 4-provider chain
- Networking config (proxy, TLS, headers) read from CLOUDSMITH_API_PROXY,
  CLOUDSMITH_WITHOUT_API_SSL_VERIFY, CLOUDSMITH_API_USER_AGENT,
  CLOUDSMITH_API_HEADERS env vars and config.ini
- Custom domain discovery via GET /orgs/{org}/custom-domains/ with
  1-hour filesystem cache in ~/.cloudsmith/cache/custom_domains/

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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