Skip to content

Commit e136352

Browse files
sigstore: add new verification policies for missing extensions (#1004)
* sigstore: add new verification policies for missing extensions Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com> * Rename policy class Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com> * Update pyproject.toml Co-authored-by: William Woodruff <william@yossarian.net> Signed-off-by: Facundo Tuesca <facu@tuesca.com> --------- Signed-off-by: Facundo Tuesca <facundo.tuesca@trailofbits.com> Signed-off-by: Facundo Tuesca <facu@tuesca.com> Co-authored-by: William Woodruff <william@yossarian.net>
1 parent 3659ffa commit e136352

File tree

5 files changed

+235
-0
lines changed

5 files changed

+235
-0
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dependencies = [
2828
"cryptography >= 42",
2929
"id >= 1.1.0",
3030
"importlib_resources ~= 5.7; python_version < '3.11'",
31+
"pyasn1 ~= 0.6",
3132
"pydantic >= 2,< 3",
3233
"pyjwt >= 2.1",
3334
"pyOpenSSL >= 23.0.0",

sigstore/verify/policy.py

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
SubjectAlternativeName,
3333
UniformResourceIdentifier,
3434
)
35+
from pyasn1.codec.der.decoder import decode as der_decode
36+
from pyasn1.type.char import UTF8String
3537

3638
from sigstore.errors import VerificationError
3739

@@ -45,6 +47,23 @@
4547
_OIDC_GITHUB_WORKFLOW_REPOSITORY_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.5")
4648
_OIDC_GITHUB_WORKFLOW_REF_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.6")
4749
_OTHERNAME_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.7")
50+
_OIDC_ISSUER_V2_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.8")
51+
_OIDC_BUILD_SIGNER_URI_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.9")
52+
_OIDC_BUILD_SIGNER_DIGEST_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.10")
53+
_OIDC_RUNNER_ENVIRONMENT_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.11")
54+
_OIDC_SOURCE_REPOSITORY_URI_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.12")
55+
_OIDC_SOURCE_REPOSITORY_DIGEST_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.13")
56+
_OIDC_SOURCE_REPOSITORY_REF_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.14")
57+
_OIDC_SOURCE_REPOSITORY_IDENTIFIER_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.15")
58+
_OIDC_SOURCE_REPOSITORY_OWNER_URI_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.16")
59+
_OIDC_SOURCE_REPOSITORY_OWNER_IDENTIFIER_OID = ObjectIdentifier(
60+
"1.3.6.1.4.1.57264.1.17"
61+
)
62+
_OIDC_BUILD_CONFIG_URI_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.18")
63+
_OIDC_BUILD_CONFIG_DIGEST_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.19")
64+
_OIDC_BUILD_TRIGGER_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.20")
65+
_OIDC_RUN_INVOCATION_URI_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.21")
66+
_OIDC_SOURCE_REPOSITORY_VISIBILITY_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.22")
4867

4968

5069
class _SingleX509ExtPolicy(ABC):
@@ -93,6 +112,41 @@ def verify(self, cert: Certificate) -> None:
93112
)
94113

95114

