podman

Форк
0
439 строк · 14.5 Кб
1
// Copyright 2022 The Sigstore Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package certificate
16

17
import (
18
	"crypto/x509/pkix"
19
	"encoding/asn1"
20
	"errors"
21
	"fmt"
22
)
23

24
var (
25
	// Deprecated: Use OIDIssuerV2
26
	OIDIssuer = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1}
27
	// Deprecated: Use OIDBuildTrigger
28
	OIDGitHubWorkflowTrigger = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}
29
	// Deprecated: Use OIDSourceRepositoryDigest
30
	OIDGitHubWorkflowSHA = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}
31
	// Deprecated: Use OIDBuildConfigURI or OIDBuildConfigDigest
32
	OIDGitHubWorkflowName = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}
33
	// Deprecated: Use SourceRepositoryURI
34
	OIDGitHubWorkflowRepository = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}
35
	// Deprecated: Use OIDSourceRepositoryRef
36
	OIDGitHubWorkflowRef = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}
37

38
	OIDOtherName = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 7}
39
	OIDIssuerV2  = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 8}
40

41
	// CI extensions
42
	OIDBuildSignerURI                      = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 9}
43
	OIDBuildSignerDigest                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 10}
44
	OIDRunnerEnvironment                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 11}
45
	OIDSourceRepositoryURI                 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 12}
46
	OIDSourceRepositoryDigest              = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 13}
47
	OIDSourceRepositoryRef                 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 14}
48
	OIDSourceRepositoryIdentifier          = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 15}
49
	OIDSourceRepositoryOwnerURI            = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 16}
50
	OIDSourceRepositoryOwnerIdentifier     = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 17}
51
	OIDBuildConfigURI                      = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 18}
52
	OIDBuildConfigDigest                   = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 19}
53
	OIDBuildTrigger                        = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 20}
54
	OIDRunInvocationURI                    = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 21}
55
	OIDSourceRepositoryVisibilityAtSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 22}
56
)
57

58
// Extensions contains all custom x509 extensions defined by Fulcio
59
type Extensions struct {
60
	// NB: New extensions must be added here and documented
61
	// at docs/oidc-info.md
62

63
	// The OIDC issuer. Should match `iss` claim of ID token or, in the case of
64
	// a federated login like Dex it should match the issuer URL of the
65
	// upstream issuer. The issuer is not set the extensions are invalid and
66
	// will fail to render.
67
	Issuer string // OID 1.3.6.1.4.1.57264.1.8 and 1.3.6.1.4.1.57264.1.1 (Deprecated)
68

69
	// Deprecated
70
	// Triggering event of the Github Workflow. Matches the `event_name` claim of ID
71
	// tokens from Github Actions
72
	GithubWorkflowTrigger string // OID 1.3.6.1.4.1.57264.1.2
73

74
	// Deprecated
75
	// SHA of git commit being built in Github Actions. Matches the `sha` claim of ID
76
	// tokens from Github Actions
77
	GithubWorkflowSHA string // OID 1.3.6.1.4.1.57264.1.3
78

79
	// Deprecated
80
	// Name of Github Actions Workflow. Matches the `workflow` claim of the ID
81
	// tokens from Github Actions
82
	GithubWorkflowName string // OID 1.3.6.1.4.1.57264.1.4
83

84
	// Deprecated
85
	// Repository of the Github Actions Workflow. Matches the `repository` claim of the ID
86
	// tokens from Github Actions
87
	GithubWorkflowRepository string // OID 1.3.6.1.4.1.57264.1.5
88

89
	// Deprecated
90
	// Git Ref of the Github Actions Workflow. Matches the `ref` claim of the ID tokens
91
	// from Github Actions
92
	GithubWorkflowRef string // 1.3.6.1.4.1.57264.1.6
93

94
	// Reference to specific build instructions that are responsible for signing.
95
	BuildSignerURI string // 1.3.6.1.4.1.57264.1.9
96

97
	// Immutable reference to the specific version of the build instructions that is responsible for signing.
98
	BuildSignerDigest string // 1.3.6.1.4.1.57264.1.10
99

100
	// Specifies whether the build took place in platform-hosted cloud infrastructure or customer/self-hosted infrastructure.
101
	RunnerEnvironment string // 1.3.6.1.4.1.57264.1.11
102

103
	// Source repository URL that the build was based on.
104
	SourceRepositoryURI string // 1.3.6.1.4.1.57264.1.12
105

106
	// Immutable reference to a specific version of the source code that the build was based upon.
107
	SourceRepositoryDigest string // 1.3.6.1.4.1.57264.1.13
108

109
	// Source Repository Ref that the build run was based upon.
110
	SourceRepositoryRef string // 1.3.6.1.4.1.57264.1.14
111

112
	// Immutable identifier for the source repository the workflow was based upon.
113
	SourceRepositoryIdentifier string // 1.3.6.1.4.1.57264.1.15
114

115
	// Source repository owner URL of the owner of the source repository that the build was based on.
116
	SourceRepositoryOwnerURI string // 1.3.6.1.4.1.57264.1.16
117

118
	// Immutable identifier for the owner of the source repository that the workflow was based upon.
119
	SourceRepositoryOwnerIdentifier string // 1.3.6.1.4.1.57264.1.17
120

121
	// Build Config URL to the top-level/initiating build instructions.
122
	BuildConfigURI string // 1.3.6.1.4.1.57264.1.18
123

124
	// Immutable reference to the specific version of the top-level/initiating build instructions.
125
	BuildConfigDigest string // 1.3.6.1.4.1.57264.1.19
126

127
	// Event or action that initiated the build.
128
	BuildTrigger string // 1.3.6.1.4.1.57264.1.20
129

130
	// Run Invocation URL to uniquely identify the build execution.
131
	RunInvocationURI string // 1.3.6.1.4.1.57264.1.21
132

133
	// Source repository visibility at the time of signing the certificate.
134
	SourceRepositoryVisibilityAtSigning string // 1.3.6.1.4.1.57264.1.22
135
}
136

