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 @@

Attestation +name
+ +string + + + +

Name is the variable name.

+ + + + predicateType
string @@ -1613,6 +1624,7 @@

Deny

(Appears on: ForEachValidation, +ValidateImageVerification, Validation)

@@ -2771,6 +2783,20 @@

ImageVerification +validate
+ + +ValidateImageVerification + + + + +

Validation checks conditions across multiple image +verification attestations or context entries

+ + + + required
bool @@ -4634,6 +4660,54 @@

UserInfo
+

ValidateImageVerification +

+

+(Appears on: +ImageVerification, +ImageVerification) +

+

+

ValidateImageVerification checks conditions across multiple image +verification attestations or context entries

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+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.

+
+

ValidatingAdmissionPolicyStatus

@@ -8837,6 +8911,20 @@

ImageVerification +validate
+ + +ValidateImageVerification + + + + +

Validation checks conditions across multiple image +verification attestations or context entries

+ + + + required
bool diff --git a/docs/user/crd/kyverno.v1.html b/docs/user/crd/kyverno.v1.html index 83c05bbfc5aa..4276b605ff88 100644 --- a/docs/user/crd/kyverno.v1.html +++ b/docs/user/crd/kyverno.v1.html @@ -1535,6 +1535,35 @@

Attestation + + name + + * + +
+ + + + + string + + + + + + +

Name is the variable name.

+ + + + + + + + + + + predicateType @@ -3319,6 +3348,7 @@

Deny

(Appears in: ForEachValidation, + ValidateImageVerification, Validation)

@@ -5567,6 +5597,38 @@

ImageVerification + + validate + + * + +
+ + + + + + ValidateImageVerification + + + + + + + +

Validation checks conditions across multiple image +verification attestations or context entries

+ + + + + + + + + + + required @@ -9321,6 +9383,99 @@

UserInfo + + + + +

ValidateImageVerification +

+ + +

+ (Appears in: + ImageVerification) +

+ + +

ValidateImageVerification checks conditions across multiple image +verification attestations or context entries

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
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.

+ + + + + +
diff --git a/docs/user/crd/kyverno.v2beta1.html b/docs/user/crd/kyverno.v2beta1.html index 92fb73e60665..b4f3e25105fa 100644 --- a/docs/user/crd/kyverno.v2beta1.html +++ b/docs/user/crd/kyverno.v2beta1.html @@ -3052,6 +3052,38 @@

ImageVerification + + 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