Skip to content

Commit 9672fae

Browse files
committed
Add support to vuln report for pulp_python plugin
closes: #1272
1 parent 9be8871 commit 9672fae

File tree

8 files changed

+148
-1
lines changed

8 files changed

+148
-1
lines changed

CHANGES/1272.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added support to vulnerability report for pulp_python plugin.

pulp-glue/pulp_glue/common/context.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,9 @@ def needs_capability(self, capability: str) -> None:
12841284
)
12851285
)
12861286

1287+
def scan(self) -> t.Any:
1288+
return self.call("scan", parameters={self.HREF: self.pulp_href})
1289+
12871290

12881291
class PulpRemoteContext(PulpEntityContext):
12891292
"""

pulp-glue/pulp_glue/core/context.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,11 @@ def find(self, **kwargs: t.Any) -> t.Any:
613613

614614
def replicate(self) -> t.Any:
615615
return self.call("replicate", parameters={self.HREF: self.pulp_href})
616+
617+
618+
class PulpVulnerabilityReportContext(PulpEntityContext):
619+
ENTITY = _("vulnerability report")
620+
ENTITIES = _("vulnerability reports")
621+
ID_PREFIX = "vuln_report"
622+
HREF = "vulnerability_report_href"
623+
NEEDS_PLUGINS = [PluginRequirement("core", specifier=">=3.85.3")]

pulp-glue/pulp_glue/python/context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class PulpPythonRepositoryVersionContext(PulpRepositoryVersionContext):
101101
HREF = "python_python_repository_version_href"
102102
ID_PREFIX = "repositories_python_python_versions"
103103
NEEDS_PLUGINS = [PluginRequirement("python", specifier=">=3.1.0")]
104+
CAPABILITIES = {"scan": [PluginRequirement("python", specifier=">=3.21.0")]}
104105

105106

106107
class PulpPythonRepositoryContext(PulpRepositoryContext):

pulp_cli/generic.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1521,11 +1521,33 @@ def callback(entity_ctx: PulpEntityContext, /) -> None:
15211521
return callback
15221522

15231523

1524+
def scan_command(**kwargs: t.Any) -> click.Command:
1525+
"""A factory that creates a scan command."""
1526+
1527+
kwargs.setdefault("name", "scan")
1528+
kwargs.setdefault("help", _("Verify repository version package vulnerabilities."))
1529+
decorators = kwargs.pop("decorators", [])
1530+
1531+
@pulp_command(**kwargs)
1532+
@pass_entity_context
1533+
def callback(entity_ctx: PulpEntityContext, /) -> None:
1534+
"""
1535+
Scan a {entity}.
1536+
"""
1537+
entity_ctx.needs_capability("scan")
1538+
entity_ctx.scan()
1539+
1540+
for option in decorators:
1541+
# Decorate callback
1542+
callback = option(callback)
1543+
return callback
1544+
1545+
15241546
def version_command(**kwargs: t.Any) -> click.Command:
15251547
"""
15261548
A factory that creates a repository version command group.
15271549
1528-
This group contains `list`, `show`, `destroy` and `repair` subcommands.
1550+
This group contains `list`, `show`, `destroy`, `repair` and `scan` subcommands.
15291551
If `list_only=True` is passed, only the `list` command will be instantiated.
15301552
Repository lookup options can be provided in `decorators`.
15311553
"""
@@ -1545,6 +1567,7 @@ def callback(ctx: click.Context, repository_ctx: PulpRepositoryContext, /) -> No
15451567
if not list_only:
15461568
callback.add_command(show_command(decorators=decorators + [version_option]))
15471569
callback.add_command(destroy_command(decorators=decorators + [version_option]))
1570+
callback.add_command(scan_command(decorators=decorators + [version_option]))
15481571

15491572
@callback.command()
15501573
@repository_lookup_option

pulpcore/cli/core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from pulpcore.cli.core.upload import upload
2626
from pulpcore.cli.core.upstream_pulp import upstream_pulp
2727
from pulpcore.cli.core.user import user
28+
from pulpcore.cli.core.vulnerability_report import vulnerability_report
2829
from pulpcore.cli.core.worker import worker
2930

3031

@@ -52,6 +53,7 @@ def mount(main: click.Group, **kwargs: t.Any) -> None:
5253
main.add_command(upload)
5354
main.add_command(upstream_pulp)
5455
main.add_command(user)
56+
main.add_command(vulnerability_report)
5557
main.add_command(worker)
5658

5759
_orig_get_command = main.get_command
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import typing as t
2+
3+
import click
4+
from pulp_glue.common.context import PulpRepositoryContext
5+
from pulp_glue.common.exceptions import PulpException
6+
from pulp_glue.common.i18n import get_translation
7+
from pulp_glue.core.context import PulpVulnerabilityReportContext
8+
from pulp_glue.python.context import PulpPythonRepositoryVersionContext
9+
10+
from pulpcore.cli.common.generic import (
11+
PulpCLIContext,
12+
href_option,
13+
list_command,
14+
pass_pulp_context,
15+
pulp_group,
16+
resource_option,
17+
show_command,
18+
)
19+
20+
translation = get_translation(__package__)
21+
_ = translation.gettext
22+
23+
lookup_options = [href_option]
24+
25+
repository_option = resource_option(
26+
"--repository",
27+
default_plugin="python",
28+
default_type="python",
29+
context_table=PulpRepositoryContext.TYPE_REGISTRY,
30+
href_pattern=PulpRepositoryContext.HREF_PATTERN,
31+
help=_("Repository to scan in the form '[<plugin>:<resource_type>:]<name>' or by href."),
32+
required=True,
33+
)
34+
35+
36+
@pulp_group()
37+
@pass_pulp_context
38+
@click.pass_context
39+
def vulnerability_report(ctx: click.Context, pulp_ctx: PulpCLIContext, /) -> None:
40+
ctx.obj = PulpVulnerabilityReportContext(pulp_ctx)
41+
42+
43+
vulnerability_report.add_command(list_command())
44+
vulnerability_report.add_command(show_command(decorators=lookup_options))
45+
46+
47+
@vulnerability_report.command()
48+
@repository_option
49+
@click.option(
50+
"--version",
51+
type=int,
52+
help=_("Version of the repository to scan. Leave blank for latest version."),
53+
)
54+
@pass_pulp_context
55+
def create(
56+
pulp_ctx: PulpCLIContext,
57+
/,
58+
repository: PulpRepositoryContext,
59+
version: t.Optional[int],
60+
) -> None:
61+
62+
if version is None:
63+
version_ctx = t.cast(PulpPythonRepositoryVersionContext, repository.get_version_context())
64+
# fetch repository to get the latest version
65+
repo_data = repository.show()
66+
version_ctx.pulp_href = repo_data["latest_version_href"]
67+
else:
68+
version_ctx = t.cast(
69+
PulpPythonRepositoryVersionContext, repository.get_version_context(version)
70+
)
71+
72+
if version_ctx.capable("scan"):
73+
result = version_ctx.scan()
74+
pulp_ctx.output_result(result)
75+
else:
76+
raise PulpException(
77+
_("Capability '{capability}' needed on '{entity}' for this command.").format(
78+
capability="scan",
79+
entity=version_ctx.ID_PREFIX,
80+
)
81+
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
set -eu
4+
# shellcheck source=tests/scripts/config.source
5+
. "$(dirname "$(dirname "$(realpath "$0")")")"/config.source
6+
7+
cleanup() {
8+
pulp python repository destroy --name python || true
9+
pulp python remote destroy --name python || true
10+
pulp orphan cleanup --protection-time=0
11+
}
12+
trap cleanup EXIT
13+
14+
# create a test repository
15+
pulp python repository create --name python
16+
pulp python remote create --name python --url "https://pypi.org/" --includes '["django==5.2.1"]'
17+
pulp python repository sync --name python --remote python
18+
19+
REPO_VERSION=$(pulp python repository show --name python|jq -r .pulp_href)
20+
expect_succ pulp vulnerability-report create --repository "$REPO_VERSION"
21+
expect_succ pulp vulnerability-report list
22+
23+
VULN_REPORT=$(pulp vulnerability-report list --field pulp_href --limit 1|jq .[0].pulp_href -r)
24+
expect_succ pulp vulnerability-report show --href "$VULN_REPORT"
25+
26+
# test with non-implemented content type
27+
pulp file repository create --name file-repo
28+
expect_fail pulp file repository version scan --repository file-repo

0 commit comments

Comments
 (0)