Skip to content

Commit e61c69c

Browse files
author
Trong Nhan Mai
committed
fix: use artifact filenames as keys for verifying jfrog assets in provenance_witness_l1_check
Signed-off-by: Trong Nhan Mai <trong.nhan.mai@oracle.com>
1 parent 429ba95 commit e61c69c

File tree

3 files changed

+161
-20
lines changed

3 files changed

+161
-20
lines changed

src/macaron/slsa_analyzer/checks/provenance_witness_l1_check.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,15 @@ def verify_artifact_assets(
7373
look_up: dict[str, dict[str, InTotoV01Subject]] = {}
7474

7575
for subject in subjects:
76-
if subject["name"] not in look_up:
77-
look_up[subject["name"]] = {}
78-
look_up[subject["name"]][subject["digest"]["sha256"]] = subject
76+
# Get the artifact name, which should be the last part of the artifact subject value.
77+
_, _, artifact_filename = subject["name"].rpartition("/")
78+
if artifact_filename not in look_up:
79+
look_up[artifact_filename] = {}
80+
look_up[artifact_filename][subject["digest"]["sha256"]] = subject
7981

8082
for asset in artifact_assets:
8183
if asset.name not in look_up:
82-
message = f"Could not find subject with name {asset.name} in the provenance."
84+
message = f"Could not find subject for asset {asset.name} in the provenance."
8385
logger.info(message)
8486
return False
8587

src/macaron/slsa_analyzer/provenance/witness/__init__.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,6 @@ def is_witness_provenance_payload(
8282
return isinstance(payload, InTotoV01Payload) and payload.statement["predicateType"] in predicate_types
8383

8484

85-
class WitnessProvenanceSubject(NamedTuple):
86-
"""A helper class to store elements of the ``subject`` list in the provenances."""
87-
88-
#: The ``"name"`` field of each ``subject``.
89-
subject_name: str
90-
#: The SHA256 digest of the corresponding asset to the subject.
91-
sha256_digest: str
92-
93-
@property
94-
def artifact_name(self) -> str:
95-
"""Get the artifact name, which should be the last part of the subject."""
96-
_, _, artifact_name = self.subject_name.rpartition("/")
97-
return artifact_name
98-
99-
10085
def extract_repo_url(witness_payload: InTotoPayload) -> str | None:
10186
"""Extract the repo URL from the witness provenance payload.
10287
Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,158 @@
1-
# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2023 - 2024, Oracle and/or its affiliates. All rights reserved.
22
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
33

44
"""Test the check ``provenance_witness_l1_check``."""
5+
6+
import pytest
7+
8+
from macaron.slsa_analyzer.checks.provenance_witness_l1_check import verify_artifact_assets
9+
from macaron.slsa_analyzer.package_registry.jfrog_maven_registry import (
10+
JFrogMavenAsset,
11+
JFrogMavenAssetMetadata,
12+
JFrogMavenRegistry,
13+
)
14+
from macaron.slsa_analyzer.provenance.intoto.v01 import InTotoV01Subject
15+
16+
17+
@pytest.fixture(name="subjects")
18+
def subjects_() -> list[InTotoV01Subject]:
19+
"""Return the list of subjects in an example witness provenance."""
20+
return [
21+
{
22+
"name": "https://witness.dev/attestations/product/v0.1/file:target/boo-1.0.0.jar",
23+
"digest": {
24+
"sha256": "cbc8f554dbfa17e5c5873c425a09cb1488c2f784ac52340747a92b7ec0aaefba",
25+
},
26+
},
27+
{
28+
"name": "https://witness.dev/attestations/product/v0.1/file:sources/boo-1.0.0-sources.jar",
29+
"digest": {
30+
"sha256": "6f97fe2094bd50435d6fbb7a2f6c2638fe44e6af17cfff98ce111d0abfffe17e",
31+
},
32+
},
33+
{
34+
"name": "https://witness.dev/attestations/product/v0.1/file:foo/bar/boo-1.0.0.jar",
35+
"digest": {
36+
"sha256": "d2238e45bb212fbe4a2e8e7dc160ffa123bacc5396899a039e973d2930eb4e41",
37+
},
38+
},
39+
]
40+
41+
42+
@pytest.mark.parametrize(
43+
("artifact_assets"),
44+
[
45+
pytest.param(
46+
[
47+
JFrogMavenAsset(
48+
name="boo-1.0.0.jar",
49+
group_id="io.oracle.macaron",
50+
artifact_id="boo",
51+
version="1.0.0",
52+
metadata=JFrogMavenAssetMetadata(
53+
size_in_bytes=50,
54+
sha256_digest="cbc8f554dbfa17e5c5873c425a09cb1488c2f784ac52340747a92b7ec0aaefba",
55+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/target/boo-1.0.0.jar",
56+
),
57+
jfrog_maven_registry=JFrogMavenRegistry(),
58+
),
59+
JFrogMavenAsset(
60+
name="boo-1.0.0-sources.jar",
61+
group_id="io.oracle.macaron",
62+
artifact_id="boo",
63+
version="1.0.0",
64+
metadata=JFrogMavenAssetMetadata(
65+
size_in_bytes=100,
66+
sha256_digest="6f97fe2094bd50435d6fbb7a2f6c2638fe44e6af17cfff98ce111d0abfffe17e",
67+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/sources/boo-1.0.0-sources.jar",
68+
),
69+
jfrog_maven_registry=JFrogMavenRegistry(),
70+
),
71+
],
72+
id="The assets list can match only a subset of subjects. As long as all assets in that list are verified.",
73+
),
74+
pytest.param(
75+
[
76+
JFrogMavenAsset(
77+
name="boo-1.0.0.jar",
78+
group_id="io.oracle.macaron",
79+
artifact_id="boo",
80+
version="1.0.0",
81+
metadata=JFrogMavenAssetMetadata(
82+
size_in_bytes=50,
83+
sha256_digest="cbc8f554dbfa17e5c5873c425a09cb1488c2f784ac52340747a92b7ec0aaefba",
84+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/target/boo-1.0.0.jar",
85+
),
86+
jfrog_maven_registry=JFrogMavenRegistry(),
87+
),
88+
JFrogMavenAsset(
89+
name="boo-1.0.0.jar",
90+
group_id="io.oracle.macaron",
91+
artifact_id="boo",
92+
version="1.0.0",
93+
metadata=JFrogMavenAssetMetadata(
94+
size_in_bytes=99,
95+
sha256_digest="d2238e45bb212fbe4a2e8e7dc160ffa123bacc5396899a039e973d2930eb4e41",
96+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/foo/bar/boo-1.0.0.jar",
97+
),
98+
jfrog_maven_registry=JFrogMavenRegistry(),
99+
),
100+
],
101+
id="2 assets can share the same file name but have different digests.",
102+
),
103+
],
104+
)
105+
def test_verify_artifact_assets(
106+
artifact_assets: list[JFrogMavenAsset],
107+
subjects: list[InTotoV01Subject],
108+
) -> None:
109+
"""Test the verify_artifact_assets function."""
110+
assert verify_artifact_assets(
111+
artifact_assets=artifact_assets,
112+
subjects=subjects,
113+
)
114+
115+
116+
@pytest.mark.parametrize(
117+
("artifact_assets"),
118+
[
119+
pytest.param(
120+
[
121+
JFrogMavenAsset(
122+
name="boo-1.0.0.jar",
123+
group_id="io.oracle.macaron",
124+
artifact_id="boo",
125+
version="1.0.0",
126+
metadata=JFrogMavenAssetMetadata(
127+
size_in_bytes=50,
128+
sha256_digest="cbc8f554dbfa17e5c5873c425a09cb1488c2f784ac52340747a92b7ec0aaefba",
129+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/target/boo-1.0.0.jar",
130+
),
131+
jfrog_maven_registry=JFrogMavenRegistry(),
132+
),
133+
JFrogMavenAsset(
134+
name="this-does-not-exist",
135+
group_id="io.oracle.macaron",
136+
artifact_id="boo",
137+
version="1.0.0",
138+
metadata=JFrogMavenAssetMetadata(
139+
size_in_bytes=50,
140+
sha256_digest="cbc8f554dbfa17e5c5873c425a09cb1488c2f784ac52340747a92b7ec0aaefba",
141+
download_uri="https://artifactory.com/repo/io/oracle/macaron/boo/1.0.0/this-does-not-exist",
142+
),
143+
jfrog_maven_registry=JFrogMavenRegistry(),
144+
),
145+
],
146+
id="An asset that is not included in the subjects lead to a failed verification.",
147+
),
148+
],
149+
)
150+
def test_verify_invalid_artifact_assets(
151+
artifact_assets: list[JFrogMavenAsset],
152+
subjects: list[InTotoV01Subject],
153+
) -> None:
154+
"""Test the verify_artifact_assets function with invalid assets."""
155+
assert not verify_artifact_assets(
156+
artifact_assets=artifact_assets,
157+
subjects=subjects,
158+
)

0 commit comments

Comments
 (0)