@@ -15,13 +15,12 @@ import (
15
15
16
16
v1 "github.com/google/go-containerregistry/pkg/v1"
17
17
"github.com/google/go-containerregistry/pkg/v1/static"
18
- "github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"
19
18
"github.com/sigstore/cosign/v2/pkg/cosign"
20
19
"github.com/sigstore/cosign/v2/pkg/oci"
21
20
"github.com/sigstore/cosign/v2/pkg/oci/signature"
22
21
sig "github.com/sigstore/cosign/v2/pkg/signature"
23
22
"github.com/sigstore/sigstore/pkg/cryptoutils"
24
- "github.com/sigstore/sigstore/pkg/tuf"
23
+ sigtuf "github.com/sigstore/sigstore/pkg/tuf"
25
24
)
26
25
27
26
type Configuration struct {
@@ -63,12 +62,47 @@ type SignatureData struct {
63
62
Payloads map [string ]string `json:"Payloads"`
64
63
}
65
64
65
+ var configFilePath = flag .String ("config-file" , "" , "path to the config file with target image digest, root of trust, signature, and verifier data" )
66
+
67
+ var proxyURL = flag .String ("proxy-url" , "" , "" )
68
+ var proxyHasCredentials = flag .Bool ("proxy-has-credentials" , false , "" )
69
+
70
+ func getProxyDetails () (Proxy , error ) {
71
+ if * proxyURL == "" {
72
+ return Proxy {}, nil
73
+ }
74
+ proxy := Proxy {URL : * proxyURL }
75
+ if * proxyHasCredentials {
76
+ stdinCredentials , err := os .ReadFile (os .Stdin .Name ())
77
+ if err != nil {
78
+ return Proxy {}, fmt .Errorf ("error when reading credentials, could not read stdin: %s" , err .Error ())
79
+ }
80
+ if len (stdinCredentials ) == 0 {
81
+ return Proxy {}, fmt .Errorf ("expecting credentials but received empty string" )
82
+ }
83
+ separatorIndex := strings .Index (string (stdinCredentials ), ":" )
84
+ if separatorIndex == 0 {
85
+ return Proxy {}, fmt .Errorf ("proxy credentials argument cannot start with colon, expecting USERNAME:PASSWORD" )
86
+ }
87
+ splitCredentials := strings .Split (string (stdinCredentials ), ":" )
88
+ proxy .Username = splitCredentials [0 ]
89
+ proxy .Password = strings .Join (splitCredentials [1 :], ":" )
90
+ }
91
+ return proxy , nil
92
+ }
93
+
66
94
func main () {
95
+ flag .Parse ()
67
96
config , err := loadConfiguration ()
68
97
if err != nil {
69
98
log .Fatalf ("ERROR: error loading config: %s" , err .Error ())
70
99
}
71
100
101
+ proxy , err := getProxyDetails ()
102
+ if err != nil {
103
+ log .Fatalf ("ERROR: error when getting proxy details: %s" , err .Error ())
104
+ }
105
+
72
106
imageDigestHash , err := v1 .NewHash (config .ImageDigest )
73
107
if err != nil {
74
108
log .Fatalf ("ERROR: error hashing image digest: %s" , err .Error ())
@@ -82,7 +116,7 @@ func main() {
82
116
allSatisfiedVerifiers := []string {}
83
117
for _ , rootOfTrust := range config .RootsOfTrust {
84
118
fmt .Printf ("\n >>>> checking root of trust: %s\n " , rootOfTrust .Name )
85
- satisfiedVerifiers , err := verify (imageDigestHash , rootOfTrust , signatures )
119
+ satisfiedVerifiers , err := verify (imageDigestHash , rootOfTrust , signatures , proxy )
86
120
if err != nil {
87
121
// line with prefix "ERROR: " is recognized by scanner for error encounted when verifying against a verifier
88
122
fmt .Printf ("ERROR: %s\n " , err .Error ())
@@ -96,8 +130,6 @@ func main() {
96
130
}
97
131
98
132
func loadConfiguration () (config Configuration , err error ) {
99
- configFilePath := flag .String ("config-file" , "" , "path to the config file with target image digest, root of trust, signature, and verifier data" )
100
- flag .Parse ()
101
133
if * configFilePath == "" {
102
134
return config , errors .New ("must provide --config-file flag" )
103
135
}
@@ -126,10 +158,10 @@ func generateCosignSignatureObjects(sigData SignatureData) ([]oci.Signature, err
126
158
return signatures , nil
127
159
}
128
160
129
- func verify (imgDigest v1.Hash , rootOfTrust RootOfTrust , sigs []oci.Signature ) (satisfiedVerifiers []string , err error ) {
161
+ func verify (imgDigest v1.Hash , rootOfTrust RootOfTrust , sigs []oci.Signature , proxy Proxy ) (satisfiedVerifiers []string , err error ) {
130
162
ctx := context .Background ()
131
163
cosignOptions := cosign.CheckOpts {ClaimVerifier : cosign .SimpleClaimVerifier }
132
- err = setRootOfTrustCosignOptions (& cosignOptions , rootOfTrust , ctx )
164
+ err = setRootOfTrustCosignOptions (& cosignOptions , rootOfTrust , proxy , ctx )
133
165
if err != nil {
134
166
return satisfiedVerifiers , fmt .Errorf ("could not set root of trust %s cosign check options: %s" , rootOfTrust .Name , err .Error ())
135
167
}
@@ -158,25 +190,31 @@ func verify(imgDigest v1.Hash, rootOfTrust RootOfTrust, sigs []oci.Signature) (s
158
190
return satisfiedVerifiers , nil
159
191
}
160
192
161
- func setRootOfTrustCosignOptions (cosignOptions * cosign.CheckOpts , rootOfTrust RootOfTrust , ctx context.Context ) (err error ) {
162
- // rekor pub keys
163
- if rootOfTrust .RekorPublicKey != "" {
164
- publicKeyCollection := cosign .NewTrustedTransparencyLogPubKeys ()
165
- if err := publicKeyCollection .AddTransparencyLogPubKey ([]byte (rootOfTrust .RekorPublicKey ), tuf .Active ); err != nil {
166
- return fmt .Errorf ("could not add custom rekor public key to collection: %w" , err )
193
+ func setRootOfTrustCosignOptions (cosignOptions * cosign.CheckOpts , rootOfTrust RootOfTrust , proxy Proxy , ctx context.Context ) (err error ) {
194
+ // rekor public keys
195
+ rekorKeyCollection := cosign .NewTrustedTransparencyLogPubKeys ()
196
+ if rootOfTrust .RekorPublicKey == "" {
197
+ rekorKeyTargets , err := GetTargets (sigtuf .Rekor , proxy )
198
+ if err != nil {
199
+ return fmt .Errorf ("could not retrieve rekor tuf targets: %s" , err .Error ())
200
+ }
201
+ for _ , rekorKeyTarget := range rekorKeyTargets {
202
+ if err := rekorKeyCollection .AddTransparencyLogPubKey (rekorKeyTarget .Target , rekorKeyTarget .Status ); err != nil {
203
+ return fmt .Errorf ("could not add public root of trust rekor public key to collection: %w" , err )
204
+ }
167
205
}
168
- cosignOptions .RekorPubKeys = & publicKeyCollection
169
206
} else {
170
- cosignOptions .RekorPubKeys , err = cosign .GetRekorPubs (ctx )
171
- if err != nil {
172
- return fmt .Errorf ("could not get default rekor public key: %w" , err )
207
+ if err := rekorKeyCollection .AddTransparencyLogPubKey ([]byte (rootOfTrust .RekorPublicKey ), sigtuf .Active ); err != nil {
208
+ return fmt .Errorf ("could not add custom root of trust rekor public key to collection: %w" , err )
173
209
}
174
210
}
175
- // root certificate(s)
211
+ cosignOptions .RekorPubKeys = & rekorKeyCollection
212
+
213
+ // root & intermediate certificates
214
+ selfSigned := func (cert * x509.Certificate ) bool {
215
+ return bytes .Equal (cert .RawSubject , cert .RawIssuer )
216
+ }
176
217
if rootOfTrust .RootCert != "" {
177
- selfSigned := func (cert * x509.Certificate ) bool {
178
- return bytes .Equal (cert .RawSubject , cert .RawIssuer )
179
- }
180
218
rootPool := x509 .NewCertPool ()
181
219
var intermediatePool * x509.CertPool // should be nil if no intermediate certs are found
182
220
certs , err := cryptoutils .UnmarshalCertificatesFromPEM ([]byte (rootOfTrust .RootCert ))
@@ -196,28 +234,52 @@ func setRootOfTrustCosignOptions(cosignOptions *cosign.CheckOpts, rootOfTrust Ro
196
234
cosignOptions .RootCerts = rootPool
197
235
cosignOptions .IntermediateCerts = intermediatePool
198
236
} else {
199
- cosignOptions .RootCerts , err = fulcio .GetRoots ()
237
+ targetCertificates , err := GetTargets (sigtuf .Fulcio , proxy )
238
+ // certificates, err := GetPublicRootOfTrustFulcioCertificates(proxy)
200
239
if err != nil {
201
- return fmt .Errorf ("could not fetch default fulcio root certificate(s) : %s" , err .Error ())
240
+ return fmt .Errorf ("could not retrieve public root of trust fulcio certificates : %s" , err .Error ())
202
241
}
203
- cosignOptions .IntermediateCerts , err = fulcio .GetIntermediates ()
204
- if err != nil {
205
- return fmt .Errorf ("could not fetch default fulcio intermediate certificate(s): %s" , err .Error ())
242
+ rootPool := x509 .NewCertPool ()
243
+ var intermediatePool * x509.CertPool // should be nil if no intermediate certs are found
244
+ for _ , targetCertificate := range targetCertificates {
245
+ certs , err := cryptoutils .UnmarshalCertificatesFromPEM (targetCertificate .Target )
246
+ if err != nil {
247
+ continue
248
+ }
249
+ for _ , cert := range certs {
250
+ if selfSigned (cert ) {
251
+ rootPool .AddCert (cert )
252
+ } else {
253
+ if intermediatePool == nil {
254
+ intermediatePool = x509 .NewCertPool ()
255
+ }
256
+ intermediatePool .AddCert (cert )
257
+ }
258
+ }
206
259
}
260
+ cosignOptions .RootCerts = rootPool
261
+ cosignOptions .IntermediateCerts = intermediatePool
207
262
}
208
- // sct pub keys
209
- if rootOfTrust .SCTPublicKey != "" {
210
- sctPubKeyCollection := cosign .NewTrustedTransparencyLogPubKeys ()
211
- if err := sctPubKeyCollection .AddTransparencyLogPubKey ([]byte (rootOfTrust .SCTPublicKey ), tuf .Active ); err != nil {
212
- return fmt .Errorf ("could not add custom sct public key to collection: %w" , err )
263
+
264
+ // sct public keys
265
+ sctKeyCollection := cosign .NewTrustedTransparencyLogPubKeys ()
266
+ if rootOfTrust .SCTPublicKey == "" {
267
+ sctKeyTargets , err := GetTargets (sigtuf .CTFE , proxy )
268
+ if err != nil {
269
+ return fmt .Errorf ("could not retrieve ctfe tuf targets: %s" , err .Error ())
270
+ }
271
+ for _ , sctKeyTarget := range sctKeyTargets {
272
+ if err := sctKeyCollection .AddTransparencyLogPubKey (sctKeyTarget .Target , sctKeyTarget .Status ); err != nil {
273
+ return fmt .Errorf ("could not add public root of trust sct public key to collection: %w" , err )
274
+ }
213
275
}
214
- cosignOptions .CTLogPubKeys = & sctPubKeyCollection
215
276
} else {
216
- cosignOptions .CTLogPubKeys , err = cosign .GetCTLogPubs (ctx )
217
- if err != nil {
218
- return fmt .Errorf ("error retrieving default CT log public keys: %s" , err .Error ())
277
+ if err := sctKeyCollection .AddTransparencyLogPubKey ([]byte (rootOfTrust .SCTPublicKey ), sigtuf .Active ); err != nil {
278
+ return fmt .Errorf ("could not add custom root of trust sct public key to collection: %w" , err )
219
279
}
220
280
}
281
+ cosignOptions .CTLogPubKeys = & sctKeyCollection
282
+
221
283
return nil
222
284
}
223
285
0 commit comments