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,171 @@
|
|
|
1
|
+
import getpass
|
|
2
|
+
import os
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
|
+
|
|
5
|
+
import keyring
|
|
6
|
+
from keyring.errors import KeyringError
|
|
7
|
+
|
|
8
|
+
ACCESS_TOKEN_KEY = "cloudsmith_cli-access_token-{api_host}"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def should_use_keyring():
|
|
12
|
+
"""Check if keyring should be used based on CLOUDSMITH_NO_KEYRING env var."""
|
|
13
|
+
env_value = os.environ.get("CLOUDSMITH_NO_KEYRING", "").strip().lower()
|
|
14
|
+
return env_value not in ("1", "true", "yes")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
ACCESS_TOKEN_REFRESH_ATTEMPTED_AT_KEY = (
|
|
18
|
+
"cloudsmith_cli-access_token_refresh_attempted_at-{api_host}"
|
|
19
|
+
)
|
|
20
|
+
REFRESH_TOKEN_KEY = "cloudsmith_cli-refresh_token-{api_host}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_username():
|
|
24
|
+
return getpass.getuser()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _get_value(key):
|
|
28
|
+
username = _get_username()
|
|
29
|
+
try:
|
|
30
|
+
return keyring.get_password(key, username)
|
|
31
|
+
except KeyringError:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _set_value(key, value):
|
|
36
|
+
username = _get_username()
|
|
37
|
+
keyring.set_password(key, username, value)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def store_access_token(api_host, access_token):
|
|
41
|
+
key = ACCESS_TOKEN_KEY.format(api_host=api_host)
|
|
42
|
+
_set_value(key, access_token)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_access_token(api_host):
|
|
46
|
+
if not should_use_keyring():
|
|
47
|
+
return None
|
|
48
|
+
key = ACCESS_TOKEN_KEY.format(api_host=api_host)
|
|
49
|
+
return _get_value(key)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def update_refresh_attempted_at(api_host, refresh_time=None):
|
|
53
|
+
if refresh_time is None:
|
|
54
|
+
refresh_time = datetime.utcnow()
|
|
55
|
+
|
|
56
|
+
refresh_attempted_at_value = refresh_time.isoformat()
|
|
57
|
+
|
|
58
|
+
key = ACCESS_TOKEN_REFRESH_ATTEMPTED_AT_KEY.format(api_host=api_host)
|
|
59
|
+
_set_value(key, refresh_attempted_at_value)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_refresh_attempted_at(api_host):
|
|
63
|
+
key = ACCESS_TOKEN_REFRESH_ATTEMPTED_AT_KEY.format(api_host=api_host)
|
|
64
|
+
value = _get_value(key)
|
|
65
|
+
|
|
66
|
+
if not value:
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
return datetime.fromisoformat(value)
|
|
71
|
+
except ValueError:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def should_refresh_access_token(api_host):
|
|
76
|
+
if not should_use_keyring():
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
token_refreshed_at = get_refresh_attempted_at(api_host)
|
|
80
|
+
|
|
81
|
+
if token_refreshed_at:
|
|
82
|
+
return token_refreshed_at < (datetime.utcnow() - timedelta(minutes=30))
|
|
83
|
+
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def store_refresh_token(api_host, refresh_token):
|
|
88
|
+
key = REFRESH_TOKEN_KEY.format(api_host=api_host)
|
|
89
|
+
_set_value(key, refresh_token)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def get_refresh_token(api_host):
|
|
93
|
+
key = REFRESH_TOKEN_KEY.format(api_host=api_host)
|
|
94
|
+
return _get_value(key)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def store_sso_tokens(api_host, access_token, refresh_token):
|
|
98
|
+
"""Store SSO tokens in keyring if enabled."""
|
|
99
|
+
if not should_use_keyring():
|
|
100
|
+
return False
|
|
101
|
+
|
|
102
|
+
if access_token:
|
|
103
|
+
store_access_token(api_host=api_host, access_token=access_token)
|
|
104
|
+
update_refresh_attempted_at(api_host=api_host)
|
|
105
|
+
|
|
106
|
+
if refresh_token:
|
|
107
|
+
store_refresh_token(api_host=api_host, refresh_token=refresh_token)
|
|
108
|
+
|
|
109
|
+
return True
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _delete_value(key):
|
|
113
|
+
username = _get_username()
|
|
114
|
+
try:
|
|
115
|
+
keyring.delete_password(key, username)
|
|
116
|
+
return True
|
|
117
|
+
except KeyringError:
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _sso_keys(api_host):
|
|
122
|
+
"""Return the keyring service names for all SSO-related entries."""
|
|
123
|
+
return [
|
|
124
|
+
ACCESS_TOKEN_KEY.format(api_host=api_host),
|
|
125
|
+
REFRESH_TOKEN_KEY.format(api_host=api_host),
|
|
126
|
+
ACCESS_TOKEN_REFRESH_ATTEMPTED_AT_KEY.format(api_host=api_host),
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def has_sso_tokens(api_host):
|
|
131
|
+
"""Check if any SSO tokens exist in the keyring for the given host."""
|
|
132
|
+
if not should_use_keyring():
|
|
133
|
+
return False
|
|
134
|
+
return any(_get_value(key) for key in _sso_keys(api_host))
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def delete_sso_tokens(api_host):
|
|
138
|
+
"""Delete all SSO tokens from the keyring for the given host."""
|
|
139
|
+
results = [_delete_value(key) for key in _sso_keys(api_host)]
|
|
140
|
+
return any(results)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
OIDC_TOKEN_KEY = "cloudsmith_cli-oidc_token-{api_host}-{org}-{service_slug}"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def store_oidc_token(api_host, org, service_slug, token_data):
|
|
147
|
+
"""Store OIDC token in keyring if enabled."""
|
|
148
|
+
if not should_use_keyring():
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
key = OIDC_TOKEN_KEY.format(api_host=api_host, org=org, service_slug=service_slug)
|
|
152
|
+
try:
|
|
153
|
+
_set_value(key, token_data)
|
|
154
|
+
return True
|
|
155
|
+
except KeyringError:
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_oidc_token(api_host, org, service_slug):
|
|
160
|
+
"""Retrieve OIDC token from keyring."""
|
|
161
|
+
if not should_use_keyring():
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
key = OIDC_TOKEN_KEY.format(api_host=api_host, org=org, service_slug=service_slug)
|
|
165
|
+
return _get_value(key)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def delete_oidc_token(api_host, org, service_slug):
|
|
169
|
+
"""Delete OIDC token from keyring."""
|
|
170
|
+
key = OIDC_TOKEN_KEY.format(api_host=api_host, org=org, service_slug=service_slug)
|
|
171
|
+
return _delete_value(key)
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class OpenAPITool:
|
|
7
|
+
"""Represents a tool generated from OpenAPI spec"""
|
|
8
|
+
|
|
9
|
+
name: str
|
|
10
|
+
description: str
|
|
11
|
+
method: str
|
|
12
|
+
path: str
|
|
13
|
+
parameters: dict[str, Any]
|
|
14
|
+
base_url: str
|
|
15
|
+
query_filter: str | None
|
|
16
|
+
is_destructive: bool = False
|
|
17
|
+
is_read_only: bool = False
|