@@ -37,9 +37,11 @@ import (
3737 "github.com/sigstore/cosign/v3/internal/test"
3838 "github.com/sigstore/cosign/v3/pkg/cosign"
3939 "github.com/sigstore/cosign/v3/pkg/cosign/attestation"
40+ protobundle "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1"
4041 "github.com/sigstore/sigstore/pkg/signature"
4142 "github.com/sigstore/sigstore/pkg/signature/dsse"
4243 "github.com/stretchr/testify/assert"
44+ "google.golang.org/protobuf/encoding/protojson"
4345)
4446
4547// TestAttestBlobCmdLocalKeyAndSk verifies the AttestBlobCmd returns an error
@@ -73,6 +75,31 @@ func writeFile(t *testing.T, td string, blob string, name string) string {
7375 return blobPath
7476}
7577
78+ // assertOfflineBundle asserts that a key-signed bundle file carries no material
79+ // from online services (certificates, tlog entries, or signed timestamps).
80+ func assertOfflineBundle (t * testing.T , bundlePath string ) {
81+ t .Helper ()
82+ bundleBytes , err := os .ReadFile (bundlePath )
83+ if err != nil {
84+ t .Fatalf ("failed to read bundle: %v" , err )
85+ }
86+ var bundle protobundle.Bundle
87+ if err := protojson .Unmarshal (bundleBytes , & bundle ); err != nil {
88+ t .Fatalf ("failed to unmarshal bundle: %v" , err )
89+ }
90+ vm := bundle .GetVerificationMaterial ()
91+ // The content is a oneof, so a public key hint also rules out a certificate.
92+ if vm .GetPublicKey () == nil {
93+ t .Errorf ("expected a public key hint, got %T" , vm .GetContent ())
94+ }
95+ if n := len (vm .GetTlogEntries ()); n != 0 {
96+ t .Errorf ("expected no transparency log entries, got %d" , n )
97+ }
98+ if n := len (vm .GetTimestampVerificationData ().GetRfc3161Timestamps ()); n != 0 {
99+ t .Errorf ("expected no RFC 3161 timestamps, got %d" , n )
100+ }
101+ }
102+
76103func makeSLSA02PredicateFile (t * testing.T , td string ) string {
77104 predicate := `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`
78105 return writeFile (t , td , predicate , "predicate02.json" )
@@ -124,7 +151,6 @@ func TestAttestBlobCmdLocalKeyAndCert(t *testing.T) {
124151 keyref string
125152 certref string
126153 certchainref string
127- newBundle bool
128154 errString string
129155 }{
130156 {
@@ -136,24 +162,12 @@ func TestAttestBlobCmdLocalKeyAndCert(t *testing.T) {
136162 keyref : keyRef ,
137163 certref : certRef ,
138164 },
139- {
140- name : "new bundle generation" ,
141- keyref : keyRef ,
142- certref : certRef ,
143- newBundle : true ,
144- },
145165 {
146166 name : "fail: cert no match key" ,
147167 keyref : keyRef ,
148168 certref : subCertPem ,
149169 errString : "public key in certificate does not match the provided public key" ,
150170 },
151- {
152- name : "cert chain matches key" ,
153- keyref : keyRef ,
154- certref : certRef ,
155- certchainref : subCertPem ,
156- },
157171 {
158172 name : "cert chain partial" ,
159173 keyref : keyRef ,
@@ -175,18 +189,13 @@ func TestAttestBlobCmdLocalKeyAndCert(t *testing.T) {
175189 },
176190 } {
177191 t .Run (tc .name , func (t * testing.T ) {
178- keyOpts := options.KeyOpts {KeyRef : tc .keyref }
179- if tc .newBundle {
180- keyOpts .NewBundleFormat = true
181- keyOpts .BundlePath = filepath .Join (td , "output.bundle" )
182- }
192+ keyOpts := options.KeyOpts {KeyRef : tc .keyref , BundlePath : filepath .Join (td , "output.bundle" )}
183193 at := AttestBlobCommand {
184- KeyOpts : keyOpts ,
185- CertPath : tc .certref ,
186- CertChainPath : tc .certchainref ,
187- PredicatePath : predicatePath ,
188- PredicateType : predicateType ,
189- RekorEntryType : "dsse" ,
194+ KeyOpts : keyOpts ,
195+ CertPath : tc .certref ,
196+ CertChainPath : tc .certchainref ,
197+ PredicatePath : predicatePath ,
198+ PredicateType : predicateType ,
190199 }
191200 err := at .Exec (ctx , blob )
192201 if err != nil {
@@ -228,25 +237,34 @@ func TestAttestBlob(t *testing.T) {
228237
229238 for predicateType , predicatePath := range predicates {
230239 t .Run (predicateType , func (t * testing.T ) {
231- dssePath := filepath .Join (td , "dsse.intoto.jsonl" )
240+ bundlePath := filepath .Join (td , "bundle.json" )
241+ keyOpts := options.KeyOpts {KeyRef : keyRef , BundlePath : bundlePath }
232242 at := AttestBlobCommand {
233- KeyOpts : options.KeyOpts {KeyRef : keyRef },
234- PredicatePath : predicatePath ,
235- PredicateType : predicateType ,
236- OutputSignature : dssePath ,
237- RekorEntryType : "dsse" ,
243+ KeyOpts : keyOpts ,
244+ PredicatePath : predicatePath ,
245+ PredicateType : predicateType ,
238246 }
239247 err := at .Exec (ctx , blobPath )
240248 if err != nil {
241249 t .Fatal (err )
242250 }
251+ assertOfflineBundle (t , bundlePath )
243252
244- // Load the attestation.
245- dsseBytes , _ := os .ReadFile (dssePath )
246- env := & ssldsse.Envelope {}
247- if err := json .Unmarshal (dsseBytes , env ); err != nil {
253+ // Load the attestation bundle.
254+ bundleBytes , err := os .ReadFile (bundlePath )
255+ if err != nil {
248256 t .Fatal (err )
249257 }
258+ var bundleJSON struct {
259+ DsseEnvelope * ssldsse.Envelope `json:"dsseEnvelope"`
260+ }
261+ if err := json .Unmarshal (bundleBytes , & bundleJSON ); err != nil {
262+ t .Fatal (err )
263+ }
264+ env := bundleJSON .DsseEnvelope
265+ if env == nil {
266+ t .Fatal ("expected dsse envelope in bundle" )
267+ }
250268
251269 if len (env .Signatures ) != 1 {
252270 t .Fatalf ("expected 1 signature, got %d" , len (env .Signatures ))
@@ -284,38 +302,6 @@ func TestAttestBlob(t *testing.T) {
284302 }
285303}
286304
287- func TestBadRekorEntryType (t * testing.T ) {
288- ctx := context .Background ()
289- td := t .TempDir ()
290-
291- keys , _ := cosign .GenerateKeyPair (nil )
292- keyRef := writeFile (t , td , string (keys .PrivateBytes ), "key.pem" )
293-
294- blob := []byte ("foo" )
295- blobPath := writeFile (t , td , string (blob ), "foo.txt" )
296-
297- predicates := map [string ]string {}
298- predicates ["slsaprovenance" ] = makeSLSA02PredicateFile (t , td )
299- predicates ["slsaprovenance1" ] = makeSLSA1PredicateFile (t , td )
300-
301- for predicateType , predicatePath := range predicates {
302- t .Run (predicateType , func (t * testing.T ) {
303- dssePath := filepath .Join (td , "dsse.intoto.jsonl" )
304- at := AttestBlobCommand {
305- KeyOpts : options.KeyOpts {KeyRef : keyRef },
306- PredicatePath : predicatePath ,
307- PredicateType : predicateType ,
308- OutputSignature : dssePath ,
309- RekorEntryType : "badvalue" ,
310- }
311- err := at .Exec (ctx , blobPath )
312- if err == nil || err .Error () != "unknown value for rekor-entry-type" {
313- t .Fatal ("expected an error due to unknown rekor entry type" )
314- }
315- })
316- }
317- }
318-
319305func TestStatementPath (t * testing.T ) {
320306 ctx := context .Background ()
321307 td := t .TempDir ()
@@ -340,10 +326,10 @@ func TestStatementPath(t *testing.T) {
340326 }`
341327 statementPath := writeFile (t , td , statement , "statement.json" )
342328
329+ keyOpts := options.KeyOpts {KeyRef : keyRef , BundlePath : filepath .Join (td , "bundle.json" )}
343330 at := AttestBlobCommand {
344- KeyOpts : options.KeyOpts {KeyRef : keyRef },
345- StatementPath : statementPath ,
346- RekorEntryType : "dsse" ,
331+ KeyOpts : keyOpts ,
332+ StatementPath : statementPath ,
347333 }
348334 err := at .Exec (ctx , "" )
349335 assert .NoError (t , err )
0 commit comments