1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 18:38:40 +00:00

[ImageVerify] Verify additional certificate-extensions (#3404)

* feat: add additionalExtensions to keyless imageVerify

Signed-off-by: Christian Kotzbauer <git@ckotzbauer.de>

* feat: regenerate code

Signed-off-by: Christian Kotzbauer <git@ckotzbauer.de>
This commit is contained in:
Christian Kotzbauer 2022-03-17 09:42:12 +01:00 committed by GitHub
parent b0860ba177
commit 860253d6aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 172 additions and 8 deletions

View file

@ -23,6 +23,9 @@ type ImageVerification struct {
// Issuer is the certificate issuer used for keyless signing.
Issuer string `json:"issuer,omitempty" yaml:"issuer,omitempty"`
// AdditionalExtensions are certificate-extensions used for keyless signing.
AdditionalExtensions map[string]string `json:"additionalExtensions,omitempty" yaml:"additionalExtensions,omitempty"`
// Annotations are used for image verification.
// Every specified key-value pair must exist and match in the verified payload.
// The payload may contain other key-value pairs.

View file

@ -568,6 +568,13 @@ func (in *ImageRegistry) DeepCopy() *ImageRegistry {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
*out = *in
if in.AdditionalExtensions != nil {
in, out := &in.AdditionalExtensions, &out.AdditionalExtensions
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))

View file

@ -1215,6 +1215,11 @@ spec:
items:
description: ImageVerification validates that images that match the specified pattern are signed with the supplied public key. Once the image is verified it is mutated to include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -2530,6 +2535,11 @@ spec:
items:
description: ImageVerification validates that images that match the specified pattern are signed with the supplied public key. Once the image is verified it is mutated to include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -5041,6 +5051,11 @@ spec:
items:
description: ImageVerification validates that images that match the specified pattern are signed with the supplied public key. Once the image is verified it is mutated to include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -6356,6 +6371,11 @@ spec:
items:
description: ImageVerification validates that images that match the specified pattern are signed with the supplied public key. Once the image is verified it is mutated to include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions used for keyless signing.
type: object
annotations:
additionalProperties:
type: string

View file

@ -1943,6 +1943,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -4057,6 +4063,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string

View file

@ -1944,6 +1944,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -4059,6 +4065,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string

View file

@ -1959,6 +1959,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -4073,6 +4079,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -7771,6 +7783,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -9886,6 +9904,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string

View file

@ -1948,6 +1948,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -4062,6 +4068,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -7736,6 +7748,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string
@ -9851,6 +9869,12 @@ spec:
public key. Once the image is verified it is mutated to
include the SHA digest retrieved during the registration.
properties:
additionalExtensions:
additionalProperties:
type: string
description: AdditionalExtensions are certificate-extensions
used for keyless signing.
type: object
annotations:
additionalProperties:
type: string

View file

@ -1456,6 +1456,17 @@ string
</tr>
<tr>
<td>
<code>additionalExtensions</code></br>
<em>
map[string]string
</em>
</td>
<td>
<p>AdditionalExtensions are certificate-extensions used for keyless signing.</p>
</td>
</tr>
<tr>
<td>
<code>annotations</code></br>
<em>
map[string]string

View file

@ -38,14 +38,15 @@ import (
var ImageSignatureRepository string
type Options struct {
ImageRef string
Key string
Roots []byte
Subject string
Issuer string
Annotations map[string]string
Repository string
Log logr.Logger
ImageRef string
Key string
Roots []byte
Subject string
Issuer string
AdditionalExtensions map[string]string
Annotations map[string]string
Repository string
Log logr.Logger
}
// VerifySignature verifies that the image has the expected key
@ -120,6 +121,10 @@ func VerifySignature(opts Options) (digest string, err error) {
return "", err
}
if err := matchExtensions(signatures, opts.AdditionalExtensions, log); err != nil {
return "", errors.Wrap(err, "extensions mismatch")
}
err = checkAnnotations(pld, opts.Annotations)
if err != nil {
return "", errors.Wrap(err, "annotation mismatch")
@ -378,6 +383,48 @@ func matchSubjectAndIssuer(signatures []oci.Signature, subject, issuer string) e
return fmt.Errorf("subject mismatch: expected %s, got %s", s, subject)
}
func matchExtensions(signatures []oci.Signature, requiredExtensions map[string]string, log logr.Logger) error {
if len(requiredExtensions) == 0 {
return nil
}
for _, sig := range signatures {
cert, err := sig.Cert()
if err != nil {
return errors.Wrap(err, "failed to read certificate")
}
if cert == nil {
return errors.Wrap(err, "certificate not found")
}
// This will return a map which consists of readable extension-names as keys
// or the raw extensionIDs as fallback and its values.
certExtensions := sigs.CertExtensions(cert)
for requiredKey, requiredValue := range requiredExtensions {
certValue, ok := certExtensions[requiredKey]
if !ok {
// "requiredKey" seems to be an extensionID, try to resolve its human readable name
readableName, ok := sigs.CertExtensionMap[requiredKey]
if !ok {
return fmt.Errorf("key %s not present", requiredKey)
}
certValue, ok = certExtensions[readableName]
if !ok {
return fmt.Errorf("key %s (%s) not present", requiredKey, readableName)
}
}
if requiredValue != "" && !wildcard.Match(requiredValue, certValue) {
return fmt.Errorf("extension mismatch: expected %s for key %s, got %s", requiredValue, requiredKey, certValue)
}
}
}
return nil
}
func checkAnnotations(payload []payload.SimpleContainerImage, annotations map[string]string) error {
for _, p := range payload {
for key, val := range annotations {

View file

@ -195,6 +195,10 @@ func (iv *imageVerifier) verifySignature(imageVerify *v1.ImageVerification, imag
opts.Subject = imageVerify.Subject
}
if imageVerify.AdditionalExtensions != nil {
opts.AdditionalExtensions = imageVerify.AdditionalExtensions
}
if imageVerify.Annotations != nil {
opts.Annotations = imageVerify.Annotations
}