Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions sigstore/sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,36 +151,35 @@ def _signing_cert(
the returned certificate is present in Fulcio's CT log.
"""

# Our CSR cannot possibly succeed if our underlying identity token
# is expired.
if not self._identity_token.in_validity_period():
raise ExpiredIdentity

# If it exists, verify if the current certificate is expired
# If a cached certificate exists, use it until it expires.
if self.__cached_signing_certificate:
not_valid_after = self.__cached_signing_certificate.not_valid_after_utc
if datetime.now(timezone.utc) > not_valid_after:
raise ExpiredCertificate
return self.__cached_signing_certificate

else:
_logger.debug("Retrieving signed certificate...")
# Our CSR cannot possibly succeed if our underlying identity token
# is expired.
if not self._identity_token.in_validity_period():
raise ExpiredIdentity

_logger.debug("Retrieving signed certificate...")

certificate_request = self._build_csr()
certificate_request = self._build_csr()

certificate_response = self._signing_ctx._fulcio.signing_cert.post(
certificate_request, self._identity_token
)
certificate_response = self._signing_ctx._fulcio.signing_cert.post(
certificate_request, self._identity_token
)

verify_sct(
certificate_response.cert,
certificate_response.chain,
self._signing_ctx._trusted_root.ct_keyring(KeyringPurpose.SIGN),
)
verify_sct(
certificate_response.cert,
certificate_response.chain,
self._signing_ctx._trusted_root.ct_keyring(KeyringPurpose.SIGN),
)

_logger.debug("Successfully verified SCT...")
_logger.debug("Successfully verified SCT...")

return certificate_response.cert
return certificate_response.cert

def _finalize_sign(
self,
Expand Down
16 changes: 16 additions & 0 deletions test/unit/test_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,22 @@ def test_build_csr_non_ascii_identity_produces_valid_csr():
assert len(reparsed.subject) == 0


@pytest.mark.staging
@pytest.mark.ambient_oidc
def test_signer_uses_valid_cached_certificate_with_expired_identity(staging):
ctx_cls, _, identity = staging
ctx: SigningContext = ctx_cls()
assert identity is not None

# Constructing a cached signer obtains its certificate while the token is
# valid. Expire the local token afterward, then perform a real signing
# operation: it must reuse the still-valid cached certificate.
with ctx.signer(identity) as signer:
identity._exp = 0
assert not signer._identity_token.in_validity_period()
signer.sign_artifact(secrets.token_bytes(32))


# only check the log contents for production: staging is already on
# rekor v2 and we don't currently support log lookups on rekor v2.
# This test can likely be removed once prod also uses rekor v2
Expand Down
Loading