Skip to content

Commit 2e01233

Browse files
authored
Merge pull request #245 from trail-of-forks/alex/conformance-pr
Add conformance testing
2 parents ec9878a + f5f7d14 commit 2e01233

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

.github/workflows/conformance.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Conformance Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request_target:
8+
types: [labeled]
9+
workflow_dispatch:
10+
11+
jobs:
12+
conformance:
13+
strategy:
14+
matrix:
15+
java-version: [11, 17]
16+
fail-fast: false
17+
18+
permissions:
19+
# Needed to access the workflow's OIDC identity.
20+
id-token: write
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@d171c3b028d844f2bf14e9fdec0c58114451e4bf
24+
25+
- name: Set up JDK ${{ matrix.java-version }}
26+
uses: actions/setup-java@v3
27+
with:
28+
java-version: ${{ matrix.java-version }}
29+
distribution: 'temurin'
30+
31+
- name: Build sigstore-java
32+
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # tag=v2.3.3
33+
with:
34+
arguments: :sigstore-conformance:build
35+
36+
- name: Unpack sigstore-java distribution
37+
run: tar -xvf ${{ github.workspace }}/sigstore-conformance/build/distributions/sigstore-conformance-*.tar --strip-components 1
38+
39+
- uses: trailofbits/sigstore-conformance@0748d63c53810e36cc3f4bbe4114301080f0d844
40+
with:
41+
entrypoint: ${{ github.workspace }}/bin/sigstore-conformance

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ include("sigstore-java")
77
include("sigstore-gradle:sigstore-gradle-sign-base-plugin")
88
include("sigstore-gradle:sigstore-gradle-sign-plugin")
99
include("sigstore-testkit")
10+
include("sigstore-conformance")

