Skip to content

Commit 46fa1a5

Browse files
authored
chore: improve types and add interop test workflow (#9)
1 parent 1993fa0 commit 46fa1a5

File tree

22 files changed

+1368
-159
lines changed

22 files changed

+1368
-159
lines changed

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Preserve line endings in test data files (hashes depend on exact content)
2+
**/test_data/** binary
3+
**/fixtures/** binary

.github/workflows/interop.yml

Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
name: Interoperability Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
workflow_dispatch:
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
13+
jobs:
14+
interop:
15+
name: Interoperability Tests
16+
runs-on: ubuntu-latest
17+
permissions:
18+
id-token: write # Required for OIDC token
19+
contents: read
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- uses: dtolnay/[email protected]
24+
25+
- name: Install Cosign
26+
uses: sigstore/[email protected]
27+
with:
28+
cosign-release: 'v3.0.2'
29+
30+
- name: Build release binaries
31+
run: cargo build --release -p sigstore-sign -p sigstore-verify --examples
32+
33+
# =========================================
34+
# Setup: Create test artifacts
35+
# =========================================
36+
- name: Create test artifacts
37+
run: |
38+
echo "Hello from sigstore-rust interop test at $(date)" > test-artifact.txt
39+
echo "Hello from sigstore-rust interop test V2 at $(date)" > test-artifact-v2.txt
40+
echo "Digest-based verification test at $(date)" > digest-test.txt
41+
echo "Test package content for attestation at $(date)" > test-package.txt
42+
43+
echo "Test artifacts created:"
44+
sha256sum test-artifact.txt test-artifact-v2.txt digest-test.txt test-package.txt
45+
46+
# Store digest for later use
47+
DIGEST=$(sha256sum digest-test.txt | cut -d' ' -f1)
48+
echo "ARTIFACT_DIGEST=sha256:${DIGEST}" >> $GITHUB_ENV
49+
50+
# =========================================
51+
# REKOR V1: Blob Signing Tests
52+
# =========================================
53+
- name: "[V1] Sign with sigstore-rust"
54+
run: |
55+
./target/release/examples/sign_blob test-artifact.txt -o rust-signed.sigstore.json
56+
echo "Bundle created:"
57+
cat rust-signed.sigstore.json | jq -r '.mediaType'
58+
59+
- name: "[V1] Verify sigstore-rust signature with cosign"
60+
run: |
61+
cosign verify-blob \
62+
--bundle rust-signed.sigstore.json \
63+
--certificate-identity-regexp ".*" \
64+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
65+
test-artifact.txt
66+
echo "✅ Cosign successfully verified sigstore-rust signature (V1)"
67+
68+
- name: "[V1] Verify sigstore-rust signature with sigstore-rust"
69+
run: |
70+
./target/release/examples/verify_bundle \
71+
--certificate-identity-regexp ".*" \
72+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
73+
test-artifact.txt rust-signed.sigstore.json
74+
echo "✅ sigstore-rust successfully verified its own signature (V1)"
75+
76+
- name: "[V1] Sign with cosign"
77+
run: |
78+
cosign version
79+
cosign sign-blob \
80+
--yes \
81+
--bundle cosign-signed.sigstore.json \
82+
test-artifact.txt
83+
echo "Bundle created:"
84+
cat cosign-signed.sigstore.json | jq -r '.mediaType'
85+
86+
- name: "[V1] Verify cosign signature with sigstore-rust"
87+
run: |
88+
./target/release/examples/verify_bundle \
89+
--certificate-identity-regexp ".*" \
90+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
91+
test-artifact.txt cosign-signed.sigstore.json
92+
echo "✅ sigstore-rust successfully verified cosign signature (V1)"
93+
94+
- name: "[V1] Verify cosign signature with cosign (sanity check)"
95+
run: |
96+
cosign verify-blob \
97+
--bundle cosign-signed.sigstore.json \
98+
--certificate-identity-regexp ".*" \
99+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
100+
test-artifact.txt
101+
echo "✅ Cosign successfully verified its own signature (V1)"
102+
103+
# =========================================
104+
# REKOR V2: Blob Signing Tests
105+
# =========================================
106+
- name: "[V2] Sign with sigstore-rust --v2"
107+
run: |
108+
./target/release/examples/sign_blob --v2 test-artifact-v2.txt -o rust-signed-v2.sigstore.json
109+
echo "Bundle created:"
110+
cat rust-signed-v2.sigstore.json | jq -r '.mediaType'
111+
echo "Entry kind/version:"
112+
cat rust-signed-v2.sigstore.json | jq -r '.verificationMaterial.tlogEntries[0].kindVersion'
113+
114+
- name: "[V2] Verify sigstore-rust V2 signature with cosign"
115+
run: |
116+
# V2 bundles use RFC3161 timestamps instead of integratedTime
117+
cosign verify-blob \
118+
--bundle rust-signed-v2.sigstore.json \
119+
--certificate-identity-regexp ".*" \
120+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
121+
--use-signed-timestamps \
122+
test-artifact-v2.txt
123+
echo "✅ Cosign successfully verified sigstore-rust V2 signature"
124+
125+
- name: "[V2] Verify sigstore-rust V2 signature with sigstore-rust"
126+
run: |
127+
./target/release/examples/verify_bundle \
128+
--certificate-identity-regexp ".*" \
129+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
130+
test-artifact-v2.txt rust-signed-v2.sigstore.json
131+
echo "✅ sigstore-rust successfully verified its own V2 signature"
132+
133+
- name: "[V2] Sign with cosign"
134+
run: |
135+
cosign sign-blob \
136+
--yes \
137+
--bundle cosign-signed-v2.sigstore.json \
138+
test-artifact-v2.txt
139+
echo "Bundle created:"
140+
cat cosign-signed-v2.sigstore.json | jq -r '.mediaType'
141+
142+
- name: "[V2] Verify cosign V2 signature with sigstore-rust"
143+
run: |
144+
./target/release/examples/verify_bundle \
145+
--certificate-identity-regexp ".*" \
146+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
147+
test-artifact-v2.txt cosign-signed-v2.sigstore.json
148+
echo "✅ sigstore-rust successfully verified cosign V2 signature"
149+
150+
- name: "[V2] Verify cosign V2 signature with cosign (sanity check)"
151+
run: |
152+
cosign verify-blob \
153+
--bundle cosign-signed-v2.sigstore.json \
154+
--certificate-identity-regexp ".*" \
155+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
156+
test-artifact-v2.txt
157+
echo "✅ Cosign successfully verified its own V2 signature"
158+
159+
# =========================================
160+
# DIGEST: Digest-based Verification Tests
161+
# =========================================
162+
- name: "[Digest] Sign with sigstore-rust"
163+
run: |
164+
./target/release/examples/sign_blob digest-test.txt -o digest-bundle.sigstore.json
165+
166+
- name: "[Digest] Verify with cosign using digest"
167+
run: |
168+
cosign verify-blob \
169+
--bundle digest-bundle.sigstore.json \
170+
--certificate-identity-regexp ".*" \
171+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
172+
${{ env.ARTIFACT_DIGEST }}
173+
echo "✅ Cosign verified using digest"
174+
175+
- name: "[Digest] Verify with sigstore-rust using digest"
176+
run: |
177+
./target/release/examples/verify_bundle \
178+
--certificate-identity-regexp ".*" \
179+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
180+
${{ env.ARTIFACT_DIGEST }} digest-bundle.sigstore.json
181+
echo "✅ sigstore-rust verified using digest"
182+
183+
- name: "[Digest] Sign with cosign"
184+
run: |
185+
cosign sign-blob \
186+
--yes \
187+
--bundle cosign-digest-bundle.sigstore.json \
188+
digest-test.txt
189+
190+
- name: "[Digest] Verify cosign bundle with sigstore-rust using digest"
191+
run: |
192+
./target/release/examples/verify_bundle \
193+
--certificate-identity-regexp ".*" \
194+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
195+
${{ env.ARTIFACT_DIGEST }} cosign-digest-bundle.sigstore.json
196+
echo "✅ sigstore-rust verified cosign bundle using digest"
197+
198+
# =========================================
199+
# DSSE: Attestation Tests
200+
# =========================================
201+
- name: "[DSSE] Attest with sigstore-rust"
202+
run: |
203+
./target/release/examples/sign_attestation \
204+
--channel "https://example.com/test-channel" \
205+
test-package.txt -o rust-attestation.sigstore.json
206+
echo "Attestation bundle created:"
207+
cat rust-attestation.sigstore.json | jq -r '.mediaType'
208+
echo "Entry kind:"
209+
cat rust-attestation.sigstore.json | jq -r '.verificationMaterial.tlogEntries[0].kindVersion.kind'
210+
211+
- name: "[DSSE] Verify sigstore-rust attestation with cosign"
212+
run: |
213+
cosign verify-blob-attestation \
214+
--bundle rust-attestation.sigstore.json \
215+
--certificate-identity-regexp ".*" \
216+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
217+
--type "https://schemas.conda.org/attestations-publish-1.schema.json" \
218+
test-package.txt
219+
echo "✅ Cosign successfully verified sigstore-rust attestation"
220+
221+
- name: "[DSSE] Verify sigstore-rust attestation with sigstore-rust"
222+
run: |
223+
./target/release/examples/verify_conda_attestation \
224+
test-package.txt rust-attestation.sigstore.json
225+
echo "✅ sigstore-rust successfully verified its own attestation"
226+
227+
- name: "[DSSE] Attest with cosign"
228+
run: |
229+
# Create a predicate for cosign
230+
cat > predicate.json << EOF
231+
{
232+
"targetChannel": "https://example.com/cosign-test-channel"
233+
}
234+
EOF
235+
236+
cosign attest-blob \
237+
--yes \
238+
--bundle cosign-attestation.sigstore.json \
239+
--predicate predicate.json \
240+
--type "https://schemas.conda.org/attestations-publish-1.schema.json" \
241+
test-package.txt
242+
echo "Attestation bundle created:"
243+
cat cosign-attestation.sigstore.json | jq -r '.mediaType'
244+
245+
- name: "[DSSE] Verify cosign attestation with sigstore-rust"
246+
run: |
247+
./target/release/examples/verify_conda_attestation \
248+
test-package.txt cosign-attestation.sigstore.json
249+
echo "✅ sigstore-rust successfully verified cosign attestation"
250+
251+
- name: "[DSSE] Verify cosign attestation with cosign (sanity check)"
252+
run: |
253+
cosign verify-blob-attestation \
254+
--bundle cosign-attestation.sigstore.json \
255+
--certificate-identity-regexp ".*" \
256+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
257+
--type "https://schemas.conda.org/attestations-publish-1.schema.json" \
258+
test-package.txt
259+
echo "✅ Cosign successfully verified its own attestation"
260+
261+
# =========================================
262+
# SIGSTORE-PYTHON: Cross-implementation verification
263+
# =========================================
264+
- name: Install sigstore-python
265+
run: |
266+
pip install sigstore
267+
sigstore --version
268+
269+
- name: "[Python] Verify sigstore-rust V1 bundle"
270+
run: |
271+
# GitHub Actions identity is the workflow file URL
272+
IDENTITY="https://github.com/${{ github.repository }}/.github/workflows/interop.yml@${{ github.ref }}"
273+
echo "Expected identity: $IDENTITY"
274+
sigstore verify identity \
275+
--bundle rust-signed.sigstore.json \
276+
--cert-identity "$IDENTITY" \
277+
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
278+
test-artifact.txt
279+
echo "✅ sigstore-python verified sigstore-rust V1 bundle"
280+
281+
- name: "[Python] Verify sigstore-rust V2 bundle"
282+
run: |
283+
IDENTITY="https://github.com/${{ github.repository }}/.github/workflows/interop.yml@${{ github.ref }}"
284+
sigstore verify identity \
285+
--bundle rust-signed-v2.sigstore.json \
286+
--cert-identity "$IDENTITY" \
287+
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
288+
test-artifact-v2.txt
289+
echo "✅ sigstore-python verified sigstore-rust V2 bundle"
290+
291+
- name: "[Python] Verify sigstore-rust attestation"
292+
run: |
293+
IDENTITY="https://github.com/${{ github.repository }}/.github/workflows/interop.yml@${{ github.ref }}"
294+
sigstore verify identity \
295+
--bundle rust-attestation.sigstore.json \
296+
--cert-identity "$IDENTITY" \
297+
--cert-oidc-issuer "https://token.actions.githubusercontent.com" \
298+
test-package.txt
299+
echo "✅ sigstore-python verified sigstore-rust attestation"
300+
301+
# =========================================
302+
# BUNDLE FORMAT: Structural compatibility checks
303+
# =========================================
304+
- name: "[Format] Check sigstore-rust V1 bundle format"
305+
run: python scripts/compare_bundles.py --check rust-signed.sigstore.json
306+
307+
- name: "[Format] Check sigstore-rust V2 bundle format"
308+
run: python scripts/compare_bundles.py --check rust-signed-v2.sigstore.json
309+
310+
- name: "[Format] Compare V1 bundles (sigstore-rust vs cosign)"
311+
run: python scripts/compare_bundles.py rust-signed.sigstore.json cosign-signed.sigstore.json
312+
313+
- name: "[Format] Compare attestation bundles (sigstore-rust vs cosign)"
314+
run: python scripts/compare_bundles.py rust-attestation.sigstore.json cosign-attestation.sigstore.json

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ chrono = { version = "0.4", features = ["serde"] }
6969
# Testing
7070
hex = "0.4"
7171
rstest = { version = "0.26", default-features = false }
72+
regex = "1.11"
7273

7374
# Logging
7475
tracing = { version = "0.1" }

0 commit comments

Comments
 (0)