Skip to content

Commit df15ca1

Browse files
Merge branch 'master' into iduffy/circleci
2 parents af314d7 + 19b865b commit df15ca1

33 files changed

Lines changed: 3780 additions & 150 deletions

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 1.17.0
2+
current_version = 1.18.0
33
commit = True
44
tag = True
55
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<revision>\d+)

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1111
### Added
1212

1313
- Added CircleCI to OIDC credential auto-discovery. When running in CircleCI, the CLI reads the OIDC token from the `CIRCLE_OIDC_TOKEN_V2` (preferred) or `CIRCLE_OIDC_TOKEN` environment variable and exchanges it for a Cloudsmith access token. Works out of the box with no extra dependencies.
14+
- Added Azure DevOps to OIDC credential auto-discovery. When running in an Azure DevOps pipeline, the CLI fetches an OIDC token from the `SYSTEM_OIDCREQUESTURI` endpoint using the pipeline's `SYSTEM_ACCESSTOKEN` and exchanges it for a Cloudsmith access token. Works out of the box with no extra dependencies.
15+
- Added GitHub Actions to OIDC credential auto-discovery. When running in GitHub Actions (with `id-token: write` permission), the CLI fetches an OIDC token from the Actions runtime endpoint and exchanges it for a Cloudsmith access token. Works out of the box with no extra dependencies.
16+
17+
## [1.18.0] - 2026-06-09
18+
19+
### Added
20+
21+
- OIDC credential auto-discovery for CI/CD. When `CLOUDSMITH_ORG` and `CLOUDSMITH_SERVICE_SLUG` are set, the CLI auto-detects a supported cloud environment, obtains a vendor OIDC token, and exchanges it for a short-lived Cloudsmith API token — no static API key required. Initial support is for AWS (install the extra with `pip install cloudsmith-cli[aws]`). Tunable via `--oidc-org`, `--oidc-service-slug`, `--oidc-audience`, and `--oidc-discovery-disabled` (and matching `CLOUDSMITH_OIDC_*` env vars). The detector skips itself silently when its dependencies are not installed.
22+
- `cloudsmith mcp configure` now supports Claude Code as a client (`--client claude-code`), registering the Cloudsmith MCP server in `~/.claude.json`.
23+
24+
### Changed
25+
26+
- Authentication now resolves credentials through an explicit, predictable provider chain: CLI flag → environment variable → credentials file → keyring → OIDC. This separates the previously combined credential sources and makes precedence deterministic.
27+
28+
### Fixed
29+
30+
- `metadata list` filters (`--source-kind`, `--classification`) now send the enum name the v2 API expects instead of an integer, fixing an HTTP 400 on every filtered list. Valid source kinds: `unknown, system, upstream, custom, third_party`; classifications: `unknown, intrinsic, security, provenance, sbom, generic`.
31+
1432

1533
## [1.17.0] - 2026-05-18
1634

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ pip install cloudsmith-cli[all]
169169