115+
class _SingleX509ExtPolicyV2(_SingleX509ExtPolicy):
116+
"""
117+
An base class for verification policies that boil down to checking a single
118+
X.509 extension's value, where the value is formatted as a DER-encoded string,
119+
the ASN.1 tag is UTF8String (0x0C) and the tag class is universal.
120+
"""
121+
122+
def verify(self, cert: Certificate) -> None:
123+
"""
124+
Verify this policy against `cert`.
125+
126+
Raises `VerificationError` on failure.
127+
"""
128+
try:
129+
ext = cert.extensions.get_extension_for_oid(self.oid).value
130+
except ExtensionNotFound:
131+
raise VerificationError(
132+
(
133+
f"Certificate does not contain {self.__class__.__name__} "
134+
f"({self.oid.dotted_string}) extension"
135+
)
136+
)
137+
138+
# NOTE(ww): mypy is confused by the `Extension[ExtensionType]` returned
139+
# by `get_extension_for_oid` above.
140+
ext_value = der_decode(ext.value, UTF8String)[0].decode() # type: ignore[attr-defined]
141+
if ext_value != self._value:
142+
raise VerificationError(
143+
(
144+
f"Certificate's {self.__class__.__name__} does not match "
145+
f"(got {ext_value}, expected {self._value})"
146+
)
147+
)
148+
149+
96150
class OIDCIssuer(_SingleX509ExtPolicy):
97151
"""
98152
Verifies the certificate's OIDC issuer, identified by
@@ -147,6 +201,145 @@ class GitHubWorkflowRef(_SingleX509ExtPolicy):
147201
oid = _OIDC_GITHUB_WORKFLOW_REF_OID
148202

149203

204+
class OIDCIssuerV2(_SingleX509ExtPolicyV2):
205+
"""
206+
Verifies the certificate's OIDC issuer, identified by
207+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.8`.
208+
The difference with `OIDCIssuer` is that the value for
209+
this extension is formatted to the RFC 5280 specification
210+
as a DER-encoded string.
211+
"""
212+
213+
oid = _OIDC_ISSUER_V2_OID
214+
215+
216+
class OIDCBuildSignerURI(_SingleX509ExtPolicyV2):
217+
"""
218+
Verifies the certificate's OIDC Build Signer URI, identified by
219+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.9`.
220+
"""
221+
222+
oid = _OIDC_BUILD_SIGNER_URI_OID
223+
224+
225+
class OIDCBuildSignerDigest(_SingleX509ExtPolicyV2):
226+
"""
227+
Verifies the certificate's OIDC Build Signer Digest, identified by
228+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.10`.
229+
"""
230+
231+
oid = _OIDC_BUILD_SIGNER_DIGEST_OID
232+
233+
234+
class OIDCRunnerEnvironment(_SingleX509ExtPolicyV2):
235+
"""
236+
Verifies the certificate's OIDC Runner Environment, identified by
237+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.11`.
238+
"""
239+
240+
oid = _OIDC_RUNNER_ENVIRONMENT_OID
241+
242+
243+
class OIDCSourceRepositoryURI(_SingleX509ExtPolicyV2):
244+
"""
245+
Verifies the certificate's OIDC Source Repository URI, identified by
246+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.12`.
247+
"""
248+
249+
oid = _OIDC_SOURCE_REPOSITORY_URI_OID
250+
251+
252+
class OIDCSourceRepositoryDigest(_SingleX509ExtPolicyV2):
253+
"""
254+
Verifies the certificate's OIDC Source Repository Digest, identified by
255+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.13`.
256+
"""
257+
258+
oid = _OIDC_SOURCE_REPOSITORY_DIGEST_OID
259+
260+
261+
class OIDCSourceRepositoryRef(_SingleX509ExtPolicyV2):
262+
"""
263+
Verifies the certificate's OIDC Source Repository Ref, identified by
264+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.14`.
265+
"""
266+
267+
oid = _OIDC_SOURCE_REPOSITORY_REF_OID
268+
269+
270+
class OIDCSourceRepositoryIdentifier(_SingleX509ExtPolicyV2):
271+
"""
272+
Verifies the certificate's OIDC Source Repository Identifier, identified by
273+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.15`.
274+
"""
275+
276+
oid = _OIDC_SOURCE_REPOSITORY_IDENTIFIER_OID
277+
278+
279+
class OIDCSourceRepositoryOwnerURI(_SingleX509ExtPolicyV2):
280+
"""
281+
Verifies the certificate's OIDC Source Repository Owner URI, identified by
282+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.16`.
283+
"""
284+
285+
oid = _OIDC_SOURCE_REPOSITORY_OWNER_URI_OID
286+
287+
288+
class OIDCSourceRepositoryOwnerIdentifier(_SingleX509ExtPolicyV2):
289+
"""
290+
Verifies the certificate's OIDC Source Repository Owner Identifier, identified by
291+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.17`.
292+
"""
293+
294+
oid = _OIDC_SOURCE_REPOSITORY_OWNER_IDENTIFIER_OID
295+
296+
297+
class OIDCBuildConfigURI(_SingleX509ExtPolicyV2):
298+
"""
299+
Verifies the certificate's OIDC Build Config URI, identified by
300+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.18`.
301+
"""
302+
303+
oid = _OIDC_BUILD_CONFIG_URI_OID
304+
305+
306+
class OIDCBuildConfigDigest(_SingleX509ExtPolicyV2):
307+
"""
308+
Verifies the certificate's OIDC Build Config Digest, identified by
309+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.19`.
310+
"""
311+
312+
oid = _OIDC_BUILD_CONFIG_DIGEST_OID
313+
314+
315+
class OIDCBuildTrigger(_SingleX509ExtPolicyV2):
316+
"""
317+
Verifies the certificate's OIDC Build Trigger, identified by
318+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.20`.
319+
"""
320+
321+
oid = _OIDC_BUILD_TRIGGER_OID
322+
323+
324+
class OIDCRunInvocationURI(_SingleX509ExtPolicyV2):
325+
"""
326+
Verifies the certificate's OIDC Run Invocation URI, identified by
327+
an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.21`.
328+
"""
329+
330+
oid = _OIDC_RUN_INVOCATION_URI_OID
331+
332+
333+
class OIDCSourceRepositoryVisibility(_SingleX509ExtPolicyV2):
334+
"""
335+
Verifies the certificate's OIDC Source Repository Visibility
336+
At Signing, identified by an X.509v3 extension tagged with
337+
`1.3.6.1.4.1.57264.1.22`.
338+
"""
339+
340+
oid = _OIDC_SOURCE_REPOSITORY_VISIBILITY_OID
341+
342+
150343
class VerificationPolicy(Protocol):
151344
"""
152345
A protocol type describing the interface that all verification policies

