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
87 changes: 87 additions & 0 deletions .github/workflows/cross-os.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright 2025 The Sigstore Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Cross-platform sign and verify
on:
push:
branches:
- main
- series/*
pull_request:
workflow_dispatch:

permissions: {}

defaults:
run:
shell: bash

jobs:
sign:
name: Sign on ${{ matrix.os }}
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu, macos, windows]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.x"
cache: "pip"
cache-dependency-path: pyproject.toml
- run: pip install .
- name: Fetch testing oidc token
uses: sigstore-conformance/extremely-dangerous-public-oidc-beacon@b517a742e5a3db9e3cbf8e2e1c792b36982f78db # main
- name: Sign
run: python -m sigstore --staging sign --identity-token $(cat oidc-token.txt) test/assets/a.txt
- name: upload signature bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ matrix.os }}-bundle
path: test/assets/a.txt.sigstore.json
if-no-files-found: error
retention-days: 1
verify:
name: Verify ${{ matrix.signed-with-os }} bundle on ${{ matrix.os }}
if: ${{ always() }} # don't stop some verification if one of the signing jobs failed
needs: [sign]
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false # Don't cancel other jobs if one fails
matrix:
os: [ubuntu, macos, windows]
signed-with-os: [ubuntu, macos, windows]
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.x"
cache: "pip"
cache-dependency-path: pyproject.toml
- run: pip install .
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
name: ${{ matrix.signed-with-os }}-bundle
- name: Verify
run: |
python -m sigstore --staging verify github --verbose \
--cert-identity "https://github.com/sigstore-conformance/extremely-dangerous-public-oidc-beacon/.github/workflows/extremely-dangerous-oidc-beacon.yml@refs/heads/main" \
--bundle a.txt.sigstore.json \
test/assets/a.txt
10 changes: 5 additions & 5 deletions sigstore/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,16 +686,16 @@ def _sign_file_threaded(

if outputs.signature is not None:
signature = base64.b64encode(result.signature).decode()
with outputs.signature.open(mode="w") as io:
with outputs.signature.open(mode="w", encoding="utf-8") as io:
print(signature, file=io)

if outputs.certificate is not None:
cert_pem = signer._signing_cert().public_bytes(Encoding.PEM).decode()
with outputs.certificate.open(mode="w") as io:
with outputs.certificate.open(mode="w", encoding="utf-8") as io:
print(cert_pem, file=io)

if outputs.bundle is not None:
with outputs.bundle.open(mode="w") as io:
with outputs.bundle.open(mode="w", encoding="utf-8") as io:
print(result.to_json(), file=io)


Expand Down Expand Up @@ -769,7 +769,7 @@ def _attest(args: argparse.Namespace) -> None:
_invalid_arguments(args, f"Predicate must be a file: {predicate_path}")

try:
with open(predicate_path, "r") as f:
with open(predicate_path, "r", encoding="utf-8") as f:
predicate = json.load(f)
# We do a basic sanity check using our Pydantic models to see if the
# contents of the predicate file match the specified predicate type.
Expand Down Expand Up @@ -1067,7 +1067,7 @@ def _collect_verification_state(

# Load the signature
_logger.debug(f"Using signature from: {materials.signature}")
b64_signature = materials.signature.read_text()
b64_signature = materials.signature.read_text(encoding="utf-8")
signature = base64.b64decode(b64_signature)

# When using "detached" materials, we *must* retrieve the log
Expand Down
2 changes: 1 addition & 1 deletion test/integration/cli/test_attest.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def test_attest_success_default_output_bundle(

assert expected_output_bundle.exists()
verifier = Verifier.staging()
with open(expected_output_bundle, "r") as bundle_file:
with open(expected_output_bundle, "r", encoding="utf-8") as bundle_file:
bundle = Bundle.from_json(bundle_file.read())
verifier.verify_dsse(bundle=bundle, policy=UnsafeNoOp())

Expand Down
6 changes: 3 additions & 3 deletions test/integration/cli/test_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_sign_success_default_output_bundle(
assert expected_output_bundle.exists()
verifier = Verifier.staging()
with (
open(expected_output_bundle, "r") as bundle_file,
open(expected_output_bundle, "r", encoding="utf-8") as bundle_file,
open(artifact, "rb") as input_file,
):
bundle = Bundle.from_json(bundle_file.read())
Expand Down Expand Up @@ -112,7 +112,7 @@ def test_sign_success_multiple_artifacts(capsys, sigstore, asset_integration, tm
assert expected_output_bundle.exists()
verifier = Verifier.staging()
with (
open(expected_output_bundle, "r") as bundle_file,
open(expected_output_bundle, "r", encoding="utf-8") as bundle_file,
open(artifact, "rb") as input_file,
):
bundle = Bundle.from_json(bundle_file.read())
Expand Down Expand Up @@ -154,7 +154,7 @@ def test_sign_success_multiple_artifacts_rekor_v2(
assert expected_output_bundle.exists()
verifier = Verifier.staging()
with (
open(expected_output_bundle, "r") as bundle_file,
open(expected_output_bundle, "r", encoding="utf-8") as bundle_file,
open(artifact, "rb") as input_file,
):
bundle = Bundle.from_json(bundle_file.read())
Expand Down
Loading