137
func (e Extensions) Render() ([]pkix.Extension, error) {
138
	var exts []pkix.Extension
139

140
	// BEGIN: Deprecated
141
	if e.Issuer != "" {
142
		// deprecated issuer extension due to incorrect encoding
143
		exts = append(exts, pkix.Extension{
144
			Id:    OIDIssuer,
145
			Value: []byte(e.Issuer),
146
		})
147
	} else {
148
		return nil, errors.New("extensions must have a non-empty issuer url")
149
	}
150
	if e.GithubWorkflowTrigger != "" {
151
		exts = append(exts, pkix.Extension{
152
			Id:    OIDGitHubWorkflowTrigger,
153
			Value: []byte(e.GithubWorkflowTrigger),
154
		})
155
	}
156
	if e.GithubWorkflowSHA != "" {
157
		exts = append(exts, pkix.Extension{
158
			Id:    OIDGitHubWorkflowSHA,
159
			Value: []byte(e.GithubWorkflowSHA),
160
		})
161
	}
162
	if e.GithubWorkflowName != "" {
163
		exts = append(exts, pkix.Extension{
164
			Id:    OIDGitHubWorkflowName,
165
			Value: []byte(e.GithubWorkflowName),
166
		})
167
	}
168
	if e.GithubWorkflowRepository != "" {
169
		exts = append(exts, pkix.Extension{
170
			Id:    OIDGitHubWorkflowRepository,
171
			Value: []byte(e.GithubWorkflowRepository),
172
		})
173
	}
174
	if e.GithubWorkflowRef != "" {
175
		exts = append(exts, pkix.Extension{
176
			Id:    OIDGitHubWorkflowRef,
177
			Value: []byte(e.GithubWorkflowRef),
178
		})
179
	}
180
	// END: Deprecated
181

182
	// duplicate issuer with correct RFC 5280 encoding
183
	if e.Issuer != "" {
184
		// construct DER encoding of issuer string
185
		val, err := asn1.MarshalWithParams(e.Issuer, "utf8")
186
		if err != nil {
187
			return nil, err
188
		}
189
		exts = append(exts, pkix.Extension{
190
			Id:    OIDIssuerV2,
191
			Value: val,
192
		})
193
	} else {
194
		return nil, errors.New("extensions must have a non-empty issuer url")
195
	}
196

197
	if e.BuildSignerURI != "" {
198
		val, err := asn1.MarshalWithParams(e.BuildSignerURI, "utf8")
199
		if err != nil {
200
			return nil, err
201
		}
202
		exts = append(exts, pkix.Extension{
203
			Id:    OIDBuildSignerURI,
204
			Value: val,
205
		})
206
	}
207
	if e.BuildSignerDigest != "" {
208
		val, err := asn1.MarshalWithParams(e.BuildSignerDigest, "utf8")
209
		if err != nil {
210
			return nil, err
211
		}
212
		exts = append(exts, pkix.Extension{
213
			Id:    OIDBuildSignerDigest,
214
			Value: val,
215
		})
216
	}
217
	if e.RunnerEnvironment != "" {
218
		val, err := asn1.MarshalWithParams(e.RunnerEnvironment, "utf8")
219
		if err != nil {
220
			return nil, err
221
		}
222
		exts = append(exts, pkix.Extension{
223
			Id:    OIDRunnerEnvironment,
224
			Value: val,
225
		})
226
	}
227
	if e.SourceRepositoryURI != "" {
228
		val, err := asn1.MarshalWithParams(e.SourceRepositoryURI, "utf8")
229
		if err != nil {
230
			return nil, err
231
		}
232
		exts = append(exts, pkix.Extension{
233
			Id:    OIDSourceRepositoryURI,
234
			Value: val,
235
		})
236
	}
237
	if e.SourceRepositoryDigest != "" {
238
		val, err := asn1.MarshalWithParams(e.SourceRepositoryDigest, "utf8")
239
		if err != nil {
240
			return nil, err
241
		}
242
		exts = append(exts, pkix.Extension{
243
			Id:    OIDSourceRepositoryDigest,
244
			Value: val,
245
		})
246
	}
247
	if e.SourceRepositoryRef != "" {
248
		val, err := asn1.MarshalWithParams(e.SourceRepositoryRef, "utf8")
249
		if err != nil {
250
			return nil, err
251
		}
252
		exts = append(exts, pkix.Extension{
253
			Id:    OIDSourceRepositoryRef,
254
			Value: val,
255
		})
256
	}
257
	if e.SourceRepositoryIdentifier != "" {
258
		val, err := asn1.MarshalWithParams(e.SourceRepositoryIdentifier, "utf8")
259
		if err != nil {
260
			return nil, err
261
		}
262
		exts = append(exts, pkix.Extension{
263
			Id:    OIDSourceRepositoryIdentifier,
264
			Value: val,
265
		})
266
	}
267
	if e.SourceRepositoryOwnerURI != "" {
268
		val, err := asn1.MarshalWithParams(e.SourceRepositoryOwnerURI, "utf8")
269
		if err != nil {
270
			return nil, err
271
		}
272
		exts = append(exts, pkix.Extension{
273
			Id:    OIDSourceRepositoryOwnerURI,
274
			Value: val,
275
		})
276
	}
277
	if e.SourceRepositoryOwnerIdentifier != "" {
278
		val, err := asn1.MarshalWithParams(e.SourceRepositoryOwnerIdentifier, "utf8")
279
		if err != nil {
280
			return nil, err
281
		}
282
		exts = append(exts, pkix.Extension{
283
			Id:    OIDSourceRepositoryOwnerIdentifier,
284
			Value: val,
285
		})
286
	}
287
	if e.BuildConfigURI != "" {
288
		val, err := asn1.MarshalWithParams(e.BuildConfigURI, "utf8")
289
		if err != nil {
290
			return nil, err
291
		}
292
		exts = append(exts, pkix.Extension{
293
			Id:    OIDBuildConfigURI,
294
			Value: val,
295
		})
296
	}
297
	if e.BuildConfigDigest != "" {
298
		val, err := asn1.MarshalWithParams(e.BuildConfigDigest, "utf8")
299
		if err != nil {
300
			return nil, err
301
		}
302
		exts = append(exts, pkix.Extension{
303
			Id:    OIDBuildConfigDigest,
304
			Value: val,
305
		})
306
	}
307
	if e.BuildTrigger != "" {
308
		val, err := asn1.MarshalWithParams(e.BuildTrigger, "utf8")
309
		if err != nil {
310
			return nil, err
311
		}
312
		exts = append(exts, pkix.Extension{
313
			Id:    OIDBuildTrigger,
314
			Value: val,
315
		})
316
	}
317
	if e.RunInvocationURI != "" {
318
		val, err := asn1.MarshalWithParams(e.RunInvocationURI, "utf8")
319
		if err != nil {
320
			return nil, err
321
		}
322
		exts = append(exts, pkix.Extension{
323
			Id:    OIDRunInvocationURI,
324
			Value: val,
325
		})
326
	}
327
	if e.SourceRepositoryVisibilityAtSigning != "" {
328
		val, err := asn1.MarshalWithParams(e.SourceRepositoryVisibilityAtSigning, "utf8")
329
		if err != nil {
330
			return nil, err
331
		}
332
		exts = append(exts, pkix.Extension{
333
			Id:    OIDSourceRepositoryVisibilityAtSigning,
334
			Value: val,
335
		})
336
	}
337

338
	return exts, nil
339
}
340

