17
17
18
18
import com .google .common .annotations .VisibleForTesting ;
19
19
import com .google .common .base .Preconditions ;
20
- import com .google .protobuf .util .JsonFormat ;
21
- import dev .sigstore .proto .trustroot .v1 .TrustedRoot ;
22
20
import dev .sigstore .trustroot .SigstoreConfigurationException ;
21
+ import dev .sigstore .trustroot .SigstoreSigningConfig ;
23
22
import dev .sigstore .trustroot .SigstoreTrustedRoot ;
24
23
import java .io .IOException ;
25
24
import java .net .MalformedURLException ;
26
25
import java .net .URL ;
27
- import java .nio .charset .StandardCharsets ;
28
26
import java .nio .file .Files ;
29
27
import java .nio .file .Path ;
30
28
import java .security .InvalidKeyException ;
31
29
import java .security .NoSuchAlgorithmException ;
32
- import java .security .cert .CertificateException ;
33
30
import java .security .spec .InvalidKeySpecException ;
34
31
import java .time .Duration ;
35
32
import java .time .Instant ;
33
+ import javax .annotation .Nullable ;
36
34
37
35
/**
38
36
* Wrapper around {@link dev.sigstore.tuf.Updater} that provides access to sigstore specific
41
39
public class SigstoreTufClient {
42
40
43
41
@ VisibleForTesting static final String TRUST_ROOT_FILENAME = "trusted_root.json" ;
42
+ @ VisibleForTesting static final String SIGNING_CONFIG_FILENAME = "signing_config.v0.2.json" ;
44
43
45
44
public static final String PUBLIC_GOOD_ROOT_RESOURCE =
46
45
"dev/sigstore/tuf/sigstore-tuf-root/root.json" ;
@@ -49,6 +48,10 @@ public class SigstoreTufClient {
49
48
private final Updater updater ;
50
49
private Instant lastUpdate ;
51
50
private SigstoreTrustedRoot sigstoreTrustedRoot ;
51
+ // TODO: this is nullable because we expect all future sigstore tuf repos to contain a signing
52
+ // config
53
+ // but while we transition, we need to handle the null case.
54
+ @ Nullable private SigstoreSigningConfig sigstoreSigningConfig ;
52
55
private final Duration cacheValidity ;
53
56
54
57
@ VisibleForTesting
@@ -66,8 +69,8 @@ public static class Builder {
66
69
Path tufCacheLocation =
67
70
Path .of (System .getProperty ("user.home" )).resolve (".sigstore-java" ).resolve ("root" );
68
71
69
- URL remoteMirror ;
70
- RootProvider trustedRoot ;
72
+ private URL remoteMirror ;
73
+ private RootProvider trustedRoot ;
71
74
72
75
public Builder usePublicGoodInstance () {
73
76
if (remoteMirror != null || trustedRoot != null ) {
@@ -152,39 +155,53 @@ public SigstoreTufClient build() throws IOException {
152
155
* Update the tuf metadata if the cache has not been updated for at least {@code cacheValidity}
153
156
* defined on the client.
154
157
*/
155
- public void update ()
156
- throws SigstoreConfigurationException ,
157
- CertificateException ,
158
- IOException ,
159
- NoSuchAlgorithmException ,
160
- InvalidKeySpecException ,
161
- InvalidKeyException {
158
+ public void update () throws SigstoreConfigurationException {
162
159
if (lastUpdate == null
163
160
|| Duration .between (lastUpdate , Instant .now ()).compareTo (cacheValidity ) > 0 ) {
164
161
this .forceUpdate ();
165
162
}
166
163
}
167
164
168
165
/** Force an update, ignoring any cache validity. */
169
- public void forceUpdate ()
170
- throws SigstoreConfigurationException ,
171
- CertificateException ,
172
- IOException ,
173
- NoSuchAlgorithmException ,
174
- InvalidKeySpecException ,
175
- InvalidKeyException {
176
- updater .update ();
166
+ public void forceUpdate () throws SigstoreConfigurationException {
167
+ try {
168
+ updater .update ();
169
+ } catch (IOException
170
+ | NoSuchAlgorithmException
171
+ | InvalidKeySpecException
172
+ | InvalidKeyException ex ) {
173
+ throw new SigstoreConfigurationException ("TUF repo failed to update" , ex );
174
+ }
177
175
lastUpdate = Instant .now ();
178
- var trustedRootBuilder = TrustedRoot .newBuilder ();
179
- JsonFormat .parser ()
180
- .merge (
181
- new String (
182
- updater .getTargetStore ().readTarget (TRUST_ROOT_FILENAME ), StandardCharsets .UTF_8 ),
183
- trustedRootBuilder );
184
- sigstoreTrustedRoot = SigstoreTrustedRoot .from (trustedRootBuilder .build ());
176
+ try {
177
+ sigstoreTrustedRoot =
178
+ SigstoreTrustedRoot .from (
179
+ updater .getTargetStore ().getTargetInputSteam (TRUST_ROOT_FILENAME ));
180
+ } catch (IOException ex ) {
181
+ throw new SigstoreConfigurationException ("Failed to read trusted root from target store" , ex );
182
+ }
183
+ try {
184
+ if (updater .getTargetStore ().hasTarget (SIGNING_CONFIG_FILENAME )) {
185
+ sigstoreSigningConfig =
186
+ SigstoreSigningConfig .from (
187
+ updater .getTargetStore ().getTargetInputSteam (SIGNING_CONFIG_FILENAME ));
188
+ } else {
189
+ sigstoreSigningConfig = null ;
190
+ // TODO: Remove when prod and staging TUF repos have fully configured signing configs, but
191
+ // right now sigstore tuf repos not having sigstoreSigningConfig is a valid state.
192
+ }
193
+ } catch (IOException ex ) {
194
+ throw new SigstoreConfigurationException (
195
+ "Failed to read signing config from target store" , ex );
196
+ }
185
197
}
186
198
187
199
public SigstoreTrustedRoot getSigstoreTrustedRoot () {
188
200
return sigstoreTrustedRoot ;
189
201
}
202
+
203
+ @ Nullable
204
+ public SigstoreSigningConfig getSigstoreSigningConfig () {
205
+ return sigstoreSigningConfig ;
206
+ }
190
207
}
0 commit comments