diff --git a/attestations.py b/attestations.py index faab9f9..8257743 100644 --- a/attestations.py +++ b/attestations.py @@ -9,11 +9,11 @@ from sigstore.oidc import IdentityError, IdentityToken, detect_credential from sigstore.sign import Signer, SigningContext # Be very verbose. -sigstore_logger = logging.getLogger("sigstore") +sigstore_logger = logging.getLogger('sigstore') sigstore_logger.setLevel(logging.DEBUG) sigstore_logger.addHandler(logging.StreamHandler()) -_GITHUB_STEP_SUMMARY = Path(os.getenv("GITHUB_STEP_SUMMARY")) +_GITHUB_STEP_SUMMARY = Path(os.getenv('GITHUB_STEP_SUMMARY')) # The top-level error message that gets rendered. # This message wraps one of the other templates/messages defined below. @@ -40,46 +40,52 @@ permissions: ``` Learn more at https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings. -""" +""" # noqa: S105; not a password def die(msg: str) -> NoReturn: - with _GITHUB_STEP_SUMMARY.open("a", encoding="utf-8") as io: + with _GITHUB_STEP_SUMMARY.open('a', encoding='utf-8') as io: print(_ERROR_SUMMARY_MESSAGE.format(message=msg), file=io) # HACK: GitHub Actions' annotations don't work across multiple lines naively; # translating `\n` into `%0A` (i.e., HTML percent-encoding) is known to work. # See: https://github.com/actions/toolkit/issues/193 - msg = msg.replace("\n", "%0A") - print(f"::error::Attestation generation failure: {msg}", file=sys.stderr) + msg = msg.replace('\n', '%0A') + print(f'::error::Attestation generation failure: {msg}', file=sys.stderr) sys.exit(1) def debug(msg: str): - print(f"::debug::{msg}", file=sys.stderr) + print(f'::debug::{msg}', file=sys.stderr) # pylint: disable=redefined-outer-name def attest_dist(dist: Path, signer: Signer) -> None: # We are the publishing step, so there should be no pre-existing publish # attestation. The presence of one indicates user confusion. - attestation_path = Path(f"{dist}.publish.attestation") + attestation_path = Path(f'{dist}.publish.attestation') if attestation_path.is_file(): - die(f"{dist} already has a publish attestation: {attestation_path}") + die(f'{dist} already has a publish attestation: {attestation_path}') payload = AttestationPayload.from_dist(dist) attestation = payload.sign(signer) - attestation_path.write_text(attestation.model_dump_json(), encoding="utf-8") - debug(f"saved publish attestation: {dist=} {attestation_path=}") + attestation_path.write_text(attestation.model_dump_json(), encoding='utf-8') + debug(f'saved publish attestation: {dist=} {attestation_path=}') + + +def get_identity_token() -> IdentityToken: + # Will raise `sigstore.oidc.IdentityError` if it fails to get the token + # from the environment or if the token is malformed. + # NOTE: audience is always sigstore. + oidc_token = detect_credential() + return IdentityToken(oidc_token) packages_dir = Path(sys.argv[1]) try: - # NOTE: audience is always sigstore. - oidc_token = detect_credential() - identity = IdentityToken(oidc_token) + identity = get_identity_token() except IdentityError as identity_error: # NOTE: We only perform attestations in trusted publishing flows, so we # don't need to re-check for the "PR from fork" error mode, only @@ -88,8 +94,8 @@ except IdentityError as identity_error: die(cause) # Collect all sdists and wheels. -dists = [sdist.absolute() for sdist in packages_dir.glob("*.tar.gz")] -dists.extend(whl.absolute() for whl in packages_dir.glob("*.whl")) +dists = [sdist.absolute() for sdist in packages_dir.glob('*.tar.gz')] +dists.extend(whl.absolute() for whl in packages_dir.glob('*.whl')) with SigningContext.production().signer(identity, cache=True) as signer: for dist in dists: @@ -97,6 +103,6 @@ with SigningContext.production().signer(identity, cache=True) as signer: # download-artifact will create a subdirectory with the same name # as the artifact being downloaded, e.g. `dist/foo.whl/foo.whl`. if not dist.is_file(): - die(f"Path looks like a distribution but is not a file: {dist}") + die(f'Path looks like a distribution but is not a file: {dist}') attest_dist(dist, signer)