1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package remote
17
18 import (
19 "bytes"
20 "encoding/json"
21 "fmt"
22 "os"
23
24 "github.com/google/go-containerregistry/pkg/name"
25 v1 "github.com/google/go-containerregistry/pkg/v1"
26 "github.com/google/go-containerregistry/pkg/v1/remote"
27 "github.com/google/go-containerregistry/pkg/v1/static"
28 "github.com/google/go-containerregistry/pkg/v1/types"
29 ociexperimental "github.com/sigstore/cosign/v2/internal/pkg/oci/remote"
30 "github.com/sigstore/cosign/v2/pkg/oci"
31 ctypes "github.com/sigstore/cosign/v2/pkg/types"
32 )
33
34
35
36
37
38 func WriteSignedImageIndexImages(ref name.Reference, sii oci.SignedImageIndex, opts ...Option) error {
39 repo := ref.Context()
40 o := makeOptions(repo, opts...)
41
42
43 ii, err := sii.SignedImageIndex(v1.Hash{})
44 if err != nil {
45 return fmt.Errorf("signed image index: %w", err)
46 }
47 if ii != nil {
48 if err := remote.WriteIndex(ref, ii, o.ROpt...); err != nil {
49 return fmt.Errorf("writing index: %w", err)
50 }
51 }
52
53
54 si, err := sii.SignedImage(v1.Hash{})
55 if err != nil {
56 return fmt.Errorf("signed image: %w", err)
57 }
58 if si != nil {
59 if err := remoteWrite(ref, si, o.ROpt...); err != nil {
60 return fmt.Errorf("remote write: %w", err)
61 }
62 }
63
64
65 sigs, err := sii.Signatures()
66 if err != nil {
67 return err
68 }
69 if sigs != nil {
70 sigsTag, err := SignatureTag(ref, opts...)
71 if err != nil {
72 return fmt.Errorf("sigs tag: %w", err)
73 }
74 if err := remoteWrite(sigsTag, sigs, o.ROpt...); err != nil {
75 return err
76 }
77 }
78
79
80 atts, err := sii.Attestations()
81 if err != nil {
82 return err
83 }
84 if atts != nil {
85 attsTag, err := AttestationTag(ref, opts...)
86 if err != nil {
87 return fmt.Errorf("sigs tag: %w", err)
88 }
89 return remoteWrite(attsTag, atts, o.ROpt...)
90 }
91 return nil
92 }
93
94
95
96 func WriteSignatures(repo name.Repository, se oci.SignedEntity, opts ...Option) error {
97 o := makeOptions(repo, opts...)
98
99
100 sigs, err := se.Signatures()
101 if err != nil {
102 return err
103 }
104
105
106 h, err := se.Digest()
107 if err != nil {
108 return err
109 }
110 tag := o.TargetRepository.Tag(normalize(h, o.TagPrefix, o.SignatureSuffix))
111
112
113 return remoteWrite(tag, sigs, o.ROpt...)
114 }
115
116
117
118 func WriteAttestations(repo name.Repository, se oci.SignedEntity, opts ...Option) error {
119 o := makeOptions(repo, opts...)
120
121
122 atts, err := se.Attestations()
123 if err != nil {
124 return err
125 }
126
127
128 h, err := se.Digest()
129 if err != nil {
130 return err
131 }
132 tag := o.TargetRepository.Tag(normalize(h, o.TagPrefix, o.AttestationSuffix))
133
134
135 return remoteWrite(tag, atts, o.ROpt...)
136 }
137
138
139
140 func WriteSignaturesExperimentalOCI(d name.Digest, se oci.SignedEntity, opts ...Option) error {
141 o := makeOptions(d.Repository, opts...)
142 signTarget := d.String()
143 ref, err := name.ParseReference(signTarget, o.NameOpts...)
144 if err != nil {
145 return err
146 }
147 desc, err := remote.Head(ref, o.ROpt...)
148 if err != nil {
149 return err
150 }
151 sigs, err := se.Signatures()
152 if err != nil {
153 return err
154 }
155
156
157 s, err := sigs.Get()
158 if err != nil {
159 return err
160 }
161 for _, v := range s {
162 if err := remote.WriteLayer(d.Repository, v, o.ROpt...); err != nil {
163 return err
164 }
165 }
166
167
168 configBytes, err := sigs.RawConfigFile()
169 if err != nil {
170 return err
171 }
172 var configDesc v1.Descriptor
173 if err := json.Unmarshal(configBytes, &configDesc); err != nil {
174 return err
175 }
176 configLayer := static.NewLayer(configBytes, configDesc.MediaType)
177 if err := remote.WriteLayer(d.Repository, configLayer, o.ROpt...); err != nil {
178 return err
179 }
180
181
182 b, err := sigs.RawManifest()
183 if err != nil {
184 return err
185 }
186 var m v1.Manifest
187 if err := json.Unmarshal(b, &m); err != nil {
188 return err
189 }
190
191 artifactType := ociexperimental.ArtifactType("sig")
192 m.Config.MediaType = types.MediaType(artifactType)
193 m.Subject = desc
194 b, err = json.Marshal(&m)
195 if err != nil {
196 return err
197 }
198 digest, _, err := v1.SHA256(bytes.NewReader(b))
199 if err != nil {
200 return err
201 }
202 targetRef, err := name.ParseReference(fmt.Sprintf("%s/%s@%s", d.RegistryStr(), d.RepositoryStr(), digest.String()))
203 if err != nil {
204 return err
205 }
206
207 fmt.Fprintf(os.Stderr, "Uploading signature for [%s] to [%s] with config.mediaType [%s] layers[0].mediaType [%s].\n",
208 d.String(), targetRef.String(), artifactType, ctypes.SimpleSigningMediaType)
209 return remote.Put(targetRef, &taggableManifest{raw: b, mediaType: m.MediaType}, o.ROpt...)
210 }
211
212 type taggableManifest struct {
213 raw []byte
214 mediaType types.MediaType
215 }
216
217 func (taggable taggableManifest) RawManifest() ([]byte, error) {
218 return taggable.raw, nil
219 }
220
221 func (taggable taggableManifest) MediaType() (types.MediaType, error) {
222 return taggable.mediaType, nil
223 }
224
View as plain text