cloudsmith-cli 1.28.0__tar.gz → 1.30.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.28.0/cloudsmith_cli.egg-info → cloudsmith_cli-1.30.0}/PKG-INFO +51 -34
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/README.md +41 -27
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/command.py +43 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/auth.py +11 -10
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/check.py +1 -3
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/manage.py +71 -8
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/terraform.py +12 -11
- cloudsmith_cli-1.30.0/cloudsmith_cli/cli/commands/domains.py +305 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/download.py +7 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/list_.py +25 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/login.py +76 -6
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/logout.py +7 -7
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/main.py +3 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metadata.py +9 -3
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/deny.py +2 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/license.py +3 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/vulnerability.py +3 -3
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/push.py +7 -4
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/repos.py +7 -8
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/tokens.py +20 -24
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/update.py +2 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/upstream.py +2 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/whoami.py +7 -7
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/config.py +69 -9
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/decorators.py +122 -32
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/exceptions.py +16 -6
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/saml.py +0 -24
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/utils.py +3 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/validators.py +7 -7
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/webserver.py +5 -4
- cloudsmith_cli-1.30.0/cloudsmith_cli/conftest.py +83 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/exceptions.py +5 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/files.py +20 -8
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/init.py +3 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/metadata.py +37 -93
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/orgs.py +5 -9
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/packages.py +2 -0
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/api/v2.py +96 -0
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/api/workspaces.py +22 -0
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/certificate_errors.py +80 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/config.py +32 -19
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/models.py +2 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +4 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/aws.py +20 -2
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/credentials/oidc/detectors/buildkite.py +54 -0
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/credentials/oidc/detectors/gcp.py +200 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/keyring_provider.py +1 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/download.py +1 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/keyring.py +8 -10
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/server.py +6 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/ratelimits.py +1 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/session.py +101 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/sso.py +12 -12
- cloudsmith_cli-1.30.0/cloudsmith_cli/core/telemetry.py +841 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/update_check.py +26 -7
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/utils.py +5 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/installer.py +26 -27
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/runtime.py +4 -11
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/common.py +27 -3
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/installer.py +22 -25
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/runtime.py +3 -10
- cloudsmith_cli-1.30.0/cloudsmith_cli/credential_helpers/domains.py +399 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/generic.py +4 -9
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/launchers.py +25 -33
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/installer.py +13 -22
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/rc.py +1 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/runtime.py +3 -10
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/installer.py +5 -20
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/runtime.py +28 -15
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/terraformrc.py +1 -1
- cloudsmith_cli-1.30.0/cloudsmith_cli/data/VERSION +1 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/data/config.ini +11 -5
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0/cloudsmith_cli.egg-info}/PKG-INFO +51 -34
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/SOURCES.txt +7 -2
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/requires.txt +9 -4
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/pyproject.toml +10 -8
- cloudsmith_cli-1.28.0/cloudsmith_cli/cli/commands/domains.py +0 -304
- cloudsmith_cli-1.28.0/cloudsmith_cli/conftest.py +0 -16
- cloudsmith_cli-1.28.0/cloudsmith_cli/credential_helpers/custom_domains.py +0 -378
- cloudsmith_cli-1.28.0/cloudsmith_cli/credential_helpers/default_domains.py +0 -305
- cloudsmith_cli-1.28.0/cloudsmith_cli/data/VERSION +0 -1
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/LICENSE +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/MANIFEST.in +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/__main__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/copy.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/cargo.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/docker.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/generic.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/credential_helper/pnpm.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/delete.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/dependencies.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/docs.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/entitlements.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/help_.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/mcp.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/entitlements.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/move.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quarantine.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/registry.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/resync.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/status.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/tags.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/commands/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/dsc_parser.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/metadata_common.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/table.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/cli/types.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/distros.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/entitlements.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/metrics.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/quota.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/rates.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/repos.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/status.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/upstreams.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/user.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/version.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/api/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/cache_utils.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/chain.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/cache.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/base.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/generic.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/oidc/exchange.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/provider.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/cli_flag.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/credentials_file.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/env_var.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/credentials/providers/oidc_provider.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/installation.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/macos_keychain.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/mcp/data.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/pagination.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/rest.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/self_update.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/core/version.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/backends.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/cargo/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/docker/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/pnpm/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/credential_helpers/terraform/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/data/credentials.ini +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/__init__.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_error.html +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_success.html +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/templates/auth_two_factor.html +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli/wrapper.py +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/cloudsmith_cli.egg-info/top_level.txt +0 -0
- {cloudsmith_cli-1.28.0 → cloudsmith_cli-1.30.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudsmith-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.30.0
|
|
4
4
|
Summary: Cloudsmith Command-Line Interface (CLI)
|
|
5
5
|
Author-email: Cloudsmith Ltd <support@cloudsmith.io>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -12,7 +12,6 @@ Classifier: Intended Audience :: Developers
|
|
|
12
12
|
Classifier: Intended Audience :: System Administrators
|
|
13
13
|
Classifier: Operating System :: POSIX :: Linux
|
|
14
14
|
Classifier: Programming Language :: Python
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
@@ -20,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
20
19
|
Classifier: Topic :: Internet
|
|
21
20
|
Classifier: Topic :: System :: Systems Administration
|
|
22
21
|
Classifier: Topic :: Utilities
|
|
23
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.11.0
|
|
24
23
|
Description-Content-Type: text/markdown
|
|
25
24
|
License-File: LICENSE
|
|
26
25
|
Requires-Dist: certifi>=2024.7.4
|
|
@@ -29,26 +28,30 @@ Requires-Dist: click-configfile>=0.2.3
|
|
|
29
28
|
Requires-Dist: click-didyoumean>=0.0.3
|
|
30
29
|
Requires-Dist: click-spinner>=0.1.7
|
|
31
30
|
Requires-Dist: json5>=0.9.0
|
|
32
|
-
Requires-Dist: cloudsmith-api<3.0,>=2.0.
|
|
31
|
+
Requires-Dist: cloudsmith-api<3.0,>=2.0.38
|
|
33
32
|
Requires-Dist: keyring>=25.4.1
|
|
34
33
|
Requires-Dist: keyrings-alt>=5.0.2
|
|
35
34
|
Requires-Dist: keyrings-cryptfile>=1.3.9
|
|
36
35
|
Requires-Dist: cryptography>=50.0.0
|
|
37
|
-
Requires-Dist: mcp==2.
|
|
36
|
+
Requires-Dist: mcp==2.3.0
|
|
38
37
|
Requires-Dist: pydantic-settings>=2.14.2
|
|
39
38
|
Requires-Dist: PyJWT[crypto]>=2.13.0
|
|
40
|
-
Requires-Dist: python-toon==0.
|
|
41
|
-
Requires-Dist: requests>=2.
|
|
39
|
+
Requires-Dist: python-toon==0.2.0
|
|
40
|
+
Requires-Dist: requests>=2.32.5
|
|
42
41
|
Requires-Dist: requests_toolbelt>=1.0.0
|
|
43
42
|
Requires-Dist: rich>=13.0.0
|
|
44
43
|
Requires-Dist: semver>=2.7.9
|
|
45
44
|
Requires-Dist: starlette>=1.3.1
|
|
46
45
|
Requires-Dist: urllib3>=2.5
|
|
47
46
|
Requires-Dist: tomlkit>=0.15.0
|
|
47
|
+
Requires-Dist: sentry-sdk<3,>=2
|
|
48
48
|
Provides-Extra: aws
|
|
49
49
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "aws"
|
|
50
|
+
Provides-Extra: gcp
|
|
51
|
+
Requires-Dist: google-auth>=2.40.0; extra == "gcp"
|
|
50
52
|
Provides-Extra: all
|
|
51
53
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "all"
|
|
54
|
+
Requires-Dist: google-auth>=2.40.0; extra == "all"
|
|
52
55
|
Dynamic: license-file
|
|
53
56
|
|
|
54
57
|
# Cloudsmith Command Line Interface (CLI)
|
|
@@ -100,8 +103,8 @@ The CLI currently supports the following commands (and sub-commands):
|
|
|
100
103
|
- `entitlements`|`ents`: List entitlements for a repository.
|
|
101
104
|
- `packages`: List packages for a repository. (Aliases `repos list`)
|
|
102
105
|
- `repos`: List repositories for a namespace (owner).
|
|
103
|
-
- `login`|`token`: Retrieve your API authentication token/key via login.
|
|
104
|
-
- `logout`: Clear stored authentication credentials and
|
|
106
|
+
- `login`|`token`: [DEPRECATED] Retrieve your API authentication token/key via login.
|
|
107
|
+
- `logout`: Clear stored authentication credentials and SAML tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
|
|
105
108
|
- `metadata`: Manage arbitrary JSON metadata (SBOM, BuildInfo, custom) attached to a package.
|
|
106
109
|
- `add`: Attach a new metadata entry to a package.
|
|
107
110
|
- `list`|`ls`: List metadata entries for a package, or fetch a single entry by slug.
|
|
@@ -232,6 +235,29 @@ pip install cloudsmith-cli[aws]
|
|
|
232
235
|
|
|
233
236
|
This installs `boto3[crt]` for AWS credential chain support, STS token generation, and AWS SSO compatibility.
|
|
234
237
|
|
|
238
|
+
#### GCP OIDC Support
|
|
239
|
+
|
|
240
|
+
For Google Cloud environments (GCE, Cloud Run, GKE, Cloud Functions, App Engine, Cloud Build), install with the `gcp` extra to enable automatic credential discovery:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
pip install cloudsmith-cli[gcp]
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
This installs `google-auth` for Application Default Credentials (ADC) resolution and OIDC ID token generation. It works with an attached Google Cloud service account, a service-account key supplied through `GOOGLE_APPLICATION_CREDENTIALS`, or service-account impersonation configured locally:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL
|
|
250
|
+
cloudsmith whoami --workspace=YOUR_WORKSPACE --oidc-service-slug=YOUR_SERVICE --oidc-detector-order=gcp
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Configure a Cloudsmith OIDC provider to trust `https://accounts.google.com`, the service account's numeric unique ID as the subject, and audience `cloudsmith` (override with `--oidc-audience` or `CLOUDSMITH_OIDC_AUDIENCE`). Local impersonation requires the Service Account Token Creator role on the target service account and the IAM Service Account Credentials API enabled.
|
|
254
|
+
|
|
255
|
+
On workloads with a metadata identity endpoint, the CLI requests an ID token directly. If that endpoint returns HTTP 404 (as on some Cloud Build environments), it uses IAM `generateIdToken` for the same attached service account. This fallback requires the IAM Service Account Credentials API and `iam.serviceAccounts.getOpenIdToken` on that account; the Service Account OpenID Connect Identity Token Creator role grants this permission. Permission and transport failures are reported, not treated as a missing endpoint.
|
|
256
|
+
|
|
257
|
+
A plain `gcloud auth application-default login` user session cannot mint an ID token for an arbitrary audience. To use it, set `--oidc-audience` to the session's OAuth client ID and configure Cloudsmith to trust that audience and user subject; otherwise use service-account impersonation. `gcloud auth login` alone does not configure ADC. Other ADC types, including direct external-account federation, are skipped rather than incorrectly treated as ID-token-capable credentials.
|
|
258
|
+
|
|
259
|
+
See Google's [Authenticate with auth libraries](https://docs.cloud.google.com/iam/docs/authenticate-with-auth-libraries#authenticate-standard) guide for credential discovery.
|
|
260
|
+
|
|
235
261
|
#### All Optional Features
|
|
236
262
|
|
|
237
263
|
To install all optional dependencies:
|
|
@@ -240,7 +266,7 @@ To install all optional dependencies:
|
|
|
240
266
|
pip install cloudsmith-cli[all]
|
|
241
267
|
```
|
|
242
268
|
|
|
243
|
-
**Note:** If you don't install the AWS extra, the
|
|
269
|
+
**Note:** If you don't install the AWS or GCP extra, the corresponding OIDC detector will gracefully skip itself with no errors.
|
|
244
270
|
|
|
245
271
|
#### Bitbucket Pipelines OIDC Support
|
|
246
272
|
|
|
@@ -261,6 +287,10 @@ See the [Bitbucket Pipelines OIDC documentation](https://support.atlassian.com/b
|
|
|
261
287
|
|
|
262
288
|
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).
|
|
263
289
|
|
|
290
|
+
#### Buildkite OIDC Support
|
|
291
|
+
|
|
292
|
+
In Buildkite, OIDC credential discovery works out of the box with no extra dependencies — the CLI requests a token for the current job through `buildkite-agent oidc request-token`. By default it requests the `cloudsmith` audience; use `--oidc-audience` or `CLOUDSMITH_OIDC_AUDIENCE` if your Cloudsmith OIDC provider expects a different audience. See the [Buildkite OIDC documentation](https://buildkite.com/docs/pipelines/security/oidc).
|
|
293
|
+
|
|
264
294
|
#### Azure DevOps OIDC Support
|
|
265
295
|
|
|
266
296
|
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).
|
|
@@ -295,7 +325,7 @@ By default the CLI tries each detector in a fixed priority order and uses the fi
|
|
|
295
325
|
- **Disable a detector** — set `CLOUDSMITH_OIDC_<DETECTOR>_DISABLED=true` to skip it entirely. Only the literal value `true` (case-insensitive) disables; anything else leaves the detector enabled. For example, `CLOUDSMITH_OIDC_AWS_DISABLED=true` skips the AWS detector so an explicitly-set `CLOUDSMITH_OIDC_TOKEN` is picked up by the generic detector instead.
|
|
296
326
|
- **Reorder evaluation** — use `--oidc-detector-order` (or the `CLOUDSMITH_OIDC_DETECTOR_ORDER` environment variable) with a comma-separated list of detector ids to control both which detectors are considered and the order they are tried in (first match wins). Ids not listed are skipped; unrecognised ids are ignored with a warning. For example, `--oidc-detector-order=generic,aws` tries the generic detector first and considers only those two.
|
|
297
327
|
|
|
298
|
-
When both are set, the order list defines the candidate set and sequence, then the `*_DISABLED` flags are applied on top — so a disabled detector is always skipped even if it appears in the order list. Detector ids are: `aws`, `azure_devops`, `bitbucket`, `circleci`, `generic`, `github`, `gitlab`.
|
|
328
|
+
When both are set, the order list defines the candidate set and sequence, then the `*_DISABLED` flags are applied on top — so a disabled detector is always skipped even if it appears in the order list. Detector ids are: `aws`, `azure_devops`, `bitbucket`, `buildkite`, `circleci`, `gcp`, `generic`, `github`, `gitlab`.
|
|
299
329
|
|
|
300
330
|
Both controls can also be set in `config.ini`, under `[default]` or a profile section:
|
|
301
331
|
|
|
@@ -338,7 +368,7 @@ Both configuration files use the simple INI format, such as:
|
|
|
338
368
|
api_key=1234567890abcdef1234567890abcdef
|
|
339
369
|
```
|
|
340
370
|
|
|
341
|
-
Additionally, the CLI will store
|
|
371
|
+
Additionally, the CLI will store SAML access and refresh tokens in the system keyring
|
|
342
372
|
using the [`keyring`](https://github.com/jaraco/keyring) library.
|
|
343
373
|
|
|
344
374
|
|
|
@@ -349,8 +379,9 @@ See the [default config](https://raw.githubusercontent.com/cloudsmith-io/cloudsm
|
|
|
349
379
|
You can specify the following configuration options:
|
|
350
380
|
|
|
351
381
|
- `api_host`: The API host to connect to.
|
|
352
|
-
- `
|
|
353
|
-
- `
|
|
382
|
+
- `proxy`: The proxy to connect through for all HTTP requests, including API, SAML, upload, download, MCP, update, credential helper, OIDC, and error report connections. Use `--proxy` or `CLOUDSMITH_PROXY` to set it for one command. The config key `api_proxy`, flag `--api-proxy`, and environment variable `CLOUDSMITH_API_PROXY` remain supported for compatibility. In config and environment variables, the new name takes precedence over the alias. Without `proxy`, the CLI uses the `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables. When `proxy` is set, it takes precedence over them.
|
|
383
|
+
- `ssl_verify`: Whether or not to verify SSL certificates for HTTPS requests, including API, SAML, uploads, downloads, and MCP (default: `true`). Use `CLOUDSMITH_SSL_VERIFY=1` to enable verification or `CLOUDSMITH_SSL_VERIFY=0` / `--without-ssl-verify` to disable it. Disabling verification is dangerous; prefer disabling only strict checks where possible. The config key `api_ssl_verify`, flag `--without-api-ssl-verify` / `-S`, and environment variable `CLOUDSMITH_WITHOUT_API_SSL_VERIFY` remain supported for compatibility. Command-line settings override environment variables, which override config; within the same source, the new spelling takes precedence.
|
|
384
|
+
- `ssl_verify_strict`: Whether or not to apply strict X.509 certificate verification (`VERIFY_X509_STRICT`, enabled by default on Python 3.13+). Set to `false` (or use `--without-ssl-verify-strict` / `CLOUDSMITH_SSL_VERIFY_STRICT=0`) if a TLS-intercepting proxy issues certificates that fail these checks. `CLOUDSMITH_SSL_VERIFY_STRICT=1` keeps strict verification enabled (the default). Certificates are still verified.
|
|
354
385
|
- `api_user_agent`: The user agent to use for requests.
|
|
355
386
|
|
|
356
387
|
### Credentials (credentials.ini)
|
|
@@ -389,29 +420,15 @@ cloudsmith auth --owner example --no-browser
|
|
|
389
420
|
|
|
390
421
|
#### Getting Your API Key
|
|
391
422
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
```
|
|
395
|
-
cloudsmith login
|
|
396
|
-
Login: you@example.com
|
|
397
|
-
Password:
|
|
398
|
-
Repeat for confirmation:
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
*Note:* Please ensure you use your email for the 'Login' prompt and not your user slug/identifier.
|
|
402
|
-
|
|
403
|
-
The resulting output looks something like:
|
|
404
|
-
|
|
405
|
-
```
|
|
406
|
-
Retrieving API token for 'you@example.com' ... OK
|
|
407
|
-
Your API token is: 1234567890abcdef1234567890abcdef
|
|
408
|
-
```
|
|
423
|
+
Get your API key from the Cloudsmith web app: click your user icon in the top right corner, then click **Personal API Keys**. See [API Key](https://docs.cloudsmith.com/accounts-and-teams/api-key) for more information. If you authenticated with `cloudsmith auth`, you can also use `cloudsmith tokens create` to create an API key.
|
|
409
424
|
|
|
410
|
-
|
|
425
|
+
Give your API key to the CLI in one of these ways:
|
|
411
426
|
|
|
412
|
-
|
|
427
|
+
- Set the `CLOUDSMITH_API_KEY` environment variable: `export CLOUDSMITH_API_KEY=your_key_here`.
|
|
428
|
+
- Put the key into your `credentials.ini` file.
|
|
429
|
+
- Pass the key to the CLI with the `-k your_key_here` flag.
|
|
413
430
|
|
|
414
|
-
|
|
431
|
+
*Note:* The `cloudsmith login` command and its `cloudsmith token` alias are deprecated. They retrieve your API key with your email address and password, and they will stop working on November 20, 2026, when Cloudsmith disables username and password login. See the [Cloudsmith changelog](https://cloudsmith.com/changelog). After that, both commands fail with a message that explains how to get an API key instead.
|
|
415
432
|
|
|
416
433
|
|
|
417
434
|
## Uploading Packages
|
|
@@ -47,8 +47,8 @@ The CLI currently supports the following commands (and sub-commands):
|
|
|
47
47
|
- `entitlements`|`ents`: List entitlements for a repository.
|
|
48
48
|
- `packages`: List packages for a repository. (Aliases `repos list`)
|
|
49
49
|
- `repos`: List repositories for a namespace (owner).
|
|
50
|
-
- `login`|`token`: Retrieve your API authentication token/key via login.
|
|
51
|
-
- `logout`: Clear stored authentication credentials and
|
|
50
|
+
- `login`|`token`: [DEPRECATED] Retrieve your API authentication token/key via login.
|
|
51
|
+
- `logout`: Clear stored authentication credentials and SAML tokens (Keyring, API key from credential file and emit warning when `$CLOUDSMITH_API_KEY` is still set).
|
|
52
52
|
- `metadata`: Manage arbitrary JSON metadata (SBOM, BuildInfo, custom) attached to a package.
|
|
53
53
|
- `add`: Attach a new metadata entry to a package.
|
|
54
54
|
- `list`|`ls`: List metadata entries for a package, or fetch a single entry by slug.
|
|
@@ -179,6 +179,29 @@ pip install cloudsmith-cli[aws]
|
|
|
179
179
|
|
|
180
180
|
This installs `boto3[crt]` for AWS credential chain support, STS token generation, and AWS SSO compatibility.
|
|
181
181
|
|
|
182
|
+
#### GCP OIDC Support
|
|
183
|
+
|
|
184
|
+
For Google Cloud environments (GCE, Cloud Run, GKE, Cloud Functions, App Engine, Cloud Build), install with the `gcp` extra to enable automatic credential discovery:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
pip install cloudsmith-cli[gcp]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This installs `google-auth` for Application Default Credentials (ADC) resolution and OIDC ID token generation. It works with an attached Google Cloud service account, a service-account key supplied through `GOOGLE_APPLICATION_CREDENTIALS`, or service-account impersonation configured locally:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
gcloud auth application-default login --impersonate-service-account=SERVICE_ACCOUNT_EMAIL
|
|
194
|
+
cloudsmith whoami --workspace=YOUR_WORKSPACE --oidc-service-slug=YOUR_SERVICE --oidc-detector-order=gcp
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Configure a Cloudsmith OIDC provider to trust `https://accounts.google.com`, the service account's numeric unique ID as the subject, and audience `cloudsmith` (override with `--oidc-audience` or `CLOUDSMITH_OIDC_AUDIENCE`). Local impersonation requires the Service Account Token Creator role on the target service account and the IAM Service Account Credentials API enabled.
|
|
198
|
+
|
|
199
|
+
On workloads with a metadata identity endpoint, the CLI requests an ID token directly. If that endpoint returns HTTP 404 (as on some Cloud Build environments), it uses IAM `generateIdToken` for the same attached service account. This fallback requires the IAM Service Account Credentials API and `iam.serviceAccounts.getOpenIdToken` on that account; the Service Account OpenID Connect Identity Token Creator role grants this permission. Permission and transport failures are reported, not treated as a missing endpoint.
|
|
200
|
+
|
|
201
|
+
A plain `gcloud auth application-default login` user session cannot mint an ID token for an arbitrary audience. To use it, set `--oidc-audience` to the session's OAuth client ID and configure Cloudsmith to trust that audience and user subject; otherwise use service-account impersonation. `gcloud auth login` alone does not configure ADC. Other ADC types, including direct external-account federation, are skipped rather than incorrectly treated as ID-token-capable credentials.
|
|
202
|
+
|
|
203
|
+
See Google's [Authenticate with auth libraries](https://docs.cloud.google.com/iam/docs/authenticate-with-auth-libraries#authenticate-standard) guide for credential discovery.
|
|
204
|
+
|
|
182
205
|
#### All Optional Features
|
|
183
206
|
|
|
184
207
|
To install all optional dependencies:
|
|
@@ -187,7 +210,7 @@ To install all optional dependencies:
|
|
|
187
210
|
pip install cloudsmith-cli[all]
|
|
188
211
|
```
|
|
189
212
|
|
|
190
|
-
**Note:** If you don't install the AWS extra, the
|
|
213
|
+
**Note:** If you don't install the AWS or GCP extra, the corresponding OIDC detector will gracefully skip itself with no errors.
|
|
191
214
|
|
|
192
215
|
#### Bitbucket Pipelines OIDC Support
|
|
193
216
|
|
|
@@ -208,6 +231,10 @@ See the [Bitbucket Pipelines OIDC documentation](https://support.atlassian.com/b
|
|
|
208
231
|
|
|
209
232
|
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).
|
|
210
233
|
|
|
234
|
+
#### Buildkite OIDC Support
|
|
235
|
+
|
|
236
|
+
In Buildkite, OIDC credential discovery works out of the box with no extra dependencies — the CLI requests a token for the current job through `buildkite-agent oidc request-token`. By default it requests the `cloudsmith` audience; use `--oidc-audience` or `CLOUDSMITH_OIDC_AUDIENCE` if your Cloudsmith OIDC provider expects a different audience. See the [Buildkite OIDC documentation](https://buildkite.com/docs/pipelines/security/oidc).
|
|
237
|
+
|
|
211
238
|
#### Azure DevOps OIDC Support
|
|
212
239
|
|
|
213
240
|
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).
|
|
@@ -242,7 +269,7 @@ By default the CLI tries each detector in a fixed priority order and uses the fi
|
|
|
242
269
|
- **Disable a detector** — set `CLOUDSMITH_OIDC_<DETECTOR>_DISABLED=true` to skip it entirely. Only the literal value `true` (case-insensitive) disables; anything else leaves the detector enabled. For example, `CLOUDSMITH_OIDC_AWS_DISABLED=true` skips the AWS detector so an explicitly-set `CLOUDSMITH_OIDC_TOKEN` is picked up by the generic detector instead.
|
|
243
270
|
- **Reorder evaluation** — use `--oidc-detector-order` (or the `CLOUDSMITH_OIDC_DETECTOR_ORDER` environment variable) with a comma-separated list of detector ids to control both which detectors are considered and the order they are tried in (first match wins). Ids not listed are skipped; unrecognised ids are ignored with a warning. For example, `--oidc-detector-order=generic,aws` tries the generic detector first and considers only those two.
|
|
244
271
|
|
|
245
|
-
When both are set, the order list defines the candidate set and sequence, then the `*_DISABLED` flags are applied on top — so a disabled detector is always skipped even if it appears in the order list. Detector ids are: `aws`, `azure_devops`, `bitbucket`, `circleci`, `generic`, `github`, `gitlab`.
|
|
272
|
+
When both are set, the order list defines the candidate set and sequence, then the `*_DISABLED` flags are applied on top — so a disabled detector is always skipped even if it appears in the order list. Detector ids are: `aws`, `azure_devops`, `bitbucket`, `buildkite`, `circleci`, `gcp`, `generic`, `github`, `gitlab`.
|
|
246
273
|
|
|
247
274
|
Both controls can also be set in `config.ini`, under `[default]` or a profile section:
|
|
248
275
|
|
|
@@ -285,7 +312,7 @@ Both configuration files use the simple INI format, such as:
|
|
|
285
312
|
api_key=1234567890abcdef1234567890abcdef
|
|
286
313
|
```
|
|
287
314
|
|
|
288
|
-
Additionally, the CLI will store
|
|
315
|
+
Additionally, the CLI will store SAML access and refresh tokens in the system keyring
|
|
289
316
|
using the [`keyring`](https://github.com/jaraco/keyring) library.
|
|
290
317
|
|
|
291
318
|
|
|
@@ -296,8 +323,9 @@ See the [default config](https://raw.githubusercontent.com/cloudsmith-io/cloudsm
|
|
|
296
323
|
You can specify the following configuration options:
|
|
297
324
|
|
|
298
325
|
- `api_host`: The API host to connect to.
|
|
299
|
-
- `
|
|
300
|
-
- `
|
|
326
|
+
- `proxy`: The proxy to connect through for all HTTP requests, including API, SAML, upload, download, MCP, update, credential helper, OIDC, and error report connections. Use `--proxy` or `CLOUDSMITH_PROXY` to set it for one command. The config key `api_proxy`, flag `--api-proxy`, and environment variable `CLOUDSMITH_API_PROXY` remain supported for compatibility. In config and environment variables, the new name takes precedence over the alias. Without `proxy`, the CLI uses the `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables. When `proxy` is set, it takes precedence over them.
|
|
327
|
+
- `ssl_verify`: Whether or not to verify SSL certificates for HTTPS requests, including API, SAML, uploads, downloads, and MCP (default: `true`). Use `CLOUDSMITH_SSL_VERIFY=1` to enable verification or `CLOUDSMITH_SSL_VERIFY=0` / `--without-ssl-verify` to disable it. Disabling verification is dangerous; prefer disabling only strict checks where possible. The config key `api_ssl_verify`, flag `--without-api-ssl-verify` / `-S`, and environment variable `CLOUDSMITH_WITHOUT_API_SSL_VERIFY` remain supported for compatibility. Command-line settings override environment variables, which override config; within the same source, the new spelling takes precedence.
|
|
328
|
+
- `ssl_verify_strict`: Whether or not to apply strict X.509 certificate verification (`VERIFY_X509_STRICT`, enabled by default on Python 3.13+). Set to `false` (or use `--without-ssl-verify-strict` / `CLOUDSMITH_SSL_VERIFY_STRICT=0`) if a TLS-intercepting proxy issues certificates that fail these checks. `CLOUDSMITH_SSL_VERIFY_STRICT=1` keeps strict verification enabled (the default). Certificates are still verified.
|
|
301
329
|
- `api_user_agent`: The user agent to use for requests.
|
|
302
330
|
|
|
303
331
|
### Credentials (credentials.ini)
|
|
@@ -336,29 +364,15 @@ cloudsmith auth --owner example --no-browser
|
|
|
336
364
|
|
|
337
365
|
#### Getting Your API Key
|
|
338
366
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
```
|
|
342
|
-
cloudsmith login
|
|
343
|
-
Login: you@example.com
|
|
344
|
-
Password:
|
|
345
|
-
Repeat for confirmation:
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
*Note:* Please ensure you use your email for the 'Login' prompt and not your user slug/identifier.
|
|
349
|
-
|
|
350
|
-
The resulting output looks something like:
|
|
351
|
-
|
|
352
|
-
```
|
|
353
|
-
Retrieving API token for 'you@example.com' ... OK
|
|
354
|
-
Your API token is: 1234567890abcdef1234567890abcdef
|
|
355
|
-
```
|
|
367
|
+
Get your API key from the Cloudsmith web app: click your user icon in the top right corner, then click **Personal API Keys**. See [API Key](https://docs.cloudsmith.com/accounts-and-teams/api-key) for more information. If you authenticated with `cloudsmith auth`, you can also use `cloudsmith tokens create` to create an API key.
|
|
356
368
|
|
|
357
|
-
|
|
369
|
+
Give your API key to the CLI in one of these ways:
|
|
358
370
|
|
|
359
|
-
|
|
371
|
+
- Set the `CLOUDSMITH_API_KEY` environment variable: `export CLOUDSMITH_API_KEY=your_key_here`.
|
|
372
|
+
- Put the key into your `credentials.ini` file.
|
|
373
|
+
- Pass the key to the CLI with the `-k your_key_here` flag.
|
|
360
374
|
|
|
361
|
-
|
|
375
|
+
*Note:* The `cloudsmith login` command and its `cloudsmith token` alias are deprecated. They retrieve your API key with your email address and password, and they will stop working on November 20, 2026, when Cloudsmith disables username and password login. See the [Cloudsmith changelog](https://cloudsmith.com/changelog). After that, both commands fail with a message that explains how to get an API key instead.
|
|
362
376
|
|
|
363
377
|
|
|
364
378
|
## Uploading Packages
|
|
@@ -6,6 +6,8 @@ from collections import OrderedDict
|
|
|
6
6
|
import click.exceptions
|
|
7
7
|
from click_didyoumean import DYMGroup
|
|
8
8
|
|
|
9
|
+
from ..core.certificate_errors import describe_certificate_error
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
def _is_json_output_requested(exception):
|
|
11
13
|
"""Determine if JSON output was requested, checking context and argv."""
|
|
@@ -35,6 +37,19 @@ def _is_json_output_requested(exception):
|
|
|
35
37
|
return False
|
|
36
38
|
|
|
37
39
|
|
|
40
|
+
def _is_debug_requested(args=None):
|
|
41
|
+
"""Determine if --debug was passed (the click context is gone by now).
|
|
42
|
+
|
|
43
|
+
``args`` are the arguments given to ``main``; click falls back to
|
|
44
|
+
``sys.argv`` when they are ``None``, so we do the same.
|
|
45
|
+
"""
|
|
46
|
+
import sys
|
|
47
|
+
|
|
48
|
+
if args is None:
|
|
49
|
+
args = sys.argv[1:]
|
|
50
|
+
return any(arg in ("-d", "--debug") for arg in args)
|
|
51
|
+
|
|
52
|
+
|
|
38
53
|
def _format_click_exception_as_json(exception):
|
|
39
54
|
"""Format a ClickException as a JSON error dict."""
|
|
40
55
|
return {
|
|
@@ -45,11 +60,19 @@ def _format_click_exception_as_json(exception):
|
|
|
45
60
|
},
|
|
46
61
|
"help": {
|
|
47
62
|
"context": "Invalid usage",
|
|
48
|
-
"hint":
|
|
63
|
+
"hint": describe_certificate_error(exception)
|
|
64
|
+
or "Check your command arguments/flags.",
|
|
49
65
|
},
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
|
|
69
|
+
def _echo_certificate_hint(exception):
|
|
70
|
+
"""Explain a TLS certificate failure behind ``exception`` on stderr."""
|
|
71
|
+
hint = describe_certificate_error(exception)
|
|
72
|
+
if hint:
|
|
73
|
+
click.echo(f"Hint: {click.style(hint, fg='yellow')}", err=True)
|
|
74
|
+
|
|
75
|
+
|
|
53
76
|
class AliasGroup(DYMGroup):
|
|
54
77
|
"""A command group with DYM, alias and lazy-subcommand support.
|
|
55
78
|
|
|
@@ -177,4 +200,23 @@ class AliasGroup(DYMGroup):
|
|
|
177
200
|
if not original_standalone_mode:
|
|
178
201
|
raise
|
|
179
202
|
e.show()
|
|
203
|
+
_echo_certificate_hint(e)
|
|
180
204
|
sys.exit(e.exit_code)
|
|
205
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
206
|
+
# Anything reaching here is unexpected: click's own errors and
|
|
207
|
+
# handled API errors (which exit via ctx.exit) are dealt with
|
|
208
|
+
# above or never get this far.
|
|
209
|
+
if not original_standalone_mode:
|
|
210
|
+
raise
|
|
211
|
+
main_args = kwargs.get("args", args[0] if args else None)
|
|
212
|
+
if _is_debug_requested(main_args):
|
|
213
|
+
import traceback
|
|
214
|
+
|
|
215
|
+
click.echo(traceback.format_exc(), err=True, nl=False)
|
|
216
|
+
from ..core import telemetry
|
|
217
|
+
|
|
218
|
+
# Reporting is silent: the user sees the same line either way.
|
|
219
|
+
telemetry.report_exception(e)
|
|
220
|
+
click.echo(f"Error: {telemetry.format_exception_summary(e)}", err=True)
|
|
221
|
+
_echo_certificate_hint(e)
|
|
222
|
+
sys.exit(1)
|
|
@@ -12,7 +12,7 @@ from ...core.sso import (
|
|
|
12
12
|
)
|
|
13
13
|
from .. import decorators, utils, validators
|
|
14
14
|
from ..exceptions import handle_api_exceptions
|
|
15
|
-
from ..saml import
|
|
15
|
+
from ..saml import get_idp_url
|
|
16
16
|
from ..webserver import AuthenticationWebRequestHandler, AuthenticationWebServer
|
|
17
17
|
from .main import main
|
|
18
18
|
from .tokens import create, request_api_key
|
|
@@ -53,7 +53,7 @@ def _create_auth_server(opts, owner, session, enable_token_creation, profile):
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def _renew_existing_sso_session(opts, profile):
|
|
56
|
-
"""Return a usable existing
|
|
56
|
+
"""Return a usable existing SAML session, or fall back to browser auth."""
|
|
57
57
|
renewal = renew_sso_session(opts.api_config.host, opts.session, profile=profile)
|
|
58
58
|
if renewal.status in (
|
|
59
59
|
SsoRenewalStatus.RENEWED,
|
|
@@ -64,14 +64,15 @@ def _renew_existing_sso_session(opts, profile):
|
|
|
64
64
|
renewal.error, requests.RequestException
|
|
65
65
|
):
|
|
66
66
|
raise click.ClickException(
|
|
67
|
-
"The
|
|
67
|
+
"The SAML session has expired and Cloudsmith could not be reached: "
|
|
68
|
+
f"{renewal.error}\n"
|
|
68
69
|
"Check your connection, then run 'cloudsmith auth' again."
|
|
69
70
|
) from renewal.error
|
|
70
71
|
return None
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def _report_active_sso_session(opts, renewal, use_stderr=False):
|
|
74
|
-
"""Report the usable
|
|
75
|
+
"""Report the usable SAML session without exposing its access token."""
|
|
75
76
|
expires_at = get_access_token_expiry(renewal.access_token)
|
|
76
77
|
data = {
|
|
77
78
|
"authenticated": True,
|
|
@@ -84,16 +85,16 @@ def _report_active_sso_session(opts, renewal, use_stderr=False):
|
|
|
84
85
|
return
|
|
85
86
|
|
|
86
87
|
if renewal.status == SsoRenewalStatus.RENEWED:
|
|
87
|
-
click.secho("
|
|
88
|
+
click.secho("SAML session renewed.", fg="green", err=use_stderr)
|
|
88
89
|
elif renewal.error:
|
|
89
90
|
click.secho(
|
|
90
|
-
"The
|
|
91
|
+
"The SAML session could not be renewed; the existing access token "
|
|
91
92
|
"remains active.",
|
|
92
93
|
fg="yellow",
|
|
93
94
|
err=use_stderr,
|
|
94
95
|
)
|
|
95
96
|
else:
|
|
96
|
-
click.secho("
|
|
97
|
+
click.secho("SAML session is active.", fg="green", err=use_stderr)
|
|
97
98
|
if expires_at:
|
|
98
99
|
click.echo(
|
|
99
100
|
f"Access token expires at {utils.fmt_datetime(expires_at)}.",
|
|
@@ -110,7 +111,7 @@ def _perform_saml_authentication(
|
|
|
110
111
|
profile=None,
|
|
111
112
|
):
|
|
112
113
|
"""Perform SAML authentication via web browser and local web server."""
|
|
113
|
-
session =
|
|
114
|
+
session = opts.session
|
|
114
115
|
api_host = opts.api_config.host
|
|
115
116
|
|
|
116
117
|
auth_server, port = _create_auth_server(
|
|
@@ -270,10 +271,10 @@ def authenticate(
|
|
|
270
271
|
err=use_stderr,
|
|
271
272
|
)
|
|
272
273
|
|
|
273
|
-
# Determine if we need to refresh API after
|
|
274
|
+
# Determine if we need to refresh API after SAML (required for token operations)
|
|
274
275
|
enable_token_creation = token or request_api_key_flag
|
|
275
276
|
|
|
276
|
-
context_message = "Failed to authenticate via
|
|
277
|
+
context_message = "Failed to authenticate via SAML!"
|
|
277
278
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_message):
|
|
278
279
|
_perform_saml_authentication(
|
|
279
280
|
opts,
|
|
@@ -127,6 +127,4 @@ def service(ctx, opts):
|
|
|
127
127
|
click.secho("(up-to-date)", fg="green")
|
|
128
128
|
|
|
129
129
|
click.echo()
|
|
130
|
-
click.secho(
|
|
131
|
-
"The API library used by this CLI tool seems to be up-to-date.", fg="green"
|
|
132
|
-
)
|
|
130
|
+
click.secho("The API library used by this CLI tool is up-to-date.", fg="green")
|
|
@@ -9,6 +9,7 @@ Provides ``credential-helper install``, ``credential-helper uninstall``, and
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
11
|
import sys
|
|
12
|
+
from urllib.parse import urlsplit
|
|
12
13
|
|
|
13
14
|
import click
|
|
14
15
|
|
|
@@ -78,10 +79,14 @@ def _get_installer(name: str):
|
|
|
78
79
|
def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...]:
|
|
79
80
|
"""Build the terraformrc ``args`` list from the resolved config.
|
|
80
81
|
|
|
81
|
-
Baking
|
|
82
|
+
Baking ``-w``/``-r``/``-P`` into the block means ``terraform init`` works
|
|
82
83
|
with no environment variables and no hand-edited config. Only values
|
|
83
|
-
actually supplied are written, so an install without
|
|
84
|
-
``-P`` leaves ``args = []``.
|
|
84
|
+
actually supplied are written, so an install without ``-w``/``--repo``/
|
|
85
|
+
``-P`` leaves ``args = []``. The API host and proxy are baked in too, so
|
|
86
|
+
the helper looks up domains on the same API host, through the same proxy,
|
|
87
|
+
as the install. A proxy URL with credentials is never baked in: Terraform
|
|
88
|
+
passes ``args`` on the helper's command line, where any local user can read
|
|
89
|
+
them.
|
|
85
90
|
|
|
86
91
|
A non-default ``--config-file``/``--credentials-file`` is also baked in: the
|
|
87
92
|
helper is later invoked by ``terraform init`` in a fresh process with none
|
|
@@ -91,7 +96,7 @@ def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...
|
|
|
91
96
|
"""
|
|
92
97
|
args: list[str] = []
|
|
93
98
|
if opts.org:
|
|
94
|
-
args.extend(["
|
|
99
|
+
args.extend(["-w", opts.org])
|
|
95
100
|
if repo:
|
|
96
101
|
args.extend(["-r", repo])
|
|
97
102
|
profile = ctx.meta.get("profile")
|
|
@@ -103,9 +108,32 @@ def _terraform_helper_args(ctx, opts, repo: str | None = None) -> tuple[str, ...
|
|
|
103
108
|
creds_file = ctx.meta.get("creds_file")
|
|
104
109
|
if creds_file:
|
|
105
110
|
args.extend(["--credentials-file", creds_file])
|
|
111
|
+
if opts.api_host:
|
|
112
|
+
args.extend(["--api-host", opts.api_host])
|
|
113
|
+
if opts.proxy and not _proxy_has_credentials(opts.proxy):
|
|
114
|
+
args.extend(["--proxy", opts.proxy])
|
|
106
115
|
return tuple(args)
|
|
107
116
|
|
|
108
117
|
|
|
118
|
+
def _proxy_has_credentials(proxy: str) -> bool:
|
|
119
|
+
"""Return True if the proxy URL carries a username or password."""
|
|
120
|
+
parsed = urlsplit(proxy if "://" in proxy else f"//{proxy}")
|
|
121
|
+
return parsed.username is not None or parsed.password is not None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _terraform_proxy_next_steps(opts) -> list[str]:
|
|
125
|
+
"""Return the post-install guidance when the proxy was not baked in."""
|
|
126
|
+
if not opts.proxy or not _proxy_has_credentials(opts.proxy):
|
|
127
|
+
return []
|
|
128
|
+
return [
|
|
129
|
+
(
|
|
130
|
+
"Next steps: the proxy URL contains credentials, so it was not"
|
|
131
|
+
" written to the Terraform config. export CLOUDSMITH_PROXY=<proxy-url>"
|
|
132
|
+
" in the environment that runs `terraform init`."
|
|
133
|
+
),
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
|
|
109
137
|
_REPO_FLAGS = ("-r", "--repo", "--repository")
|
|
110
138
|
|
|
111
139
|
|
|
@@ -141,6 +169,31 @@ def _terraform_next_steps(helper_args: tuple[str, ...]) -> list[str]:
|
|
|
141
169
|
]
|
|
142
170
|
|
|
143
171
|
|
|
172
|
+
def _terraform_workspace_next_steps(helper_args: tuple[str, ...]) -> list[str]:
|
|
173
|
+
"""Return the post-install guidance when no Workspace is baked in.
|
|
174
|
+
|
|
175
|
+
The helper needs a Workspace to match custom domains and to scope the
|
|
176
|
+
token for a Cloudsmith-owned host.
|
|
177
|
+
"""
|
|
178
|
+
if "-w" in helper_args:
|
|
179
|
+
return []
|
|
180
|
+
rc_path = _terraformrc_path()
|
|
181
|
+
return [
|
|
182
|
+
(
|
|
183
|
+
"Next steps: the Terraform helper needs a Workspace to match custom"
|
|
184
|
+
" domains and to scope tokens. Provide it in one of these ways:"
|
|
185
|
+
),
|
|
186
|
+
(
|
|
187
|
+
" - export CLOUDSMITH_WORKSPACE=<your-workspace> in the environment"
|
|
188
|
+
" that runs `terraform init`, or"
|
|
189
|
+
),
|
|
190
|
+
(
|
|
191
|
+
f" - add it to the args in {rc_path}, e.g."
|
|
192
|
+
' args = ["-w", "<your-workspace>", ...].'
|
|
193
|
+
),
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
|
|
144
197
|
# ---------------------------------------------------------------------------
|
|
145
198
|
# install
|
|
146
199
|
# ---------------------------------------------------------------------------
|
|
@@ -149,7 +202,10 @@ def _terraform_next_steps(helper_args: tuple[str, ...]) -> list[str]:
|
|
|
149
202
|
@click.command("install")
|
|
150
203
|
@click.argument("helper")
|
|
151
204
|
@click.option(
|
|
152
|
-
"--bin-dir",
|
|
205
|
+
"--bin-dir",
|
|
206
|
+
default=None,
|
|
207
|
+
help="Directory to install the launcher binary. "
|
|
208
|
+
"[default: ~/.cloudsmith/bin, or Terraform's plugin directory]",
|
|
153
209
|
)
|
|
154
210
|
@click.option(
|
|
155
211
|
"--domain",
|
|
@@ -231,7 +287,7 @@ def install_cmd(
|
|
|
231
287
|
\b
|
|
232
288
|
# Terraform: bake the repository into the terraformrc args so
|
|
233
289
|
# `terraform init` needs no CLOUDSMITH_REPO env var
|
|
234
|
-
$ cloudsmith credential-helper install terraform
|
|
290
|
+
$ cloudsmith credential-helper install terraform -w acme --repo my-repo
|
|
235
291
|
"""
|
|
236
292
|
installer = _get_installer(helper)
|
|
237
293
|
|
|
@@ -278,7 +334,11 @@ def install_cmd(
|
|
|
278
334
|
|
|
279
335
|
next_steps: list[str] = []
|
|
280
336
|
if helper == "terraform":
|
|
281
|
-
next_steps =
|
|
337
|
+
next_steps = (
|
|
338
|
+
_terraform_workspace_next_steps(helper_args)
|
|
339
|
+
+ _terraform_next_steps(helper_args)
|
|
340
|
+
+ _terraform_proxy_next_steps(opts)
|
|
341
|
+
)
|
|
282
342
|
|
|
283
343
|
data = {
|
|
284
344
|
"helper": helper,
|
|
@@ -309,7 +369,10 @@ def install_cmd(
|
|
|
309
369
|
@click.command("uninstall")
|
|
310
370
|
@click.argument("helper")
|
|
311
371
|
@click.option(
|
|
312
|
-
"--bin-dir",
|
|
372
|
+
"--bin-dir",
|
|
373
|
+
default=None,
|
|
374
|
+
help="Directory where the launcher binary was installed. "
|
|
375
|
+
"[default: ~/.cloudsmith/bin, or Terraform's plugin directory]",
|
|
313
376
|
)
|
|
314
377
|
@click.option(
|
|
315
378
|
"--dry-run",
|