Skip to content

Commit 5f17fc9

Browse files
authored
Merge pull request #599 from sigstore/conformance009
Rework trusted root injection for conformance v0.0.9
2 parents 76aca3e + 9a98407 commit 5f17fc9

File tree

5 files changed

+88
-10
lines changed

5 files changed

+88
-10
lines changed

.github/workflows/conformance.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ jobs:
3131
- name: Unpack sigstore-java distribution
3232
run: tar -xvf ${{ github.workspace }}/sigstore-cli/build/distributions/sigstore-cli-*.tar --strip-components 1
3333

34-
- uses: sigstore/sigstore-conformance@00922385de455be5ec46288a947044aa44fb0981 # v0.0.8
34+
- uses: sigstore/sigstore-conformance@c8d17eb7ee884cf86b93a3a3f471648fb0a83819 # v0.0.9
3535
with:
3636
entrypoint: ${{ github.workspace }}/bin/sigstore-cli

sigstore-cli/src/main/java/dev/sigstore/cli/Sign.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.nio.charset.StandardCharsets;
2323
import java.nio.file.Files;
2424
import java.nio.file.Path;
25+
import java.util.Base64;
2526
import java.util.concurrent.Callable;
2627
import picocli.CommandLine.ArgGroup;
2728
import picocli.CommandLine.Command;
@@ -57,7 +58,9 @@ public Integer call() throws Exception {
5758
var signer = signerBuilder.build();
5859
var signingResult = signer.signFile(artifact);
5960
if (signatureFiles.sigAndCert != null) {
60-
Files.write(signatureFiles.sigAndCert.signatureFile, signingResult.getSignature());
61+
Files.write(
62+
signatureFiles.sigAndCert.signatureFile,
63+
Base64.getEncoder().encode(signingResult.getSignature()));
6164
Files.write(
6265
signatureFiles.sigAndCert.certificateFile,
6366
Certificates.toPemBytes(signingResult.getCertPath()));

sigstore-cli/src/main/java/dev/sigstore/cli/Verify.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.nio.file.Files;
3131
import java.nio.file.Path;
3232
import java.security.cert.CertPath;
33+
import java.util.Base64;
3334
import java.util.concurrent.Callable;
3435
import picocli.CommandLine.ArgGroup;
3536
import picocli.CommandLine.Command;
@@ -50,6 +51,12 @@ public class Verify implements Callable<Integer> {
5051
@ArgGroup(multiplicity = "0..1", exclusive = false)
5152
Policy policy;
5253

54+
@Option(
55+
names = {"--trusted-root"},
56+
description = "an alternative to the TUF managed sigstore public good trusted root",
57+
required = false)
58+
Path trustedRoot;
59+
5360
static class Policy {
5461
@Option(
5562
names = {"--certificate-identity"},
@@ -70,7 +77,9 @@ public Integer call() throws Exception {
7077
KeylessSignature keylessSignature;
7178

7279
if (signatureFiles.sigAndCert != null) {
73-
byte[] signature = Files.readAllBytes(signatureFiles.sigAndCert.signatureFile);
80+
byte[] signature =
81+
Base64.getMimeDecoder()
82+
.decode(Files.readAllBytes(signatureFiles.sigAndCert.signatureFile));
7483
CertPath certPath =
7584
Certificates.fromPemChain(Files.readAllBytes(signatureFiles.sigAndCert.certificateFile));
7685
keylessSignature =
@@ -91,7 +100,10 @@ public Integer call() throws Exception {
91100
}
92101
var verificationOptions = verificationOptionsBuilder.alwaysUseRemoteRekorEntry(false).build();
93102

94-
var verifier = new KeylessVerifier.Builder().sigstorePublicDefaults().build();
103+
var verifier =
104+
(trustedRoot == null)
105+
? new KeylessVerifier.Builder().sigstorePublicDefaults().build()
106+
: new KeylessVerifier.Builder().fromTrustedRoot(trustedRoot).build();
95107
verifier.verify(
96108
artifact,
97109
KeylessVerificationRequest.builder()

sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,33 @@ public static KeylessVerifier.Builder builder() {
6464
}
6565

6666
public static class Builder {
67-
private SigstoreTufClient sigstoreTufClient;
67+
private TrustedRootProvider trustedRootProvider;
6868

6969
public KeylessVerifier build()
7070
throws InvalidAlgorithmParameterException, CertificateException, InvalidKeySpecException,
7171
NoSuchAlgorithmException, IOException, InvalidKeyException {
72-
Preconditions.checkNotNull(sigstoreTufClient);
73-
sigstoreTufClient.update();
74-
var trustedRoot = sigstoreTufClient.getSigstoreTrustedRoot();
72+
Preconditions.checkNotNull(trustedRootProvider);
73+
var trustedRoot = trustedRootProvider.get();
7574
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(trustedRoot);
7675
var rekorClient = RekorClient.builder().setTransparencyLog(trustedRoot).build();
7776
var rekorVerifier = RekorVerifier.newRekorVerifier(trustedRoot);
7877
return new KeylessVerifier(fulcioVerifier, rekorClient, rekorVerifier);
7978
}
8079

8180
public Builder sigstorePublicDefaults() throws IOException {
82-
sigstoreTufClient = SigstoreTufClient.builder().usePublicGoodInstance().build();
81+
var sigstoreTufClient = SigstoreTufClient.builder().usePublicGoodInstance().build();
82+
trustedRootProvider = TrustedRootProvider.from(sigstoreTufClient);
8383
return this;
8484
}
8585

8686
public Builder sigstoreStagingDefaults() throws IOException {
87-
sigstoreTufClient = SigstoreTufClient.builder().useStagingInstance().build();
87+
var sigstoreTufClient = SigstoreTufClient.builder().useStagingInstance().build();
88+
trustedRootProvider = TrustedRootProvider.from(sigstoreTufClient);
89+
return this;
90+
}
91+
92+
public Builder fromTrustedRoot(Path trustedRoot) {
93+
trustedRootProvider = TrustedRootProvider.from(trustedRoot);
8894
return this;
8995
}
9096
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2023 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;
17+
18+
import com.google.common.base.Preconditions;
19+
import com.google.protobuf.util.JsonFormat;
20+
import dev.sigstore.proto.trustroot.v1.TrustedRoot;
21+
import dev.sigstore.trustroot.SigstoreTrustedRoot;
22+
import dev.sigstore.tuf.SigstoreTufClient;
23+
import java.io.IOException;
24+
import java.nio.charset.StandardCharsets;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.security.InvalidAlgorithmParameterException;
28+
import java.security.InvalidKeyException;
29+
import java.security.NoSuchAlgorithmException;
30+
import java.security.cert.CertificateException;
31+
import java.security.spec.InvalidKeySpecException;
32+
33+
@FunctionalInterface
34+
public interface TrustedRootProvider {
35+
36+
SigstoreTrustedRoot get()
37+
throws InvalidAlgorithmParameterException, CertificateException, InvalidKeySpecException,
38+
NoSuchAlgorithmException, IOException, InvalidKeyException;
39+
40+
static TrustedRootProvider from(SigstoreTufClient tufClient) {
41+
Preconditions.checkNotNull(tufClient);
42+
return () -> {
43+
tufClient.update();
44+
return tufClient.getSigstoreTrustedRoot();
45+
};
46+
}
47+
48+
static TrustedRootProvider from(Path trustedRoot) {
49+
Preconditions.checkNotNull(trustedRoot);
50+
return () -> {
51+
var trustedRootBuilder = TrustedRoot.newBuilder();
52+
JsonFormat.parser()
53+
.merge(Files.readString(trustedRoot, StandardCharsets.UTF_8), trustedRootBuilder);
54+
return SigstoreTrustedRoot.from(trustedRootBuilder.build());
55+
};
56+
}
57+
}

0 commit comments

Comments
 (0)