170170
In CircleCI, OIDC credential discovery works out of the box with no extra dependencies — the CLI reads the token from the `CIRCLE_OIDC_TOKEN_V2` (preferred) or `CIRCLE_OIDC_TOKEN` environment variable that CircleCI injects into every job. The Cloudsmith OIDC provider must expect the audience CircleCI mints, which is your CircleCI organization UUID. See the [Cloudsmith CircleCI integration guide](https://docs.cloudsmith.com/integrations/integrating-with-circleci).
171171

172+
#### Azure DevOps OIDC Support
173+
174+
In Azure DevOps Pipelines, OIDC credential discovery works out of the box with no extra dependencies — the CLI fetches an OIDC token from the `SYSTEM_OIDCREQUESTURI` endpoint using the pipeline's `SYSTEM_ACCESSTOKEN`. Make sure `SYSTEM_ACCESSTOKEN` is mapped into the step's environment. The Cloudsmith OIDC provider must expect the audience `api://AzureADTokenExchange`, which Azure DevOps always mints (any requested audience is ignored). See the [Cloudsmith Azure DevOps integration guide](https://docs.cloudsmith.com/integrations/integrating-with-azure-devops).
175+
176+
#### GitHub Actions OIDC Support
177+
178+
In GitHub Actions, OIDC credential discovery works out of the box with no extra dependencies — the CLI fetches an OIDC token from the Actions runtime when the workflow requests `id-token: write` permission. See the [Cloudsmith GitHub Actions OIDC guide](https://docs.cloudsmith.com/authentication/setup-cloudsmith-to-authenticate-with-oidc-in-github-actions).
179+
172180
## Configuration
173181

174182
There are two configuration files used by the CLI:

cloudsmith_cli/cli/commands/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
auth,
55
check,
66
copy,
7+
credential_helper,
78
delete,
89
dependencies,
910
docs,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2026 Cloudsmith Ltd
2+
"""
3+
Credential helper commands for Cloudsmith.
4+
5+
This module provides credential helper commands for package managers
6+
that follow their respective credential helper protocols.
7+
"""
8+
9+
import click
10+
11+
from ..main import main
12+
from .docker import docker as docker_cmd
13+
from .manage import install_cmd, list_cmd, uninstall_cmd
14+
15+
16+
@click.group()
17+
def credential_helper():
18+
"""
19+
Credential helpers for package managers.
20+
21+
These commands provide credentials for package managers like Docker.
22+
Use ``install`` to set up the on-PATH launcher and configure the package
23+
manager automatically, or run the runtime command directly for debugging.
24+
25+
Examples:
26+
# Install Docker credential helper
27+
$ cloudsmith credential-helper install docker
28+
29+
# Test Docker credential helper directly
30+
$ echo "docker.cloudsmith.io" | cloudsmith credential-helper docker
31+
"""
32+
33+
34+
credential_helper.add_command(docker_cmd, name="docker")
35+
credential_helper.add_command(install_cmd, name="install")
36+
credential_helper.add_command(uninstall_cmd, name="uninstall")
37+
credential_helper.add_command(list_cmd, name="list")
38+
39+
main.add_command(credential_helper, name="credential-helper")
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright 2026 Cloudsmith Ltd
2+
"""
3+
Docker credential helper command.
4+
5+
Implements the Docker credential helper protocol for Cloudsmith registries.
6+
7+
See: https://github.com/docker/docker-credential-helpers
8+
"""
9+
10+
import sys
11+
12+
import click
13+
14+
from ....credential_helpers.docker import execute
15+
from ...decorators import common_api_auth_options, resolve_credentials
16+
17+
18+
@click.command()
19+
@click.argument("operation", required=False, default="get")
20+
@common_api_auth_options
21+
@resolve_credentials
22+
def docker(opts, operation):
23+
"""
24+
Docker credential helper for Cloudsmith registries.
25+
26+
Reads a Docker registry server URL from stdin and returns credentials in
27+
JSON format. Implements the full Docker credential helper protocol
28+
(get/store/erase/list).
29+
30+
Provides credentials for all Cloudsmith Docker registries: ``*.cloudsmith.io``,
31+
``*.cloudsmith.com``, and any custom domains configured for the organisation
32+
(requires CLOUDSMITH_ORG and a valid API key/token).
33+
34+
Input (stdin):
35+
Server URL as plain text (e.g. "docker.cloudsmith.io")
36+
37+
Output (stdout):
38+
JSON: {"Username": "token", "Secret": "<cloudsmith-token>"}
39+
40+
Exit codes:
41+
0: Success
42+
1: Error (no credentials available, not a Cloudsmith registry, etc.)
43+
44+
Examples:
45+
# Manual testing
46+
$ echo "docker.cloudsmith.io" | cloudsmith credential-helper docker
47+
48+
# Called by Docker via launcher
49+
$ echo "docker.cloudsmith.io" | docker-credential-cloudsmith get
50+
51+
Environment variables:
52+
CLOUDSMITH_API_KEY: API key for authentication (optional)
53+
CLOUDSMITH_ORG: Organisation slug (required for custom domain support)
54+
"""
55+
exit_code, stdout, stderr = execute(
56+
operation,
57+
sys.stdin,
58+
credential=opts.credential,
59+
api_host=opts.api_host,
60+
)
61+
62+
if stdout is not None:
63+
click.echo(stdout)
64+
if stderr is not None:
65+
click.echo(stderr, err=True)
66+
sys.exit(exit_code)

0 commit comments

Comments
 (0)