cloudsmith-cli 1.20.0__py3-none-any.whl
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/__init__.py +10 -0
- cloudsmith_cli/__main__.py +8 -0
- cloudsmith_cli/cli/__init__.py +1 -0
- cloudsmith_cli/cli/command.py +160 -0
- cloudsmith_cli/cli/commands/__init__.py +33 -0
- cloudsmith_cli/cli/commands/auth.py +173 -0
- cloudsmith_cli/cli/commands/check.py +129 -0
- cloudsmith_cli/cli/commands/copy.py +98 -0
- cloudsmith_cli/cli/commands/credential_helper/__init__.py +39 -0
- cloudsmith_cli/cli/commands/credential_helper/docker.py +66 -0
- cloudsmith_cli/cli/commands/credential_helper/manage.py +299 -0
- cloudsmith_cli/cli/commands/delete.py +67 -0
- cloudsmith_cli/cli/commands/dependencies.py +108 -0
- cloudsmith_cli/cli/commands/docs.py +16 -0
- cloudsmith_cli/cli/commands/download.py +620 -0
- cloudsmith_cli/cli/commands/entitlements.py +819 -0
- cloudsmith_cli/cli/commands/help_.py +12 -0
- cloudsmith_cli/cli/commands/list_.py +317 -0
- cloudsmith_cli/cli/commands/login.py +99 -0
- cloudsmith_cli/cli/commands/logout.py +151 -0
- cloudsmith_cli/cli/commands/main.py +73 -0
- cloudsmith_cli/cli/commands/mcp.py +523 -0
- cloudsmith_cli/cli/commands/metadata.py +503 -0
- cloudsmith_cli/cli/commands/metrics/__init__.py +2 -0
- cloudsmith_cli/cli/commands/metrics/command.py +20 -0
- cloudsmith_cli/cli/commands/metrics/entitlements.py +148 -0
- cloudsmith_cli/cli/commands/metrics/packages.py +134 -0
- cloudsmith_cli/cli/commands/move.py +111 -0
- cloudsmith_cli/cli/commands/policy/__init__.py +3 -0
- cloudsmith_cli/cli/commands/policy/command.py +20 -0
- cloudsmith_cli/cli/commands/policy/deny.py +248 -0
- cloudsmith_cli/cli/commands/policy/license.py +335 -0
- cloudsmith_cli/cli/commands/policy/vulnerability.py +322 -0
- cloudsmith_cli/cli/commands/push.py +1323 -0
- cloudsmith_cli/cli/commands/quarantine.py +148 -0
- cloudsmith_cli/cli/commands/quota/__init__.py +2 -0
- cloudsmith_cli/cli/commands/quota/command.py +20 -0
- cloudsmith_cli/cli/commands/quota/history.py +122 -0
- cloudsmith_cli/cli/commands/quota/quota.py +107 -0
- cloudsmith_cli/cli/commands/repos.py +330 -0
- cloudsmith_cli/cli/commands/resync.py +90 -0
- cloudsmith_cli/cli/commands/status.py +92 -0
- cloudsmith_cli/cli/commands/tags.py +375 -0
- cloudsmith_cli/cli/commands/tokens.py +318 -0
- cloudsmith_cli/cli/commands/upstream.py +479 -0
- cloudsmith_cli/cli/commands/vulnerabilities.py +141 -0
- cloudsmith_cli/cli/commands/whoami.py +188 -0
- cloudsmith_cli/cli/config.py +635 -0
- cloudsmith_cli/cli/decorators.py +624 -0
- cloudsmith_cli/cli/exceptions.py +215 -0
- cloudsmith_cli/cli/metadata_common.py +146 -0
- cloudsmith_cli/cli/saml.py +109 -0
- cloudsmith_cli/cli/table.py +59 -0
- cloudsmith_cli/cli/types.py +14 -0
- cloudsmith_cli/cli/utils.py +267 -0
- cloudsmith_cli/cli/validators.py +378 -0
- cloudsmith_cli/cli/webserver.py +263 -0
- cloudsmith_cli/core/__init__.py +1 -0
- cloudsmith_cli/core/api/__init__.py +1 -0
- cloudsmith_cli/core/api/distros.py +31 -0
- cloudsmith_cli/core/api/entitlements.py +130 -0
- cloudsmith_cli/core/api/exceptions.py +57 -0
- cloudsmith_cli/core/api/files.py +131 -0
- cloudsmith_cli/core/api/init.py +109 -0
- cloudsmith_cli/core/api/metadata.py +217 -0
- cloudsmith_cli/core/api/metrics.py +78 -0
- cloudsmith_cli/core/api/orgs.py +201 -0
- cloudsmith_cli/core/api/packages.py +309 -0
- cloudsmith_cli/core/api/quota.py +64 -0
- cloudsmith_cli/core/api/rates.py +28 -0
- cloudsmith_cli/core/api/repos.py +81 -0
- cloudsmith_cli/core/api/status.py +27 -0
- cloudsmith_cli/core/api/upstreams.py +72 -0
- cloudsmith_cli/core/api/user.py +109 -0
- cloudsmith_cli/core/api/version.py +15 -0
- cloudsmith_cli/core/api/vulnerabilities.py +230 -0
- cloudsmith_cli/core/cache_utils.py +160 -0
- cloudsmith_cli/core/config.py +140 -0
- cloudsmith_cli/core/credentials/__init__.py +0 -0
- cloudsmith_cli/core/credentials/chain.py +69 -0
- cloudsmith_cli/core/credentials/models.py +44 -0
- cloudsmith_cli/core/credentials/oidc/__init__.py +6 -0
- cloudsmith_cli/core/credentials/oidc/cache.py +220 -0
- cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +122 -0
- cloudsmith_cli/core/credentials/oidc/detectors/aws.py +85 -0
- cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +70 -0
- cloudsmith_cli/core/credentials/oidc/detectors/base.py +26 -0
- cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +35 -0
- cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +40 -0
- cloudsmith_cli/core/credentials/oidc/detectors/generic.py +42 -0
- cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +64 -0
- cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +49 -0
- cloudsmith_cli/core/credentials/oidc/exchange.py +87 -0
- cloudsmith_cli/core/credentials/provider.py +17 -0
- cloudsmith_cli/core/credentials/providers/__init__.py +15 -0
- cloudsmith_cli/core/credentials/providers/cli_flag.py +24 -0
- cloudsmith_cli/core/credentials/providers/credentials_file.py +24 -0
- cloudsmith_cli/core/credentials/providers/env_var.py +24 -0
- cloudsmith_cli/core/credentials/providers/keyring_provider.py +59 -0
- cloudsmith_cli/core/credentials/providers/oidc_provider.py +115 -0
- cloudsmith_cli/core/download.py +594 -0
- cloudsmith_cli/core/keyring.py +171 -0
- cloudsmith_cli/core/mcp/__init__.py +0 -0
- cloudsmith_cli/core/mcp/data.py +17 -0
- cloudsmith_cli/core/mcp/server.py +786 -0
- cloudsmith_cli/core/pagination.py +131 -0
- cloudsmith_cli/core/ratelimits.py +88 -0
- cloudsmith_cli/core/rest.py +255 -0
- cloudsmith_cli/core/utils.py +95 -0
- cloudsmith_cli/core/version.py +20 -0
- cloudsmith_cli/credential_helpers/__init__.py +7 -0
- cloudsmith_cli/credential_helpers/backends.py +41 -0
- cloudsmith_cli/credential_helpers/common.py +111 -0
- cloudsmith_cli/credential_helpers/custom_domains.py +281 -0
- cloudsmith_cli/credential_helpers/docker/__init__.py +4 -0
- cloudsmith_cli/credential_helpers/docker/installer.py +349 -0
- cloudsmith_cli/credential_helpers/docker/runtime.py +117 -0
- cloudsmith_cli/credential_helpers/launchers.py +175 -0
- cloudsmith_cli/data/VERSION +1 -0
- cloudsmith_cli/data/config.ini +23 -0
- cloudsmith_cli/data/credentials.ini +14 -0
- cloudsmith_cli/templates/__init__.py +3 -0
- cloudsmith_cli/templates/auth_error.html +45 -0
- cloudsmith_cli/templates/auth_success.html +37 -0
- cloudsmith_cli-1.20.0.dist-info/METADATA +610 -0
- cloudsmith_cli-1.20.0.dist-info/RECORD +130 -0
- cloudsmith_cli-1.20.0.dist-info/WHEEL +5 -0
- cloudsmith_cli-1.20.0.dist-info/entry_points.txt +2 -0
- cloudsmith_cli-1.20.0.dist-info/licenses/LICENSE +201 -0
- cloudsmith_cli-1.20.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""CLI/Commands - Retrieve authentication status."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ...core import keyring
|
|
6
|
+
from ...core.api.exceptions import ApiException
|
|
7
|
+
from ...core.api.user import get_token_metadata, get_user_brief
|
|
8
|
+
from .. import decorators, utils
|
|
9
|
+
from ..exceptions import handle_api_exceptions
|
|
10
|
+
from .main import main
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_active_method(api_config):
|
|
14
|
+
"""Inspect API config to determine SSO, API key, or no auth."""
|
|
15
|
+
headers = getattr(api_config, "headers", {}) or {}
|
|
16
|
+
if headers.get("Authorization", "").startswith("Bearer "):
|
|
17
|
+
return "sso_token"
|
|
18
|
+
if (getattr(api_config, "api_key", {}) or {}).get("X-Api-Key"):
|
|
19
|
+
return "api_key"
|
|
20
|
+
return "none"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_api_key_source(opts):
|
|
24
|
+
"""Determine where the API key was loaded from.
|
|
25
|
+
|
|
26
|
+
Uses the credential provider chain result attached by initialise_api.
|
|
27
|
+
"""
|
|
28
|
+
credential = getattr(opts, "credential", None)
|
|
29
|
+
if credential and credential.auth_type == "api_key":
|
|
30
|
+
return {
|
|
31
|
+
"configured": True,
|
|
32
|
+
"source": credential.source_detail or credential.source_name,
|
|
33
|
+
"source_key": credential.source_name,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {"configured": False, "source": None, "source_key": None}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _get_sso_status(api_host):
|
|
40
|
+
"""Return SSO token status from the system keyring."""
|
|
41
|
+
enabled = keyring.should_use_keyring()
|
|
42
|
+
has_tokens = enabled and keyring.has_sso_tokens(api_host)
|
|
43
|
+
refreshed = keyring.get_refresh_attempted_at(api_host) if has_tokens else None
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
"configured": has_tokens,
|
|
47
|
+
"keyring_enabled": enabled,
|
|
48
|
+
"source": "System Keyring" if has_tokens else None,
|
|
49
|
+
"last_refreshed": utils.fmt_datetime(refreshed) if refreshed else None,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _get_verbose_auth_data(opts, api_host):
|
|
54
|
+
"""Gather all auth details for verbose output."""
|
|
55
|
+
api_key_info = _get_api_key_source(opts)
|
|
56
|
+
sso_info = _get_sso_status(api_host)
|
|
57
|
+
|
|
58
|
+
# Fetch token metadata (extra API call, graceful fallback)
|
|
59
|
+
token_meta = None
|
|
60
|
+
if api_key_info["configured"]:
|
|
61
|
+
try:
|
|
62
|
+
token_meta = get_token_metadata()
|
|
63
|
+
except ApiException:
|
|
64
|
+
token_meta = None
|
|
65
|
+
|
|
66
|
+
created = token_meta.get("created") if token_meta else None
|
|
67
|
+
api_key_info["slug"] = token_meta["slug"] if token_meta else None
|
|
68
|
+
api_key_info["created"] = utils.fmt_datetime(created) if created else None
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
"active_method": _get_active_method(opts.api_config),
|
|
72
|
+
"api_key": api_key_info,
|
|
73
|
+
"sso": sso_info,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _print_user_line(name, username, email):
|
|
78
|
+
"""Print a styled user identity line."""
|
|
79
|
+
styled_name = click.style(name or "Unknown", fg="cyan")
|
|
80
|
+
styled_slug = click.style(username or "Unknown", fg="magenta")
|
|
81
|
+
email_part = f", email: {click.style(email, fg='green')}" if email else ""
|
|
82
|
+
click.echo(f"User: {styled_name} (slug: {styled_slug}{email_part})")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _print_verbose_text(data):
|
|
86
|
+
"""Print verbose authentication details as styled text."""
|
|
87
|
+
click.echo()
|
|
88
|
+
_print_user_line(data["name"], data["username"], data.get("email"))
|
|
89
|
+
|
|
90
|
+
auth = data["auth"]
|
|
91
|
+
active = auth["active_method"]
|
|
92
|
+
ak = auth["api_key"]
|
|
93
|
+
sso = auth["sso"]
|
|
94
|
+
|
|
95
|
+
click.echo()
|
|
96
|
+
if active == "sso_token":
|
|
97
|
+
click.secho("Authentication Method: SSO Token (primary)", fg="cyan", bold=True)
|
|
98
|
+
if sso.get("source"):
|
|
99
|
+
click.echo(f" Source: {sso['source']}")
|
|
100
|
+
if sso.get("last_refreshed"):
|
|
101
|
+
click.echo(
|
|
102
|
+
f" Last Refreshed: {sso['last_refreshed']} (refreshes every 30 min)"
|
|
103
|
+
)
|
|
104
|
+
if ak["configured"]:
|
|
105
|
+
click.echo()
|
|
106
|
+
click.secho("API Key: Also configured", fg="yellow")
|
|
107
|
+
if ak.get("source"):
|
|
108
|
+
click.echo(f" Source: {ak['source']}")
|
|
109
|
+
click.echo(" Note: SSO token is being used instead")
|
|
110
|
+
elif active == "api_key":
|
|
111
|
+
if ak.get("source_key") == "oidc":
|
|
112
|
+
click.secho(
|
|
113
|
+
"Authentication Method: OIDC Auto-Discovery", fg="cyan", bold=True
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
click.secho("Authentication Method: API Key", fg="cyan", bold=True)
|
|
117
|
+
for label, field in [
|
|
118
|
+
("Source", "source"),
|
|
119
|
+
("Token Slug", "slug"),
|
|
120
|
+
("Created", "created"),
|
|
121
|
+
]:
|
|
122
|
+
if ak.get(field):
|
|
123
|
+
click.echo(f" {label}: {ak[field]}")
|
|
124
|
+
else:
|
|
125
|
+
click.secho("Authentication Method: None (anonymous)", fg="yellow", bold=True)
|
|
126
|
+
|
|
127
|
+
if active != "sso_token":
|
|
128
|
+
click.echo()
|
|
129
|
+
if not sso["keyring_enabled"]:
|
|
130
|
+
click.secho(
|
|
131
|
+
"SSO Status: Keyring disabled (CLOUDSMITH_NO_KEYRING)", fg="yellow"
|
|
132
|
+
)
|
|
133
|
+
elif sso["configured"]:
|
|
134
|
+
click.secho("SSO Status: Configured (not active)", fg="yellow")
|
|
135
|
+
click.echo(f" Source: {sso['source']}")
|
|
136
|
+
else:
|
|
137
|
+
click.echo("SSO Status: Not configured")
|
|
138
|
+
click.echo(" Keyring: Enabled (no tokens stored)")
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@main.command()
|
|
142
|
+
@decorators.common_cli_config_options
|
|
143
|
+
@decorators.common_cli_output_options
|
|
144
|
+
@decorators.common_api_auth_options
|
|
145
|
+
@decorators.initialise_api
|
|
146
|
+
@click.pass_context
|
|
147
|
+
def whoami(ctx, opts):
|
|
148
|
+
"""Retrieve your current authentication status."""
|
|
149
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
150
|
+
|
|
151
|
+
click.echo(
|
|
152
|
+
"Retrieving your authentication status from the API ... ",
|
|
153
|
+
nl=False,
|
|
154
|
+
err=use_stderr,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
context_msg = "Failed to retrieve your authentication status!"
|
|
158
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
159
|
+
with utils.maybe_spinner(opts):
|
|
160
|
+
is_auth, username, email, name = get_user_brief()
|
|
161
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
162
|
+
|
|
163
|
+
data = {
|
|
164
|
+
"is_authenticated": is_auth,
|
|
165
|
+
"username": username,
|
|
166
|
+
"email": email,
|
|
167
|
+
"name": name,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if opts.verbose:
|
|
171
|
+
api_host = getattr(opts.api_config, "host", None) or opts.api_host
|
|
172
|
+
data["auth"] = _get_verbose_auth_data(opts, api_host)
|
|
173
|
+
|
|
174
|
+
if utils.maybe_print_as_json(opts, data):
|
|
175
|
+
if not is_auth:
|
|
176
|
+
ctx.exit(1)
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
if not is_auth:
|
|
180
|
+
click.echo("You are authenticated as:")
|
|
181
|
+
click.secho("Nobody (i.e. anonymous user)", fg="yellow")
|
|
182
|
+
ctx.exit(1)
|
|
183
|
+
|
|
184
|
+
if opts.verbose:
|
|
185
|
+
_print_verbose_text(data)
|
|
186
|
+
else:
|
|
187
|
+
click.echo("You are authenticated as:")
|
|
188
|
+
_print_user_line(name, username, email)
|