sigstore.verify.policy
APIs for describing identity verification "policies", which describe how the identities passed into an individual verification step are verified.
1# Copyright 2022 The Sigstore Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16APIs for describing identity verification "policies", which describe how the identities 17passed into an individual verification step are verified. 18""" 19 20from __future__ import annotations 21 22import logging 23from abc import ABC, abstractmethod 24from typing import Protocol 25 26from cryptography.x509 import ( 27 Certificate, 28 ExtensionNotFound, 29 ObjectIdentifier, 30 OtherName, 31 RFC822Name, 32 SubjectAlternativeName, 33 UniformResourceIdentifier, 34) 35from pyasn1.codec.der.decoder import decode as der_decode 36from pyasn1.type.char import UTF8String 37 38from sigstore.errors import VerificationError 39 40_logger = logging.getLogger(__name__) 41 42# From: https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md 43_OIDC_ISSUER_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.1") 44_OIDC_GITHUB_WORKFLOW_TRIGGER_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.2") 45_OIDC_GITHUB_WORKFLOW_SHA_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.3") 46_OIDC_GITHUB_WORKFLOW_NAME_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.4") 47_OIDC_GITHUB_WORKFLOW_REPOSITORY_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.5") 48_OIDC_GITHUB_WORKFLOW_REF_OID = ObjectIdentifier("1.3.6.1.4.1.57264.1.6") 49_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") 67 68 69class _SingleX509ExtPolicy(ABC): 70 """ 71 An ABC for verification policies that boil down to checking a single 72 X.509 extension's value. 73 """ 74 75 oid: ObjectIdentifier 76 """ 77 The OID of the extension being checked. 78 """ 79 80 def __init__(self, value: str) -> None: 81 """ 82 Creates the new policy, with `value` as the expected value during 83 verification. 84 """ 85 self._value = value 86 87 def verify(self, cert: Certificate) -> None: 88 """ 89 Verify this policy against `cert`. 90 91 Raises `VerificationError` on failure. 92 """ 93 try: 94 ext = cert.extensions.get_extension_for_oid(self.oid).value 95 except ExtensionNotFound: 96 raise VerificationError( 97 ( 98 f"Certificate does not contain {self.__class__.__name__} " 99 f"({self.oid.dotted_string}) extension" 100 ) 101 ) 102 103 # NOTE(ww): mypy is confused by the `Extension[ExtensionType]` returned 104 # by `get_extension_for_oid` above. 105 ext_value = ext.value.decode() # type: ignore[attr-defined] 106 if ext_value != self._value: 107 raise VerificationError( 108 ( 109 f"Certificate's {self.__class__.__name__} does not match " 110 f"(got '{ext_value}', expected '{self._value}')" 111 ) 112 ) 113 114 115class _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 150class OIDCIssuer(_SingleX509ExtPolicy): 151 """ 152 Verifies the certificate's OIDC issuer, identified by 153 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.1`. 154 """ 155 156 oid = _OIDC_ISSUER_OID 157 158 159class GitHubWorkflowTrigger(_SingleX509ExtPolicy): 160 """ 161 Verifies the certificate's GitHub Actions workflow trigger, 162 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.2`. 163 """ 164 165 oid = _OIDC_GITHUB_WORKFLOW_TRIGGER_OID 166 167 168class GitHubWorkflowSHA(_SingleX509ExtPolicy): 169 """ 170 Verifies the certificate's GitHub Actions workflow commit SHA, 171 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.3`. 172 """ 173 174 oid = _OIDC_GITHUB_WORKFLOW_SHA_OID 175 176 177class GitHubWorkflowName(_SingleX509ExtPolicy): 178 """ 179 Verifies the certificate's GitHub Actions workflow name, 180 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.4`. 181 """ 182 183 oid = _OIDC_GITHUB_WORKFLOW_NAME_OID 184 185 186class GitHubWorkflowRepository(_SingleX509ExtPolicy): 187 """ 188 Verifies the certificate's GitHub Actions workflow repository, 189 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.5`. 190 """ 191 192 oid = _OIDC_GITHUB_WORKFLOW_REPOSITORY_OID 193 194 195class GitHubWorkflowRef(_SingleX509ExtPolicy): 196 """ 197 Verifies the certificate's GitHub Actions workflow ref, 198 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.6`. 199 """ 200 201 oid = _OIDC_GITHUB_WORKFLOW_REF_OID 202 203 204class 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 216class 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 225class 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 234class 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 243class 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 252class 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 261class 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 270class 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 279class 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 288class 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 297class 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 306class 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 315class 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 324class 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 333class 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 343class VerificationPolicy(Protocol): 344 """ 345 A protocol type describing the interface that all verification policies 346 conform to. 347 """ 348 349 @abstractmethod 350 def verify(self, cert: Certificate) -> None: 351 """ 352 Verify the given `cert` against this policy, raising `VerificationError` 353 on failure. 354 """ 355 raise NotImplementedError # pragma: no cover 356 357 358class AnyOf: 359 """ 360 The "any of" policy, corresponding to a logical OR between child policies. 361 362 An empty list of child policies is considered trivially invalid. 363 """ 364 365 def __init__(self, children: list[VerificationPolicy]): 366 """ 367 Create a new `AnyOf`, with the given child policies. 368 """ 369 self._children = children 370 371 def verify(self, cert: Certificate) -> None: 372 """ 373 Verify `cert` against the policy. 374 375 Raises `VerificationError` on failure. 376 """ 377 378 for child in self._children: 379 try: 380 child.verify(cert) 381 except VerificationError: 382 pass 383 else: 384 return 385 386 raise VerificationError(f"0 of {len(self._children)} policies succeeded") 387 388 389class AllOf: 390 """ 391 The "all of" policy, corresponding to a logical AND between child 392 policies. 393 394 An empty list of child policies is considered trivially invalid. 395 """ 396 397 def __init__(self, children: list[VerificationPolicy]): 398 """ 399 Create a new `AllOf`, with the given child policies. 400 """ 401 402 self._children = children 403 404 def verify(self, cert: Certificate) -> None: 405 """ 406 Verify `cert` against the policy. 407 """ 408 409 # Without this, we'd consider empty lists of child policies trivially valid. 410 # This is almost certainly not what the user wants and is a potential 411 # source of API misuse, so we explicitly disallow it. 412 if len(self._children) < 1: 413 raise VerificationError("no child policies to verify") 414 415 for child in self._children: 416 child.verify(cert) 417 418 419class UnsafeNoOp: 420 """ 421 The "no-op" policy, corresponding to a no-op "verification". 422 423 **This policy is fundamentally insecure. You cannot use it safely. 424 It must not be used to verify any sort of certificate identity, because 425 it cannot do so. Using this policy is equivalent to reducing the 426 verification proof down to an integrity check against a completely 427 untrusted and potentially attacker-created signature. It must only 428 be used for testing purposes.** 429 """ 430 431 def verify(self, cert: Certificate) -> None: 432 """ 433 Verify `cert` against the policy. 434 """ 435 436 _logger.warning( 437 "unsafe (no-op) verification policy used! no verification performed!" 438 ) 439 440 441class Identity: 442 """ 443 Verifies the certificate's "identity", corresponding to the X.509v3 SAN. 444 445 Identities can be verified modulo an OIDC issuer, to prevent an unexpected 446 issuer from offering a particular identity. 447 448 Supported SAN types include emails, URIs, and Sigstore-specific "other names". 449 """ 450 451 _issuer: OIDCIssuer | None 452 453 def __init__(self, *, identity: str, issuer: str | None = None): 454 """ 455 Create a new `Identity`, with the given expected identity and issuer values. 456 """ 457 458 self._identity = identity 459 if issuer: 460 self._issuer = OIDCIssuer(issuer) 461 else: 462 self._issuer = None 463 464 def verify(self, cert: Certificate) -> None: 465 """ 466 Verify `cert` against the policy. 467 """ 468 469 if self._issuer: 470 self._issuer.verify(cert) 471 472 # Build a set of all valid identities. 473 san_ext = cert.extensions.get_extension_for_class(SubjectAlternativeName).value 474 all_sans = set(san_ext.get_values_for_type(RFC822Name)) 475 all_sans.update(san_ext.get_values_for_type(UniformResourceIdentifier)) 476 all_sans.update( 477 [ 478 on.value.decode() 479 for on in san_ext.get_values_for_type(OtherName) 480 if on.type_id == _OTHERNAME_OID 481 ] 482 ) 483 484 verified = self._identity in all_sans 485 if not verified: 486 raise VerificationError( 487 f"Certificate's SANs do not match {self._identity}; actual SANs: {all_sans}" 488 )
151class OIDCIssuer(_SingleX509ExtPolicy): 152 """ 153 Verifies the certificate's OIDC issuer, identified by 154 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.1`. 155 """ 156 157 oid = _OIDC_ISSUER_OID
Verifies the certificate's OIDC issuer, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.1
.
The OID of the extension being checked.
Inherited Members
160class GitHubWorkflowTrigger(_SingleX509ExtPolicy): 161 """ 162 Verifies the certificate's GitHub Actions workflow trigger, 163 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.2`. 164 """ 165 166 oid = _OIDC_GITHUB_WORKFLOW_TRIGGER_OID
Verifies the certificate's GitHub Actions workflow trigger,
identified by an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.2
.
The OID of the extension being checked.
Inherited Members
169class GitHubWorkflowSHA(_SingleX509ExtPolicy): 170 """ 171 Verifies the certificate's GitHub Actions workflow commit SHA, 172 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.3`. 173 """ 174 175 oid = _OIDC_GITHUB_WORKFLOW_SHA_OID
Verifies the certificate's GitHub Actions workflow commit SHA,
identified by an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.3
.
The OID of the extension being checked.
Inherited Members
178class GitHubWorkflowName(_SingleX509ExtPolicy): 179 """ 180 Verifies the certificate's GitHub Actions workflow name, 181 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.4`. 182 """ 183 184 oid = _OIDC_GITHUB_WORKFLOW_NAME_OID
Verifies the certificate's GitHub Actions workflow name,
identified by an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.4
.
The OID of the extension being checked.
Inherited Members
187class GitHubWorkflowRepository(_SingleX509ExtPolicy): 188 """ 189 Verifies the certificate's GitHub Actions workflow repository, 190 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.5`. 191 """ 192 193 oid = _OIDC_GITHUB_WORKFLOW_REPOSITORY_OID
Verifies the certificate's GitHub Actions workflow repository,
identified by an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.5
.
The OID of the extension being checked.
Inherited Members
196class GitHubWorkflowRef(_SingleX509ExtPolicy): 197 """ 198 Verifies the certificate's GitHub Actions workflow ref, 199 identified by an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.6`. 200 """ 201 202 oid = _OIDC_GITHUB_WORKFLOW_REF_OID
Verifies the certificate's GitHub Actions workflow ref,
identified by an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.6
.
The OID of the extension being checked.
Inherited Members
205class OIDCIssuerV2(_SingleX509ExtPolicyV2): 206 """ 207 Verifies the certificate's OIDC issuer, identified by 208 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.8`. 209 The difference with `OIDCIssuer` is that the value for 210 this extension is formatted to the RFC 5280 specification 211 as a DER-encoded string. 212 """ 213 214 oid = _OIDC_ISSUER_V2_OID
Verifies the certificate's OIDC issuer, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.8
.
The difference with OIDCIssuer
is that the value for
this extension is formatted to the RFC 5280 specification
as a DER-encoded string.
The OID of the extension being checked.
Inherited Members
217class OIDCBuildSignerURI(_SingleX509ExtPolicyV2): 218 """ 219 Verifies the certificate's OIDC Build Signer URI, identified by 220 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.9`. 221 """ 222 223 oid = _OIDC_BUILD_SIGNER_URI_OID
Verifies the certificate's OIDC Build Signer URI, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.9
.
The OID of the extension being checked.
Inherited Members
226class OIDCBuildSignerDigest(_SingleX509ExtPolicyV2): 227 """ 228 Verifies the certificate's OIDC Build Signer Digest, identified by 229 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.10`. 230 """ 231 232 oid = _OIDC_BUILD_SIGNER_DIGEST_OID
Verifies the certificate's OIDC Build Signer Digest, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.10
.
The OID of the extension being checked.
Inherited Members
235class OIDCRunnerEnvironment(_SingleX509ExtPolicyV2): 236 """ 237 Verifies the certificate's OIDC Runner Environment, identified by 238 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.11`. 239 """ 240 241 oid = _OIDC_RUNNER_ENVIRONMENT_OID
Verifies the certificate's OIDC Runner Environment, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.11
.
The OID of the extension being checked.
Inherited Members
244class OIDCSourceRepositoryURI(_SingleX509ExtPolicyV2): 245 """ 246 Verifies the certificate's OIDC Source Repository URI, identified by 247 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.12`. 248 """ 249 250 oid = _OIDC_SOURCE_REPOSITORY_URI_OID
Verifies the certificate's OIDC Source Repository URI, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.12
.
The OID of the extension being checked.
Inherited Members
253class OIDCSourceRepositoryDigest(_SingleX509ExtPolicyV2): 254 """ 255 Verifies the certificate's OIDC Source Repository Digest, identified by 256 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.13`. 257 """ 258 259 oid = _OIDC_SOURCE_REPOSITORY_DIGEST_OID
Verifies the certificate's OIDC Source Repository Digest, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.13
.
The OID of the extension being checked.
Inherited Members
262class OIDCSourceRepositoryRef(_SingleX509ExtPolicyV2): 263 """ 264 Verifies the certificate's OIDC Source Repository Ref, identified by 265 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.14`. 266 """ 267 268 oid = _OIDC_SOURCE_REPOSITORY_REF_OID
Verifies the certificate's OIDC Source Repository Ref, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.14
.
The OID of the extension being checked.
Inherited Members
271class OIDCSourceRepositoryIdentifier(_SingleX509ExtPolicyV2): 272 """ 273 Verifies the certificate's OIDC Source Repository Identifier, identified by 274 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.15`. 275 """ 276 277 oid = _OIDC_SOURCE_REPOSITORY_IDENTIFIER_OID
Verifies the certificate's OIDC Source Repository Identifier, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.15
.
The OID of the extension being checked.
Inherited Members
280class OIDCSourceRepositoryOwnerURI(_SingleX509ExtPolicyV2): 281 """ 282 Verifies the certificate's OIDC Source Repository Owner URI, identified by 283 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.16`. 284 """ 285 286 oid = _OIDC_SOURCE_REPOSITORY_OWNER_URI_OID
Verifies the certificate's OIDC Source Repository Owner URI, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.16
.
The OID of the extension being checked.
Inherited Members
289class OIDCSourceRepositoryOwnerIdentifier(_SingleX509ExtPolicyV2): 290 """ 291 Verifies the certificate's OIDC Source Repository Owner Identifier, identified by 292 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.17`. 293 """ 294 295 oid = _OIDC_SOURCE_REPOSITORY_OWNER_IDENTIFIER_OID
Verifies the certificate's OIDC Source Repository Owner Identifier, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.17
.
The OID of the extension being checked.
Inherited Members
298class OIDCBuildConfigURI(_SingleX509ExtPolicyV2): 299 """ 300 Verifies the certificate's OIDC Build Config URI, identified by 301 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.18`. 302 """ 303 304 oid = _OIDC_BUILD_CONFIG_URI_OID
Verifies the certificate's OIDC Build Config URI, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.18
.
The OID of the extension being checked.
Inherited Members
307class OIDCBuildConfigDigest(_SingleX509ExtPolicyV2): 308 """ 309 Verifies the certificate's OIDC Build Config Digest, identified by 310 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.19`. 311 """ 312 313 oid = _OIDC_BUILD_CONFIG_DIGEST_OID
Verifies the certificate's OIDC Build Config Digest, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.19
.
The OID of the extension being checked.
Inherited Members
316class OIDCBuildTrigger(_SingleX509ExtPolicyV2): 317 """ 318 Verifies the certificate's OIDC Build Trigger, identified by 319 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.20`. 320 """ 321 322 oid = _OIDC_BUILD_TRIGGER_OID
Verifies the certificate's OIDC Build Trigger, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.20
.
The OID of the extension being checked.
Inherited Members
325class OIDCRunInvocationURI(_SingleX509ExtPolicyV2): 326 """ 327 Verifies the certificate's OIDC Run Invocation URI, identified by 328 an X.509v3 extension tagged with `1.3.6.1.4.1.57264.1.21`. 329 """ 330 331 oid = _OIDC_RUN_INVOCATION_URI_OID
Verifies the certificate's OIDC Run Invocation URI, identified by
an X.509v3 extension tagged with 1.3.6.1.4.1.57264.1.21
.
The OID of the extension being checked.
Inherited Members
334class OIDCSourceRepositoryVisibility(_SingleX509ExtPolicyV2): 335 """ 336 Verifies the certificate's OIDC Source Repository Visibility 337 At Signing, identified by an X.509v3 extension tagged with 338 `1.3.6.1.4.1.57264.1.22`. 339 """ 340 341 oid = _OIDC_SOURCE_REPOSITORY_VISIBILITY_OID
Verifies the certificate's OIDC Source Repository Visibility
At Signing, identified by an X.509v3 extension tagged with
1.3.6.1.4.1.57264.1.22
.
The OID of the extension being checked.
Inherited Members
344class VerificationPolicy(Protocol): 345 """ 346 A protocol type describing the interface that all verification policies 347 conform to. 348 """ 349 350 @abstractmethod 351 def verify(self, cert: Certificate) -> None: 352 """ 353 Verify the given `cert` against this policy, raising `VerificationError` 354 on failure. 355 """ 356 raise NotImplementedError # pragma: no cover
A protocol type describing the interface that all verification policies conform to.
350 @abstractmethod 351 def verify(self, cert: Certificate) -> None: 352 """ 353 Verify the given `cert` against this policy, raising `VerificationError` 354 on failure. 355 """ 356 raise NotImplementedError # pragma: no cover
Verify the given cert
against this policy, raising VerificationError
on failure.
359class AnyOf: 360 """ 361 The "any of" policy, corresponding to a logical OR between child policies. 362 363 An empty list of child policies is considered trivially invalid. 364 """ 365 366 def __init__(self, children: list[VerificationPolicy]): 367 """ 368 Create a new `AnyOf`, with the given child policies. 369 """ 370 self._children = children 371 372 def verify(self, cert: Certificate) -> None: 373 """ 374 Verify `cert` against the policy. 375 376 Raises `VerificationError` on failure. 377 """ 378 379 for child in self._children: 380 try: 381 child.verify(cert) 382 except VerificationError: 383 pass 384 else: 385 return 386 387 raise VerificationError(f"0 of {len(self._children)} policies succeeded")
The "any of" policy, corresponding to a logical OR between child policies.
An empty list of child policies is considered trivially invalid.
366 def __init__(self, children: list[VerificationPolicy]): 367 """ 368 Create a new `AnyOf`, with the given child policies. 369 """ 370 self._children = children
Create a new AnyOf
, with the given child policies.
372 def verify(self, cert: Certificate) -> None: 373 """ 374 Verify `cert` against the policy. 375 376 Raises `VerificationError` on failure. 377 """ 378 379 for child in self._children: 380 try: 381 child.verify(cert) 382 except VerificationError: 383 pass 384 else: 385 return 386 387 raise VerificationError(f"0 of {len(self._children)} policies succeeded")
Verify cert
against the policy.
Raises VerificationError
on failure.
390class AllOf: 391 """ 392 The "all of" policy, corresponding to a logical AND between child 393 policies. 394 395 An empty list of child policies is considered trivially invalid. 396 """ 397 398 def __init__(self, children: list[VerificationPolicy]): 399 """ 400 Create a new `AllOf`, with the given child policies. 401 """ 402 403 self._children = children 404 405 def verify(self, cert: Certificate) -> None: 406 """ 407 Verify `cert` against the policy. 408 """ 409 410 # Without this, we'd consider empty lists of child policies trivially valid. 411 # This is almost certainly not what the user wants and is a potential 412 # source of API misuse, so we explicitly disallow it. 413 if len(self._children) < 1: 414 raise VerificationError("no child policies to verify") 415 416 for child in self._children: 417 child.verify(cert)
The "all of" policy, corresponding to a logical AND between child policies.
An empty list of child policies is considered trivially invalid.
398 def __init__(self, children: list[VerificationPolicy]): 399 """ 400 Create a new `AllOf`, with the given child policies. 401 """ 402 403 self._children = children
Create a new AllOf
, with the given child policies.
405 def verify(self, cert: Certificate) -> None: 406 """ 407 Verify `cert` against the policy. 408 """ 409 410 # Without this, we'd consider empty lists of child policies trivially valid. 411 # This is almost certainly not what the user wants and is a potential 412 # source of API misuse, so we explicitly disallow it. 413 if len(self._children) < 1: 414 raise VerificationError("no child policies to verify") 415 416 for child in self._children: 417 child.verify(cert)
Verify cert
against the policy.
420class UnsafeNoOp: 421 """ 422 The "no-op" policy, corresponding to a no-op "verification". 423 424 **This policy is fundamentally insecure. You cannot use it safely. 425 It must not be used to verify any sort of certificate identity, because 426 it cannot do so. Using this policy is equivalent to reducing the 427 verification proof down to an integrity check against a completely 428 untrusted and potentially attacker-created signature. It must only 429 be used for testing purposes.** 430 """ 431 432 def verify(self, cert: Certificate) -> None: 433 """ 434 Verify `cert` against the policy. 435 """ 436 437 _logger.warning( 438 "unsafe (no-op) verification policy used! no verification performed!" 439 )
The "no-op" policy, corresponding to a no-op "verification".
This policy is fundamentally insecure. You cannot use it safely. It must not be used to verify any sort of certificate identity, because it cannot do so. Using this policy is equivalent to reducing the verification proof down to an integrity check against a completely untrusted and potentially attacker-created signature. It must only be used for testing purposes.
432 def verify(self, cert: Certificate) -> None: 433 """ 434 Verify `cert` against the policy. 435 """ 436 437 _logger.warning( 438 "unsafe (no-op) verification policy used! no verification performed!" 439 )
Verify cert
against the policy.
442class Identity: 443 """ 444 Verifies the certificate's "identity", corresponding to the X.509v3 SAN. 445 446 Identities can be verified modulo an OIDC issuer, to prevent an unexpected 447 issuer from offering a particular identity. 448 449 Supported SAN types include emails, URIs, and Sigstore-specific "other names". 450 """ 451 452 _issuer: OIDCIssuer | None 453 454 def __init__(self, *, identity: str, issuer: str | None = None): 455 """ 456 Create a new `Identity`, with the given expected identity and issuer values. 457 """ 458 459 self._identity = identity 460 if issuer: 461 self._issuer = OIDCIssuer(issuer) 462 else: 463 self._issuer = None 464 465 def verify(self, cert: Certificate) -> None: 466 """ 467 Verify `cert` against the policy. 468 """ 469 470 if self._issuer: 471 self._issuer.verify(cert) 472 473 # Build a set of all valid identities. 474 san_ext = cert.extensions.get_extension_for_class(SubjectAlternativeName).value 475 all_sans = set(san_ext.get_values_for_type(RFC822Name)) 476 all_sans.update(san_ext.get_values_for_type(UniformResourceIdentifier)) 477 all_sans.update( 478 [ 479 on.value.decode() 480 for on in san_ext.get_values_for_type(OtherName) 481 if on.type_id == _OTHERNAME_OID 482 ] 483 ) 484 485 verified = self._identity in all_sans 486 if not verified: 487 raise VerificationError( 488 f"Certificate's SANs do not match {self._identity}; actual SANs: {all_sans}" 489 )
Verifies the certificate's "identity", corresponding to the X.509v3 SAN.
Identities can be verified modulo an OIDC issuer, to prevent an unexpected issuer from offering a particular identity.
Supported SAN types include emails, URIs, and Sigstore-specific "other names".
454 def __init__(self, *, identity: str, issuer: str | None = None): 455 """ 456 Create a new `Identity`, with the given expected identity and issuer values. 457 """ 458 459 self._identity = identity 460 if issuer: 461 self._issuer = OIDCIssuer(issuer) 462 else: 463 self._issuer = None
Create a new Identity
, with the given expected identity and issuer values.
465 def verify(self, cert: Certificate) -> None: 466 """ 467 Verify `cert` against the policy. 468 """ 469 470 if self._issuer: 471 self._issuer.verify(cert) 472 473 # Build a set of all valid identities. 474 san_ext = cert.extensions.get_extension_for_class(SubjectAlternativeName).value 475 all_sans = set(san_ext.get_values_for_type(RFC822Name)) 476 all_sans.update(san_ext.get_values_for_type(UniformResourceIdentifier)) 477 all_sans.update( 478 [ 479 on.value.decode() 480 for on in san_ext.get_values_for_type(OtherName) 481 if on.type_id == _OTHERNAME_OID 482 ] 483 ) 484 485 verified = self._identity in all_sans 486 if not verified: 487 raise VerificationError( 488 f"Certificate's SANs do not match {self._identity}; actual SANs: {all_sans}" 489 )
Verify cert
against the policy.