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,335 @@
|
|
|
1
|
+
"""CLI/Commands - create, retrieve, update or delete license policies."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from ....core.api import orgs as api
|
|
8
|
+
from ....core.pagination import paginate_results
|
|
9
|
+
from ... import command, decorators, utils, validators
|
|
10
|
+
from ...exceptions import handle_api_exceptions
|
|
11
|
+
from ...utils import (
|
|
12
|
+
fmt_bool,
|
|
13
|
+
fmt_datetime,
|
|
14
|
+
maybe_spinner,
|
|
15
|
+
maybe_truncate_list,
|
|
16
|
+
maybe_truncate_string,
|
|
17
|
+
)
|
|
18
|
+
from .command import policy
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def print_license_policies(policies):
|
|
22
|
+
"""Print license policies as a table or output in another format."""
|
|
23
|
+
headers = [
|
|
24
|
+
"Name",
|
|
25
|
+
"Description",
|
|
26
|
+
"Allow Unknown Licenses",
|
|
27
|
+
"Quarantine On Violation",
|
|
28
|
+
"Package Query",
|
|
29
|
+
"SPDX Identifiers",
|
|
30
|
+
"Created",
|
|
31
|
+
"Updated",
|
|
32
|
+
"Identifier",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
rows = [
|
|
36
|
+
[
|
|
37
|
+
click.style(policy["name"], fg="cyan"),
|
|
38
|
+
click.style(policy["description"], fg="yellow"),
|
|
39
|
+
click.style(fmt_bool(policy["allow_unknown_licenses"]), fg="yellow"),
|
|
40
|
+
click.style(fmt_bool(policy["on_violation_quarantine"]), fg="yellow"),
|
|
41
|
+
click.style(
|
|
42
|
+
str(maybe_truncate_string(policy["package_query_string"])),
|
|
43
|
+
fg="yellow",
|
|
44
|
+
),
|
|
45
|
+
click.style(
|
|
46
|
+
str(maybe_truncate_list(policy["spdx_identifiers"])),
|
|
47
|
+
fg="blue",
|
|
48
|
+
),
|
|
49
|
+
click.style(fmt_datetime(policy["created_at"]), fg="blue"),
|
|
50
|
+
click.style(fmt_datetime(policy["updated_at"]), fg="blue"),
|
|
51
|
+
click.style(policy["slug_perm"], fg="green"),
|
|
52
|
+
]
|
|
53
|
+
for policy in policies
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
click.echo()
|
|
57
|
+
utils.pretty_print_table(headers, rows)
|
|
58
|
+
click.echo()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@policy.group(cls=command.AliasGroup, name="license", aliases=[])
|
|
62
|
+
@decorators.common_cli_config_options
|
|
63
|
+
@decorators.common_cli_output_options
|
|
64
|
+
@decorators.common_api_auth_options
|
|
65
|
+
@decorators.initialise_api
|
|
66
|
+
@click.pass_context
|
|
67
|
+
def licence(*args, **kwargs):
|
|
68
|
+
"""
|
|
69
|
+
Manage license policies for an organization.
|
|
70
|
+
|
|
71
|
+
See the help for subcommands for more information on each.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@licence.command(name="list", aliases=["ls"])
|
|
76
|
+
@decorators.common_cli_config_options
|
|
77
|
+
@decorators.common_cli_list_options
|
|
78
|
+
@decorators.common_cli_output_options
|
|
79
|
+
@decorators.common_api_auth_options
|
|
80
|
+
@decorators.initialise_api
|
|
81
|
+
@click.argument(
|
|
82
|
+
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
|
|
83
|
+
)
|
|
84
|
+
@click.pass_context
|
|
85
|
+
def ls(ctx, opts, owner, page, page_size, page_all):
|
|
86
|
+
"""
|
|
87
|
+
List license policies.
|
|
88
|
+
|
|
89
|
+
This requires appropriate permissions for the owner (a member of the
|
|
90
|
+
organisation and a valid API key).
|
|
91
|
+
|
|
92
|
+
- OWNER: Specify the OWNER namespace (i.e. org)
|
|
93
|
+
|
|
94
|
+
Example: 'your-org'
|
|
95
|
+
|
|
96
|
+
Full CLI example:
|
|
97
|
+
|
|
98
|
+
$ cloudsmith policy license list your-org
|
|
99
|
+
"""
|
|
100
|
+
owner = owner[0]
|
|
101
|
+
|
|
102
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
103
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
104
|
+
|
|
105
|
+
click.echo("Getting license policies ... ", nl=False, err=use_stderr)
|
|
106
|
+
|
|
107
|
+
context_msg = "Failed to get license policies!"
|
|
108
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
109
|
+
with maybe_spinner(opts):
|
|
110
|
+
policies, page_info = paginate_results(
|
|
111
|
+
api.list_license_policies, page_all, page, page_size, owner=owner
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
115
|
+
|
|
116
|
+
if utils.maybe_print_as_json(opts, policies, page_info):
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
print_license_policies(policies)
|
|
120
|
+
|
|
121
|
+
click.echo()
|
|
122
|
+
|
|
123
|
+
num_results = len(policies)
|
|
124
|
+
list_suffix = "license polic%s" % ("y" if num_results == 1 else "ies")
|
|
125
|
+
utils.pretty_print_list_info(
|
|
126
|
+
num_results=num_results,
|
|
127
|
+
page_info=None if page_all else page_info,
|
|
128
|
+
suffix=list_suffix,
|
|
129
|
+
page_all=page_all,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@licence.command(aliases=["new"])
|
|
134
|
+
@decorators.common_cli_config_options
|
|
135
|
+
@decorators.common_cli_output_options
|
|
136
|
+
@decorators.common_api_auth_options
|
|
137
|
+
@decorators.initialise_api
|
|
138
|
+
@click.argument("owner", default=None, required=True)
|
|
139
|
+
@click.argument("policy_config_file", type=click.File("rb"), required=True)
|
|
140
|
+
@click.pass_context
|
|
141
|
+
def create(ctx, opts, owner, policy_config_file):
|
|
142
|
+
"""
|
|
143
|
+
Create a new license policy in a namespace.
|
|
144
|
+
|
|
145
|
+
- OWNER: Specify the OWNER namespace (i.e. user or org) where you want
|
|
146
|
+
to create a license policy.
|
|
147
|
+
|
|
148
|
+
Example: 'your-org'
|
|
149
|
+
|
|
150
|
+
- POLICY_CONFIG_FILE: Config file specifying the settings for the
|
|
151
|
+
license policy to be created.
|
|
152
|
+
|
|
153
|
+
\b
|
|
154
|
+
Example:
|
|
155
|
+
{
|
|
156
|
+
"name": "your-license-policy",
|
|
157
|
+
"description": "your license policy description",
|
|
158
|
+
"spdx_identifiers" : ["your_licenses"],
|
|
159
|
+
"package_query_string" : "format:python AND downloads:>50",
|
|
160
|
+
"allow_unknown_licenses": false,
|
|
161
|
+
"quarantine_on_violation": true
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
Full CLI example:
|
|
165
|
+
|
|
166
|
+
$ cloudsmith policy license create your-org policy-config-file.json
|
|
167
|
+
"""
|
|
168
|
+
# Use stderr for messages if the output is something else (e.g. JSON)
|
|
169
|
+
use_stderr = opts.output != "pretty"
|
|
170
|
+
policy_config = json.load(policy_config_file)
|
|
171
|
+
|
|
172
|
+
policy_name = policy_config.get("name", None)
|
|
173
|
+
if policy_name is None:
|
|
174
|
+
raise click.BadParameter(
|
|
175
|
+
"Name is a required field for creating a license policy.", param="name"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
spdx_identifiers = policy_config.get("spdx_identifiers", None)
|
|
179
|
+
if spdx_identifiers is None:
|
|
180
|
+
raise click.BadParameter(
|
|
181
|
+
"SPDX Identifiers is a required field for creating a license policy.",
|
|
182
|
+
param="spdx_identifiers",
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
click.secho(
|
|
186
|
+
"Creating %(name)s license policy for the %(owner)s namespace ..."
|
|
187
|
+
% {
|
|
188
|
+
"name": click.style(policy_name, bold=True),
|
|
189
|
+
"owner": click.style(owner, bold=True),
|
|
190
|
+
},
|
|
191
|
+
nl=False,
|
|
192
|
+
err=use_stderr,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
context_msg = "Failed to create the license policy!"
|
|
196
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
197
|
+
with maybe_spinner(opts):
|
|
198
|
+
policies = [api.create_license_policy(owner, policy_config)]
|
|
199
|
+
|
|
200
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
201
|
+
|
|
202
|
+
if utils.maybe_print_as_json(opts, policies):
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
print_license_policies(policies)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@licence.command()
|
|
209
|
+
@decorators.common_cli_config_options
|
|
210
|
+
@decorators.common_cli_output_options
|
|
211
|
+
@decorators.common_api_auth_options
|
|
212
|
+
@decorators.initialise_api
|
|
213
|
+
@click.argument("owner", default=None, required=True)
|
|
214
|
+
@click.argument("identifier", default=None, required=True)
|
|
215
|
+
@click.argument("policy_config_file", type=click.File("rb"), required=True)
|
|
216
|
+
@click.pass_context
|
|
217
|
+
def update(ctx, opts, owner, identifier, policy_config_file):
|
|
218
|
+
"""
|
|
219
|
+
Update a license policy.
|
|
220
|
+
|
|
221
|
+
- OWNER: Specify the OWNER namespace (i.e. user or org) where you want
|
|
222
|
+
to update a license policy.
|
|
223
|
+
|
|
224
|
+
Example: 'your-org'
|
|
225
|
+
|
|
226
|
+
- IDENTIFIER: Specify the license policy IDENTIFIER (i.e. slug_perm)
|
|
227
|
+
for the license policy which you wish to update.
|
|
228
|
+
|
|
229
|
+
Example: 'your-license-policy'
|
|
230
|
+
|
|
231
|
+
- POLICY_CONFIG_FILE: Config file specifying the settings for the
|
|
232
|
+
license policy to be updated.
|
|
233
|
+
|
|
234
|
+
\b
|
|
235
|
+
Example:
|
|
236
|
+
{
|
|
237
|
+
"name": "your-license-policy",
|
|
238
|
+
"description": "your license policy description",
|
|
239
|
+
"spdx_identifiers" : ["your_licenses"],
|
|
240
|
+
"package_query_string" : "format:python AND downloads:>50",
|
|
241
|
+
"allow_unknown_licenses": false,
|
|
242
|
+
"quarantine_on_violation": true
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
Full CLI example:
|
|
246
|
+
|
|
247
|
+
$ cloudsmith policy license update your-org your-license-policy policy-config-file.json
|
|
248
|
+
"""
|
|
249
|
+
# Use stderr for message if the output is something else (e.g. JSON)
|
|
250
|
+
use_stderr = opts.output != "pretty"
|
|
251
|
+
|
|
252
|
+
policy_config = json.load(policy_config_file)
|
|
253
|
+
|
|
254
|
+
click.secho(
|
|
255
|
+
"Updating %(slug_perm)s license policy in the %(owner)s namespace ..."
|
|
256
|
+
% {
|
|
257
|
+
"slug_perm": click.style(identifier, bold=True),
|
|
258
|
+
"owner": click.style(owner, bold=True),
|
|
259
|
+
},
|
|
260
|
+
nl=False,
|
|
261
|
+
err=use_stderr,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
context_msg = "Failed to update the license policy!"
|
|
265
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
266
|
+
with maybe_spinner(opts):
|
|
267
|
+
policies = [api.update_license_policy(owner, identifier, policy_config)]
|
|
268
|
+
|
|
269
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
270
|
+
|
|
271
|
+
if utils.maybe_print_as_json(opts, policies):
|
|
272
|
+
return
|
|
273
|
+
|
|
274
|
+
print_license_policies(policies)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@licence.command(aliases=["rm"])
|
|
278
|
+
@decorators.common_cli_config_options
|
|
279
|
+
@decorators.common_cli_output_options
|
|
280
|
+
@decorators.common_api_auth_options
|
|
281
|
+
@decorators.initialise_api
|
|
282
|
+
@click.argument("owner", metavar="OWNER")
|
|
283
|
+
@click.argument("identifier", default=None, required=True)
|
|
284
|
+
@click.option(
|
|
285
|
+
"-y",
|
|
286
|
+
"--yes",
|
|
287
|
+
default=False,
|
|
288
|
+
is_flag=True,
|
|
289
|
+
help="Assume yes as default answer to questions (this is dangerous!)",
|
|
290
|
+
)
|
|
291
|
+
@click.pass_context
|
|
292
|
+
def delete(ctx, opts, owner, identifier, yes):
|
|
293
|
+
"""
|
|
294
|
+
Delete a license policy from a namespace.
|
|
295
|
+
|
|
296
|
+
- OWNER: Specify the OWNER namespace (i.e. org).
|
|
297
|
+
|
|
298
|
+
Example: 'your-org'
|
|
299
|
+
|
|
300
|
+
- IDENTIFIER: Specify the license policy IDENTIFIER (i.e. slug_perm)
|
|
301
|
+
for the license policy which you wish to delete.
|
|
302
|
+
|
|
303
|
+
Example: 'your-license-policy'
|
|
304
|
+
|
|
305
|
+
Full CLI example:
|
|
306
|
+
|
|
307
|
+
$ cloudsmith policy license delete your-org your-license-policy
|
|
308
|
+
"""
|
|
309
|
+
|
|
310
|
+
delete_args = {
|
|
311
|
+
"namespace": click.style(owner, bold=True),
|
|
312
|
+
"slug_perm": click.style(identifier, bold=True),
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
prompt = (
|
|
316
|
+
"delete the %(slug_perm)s license policy from the %(namespace)s namespace"
|
|
317
|
+
% delete_args
|
|
318
|
+
)
|
|
319
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
320
|
+
|
|
321
|
+
if not utils.confirm_operation(prompt, assume_yes=yes, err=use_stderr):
|
|
322
|
+
return
|
|
323
|
+
|
|
324
|
+
click.secho(
|
|
325
|
+
"Deleting %(slug_perm)s from the %(namespace)s namespace ... " % delete_args,
|
|
326
|
+
nl=False,
|
|
327
|
+
err=use_stderr,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
context_msg = "Failed to delete the license policy!"
|
|
331
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
332
|
+
with maybe_spinner(opts):
|
|
333
|
+
api.delete_license_policy(owner=owner, slug_perm=identifier)
|
|
334
|
+
|
|
335
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"""CLI/Commands - Import all vulnerability policy commands."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from ....core.api import orgs as api
|
|
8
|
+
from ....core.pagination import paginate_results
|
|
9
|
+
from ... import command, decorators, utils, validators
|
|
10
|
+
from ...exceptions import handle_api_exceptions
|
|
11
|
+
from ...utils import fmt_bool, fmt_datetime, maybe_spinner, maybe_truncate_string
|
|
12
|
+
from .command import policy
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def print_vulnerability_policies(policies):
|
|
16
|
+
headers = [
|
|
17
|
+
"Name",
|
|
18
|
+
"Description",
|
|
19
|
+
"Min Severity",
|
|
20
|
+
"Allow Unknown Severity",
|
|
21
|
+
"Quarantine On Violation",
|
|
22
|
+
"Package Query",
|
|
23
|
+
"Created",
|
|
24
|
+
"Updated",
|
|
25
|
+
"Identifier",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
rows = [
|
|
29
|
+
[
|
|
30
|
+
click.style(policy["name"], fg="cyan"),
|
|
31
|
+
click.style(policy["description"], fg="magenta"),
|
|
32
|
+
click.style(policy["min_severity"], fg="yellow"),
|
|
33
|
+
click.style(fmt_bool(policy["allow_unknown_severity"]), fg="yellow"),
|
|
34
|
+
click.style(fmt_bool(policy["on_violation_quarantine"]), fg="yellow"),
|
|
35
|
+
click.style(
|
|
36
|
+
str(maybe_truncate_string(policy["package_query_string"])),
|
|
37
|
+
fg="yellow",
|
|
38
|
+
),
|
|
39
|
+
click.style(fmt_datetime(policy["created_at"]), fg="blue"),
|
|
40
|
+
click.style(fmt_datetime(policy["updated_at"]), fg="blue"),
|
|
41
|
+
click.style(policy["slug_perm"], fg="green"),
|
|
42
|
+
]
|
|
43
|
+
for policy in policies
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
click.echo()
|
|
47
|
+
utils.pretty_print_table(headers, rows, title="Vulnerability Policies")
|
|
48
|
+
click.echo()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@policy.group(cls=command.AliasGroup, name="vulnerability", aliases=[])
|
|
52
|
+
@decorators.common_cli_config_options
|
|
53
|
+
@decorators.common_cli_output_options
|
|
54
|
+
@decorators.common_api_auth_options
|
|
55
|
+
@decorators.initialise_api
|
|
56
|
+
@click.pass_context
|
|
57
|
+
def vulnerability(*args, **kwargs):
|
|
58
|
+
"""
|
|
59
|
+
Manage vulnerability policies for an organization.
|
|
60
|
+
|
|
61
|
+
See the help for subcommands for more information on each.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@vulnerability.command(name="list", aliases=["ls"])
|
|
66
|
+
@decorators.common_cli_config_options
|
|
67
|
+
@decorators.common_cli_list_options
|
|
68
|
+
@decorators.common_cli_output_options
|
|
69
|
+
@decorators.common_api_auth_options
|
|
70
|
+
@decorators.initialise_api
|
|
71
|
+
@click.argument(
|
|
72
|
+
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
|
|
73
|
+
)
|
|
74
|
+
@click.pass_context
|
|
75
|
+
def ls(ctx, opts, owner, page, page_size, page_all):
|
|
76
|
+
"""
|
|
77
|
+
List vulnerability policies.
|
|
78
|
+
|
|
79
|
+
This requires appropriate permissions for the owner (a member of the
|
|
80
|
+
organisation and a valid API key).
|
|
81
|
+
|
|
82
|
+
- OWNER: Specify the OWNER namespace (i.e. org)
|
|
83
|
+
|
|
84
|
+
Example: 'your-org'
|
|
85
|
+
|
|
86
|
+
Full CLI example:
|
|
87
|
+
|
|
88
|
+
$ cloudsmith policy vulnerability list your-org
|
|
89
|
+
"""
|
|
90
|
+
owner = owner[0]
|
|
91
|
+
|
|
92
|
+
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
93
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
94
|
+
|
|
95
|
+
click.echo("Getting vulnerability policies ... ", nl=False, err=use_stderr)
|
|
96
|
+
|
|
97
|
+
context_msg = "Failed to get package vulnerability policies!"
|
|
98
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
99
|
+
with maybe_spinner(opts):
|
|
100
|
+
policies, page_info = paginate_results(
|
|
101
|
+
api.list_vulnerability_policies, page_all, page, page_size, owner=owner
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
105
|
+
|
|
106
|
+
if utils.maybe_print_as_json(opts, policies, page_info):
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
print_vulnerability_policies(policies)
|
|
110
|
+
|
|
111
|
+
click.echo()
|
|
112
|
+
|
|
113
|
+
num_results = len(policies)
|
|
114
|
+
list_suffix = "vulnerability polic%s" % ("y" if num_results == 1 else "ies")
|
|
115
|
+
utils.pretty_print_list_info(
|
|
116
|
+
num_results=num_results,
|
|
117
|
+
page_info=None if page_all else page_info,
|
|
118
|
+
suffix=list_suffix,
|
|
119
|
+
page_all=page_all,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@vulnerability.command(aliases=["new"])
|
|
124
|
+
@decorators.common_cli_config_options
|
|
125
|
+
@decorators.common_cli_output_options
|
|
126
|
+
@decorators.common_api_auth_options
|
|
127
|
+
@decorators.initialise_api
|
|
128
|
+
@click.argument("owner", default=None, required=True)
|
|
129
|
+
@click.argument("policy_config_file", type=click.File("rb"), required=True)
|
|
130
|
+
@click.pass_context
|
|
131
|
+
def create(ctx, opts, owner, policy_config_file):
|
|
132
|
+
"""
|
|
133
|
+
Create a new vulnerability policy in a namespace.
|
|
134
|
+
|
|
135
|
+
- OWNER: Specify the OWNER namespace (i.e. user or org) where you want
|
|
136
|
+
to create a vulnerability policy.
|
|
137
|
+
|
|
138
|
+
Example: 'your-org'
|
|
139
|
+
|
|
140
|
+
- POLICY_CONFIG_FILE: Config file specifying the settings for the
|
|
141
|
+
vulnerability policy to be created.
|
|
142
|
+
|
|
143
|
+
\b
|
|
144
|
+
Example:
|
|
145
|
+
{
|
|
146
|
+
"name": "your-vulnerability-policy",
|
|
147
|
+
"description": "your vulnerability policy description",
|
|
148
|
+
"min_severity": "Critical",
|
|
149
|
+
"package_query_string" : "format:python AND downloads:>50",
|
|
150
|
+
"allow_unknown_severity": false,
|
|
151
|
+
"quarantine_on_violation": true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
Full CLI example:
|
|
155
|
+
|
|
156
|
+
$ cloudsmith policy vulnerability create your-org policy-config-file.json
|
|
157
|
+
"""
|
|
158
|
+
# Use stderr for messages if the output is something else (e.g. JSON)
|
|
159
|
+
use_stderr = opts.output != "pretty"
|
|
160
|
+
policy_config = json.load(policy_config_file)
|
|
161
|
+
|
|
162
|
+
policy_name = policy_config.get("name", None)
|
|
163
|
+
if policy_name is None:
|
|
164
|
+
raise click.BadParameter(
|
|
165
|
+
"Name is a required field for creating a vulnerability policy.",
|
|
166
|
+
param="name",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
click.secho(
|
|
170
|
+
"Creating %(name)s vulnerability policy for the %(owner)s namespace ..."
|
|
171
|
+
% {
|
|
172
|
+
"name": click.style(policy_name, bold=True),
|
|
173
|
+
"owner": click.style(owner, bold=True),
|
|
174
|
+
},
|
|
175
|
+
nl=False,
|
|
176
|
+
err=use_stderr,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
context_msg = "Failed to create the vulnerability policy!"
|
|
180
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
181
|
+
with maybe_spinner(opts):
|
|
182
|
+
policies = [api.create_vulnerability_policy(owner, policy_config)]
|
|
183
|
+
|
|
184
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
185
|
+
|
|
186
|
+
if utils.maybe_print_as_json(opts, policies):
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
print_vulnerability_policies(policies)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@vulnerability.command()
|
|
193
|
+
@decorators.common_cli_config_options
|
|
194
|
+
@decorators.common_cli_output_options
|
|
195
|
+
@decorators.common_api_auth_options
|
|
196
|
+
@decorators.initialise_api
|
|
197
|
+
@click.argument("owner", default=None, required=True)
|
|
198
|
+
@click.argument("identifier", default=None, required=True)
|
|
199
|
+
@click.argument("policy_config_file", type=click.File("rb"), required=True)
|
|
200
|
+
@click.pass_context
|
|
201
|
+
def update(ctx, opts, owner, identifier, policy_config_file):
|
|
202
|
+
"""
|
|
203
|
+
Update a vulnerability policy.
|
|
204
|
+
|
|
205
|
+
- OWNER: Specify the OWNER namespace (i.e. user or org) where you want
|
|
206
|
+
to update a vulnerability policy.
|
|
207
|
+
|
|
208
|
+
Example: 'your-org'
|
|
209
|
+
|
|
210
|
+
- IDENTIFIER: Specify the vulnerability policy IDENTIFIER (i.e. slug_perm)
|
|
211
|
+
for the vulnerability policy which you wish to update.
|
|
212
|
+
|
|
213
|
+
Example: 'your-vulnerability-policy'
|
|
214
|
+
|
|
215
|
+
- POLICY_CONFIG_FILE: Config file specifying the settings for the
|
|
216
|
+
vulnerability policy to be updated.
|
|
217
|
+
|
|
218
|
+
\b
|
|
219
|
+
Example:
|
|
220
|
+
{
|
|
221
|
+
"name": "your-vulnerability-policy",
|
|
222
|
+
"description": "your vulnerability policy description",
|
|
223
|
+
"min_severity": "Critical",
|
|
224
|
+
"package_query_string" : "format:python AND downloads:>50",
|
|
225
|
+
"allow_unknown_severity": false,
|
|
226
|
+
"quarantine_on_violation": true
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
Full CLI example:
|
|
230
|
+
|
|
231
|
+
$ cloudsmith policy vulnerability update your-org your-vulnerability-policy policy-config-file.json
|
|
232
|
+
"""
|
|
233
|
+
# Use stderr for message if the output is something else (e.g. JSON)
|
|
234
|
+
use_stderr = opts.output != "pretty"
|
|
235
|
+
|
|
236
|
+
policy_config = json.load(policy_config_file)
|
|
237
|
+
|
|
238
|
+
click.secho(
|
|
239
|
+
"Updating %(slug_perm)s vulnerability policy in the %(owner)s namespace ..."
|
|
240
|
+
% {
|
|
241
|
+
"slug_perm": click.style(identifier, bold=True),
|
|
242
|
+
"owner": click.style(owner, bold=True),
|
|
243
|
+
},
|
|
244
|
+
nl=False,
|
|
245
|
+
err=use_stderr,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
context_msg = "Failed to update the vulnerability policy!"
|
|
249
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
250
|
+
with maybe_spinner(opts):
|
|
251
|
+
policies = [
|
|
252
|
+
api.update_vulnerability_policy(owner, identifier, policy_config)
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
click.secho("OK", fg="green", err=use_stderr)
|
|
256
|
+
|
|
257
|
+
if utils.maybe_print_as_json(opts, policies):
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
print_vulnerability_policies(policies)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@vulnerability.command(aliases=["rm"])
|
|
264
|
+
@decorators.common_cli_config_options
|
|
265
|
+
@decorators.common_cli_output_options
|
|
266
|
+
@decorators.common_api_auth_options
|
|
267
|
+
@decorators.initialise_api
|
|
268
|
+
@click.argument("owner", metavar="OWNER")
|
|
269
|
+
@click.argument("identifier", default=None, required=True)
|
|
270
|
+
@click.option(
|
|
271
|
+
"-y",
|
|
272
|
+
"--yes",
|
|
273
|
+
default=False,
|
|
274
|
+
is_flag=True,
|
|
275
|
+
help="Assume yes as default answer to questions (this is dangerous!)",
|
|
276
|
+
)
|
|
277
|
+
@click.pass_context
|
|
278
|
+
def delete(ctx, opts, owner, identifier, yes):
|
|
279
|
+
"""
|
|
280
|
+
Delete a vulnerability policy from a namespace.
|
|
281
|
+
|
|
282
|
+
- OWNER: Specify the OWNER namespace (i.e. org).
|
|
283
|
+
|
|
284
|
+
Example: 'your-org'
|
|
285
|
+
|
|
286
|
+
- IDENTIFIER: Specify the vulnerability policy IDENTIFIER (i.e. slug_perm)
|
|
287
|
+
for the vulnerability policy which you wish to delete.
|
|
288
|
+
|
|
289
|
+
Example: 'your-vulnerability-policy'
|
|
290
|
+
|
|
291
|
+
Full CLI example:
|
|
292
|
+
|
|
293
|
+
$ cloudsmith policy vulnerability delete your-org your-vulnerability-policy
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
delete_args = {
|
|
297
|
+
"namespace": click.style(owner, bold=True),
|
|
298
|
+
"slug_perm": click.style(identifier, bold=True),
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
prompt = (
|
|
302
|
+
"delete the %(slug_perm)s vulnerability policy from the %(namespace)s namespace"
|
|
303
|
+
% delete_args
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
use_stderr = utils.should_use_stderr(opts)
|
|
307
|
+
|
|
308
|
+
if not utils.confirm_operation(prompt, assume_yes=yes, err=use_stderr):
|
|
309
|
+
return
|
|
310
|
+
|
|
311
|
+
click.secho(
|
|
312
|
+
"Deleting %(slug_perm)s from the %(namespace)s namespace ... " % delete_args,
|
|
313
|
+
nl=False,
|
|
314
|
+
err=use_stderr,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
context_msg = "Failed to delete the vulnerability policy!"
|
|
318
|
+
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
319
|
+
with maybe_spinner(opts):
|
|
320
|
+
api.delete_vulnerability_policy(owner=owner, slug_perm=identifier)
|
|
321
|
+
|
|
322
|
+
click.secho("OK", fg="green", err=use_stderr)
|