test/unit/assets/bundle_v3_github.whl

8.96 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.2", "verificationMaterial": {"x509CertificateChain": {"certificates": [{"rawBytes": "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"}]}, "tlogEntries": [{"logIndex": "79605083", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1710888076", "inclusionPromise": {"signedEntryTimestamp": "MEYCIQD8ohK48/Ls8D4Qd3dQZl6geplAt0p5Sgpa1wabniB/ZgIhALsVfKCe1m2KKtaEImxijm5bO2K49NltHWafJE2a1hnr"}, "inclusionProof": {"logIndex": "75441652", "rootHash": "uAqI3id6JHPMMNUltHIKHuX1kVHpm5y7jSfnbaRO+E4=", "treeSize": "75441653", "hashes": ["XoeIGlDW7f2lVjTlQEXPaV7szUXY2BECAEKtNA/lgfk=", "Pz5CyFQH78eikJoZuJ44Ls4R5najWJ1nKWunxb/vxeM=", "COo4wZnRb/d6zZOa7RP1euSRFb7H5EX5bYXs4HEQ0uU=", "1A4EnFDN5UCHjrJDWPuYDmY+ZLb4B+Jvis+k3ti+wjs=", "bBpWKtQryG7/tMDt9HDvKk/Fp3S+q7gTnYF56qGKMiI=", "ZR8qbYzXTNaK4SaofTZtbR0srNmOJ0Yx891OF5/G2gQ=", "7MueyMCRkh/GaluPkJl3xQFyXFq/SS9xykP299KtvS0=", "kFt/VRwfXksHcnd9vpdeifz3N16KyWQoDxAPfLlRwTA=", "gtt9e0foHZTCS9w+epNsmDWbwvX4FNV1EAg0rhxLfjg=", "BGqH+LzVuhuqCLiUvBJaB2hlsvtu2a15qq1WGw6mG44=", "OeS7D4kPES7ChE7kWSEmhbAMqBcKVj/z8/afMK4Y3pI=", "JtjqvAqFyXXYjWlZfDzElHpEzdBjsz1LmGFJuYx0kTU=", "s/ZIVcfcD4/nuZwUtQf4ydGsIAkGTPTzk3b0zhUC95k=", "YU1jZY/fp5tJdGF/i+/7ez8107O4/lOUp7acMPFEaOA=", "7Z18YLBAvejEV4nJHIKoks/xlijnhR005qTW2w4QtHg=", "98enzMaC+x5oCMvIZQA5z8vu2apDMCFvE/935NfuPw8="], "checkpoint": {"envelope": "rekor.sigstore.dev - 2605736670972794746\n75441653\nuAqI3id6JHPMMNUltHIKHuX1kVHpm5y7jSfnbaRO+E4=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEA5perJLLm94gCQOQT5/vO29OXWNZ1SoengZDZ/U6vsOUCIQDBL0BIkCjWGR6V622znnVpXF5D1g0jPgajBlHh8uSc8g==\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjNGU5MmU5ZWNjODI4YmVmMmFhN2RiYTFkZThhYzk4MzUxMWY3NTMyYTBkZjExYzc3MGQzOTA5OWEyNWNmMjAxIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUNlSDZFM01wWm5nV0E2UlBnOEhBbC9aNzY0aFRGWXljTnlGM1IrbVBUU2JBSWhBUGdNUzhxQk04bENFVTJYVzc2NW15TU16Mnp1eXU5aVRGNDBQSCtYWmxKUSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVZDZla05EUW14VFowRjNTVUpCWjBsVlRUSTVZblpaYTNKRVMyNUNWbHB0Vm1Wc2IxUlZUV3hhY1U1WmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJkMDE2UlRWTmFra3dUVlJGTVZkb1kwNU5hbEYzVFhwRk5VMXFTVEZOVkVVeFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVV4Y1RoM2JYQnRTekIyWlhORFJEQTFXa1V4YnpWS2VYVXJaeTlEZEV4YVRGaE9SVm9LYVVsdmJXZ3hhbkYxVUUxRFduSm9iRkJrVDJaNlVYZHpLMFVyU1ZWQ1dETndZMVpWZUhSdU5ISlpTMjVOU0RNNWIyRlBRMEpZVFhkbloxWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlV3VUdGVkNtSm9kSEE0TkU5eVlqSlpZWFIyV210SmFtdGFhVTlGZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDFwbldVUldVakJTUVZGSUwwSkdkM2RYYjFwWllVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcFlWaFNlZ3BNTTBwdFdYcG5NMDlFVlhWalNHdDJURzFrY0dSSGFERlphVGt6WWpOS2NscHRlSFprTTAxMlkyMVdjMXBYUm5wYVV6VTFZbGQ0UVdOdFZtMWplVGt3Q2xsWFpIcE1NMWwzVEdwRmRVMXFRVFZDWjI5eVFtZEZSVUZaVHk5TlFVVkNRa04wYjJSSVVuZGplbTkyVEROU2RtRXlWblZNYlVacVpFZHNkbUp1VFhVS1dqSnNNR0ZJVm1sa1dFNXNZMjFPZG1KdVVteGlibEYxV1RJNWRFMUNWVWREYVhOSFFWRlJRbWMzT0hkQlVVbEZRak5LYkdKSFZtaGpNbFYzVG1kWlN3cExkMWxDUWtGSFJIWjZRVUpCZDFGdldrUm9hVTVIUlRKT1JGRXhXbXBOTkZsNlVUUlphbXQ0VFhwa2FFOUVRVFZQVkdOM1RtMVJOVmxxWjNkT2VrMTRDazVFV214T1JFRldRbWR2Y2tKblJVVkJXVTh2VFVGRlJVSkJaSGxhVjNoc1dWaE9iRTFEVVVkRGFYTkhRVkZSUW1jM09IZEJVVlZGUm01U2VWbFhiSE1LWWpKYWFXRllVbnBNTTBwdFdYcG5NMDlFVlhWalNHdDNTR2RaUzB0M1dVSkNRVWRFZG5wQlFrSm5VVkZqYlZadFkzazVNRmxYWkhwTU0xbDNUR3BGZFFwTmFrRTNRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkRNRTFMTW1nd1pFaENlazlwT0haa1J6bHlXbGMwZFZsWFRqQmhWemwxWTNrMWJtRllVbTlrVjBveENtTXlWbmxaTWpsMVpFZFdkV1JETldwaU1qQjNZVUZaUzB0M1dVSkNRVWRFZG5wQlFrTlJVbUZFUm1odlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5Xb0tZakl3ZG1SSVNtaGhWM2gyV20xS2NHUklUWFpqYlZwcVQwUmpORTVUTlhkbFV6aDFXakpzTUdGSVZtbE1NMlIyWTIxMGJXSkhPVE5qZVRsNVdsZDRiQXBaV0U1c1RHNXNkR0pGUW5sYVYxcDZURE5TYUZvelRYWmtha0YxVFZNMGVVMUVaMGREYVhOSFFWRlJRbWMzT0hkQlVXOUZTMmQzYjFwRWFHbE9SMFV5Q2s1RVVURmFhazAwV1hwUk5GbHFhM2hOZW1Sb1QwUkJOVTlVWTNkT2JWRTFXV3BuZDA1NlRYaE9SRnBzVGtSQlpFSm5iM0pDWjBWRlFWbFBMMDFCUlV3S1FrRTRUVVJYWkhCa1IyZ3hXV2t4YjJJelRqQmFWMUYzVDFGWlMwdDNXVUpDUVVkRWRucEJRa1JCVVhKRVEyeHZaRWhTZDJONmIzWk1NbVJ3WkVkb01RcFphVFZxWWpJd2RtUklTbWhoVjNoMldtMUtjR1JJVFhaamJWcHFUMFJqTkU1VE5YZGxWRUUwUW1kdmNrSm5SVVZCV1U4dlRVRkZUa0pEYjAxTFIxRTBDbGxxVW1oT2FsRXdUbGRaZWs5SFRUQlBSMGsxVFZSTk0xbFVaM2RQVkdzelRVUmFhMDlYU1RSTlJHTjZUVlJSTWxwVVVYZEpRVmxMUzNkWlFrSkJSMFFLZG5wQlFrUm5VVk5FUWtKNVdsZGFla3d6VW1oYU0wMTJaR3BCZFUxVE5IbE5RbXRIUTJselIwRlJVVUpuTnpoM1FWRTRSVU4zZDBwT2VsazBUV3BGZWdwUFZHc3pUVU0wUjBOcGMwZEJVVkZDWnpjNGQwRlNRVVZKUVhkbFlVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVEROU2VWbFhiSE5pTWxwcENtRllVbnBOUW1OSFEybHpSMEZSVVVKbk56aDNRVkpGUlVOUmQwaE5hazE0VGtSUmVVMTZRbTlDWjI5eVFtZEZSVUZaVHk5TlFVVlRRa1p2VFZkSGFEQUtaRWhDZWs5cE9IWmFNbXd3WVVoV2FVeHRUblppVXprd1kyMUdjR0pIT1cxWmJXd3dZM2s1ZVZwdFRUUk9lbWN4VEc1Q05VeDVOVzVoV0ZKdlpGZEpkZ3BrTWpsNVlUSmFjMkl6WkhwTU0wcHNZa2RXYUdNeVZYVmxWekZ6VVVoS2JGcHVUWFprUjBadVkzazVNazFETkhoTWFrbDNUMEZaUzB0M1dVSkNRVWRFQ25aNlFVSkZkMUZ4UkVOb2EwOUhTVEJaVkZrd1RrUldiVTE2YUdwT1JHaHBUMVJGZWs0eVJUUk5SR3MxVG5wQk1scEViR2xQUkVFelRYcEZNRTV0VlRBS1RVSmpSME5wYzBkQlVWRkNaemM0ZDBGU1VVVkRVWGRJWTIxV2MxcFhSbnBhVkVKalFtZHZja0puUlVWQldVOHZUVUZGVmtKRk5FMVVSMmd3WkVoQ2VncFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVNR050Um5CaVJ6bHRXVzFzTUdONU9YbGFiVTAwVG5wbk1VeHVRalZNTWtacVpFZHNkbUp1VFhaamJsWjFDbU41T0RSTmVsVjRUVVJWTkU1VVFYaE1Na1l3WkVkV2RHTklVbnBNZWtWM1JtZFpTMHQzV1VKQ1FVZEVkbnBCUWtablVVbEVRVnAzWkZkS2MyRlhUWGNLWjFsdlIwTnBjMGRCVVZGQ01XNXJRMEpCU1VWbVFWSTJRVWhuUVdSblJHUlFWRUp4ZUhOalVrMXRUVnBJYUhsYVducGpRMjlyY0dWMVRqUTRjbVlyU0FwcGJrdEJUSGx1ZFdwblFVRkJXVFZaTkVWTEswRkJRVVZCZDBKSVRVVlZRMGxFWVdkbWFuQjNNVUZhV0RNM05IWkdXRWRFVTFwblNqbExjWEpqY1RkVUNtc3ZWWE16WmpkdWJWWlJNVUZwUlVFMFpYTkhRbkpFYUdac1lrbFZkV3BWYlZsRE0yVlZWMFpHUW1kWVNHWkJRa3hwVTBSM1kybFVVWGM0ZDBObldVa0tTMjlhU1hwcU1FVkJkMDFFWVZGQmQxcG5TWGhCVFRablMwazFka3R2Y1dOMlZHdDJPRGRHYjNFelYxaE9XVzFCYUZCcU0zRmhVVFZ2WTFoUldITlhlZ3BJWlU1WFIwSTJiRk5JVkVjelJVNTVZWEJ4V1VKblNYaEJUVXBYT1d4NU0wcFlSV1JKTlhsa1NHWjZLMGRhYjJneGEzbGpNRmhHVlZCd05GWTBhMVpxQ201VldGa3JTM1J2VVZkTFUxQklZVnBOYTFsREwzTjZXR2huUFQwS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19"}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "xOkunsyCi+8qp9uh3orJg1EfdTKg3xHHcNOQmaJc8gE="}, "signature": "MEYCIQCeH6E3MpZngWA6RPg8HAl/Z764hTFYycNyF3R+mPTSbAIhAPgMS8qBM8lCEU2XW765myMMz2zuyu9iTF40PH+XZlJQ"}}

