@@ -67,18 +67,33 @@ def _b64(data: bytes) -> str:
6767 return base64 .b64encode (data ).decode ()
6868
6969
70- def _make_attestation (statement_bytes , signature_bytes ):
70+ def _make_attestation (statement_bytes , signature_bytes , verification_material = None ):
7171 """Return a single PEP-740 Attestation dict (SLSA flavour)."""
7272 return {
7373 "version" : 1 ,
74- "verification_material" : None ,
74+ "verification_material" : verification_material ,
7575 "envelope" : {
7676 "statement" : _b64 (statement_bytes ),
7777 "signature" : _b64 (signature_bytes ),
7878 },
7979 }
8080
8181
82+ def _read_public_key_pem ():
83+ """Read the test public key as a PEM string."""
84+ with open (TEST_PUBLIC_KEY_PATH ) as f :
85+ return f .read ()
86+
87+
88+ def _make_embedded_key_material (public_key_pem ):
89+ """Build a verification_material dict with an embedded public key."""
90+ return {
91+ "certificate" : None ,
92+ "public_key" : public_key_pem ,
93+ "transparency_entries" : [{"log_index" : 0 }],
94+ }
95+
96+
8297def _make_provenance (attestation ):
8398 """Wrap an attestation into a full PEP-740 Provenance object."""
8499 return {
@@ -245,3 +260,63 @@ def test_slsa_attestation_via_content_upload(
245260 assert publisher ["builder_id" ] == "https://konflux-ci.dev/calunga"
246261 assert publisher ["build_type" ] == "https://konflux-ci.dev/PythonWheelBuild@v1"
247262 assert publisher ["kind" ] == "konflux-ci.dev"
263+
264+
265+ def test_slsa_embedded_key_accepted (
266+ python_bindings , python_content_factory , monitor_task , test_private_key , _provenance_file
267+ ):
268+ """An attestation with an embedded public key matching the server key is accepted."""
269+ content = python_content_factory ()
270+
271+ stmt = _build_statement (content .filename , content .sha256 )
272+ sig = _sign (stmt , test_private_key )
273+ vm = _make_embedded_key_material (_read_public_key_pem ())
274+ att = _make_attestation (stmt , sig , verification_material = vm )
275+ prov = _make_provenance (att )
276+
277+ task = python_bindings .ContentProvenanceApi .create (
278+ package = content .pulp_href ,
279+ file = _provenance_file (prov ),
280+ verify = True ,
281+ ).task
282+ result = monitor_task (task )
283+
284+ prov_obj = python_bindings .ContentProvenanceApi .read (result .created_resources [- 1 ])
285+ assert prov_obj .package == content .pulp_href
286+ stored_vm = prov_obj .provenance ["attestation_bundles" ][0 ]["attestations" ][0 ][
287+ "verification_material"
288+ ]
289+ assert stored_vm ["public_key" ] == _read_public_key_pem ()
290+
291+
292+ def test_slsa_embedded_key_mismatch_rejected (
293+ python_bindings , python_content_factory , monitor_task , test_private_key , _provenance_file
294+ ):
295+ """An attestation with an embedded key that does not match the server key is rejected."""
296+ content = python_content_factory ()
297+
298+ stmt = _build_statement (content .filename , content .sha256 )
299+ sig = _sign (stmt , test_private_key )
300+ wrong_key = (
301+ "-----BEGIN PUBLIC KEY-----\n "
302+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvxtuKOCCHGNd6agbC4b\n "
303+ "zX9S7qMnMRdz9bxxzkPf9a4T75St3EcrNQYxLqzcDBfeiiLa1wXQoraqFSGkvqX+\n "
304+ "YDFmtYRgnXEujUwYqHQBYrKtrQHxrQ2J3V1e+PqhJ4HCQq/uRZdx6KJ5DOlpYuJM\n "
305+ "aL2m7IozNJJkgjQH1frmDfM5/GuPVbgwN0QDnC0oSzNJFKtdVMD3SPnQGMPQ9qxf\n "
306+ "DiTZOk1tO3VD/xXoNJ6Zgf0D5RvGyLAfLflgojKImHezgpdE6iQyZAVU2ShKMq3M\n "
307+ "K+XtX39/ajXHJ1FCLXlRFoNoHltWioyvkmXHbhb9OxGncB+x6idSjgp7AR5y15HN\n "
308+ "DwIDAQAB\n "
309+ "-----END PUBLIC KEY-----\n "
310+ )
311+ vm = _make_embedded_key_material (wrong_key )
312+ att = _make_attestation (stmt , sig , verification_material = vm )
313+ prov = _make_provenance (att )
314+
315+ task = python_bindings .ContentProvenanceApi .create (
316+ package = content .pulp_href ,
317+ file = _provenance_file (prov ),
318+ verify = True ,
319+ ).task
320+ with pytest .raises (PulpTaskError ) as exc_info :
321+ monitor_task (task )
322+ assert "embedded public key does not match" in exc_info .value .task .error ["description" ]
0 commit comments