1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package remote
17
18 import (
19 "errors"
20 "io"
21 "strings"
22 "testing"
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/types"
28 )
29
30 func TestTagMethods(t *testing.T) {
31 rg := remoteGet
32 defer func() {
33 remoteGet = rg
34 }()
35 remoteGet = func(_ name.Reference, _ ...remote.Option) (*remote.Descriptor, error) {
36 return &remote.Descriptor{
37 Descriptor: v1.Descriptor{
38 Digest: v1.Hash{
39 Algorithm: "sha256",
40
41
42 Hex: "be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4",
43 },
44 },
45 }, nil
46 }
47
48 tests := []struct {
49 name string
50 fn func(name.Reference, ...Option) (name.Tag, error)
51 ref name.Reference
52 opts []Option
53 want name.Reference
54 }{{
55 name: "signature passed a tag",
56 fn: SignatureTag,
57 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
58 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sig"),
59 }, {
60 name: "signature passed a tag (w/ custom suffix)",
61 fn: SignatureTag,
62 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
63 opts: []Option{WithSignatureSuffix("snowflake")},
64 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.snowflake"),
65 }, {
66 name: "signature passed a digest",
67 fn: SignatureTag,
68 ref: name.MustParseReference("gcr.io/distroless/static@sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
69 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sig"),
70 }, {
71 name: "attestation passed a tag",
72 fn: AttestationTag,
73 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
74 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.att"),
75 }, {
76 name: "attestation passed a tag (w/ custom suffix)",
77 fn: AttestationTag,
78 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
79 opts: []Option{WithAttestationSuffix("snowflake")},
80 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.snowflake"),
81 }, {
82 name: "attestation passed a digest",
83 fn: AttestationTag,
84 ref: name.MustParseReference("gcr.io/distroless/static@sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
85 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.att"),
86 }, {
87 name: "sbom passed a tag",
88 fn: SBOMTag,
89 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
90 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sbom"),
91 }, {
92 name: "sbom passed a tag (w/ custom suffix)",
93 fn: SBOMTag,
94 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
95 opts: []Option{WithSBOMSuffix("snowflake")},
96 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.snowflake"),
97 }, {
98 name: "sbom passed a digest",
99 fn: SBOMTag,
100 ref: name.MustParseReference("gcr.io/distroless/static@sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
101 want: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sbom"),
102 }}
103
104 for _, test := range tests {
105 t.Run(test.name, func(t *testing.T) {
106 got, err := test.fn(test.ref, test.opts...)
107 if err != nil {
108 t.Fatalf("fn() = %v", err)
109 }
110 if got.String() != test.want.String() {
111 t.Errorf("fn() = %s, wanted %s", got.String(), test.want.String())
112 }
113 })
114 }
115 }
116
117 func TestTagMethodErrors(t *testing.T) {
118 rg := remoteGet
119 defer func() {
120 remoteGet = rg
121 }()
122 errRemoteGet := errors.New("remote.Get failure")
123 remoteGet = func(_ name.Reference, _ ...remote.Option) (*remote.Descriptor, error) {
124 return nil, errRemoteGet
125 }
126
127 tests := []struct {
128 name string
129 fn func(name.Reference, ...Option) (name.Tag, error)
130 ref name.Reference
131 want error
132 }{
133 {
134 name: "signature passed a tag",
135 fn: SignatureTag,
136 ref: name.MustParseReference("gcr.io/distroless/static:nonroot"),
137 want: errRemoteGet,
138 },
139 }
140
141 for _, test := range tests {
142 t.Run(test.name, func(t *testing.T) {
143 tag, got := test.fn(test.ref)
144 if got == nil {
145 t.Fatalf("fn() = %v, wanted %v", tag, test.want)
146 }
147 if got.Error() != test.want.Error() {
148 t.Errorf("fn() = %v, wanted %v", got, test.want)
149 }
150 })
151 }
152 }
153
154 func TestDockercontentDigest(t *testing.T) {
155 rg := remoteGet
156 defer func() {
157 remoteGet = rg
158 }()
159 remoteGet = func(_ name.Reference, _ ...remote.Option) (*remote.Descriptor, error) {
160 return &remote.Descriptor{
161 Descriptor: v1.Descriptor{
162 Digest: v1.Hash{
163 Algorithm: "sha256",
164
165
166 Hex: "be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4",
167 },
168 },
169 }, nil
170 }
171
172 repo, err := name.NewRepository("gcr.io/distroless/static")
173 if err != nil {
174 t.Fatalf("unexpected error: %v", err)
175 }
176 tests := []struct {
177 name string
178 tag name.Tag
179 wantTag name.Tag
180 }{
181 {
182 name: "docker content digest for tag",
183 tag: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sig").(name.Tag),
184 wantTag: repo.Tag("sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
185 },
186 {
187 name: "docker content digest for attestation",
188 tag: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.att").(name.Tag),
189 wantTag: repo.Tag("sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
190 },
191 {
192 name: "docker content digest for SBOM",
193 tag: name.MustParseReference("gcr.io/distroless/static:sha256-be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4.sbom").(name.Tag),
194 wantTag: repo.Tag("sha256:be5d77c62dbe7fedfb0a4e5ec2f91078080800ab1f18358e5f31fcc8faa023c4"),
195 },
196 }
197 for _, test := range tests {
198 t.Run(test.name, func(t *testing.T) {
199 gotTag, err := DockerContentDigest(test.tag)
200 if err != nil {
201 t.Fatalf("fn() = %v", err)
202 }
203 if gotTag != test.wantTag {
204 t.Errorf("fn() = %s, wanted %s", gotTag.String(), test.wantTag.String())
205 }
206 })
207 }
208 }
209
210 func TestPayload(t *testing.T) {
211 tests := []struct {
212 name string
213 size int64
214 env map[string]string
215 wantError error
216 }{
217 {
218 name: "within default limit",
219 size: 1000,
220 wantError: nil,
221 },
222 {
223 name: "excceds default limit",
224 size: 1073741824,
225 wantError: errors.New("size of layer (1073741824) exceeded the limit (134217728)"),
226 },
227 {
228 name: "exceeds overridden limit",
229 size: 5120,
230 env: map[string]string{"COSIGN_MAX_ATTACHMENT_SIZE": "1KB"},
231 wantError: errors.New("size of layer (5120) exceeded the limit (1000)"),
232 },
233 {
234 name: "within overridden limit",
235 size: 5120,
236 env: map[string]string{"COSIGN_MAX_ATTACHMENT_SIZE": "10KB"},
237 },
238 }
239 for _, test := range tests {
240 t.Run(test.name, func(t *testing.T) {
241 for k, v := range test.env {
242 t.Setenv(k, v)
243 }
244 a := attached{
245 layer: &mockLayer{
246 size: test.size,
247 },
248 }
249 _, err := a.Payload()
250 if test.wantError != nil && test.wantError.Error() != err.Error() {
251 t.Fatalf("Payload() = %v, wanted %v", err, test.wantError)
252 }
253 if test.wantError == nil && err != nil {
254 t.Fatalf("Payload() = %v, wanted %v", err, test.wantError)
255 }
256 })
257 }
258 }
259
260 type mockLayer struct {
261 size int64
262 }
263
264 func (m *mockLayer) Compressed() (io.ReadCloser, error) {
265 return io.NopCloser(strings.NewReader("test payload")), nil
266 }
267
268 func (m *mockLayer) Size() (int64, error) {
269 return m.size, nil
270 }
271
272 func (m *mockLayer) Digest() (v1.Hash, error) { panic("not implemented") }
273 func (m *mockLayer) DiffID() (v1.Hash, error) { panic("not implemented") }
274 func (m *mockLayer) Uncompressed() (io.ReadCloser, error) { panic("not implemented") }
275 func (m *mockLayer) MediaType() (types.MediaType, error) { panic("not implemented") }
276
View as plain text