test/unit/verify/test_policy.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,43 @@ def test_fails_no_san_match(self, signing_bundle):
151151
match="Certificate's SANs do not match",
152152
):
153153
policy_.verify(bundle.signing_certificate)
154+
155+
156+
class TestSingleExtPolicy:
157+
def test_succeeds(self, signing_bundle):
158+
_, bundle = signing_bundle("bundle_v3_github.whl")
159+
160+
verification_policy_extensions = [
161+
policy.OIDCIssuer("https://token.actions.githubusercontent.com"),
162+
policy.GitHubWorkflowTrigger("release"),
163+
policy.GitHubWorkflowSHA("d8b4a6445f38c48b9137a8099706d9b8073146e4"),
164+
policy.GitHubWorkflowName("release"),
165+
policy.GitHubWorkflowRepository("trailofbits/rfc8785.py"),
166+
policy.GitHubWorkflowRef("refs/tags/v0.1.2"),
167+
policy.OIDCIssuerV2("https://token.actions.githubusercontent.com"),
168+
policy.OIDCBuildSignerURI(
169+
"https://github.com/trailofbits/rfc8785.py/.github/workflows/release.yml@refs/tags/v0.1.2"
170+
),
171+
policy.OIDCBuildSignerDigest("d8b4a6445f38c48b9137a8099706d9b8073146e4"),
172+
policy.OIDCRunnerEnvironment("github-hosted"),
173+
policy.OIDCSourceRepositoryURI("https://github.com/trailofbits/rfc8785.py"),
174+
policy.OIDCSourceRepositoryDigest(
175+
"d8b4a6445f38c48b9137a8099706d9b8073146e4"
176+
),
177+
policy.OIDCSourceRepositoryRef("refs/tags/v0.1.2"),
178+
policy.OIDCSourceRepositoryIdentifier("768213997"),
179+
policy.OIDCSourceRepositoryOwnerURI("https://github.com/trailofbits"),
180+
policy.OIDCSourceRepositoryOwnerIdentifier("2314423"),
181+
policy.OIDCBuildConfigURI(
182+
"https://github.com/trailofbits/rfc8785.py/.github/workflows/release.yml@refs/tags/v0.1.2"
183+
),
184+
policy.OIDCBuildConfigDigest("d8b4a6445f38c48b9137a8099706d9b8073146e4"),
185+
policy.OIDCBuildTrigger("release"),
186+
policy.OIDCRunInvocationURI(
187+
"https://github.com/trailofbits/rfc8785.py/actions/runs/8351058501/attempts/1"
188+
),
189+
policy.OIDCSourceRepositoryVisibility("public"),
190+
]
191+
192+
policy_ = policy.AllOf(verification_policy_extensions)
193+
policy_.verify(bundle.signing_certificate)

0 commit comments

Comments
 (0)