@@ -16,13 +16,17 @@ package main
16
16
17
17
import (
18
18
"context"
19
+ "encoding/base64"
19
20
"encoding/json"
20
21
"flag"
21
22
"fmt"
22
23
"io/ioutil"
23
24
"net/http"
25
+ "os"
26
+ "strings"
24
27
25
28
"github.com/google/go-containerregistry/pkg/name"
29
+ "github.com/in-toto/in-toto-golang/in_toto"
26
30
"github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"
27
31
28
32
"github.com/minio/pkg/wildcard"
@@ -33,6 +37,7 @@ import (
33
37
"github.com/sigstore/cosign/pkg/cosign/pkcs11key"
34
38
"github.com/sigstore/cosign/pkg/oci"
35
39
sigs "github.com/sigstore/cosign/pkg/signature"
40
+ "github.com/sigstore/sigstore/pkg/signature/payload"
36
41
)
37
42
38
43
const (
@@ -105,8 +110,8 @@ func validate(cfg *Config) func(w http.ResponseWriter, req *http.Request) {
105
110
}
106
111
107
112
type checkedMetadata struct {
108
- ImageSignatures []oci. Signature `json:"imageSignatures"`
109
- AttestationSignatures []oci. Signature `json:"attestationSignatures"`
113
+ ImageSignatures []payload. SimpleContainerImage `json:"imageSignatures"`
114
+ AttestationSignatures []in_toto. Statement `json:"attestationSignatures"`
110
115
}
111
116
112
117
func verifyImageSignatures (ctx context.Context , key string , verifiers []Verifier ) (* checkedMetadata , error ) {
@@ -148,7 +153,7 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
148
153
return nil , fmt .Errorf ("parseReference: %v" , err )
149
154
}
150
155
151
- var metadata * checkedMetadata
156
+ metadata := & checkedMetadata {}
152
157
153
158
checkedSignatures , bundleVerified , err := cosign .VerifyImageSignatures (ctx , ref , co )
154
159
if err != nil {
@@ -163,7 +168,10 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
163
168
return nil , fmt .Errorf ("no valid signatures found for %s" , key )
164
169
}
165
170
166
- metadata .ImageSignatures = checkedSignatures
171
+ metadata .ImageSignatures , err = formatSignaturePayloads (checkedSignatures )
172
+ if err != nil {
173
+ return nil , fmt .Errorf ("formatSignaturePayloads: %v" , err )
174
+ }
167
175
168
176
fmt .Println ("signature verified for: " , key )
169
177
fmt .Printf ("%d number of valid signatures found for %s, found signatures: %v\n " , len (checkedSignatures ), key , checkedSignatures )
@@ -179,7 +187,12 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
179
187
return nil , fmt .Errorf ("no valid attestations found for: %s" , key )
180
188
}
181
189
182
- metadata .AttestationSignatures = checkedAttestations
190
+ AttestationPayloads , err := formatAttestations (checkedAttestations )
191
+ if err != nil {
192
+ return nil , fmt .Errorf ("formatAttestations: %v" , err )
193
+ }
194
+
195
+ metadata .AttestationSignatures = AttestationPayloads
183
196
184
197
fmt .Println ("attestation verified for: " , key )
185
198
fmt .Printf ("%d number of valid attestations found for %s, found attestations: %v\n " , len (checkedAttestations ), key , checkedAttestations )
@@ -191,6 +204,80 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
191
204
return nil , fmt .Errorf ("no verifier found for: %s" , key )
192
205
}
193
206
207
+ // formatAttestations takes the payload within an Attestation and base64 decodes it, returning it as an in-toto statement
208
+ func formatAttestations (verifiedAttestations []oci.Signature ) ([]in_toto.Statement , error ) {
209
+
210
+ decodedAttestations := make ([]in_toto.Statement , len (verifiedAttestations ))
211
+
212
+ for i , att := range verifiedAttestations {
213
+ p , err := att .Payload ()
214
+ if err != nil {
215
+ fmt .Fprintf (os .Stderr , "error fetching payload: %v" , err )
216
+ return nil , err
217
+ }
218
+
219
+ var pm map [string ]interface {}
220
+ json .Unmarshal (p , & pm )
221
+
222
+ payload := strings .Trim (fmt .Sprintf ("%v" , pm ["payload" ]), "\" " )
223
+
224
+ statementRaw , err := base64 .StdEncoding .DecodeString (payload )
225
+ if err != nil {
226
+ fmt .Fprintf (os .Stderr , "error decoding payload: %v" , err )
227
+ }
228
+
229
+ var statement in_toto.Statement
230
+ if err := json .Unmarshal (statementRaw , & statement ); err != nil {
231
+ return nil , err
232
+ }
233
+
234
+ decodedAttestations [i ] = statement
235
+ }
236
+
237
+ return decodedAttestations , nil
238
+
239
+ }
240
+
241
+ // formatPayload converts the signature into a payload to be sent back to gatekeeper
242
+ func formatSignaturePayloads (verifiedSignatures []oci.Signature ) ([]payload.SimpleContainerImage , error ) {
243
+
244
+ var outputKeys []payload.SimpleContainerImage
245
+
246
+ for _ , sig := range verifiedSignatures {
247
+ p , err := sig .Payload ()
248
+ if err != nil {
249
+ fmt .Fprintf (os .Stderr , "error fetching payload: %v" , err )
250
+ return nil , err
251
+ }
252
+
253
+ ss := payload.SimpleContainerImage {}
254
+ if err := json .Unmarshal (p , & ss ); err != nil {
255
+ fmt .Println ("error decoding the payload:" , err .Error ())
256
+ return nil , err
257
+ }
258
+
259
+ if cert , err := sig .Cert (); err == nil && cert != nil {
260
+ if ss .Optional == nil {
261
+ ss .Optional = make (map [string ]interface {})
262
+ }
263
+ ss .Optional ["Subject" ] = sigs .CertSubject (cert )
264
+ if issuerURL := sigs .CertIssuerExtension (cert ); issuerURL != "" {
265
+ ss .Optional ["Issuer" ] = issuerURL
266
+ }
267
+ }
268
+ if bundle , err := sig .Bundle (); err == nil && bundle != nil {
269
+ if ss .Optional == nil {
270
+ ss .Optional = make (map [string ]interface {})
271
+ }
272
+ ss .Optional ["Bundle" ] = bundle
273
+ }
274
+
275
+ outputKeys = append (outputKeys , ss )
276
+ }
277
+
278
+ return outputKeys , nil
279
+ }
280
+
194
281
// sendResponse sends back the response to Gatekeeper.
195
282
func sendResponse (results * []externaldata.Item , systemErr string , w http.ResponseWriter ) {
196
283
response := externaldata.ProviderResponse {
0 commit comments