sigstore-conformance/build.gradle.kts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
plugins {
2+
id("java")
3+
id("application")
4+
id("com.diffplug.spotless") version "6.11.0"
5+
}
6+
7+
repositories {
8+
mavenCentral()
9+
}
10+
11+
dependencies {
12+
implementation(project(":sigstore-java"))
13+
implementation("com.google.guava:guava:31.1-jre")
14+
}
15+
16+
spotless {
17+
kotlinGradle {
18+
target("*.gradle.kts") // default target for kotlinGradle
19+
ktlint()
20+
}
21+
format("misc") {
22+
target("*.md", ".gitignore", "**/*.yaml")
23+
24+
trimTrailingWhitespace()
25+
indentWithSpaces()
26+
endWithNewline()
27+
}
28+
java {
29+
googleJavaFormat("1.6")
30+
licenseHeaderFile("$rootDir/config/licenseHeader")
31+
}
32+
}
33+
34+
application {
35+
mainClass.set("dev.sigstore.conformance.Main")
36+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright 2022 The Sigstore Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package dev.sigstore.conformance;
17+
18+
import static com.google.common.io.Files.asByteSource;
19+
import static dev.sigstore.encryption.certificates.Certificates.toPemString;
20+
21+
import com.google.common.hash.Hashing;
22+
import dev.sigstore.KeylessSigner;
23+
import dev.sigstore.KeylessVerifier;
24+
import dev.sigstore.oidc.client.GithubActionsOidcClient;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.nio.file.Paths;
28+
29+
public class Main {
30+
private static final String SIGN_COMMAND = "sign";
31+
private static final String VERIFY_COMMAND = "verify";
32+
private static final String SIGNATURE_FLAG = "--signature";
33+
private static final String CERTIFICATE_FLAG = "--certificate";
34+
private static final String CERTIFICATE_IDENTITY_FLAG = "--certificate-identity";
35+
private static final String CERTIFICATE_OIDC_ISSUER_FLAG = "--certificate-oidc-issuer";
36+
37+
public static void main(String[] args) throws Exception {
38+
Arguments a = new Arguments(args);
39+
final var action = a.getNextArgument();
40+
if (action.equals(SIGN_COMMAND)) {
41+
final SignArguments signArgs = parseSignArguments(a);
42+
executeSign(signArgs);
43+
} else if (action.equals(VERIFY_COMMAND)) {
44+
final VerifyArguments verifyArgs = parseVerifyArguments(a);
45+
executeVerify(verifyArgs);
46+
} else {
47+
throw new IllegalArgumentException("Unrecognized action: " + action);
48+
}
49+
}
50+
51+
private static class Arguments {
52+
private int index;
53+
private final String[] args;
54+
55+
public Arguments(String[] args) {
56+
this.index = 0;
57+
this.args = args;
58+
}
59+
60+
public String getNextArgument() {
61+
if (index >= args.length) {
62+
final var errorMsg =
63+
String.format("Insufficient arguments; amount=%d, requested=%d", args.length, index);
64+
throw new IllegalArgumentException(errorMsg);
65+
}
66+
return args[index++];
67+
}
68+
69+
public void expectNextArgument(String expectedArg) {
70+
final var nextArg = getNextArgument();
71+
if (!expectedArg.equals(nextArg)) {
72+
final var errorMsg =
73+
String.format(
74+
"Found unexpected argument; expected=\"%s\", found=\"%s\"", expectedArg, nextArg);
75+
throw new IllegalArgumentException(errorMsg);
76+
}
77+
}
78+
}
79+
80+
private static class SignArguments {
81+
public Path signature;
82+
public Path certificate;
83+
public Path artifact;
84+
}
85+
86+
private static SignArguments parseSignArguments(Arguments args) {
87+
final var signArgs = new SignArguments();
88+
args.expectNextArgument(SIGNATURE_FLAG);
89+
signArgs.signature = Paths.get(args.getNextArgument());
90+
args.expectNextArgument(CERTIFICATE_FLAG);
91+
signArgs.certificate = Paths.get(args.getNextArgument());
92+
signArgs.artifact = Paths.get(args.getNextArgument());
93+
return signArgs;
94+
}
95+
96+
private static void executeSign(SignArguments args) throws Exception {
97+
final var signer =
98+
KeylessSigner.builder()
99+
.sigstorePublicDefaults()
100+
.oidcClient(GithubActionsOidcClient.builder().build())
101+
.build();
102+
final var result = signer.signFile(args.artifact);
103+
Files.write(args.signature, result.getSignature());
104+
final var pemBytes = toPemString(result.getCertPath()).getBytes();
105+
Files.write(args.certificate, pemBytes);
106+
}
107+
108+
private static class VerifyArguments {
109+
public Path signature;
110+
public Path certificate;
111+
public String certificateIdentity;
112+
public String certificateOidcIssuer;
113+
public Path artifact;
114+
}
115+
116+
private static VerifyArguments parseVerifyArguments(Arguments args) {
117+
final var verifyArgs = new VerifyArguments();
118+
args.expectNextArgument(SIGNATURE_FLAG);
119+
verifyArgs.signature = Paths.get(args.getNextArgument());
120+
args.expectNextArgument(CERTIFICATE_FLAG);
121+
verifyArgs.certificate = Paths.get(args.getNextArgument());
122+
args.expectNextArgument(CERTIFICATE_IDENTITY_FLAG);
123+
verifyArgs.certificateIdentity = args.getNextArgument();
124+
args.expectNextArgument(CERTIFICATE_OIDC_ISSUER_FLAG);
125+
verifyArgs.certificateOidcIssuer = args.getNextArgument();
126+
verifyArgs.artifact = Paths.get(args.getNextArgument());
127+
return verifyArgs;
128+
}
129+
130+
private static void executeVerify(VerifyArguments args) throws Exception {
131+
final var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
132+
final var artifactByteSource = asByteSource(args.artifact.toFile());
133+
final byte[] artifactDigest = artifactByteSource.hash(Hashing.sha256()).asBytes();
134+
verifier.verifyOnline(
135+
artifactDigest, Files.readAllBytes(args.certificate), Files.readAllBytes(args.signature));
136+
}
137+
}

0 commit comments

Comments
 (0)