cloudsmith-cli 1.20.1__tar.gz → 1.21.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cloudsmith_cli-1.20.1/cloudsmith_cli.egg-info → cloudsmith_cli-1.21.0}/PKG-INFO +1 -1
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/credential_helper/__init__.py +2 -0
- cloudsmith_cli-1.21.0/cloudsmith_cli/cli/commands/credential_helper/generic.py +62 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/decorators.py +0 -3
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/exceptions.py +6 -6
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/webserver.py +4 -24
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/files.py +2 -1
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/config.py +2 -2
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/models.py +12 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/download.py +7 -15
- cloudsmith_cli-1.21.0/cloudsmith_cli/credential_helpers/generic.py +63 -0
- cloudsmith_cli-1.21.0/cloudsmith_cli/data/VERSION +1 -0
- cloudsmith_cli-1.21.0/cloudsmith_cli/templates/__init__.py +27 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0/cloudsmith_cli.egg-info}/PKG-INFO +1 -1
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/SOURCES.txt +2 -0
- cloudsmith_cli-1.20.1/cloudsmith_cli/data/VERSION +0 -1
- cloudsmith_cli-1.20.1/cloudsmith_cli/templates/__init__.py +0 -3
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/LICENSE +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/MANIFEST.in +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/README.md +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/__main__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/command.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/auth.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/check.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/copy.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/credential_helper/docker.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/credential_helper/manage.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/delete.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/dependencies.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/docs.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/download.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/entitlements.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/help_.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/list_.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/login.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/logout.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/main.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/mcp.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metadata.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/entitlements.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/move.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/deny.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/license.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/vulnerability.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/push.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quarantine.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/repos.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/resync.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/status.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/tags.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/tokens.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/upstream.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/whoami.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/config.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/metadata_common.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/saml.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/table.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/types.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/utils.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/validators.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/distros.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/entitlements.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/exceptions.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/init.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/metadata.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/metrics.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/orgs.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/packages.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/quota.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/rates.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/repos.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/status.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/upstreams.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/user.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/version.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/api/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/cache_utils.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/chain.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/cache.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/aws.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/base.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/generic.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/exchange.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/provider.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/cli_flag.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/credentials_file.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/env_var.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/keyring_provider.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/oidc_provider.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/keyring.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/mcp/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/mcp/data.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/mcp/server.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/pagination.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/ratelimits.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/rest.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/utils.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/version.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/backends.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/common.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/custom_domains.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/docker/__init__.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/docker/installer.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/docker/runtime.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/launchers.py +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/data/config.ini +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/data/credentials.ini +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/templates/auth_error.html +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/templates/auth_success.html +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/requires.txt +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/top_level.txt +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/pyproject.toml +0 -0
- {cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/setup.cfg +0 -0
|
@@ -10,6 +10,7 @@ import click
|
|
|
10
10
|
|
|
11
11
|
from ..main import main
|
|
12
12
|
from .docker import docker as docker_cmd
|
|
13
|
+
from .generic import generic as generic_cmd
|
|
13
14
|
from .manage import install_cmd, list_cmd, uninstall_cmd
|
|
14
15
|
|
|
15
16
|
|
|
@@ -32,6 +33,7 @@ def credential_helper():
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
credential_helper.add_command(docker_cmd, name="docker")
|
|
36
|
+
credential_helper.add_command(generic_cmd, name="generic")
|
|
35
37
|
credential_helper.add_command(install_cmd, name="install")
|
|
36
38
|
credential_helper.add_command(uninstall_cmd, name="uninstall")
|
|
37
39
|
credential_helper.add_command(list_cmd, name="list")
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Copyright 2026 Cloudsmith Ltd
|
|
2
|
+
"""
|
|
3
|
+
Generic credential helper command.
|
|
4
|
+
|
|
5
|
+
Emits a versioned JSON credential document.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
|
|
12
|
+
from ....credential_helpers.generic import execute
|
|
13
|
+
from ...decorators import (
|
|
14
|
+
common_api_auth_options,
|
|
15
|
+
common_cli_config_options,
|
|
16
|
+
resolve_credentials,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.command()
|
|
21
|
+
@common_cli_config_options
|
|
22
|
+
@common_api_auth_options
|
|
23
|
+
@resolve_credentials
|
|
24
|
+
def generic(opts):
|
|
25
|
+
"""
|
|
26
|
+
Emit a Cloudsmith credential as JSON.
|
|
27
|
+
|
|
28
|
+
Resolves a credential through the full provider chain and writes a
|
|
29
|
+
versioned JSON document to stdout. Takes no arguments: a Cloudsmith token
|
|
30
|
+
is organisation-wide, so the host it will be used against does not change
|
|
31
|
+
which credential resolves.
|
|
32
|
+
|
|
33
|
+
\b
|
|
34
|
+
Output (stdout):
|
|
35
|
+
JSON: {"version": 1, "username": "token", "password": "<token>"}
|
|
36
|
+
|
|
37
|
+
\b
|
|
38
|
+
Exit codes:
|
|
39
|
+
0: Success
|
|
40
|
+
1: No credential could be resolved
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
|
|
44
|
+
\b
|
|
45
|
+
# Resolve a credential
|
|
46
|
+
$ cloudsmith credential-helper generic
|
|
47
|
+
|
|
48
|
+
\b
|
|
49
|
+
# Extract just the token
|
|
50
|
+
$ cloudsmith credential-helper generic | jq -r .password
|
|
51
|
+
|
|
52
|
+
\b
|
|
53
|
+
Environment variables:
|
|
54
|
+
CLOUDSMITH_API_KEY: API key for authentication (optional)
|
|
55
|
+
"""
|
|
56
|
+
exit_code, stdout, stderr = execute(credential=opts.credential)
|
|
57
|
+
|
|
58
|
+
if stdout is not None:
|
|
59
|
+
click.echo(stdout)
|
|
60
|
+
if stderr is not None:
|
|
61
|
+
click.echo(stderr, err=True)
|
|
62
|
+
sys.exit(exit_code)
|
|
@@ -246,9 +246,6 @@ def common_api_auth_options(f):
|
|
|
246
246
|
opts.api_key_from_flag = None
|
|
247
247
|
opts.api_key_from_env = None
|
|
248
248
|
|
|
249
|
-
# Keep opts.api_key populated for any code that still reads it directly.
|
|
250
|
-
if api_key:
|
|
251
|
-
opts.api_key = api_key
|
|
252
249
|
kwargs["opts"] = opts
|
|
253
250
|
return ctx.invoke(f, *args, **kwargs)
|
|
254
251
|
|
|
@@ -7,7 +7,6 @@ import sys
|
|
|
7
7
|
import click
|
|
8
8
|
|
|
9
9
|
from ..core.api.exceptions import ApiException
|
|
10
|
-
from ..core.keyring import get_access_token
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
@contextlib.contextmanager
|
|
@@ -171,16 +170,17 @@ def get_error_hint(ctx, opts, exc):
|
|
|
171
170
|
def get_401_error_hint(ctx, opts, exc):
|
|
172
171
|
"""Get the hint for a 401/Unauthorised error."""
|
|
173
172
|
# pylint: disable=unused-argument
|
|
174
|
-
|
|
173
|
+
credential = getattr(opts, "credential", None)
|
|
174
|
+
|
|
175
|
+
if credential and credential.auth_type == "bearer":
|
|
176
|
+
return "Since you have an SSO access token set, this probably means that it has expired. Try getting a new token with 'cloudsmith auth', then try again."
|
|
177
|
+
|
|
178
|
+
if credential:
|
|
175
179
|
return (
|
|
176
180
|
"Since you have an API key set, this probably means "
|
|
177
181
|
"you don't have the permission to perform this action."
|
|
178
182
|
)
|
|
179
183
|
|
|
180
|
-
access_token = get_access_token(opts.api_host)
|
|
181
|
-
if access_token:
|
|
182
|
-
return "Since you have an SSO access token set, this probably means that it has expired. Try getting a new token with 'cloudsmith auth', then try again."
|
|
183
|
-
|
|
184
184
|
if ctx.info_name == "token":
|
|
185
185
|
# This is already the token command
|
|
186
186
|
return (
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import html
|
|
2
|
-
import os
|
|
3
2
|
import socket
|
|
4
3
|
from functools import cached_property
|
|
5
4
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
@@ -7,6 +6,7 @@ from urllib.parse import parse_qsl, unquote, urlparse
|
|
|
7
6
|
|
|
8
7
|
import click
|
|
9
8
|
|
|
9
|
+
from .. import templates
|
|
10
10
|
from ..core.api.exceptions import ApiException
|
|
11
11
|
from ..core.api.init import initialise_api
|
|
12
12
|
from ..core.credentials.models import CredentialResult
|
|
@@ -16,32 +16,12 @@ from .saml import exchange_2fa_token
|
|
|
16
16
|
|
|
17
17
|
def get_template_path(template_name):
|
|
18
18
|
"""Get the absolute path to a template file."""
|
|
19
|
-
|
|
20
|
-
return os.path.join(base_dir, "templates", template_name)
|
|
19
|
+
return templates.template_path(template_name)
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
def render_template(template_name, **context):
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
template_name: Name of the template file
|
|
29
|
-
context: Dictionary of variables to replace in the template
|
|
30
|
-
|
|
31
|
-
Returns:
|
|
32
|
-
Rendered HTML content
|
|
33
|
-
"""
|
|
34
|
-
template_path = get_template_path(template_name)
|
|
35
|
-
|
|
36
|
-
with open(template_path, encoding="utf-8") as file:
|
|
37
|
-
content = file.read()
|
|
38
|
-
|
|
39
|
-
# Replace placeholders with context values
|
|
40
|
-
for key, value in context.items():
|
|
41
|
-
placeholder = f"<!-- {key.upper()}_PLACEHOLDER -->"
|
|
42
|
-
content = content.replace(placeholder, value if value else "")
|
|
43
|
-
|
|
44
|
-
return content
|
|
23
|
+
"""Render a template with the given context (see :func:`cloudsmith_cli.templates.render`)."""
|
|
24
|
+
return templates.render(template_name, **context)
|
|
45
25
|
|
|
46
26
|
|
|
47
27
|
class AuthenticationWebServer(HTTPServer):
|
|
@@ -97,10 +97,11 @@ def upload_file(upload_url, upload_fields, filepath, callback=None):
|
|
|
97
97
|
def multi_part_upload_file(
|
|
98
98
|
opts, upload_url, owner, repo, filepath, callback, upload_id
|
|
99
99
|
):
|
|
100
|
+
headers = opts.credential.auth_headers() if opts.credential else {}
|
|
101
|
+
|
|
100
102
|
with open(filepath, "rb") as f:
|
|
101
103
|
chunk_number = 1
|
|
102
104
|
session = create_requests_session()
|
|
103
|
-
headers = {"X-Api-Key": opts.api_key}
|
|
104
105
|
while chunk := f.read(CHUNK_SIZE):
|
|
105
106
|
resp = session.put(
|
|
106
107
|
upload_url,
|
|
@@ -117,9 +117,9 @@ def new_config_messaging(has_errors, opts, create, api_key):
|
|
|
117
117
|
click.secho("Oops, please fix the errors and try again!", fg="red")
|
|
118
118
|
return
|
|
119
119
|
|
|
120
|
-
if opts.
|
|
120
|
+
if opts.api_key_from_file != api_key:
|
|
121
121
|
click.echo()
|
|
122
|
-
if opts.
|
|
122
|
+
if opts.api_key_from_file:
|
|
123
123
|
click.secho(
|
|
124
124
|
"Note: The above API key doesn't match what you have in "
|
|
125
125
|
"your default credentials config file.",
|
|
@@ -42,3 +42,15 @@ class CredentialResult:
|
|
|
42
42
|
source_name: str
|
|
43
43
|
source_detail: str | None = None
|
|
44
44
|
auth_type: Literal["api_key", "bearer"] = "api_key"
|
|
45
|
+
|
|
46
|
+
def auth_headers(self) -> dict[str, str]:
|
|
47
|
+
"""Return the headers that authenticate a raw request with this credential.
|
|
48
|
+
|
|
49
|
+
The two headers are not interchangeable: a raw JWT in ``X-Api-Key`` is
|
|
50
|
+
rejected outright, aborting the auth chain before the SSO
|
|
51
|
+
authenticators run.
|
|
52
|
+
"""
|
|
53
|
+
if self.auth_type == "bearer":
|
|
54
|
+
return {"Authorization": f"Bearer {self.api_key}"}
|
|
55
|
+
|
|
56
|
+
return {"X-Api-Key": self.api_key}
|
|
@@ -5,12 +5,11 @@ import hashlib
|
|
|
5
5
|
import os
|
|
6
6
|
|
|
7
7
|
import click
|
|
8
|
-
import cloudsmith_api
|
|
9
8
|
import requests
|
|
10
9
|
from rich.console import Console
|
|
11
10
|
from rich.table import Table
|
|
12
11
|
|
|
13
|
-
from . import
|
|
12
|
+
from . import ratelimits, utils
|
|
14
13
|
from .api.exceptions import catch_raise_api_exception
|
|
15
14
|
from .api.packages import get_packages_api, list_packages
|
|
16
15
|
from .rest import create_requests_session
|
|
@@ -36,21 +35,14 @@ def resolve_auth(
|
|
|
36
35
|
headers = {}
|
|
37
36
|
auth_source = "none"
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
# Priority: explicit --api-key > SSO token > configured API key
|
|
38
|
+
credential = getattr(opts, "credential", None)
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
access_token = keyring.get_access_token(config.host)
|
|
45
|
-
api_key = api_key_opt or getattr(opts, "api_key", None)
|
|
46
|
-
|
|
47
|
-
if api_key:
|
|
48
|
-
# Prioritize API key (from --api-key option or CLOUDSMITH_API_KEY env var) over SSO
|
|
49
|
-
headers["X-Api-Key"] = api_key
|
|
40
|
+
if api_key_opt:
|
|
41
|
+
headers["X-Api-Key"] = api_key_opt
|
|
50
42
|
auth_source = "api-key"
|
|
51
|
-
elif
|
|
52
|
-
headers
|
|
53
|
-
auth_source = "sso"
|
|
43
|
+
elif credential:
|
|
44
|
+
headers = credential.auth_headers()
|
|
45
|
+
auth_source = "sso" if credential.auth_type == "bearer" else "api-key"
|
|
54
46
|
|
|
55
47
|
return session, headers, auth_source
|
|
56
48
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Copyright 2026 Cloudsmith Ltd
|
|
2
|
+
"""
|
|
3
|
+
Generic credential helper runtime.
|
|
4
|
+
|
|
5
|
+
Emits a versioned JSON credential document.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
PROTOCOL_VERSION = 1
|
|
14
|
+
|
|
15
|
+
_REFUSAL_MESSAGE = (
|
|
16
|
+
"Error: Unable to retrieve credentials. "
|
|
17
|
+
"Provide credentials via the CLOUDSMITH_API_KEY environment variable, "
|
|
18
|
+
"credentials.ini, the system keyring, or an OIDC service. "
|
|
19
|
+
"Verify current authentication with `cloudsmith whoami --verbose`."
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_response(credential):
|
|
24
|
+
"""
|
|
25
|
+
Build the versioned credential document.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
credential: Pre-resolved CredentialResult from the provider chain
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
dict: The credential document, or None when no credential is available
|
|
32
|
+
"""
|
|
33
|
+
if not credential or not credential.api_key:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
"version": PROTOCOL_VERSION,
|
|
38
|
+
"username": "token",
|
|
39
|
+
"password": credential.api_key,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def execute(credential=None) -> tuple[int, str | None, str | None]:
|
|
44
|
+
"""
|
|
45
|
+
Resolve a credential into a versioned JSON document.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
credential: Pre-resolved CredentialResult from the provider chain
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
A (exit_code, stdout_text, stderr_text) tuple. Either text value may
|
|
52
|
+
be None if there is nothing to write to that stream. The document is
|
|
53
|
+
serialised in one step, so a partial document can never be emitted.
|
|
54
|
+
"""
|
|
55
|
+
try:
|
|
56
|
+
response = build_response(credential)
|
|
57
|
+
if response is None:
|
|
58
|
+
return (1, None, _REFUSAL_MESSAGE)
|
|
59
|
+
|
|
60
|
+
return (0, json.dumps(response), None)
|
|
61
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
62
|
+
logger.debug("generic credential-helper failed: %s", exc, exc_info=True)
|
|
63
|
+
return (1, None, _REFUSAL_MESSAGE)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.21.0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Templates for the Cloudsmith CLI (HTML pages, config-file templates).
|
|
2
|
+
|
|
3
|
+
Templates use ``<!-- KEY_PLACEHOLDER -->`` markers so the files stay valid
|
|
4
|
+
HTML/XML and get normal editor validation; :func:`render` substitutes them.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def template_path(name):
|
|
11
|
+
"""Return the absolute path to the template *name* in this package."""
|
|
12
|
+
return os.path.join(os.path.dirname(os.path.abspath(__file__)), name)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def render(name, **context):
|
|
16
|
+
"""Render template *name*, replacing ``<!-- KEY_PLACEHOLDER -->`` markers.
|
|
17
|
+
|
|
18
|
+
Each ``context`` key ``foo`` replaces ``<!-- FOO_PLACEHOLDER -->`` with its
|
|
19
|
+
value (empty string when falsy). Callers are responsible for escaping
|
|
20
|
+
values for the target format (e.g. XML-escaping).
|
|
21
|
+
"""
|
|
22
|
+
with open(template_path(name), encoding="utf-8") as handle:
|
|
23
|
+
content = handle.read()
|
|
24
|
+
for key, value in context.items():
|
|
25
|
+
placeholder = f"<!-- {key.upper()}_PLACEHOLDER -->"
|
|
26
|
+
content = content.replace(placeholder, value if value else "")
|
|
27
|
+
return content
|
|
@@ -51,6 +51,7 @@ cloudsmith_cli/cli/commands/vulnerabilities.py
|
|
|
51
51
|
cloudsmith_cli/cli/commands/whoami.py
|
|
52
52
|
cloudsmith_cli/cli/commands/credential_helper/__init__.py
|
|
53
53
|
cloudsmith_cli/cli/commands/credential_helper/docker.py
|
|
54
|
+
cloudsmith_cli/cli/commands/credential_helper/generic.py
|
|
54
55
|
cloudsmith_cli/cli/commands/credential_helper/manage.py
|
|
55
56
|
cloudsmith_cli/cli/commands/metrics/__init__.py
|
|
56
57
|
cloudsmith_cli/cli/commands/metrics/command.py
|
|
@@ -122,6 +123,7 @@ cloudsmith_cli/credential_helpers/__init__.py
|
|
|
122
123
|
cloudsmith_cli/credential_helpers/backends.py
|
|
123
124
|
cloudsmith_cli/credential_helpers/common.py
|
|
124
125
|
cloudsmith_cli/credential_helpers/custom_domains.py
|
|
126
|
+
cloudsmith_cli/credential_helpers/generic.py
|
|
125
127
|
cloudsmith_cli/credential_helpers/launchers.py
|
|
126
128
|
cloudsmith_cli/credential_helpers/docker/__init__.py
|
|
127
129
|
cloudsmith_cli/credential_helpers/docker/installer.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.20.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/command.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/entitlements.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/metrics/packages.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/license.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/policy/vulnerability.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/command.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/quota/history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/cli/commands/vulnerabilities.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/oidc/exchange.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/core/credentials/providers/env_var.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/backends.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/custom_domains.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/docker/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/docker/runtime.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli/credential_helpers/launchers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.20.1 → cloudsmith_cli-1.21.0}/cloudsmith_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|