@@ -28,6 +28,7 @@ import (
2828 ociremote "github.com/sigstore/cosign/v3/pkg/oci/remote"
2929 "github.com/sigstore/cosign/v3/pkg/oci/static"
3030 "github.com/sigstore/cosign/v3/pkg/types"
31+ "github.com/sigstore/sigstore-go/pkg/bundle"
3132)
3233
3334func AttestationCmd (ctx context.Context , regOpts options.RegistryOptions , signedPayloads []string , imageRef string ) error {
@@ -37,16 +38,58 @@ func AttestationCmd(ctx context.Context, regOpts options.RegistryOptions, signed
3738 }
3839
3940 for _ , payload := range signedPayloads {
40- if err := attachAttestation (ctx , ociremoteOpts , payload , imageRef , regOpts .NameOptions ()); err != nil {
41+ fmt .Fprintf (os .Stderr , "Using payload from: %s" , payload )
42+
43+ ref , err := name .ParseReference (imageRef , regOpts .NameOptions ()... )
44+ if err != nil {
45+ return err
46+ }
47+ if _ , ok := ref .(name.Digest ); ! ok {
48+ ui .Warnf (ctx , ui .TagReferenceMessage , imageRef )
49+ }
50+
51+ digest , err := ociremote .ResolveDigest (ref , ociremoteOpts ... )
52+ if err != nil {
53+ return err
54+ }
55+
56+ // Detect if we are using new bundle format
57+ b , err := bundle .LoadJSONFromPath (payload )
58+ if err == nil {
59+ return attachAttestationNewBundle (ociremoteOpts , b , digest )
60+ }
61+
62+ if err := attachAttestation (ociremoteOpts , payload , digest ); err != nil {
4163 return fmt .Errorf ("attaching payload from %s: %w" , payload , err )
4264 }
4365 }
4466
4567 return nil
4668}
4769
48- func attachAttestation (ctx context.Context , remoteOpts []ociremote.Option , signedPayload , imageRef string , nameOpts []name.Option ) error {
49- fmt .Fprintf (os .Stderr , "Using payload from: %s" , signedPayload )
70+ func attachAttestationNewBundle (remoteOpts []ociremote.Option , b * bundle.Bundle , digest name.Digest ) error {
71+ envelope , err := b .Envelope ()
72+ if err != nil {
73+ return err
74+ }
75+ if envelope == nil {
76+ return fmt .Errorf ("bundle does not have DSSE envelope" )
77+ }
78+ statement , err := envelope .Statement ()
79+ if err != nil {
80+ return err
81+ }
82+ if statement == nil {
83+ return fmt .Errorf ("unable to understand bundle envelope statement" )
84+ }
85+ bundleBytes , err := b .MarshalJSON ()
86+ if err != nil {
87+ return err
88+ }
89+ return ociremote .WriteAttestationNewBundleFormat (digest , bundleBytes , statement .PredicateType , remoteOpts ... )
90+ }
91+
92+ func attachAttestation (remoteOpts []ociremote.Option , signedPayload string , digest name.Digest ) error {
5093 attestationFile , err := os .Open (signedPayload )
5194 if err != nil {
5295 return err
@@ -73,22 +116,6 @@ func attachAttestation(ctx context.Context, remoteOpts []ociremote.Option, signe
73116 return fmt .Errorf ("could not attach attestation without having signatures" )
74117 }
75118
76- ref , err := name .ParseReference (imageRef , nameOpts ... )
77- if err != nil {
78- return err
79- }
80- if _ , ok := ref .(name.Digest ); ! ok {
81- ui .Warnf (ctx , ui .TagReferenceMessage , imageRef )
82- }
83- digest , err := ociremote .ResolveDigest (ref , remoteOpts ... )
84- if err != nil {
85- return err
86- }
87- // Overwrite "ref" with a digest to avoid a race where we use a tag
88- // multiple times, and it potentially points to different things at
89- // each access.
90- ref = digest // nolint
91-
92119 opts := []static.Option {static .WithLayerMediaType (types .DssePayloadType )}
93120 att , err := static .NewAttestation (payload , opts ... )
94121 if err != nil {
0 commit comments