diff --git a/api/kyverno/v1/image_verification_types.go b/api/kyverno/v1/image_verification_types.go index 6b0306f41316..e4879630f7ee 100644 --- a/api/kyverno/v1/image_verification_types.go +++ b/api/kyverno/v1/image_verification_types.go @@ -117,6 +117,10 @@ type ImageVerification struct { // +kubebuilder:validation:Optional VerifyDigest bool `json:"verifyDigest" yaml:"verifyDigest"` + // Validation checks conditions across multiple image + // verification attestations or context entries + Validation ValidateImageVerification `json:"validate,omitempty" yaml:"validate,omitempty"` + // Required validates that images are verified i.e. have matched passed a signature or attestation check. // +kubebuilder:default=true // +kubebuilder:validation:Optional @@ -320,6 +324,9 @@ type CTLog struct { // See https://github.com/in-toto/attestation. Kyverno fetches signed attestations from the // OCI registry and decodes them into a list of Statements. type Attestation struct { + // Name is the variable name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + // Deprecated in favour of 'Type', to be removed soon // +kubebuilder:validation:Optional PredicateType string `json:"predicateType" yaml:"predicateType"` @@ -354,6 +361,18 @@ type ImageRegistryCredentials struct { Secrets []string `json:"secrets,omitempty" yaml:"secrets,omitempty"` } +// ValidateImageVerification checks conditions across multiple image +// verification attestations or context entries +type ValidateImageVerification struct { + // Message specifies a custom message to be displayed on failure. + // +optional + Message string `json:"message,omitempty" yaml:"message,omitempty"` + + // Deny defines conditions used to pass or fail a validation rule. + // +optional + Deny *Deny `json:"deny,omitempty" yaml:"deny,omitempty"` +} + func (iv *ImageVerification) GetType() ImageVerificationType { if iv.Type != "" { return iv.Type diff --git a/api/kyverno/v1/rule_types.go b/api/kyverno/v1/rule_types.go index 871bda17b8d7..bdd78a41e82c 100644 --- a/api/kyverno/v1/rule_types.go +++ b/api/kyverno/v1/rule_types.go @@ -139,6 +139,19 @@ func (r *Rule) HasVerifyImages() bool { return false } +// HasValidateImageVerification checks for verifyImages rule has Validation +func (r *Rule) HasValidateImageVerification() bool { + if !r.HasVerifyImages() { + return false + } + for _, verifyImage := range r.VerifyImages { + if !datautils.DeepEqual(verifyImage.Validation, ValidateImageVerification{}) { + return true + } + } + return false +} + // HasVerifyImageChecks checks whether the verifyImages rule has validation checks func (r *Rule) HasVerifyImageChecks() bool { for _, verifyImage := range r.VerifyImages { diff --git a/api/kyverno/v1/zz_generated.deepcopy.go b/api/kyverno/v1/zz_generated.deepcopy.go index 4dfd1fda1a89..9b50a27ad3e6 100755 --- a/api/kyverno/v1/zz_generated.deepcopy.go +++ b/api/kyverno/v1/zz_generated.deepcopy.go @@ -894,6 +894,7 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { (*out)[key] = val } } + in.Validation.DeepCopyInto(&out.Validation) if in.ImageRegistryCredentials != nil { in, out := &in.ImageRegistryCredentials, &out.ImageRegistryCredentials *out = new(ImageRegistryCredentials) @@ -1640,6 +1641,27 @@ func (in *UserInfo) DeepCopy() *UserInfo { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ValidateImageVerification) DeepCopyInto(out *ValidateImageVerification) { + *out = *in + if in.Deny != nil { + in, out := &in.Deny, &out.Deny + *out = new(Deny) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValidateImageVerification. +func (in *ValidateImageVerification) DeepCopy() *ValidateImageVerification { + if in == nil { + return nil + } + out := new(ValidateImageVerification) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ValidatingAdmissionPolicyStatus) DeepCopyInto(out *ValidatingAdmissionPolicyStatus) { *out = *in diff --git a/api/kyverno/v2beta1/image_verification_types.go b/api/kyverno/v2beta1/image_verification_types.go index a92918aaaec5..fe18f65777c2 100644 --- a/api/kyverno/v2beta1/image_verification_types.go +++ b/api/kyverno/v2beta1/image_verification_types.go @@ -58,6 +58,10 @@ type ImageVerification struct { // +kubebuilder:validation:Optional VerifyDigest bool `json:"verifyDigest" yaml:"verifyDigest"` + // Validation checks conditions across multiple image + // verification attestations or context entries + Validation kyvernov1.ValidateImageVerification `json:"validate,omitempty" yaml:"validate,omitempty"` + // Required validates that images are verified i.e. have matched passed a signature or attestation check. // +kubebuilder:default=true // +kubebuilder:validation:Optional diff --git a/api/kyverno/v2beta1/zz_generated.deepcopy.go b/api/kyverno/v2beta1/zz_generated.deepcopy.go index 6fcc17e5a9b7..7a282816ffbd 100755 --- a/api/kyverno/v2beta1/zz_generated.deepcopy.go +++ b/api/kyverno/v2beta1/zz_generated.deepcopy.go @@ -397,6 +397,7 @@ func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + in.Validation.DeepCopyInto(&out.Validation) if in.ImageRegistryCredentials != nil { in, out := &in.ImageRegistryCredentials, &out.ImageRegistryCredentials *out = new(v1.ImageRegistryCredentials) diff --git a/charts/kyverno/README.md b/charts/kyverno/README.md index adf86c00d0e9..a53591fa90f9 100644 --- a/charts/kyverno/README.md +++ b/charts/kyverno/README.md @@ -740,6 +740,116 @@ The chart values are organised per component. | Key | Type | Default | Description | |-----|------|---------|-------------| +| cleanupJobs.admissionReports.enabled | bool | `true` | Enable cleanup cronjob | +| cleanupJobs.admissionReports.backoffLimit | int | `3` | Maximum number of retries before considering a Job as failed. Defaults to 3. | +| cleanupJobs.admissionReports.ttlSecondsAfterFinished | string | `""` | Time until the pod from the cronjob is deleted | +| cleanupJobs.admissionReports.image.registry | string | `nil` | Image registry | +| cleanupJobs.admissionReports.image.repository | string | `"bitnami/kubectl"` | Image repository | +| cleanupJobs.admissionReports.image.tag | string | `"1.28.5"` | Image tag Defaults to `latest` if omitted | +| cleanupJobs.admissionReports.image.pullPolicy | string | `nil` | Image pull policy Defaults to image.pullPolicy if omitted | +| cleanupJobs.admissionReports.imagePullSecrets | list | `[]` | Image pull secrets | +| cleanupJobs.admissionReports.schedule | string | `"*/10 * * * *"` | Cronjob schedule | +| cleanupJobs.admissionReports.threshold | int | `10000` | Reports threshold, if number of reports are above this value the cronjob will start deleting them | +| cleanupJobs.admissionReports.history | object | `{"failure":1,"success":1}` | Cronjob history | +| cleanupJobs.admissionReports.podSecurityContext | object | `{}` | Security context for the pod | +| cleanupJobs.admissionReports.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the containers | +| cleanupJobs.admissionReports.priorityClassName | string | `""` | Pod PriorityClassName | +| cleanupJobs.admissionReports.resources | object | `{}` | Job resources | +| cleanupJobs.admissionReports.tolerations | list | `[]` | List of node taints to tolerate | +| cleanupJobs.admissionReports.nodeSelector | object | `{}` | Node labels for pod assignment | +| cleanupJobs.admissionReports.podAnnotations | object | `{}` | Pod Annotations | +| cleanupJobs.admissionReports.podLabels | object | `{}` | Pod labels | +| cleanupJobs.admissionReports.podAntiAffinity | object | `{}` | Pod anti affinity constraints. | +| cleanupJobs.admissionReports.podAffinity | object | `{}` | Pod affinity constraints. | +| cleanupJobs.admissionReports.nodeAffinity | object | `{}` | Node affinity constraints. | +| cleanupJobs.clusterAdmissionReports.enabled | bool | `true` | Enable cleanup cronjob | +| cleanupJobs.clusterAdmissionReports.backoffLimit | int | `3` | Maximum number of retries before considering a Job as failed. Defaults to 3. | +| cleanupJobs.clusterAdmissionReports.ttlSecondsAfterFinished | string | `""` | Time until the pod from the cronjob is deleted | +| cleanupJobs.clusterAdmissionReports.image.registry | string | `nil` | Image registry | +| cleanupJobs.clusterAdmissionReports.image.repository | string | `"bitnami/kubectl"` | Image repository | +| cleanupJobs.clusterAdmissionReports.image.tag | string | `"1.28.5"` | Image tag Defaults to `latest` if omitted | +| cleanupJobs.clusterAdmissionReports.image.pullPolicy | string | `nil` | Image pull policy Defaults to image.pullPolicy if omitted | +| cleanupJobs.clusterAdmissionReports.imagePullSecrets | list | `[]` | Image pull secrets | +| cleanupJobs.clusterAdmissionReports.schedule | string | `"*/10 * * * *"` | Cronjob schedule | +| cleanupJobs.clusterAdmissionReports.threshold | int | `10000` | Reports threshold, if number of reports are above this value the cronjob will start deleting them | +| cleanupJobs.clusterAdmissionReports.history | object | `{"failure":1,"success":1}` | Cronjob history | +| cleanupJobs.clusterAdmissionReports.podSecurityContext | object | `{}` | Security context for the pod | +| cleanupJobs.clusterAdmissionReports.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the containers | +| cleanupJobs.clusterAdmissionReports.priorityClassName | string | `""` | Pod PriorityClassName | +| cleanupJobs.clusterAdmissionReports.resources | object | `{}` | Job resources | +| cleanupJobs.clusterAdmissionReports.tolerations | list | `[]` | List of node taints to tolerate | +| cleanupJobs.clusterAdmissionReports.nodeSelector | object | `{}` | Node labels for pod assignment | +| cleanupJobs.clusterAdmissionReports.podAnnotations | object | `{}` | Pod Annotations | +| cleanupJobs.clusterAdmissionReports.podLabels | object | `{}` | Pod Labels | +| cleanupJobs.clusterAdmissionReports.podAntiAffinity | object | `{}` | Pod anti affinity constraints. | +| cleanupJobs.clusterAdmissionReports.podAffinity | object | `{}` | Pod affinity constraints. | +| cleanupJobs.clusterAdmissionReports.nodeAffinity | object | `{}` | Node affinity constraints. | +| cleanupJobs.updateRequests.enabled | bool | `true` | Enable cleanup cronjob | +| cleanupJobs.updateRequests.backoffLimit | int | `3` | Maximum number of retries before considering a Job as failed. Defaults to 3. | +| cleanupJobs.updateRequests.ttlSecondsAfterFinished | string | `""` | Time until the pod from the cronjob is deleted | +| cleanupJobs.updateRequests.image.registry | string | `nil` | Image registry | +| cleanupJobs.updateRequests.image.repository | string | `"bitnami/kubectl"` | Image repository | +| cleanupJobs.updateRequests.image.tag | string | `"1.28.5"` | Image tag Defaults to `latest` if omitted | +| cleanupJobs.updateRequests.image.pullPolicy | string | `nil` | Image pull policy Defaults to image.pullPolicy if omitted | +| cleanupJobs.updateRequests.imagePullSecrets | list | `[]` | Image pull secrets | +| cleanupJobs.updateRequests.schedule | string | `"*/10 * * * *"` | Cronjob schedule | +| cleanupJobs.updateRequests.threshold | int | `10000` | Reports threshold, if number of updateRequests are above this value the cronjob will start deleting them | +| cleanupJobs.updateRequests.history | object | `{"failure":1,"success":1}` | Cronjob history | +| cleanupJobs.updateRequests.podSecurityContext | object | `{}` | Security context for the pod | +| cleanupJobs.updateRequests.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the containers | +| cleanupJobs.updateRequests.priorityClassName | string | `""` | Pod PriorityClassName | +| cleanupJobs.updateRequests.resources | object | `{}` | Job resources | +| cleanupJobs.updateRequests.tolerations | list | `[]` | List of node taints to tolerate | +| cleanupJobs.updateRequests.nodeSelector | object | `{}` | Node labels for pod assignment | +| cleanupJobs.updateRequests.podAnnotations | object | `{}` | Pod Annotations | +| cleanupJobs.updateRequests.podLabels | object | `{}` | Pod labels | +| cleanupJobs.updateRequests.podAntiAffinity | object | `{}` | Pod anti affinity constraints. | +| cleanupJobs.updateRequests.podAffinity | object | `{}` | Pod affinity constraints. | +| cleanupJobs.updateRequests.nodeAffinity | object | `{}` | Node affinity constraints. | +| cleanupJobs.ephemeralReports.enabled | bool | `true` | Enable cleanup cronjob | +| cleanupJobs.ephemeralReports.backoffLimit | int | `3` | Maximum number of retries before considering a Job as failed. Defaults to 3. | +| cleanupJobs.ephemeralReports.ttlSecondsAfterFinished | string | `""` | Time until the pod from the cronjob is deleted | +| cleanupJobs.ephemeralReports.image.registry | string | `nil` | Image registry | +| cleanupJobs.ephemeralReports.image.repository | string | `"bitnami/kubectl"` | Image repository | +| cleanupJobs.ephemeralReports.image.tag | string | `"1.28.5"` | Image tag Defaults to `latest` if omitted | +| cleanupJobs.ephemeralReports.image.pullPolicy | string | `nil` | Image pull policy Defaults to image.pullPolicy if omitted | +| cleanupJobs.ephemeralReports.imagePullSecrets | list | `[]` | Image pull secrets | +| cleanupJobs.ephemeralReports.schedule | string | `"*/10 * * * *"` | Cronjob schedule | +| cleanupJobs.ephemeralReports.threshold | int | `10000` | Reports threshold, if number of updateRequests are above this value the cronjob will start deleting them | +| cleanupJobs.ephemeralReports.history | object | `{"failure":1,"success":1}` | Cronjob history | +| cleanupJobs.ephemeralReports.podSecurityContext | object | `{}` | Security context for the pod | +| cleanupJobs.ephemeralReports.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the containers | +| cleanupJobs.ephemeralReports.priorityClassName | string | `""` | Pod PriorityClassName | +| cleanupJobs.ephemeralReports.resources | object | `{}` | Job resources | +| cleanupJobs.ephemeralReports.tolerations | list | `[]` | List of node taints to tolerate | +| cleanupJobs.ephemeralReports.nodeSelector | object | `{}` | Node labels for pod assignment | +| cleanupJobs.ephemeralReports.podAnnotations | object | `{}` | Pod Annotations | +| cleanupJobs.ephemeralReports.podLabels | object | `{}` | Pod labels | +| cleanupJobs.ephemeralReports.podAntiAffinity | object | `{}` | Pod anti affinity constraints. | +| cleanupJobs.ephemeralReports.podAffinity | object | `{}` | Pod affinity constraints. | +| cleanupJobs.ephemeralReports.nodeAffinity | object | `{}` | Node affinity constraints. | +| cleanupJobs.clusterEphemeralReports.enabled | bool | `true` | Enable cleanup cronjob | +| cleanupJobs.clusterEphemeralReports.backoffLimit | int | `3` | Maximum number of retries before considering a Job as failed. Defaults to 3. | +| cleanupJobs.clusterEphemeralReports.ttlSecondsAfterFinished | string | `""` | Time until the pod from the cronjob is deleted | +| cleanupJobs.clusterEphemeralReports.image.registry | string | `nil` | Image registry | +| cleanupJobs.clusterEphemeralReports.image.repository | string | `"bitnami/kubectl"` | Image repository | +| cleanupJobs.clusterEphemeralReports.image.tag | string | `"1.28.5"` | Image tag Defaults to `latest` if omitted | +| cleanupJobs.clusterEphemeralReports.image.pullPolicy | string | `nil` | Image pull policy Defaults to image.pullPolicy if omitted | +| cleanupJobs.clusterEphemeralReports.imagePullSecrets | list | `[]` | Image pull secrets | +| cleanupJobs.clusterEphemeralReports.schedule | string | `"*/10 * * * *"` | Cronjob schedule | +| cleanupJobs.clusterEphemeralReports.threshold | int | `10000` | Reports threshold, if number of reports are above this value the cronjob will start deleting them | +| cleanupJobs.clusterEphemeralReports.history | object | `{"failure":1,"success":1}` | Cronjob history | +| cleanupJobs.clusterEphemeralReports.podSecurityContext | object | `{}` | Security context for the pod | +| cleanupJobs.clusterEphemeralReports.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"privileged":false,"readOnlyRootFilesystem":true,"runAsNonRoot":true,"seccompProfile":{"type":"RuntimeDefault"}}` | Security context for the containers | +| cleanupJobs.clusterEphemeralReports.priorityClassName | string | `""` | Pod PriorityClassName | +| cleanupJobs.clusterEphemeralReports.resources | object | `{}` | Job resources | +| cleanupJobs.clusterEphemeralReports.tolerations | list | `[]` | List of node taints to tolerate | +| cleanupJobs.clusterEphemeralReports.nodeSelector | object | `{}` | Node labels for pod assignment | +| cleanupJobs.clusterEphemeralReports.podAnnotations | object | `{}` | Pod Annotations | +| cleanupJobs.clusterEphemeralReports.podLabels | object | `{}` | Pod Labels | +| cleanupJobs.clusterEphemeralReports.podAntiAffinity | object | `{}` | Pod anti affinity constraints. | +| cleanupJobs.clusterEphemeralReports.podAffinity | object | `{}` | Pod affinity constraints. | +| cleanupJobs.clusterEphemeralReports.nodeAffinity | object | `{}` | Node affinity constraints. | ### Other diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml index 0f8bf0e2c79c..7cc15d5e37e6 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_clusterpolicies.yaml @@ -4479,6 +4479,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4863,6 +4866,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9447,6 +9472,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9836,6 +9864,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14150,6 +14200,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14514,6 +14567,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19098,6 +19173,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19487,6 +19565,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml index 74130e58a6dc..565470431af9 100644 --- a/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml +++ b/charts/kyverno/charts/crds/templates/kyverno.io/kyverno.io_policies.yaml @@ -4480,6 +4480,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4864,6 +4867,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9449,6 +9474,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9838,6 +9866,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14153,6 +14203,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14517,6 +14570,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19101,6 +19176,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19490,6 +19568,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/charts/kyverno/values.yaml b/charts/kyverno/values.yaml index 3f299d11481a..a21b53fdd386 100644 --- a/charts/kyverno/values.yaml +++ b/charts/kyverno/values.yaml @@ -696,6 +696,409 @@ features: # -- (string) Tuf mirror mirror: ~ +# Cleanup cronjobs to prevent internal resources from stacking up in the cluster +cleanupJobs: + + admissionReports: + + # -- Enable cleanup cronjob + enabled: true + + # -- Maximum number of retries before considering a Job as failed. Defaults to 3. + backoffLimit: 3 + + # -- Time until the pod from the cronjob is deleted + ttlSecondsAfterFinished: "" + + image: + # -- (string) Image registry + registry: ~ + # -- Image repository + repository: bitnami/kubectl + # -- Image tag + # Defaults to `latest` if omitted + tag: '1.28.5' + # -- (string) Image pull policy + # Defaults to image.pullPolicy if omitted + pullPolicy: ~ + + # -- Image pull secrets + imagePullSecrets: [] + # - name: secretName + + # -- Cronjob schedule + schedule: '*/10 * * * *' + + # -- Reports threshold, if number of reports are above this value the cronjob will start deleting them + threshold: 10000 + + # -- Cronjob history + history: + success: 1 + failure: 1 + + # -- Security context for the pod + podSecurityContext: {} + + # -- Security context for the containers + securityContext: + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # -- Pod PriorityClassName + priorityClassName: "" + + # -- Job resources + resources: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- Pod Annotations + podAnnotations: {} + + # -- Pod labels + podLabels: {} + + # -- Pod anti affinity constraints. + podAntiAffinity: {} + + # -- Pod affinity constraints. + podAffinity: {} + + # -- Node affinity constraints. + nodeAffinity: {} + + clusterAdmissionReports: + + # -- Enable cleanup cronjob + enabled: true + + # -- Maximum number of retries before considering a Job as failed. Defaults to 3. + backoffLimit: 3 + + # -- Time until the pod from the cronjob is deleted + ttlSecondsAfterFinished: "" + + image: + # -- (string) Image registry + registry: ~ + # -- Image repository + repository: bitnami/kubectl + # -- Image tag + # Defaults to `latest` if omitted + tag: '1.28.5' + # -- (string) Image pull policy + # Defaults to image.pullPolicy if omitted + pullPolicy: ~ + + # -- Image pull secrets + imagePullSecrets: [] + # - name: secretName + + # -- Cronjob schedule + schedule: '*/10 * * * *' + + # -- Reports threshold, if number of reports are above this value the cronjob will start deleting them + threshold: 10000 + + # -- Cronjob history + history: + success: 1 + failure: 1 + + # -- Security context for the pod + podSecurityContext: {} + + # -- Security context for the containers + securityContext: + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # -- Pod PriorityClassName + priorityClassName: "" + + # -- Job resources + resources: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- Pod Annotations + podAnnotations: {} + + # -- Pod Labels + podLabels: {} + + # -- Pod anti affinity constraints. + podAntiAffinity: {} + + # -- Pod affinity constraints. + podAffinity: {} + + # -- Node affinity constraints. + nodeAffinity: {} + + updateRequests: + + # -- Enable cleanup cronjob + enabled: true + + # -- Maximum number of retries before considering a Job as failed. Defaults to 3. + backoffLimit: 3 + + # -- Time until the pod from the cronjob is deleted + ttlSecondsAfterFinished: "" + + image: + # -- (string) Image registry + registry: ~ + # -- Image repository + repository: bitnami/kubectl + # -- Image tag + # Defaults to `latest` if omitted + tag: '1.28.5' + # -- (string) Image pull policy + # Defaults to image.pullPolicy if omitted + pullPolicy: ~ + + # -- Image pull secrets + imagePullSecrets: [] + # - name: secretName + + # -- Cronjob schedule + schedule: '*/10 * * * *' + + # -- Reports threshold, if number of updateRequests are above this value the cronjob will start deleting them + threshold: 10000 + + # -- Cronjob history + history: + success: 1 + failure: 1 + + # -- Security context for the pod + podSecurityContext: {} + + # -- Security context for the containers + securityContext: + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # -- Pod PriorityClassName + priorityClassName: "" + + # -- Job resources + resources: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- Pod Annotations + podAnnotations: {} + + # -- Pod labels + podLabels: {} + + # -- Pod anti affinity constraints. + podAntiAffinity: {} + + # -- Pod affinity constraints. + podAffinity: {} + + # -- Node affinity constraints. + nodeAffinity: {} + + ephemeralReports: + + # -- Enable cleanup cronjob + enabled: true + + # -- Maximum number of retries before considering a Job as failed. Defaults to 3. + backoffLimit: 3 + + # -- Time until the pod from the cronjob is deleted + ttlSecondsAfterFinished: "" + + image: + # -- (string) Image registry + registry: ~ + # -- Image repository + repository: bitnami/kubectl + # -- Image tag + # Defaults to `latest` if omitted + tag: '1.28.5' + # -- (string) Image pull policy + # Defaults to image.pullPolicy if omitted + pullPolicy: ~ + + # -- Image pull secrets + imagePullSecrets: [] + # - name: secretName + + # -- Cronjob schedule + schedule: '*/10 * * * *' + + # -- Reports threshold, if number of updateRequests are above this value the cronjob will start deleting them + threshold: 10000 + + # -- Cronjob history + history: + success: 1 + failure: 1 + + # -- Security context for the pod + podSecurityContext: {} + + # -- Security context for the containers + securityContext: + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # -- Pod PriorityClassName + priorityClassName: "" + + # -- Job resources + resources: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- Pod Annotations + podAnnotations: {} + + # -- Pod labels + podLabels: {} + + # -- Pod anti affinity constraints. + podAntiAffinity: {} + + # -- Pod affinity constraints. + podAffinity: {} + + # -- Node affinity constraints. + nodeAffinity: {} + + clusterEphemeralReports: + + # -- Enable cleanup cronjob + enabled: true + + # -- Maximum number of retries before considering a Job as failed. Defaults to 3. + backoffLimit: 3 + + # -- Time until the pod from the cronjob is deleted + ttlSecondsAfterFinished: "" + + image: + # -- (string) Image registry + registry: ~ + # -- Image repository + repository: bitnami/kubectl + # -- Image tag + # Defaults to `latest` if omitted + tag: '1.28.5' + # -- (string) Image pull policy + # Defaults to image.pullPolicy if omitted + pullPolicy: ~ + + # -- Image pull secrets + imagePullSecrets: [] + # - name: secretName + + # -- Cronjob schedule + schedule: '*/10 * * * *' + + # -- Reports threshold, if number of reports are above this value the cronjob will start deleting them + threshold: 10000 + + # -- Cronjob history + history: + success: 1 + failure: 1 + + # -- Security context for the pod + podSecurityContext: {} + + # -- Security context for the containers + securityContext: + runAsNonRoot: true + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + + # -- Pod PriorityClassName + priorityClassName: "" + + # -- Job resources + resources: {} + + # -- List of node taints to tolerate + tolerations: [] + + # -- Node labels for pod assignment + nodeSelector: {} + + # -- Pod Annotations + podAnnotations: {} + + # -- Pod Labels + podLabels: {} + + # -- Pod anti affinity constraints. + podAntiAffinity: {} + + # -- Pod affinity constraints. + podAffinity: {} + + # -- Node affinity constraints. + nodeAffinity: {} + # Admission controller configuration admissionController: 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 a8af77755907..9a36663cf688 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_clusterpolicies.yaml @@ -4473,6 +4473,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4857,6 +4860,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9441,6 +9466,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9830,6 +9858,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14144,6 +14194,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14508,6 +14561,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19092,6 +19167,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19481,6 +19559,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have 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 e2fa5f76fbc5..b122fcdd1b90 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policies.yaml @@ -4474,6 +4474,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4858,6 +4861,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9443,6 +9468,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9832,6 +9860,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14147,6 +14197,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14511,6 +14564,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19095,6 +19170,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19484,6 +19562,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/config/crds/kyverno/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno/kyverno.io_clusterpolicies.yaml index a8af77755907..9a36663cf688 100644 --- a/config/crds/kyverno/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno/kyverno.io_clusterpolicies.yaml @@ -4473,6 +4473,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4857,6 +4860,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9441,6 +9466,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9830,6 +9858,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14144,6 +14194,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14508,6 +14561,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19092,6 +19167,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19481,6 +19559,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/config/crds/kyverno/kyverno.io_policies.yaml b/config/crds/kyverno/kyverno.io_policies.yaml index e2fa5f76fbc5..b122fcdd1b90 100644 --- a/config/crds/kyverno/kyverno.io_policies.yaml +++ b/config/crds/kyverno/kyverno.io_policies.yaml @@ -4474,6 +4474,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -4858,6 +4861,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -9443,6 +9468,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -9832,6 +9860,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -14147,6 +14197,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -14511,6 +14564,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -19095,6 +19170,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19484,6 +19562,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index c18dd1d1445d..8019580f5b69 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -9796,6 +9796,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -10180,6 +10183,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -14764,6 +14789,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -15153,6 +15181,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -19467,6 +19517,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -19831,6 +19884,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -24415,6 +24490,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -24804,6 +24882,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -29654,6 +29754,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -30038,6 +30141,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -34623,6 +34748,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -35012,6 +35140,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have @@ -39327,6 +39477,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -39691,6 +39844,28 @@ spec: description: UseCache enables caching of image verify responses for this rule type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message to + be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have a @@ -44275,6 +44450,9 @@ spec: type: array type: object type: array + name: + description: Name is the variable name. + type: string predicateType: description: Deprecated in favour of 'Type', to be removed soon @@ -44664,6 +44842,28 @@ spec: description: UseCache enables caching of image verify responses for this rule. type: boolean + validate: + description: |- + Validation checks conditions across multiple image + verification attestations or context entries + properties: + deny: + description: Deny defines conditions used to pass + or fail a validation rule. + properties: + conditions: + description: |- + Multiple conditions can be declared under an `any` or `all` statement. A direct list + of conditions (without `any` or `all` statements) is also supported for backwards compatibility + but will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/validate/#deny-rules + x-kubernetes-preserve-unknown-fields: true + type: object + message: + description: Message specifies a custom message + to be displayed on failure. + type: string + type: object verifyDigest: default: true description: VerifyDigest validates that images have diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 231c95137cdf..ca13fe1a9fb4 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -776,6 +776,17 @@
name
Name is the variable name.
+predicateType
(Appears on: ForEachValidation, +ValidateImageVerification, Validation)
@@ -2771,6 +2783,20 @@
validate
Validation checks conditions across multiple image +verification attestations or context entries
+required
+(Appears on: +ImageVerification, +ImageVerification) +
++
ValidateImageVerification checks conditions across multiple image +verification attestations or context entries
+ +Field | +Description | +
---|---|
+message + +string + + |
+
+(Optional)
+ Message specifies a custom message to be displayed on failure. + |
+
+deny + + +Deny + + + |
+
+(Optional)
+ Deny defines conditions used to pass or fail a validation rule. + |
+
@@ -8837,6 +8911,20 @@
validate
Validation checks conditions across multiple image +verification attestations or context entries
+required
name
+
+ *
+
+
+
+
+
+
+ string
+
+
+ Name is the variable name.
+ + + + + +predicateType
@@ -3319,6 +3348,7 @@ (Appears in: ForEachValidation, + ValidateImageVerification, Validation)
@@ -5567,6 +5597,38 @@validate
+
+ *
+
+
+
+
+
+
+
+ ValidateImageVerification
+
+
+
+ Validation checks conditions across multiple image +verification attestations or context entries
+ + + + + +required
@@ -9321,6 +9383,99 @@ + (Appears in: + ImageVerification) +
+ + +ValidateImageVerification checks conditions across multiple image +verification attestations or context entries
+ + + +Field | +Description | +
---|---|
message
+
+
+
+
+
+
+ string
+
+
+ |
+
+
+
+ Message specifies a custom message to be displayed on failure. + + + + + + |
+
deny
+
+
+
+
+
+
+
+ Deny
+
+
+
+ |
+
+
+
+ Deny defines conditions used to pass or fail a validation rule. + + + + + + |
+
validate
+
+ *
+
+
+
+
+
+
+
+ ValidateImageVerification
+
+
+
+ Validation checks conditions across multiple image +verification attestations or context entries
+ + + + + +required
diff --git a/pkg/client/applyconfigurations/kyverno/v1/attestation.go b/pkg/client/applyconfigurations/kyverno/v1/attestation.go
index 7958026d41c6..694710f74bd8 100644
--- a/pkg/client/applyconfigurations/kyverno/v1/attestation.go
+++ b/pkg/client/applyconfigurations/kyverno/v1/attestation.go
@@ -21,6 +21,7 @@ package v1
// AttestationApplyConfiguration represents an declarative configuration of the Attestation type for use
// with apply.
type AttestationApplyConfiguration struct {
+ Name *string `json:"name,omitempty"`
PredicateType *string `json:"predicateType,omitempty"`
Type *string `json:"type,omitempty"`
Attestors []AttestorSetApplyConfiguration `json:"attestors,omitempty"`
@@ -33,6 +34,14 @@ func Attestation() *AttestationApplyConfiguration {
return &AttestationApplyConfiguration{}
}
+// WithName sets the Name 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 Name field is set to the value of the last call.
+func (b *AttestationApplyConfiguration) WithName(value string) *AttestationApplyConfiguration {
+ b.Name = &value
+ return b
+}
+
// WithPredicateType sets the PredicateType 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 PredicateType field is set to the value of the last call.
diff --git a/pkg/client/applyconfigurations/kyverno/v1/imageverification.go b/pkg/client/applyconfigurations/kyverno/v1/imageverification.go
index c6795df1b636..3334cdd51354 100644
--- a/pkg/client/applyconfigurations/kyverno/v1/imageverification.go
+++ b/pkg/client/applyconfigurations/kyverno/v1/imageverification.go
@@ -25,26 +25,27 @@ import (
// ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use
// with apply.
type ImageVerificationApplyConfiguration struct {
- FailureAction *v1.ValidationFailureAction `json:"failureAction,omitempty"`
- 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"`
- Issuer *string `json:"issuer,omitempty"`
- AdditionalExtensions map[string]string `json:"additionalExtensions,omitempty"`
- Attestors []AttestorSetApplyConfiguration `json:"attestors,omitempty"`
- Attestations []AttestationApplyConfiguration `json:"attestations,omitempty"`
- Annotations map[string]string `json:"annotations,omitempty"`
- Repository *string `json:"repository,omitempty"`
- CosignOCI11 *bool `json:"cosignOCI11,omitempty"`
- MutateDigest *bool `json:"mutateDigest,omitempty"`
- VerifyDigest *bool `json:"verifyDigest,omitempty"`
- Required *bool `json:"required,omitempty"`
- ImageRegistryCredentials *ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
- UseCache *bool `json:"useCache,omitempty"`
+ FailureAction *v1.ValidationFailureAction `json:"failureAction,omitempty"`
+ 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"`
+ Issuer *string `json:"issuer,omitempty"`
+ AdditionalExtensions map[string]string `json:"additionalExtensions,omitempty"`
+ Attestors []AttestorSetApplyConfiguration `json:"attestors,omitempty"`
+ Attestations []AttestationApplyConfiguration `json:"attestations,omitempty"`
+ Annotations map[string]string `json:"annotations,omitempty"`
+ Repository *string `json:"repository,omitempty"`
+ CosignOCI11 *bool `json:"cosignOCI11,omitempty"`
+ MutateDigest *bool `json:"mutateDigest,omitempty"`
+ VerifyDigest *bool `json:"verifyDigest,omitempty"`
+ Validation *ValidateImageVerificationApplyConfiguration `json:"validate,omitempty"`
+ Required *bool `json:"required,omitempty"`
+ ImageRegistryCredentials *ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
+ UseCache *bool `json:"useCache,omitempty"`
}
// ImageVerificationApplyConfiguration constructs an declarative configuration of the ImageVerification type for use with
@@ -215,6 +216,14 @@ func (b *ImageVerificationApplyConfiguration) WithVerifyDigest(value bool) *Imag
return b
}
+// WithValidation sets the Validation 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 Validation field is set to the value of the last call.
+func (b *ImageVerificationApplyConfiguration) WithValidation(value *ValidateImageVerificationApplyConfiguration) *ImageVerificationApplyConfiguration {
+ b.Validation = value
+ return b
+}
+
// WithRequired sets the Required 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 Required field is set to the value of the last call.
diff --git a/pkg/client/applyconfigurations/kyverno/v1/validateimageverification.go b/pkg/client/applyconfigurations/kyverno/v1/validateimageverification.go
new file mode 100644
index 000000000000..c3a4f53cd8e5
--- /dev/null
+++ b/pkg/client/applyconfigurations/kyverno/v1/validateimageverification.go
@@ -0,0 +1,48 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by applyconfiguration-gen. DO NOT EDIT.
+
+package v1
+
+// ValidateImageVerificationApplyConfiguration represents an declarative configuration of the ValidateImageVerification type for use
+// with apply.
+type ValidateImageVerificationApplyConfiguration struct {
+ Message *string `json:"message,omitempty"`
+ Deny *DenyApplyConfiguration `json:"deny,omitempty"`
+}
+
+// ValidateImageVerificationApplyConfiguration constructs an declarative configuration of the ValidateImageVerification type for use with
+// apply.
+func ValidateImageVerification() *ValidateImageVerificationApplyConfiguration {
+ return &ValidateImageVerificationApplyConfiguration{}
+}
+
+// WithMessage sets the Message 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 Message field is set to the value of the last call.
+func (b *ValidateImageVerificationApplyConfiguration) WithMessage(value string) *ValidateImageVerificationApplyConfiguration {
+ b.Message = &value
+ return b
+}
+
+// WithDeny sets the Deny 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 Deny field is set to the value of the last call.
+func (b *ValidateImageVerificationApplyConfiguration) WithDeny(value *DenyApplyConfiguration) *ValidateImageVerificationApplyConfiguration {
+ b.Deny = value
+ return b
+}
diff --git a/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go b/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go
index dc2a7e8186bc..7665d6126e79 100644
--- a/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go
+++ b/pkg/client/applyconfigurations/kyverno/v2beta1/imageverification.go
@@ -26,18 +26,19 @@ import (
// ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use
// with apply.
type ImageVerificationApplyConfiguration struct {
- FailureAction *v1.ValidationFailureAction `json:"failureAction,omitempty"`
- 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"`
- MutateDigest *bool `json:"mutateDigest,omitempty"`
- VerifyDigest *bool `json:"verifyDigest,omitempty"`
- Required *bool `json:"required,omitempty"`
- ImageRegistryCredentials *kyvernov1.ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
- UseCache *bool `json:"useCache,omitempty"`
+ FailureAction *v1.ValidationFailureAction `json:"failureAction,omitempty"`
+ 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"`
+ MutateDigest *bool `json:"mutateDigest,omitempty"`
+ VerifyDigest *bool `json:"verifyDigest,omitempty"`
+ Validation *kyvernov1.ValidateImageVerificationApplyConfiguration `json:"validate,omitempty"`
+ Required *bool `json:"required,omitempty"`
+ ImageRegistryCredentials *kyvernov1.ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
+ UseCache *bool `json:"useCache,omitempty"`
}
// ImageVerificationApplyConfiguration constructs an declarative configuration of the ImageVerification type for use with
@@ -132,6 +133,14 @@ func (b *ImageVerificationApplyConfiguration) WithVerifyDigest(value bool) *Imag
return b
}
+// WithValidation sets the Validation 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 Validation field is set to the value of the last call.
+func (b *ImageVerificationApplyConfiguration) WithValidation(value *kyvernov1.ValidateImageVerificationApplyConfiguration) *ImageVerificationApplyConfiguration {
+ b.Validation = value
+ return b
+}
+
// WithRequired sets the Required 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 Required field is set to the value of the last call.
diff --git a/pkg/client/applyconfigurations/utils.go b/pkg/client/applyconfigurations/utils.go
index 3c799a0d0b47..5addd1898a3b 100644
--- a/pkg/client/applyconfigurations/utils.go
+++ b/pkg/client/applyconfigurations/utils.go
@@ -141,6 +141,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &kyvernov1.TargetResourceSpecApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("UserInfo"):
return &kyvernov1.UserInfoApplyConfiguration{}
+ case v1.SchemeGroupVersion.WithKind("ValidateImageVerification"):
+ return &kyvernov1.ValidateImageVerificationApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicyStatus"):
return &kyvernov1.ValidatingAdmissionPolicyStatusApplyConfiguration{}
case v1.SchemeGroupVersion.WithKind("Validation"):
diff --git a/pkg/engine/handlers/mutation/mutate_image.go b/pkg/engine/handlers/mutation/mutate_image.go
index 1a47d1543f84..88f2e8f0f76f 100644
--- a/pkg/engine/handlers/mutation/mutate_image.go
+++ b/pkg/engine/handlers/mutation/mutate_image.go
@@ -95,6 +95,7 @@ func (h mutateImageHandler) Process(
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to substitute variables", err, rule.ReportProperties),
)
}
+
var engineResponses []*engineapi.RuleResponse
var patches []jsonpatch.JsonPatchOperation
for _, imageVerify := range ruleCopy.VerifyImages {
@@ -141,22 +142,31 @@ func (h mutateImageHandler) Process(
func substituteVariables(rule kyvernov1.Rule, ctx enginecontext.EvalInterface, logger logr.Logger) (*kyvernov1.Rule, error) {
// remove attestations as variables are not substituted in them
+ hasValidateImageVerification := rule.HasValidateImageVerification()
ruleCopy := *rule.DeepCopy()
for i := range ruleCopy.VerifyImages {
for j := range ruleCopy.VerifyImages[i].Attestations {
ruleCopy.VerifyImages[i].Attestations[j].Conditions = nil
}
+ if hasValidateImageVerification {
+ ruleCopy.VerifyImages[i].Validation.Deny.RawAnyAllConditions = nil
+ }
}
+
var err error
ruleCopy, err = variables.SubstituteAllInRule(logger, ctx, ruleCopy)
if err != nil {
return nil, err
}
+
// replace attestations
for i := range ruleCopy.VerifyImages {
for j := range ruleCopy.VerifyImages[i].Attestations {
ruleCopy.VerifyImages[i].Attestations[j].Conditions = rule.VerifyImages[i].Attestations[j].Conditions
}
+ if hasValidateImageVerification {
+ ruleCopy.VerifyImages[i].Validation.Deny.RawAnyAllConditions = rule.VerifyImages[i].Validation.Deny.RawAnyAllConditions
+ }
}
return &ruleCopy, nil
}
diff --git a/pkg/engine/image_verify_test.go b/pkg/engine/image_verify_test.go
index 604a73797044..4e255511a6c8 100644
--- a/pkg/engine/image_verify_test.go
+++ b/pkg/engine/image_verify_test.go
@@ -1508,3 +1508,229 @@ func Test_SkipImageReferences(t *testing.T) {
fmt.Sprintf("expected: %v, got: %v, failure: %v",
engineapi.RuleStatusPass, erSkip.PolicyResponse.Rules[0].Status(), erSkip.PolicyResponse.Rules[0].Message()))
}
+
+var multipleImageVerificationAttestationPolicyPass = `{
+ "apiVersion": "kyverno.io/v1",
+ "kind": "ClusterPolicy",
+ "metadata": {
+ "name": "check-image-attestation"
+ },
+ "spec": {
+ "validationFailureAction": "Enforce",
+ "webhookTimeoutSeconds": 30,
+ "failurePolicy": "Fail",
+ "rules": [
+ {
+ "name": "verify-attestation-notary",
+ "match": {
+ "any": [
+ {
+ "resources": {
+ "kinds": [
+ "Pod"
+ ]
+ }
+ }
+ ]
+ },
+ "context": [
+ {
+ "name": "keys",
+ "configMap": {
+ "name": "keys",
+ "namespace": "notary-verify-attestation"
+ }
+ }
+ ],
+ "verifyImages": [
+ {
+ "type": "Notary",
+ "imageReferences": [
+ "ghcr.io/kyverno/test-verify-image*"
+ ],
+ "attestations": [
+ {
+ "type": "sbom/cyclone-dx",
+ "name": "sbom",
+ "attestors": [
+ {
+ "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-----"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "vulnerability-scan",
+ "name": "scan",
+ "attestors": [
+ {
+ "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-----"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "validate": {
+ "deny": {
+ "conditions": {
+ "any": [
+ {
+ "key": "{{ time_after('{{ sbom.metadata.timestamp }}', '{{ scan.descriptor.timestamp }}' ) }}",
+ "operator": "Equals",
+ "value": "False"
+ }
+ ]
+ }
+ },
+ "message": "Sample Validation"
+ }
+ }
+ ]
+ }
+ ]
+ }
+}`
+
+var multipleImageVerificationAttestationPolicyFail = `{
+ "apiVersion": "kyverno.io/v1",
+ "kind": "ClusterPolicy",
+ "metadata": {
+ "name": "check-image-attestation"
+ },
+ "spec": {
+ "validationFailureAction": "Enforce",
+ "webhookTimeoutSeconds": 30,
+ "failurePolicy": "Fail",
+ "rules": [
+ {
+ "name": "verify-attestation-notary",
+ "match": {
+ "any": [
+ {
+ "resources": {
+ "kinds": [
+ "Pod"
+ ]
+ }
+ }
+ ]
+ },
+ "context": [
+ {
+ "name": "keys",
+ "configMap": {
+ "name": "keys",
+ "namespace": "notary-verify-attestation"
+ }
+ }
+ ],
+ "verifyImages": [
+ {
+ "type": "Notary",
+ "imageReferences": [
+ "ghcr.io/kyverno/test-verify-image*"
+ ],
+ "attestations": [
+ {
+ "type": "sbom/cyclone-dx",
+ "name": "sbom",
+ "attestors": [
+ {
+ "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-----"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "vulnerability-scan",
+ "name": "scan",
+ "attestors": [
+ {
+ "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-----"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "validate": {
+ "deny": {
+ "conditions": {
+ "any": [
+ {
+ "key": "{{ time_after('{{ sbom.metadata.timestamp }}', '{{ scan.descriptor.timestamp }}' ) }}",
+ "operator": "Equals",
+ "value": "True"
+ }
+ ]
+ }
+ },
+ "message": "Sample Validation"
+ }
+ }
+ ]
+ }
+ ]
+ }
+}`
+
+func Test_MultipleImageVerificationAttestationPass(t *testing.T) {
+ policyContextPass := buildContext(t, multipleImageVerificationAttestationPolicyPass, 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()))
+}
+
+func Test_MultipleImageVerificationAttestationFail(t *testing.T) {
+ policyContextPass := buildContext(t, multipleImageVerificationAttestationPolicyFail, 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 440989cd75f4..c898a9c4ef89 100644
--- a/pkg/engine/internal/imageverifier.go
+++ b/pkg/engine/internal/imageverifier.go
@@ -23,6 +23,8 @@ import (
"github.com/kyverno/kyverno/pkg/notary"
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
"github.com/kyverno/kyverno/pkg/utils/jsonpointer"
+ stringutils "github.com/kyverno/kyverno/pkg/utils/strings"
+ "github.com/kyverno/kyverno/pkg/validation/policy"
"go.uber.org/multierr"
"gomodules.xyz/jsonpatch/v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -220,6 +222,20 @@ func EvaluateConditions(
return variables.EvaluateAnyAllConditions(log, ctx, c)
}
+func getRawResp(statements []map[string]interface{}) ([]byte, error) {
+ for _, statement := range statements {
+ predicate, ok := statement["predicate"].(map[string]interface{})
+ if ok {
+ rawResp, err := json.Marshal(predicate)
+ if err != nil {
+ return nil, err
+ }
+ return rawResp, nil
+ }
+ }
+ return nil, fmt.Errorf("predicate not found in any statement")
+}
+
// verify applies policy rules to each matching image. The policy rule results and annotation patches are
// added to tme imageVerifier `resp` and `ivm` fields.
func (iv *ImageVerifier) Verify(
@@ -405,6 +421,7 @@ func (iv *ImageVerifier) verifyAttestations(
image := imageInfo.String()
for i, attestation := range imageVerify.Attestations {
var errorList []error
+
path := fmt.Sprintf(".attestations[%d]", i)
iv.logger.V(2).Info(fmt.Sprintf("attestation %+v", attestation))
@@ -437,6 +454,22 @@ func (iv *ImageVerifier) verifyAttestations(
continue
}
+ name := imageVerify.Attestations[i].Name
+
+ rawResp, err := getRawResp(cosignResp.Statements)
+ if err != nil {
+ iv.logger.Error(err, "Error while finding report in statement")
+ errorList = append(errorList, err)
+ continue
+ }
+
+ err = iv.policyContext.JSONContext().AddContextEntry(name, rawResp)
+ if err != nil {
+ iv.logger.Error(err, "failed to add resource data to context entry")
+ errorList = append(errorList, err)
+ continue
+ }
+
if imageInfo.Digest == "" {
imageInfo.Digest = cosignResp.Digest
image = imageInfo.String()
@@ -471,6 +504,18 @@ func (iv *ImageVerifier) verifyAttestations(
iv.logger.V(4).Info("attestation checks passed", "path", path, "image", imageInfo.String(), "type", attestation.Type)
}
+ if iv.rule.HasValidateImageVerification() {
+ for _, imageVerify := range iv.rule.VerifyImages {
+ if err := iv.validate(imageVerify, ctx); err != nil {
+ msg := fmt.Sprintf("validation in verifyImages failed: %v", err)
+ iv.logger.Error(err, "validation in verifyImages failed")
+ return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), imageInfo.Digest
+ }
+ }
+ msg := fmt.Sprintf("verifyImages validation is passed in %v rule", iv.rule.Name)
+ return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), imageInfo.Digest
+ }
+
msg := fmt.Sprintf("verified image attestations for %s", image)
iv.logger.V(2).Info(msg)
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg, iv.rule.ReportProperties), imageInfo.Digest
@@ -745,3 +790,53 @@ func (iv *ImageVerifier) handleMutateDigest(ctx context.Context, digest string,
iv.logger.V(4).Info("adding digest patch", "image", imageInfo.String(), "patch", patch.Json())
return &patch, digest, nil
}
+
+func (iv *ImageVerifier) validate(imageVerify kyvernov1.ImageVerification, ctx context.Context) error {
+ spec := iv.policyContext.Policy().GetSpec()
+ background := spec.BackgroundProcessingEnabled()
+ err := policy.ValidateVariables(iv.policyContext.Policy(), background)
+ if err != nil {
+ return err
+ }
+
+ if imageVerify.Validation.Deny != nil {
+ if err := iv.validateDeny(imageVerify); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (iv *ImageVerifier) validateDeny(imageVerify kyvernov1.ImageVerification) error {
+ if deny, msg, err := CheckDenyPreconditions(iv.logger, iv.policyContext.JSONContext(), imageVerify.Validation.Deny.GetAnyAllConditions()); err != nil {
+ return fmt.Errorf("failed to check deny conditions: %v", err)
+ } else {
+ if deny {
+ return fmt.Errorf("%s", iv.getDenyMessage(imageVerify, deny, msg))
+ }
+ return nil
+ }
+}
+
+func (iv *ImageVerifier) getDenyMessage(imageVerify kyvernov1.ImageVerification, deny bool, msg string) string {
+ if !deny {
+ return fmt.Sprintf("validation imageVerify '%s' passed.", imageVerify.Validation.Message)
+ }
+
+ if imageVerify.Validation.Message == "" && msg == "" {
+ return fmt.Sprintf("validation error: imageVerify %s failed", imageVerify.Validation.Message)
+ }
+
+ s := stringutils.JoinNonEmpty([]string{imageVerify.Validation.Message, msg}, "; ")
+ raw, err := variables.SubstituteAll(iv.logger, iv.policyContext.JSONContext(), s)
+ if err != nil {
+ return msg
+ }
+
+ switch typed := raw.(type) {
+ case string:
+ return typed
+ default:
+ return "the produced message didn't resolve to a string, check your policy definition."
+ }
+}
diff --git a/pkg/validation/policy/validate.go b/pkg/validation/policy/validate.go
index 45da50169c8e..0ce03a51d948 100644
--- a/pkg/validation/policy/validate.go
+++ b/pkg/validation/policy/validate.go
@@ -424,6 +424,21 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
if rule.HasVerifyImages() {
checkForDeprecatedFieldsInVerifyImages(rule, &warnings)
+
+ if rule.HasValidateImageVerification() {
+ for _, verifyImage := range rule.VerifyImages {
+ validationElem := verifyImage.Validation.DeepCopy()
+ if validationElem.Deny != nil {
+ validationElem.Deny.RawAnyAllConditions = nil
+ }
+ validationJson, err := json.Marshal(validationElem)
+ if err != nil {
+ return nil, err
+ }
+ checkForScaleSubresource(validationJson, allKinds, &warnings)
+ checkForStatusSubresource(validationJson, allKinds, &warnings)
+ }
+ }
}
checkForDeprecatedOperatorsInRule(rule, &warnings)
@@ -560,7 +575,7 @@ func hasInvalidVariables(policy kyvernov1.PolicyInterface, background bool) erro
ctx := buildContext(ruleCopy, background, mutateTarget)
if _, err := variables.SubstituteAllInRule(logging.GlobalLogger(), ctx, *ruleCopy); !variables.CheckNotFoundErr(err) {
- return fmt.Errorf("variable substitution failed for %s/%s: %s", policy.GetName(), ruleCopy.Name, err.Error())
+ return fmt.Errorf("variable substitution failed for rule %s: %s", ruleCopy.Name, err.Error())
}
}
@@ -713,8 +728,12 @@ func ruleWithoutPattern(ruleCopy *kyvernov1.Rule) *kyvernov1.Rule {
func buildContext(rule *kyvernov1.Rule, background bool, target bool) *enginecontext.MockContext {
re := getAllowedVariables(background, target)
+
ctx := enginecontext.NewMockContext(re)
+
addContextVariables(rule.Context, ctx)
+ addImageVerifyVariables(rule, ctx)
+
for _, fe := range rule.Validation.ForEachValidation {
addContextVariables(fe.Context, ctx)
}
@@ -759,6 +778,16 @@ func addContextVariables(entries []kyvernov1.ContextEntry, ctx *enginecontext.Mo
}
}
+func addImageVerifyVariables(rule *kyvernov1.Rule, ctx *enginecontext.MockContext) {
+ if rule.HasValidateImageVerification() {
+ for _, verifyImage := range rule.VerifyImages {
+ for _, attestation := range verifyImage.Attestations {
+ ctx.AddVariable(attestation.Name + "*")
+ }
+ }
+ }
+}
+
func validateElementInForEach(document apiextensions.JSON) error {
jsonByte, err := json.Marshal(document)
if err != nil {
@@ -1011,6 +1040,16 @@ func validateResources(path *field.Path, rule kyvernov1.Rule) (string, error) {
}
}
}
+ if rule.HasValidateImageVerification() {
+ if target := vi.Validation.Deny.GetAnyAllConditions(); target != nil {
+ if path, err := validateConditions(target, "conditions"); err != nil {
+ return fmt.Sprintf("imageVerify.validate.deny.%s", path), err
+ }
+ if path, err := validateRawJSONConditionOperator(target, "conditions"); err != nil {
+ return fmt.Sprintf("imageVerify.validate.deny.%s", path), err
+ }
+ }
+ }
}
}
diff --git a/test/conformance/chainsaw/e2e-matrix.json b/test/conformance/chainsaw/e2e-matrix.json
index 6a600010c712..8fbdb33fa015 100644
--- a/test/conformance/chainsaw/e2e-matrix.json
+++ b/test/conformance/chainsaw/e2e-matrix.json
@@ -147,8 +147,8 @@
"verifyImages": [
"^verifyImages$/^clusterpolicy$/^cornercases$/^(multiple-attestors)\\[.*\\]$",
"^verifyImages$/^clusterpolicy$/^standard$/^(configmap-context-lookup|empty-image|failure-policy-test-noconfigmap-diffimage-success|failure-policy-test-noconfigmap-diffimage-success-deprecated|imageExtractors-complex|imageExtractors-complex-keyless|imageExtractors-none|imageExtractors-simple|keyed-basic|keyed-basic-namespace-selector|keyed-oci11|keyed-secret|keyed-tsa|keyless-attestation-invalid-attestor|keyless-attestation-regexp|keyless-attestations-multiple-subjects-1|keyless-attestations-multiple-subjects-2|keyless-attestations-multiple-subjects-3|keyless-attestations-multiple-subjects-4|keyless-attestations-multiple-subjects-counts-1)\\[.*\\]$",
- "^verifyImages$/^clusterpolicy$/^standard$/^(keyless-attestations-multiple-subjects-counts-2|keyless-attestations-multiple-subjects-counts-3|keyless-image-invalid-attestor|keyless-mutatedigest-verifydigest-required|keyless-nomutatedigest-noverifydigest-norequired|keyless-nomutatedigest-noverifydigest-required|mutateDigest-noverifyDigest-norequired|noconfigmap-diffimage-success|nomutateDigest-verifyDigest-norequired|notary-attestation-verification|notary-image-verification|notary-image-verification-secret-from-policy|rollback-image-verification|sigstore-attestation-verification-regexp|sigstore-attestation-verification-test|sigstore-image-verification-test|skip-image-reference|update-multi-containers|verify-image-background-audit|verify-image-background-basic)\\[.*\\]$",
- "^verifyImages$/^clusterpolicy$/^standard$/^(verify-image-background-existing|with-mutation)\\[.*\\]$"
+ "^verifyImages$/^clusterpolicy$/^standard$/^(keyless-attestations-multiple-subjects-counts-2|keyless-attestations-multiple-subjects-counts-3|keyless-image-invalid-attestor|keyless-mutatedigest-verifydigest-required|keyless-nomutatedigest-noverifydigest-norequired|keyless-nomutatedigest-noverifydigest-required|multiple-image-verification-attestations-fail|multiple-image-verification-attestations-pass|multiple-image-verification-attestations-trivy-vex-fail|multiple-image-verification-attestations-trivy-vex-pass|mutateDigest-noverifyDigest-norequired|noconfigmap-diffimage-success|nomutateDigest-verifyDigest-norequired|notary-attestation-verification|notary-image-verification|notary-image-verification-secret-from-policy|rollback-image-verification|sigstore-attestation-verification-regexp|sigstore-attestation-verification-test|sigstore-image-verification-test)\\[.*\\]$",
+ "^verifyImages$/^clusterpolicy$/^standard$/^(skip-image-reference|update-multi-containers|verify-image-background-audit|verify-image-background-basic|verify-image-background-existing|with-mutation)\\[.*\\]$"
],
"webhook-configurations": [
"^webhook-configurations$"
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/README.md
new file mode 100644
index 000000000000..bb1b6758516d
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/README.md
@@ -0,0 +1,12 @@
+## Description
+
+This test verifies multiple image attestations using notary signatures
+
+## Expected Behavior
+
+This test creates a cluster policy.
+When a pod is created with the image reference and the signature on multiple attestations matches, the pod creation is failure
+
+## Reference Issue(s)
+
+https://github.com/kyverno/kyverno/issues/9456
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/chainsaw-test.yaml
new file mode 100755
index 000000000000..d6e31ed30836
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/chainsaw-test.yaml
@@ -0,0 +1,22 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: multiple-image-verification-attestations-fail
+spec:
+ timeouts:
+ delete: 2m
+ steps:
+ - name: step-01
+ try:
+ - apply:
+ file: policy.yaml
+ - assert:
+ file: policy-ready.yaml
+ - name: step-02
+ try:
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod.yaml
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/pod.yaml
new file mode 100644
index 000000000000..e16637872d04
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/pod.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: null
+ labels:
+ run: test
+ name: test
+ namespace: notary-verify-attestation
+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/multiple-image-verification-attestations-fail/policy-ready.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/policy-ready.yaml
new file mode 100644
index 000000000000..83c51e70577c
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/policy-ready.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v2beta1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/policy.yaml
new file mode 100644
index 000000000000..1d34fa08a635
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-fail/policy.yaml
@@ -0,0 +1,83 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: notary-verify-attestation
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keys
+ namespace: notary-verify-attestation
+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/v1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+spec:
+ validationFailureAction: Enforce
+ webhookTimeoutSeconds: 30
+ failurePolicy: Fail
+ rules:
+ - name: verify-attestation-notary
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ context:
+ - name: keys
+ configMap:
+ name: keys
+ namespace: notary-verify-attestation
+ verifyImages:
+ - type: Notary
+ imageReferences:
+ - "ghcr.io/kyverno/test-verify-image*"
+ attestations:
+ - type: sbom/cyclone-dx
+ name: sbom
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ - type: vulnerability-scan
+ name: scan
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ validate:
+ deny:
+ conditions:
+ any:
+ - key: '{{ sbom.bomFormat }}'
+ operator: NotEquals
+ value: CycloneDX
+ message: test1
+ - key: "{{ time_after('{{ sbom.metadata.timestamp }}', '{{ scan.descriptor.timestamp }}' ) }}"
+ operator: Equals
+ value: True
+ message: test2
+ message: scan report should be created after sbom
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/README.md
new file mode 100644
index 000000000000..504750e3a413
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/README.md
@@ -0,0 +1,12 @@
+## Description
+
+This test verifies multiple image attestations using notary signatures
+
+## Expected Behavior
+
+This test creates a cluster policy.
+When a pod is created with the image reference and the signature on multiple attestations matches, the pod creation is successful
+
+## Reference Issue(s)
+
+https://github.com/kyverno/kyverno/issues/9456
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/chainsaw-test.yaml
new file mode 100755
index 000000000000..0cf5531cf44f
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/chainsaw-test.yaml
@@ -0,0 +1,21 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: multiple-image-verification-attestations-pass
+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
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod-assert.yaml
new file mode 100644
index 000000000000..d18a0a10e95e
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod-assert.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: test
+ namespace: notary-verify-attestation
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod.yaml
new file mode 100644
index 000000000000..e16637872d04
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/pod.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: null
+ labels:
+ run: test
+ name: test
+ namespace: notary-verify-attestation
+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/multiple-image-verification-attestations-pass/policy-ready.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/policy-ready.yaml
new file mode 100644
index 000000000000..83c51e70577c
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/policy-ready.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v2beta1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/policy.yaml
new file mode 100644
index 000000000000..9f1085071190
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-pass/policy.yaml
@@ -0,0 +1,83 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: notary-verify-attestation
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keys
+ namespace: notary-verify-attestation
+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/v1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+spec:
+ validationFailureAction: Enforce
+ webhookTimeoutSeconds: 30
+ failurePolicy: Fail
+ rules:
+ - name: verify-attestation-notary
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ context:
+ - name: keys
+ configMap:
+ name: keys
+ namespace: notary-verify-attestation
+ verifyImages:
+ - type: Notary
+ imageReferences:
+ - "ghcr.io/kyverno/test-verify-image*"
+ attestations:
+ - type: sbom/cyclone-dx
+ name: sbom
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ - type: vulnerability-scan
+ name: scan
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ validate:
+ deny:
+ conditions:
+ any:
+ - key: '{{ sbom.bomFormat }}'
+ operator: NotEquals
+ value: CycloneDX
+ message: test1
+ - key: "{{ time_after('{{ sbom.metadata.timestamp }}', '{{ scan.descriptor.timestamp }}' ) }}"
+ operator: Equals
+ value: False
+ message: test2
+ message: scan report should be created after sbom
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/README.md
new file mode 100644
index 000000000000..bb1b6758516d
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/README.md
@@ -0,0 +1,12 @@
+## Description
+
+This test verifies multiple image attestations using notary signatures
+
+## Expected Behavior
+
+This test creates a cluster policy.
+When a pod is created with the image reference and the signature on multiple attestations matches, the pod creation is failure
+
+## Reference Issue(s)
+
+https://github.com/kyverno/kyverno/issues/9456
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/chainsaw-test.yaml
new file mode 100755
index 000000000000..d030144bac73
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/chainsaw-test.yaml
@@ -0,0 +1,22 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: multiple-image-verification-attestations-trivy-vex-fail
+spec:
+ timeouts:
+ delete: 2m
+ steps:
+ - name: step-01
+ try:
+ - apply:
+ file: policy.yaml
+ - assert:
+ file: policy-ready.yaml
+ - name: step-02
+ try:
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod.yaml
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/pod.yaml
new file mode 100644
index 000000000000..e16637872d04
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/pod.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: null
+ labels:
+ run: test
+ name: test
+ namespace: notary-verify-attestation
+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/multiple-image-verification-attestations-trivy-vex-fail/policy-ready.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/policy-ready.yaml
new file mode 100644
index 000000000000..83c51e70577c
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/policy-ready.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v2beta1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/policy.yaml
new file mode 100644
index 000000000000..95a160a1a328
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-fail/policy.yaml
@@ -0,0 +1,80 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: notary-verify-attestation
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keys
+ namespace: notary-verify-attestation
+data:
+ certificate: |-
+ -----BEGIN CERTIFICATE-----
+ MIIDmDCCAoCgAwIBAgIUCntgF4FftePAhEa6nZTsu/NMT3cwDQYJKoZIhvcNAQEL
+ BQAwTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxl
+ MQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwHhcNMjQwNjEwMTYzMTQ2
+ WhcNMzQwNjA4MTYzMTQ2WjBMMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAO
+ BgNVBAcMB1NlYXR0bGUxDzANBgNVBAoMBk5vdGFyeTENMAsGA1UEAwwEdGVzdDCC
+ ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJkEGqbILiWye6C1Jz+jwwDY
+ k/rovpXzxS+EQDvfj/YKvx37Kr4cjboJORu3wtzICWhPUtVWZ21ShfjerKgNq0iB
+ mrlF4cqz2KcOfuUT3XBglH/NwhEAqOrGPQrMsoQEFWgnilr0RTc+j4vDnkdkcTj2
+ K/qPhQHRAeb97TdvFCqcZfAGqiOVUqzDGxd2INz/fJd4/nYRX3LJBn9pUGxqRwZV
+ ElP5B/aCBjJDdh6tAElT5aDnLGAB+3+W2YwG342ELyAl2ILpbSRUpKLNAfKEd7Nj
+ 1moIl4or5AIlTkgewZ/AK68HPFJEV3SwNbzkgAC+/mLVCD8tqu0o0ziyIUJtoQMC
+ AwEAAaNyMHAwHQYDVR0OBBYEFFTIzCppwv0vZnAVmETPm1CfMdcYMB8GA1UdIwQY
+ MBaAFFTIzCppwv0vZnAVmETPm1CfMdcYMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQD
+ AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQB8/vfP
+ /TQ3X80JEZDsttdvd9NLm08bTJ/T+nh0DIiV10aHymQT9/u+iahfm1+7mj+uv8LS
+ Y63LepQCX5p9SoFzt513pbNYXMBbRrOKpth3DD49IPL2Gce86AFGydfrakd86CL1
+ 9MhFeWhtRf0KndyUX8J2s7jbpoN8HrN4/wZygiEqbQWZG8YtIZ9EewmoVMYirQqH
+ EvW93NcgmjiELuhjndcT/kHjhf8fUAgSuxiPIy6ern02fJjw40KzgiKNvxMoI9su
+ G2zu6gXmxkw+x0SMe9kX+Rg4hCIjTUM7dc66XL5LcTp4S5YEZNVC40/FgTIZoK0e
+ r1dC2/Y1SmmrIoA1
+ -----END CERTIFICATE-----
+---
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+spec:
+ validationFailureAction: Enforce
+ webhookTimeoutSeconds: 30
+ failurePolicy: Fail
+ rules:
+ - name: verify-attestation-notary
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ context:
+ - name: keys
+ configMap:
+ name: keys
+ namespace: notary-verify-attestation
+ verifyImages:
+ - type: Notary
+ imageReferences:
+ - "ghcr.io/kyverno/test-verify-image*"
+ attestations:
+ - type: trivy/vulnerability-fail-test
+ name: trivy
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ - type: vex/cyclone-dx
+ name: vex
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ validate:
+ deny:
+ conditions:
+ any:
+ - key: '{{ trivy.Vulnerabilities[*].VulnerabilityID }}'
+ operator: AnyNotIn
+ value: '{{ vex.vulnerabilities[*].id }}'
+ message: All vulnerabilities in trivy and vex should be same
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/README.md
new file mode 100644
index 000000000000..43f533b82d1d
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/README.md
@@ -0,0 +1,12 @@
+## Description
+
+This test verifies multiple image attestations using notary signatures
+
+## Expected Behavior
+
+This test creates a cluster policy.
+When a pod is created with the image reference and the signature on multiple attestations matches, the pod creation is successful
+
+## Reference Issue(s)
+
+https://github.com/kyverno/kyverno/issues/9456
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/chainsaw-test.yaml
new file mode 100755
index 000000000000..a49bdddcd6d9
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/chainsaw-test.yaml
@@ -0,0 +1,21 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: multiple-image-verification-attestations-trivy-vex-pass
+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
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod-assert.yaml
new file mode 100644
index 000000000000..d18a0a10e95e
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod-assert.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: test
+ namespace: notary-verify-attestation
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod.yaml
new file mode 100644
index 000000000000..e16637872d04
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/pod.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ creationTimestamp: null
+ labels:
+ run: test
+ name: test
+ namespace: notary-verify-attestation
+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/multiple-image-verification-attestations-trivy-vex-pass/policy-ready.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/policy-ready.yaml
new file mode 100644
index 000000000000..83c51e70577c
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/policy-ready.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v2beta1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
\ No newline at end of file
diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/policy.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/policy.yaml
new file mode 100644
index 000000000000..b3024ec2b621
--- /dev/null
+++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/multiple-image-verification-attestations-trivy-vex-pass/policy.yaml
@@ -0,0 +1,80 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: notary-verify-attestation
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keys
+ namespace: notary-verify-attestation
+data:
+ certificate: |-
+ -----BEGIN CERTIFICATE-----
+ MIIDmDCCAoCgAwIBAgIUCntgF4FftePAhEa6nZTsu/NMT3cwDQYJKoZIhvcNAQEL
+ BQAwTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxl
+ MQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwHhcNMjQwNjEwMTYzMTQ2
+ WhcNMzQwNjA4MTYzMTQ2WjBMMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAO
+ BgNVBAcMB1NlYXR0bGUxDzANBgNVBAoMBk5vdGFyeTENMAsGA1UEAwwEdGVzdDCC
+ ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJkEGqbILiWye6C1Jz+jwwDY
+ k/rovpXzxS+EQDvfj/YKvx37Kr4cjboJORu3wtzICWhPUtVWZ21ShfjerKgNq0iB
+ mrlF4cqz2KcOfuUT3XBglH/NwhEAqOrGPQrMsoQEFWgnilr0RTc+j4vDnkdkcTj2
+ K/qPhQHRAeb97TdvFCqcZfAGqiOVUqzDGxd2INz/fJd4/nYRX3LJBn9pUGxqRwZV
+ ElP5B/aCBjJDdh6tAElT5aDnLGAB+3+W2YwG342ELyAl2ILpbSRUpKLNAfKEd7Nj
+ 1moIl4or5AIlTkgewZ/AK68HPFJEV3SwNbzkgAC+/mLVCD8tqu0o0ziyIUJtoQMC
+ AwEAAaNyMHAwHQYDVR0OBBYEFFTIzCppwv0vZnAVmETPm1CfMdcYMB8GA1UdIwQY
+ MBaAFFTIzCppwv0vZnAVmETPm1CfMdcYMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQD
+ AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQB8/vfP
+ /TQ3X80JEZDsttdvd9NLm08bTJ/T+nh0DIiV10aHymQT9/u+iahfm1+7mj+uv8LS
+ Y63LepQCX5p9SoFzt513pbNYXMBbRrOKpth3DD49IPL2Gce86AFGydfrakd86CL1
+ 9MhFeWhtRf0KndyUX8J2s7jbpoN8HrN4/wZygiEqbQWZG8YtIZ9EewmoVMYirQqH
+ EvW93NcgmjiELuhjndcT/kHjhf8fUAgSuxiPIy6ern02fJjw40KzgiKNvxMoI9su
+ G2zu6gXmxkw+x0SMe9kX+Rg4hCIjTUM7dc66XL5LcTp4S5YEZNVC40/FgTIZoK0e
+ r1dC2/Y1SmmrIoA1
+ -----END CERTIFICATE-----
+---
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: check-image-attestation
+spec:
+ validationFailureAction: Enforce
+ webhookTimeoutSeconds: 30
+ failurePolicy: Fail
+ rules:
+ - name: verify-attestation-notary
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ context:
+ - name: keys
+ configMap:
+ name: keys
+ namespace: notary-verify-attestation
+ verifyImages:
+ - type: Notary
+ imageReferences:
+ - "ghcr.io/kyverno/test-verify-image*"
+ attestations:
+ - type: trivy/vulnerability
+ name: trivy
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ - type: vex/cyclone-dx
+ name: vex
+ attestors:
+ - entries:
+ - certificates:
+ cert: "{{ keys.data.certificate }}"
+ validate:
+ deny:
+ conditions:
+ any:
+ - key: '{{ trivy.Vulnerabilities[*].VulnerabilityID }}'
+ operator: AnyNotIn
+ value: '{{ vex.vulnerabilities[*].id }}'
+ message: All vulnerabilities in trivy and vex should be same
\ No newline at end of file