diff --git a/api/kyverno/v1/image_verification_types.go b/api/kyverno/v1/image_verification_types.go index 3ad5a49c09ac..40b4f5f97467 100644 --- a/api/kyverno/v1/image_verification_types.go +++ b/api/kyverno/v1/image_verification_types.go @@ -56,6 +56,13 @@ type ImageVerification struct { // +kubebuilder:validation:Optional ImageReferences []string `json:"imageReferences,omitempty" yaml:"imageReferences,omitempty"` + // SkipImageReferences is a list of matching image reference patterns that should be skipped. + // At least one pattern in the list must match the image for the rule to be skipped. Each image reference + // consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). + // Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. + // +kubebuilder:validation:Optional + SkipImageReferences []string `json:"skipImageReferences,omitempty" yaml:"skipImageReferences,omitempty"` + // Deprecated. Use StaticKeyAttestor instead. Key string `json:"key,omitempty" yaml:"key,omitempty"` diff --git a/api/kyverno/v1/zz_generated.deepcopy.go b/api/kyverno/v1/zz_generated.deepcopy.go index df925f686f74..90f8f017c676 100755 --- a/api/kyverno/v1/zz_generated.deepcopy.go +++ b/api/kyverno/v1/zz_generated.deepcopy.go @@ -758,6 +758,11 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.SkipImageReferences != nil { + in, out := &in.SkipImageReferences, &out.SkipImageReferences + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.AdditionalExtensions != nil { in, out := &in.AdditionalExtensions, &out.AdditionalExtensions *out = make(map[string]string, len(*in)) diff --git a/api/kyverno/v2beta1/image_verification_types.go b/api/kyverno/v2beta1/image_verification_types.go index 04efac4a3b7a..5ec162086d43 100644 --- a/api/kyverno/v2beta1/image_verification_types.go +++ b/api/kyverno/v2beta1/image_verification_types.go @@ -21,6 +21,13 @@ type ImageVerification struct { // +kubebuilder:validation:Optional ImageReferences []string `json:"imageReferences,omitempty" yaml:"imageReferences,omitempty"` + // SkipImageReferences is a list of matching image reference patterns that should be skipped. + // At least one pattern in the list must match the image for the rule to be skipped. Each image reference + // consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). + // Wildcards ('*' and '?') are allowed. See: https://kubernetes.io/docs/concepts/containers/images. + // +kubebuilder:validation:Optional + SkipImageReferences []string `json:"skipImageReferences,omitempty" yaml:"skipImageReferences,omitempty"` + // Attestors specified the required attestors (i.e. authorities) // +kubebuilder:validation:Optional Attestors []kyvernov1.AttestorSet `json:"attestors,omitempty" yaml:"attestors,omitempty"` diff --git a/api/kyverno/v2beta1/zz_generated.deepcopy.go b/api/kyverno/v2beta1/zz_generated.deepcopy.go index 33f36147cb77..b3326b74eb10 100755 --- a/api/kyverno/v2beta1/zz_generated.deepcopy.go +++ b/api/kyverno/v2beta1/zz_generated.deepcopy.go @@ -376,6 +376,11 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.SkipImageReferences != nil { + in, out := &in.SkipImageReferences, &out.SkipImageReferences + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Attestors != nil { in, out := &in.Attestors, &out.Attestors *out = make([]v1.AttestorSet, len(*in)) diff --git a/charts/kyverno/charts/crds/templates/crds.yaml b/charts/kyverno/charts/crds/templates/crds.yaml index 258b710b5f26..a019949f73f1 100644 --- a/charts/kyverno/charts/crds/templates/crds.yaml +++ b/charts/kyverno/charts/crds/templates/crds.yaml @@ -14291,6 +14291,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -18849,6 +18860,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -23048,6 +23070,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -27603,6 +27636,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -32099,6 +32143,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -36658,6 +36713,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -40858,6 +40924,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -45413,6 +45490,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml index 5b7de6c526f1..e001acdffd11 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml @@ -4340,6 +4340,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -8898,6 +8909,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -13097,6 +13119,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -17652,6 +17685,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml index 794b75d934a6..47f889a79e0c 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml @@ -4341,6 +4341,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -8900,6 +8911,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -13100,6 +13122,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -17655,6 +17688,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/config/crds/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno.io_clusterpolicies.yaml index 5b7de6c526f1..e001acdffd11 100644 --- a/config/crds/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno.io_clusterpolicies.yaml @@ -4340,6 +4340,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -8898,6 +8909,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -13097,6 +13119,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -17652,6 +17685,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/config/crds/kyverno.io_policies.yaml b/config/crds/kyverno.io_policies.yaml index 794b75d934a6..47f889a79e0c 100644 --- a/config/crds/kyverno.io_policies.yaml +++ b/config/crds/kyverno.io_policies.yaml @@ -4341,6 +4341,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -8900,6 +8911,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -13100,6 +13122,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -17655,6 +17688,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 609db3a0a302..2f462668aee3 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -14510,6 +14510,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -19068,6 +19079,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -23267,6 +23289,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -27822,6 +27855,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -32320,6 +32364,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -36879,6 +36934,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string @@ -41079,6 +41145,17 @@ spec: i.e. have matched passed a signature or attestation check. type: boolean + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. At + least one pattern in the list must match the image for + the rule to be skipped. Each image reference consists + of a registry address (defaults to docker.io), repository, + image, and tag (defaults to latest). Wildcards (''*'' + and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array type: description: Type specifies the method of signature validation. The allowed options are Cosign and Notary. By default @@ -45634,6 +45711,17 @@ spec: roots: description: Deprecated. Use KeylessAttestor instead. type: string + skipImageReferences: + description: 'SkipImageReferences is a list of matching + image reference patterns that should be skipped. + At least one pattern in the list must match the + image for the rule to be skipped. Each image reference + consists of a registry address (defaults to docker.io), + repository, image, and tag (defaults to latest). + Wildcards (''*'' and ''?'') are allowed. See: https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array subject: description: Deprecated. Use KeylessAttestor instead. type: string diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 210d7f024975..c81187fe0245 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -2187,6 +2187,20 @@

ImageVerification +skipImageReferences
+ +[]string + + + +

SkipImageReferences is a list of matching image reference patterns that should be skipped. +At least one pattern in the list must match the image for the rule to be skipped. Each image reference +consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). +Wildcards (‘*’ and ‘?’) are allowed. See: https://kubernetes.io/docs/concepts/containers/images.