341
func parseExtensions(ext []pkix.Extension) (Extensions, error) {
342
	out := Extensions{}
343

344
	for _, e := range ext {
345
		switch {
346
		// BEGIN: Deprecated
347
		case e.Id.Equal(OIDIssuer):
348
			out.Issuer = string(e.Value)
349
		case e.Id.Equal(OIDGitHubWorkflowTrigger):
350
			out.GithubWorkflowTrigger = string(e.Value)
351
		case e.Id.Equal(OIDGitHubWorkflowSHA):
352
			out.GithubWorkflowSHA = string(e.Value)
353
		case e.Id.Equal(OIDGitHubWorkflowName):
354
			out.GithubWorkflowName = string(e.Value)
355
		case e.Id.Equal(OIDGitHubWorkflowRepository):
356
			out.GithubWorkflowRepository = string(e.Value)
357
		case e.Id.Equal(OIDGitHubWorkflowRef):
358
			out.GithubWorkflowRef = string(e.Value)
359
		// END: Deprecated
360
		case e.Id.Equal(OIDIssuerV2):
361
			if err := ParseDERString(e.Value, &out.Issuer); err != nil {
362
				return Extensions{}, err
363
			}
364
		case e.Id.Equal(OIDBuildSignerURI):
365
			if err := ParseDERString(e.Value, &out.BuildSignerURI); err != nil {
366
				return Extensions{}, err
367
			}
368
		case e.Id.Equal(OIDBuildSignerDigest):
369
			if err := ParseDERString(e.Value, &out.BuildSignerDigest); err != nil {
370
				return Extensions{}, err
371
			}
372
		case e.Id.Equal(OIDRunnerEnvironment):
373
			if err := ParseDERString(e.Value, &out.RunnerEnvironment); err != nil {
374
				return Extensions{}, err
375
			}
376
		case e.Id.Equal(OIDSourceRepositoryURI):
377
			if err := ParseDERString(e.Value, &out.SourceRepositoryURI); err != nil {
378
				return Extensions{}, err
379
			}
380
		case e.Id.Equal(OIDSourceRepositoryDigest):
381
			if err := ParseDERString(e.Value, &out.SourceRepositoryDigest); err != nil {
382
				return Extensions{}, err
383
			}
384
		case e.Id.Equal(OIDSourceRepositoryRef):
385
			if err := ParseDERString(e.Value, &out.SourceRepositoryRef); err != nil {
386
				return Extensions{}, err
387
			}
388
		case e.Id.Equal(OIDSourceRepositoryIdentifier):
389
			if err := ParseDERString(e.Value, &out.SourceRepositoryIdentifier); err != nil {
390
				return Extensions{}, err
391
			}
392
		case e.Id.Equal(OIDSourceRepositoryOwnerURI):
393
			if err := ParseDERString(e.Value, &out.SourceRepositoryOwnerURI); err != nil {
394
				return Extensions{}, err
395
			}
396
		case e.Id.Equal(OIDSourceRepositoryOwnerIdentifier):
397
			if err := ParseDERString(e.Value, &out.SourceRepositoryOwnerIdentifier); err != nil {
398
				return Extensions{}, err
399
			}
400
		case e.Id.Equal(OIDBuildConfigURI):
401
			if err := ParseDERString(e.Value, &out.BuildConfigURI); err != nil {
402
				return Extensions{}, err
403
			}
404
		case e.Id.Equal(OIDBuildConfigDigest):
405
			if err := ParseDERString(e.Value, &out.BuildConfigDigest); err != nil {
406
				return Extensions{}, err
407
			}
408
		case e.Id.Equal(OIDBuildTrigger):
409
			if err := ParseDERString(e.Value, &out.BuildTrigger); err != nil {
410
				return Extensions{}, err
411
			}
412
		case e.Id.Equal(OIDRunInvocationURI):
413
			if err := ParseDERString(e.Value, &out.RunInvocationURI); err != nil {
414
				return Extensions{}, err
415
			}
416
		case e.Id.Equal(OIDSourceRepositoryVisibilityAtSigning):
417
			if err := ParseDERString(e.Value, &out.SourceRepositoryVisibilityAtSigning); err != nil {
418
				return Extensions{}, err
419
			}
420
		}
421
	}
422

423
	// We only ever return nil, but leaving error in place so that we can add
424
	// more complex parsing of fields in a backwards compatible way if needed.
425
	return out, nil
426
}
427

428
// ParseDERString decodes a DER-encoded string and puts the value in parsedVal.
429
// Returns an error if the unmarshalling fails or if there are trailing bytes in the encoding.
430
func ParseDERString(val []byte, parsedVal *string) error {
431
	rest, err := asn1.Unmarshal(val, parsedVal)
432
	if err != nil {
433
		return fmt.Errorf("unexpected error unmarshalling DER-encoded string: %v", err)
434
	}
435
	if len(rest) != 0 {
436
		return errors.New("unexpected trailing bytes in DER-encoded string")
437
	}
438
	return nil
439
}
440

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.