+ + + + key
string @@ -9033,6 +9047,20 @@

ImageVerification +skipImageReferences
+ +[]string + + + +

SkipImageReferences is a list of matching image reference patterns that should be skipped. +At least one pattern in the list must match the image for the rule to be skipped. Each image reference +consists of a registry address (defaults to docker.io), repository, image, and tag (defaults to latest). +Wildcards (‘*’ and ‘?’) are allowed. See: https://kubernetes.io/docs/concepts/containers/images.

+ + + + attestors
diff --git a/pkg/client/applyconfigurations/kyverno/v1/imageverification.go b/pkg/client/applyconfigurations/kyverno/v1/imageverification.go index 04d051bd5ccb..60920acaf1d6 100644 --- a/pkg/client/applyconfigurations/kyverno/v1/imageverification.go +++ b/pkg/client/applyconfigurations/kyverno/v1/imageverification.go @@ -28,6 +28,7 @@ type ImageVerificationApplyConfiguration struct { Type *v1.ImageVerificationType `json:"type,omitempty"` Image *string `json:"image,omitempty"` ImageReferences []string `json:"imageReferences,omitempty"` + SkipImageReferences []string `json:"skipImageReferences,omitempty"` Key *string `json:"key,omitempty"` Roots *string `json:"roots,omitempty"` Subject *string `json:"subject,omitempty"` @@ -76,6 +77,16 @@ func (b *ImageVerificationApplyConfiguration) WithImageReferences(values ...stri return b } +// WithSkipImageReferences adds the given value to the SkipImageReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SkipImageReferences field. +func (b *ImageVerificationApplyConfiguration) WithSkipImageReferences(values ...string) *ImageVerificationApplyConfiguration { + for i := range values { + b.SkipImageReferences = append(b.SkipImageReferences, values[i]) + } + return b +} + // WithKey sets the Key field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Key field is set to the value of the last call. diff --git a/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go b/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go index 4eab917fed77..cf924395534a 100644 --- a/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go +++ b/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go @@ -28,6 +28,7 @@ import ( type ImageVerificationApplyConfiguration struct { Type *v1.ImageVerificationType `json:"type,omitempty"` ImageReferences []string `json:"imageReferences,omitempty"` + SkipImageReferences []string `json:"skipImageReferences,omitempty"` Attestors []kyvernov1.AttestorSetApplyConfiguration `json:"attestors,omitempty"` Attestations []kyvernov1.AttestationApplyConfiguration `json:"attestations,omitempty"` Repository *string `json:"repository,omitempty"` @@ -62,6 +63,16 @@ func (b *ImageVerificationApplyConfiguration) WithImageReferences(values ...stri return b } +// WithSkipImageReferences adds the given value to the SkipImageReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the SkipImageReferences field. +func (b *ImageVerificationApplyConfiguration) WithSkipImageReferences(values ...string) *ImageVerificationApplyConfiguration { + for i := range values { + b.SkipImageReferences = append(b.SkipImageReferences, values[i]) + } + return b +} + // WithAttestors adds the given value to the Attestors field in the declarative configuration // and returns the receiver, so that objects can be build by chaining "With" function invocations. // If called multiple times, values provided by each call will be appended to the Attestors field. diff --git a/pkg/engine/api/imageverifymetadata.go b/pkg/engine/api/imageverifymetadata.go index e8b5691d6c9b..8c3ea128943b 100644 --- a/pkg/engine/api/imageverifymetadata.go +++ b/pkg/engine/api/imageverifymetadata.go @@ -10,13 +10,21 @@ import ( "gomodules.xyz/jsonpatch/v2" ) +type ImageVerificationMetadataStatus string + +const ( + ImageVerificationPass ImageVerificationMetadataStatus = "pass" + ImageVerificationFail ImageVerificationMetadataStatus = "fail" + ImageVerificationSkip ImageVerificationMetadataStatus = "skip" +) + type ImageVerificationMetadata struct { - Data map[string]bool `json:"data"` + Data map[string]ImageVerificationMetadataStatus `json:"data"` } -func (ivm *ImageVerificationMetadata) Add(image string, verified bool) { +func (ivm *ImageVerificationMetadata) Add(image string, verified ImageVerificationMetadataStatus) { if ivm.Data == nil { - ivm.Data = make(map[string]bool) + ivm.Data = make(map[string]ImageVerificationMetadataStatus) } ivm.Data[image] = verified } @@ -29,11 +37,22 @@ func (ivm *ImageVerificationMetadata) IsVerified(image string) bool { if !ok { return false } + return verified == ImageVerificationPass || verified == ImageVerificationSkip +} + +func (ivm *ImageVerificationMetadata) ImageVerificationStatus(image string) ImageVerificationMetadataStatus { + if ivm.Data == nil { + return ImageVerificationFail + } + verified, ok := ivm.Data[image] + if !ok { + return ImageVerificationFail + } return verified } func ParseImageMetadata(jsonData string) (*ImageVerificationMetadata, error) { - var data map[string]bool + var data map[string]ImageVerificationMetadataStatus if err := json.Unmarshal([]byte(jsonData), &data); err != nil { return nil, err } diff --git a/pkg/engine/api/imageverifymetadata_test.go b/pkg/engine/api/imageverifymetadata_test.go index bf4da4296ed6..e834194cd250 100644 --- a/pkg/engine/api/imageverifymetadata_test.go +++ b/pkg/engine/api/imageverifymetadata_test.go @@ -10,7 +10,7 @@ import ( func TestImageVerificationMetadata_IsVerified(t *testing.T) { type fields struct { - Data map[string]bool + Data map[string]ImageVerificationMetadataStatus } type args struct { image string @@ -22,8 +22,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) { want bool }{{ fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ @@ -32,8 +32,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) { want: true, }, { fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ @@ -42,8 +42,8 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) { want: false, }, { fields: fields{ - Data: map[string]bool{ - "test2": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test2": ImageVerificationFail, }, }, args: args{ @@ -70,11 +70,11 @@ func TestImageVerificationMetadata_IsVerified(t *testing.T) { func TestImageVerificationMetadata_Add(t *testing.T) { type fields struct { - Data map[string]bool + Data map[string]ImageVerificationMetadataStatus } type args struct { image string - verified bool + verified ImageVerificationMetadataStatus } tests := []struct { name string @@ -83,43 +83,43 @@ func TestImageVerificationMetadata_Add(t *testing.T) { want *ImageVerificationMetadata }{{ fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ image: "test", - verified: false, + verified: ImageVerificationFail, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationFail, }, }, }, { args: args{ image: "test", - verified: false, + verified: ImageVerificationFail, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationFail, }, }, }, { fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ image: "test2", - verified: false, + verified: ImageVerificationFail, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": true, - "test2": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, + "test2": ImageVerificationFail, }, }, }} @@ -152,21 +152,21 @@ func TestParseImageMetadata(t *testing.T) { wantErr: true, }, { args: args{ - jsonData: `{"test":true}`, + jsonData: `{"test":"pass"}`, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, }, { args: args{ - jsonData: `{"test":true,"test2":false}`, + jsonData: `{"test":"pass","test2":"fail"}`, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": true, - "test2": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, + "test2": ImageVerificationFail, }, }, }} @@ -186,7 +186,7 @@ func TestParseImageMetadata(t *testing.T) { func TestImageVerificationMetadata_IsEmpty(t *testing.T) { type fields struct { - Data map[string]bool + Data map[string]ImageVerificationMetadataStatus } tests := []struct { name string @@ -194,8 +194,8 @@ func TestImageVerificationMetadata_IsEmpty(t *testing.T) { want bool }{{ fields: fields{ - Data: map[string]bool{ - "test": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationFail, }, }, want: false, @@ -216,7 +216,7 @@ func TestImageVerificationMetadata_IsEmpty(t *testing.T) { func TestImageVerificationMetadata_Merge(t *testing.T) { type fields struct { - Data map[string]bool + Data map[string]ImageVerificationMetadataStatus } type args struct { other ImageVerificationMetadata @@ -230,39 +230,39 @@ func TestImageVerificationMetadata_Merge(t *testing.T) { want: &ImageVerificationMetadata{}, }, { fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ other: ImageVerificationMetadata{ - Data: map[string]bool{ - "test": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationFail, }, }, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationFail, }, }, }, { fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ other: ImageVerificationMetadata{ - Data: map[string]bool{ - "test2": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test2": ImageVerificationFail, }, }, }, want: &ImageVerificationMetadata{ - Data: map[string]bool{ - "test": true, - "test2": false, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, + "test2": ImageVerificationFail, }, }, }} @@ -297,7 +297,7 @@ func Test_makeAnnotationKeyForJSONPatch(t *testing.T) { func TestImageVerificationMetadata_Patches(t *testing.T) { type fields struct { - Data map[string]bool + Data map[string]ImageVerificationMetadataStatus } type args struct { hasAnnotations bool @@ -311,8 +311,8 @@ func TestImageVerificationMetadata_Patches(t *testing.T) { wantErr bool }{{ fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ @@ -321,12 +321,12 @@ func TestImageVerificationMetadata_Patches(t *testing.T) { }, want: []string{ `{"op":"add","path":"/metadata/annotations","value":{}}`, - `{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":true}"}`, + `{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":\"pass\"}"}`, }, }, { fields: fields{ - Data: map[string]bool{ - "test": true, + Data: map[string]ImageVerificationMetadataStatus{ + "test": ImageVerificationPass, }, }, args: args{ @@ -334,7 +334,7 @@ func TestImageVerificationMetadata_Patches(t *testing.T) { log: logr.Discard(), }, want: []string{ - `{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":true}"}`, + `{"op":"add","path":"/metadata/annotations/kyverno.io~1verify-images","value":"{\"test\":\"pass\"}"}`, }, }, { args: args{ diff --git a/pkg/engine/api/ruleresponse.go b/pkg/engine/api/ruleresponse.go index 27222ee48359..2c3ccd2ef01b 100644 --- a/pkg/engine/api/ruleresponse.go +++ b/pkg/engine/api/ruleresponse.go @@ -44,14 +44,21 @@ type RuleResponse struct { podSecurityChecks *PodSecurityChecks // exception is the exception applied (if any) exception *kyvernov2beta1.PolicyException + // emitWarning enable passing rule message as warning to api server warning header + emitWarning bool } func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStatus) *RuleResponse { + emitWarn := false + if status == RuleStatusError || status == RuleStatusFail || status == RuleStatusWarn { + emitWarn = true + } return &RuleResponse{ - name: name, - ruleType: ruleType, - message: msg, - status: status, + name: name, + ruleType: ruleType, + message: msg, + status: status, + emitWarning: emitWarn, } } @@ -105,6 +112,11 @@ func (r RuleResponse) WithStats(stats ExecutionStats) RuleResponse { return r } +func (r RuleResponse) WithEmitWarning(emitWarning bool) *RuleResponse { + r.emitWarning = emitWarning + return &r +} + func (r *RuleResponse) Stats() ExecutionStats { return r.stats } @@ -145,6 +157,10 @@ func (r *RuleResponse) Status() RuleStatus { return r.status } +func (r *RuleResponse) EmitWarning() bool { + return r.emitWarning +} + // HasStatus checks if rule status is in a given list func (r *RuleResponse) HasStatus(status ...RuleStatus) bool { for _, s := range status { diff --git a/pkg/engine/handlers/validation/validate_image.go b/pkg/engine/handlers/validation/validate_image.go index ed409b6784cf..66ba799ccafd 100644 --- a/pkg/engine/handlers/validation/validate_image.go +++ b/pkg/engine/handlers/validation/validate_image.go @@ -3,6 +3,7 @@ package validation import ( "context" "fmt" + "strings" "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" @@ -61,6 +62,8 @@ func (h validateImageHandler) Process( } } + skippedImages := make([]string, 0) + passedImages := make([]string, 0) for _, v := range rule.VerifyImages { imageVerify := v.Convert() for _, infoMap := range policyContext.JSONContext().ImageInfo() { @@ -73,31 +76,45 @@ func (h validateImageHandler) Process( } logger.V(4).Info("validating image", "image", image) - if err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil { + if v, err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil { return resource, handlers.WithFail(rule, engineapi.ImageVerify, err.Error()) + } else if v == engineapi.ImageVerificationSkip { + skippedImages = append(skippedImages, image) + } else if v == engineapi.ImageVerificationPass { + passedImages = append(passedImages, image) } } } } + logger.V(4).Info("validated image", "rule", rule.Name) - return resource, handlers.WithPass(rule, engineapi.Validation, "image verified") + if len(passedImages) > 0 || len(passedImages)+len(skippedImages) == 0 { + if len(skippedImages) > 0 { + return resource, handlers.WithPass(rule, engineapi.Validation, strings.Join(append([]string{"image verified, skipped images:"}, skippedImages...), " ")) + } + return resource, handlers.WithPass(rule, engineapi.Validation, "image verified") + } else { + return resource, handlers.WithSkip(rule, engineapi.Validation, strings.Join(append([]string{"image skipped, skipped images:"}, skippedImages...), " ")) + } } -func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) error { +func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) { + var verified engineapi.ImageVerificationMetadataStatus + var err error image := imageInfo.String() if imageVerify.VerifyDigest && imageInfo.Digest == "" { log.V(2).Info("missing digest", "image", imageInfo.String()) - return fmt.Errorf("missing digest for %s", image) + return engineapi.ImageVerificationFail, fmt.Errorf("missing digest for %s", image) } newResource := ctx.NewResource() if imageVerify.Required && newResource.Object != nil { - verified, err := engineutils.IsImageVerified(newResource, image, log) + verified, err = engineutils.IsImageVerified(newResource, image, log) if err != nil { - return err + return engineapi.ImageVerificationFail, err } - if !verified { - return fmt.Errorf("unverified image %s", image) + if verified == engineapi.ImageVerificationFail { + return engineapi.ImageVerificationFail, fmt.Errorf("unverified image %s", image) } } - return nil + return verified, nil } diff --git a/pkg/engine/image_verify_test.go b/pkg/engine/image_verify_test.go index 1d949b39a5c9..377bad2cab01 100644 --- a/pkg/engine/image_verify_test.go +++ b/pkg/engine/image_verify_test.go @@ -972,7 +972,7 @@ func Test_MarkImageVerified(t *testing.T) { verified, err := engineutils.IsImageVerified(resource, image, logr.Discard()) assert.NilError(t, err) - assert.Equal(t, verified, true) + assert.Equal(t, verified, engineapi.ImageVerificationPass) } func testApplyPatches(t *testing.T, patches []jsonpatch.JsonPatchOperation) unstructured.Unstructured { @@ -1360,3 +1360,126 @@ func Test_changePolicyCacheVerificationNotary(t *testing.T) { errorAssertionUtil(t, image, ivm, er) assert.Check(t, secondOperationTime > firstOperationTime/10 && secondOperationTime < firstOperationTime*10, "cache entry not found, so image verification should not be from cache.", firstOperationTime, secondOperationTime) } + +var excludeVerifyImageNotaryPolicy = `{ + "apiVersion": "kyverno.io/v2beta1", + "kind": "ClusterPolicy", + "metadata": { + "name": "check-image-notary" + }, + "spec": { + "validationFailureAction": "Enforce", + "webhookTimeoutSeconds": 30, + "failurePolicy": "Fail", + "rules": [ + { + "name": "verify-signature-notary", + "match": { + "any": [ + { + "resources": { + "kinds": [ + "Pod" + ] + } + } + ] + }, + "verifyImages": [ + { + "type": "Notary", + "imageReferences": [ + "ghcr.io/*" + ], + "skipImageReferences" : [ + "ghcr.io/invalid-user*" + ], + "attestors": [ + { + "count": 1, + "entries": [ + { + "certificates": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIDTTCCAjWgAwIBAgIJAPI+zAzn4s0xMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV\nBAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwG\nTm90YXJ5MQ0wCwYDVQQDDAR0ZXN0MB4XDTIzMDUyMjIxMTUxOFoXDTMzMDUxOTIx\nMTUxOFowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0\ndGxlMQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3\nDQEBAQUAA4IBDwAwggEKAoIBAQDNhTwv+QMk7jEHufFfIFlBjn2NiJaYPgL4eBS+\nb+o37ve5Zn9nzRppV6kGsa161r9s2KkLXmJrojNy6vo9a6g6RtZ3F6xKiWLUmbAL\nhVTCfYw/2n7xNlVMjyyUpE+7e193PF8HfQrfDFxe2JnX5LHtGe+X9vdvo2l41R6m\nIia04DvpMdG4+da2tKPzXIuLUz/FDb6IODO3+qsqQLwEKmmUee+KX+3yw8I6G1y0\nVp0mnHfsfutlHeG8gazCDlzEsuD4QJ9BKeRf2Vrb0ywqNLkGCbcCWF2H5Q80Iq/f\nETVO9z88R7WheVdEjUB8UrY7ZMLdADM14IPhY2Y+tLaSzEVZAgMBAAGjMjAwMAkG\nA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0G\nCSqGSIb3DQEBCwUAA4IBAQBX7x4Ucre8AIUmXZ5PUK/zUBVOrZZzR1YE8w86J4X9\nkYeTtlijf9i2LTZMfGuG0dEVFN4ae3CCpBst+ilhIndnoxTyzP+sNy4RCRQ2Y/k8\nZq235KIh7uucq96PL0qsF9s2RpTKXxyOGdtp9+HO0Ty5txJE2txtLDUIVPK5WNDF\nByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ\n5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0\nuOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz\n-----END CERTIFICATE-----" + } + } + ] + } + ] + } + ] + } + ] + } +}` + +var excludeVerifyImageNotaryResourcePass = `{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "creationTimestamp": null, + "labels": { + "run": "test" + }, + "name": "test", + "namespace": "default" + }, + "spec": { + "containers": [ + { + "image": "ghcr.io/kyverno/test-verify-image:signed", + "name": "test", + "resources": {} + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always" + }, + "status": {} +}` + +var excludeVerifyImageNotaryResourceSkip = `{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "creationTimestamp": null, + "labels": { + "run": "test" + }, + "name": "testskip", + "namespace": "default" + }, + "spec": { + "containers": [ + { + "image": "ghcr.io/invalid-user/invalid-image:v1", + "name": "test", + "resources": {} + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always" + }, + "status": {} +}` + +func Test_SkipImageReferences(t *testing.T) { + policyContextPass := buildContext(t, excludeVerifyImageNotaryPolicy, excludeVerifyImageNotaryResourcePass, "") + + // Passes as image is included and not excluded + erPass, ivm := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContextPass, cfg) + assert.Equal(t, len(erPass.PolicyResponse.Rules), 1) + assert.Equal(t, erPass.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, + fmt.Sprintf("expected: %v, got: %v, failure: %v", + engineapi.RuleStatusPass, erPass.PolicyResponse.Rules[0].Status(), erPass.PolicyResponse.Rules[0].Message())) + assert.Equal(t, ivm.IsEmpty(), false) + + policyContextSkip := buildContext(t, excludeVerifyImageNotaryPolicy, excludeVerifyImageNotaryResourceSkip, "") + + // Skipped as image is excluded + erSkip, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContextSkip, cfg) + assert.Equal(t, len(erSkip.PolicyResponse.Rules), 1) + assert.Equal(t, erSkip.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusSkip, + fmt.Sprintf("expected: %v, got: %v, failure: %v", + engineapi.RuleStatusPass, erSkip.PolicyResponse.Rules[0].Status(), erSkip.PolicyResponse.Rules[0].Message())) +} diff --git a/pkg/engine/internal/imageverifier.go b/pkg/engine/internal/imageverifier.go index 92fe60490d37..7c04a753022a 100644 --- a/pkg/engine/internal/imageverifier.go +++ b/pkg/engine/internal/imageverifier.go @@ -69,7 +69,7 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log if newValue == oldValue { return false } - var newValueObj, oldValueObj map[string]bool + var newValueObj, oldValueObj map[string]engineapi.ImageVerificationMetadataStatus err := json.Unmarshal([]byte(newValue), &newValueObj) if err != nil { log.Error(err, "failed to parse new resource annotation.") @@ -93,7 +93,7 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log return false } -func matchImageReferences(imageReferences []string, image string) bool { +func matchReferences(imageReferences []string, image string) bool { for _, imageRef := range imageReferences { if wildcard.Match(imageRef, image) { return true @@ -102,6 +102,23 @@ func matchImageReferences(imageReferences []string, image string) bool { return false } +func ruleStatusToImageVerificationStatus(ruleStatus engineapi.RuleStatus) engineapi.ImageVerificationMetadataStatus { + var imageVerificationResult engineapi.ImageVerificationMetadataStatus + switch ruleStatus { + case engineapi.RuleStatusPass: + imageVerificationResult = engineapi.ImageVerificationPass + case engineapi.RuleStatusSkip: + imageVerificationResult = engineapi.ImageVerificationSkip + case engineapi.RuleStatusWarn: + imageVerificationResult = engineapi.ImageVerificationSkip + case engineapi.RuleStatusFail: + imageVerificationResult = engineapi.ImageVerificationFail + default: + imageVerificationResult = engineapi.ImageVerificationFail + } + return imageVerificationResult +} + func isImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (bool, error) { if resource.Object == nil { return false, fmt.Errorf("nil resource") @@ -234,14 +251,14 @@ func (iv *ImageVerifier) Verify( changed, err := iv.policyContext.JSONContext().HasChanged(pointer) if err == nil && !changed { iv.logger.V(4).Info("no change in image, skipping check", "image", image) - iv.ivm.Add(image, true) + iv.ivm.Add(image, engineapi.ImageVerificationPass) continue } verified, err := isImageVerified(iv.policyContext.NewResource(), image, iv.logger) if err == nil && verified { iv.logger.Info("image was previously verified, skipping check", "image", image) - iv.ivm.Add(image, true) + iv.ivm.Add(image, engineapi.ImageVerificationPass) continue } start := time.Now() @@ -295,7 +312,7 @@ func (iv *ImageVerifier) Verify( if ruleResp != nil { if len(imageVerify.Attestors) > 0 || len(imageVerify.Attestations) > 0 { - iv.ivm.Add(image, ruleResp.Status() == engineapi.RuleStatusPass) + iv.ivm.Add(image, ruleStatusToImageVerificationStatus(ruleResp.Status())) } responses = append(responses, ruleResp) } @@ -324,8 +341,14 @@ func (iv *ImageVerifier) verifyImage( return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), "" } if len(imageVerify.Attestors) > 0 { - if !matchImageReferences(imageVerify.ImageReferences, image) { - return nil, "" + if !matchReferences(imageVerify.ImageReferences, image) { + return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)), "" + } + + if matchReferences(imageVerify.SkipImageReferences, image) { + iv.logger.Info("skipping image reference", "image", image, "policy", iv.policyContext.Policy().GetName(), "ruleName", iv.rule.Name) + iv.ivm.Add(image, engineapi.ImageVerificationSkip) + return engineapi.RuleSkip(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("skipping image reference image %s, policy %s ruleName %s", image, iv.policyContext.Policy().GetName(), iv.rule.Name)).WithEmitWarning(true), "" } ruleResp, cosignResp := iv.verifyAttestors(ctx, imageVerify.Attestors, imageVerify, imageInfo, "") if ruleResp.Status() != engineapi.RuleStatusPass { diff --git a/pkg/engine/utils/image.go b/pkg/engine/utils/image.go index 00be6afb054a..ff3300c352fd 100644 --- a/pkg/engine/utils/image.go +++ b/pkg/engine/utils/image.go @@ -21,7 +21,6 @@ func ImageMatches(image string, imagePatterns []string) bool { return true } } - return false } @@ -66,19 +65,19 @@ func ExtractMatchingImages( return matchingImages, imageRefs, nil } -func IsImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (bool, error) { +func IsImageVerified(resource unstructured.Unstructured, image string, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) { if resource.Object == nil { - return false, fmt.Errorf("nil resource") + return engineapi.ImageVerificationFail, fmt.Errorf("nil resource") } if annotations := resource.GetAnnotations(); len(annotations) == 0 { - return false, nil + return engineapi.ImageVerificationFail, nil } else if data, ok := annotations[kyverno.AnnotationImageVerify]; !ok { log.V(2).Info("missing image metadata in annotation", "key", kyverno.AnnotationImageVerify) - return false, fmt.Errorf("image is not verified") + return engineapi.ImageVerificationFail, fmt.Errorf("image is not verified") } else if ivm, err := engineapi.ParseImageMetadata(data); err != nil { log.Error(err, "failed to parse image verification metadata", "data", data) - return false, fmt.Errorf("failed to parse image metadata: %w", err) + return engineapi.ImageVerificationFail, fmt.Errorf("failed to parse image metadata: %w", err) } else { - return ivm.IsVerified(image), nil + return ivm.ImageVerificationStatus(image), nil } } diff --git a/pkg/webhooks/utils/warning.go b/pkg/webhooks/utils/warning.go index 6119352097cd..cf810b49498f 100644 --- a/pkg/webhooks/utils/warning.go +++ b/pkg/webhooks/utils/warning.go @@ -10,7 +10,7 @@ func GetWarningMessages(engineResponses []engineapi.EngineResponse) []string { var warnings []string for _, er := range engineResponses { for _, rule := range er.PolicyResponse.Rules { - if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip { + if rule.EmitWarning() { msg := fmt.Sprintf("policy %s.%s: %s", er.Policy().GetName(), rule.Name(), rule.Message()) warnings = append(warnings, msg) } diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-1/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-1/chainsaw-step-02-assert-1.yaml index 669073222c51..ffa6c8bf7c61 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-1/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-1/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-2/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-2/chainsaw-step-02-assert-1.yaml index 669073222c51..ffa6c8bf7c61 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-2/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-2/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-4/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-4/chainsaw-step-02-assert-1.yaml index 669073222c51..ffa6c8bf7c61 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-4/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-4/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-counts-1/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-counts-1/chainsaw-step-02-assert-1.yaml index 669073222c51..ffa6c8bf7c61 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-counts-1/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-attestations-multiple-subjects-counts-1/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-mutatedigest-verifydigest-required/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-mutatedigest-verifydigest-required/chainsaw-step-02-assert-1.yaml index 669073222c51..ffa6c8bf7c61 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-mutatedigest-verifydigest-required/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-mutatedigest-verifydigest-required/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-norequired/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-norequired/chainsaw-step-02-assert-1.yaml index 7d1c2da8fb68..a8984c9062bc 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-norequired/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-norequired/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-required/chainsaw-step-02-assert-1.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-required/chainsaw-step-02-assert-1.yaml index 7d1c2da8fb68..a8984c9062bc 100755 --- a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-required/chainsaw-step-02-assert-1.yaml +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/keyless-nomutatedigest-noverifydigest-required/chainsaw-step-02-assert-1.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":true}' + kyverno.io/verify-images: '{"ghcr.io/chipzoller/zulu:latest":"pass"}' name: zulu namespace: default spec: diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/README.md new file mode 100644 index 000000000000..80e41e29baa5 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/README.md @@ -0,0 +1,12 @@ +## Description + +This test tests the exclude image references attribute. + +## Expected Behavior + +This test creates a cluster policy with exclude image references attribute. +The pod that is not excluded will be verified and the pod that is excluded will be skipped + +## Reference Issue(s) + +8592 diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/bad.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/bad.yaml new file mode 100644 index 000000000000..eb3bed7c9f4b --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/bad.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + creationTimestamp: null + labels: + run: test-bad + name: test-bad + namespace: exclude-refs +spec: + containers: + - image: ghcr.io/chipzoller/zulu:v0.0.14@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db + name: test + resources: {} + - image: ghcr.io/kyverno/kyverno:latest + name: test + resources: {} + dnsPolicy: ClusterFirst + restartPolicy: Always +status: {} \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/chainsaw-test.yaml new file mode 100644 index 000000000000..51526791717d --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/chainsaw-test.yaml @@ -0,0 +1,34 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: skip-image-reference +spec: + timeouts: + delete: 2m + steps: + - name: step-01 + try: + - apply: + file: policy.yaml + - assert: + file: policy-ready.yaml + - name: step-02 + try: + - apply: + file: pod.yaml + - assert: + file: pod-assert.yaml + - name: step-03 + try: + - apply: + file: skipped.yaml + - assert: + file: skipped-assert.yaml + - name: step-04 + try: + - apply: + expect: + - check: + ($error != null): true + file: bad.yaml \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod-assert.yaml new file mode 100644 index 000000000000..82022e66bbb9 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod-assert.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test + namespace: exclude-refs \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod.yaml new file mode 100644 index 000000000000..27fe6ff84149 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + creationTimestamp: null + labels: + run: test + name: test + namespace: exclude-refs +spec: + containers: + - image: ghcr.io/kyverno/test-verify-image:signed + name: test + resources: {} + dnsPolicy: ClusterFirst + restartPolicy: Always +status: {} \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy-ready.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy-ready.yaml new file mode 100644 index 000000000000..56444a2e18a2 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy-ready.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + name: verify-exclude-refs +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy.yaml new file mode 100755 index 000000000000..339878346c29 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/policy.yaml @@ -0,0 +1,66 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: exclude-refs +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: keys + namespace: exclude-refs +data: + certificate: |- + -----BEGIN CERTIFICATE----- + MIIDTTCCAjWgAwIBAgIJAPI+zAzn4s0xMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV + BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwG + Tm90YXJ5MQ0wCwYDVQQDDAR0ZXN0MB4XDTIzMDUyMjIxMTUxOFoXDTMzMDUxOTIx + MTUxOFowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0 + dGxlMQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3 + DQEBAQUAA4IBDwAwggEKAoIBAQDNhTwv+QMk7jEHufFfIFlBjn2NiJaYPgL4eBS+ + b+o37ve5Zn9nzRppV6kGsa161r9s2KkLXmJrojNy6vo9a6g6RtZ3F6xKiWLUmbAL + hVTCfYw/2n7xNlVMjyyUpE+7e193PF8HfQrfDFxe2JnX5LHtGe+X9vdvo2l41R6m + Iia04DvpMdG4+da2tKPzXIuLUz/FDb6IODO3+qsqQLwEKmmUee+KX+3yw8I6G1y0 + Vp0mnHfsfutlHeG8gazCDlzEsuD4QJ9BKeRf2Vrb0ywqNLkGCbcCWF2H5Q80Iq/f + ETVO9z88R7WheVdEjUB8UrY7ZMLdADM14IPhY2Y+tLaSzEVZAgMBAAGjMjAwMAkG + A1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0G + CSqGSIb3DQEBCwUAA4IBAQBX7x4Ucre8AIUmXZ5PUK/zUBVOrZZzR1YE8w86J4X9 + kYeTtlijf9i2LTZMfGuG0dEVFN4ae3CCpBst+ilhIndnoxTyzP+sNy4RCRQ2Y/k8 + Zq235KIh7uucq96PL0qsF9s2RpTKXxyOGdtp9+HO0Ty5txJE2txtLDUIVPK5WNDF + ByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ + 5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0 + uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz + -----END CERTIFICATE----- +--- +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + name: verify-exclude-refs +spec: + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 + failurePolicy: Fail + rules: + - name: verify-exclude-refs + context: + - name: keys + configMap: + name: keys + namespace: exclude-refs + match: + any: + - resources: + kinds: + - Pod + verifyImages: + - type: Notary + imageReferences: + - "ghcr.io/*" + skipImageReferences: + - "ghcr.io/chipzoller*" + attestors: + - count: 1 + entries: + - certificates: + cert: "{{ keys.data.certificate }}" + name: keys + namespace: test-verify-images diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped-assert.yaml new file mode 100644 index 000000000000..6fc45dcc6a6e --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped-assert.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-skipped + namespace: exclude-refs \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped.yaml new file mode 100644 index 000000000000..7264419a7fcb --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/skip-image-reference/skipped.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + creationTimestamp: null + labels: + run: test-skipped + name: test-skipped + namespace: exclude-refs +spec: + containers: + - image: ghcr.io/chipzoller/zulu:v0.0.14@sha256:476b21f1a75dc90fac3579ee757f4607bb5546f476195cf645c54badf558c0db + name: test + resources: {} + dnsPolicy: ClusterFirst + restartPolicy: Always +status: {} \ No newline at end of file