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

feat: reconcile ivpol.status ()

* feat: update ivpol.status api

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: fix unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update codegen

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update codegen

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: reconcile ivpol.status

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: linter issues

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: autogen fields replacement

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: add unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: update ivpol autogen rules

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: invoke ivpol webhook handler

Signed-off-by: ShutingZhao <shuting@nirmata.com>

---------

Signed-off-by: ShutingZhao <shuting@nirmata.com>
Signed-off-by: shuting <shuting@nirmata.com>
This commit is contained in:
shuting 2025-03-15 07:59:19 +08:00 committed by GitHub
parent af550f54d5
commit 5c5a5fc0b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 5090 additions and 2554 deletions

View file

@ -6,13 +6,17 @@ import (
"github.com/kyverno/kyverno/api/kyverno"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=imageverificationpolicies,scope="Cluster",shortName=ivpol,categories=kyverno
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.ready`
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ImageVerificationPolicy struct {
@ -21,7 +25,24 @@ type ImageVerificationPolicy struct {
Spec ImageVerificationPolicySpec `json:"spec"`
// Status contains policy runtime data.
// +optional
Status PolicyStatus `json:"status,omitempty"`
Status IvpolStatus `json:"status,omitempty"`
}
type IvpolStatus struct {
ConditionStatus *ConditionStatus `json:",inline"`
// +optional
Autogen IvpolAutogenStatus `json:"autogen,omitempty"`
}
type IvpolAutogenStatus struct {
// +optional
Rules []*IvpolAutogen `json:"rules,omitempty"`
}
type IvpolAutogen struct {
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ImageVerificationPolicySpec `json:"spec"`
}
func (s *ImageVerificationPolicy) GetName() string {
@ -68,7 +89,7 @@ func (s *ImageVerificationPolicy) GetSpec() *ImageVerificationPolicySpec {
return &s.Spec
}
func (s *ImageVerificationPolicy) GetStatus() *PolicyStatus {
func (s *ImageVerificationPolicy) GetStatus() *IvpolStatus {
return &s.Status
}
@ -92,6 +113,32 @@ func (s ImageVerificationPolicySpec) BackgroundEnabled() bool {
return *s.EvaluationConfiguration.Background.Enabled
}
func (status *IvpolStatus) SetReadyByCondition(c PolicyConditionType, s metav1.ConditionStatus, message string) {
if status.ConditionStatus == nil {
status.ConditionStatus = &ConditionStatus{}
}
reason := "Succeeded"
if s != metav1.ConditionTrue {
reason = "Failed"
}
newCondition := metav1.Condition{
Type: string(c),
Reason: reason,
Status: s,
Message: message,
}
meta.SetStatusCondition(&status.ConditionStatus.Conditions, newCondition)
}
func (status *IvpolStatus) GetConditionStatus() *ConditionStatus {
if status.ConditionStatus != nil {
return status.ConditionStatus
}
return &ConditionStatus{}
}
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View file

@ -382,10 +382,10 @@ func TestImageVerificationPolicy_GetStatus(t *testing.T) {
tests := []struct {
name string
policy *ImageVerificationPolicy
want *PolicyStatus
want *IvpolStatus
}{{
policy: &ImageVerificationPolicy{},
want: &PolicyStatus{},
want: &IvpolStatus{},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View file

@ -13,5 +13,4 @@ type GenericPolicy interface {
GetFailurePolicy() admissionregistrationv1.FailurePolicyType
GetWebhookConfiguration() *WebhookConfiguration
GetVariables() []admissionregistrationv1.Variable
GetStatus() *PolicyStatus
}

View file

@ -1,7 +1,6 @@
package v1alpha1
import (
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -14,7 +13,8 @@ const (
PolicyConditionTypeRBACPermissionsGranted PolicyConditionType = "RBACPermissionsGranted"
)
type PolicyStatus struct {
// ConditionStatus is the shared status across all policy types
type ConditionStatus struct {
// The ready of a policy is a high-level summary of where the policy is in its lifecycle.
// The conditions array, the reason and message fields contain more detail about the policy's status.
// +optional
@ -23,33 +23,13 @@ type PolicyStatus struct {
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
// +optional
Autogen AutogenStatus `json:"autogen"`
// Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy is generated from the policy or not
// +optional
Generated bool `json:"generated"`
// Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
// It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated.
// +optional
Message string `json:"message"`
}
// AutogenStatus contains autogen status information.
type AutogenStatus struct {
// Rules is a list of Rule instances. It contains auto generated rules added for pod controllers
Rules []AutogenRule `json:"rules,omitempty"`
}
type AutogenRule struct {
MatchConstraints *admissionregistrationv1.MatchResources `json:"matchConstraints,omitempty"`
MatchConditions []admissionregistrationv1.MatchCondition `json:"matchConditions,omitempty"`
Validations []admissionregistrationv1.Validation `json:"validations,omitempty"`
AuditAnnotation []admissionregistrationv1.AuditAnnotation `json:"auditAnnotations,omitempty"`
Variables []admissionregistrationv1.Variable `json:"variables,omitempty"`
}
func (status *PolicyStatus) SetReadyByCondition(c PolicyConditionType, s metav1.ConditionStatus, message string) {
func (status *ConditionStatus) SetReadyByCondition(c PolicyConditionType, s metav1.ConditionStatus, message string) {
reason := "Succeeded"
if s != metav1.ConditionTrue {
reason = "Failed"
@ -64,7 +44,7 @@ func (status *PolicyStatus) SetReadyByCondition(c PolicyConditionType, s metav1.
meta.SetStatusCondition(&status.Conditions, newCondition)
}
func (status *PolicyStatus) IsReady() bool {
func (status *ConditionStatus) IsReady() bool {
if status.Ready != nil {
return *status.Ready
}

View file

@ -12,35 +12,39 @@ import (
func TestPolicyStatus_IsReady(t *testing.T) {
tests := []struct {
name string
status PolicyStatus
status VpolStatus
want bool
}{{
name: "nil",
status: PolicyStatus{},
status: VpolStatus{},
want: false,
}, {
name: "true",
status: PolicyStatus{
status: VpolStatus{
ConditionStatus: &ConditionStatus{
Ready: ptr.To(true),
},
},
want: true,
}, {
name: "false",
status: PolicyStatus{
status: VpolStatus{
ConditionStatus: &ConditionStatus{
Ready: ptr.To(false),
},
},
want: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.status.IsReady()
got := tt.status.GetConditionStatus().IsReady()
assert.Equal(t, tt.want, got)
})
}
}
func TestPolicyStatus_SetReadyByCondition_True(t *testing.T) {
var status PolicyStatus
var status ConditionStatus
status.SetReadyByCondition(PolicyConditionTypeWebhookConfigured, metav1.ConditionTrue, "dummy")
got := meta.FindStatusCondition(status.Conditions, string(PolicyConditionTypeWebhookConfigured))
assert.NotNil(t, got)
@ -51,7 +55,7 @@ func TestPolicyStatus_SetReadyByCondition_True(t *testing.T) {
}
func TestPolicyStatus_SetReadyByCondition_False(t *testing.T) {
var status PolicyStatus
var status ConditionStatus
status.SetReadyByCondition(PolicyConditionTypeWebhookConfigured, metav1.ConditionFalse, "dummy")
got := meta.FindStatusCondition(status.Conditions, string(PolicyConditionTypeWebhookConfigured))
assert.NotNil(t, got)

View file

@ -20,7 +20,32 @@ type ValidatingPolicy struct {
Spec ValidatingPolicySpec `json:"spec"`
// Status contains policy runtime data.
// +optional
Status PolicyStatus `json:"status,omitempty"`
Status VpolStatus `json:"status,omitempty"`
}
type VpolStatus struct {
ConditionStatus *ConditionStatus `json:",inline"`
// +optional
Autogen AutogenStatus `json:"autogen"`
// Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy is generated from the policy or not
// +optional
Generated bool `json:"generated"`
}
// AutogenStatus contains autogen status information.
type AutogenStatus struct {
// Rules is a list of Rule instances. It contains auto generated rules added for pod controllers
Rules []AutogenRule `json:"rules,omitempty"`
}
type AutogenRule struct {
MatchConstraints *admissionregistrationv1.MatchResources `json:"matchConstraints,omitempty"`
MatchConditions []admissionregistrationv1.MatchCondition `json:"matchConditions,omitempty"`
Validations []admissionregistrationv1.Validation `json:"validations,omitempty"`
AuditAnnotation []admissionregistrationv1.AuditAnnotation `json:"auditAnnotations,omitempty"`
Variables []admissionregistrationv1.Variable `json:"variables,omitempty"`
}
func (s *ValidatingPolicy) GetMatchConstraints() admissionregistrationv1.MatchResources {
@ -53,7 +78,7 @@ func (s *ValidatingPolicy) GetSpec() *ValidatingPolicySpec {
return &s.Spec
}
func (s *ValidatingPolicy) GetStatus() *PolicyStatus {
func (s *ValidatingPolicy) GetStatus() *VpolStatus {
return &s.Status
}
@ -61,6 +86,13 @@ func (s *ValidatingPolicy) GetKind() string {
return "ValidatingPolicy"
}
func (status *VpolStatus) GetConditionStatus() *ConditionStatus {
if status.ConditionStatus != nil {
return status.ConditionStatus
}
return &ConditionStatus{}
}
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View file

@ -220,10 +220,10 @@ func TestValidatingPolicy_GetStatus(t *testing.T) {
tests := []struct {
name string
policy *ValidatingPolicy
want *PolicyStatus
want *VpolStatus
}{{
policy: &ValidatingPolicy{},
want: &PolicyStatus{},
want: &VpolStatus{},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View file

@ -306,6 +306,34 @@ func (in *Certificate) DeepCopy() *Certificate {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConditionStatus) DeepCopyInto(out *ConditionStatus) {
*out = *in
if in.Ready != nil {
in, out := &in.Ready, &out.Ready
*out = new(bool)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]metav1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConditionStatus.
func (in *ConditionStatus) DeepCopy() *ConditionStatus {
if in == nil {
return nil
}
out := new(ConditionStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Cosign) DeepCopyInto(out *Cosign) {
*out = *in
@ -638,6 +666,73 @@ func (in *InToto) DeepCopy() *InToto {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IvpolAutogen) DeepCopyInto(out *IvpolAutogen) {
*out = *in
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IvpolAutogen.
func (in *IvpolAutogen) DeepCopy() *IvpolAutogen {
if in == nil {
return nil
}
out := new(IvpolAutogen)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IvpolAutogenStatus) DeepCopyInto(out *IvpolAutogenStatus) {
*out = *in
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]*IvpolAutogen, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(IvpolAutogen)
(*in).DeepCopyInto(*out)
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IvpolAutogenStatus.
func (in *IvpolAutogenStatus) DeepCopy() *IvpolAutogenStatus {
if in == nil {
return nil
}
out := new(IvpolAutogenStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IvpolStatus) DeepCopyInto(out *IvpolStatus) {
*out = *in
if in.ConditionStatus != nil {
in, out := &in.ConditionStatus, &out.ConditionStatus
*out = new(ConditionStatus)
(*in).DeepCopyInto(*out)
}
in.Autogen.DeepCopyInto(&out.Autogen)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IvpolStatus.
func (in *IvpolStatus) DeepCopy() *IvpolStatus {
if in == nil {
return nil
}
out := new(IvpolStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Key) DeepCopyInto(out *Key) {
*out = *in
@ -712,35 +807,6 @@ func (in *PolicyRef) DeepCopy() *PolicyRef {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyStatus) DeepCopyInto(out *PolicyStatus) {
*out = *in
if in.Ready != nil {
in, out := &in.Ready, &out.Ready
*out = new(bool)
**out = **in
}
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]metav1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.Autogen.DeepCopyInto(&out.Autogen)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyStatus.
func (in *PolicyStatus) DeepCopy() *PolicyStatus {
if in == nil {
return nil
}
out := new(PolicyStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Referrer) DeepCopyInto(out *Referrer) {
*out = *in
@ -940,6 +1006,28 @@ func (in *ValidatingPolicySpec) DeepCopy() *ValidatingPolicySpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VpolStatus) DeepCopyInto(out *VpolStatus) {
*out = *in
if in.ConditionStatus != nil {
in, out := &in.ConditionStatus, &out.ConditionStatus
*out = new(ConditionStatus)
(*in).DeepCopyInto(*out)
}
in.Autogen.DeepCopyInto(&out.Autogen)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VpolStatus.
func (in *VpolStatus) DeepCopy() *VpolStatus {
if in == nil {
return nil
}
out := new(VpolStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
*out = *in

View file

@ -24,7 +24,14 @@ spec:
singular: imageverificationpolicy
scope: Cluster
versions:
- name: v1alpha1
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
- jsonPath: .status.ready
name: READY
type: string
name: v1alpha1
schema:
openAPIV3Schema:
properties:
@ -950,63 +957,403 @@ spec:
description: Status contains policy runtime data.
properties:
autogen:
description: AutogenStatus contains autogen status information.
properties:
rules:
description: Rules is a list of Rule instances. It contains auto
generated rules added for pod controllers
items:
properties:
auditAnnotations:
items:
description: AuditAnnotation describes how to produce
an audit annotation for an API request.
metadata:
type: object
spec:
description: ImageVerificationPolicySpec is the specification
of the desired behavior of the ImageVerificationPolicy.
properties:
key:
description: |-
key specifies the audit annotation key. The audit annotation keys of
a ValidatingAdmissionPolicy must be unique. The key must be a qualified
name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length.
The key is combined with the resource name of the
ValidatingAdmissionPolicy to construct an audit annotation key:
"{ValidatingAdmissionPolicy name}/{key}".
If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy
and the same audit annotation key, the annotation key will be identical.
In this case, the first annotation written with the key will be included
in the audit event and all subsequent annotations with the same key
will be discarded.
Required.
type: string
valueExpression:
description: |-
valueExpression represents the expression which is evaluated by CEL to
produce an audit annotation value. The expression must evaluate to either
a string or null value. If the expression evaluates to a string, the
audit annotation is included with the string value. If the expression
evaluates to null or empty string the audit annotation will be omitted.
The valueExpression may be no longer than 5kb in length.
If the result of the valueExpression is more than 10kb in length, it
will be truncated to 10kb.
If multiple ValidatingAdmissionPolicyBinding resources match an
API request, then the valueExpression will be evaluated for
each binding. All unique values produced by the valueExpressions
will be joined together in a comma-separated list.
Required.
attestations:
description: Attestations provides a list of image metadata
to verify
items:
description: Attestation defines the identification
details of the metadata that has to be verified
properties:
intoto:
description: InToto defines the details of attestation
attached using intoto format
properties:
type:
description: Type defines the type of attestation
contained within the statement.
type: string
required:
- key
- valueExpression
- type
type: object
name:
description: Name is the name for this attestation.
It is used to refer to the attestation in verification
type: string
referrer:
description: Referrer defines the details of attestation
attached using OCI 1.1 format
properties:
type:
description: Type defines the type of attestation
attached to the image.
type: string
required:
- type
type: object
required:
- name
type: object
type: array
attestors:
description: Attestors provides a list of trusted authorities.
items:
description: Attestor is an identity that confirms
or verifies the authenticity of an image or an attestation
properties:
cosign:
description: Cosign defines attestor configuration
for Cosign based signatures
properties:
annotations:
additionalProperties:
type: string
description: |-
Annotations are used for image verification.
Every specified key-value pair must exist and match in the verified payload.
The payload may contain other key-value pairs.
type: object
certificate:
description: Certificate defines the configuration
for local signature verification
properties:
cert:
description: Certificate is the to the
public certificate for local signature
verification.
type: string
certChain:
description: |-
CertificateChain is the list of CA certificates in PEM format which will be needed
when building the certificate chain for the signing certificate. Must start with the
parent intermediate CA certificate of the signing certificate and end with the root certificate
type: string
type: object
ctlog:
description: CTLog sets the configuration
to verify the authority against a Rekor
instance.
properties:
ctLogPubKey:
description: CTLogPubKey, if set, is used
to validate SCTs against a custom source.
type: string
insecureIgnoreSCT:
description: |-
IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate
timestamp. Default is false. Set to true if this was opted out during signing.
type: boolean
insecureIgnoreTlog:
description: InsecureIgnoreTlog skips
transparency log verification.
type: boolean
rekorPubKey:
description: |-
RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor.
If set, this will be used to validate transparency log signatures from a custom Rekor.
type: string
tsaCertChain:
description: |-
TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must
contain the root CA certificate. Optionally may contain intermediate CA certificates, and
may contain the leaf TSA certificate if not present in the timestamurce.
type: string
url:
description: URL sets the url to the rekor
instance (by default the public rekor.sigstore.dev)
type: string
type: object
key:
description: Key defines the type of key to
validate the image.
properties:
data:
description: Data contains the inline
public key
type: string
hashAlgorithm:
description: |-
HashAlgorithm specifues signature algorithm for public keys. Supported values are
sha224, sha256, sha384 and sha512. Defaults to sha256.
type: string
kms:
description: |-
KMS contains the KMS url of the public key
Supported formats differ based on the KMS system used.
type: string
secretRef:
description: SecretRef sets a reference
to a secret with the key.
properties:
name:
description: name is unique within
a namespace to reference a secret
resource.
type: string
namespace:
description: namespace defines the
space within which the secret name
must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
type: object
keyless:
description: Keyless sets the configuration
to verify the authority against a Fulcio
instance.
properties:
identities:
description: Identities sets a list of
identities.
items:
description: |-
Identity may contain the issuer and/or the subject found in the transparency
log.
Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp
apply a regexp for matching.
properties:
issuer:
description: Issuer defines the
issuer for this identity.
type: string
issuerRegExp:
description: IssuerRegExp specifies
a regular expression to match
the issuer for this identity.
type: string
subject:
description: Subject defines the
subject for this identity.
type: string
subjectRegExp:
description: SubjectRegExp specifies
a regular expression to match
the subject for this identity.
type: string
type: object
type: array
roots:
description: |-
Roots is an optional set of PEM encoded trusted root certificates.
If not provided, the system roots are used.
type: string
required:
- identities
type: object
source:
description: Sources sets the configuration
to specify the sources from where to consume
the signature and attestations.
properties:
PullSecrets:
description: |-
SignaturePullSecrets is an optional list of references to secrets in the
same namespace as the deploying resource for pulling any of the signatures
used by this Source.
items:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
type: object
x-kubernetes-map-type: atomic
type: array
repository:
description: Repository defines the location
from where to pull the signature / attestations.
type: string
tagPrefix:
description: |-
TagPrefix is an optional prefix that signature and attestations have.
This is the 'tag based discovery' and in the future once references are
fully supported that should likely be the preferred way to handle these.
type: string
type: object
tuf:
description: TUF defines the configuration
to fetch sigstore root
properties:
mirror:
description: Mirror is the base URL of
Sigstore TUF repository
type: string
root:
description: Root defines the path or
data of the trusted root
properties:
data:
description: Data is the base64 encoded
TUF root
type: string
path:
description: Path is the URL or File
location of the TUF root
type: string
type: object
type: object
type: object
name:
description: Name is the name for this attestor.
It is used to refer to the attestor in verification
type: string
notary:
description: Notary defines attestor configuration
for Notary based signatures
properties:
certs:
description: Certs define the cert chain for
Notary signature verification
type: string
tsaCerts:
description: TSACerts define the cert chain
for verifying timestamps of notary signature
type: string
required:
- certs
type: object
required:
- name
type: object
type: array
credentials:
description: Credentials provides credentials that will
be used for authentication with registry.
properties:
allowInsecureRegistry:
description: AllowInsecureRegistry allows insecure
access to a registry.
type: boolean
providers:
description: |-
Providers specifies a list of OCI Registry names, whose authentication providers are provided.
It can be of one of these values: default,google,azure,amazon,github.
items:
description: CredentialsProvidersType provides
the list of credential providers required.
enum:
- default
- amazon
- azure
- google
- github
type: string
type: array
secrets:
description: |-
Secrets specifies a list of secrets that are provided for credentials.
Secrets must live in the Kyverno namespace.
items:
type: string
type: array
type: object
evaluation:
description: EvaluationConfiguration defines the configuration
for the policy evaluation.
properties:
admission:
description: Admission controls policy evaluation
during admission.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied during admission.
Optional. Default value is "true".
type: boolean
type: object
background:
description: Background controls policy evaluation
during background scan.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied to existing resources during a background scan.
Optional. Default value is "true". The value must be set to "false" if the policy rule
uses variables that are only available in the admission review request (e.g. user name).
type: boolean
type: object
mode:
description: |-
Mode is the mode of policy evaluation.
Allowed values are "Kubernetes" or "JSON".
Optional. Default value is "Kubernetes".
type: string
type: object
failurePolicy:
description: |-
FailurePolicy defines how to handle failures for the admission policy. Failures can
occur from CEL expression parse errors, type check errors, runtime errors and invalid
or mis-configured policy definitions or bindings.
type: string
imageRules:
description: |-
ImagesRules is a list of Glob and CELExpressions to match images.
Any image that matches one of the rules is considered for validation
Any image that does not match a rule is skipped, even when they are passed as arguments to
image verification functions
items:
description: ImageRule defines a Glob or a CEL expression
for matching images
properties:
cel:
description: Cel defines CEL Expressions for matching
images
type: string
glob:
description: Glob defines a globbing pattern for
matching images
type: string
type: object
type: array
images:
description: Images is a list of CEL expression to extract
images from the resource
items:
properties:
expression:
description: Expression defines CEL expression
to extact images from the resource.
type: string
name:
description: Name is the name for this imageList.
It is used to refer to the images in verification
block as images.<name>
type: string
required:
- expression
- name
type: object
type: array
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be validated.
Match conditions filter requests that have already been matched by the rules,
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
There are a maximum of 64 match conditions allowed.
items:
description: MatchCondition represents a condition which
must by fulfilled for a request to be sent to a webhook.
description: MatchCondition represents a condition
which must by fulfilled for a request to be sent
to a webhook.
properties:
expression:
description: |-
@ -1042,18 +1389,16 @@ spec:
type: object
type: array
matchConstraints:
description: |-
MatchResources decides whether to run the admission control policy on an object based
on whether it meets the match criteria.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
description: MatchConstraints specifies what resources
this policy is designed to validate.
properties:
excludeResourceRules:
description: |-
ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1080,15 +1425,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1194,15 +1540,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1251,15 +1598,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1297,8 +1645,8 @@ spec:
ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches.
The policy cares about an operation if it matches _any_ Rule.
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1325,15 +1673,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1376,33 +1725,84 @@ spec:
x-kubernetes-list-type: atomic
type: object
x-kubernetes-map-type: atomic
validations:
mutateDigest:
default: true
description: |-
MutateDigest enables replacement of image tags with digests.
Defaults to true.
type: boolean
required:
default: true
description: Required validates that images are verified
i.e. have matched passed a signature or attestation
check.
type: boolean
validationActions:
description: |-
ValidationAction specifies the action to be taken when the matched resource violates the policy.
Required.
items:
description: Validation specifies the CEL expression which
is used to apply the validation.
description: ValidationAction specifies a policy enforcement
action.
type: string
type: array
x-kubernetes-list-type: set
variables:
description: |-
Variables contain definitions of variables that can be used in composition of other expressions.
Each variable is defined as a named CEL expression.
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
properties:
expression:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
type: object
x-kubernetes-map-type: atomic
type: array
verifications:
description: Verifications contain CEL expressions which
is used to apply the image verification checks.
items:
description: Validation specifies the CEL expression
which is used to apply the validation.
properties:
expression:
description: "Expression represents the expression
which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL
expressions have access to the contents of the API
request/response, organized into CEL variables as
well as some other useful variables:\n\n- 'object'
- The object from the incoming request. The value
is null for DELETE requests.\n- 'oldObject' - The
existing object. The value is null for CREATE requests.\n-
'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by the
policy binding being evaluated. Only populated if
the policy has a ParamKind.\n- 'namespaceObject'
expressions have access to the contents of the
API request/response, organized into CEL variables
as well as some other useful variables:\n\n-
'object' - The object from the incoming request.
The value is null for DELETE requests.\n- 'oldObject'
- The existing object. The value is null for
CREATE requests.\n- 'request' - Attributes of
the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by
the policy binding being evaluated. Only populated
if the policy has a ParamKind.\n- 'namespaceObject'
- The namespace object that the incoming object
belongs to. The value is null for cluster-scoped
resources.\n- 'variables' - Map of composited variables,
from its name to its lazily evaluated value.\n For
example, a variable named 'foo' can be accessed
as 'variables.foo'.\n- 'authorizer' - A CEL Authorizer.
May be used to perform authorization checks for
the principal (user or service account) of the request.\n
\ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
resources.\n- 'variables' - Map of composited
variables, from its name to its lazily evaluated
value.\n For example, a variable named 'foo'
can be accessed as 'variables.foo'.\n- 'authorizer'
- A CEL Authorizer. May be used to perform authorization
checks for the principal (user or service account)
of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
'authorizer.requestResource' - A CEL ResourceCheck
constructed from the 'authorizer' and configured
with the\n request resource.\n\nThe `apiVersion`,
@ -1410,35 +1810,39 @@ spec:
are always accessible from the root of the\nobject.
No other metadata properties are accessible.\n\nOnly
property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`
are accessible.\nAccessible property names are escaped
according to the following rules when accessed in
the expression:\n- '__' escapes to '__underscores__'\n-
'.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n-
'/' escapes to '__slash__'\n- Property names that
exactly match a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\", \"null\",
\"in\", \"as\", \"break\", \"const\", \"continue\",
\"else\", \"for\", \"function\", \"if\",\n\t \"import\",
\"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n
are accessible.\nAccessible property names are
escaped according to the following rules when
accessed in the expression:\n- '__' escapes
to '__underscores__'\n- '.' escapes to '__dot__'\n-
'-' escapes to '__dash__'\n- '/' escapes to
'__slash__'\n- Property names that exactly match
a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\",
\"null\", \"in\", \"as\", \"break\", \"const\",
\"continue\", \"else\", \"for\", \"function\",
\"if\",\n\t \"import\", \"let\", \"loop\",
\"package\", \"namespace\", \"return\".\nExamples:\n
\ - Expression accessing a property named \"namespace\":
{\"Expression\": \"object.__namespace__ > 0\"}\n
\ - Expression accessing a property named \"x-prop\":
{\"Expression\": \"object.x__dash__prop > 0\"}\n
\ - Expression accessing a property named \"redact__d\":
{\"Expression\": \"object.redact__underscores__d
> 0\"}\n\nEquality on arrays with list type of 'set'
or 'map' ignores element order, i.e. [1, 2] == [2,
1].\nConcatenation on arrays with x-kubernetes-list-type
use the semantics of the list type:\n - 'set':
`X + Y` performs a union where the array positions
of all elements in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their partial
order.\n - 'map': `X + Y` performs a merge where
the array positions of all keys in `X` are preserved
but the values\n are overwritten by values in
`Y` when the key sets of `X` and `Y` intersect.
Elements in `Y` with\n non-intersecting keys
are appended, retaining their partial order.\nRequired."
> 0\"}\n\nEquality on arrays with list type
of 'set' or 'map' ignores element order, i.e.
[1, 2] == [2, 1].\nConcatenation on arrays with
x-kubernetes-list-type use the semantics of
the list type:\n - 'set': `X + Y` performs
a union where the array positions of all elements
in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their
partial order.\n - 'map': `X + Y` performs
a merge where the array positions of all keys
in `X` are preserved but the values\n are
overwritten by values in `Y` when the key sets
of `X` and `Y` intersect. Elements in `Y` with\n
\ non-intersecting keys are appended, retaining
their partial order.\nRequired."
type: string
message:
description: |-
@ -1476,29 +1880,30 @@ spec:
- expression
type: object
type: array
variables:
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
x-kubernetes-list-type: atomic
verifyDigest:
default: true
description: VerifyDigest validates that images have
a digest.
type: boolean
webhookConfiguration:
description: WebhookConfiguration defines the configuration
for the webhook.
properties:
expression:
timeoutSeconds:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy.
After the configured time expires, the admission request may fail, or may simply ignore the policy results,
based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds.
format: int32
type: integer
type: object
x-kubernetes-map-type: atomic
type: array
required:
- attestors
- verifications
type: object
required:
- spec
type: object
type: array
type: object
@ -1558,10 +1963,6 @@ spec:
- type
type: object
type: array
generated:
description: Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy
is generated from the policy or not
type: boolean
message:
description: |-
Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
@ -1572,12 +1973,12 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}

View file

@ -1334,8 +1334,6 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec

View file

@ -18,7 +18,14 @@ spec:
singular: imageverificationpolicy
scope: Cluster
versions:
- name: v1alpha1
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
- jsonPath: .status.ready
name: READY
type: string
name: v1alpha1
schema:
openAPIV3Schema:
properties:
@ -944,63 +951,403 @@ spec:
description: Status contains policy runtime data.
properties:
autogen:
description: AutogenStatus contains autogen status information.
properties:
rules:
description: Rules is a list of Rule instances. It contains auto
generated rules added for pod controllers
items:
properties:
auditAnnotations:
items:
description: AuditAnnotation describes how to produce
an audit annotation for an API request.
metadata:
type: object
spec:
description: ImageVerificationPolicySpec is the specification
of the desired behavior of the ImageVerificationPolicy.
properties:
key:
description: |-
key specifies the audit annotation key. The audit annotation keys of
a ValidatingAdmissionPolicy must be unique. The key must be a qualified
name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length.
The key is combined with the resource name of the
ValidatingAdmissionPolicy to construct an audit annotation key:
"{ValidatingAdmissionPolicy name}/{key}".
If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy
and the same audit annotation key, the annotation key will be identical.
In this case, the first annotation written with the key will be included
in the audit event and all subsequent annotations with the same key
will be discarded.
Required.
type: string
valueExpression:
description: |-
valueExpression represents the expression which is evaluated by CEL to
produce an audit annotation value. The expression must evaluate to either
a string or null value. If the expression evaluates to a string, the
audit annotation is included with the string value. If the expression
evaluates to null or empty string the audit annotation will be omitted.
The valueExpression may be no longer than 5kb in length.
If the result of the valueExpression is more than 10kb in length, it
will be truncated to 10kb.
If multiple ValidatingAdmissionPolicyBinding resources match an
API request, then the valueExpression will be evaluated for
each binding. All unique values produced by the valueExpressions
will be joined together in a comma-separated list.
Required.
attestations:
description: Attestations provides a list of image metadata
to verify
items:
description: Attestation defines the identification
details of the metadata that has to be verified
properties:
intoto:
description: InToto defines the details of attestation
attached using intoto format
properties:
type:
description: Type defines the type of attestation
contained within the statement.
type: string
required:
- key
- valueExpression
- type
type: object
name:
description: Name is the name for this attestation.
It is used to refer to the attestation in verification
type: string
referrer:
description: Referrer defines the details of attestation
attached using OCI 1.1 format
properties:
type:
description: Type defines the type of attestation
attached to the image.
type: string
required:
- type
type: object
required:
- name
type: object
type: array
attestors:
description: Attestors provides a list of trusted authorities.
items:
description: Attestor is an identity that confirms
or verifies the authenticity of an image or an attestation
properties:
cosign:
description: Cosign defines attestor configuration
for Cosign based signatures
properties:
annotations:
additionalProperties:
type: string
description: |-
Annotations are used for image verification.
Every specified key-value pair must exist and match in the verified payload.
The payload may contain other key-value pairs.
type: object
certificate:
description: Certificate defines the configuration
for local signature verification
properties:
cert:
description: Certificate is the to the
public certificate for local signature
verification.
type: string
certChain:
description: |-
CertificateChain is the list of CA certificates in PEM format which will be needed
when building the certificate chain for the signing certificate. Must start with the
parent intermediate CA certificate of the signing certificate and end with the root certificate
type: string
type: object
ctlog:
description: CTLog sets the configuration
to verify the authority against a Rekor
instance.
properties:
ctLogPubKey:
description: CTLogPubKey, if set, is used
to validate SCTs against a custom source.
type: string
insecureIgnoreSCT:
description: |-
IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate
timestamp. Default is false. Set to true if this was opted out during signing.
type: boolean
insecureIgnoreTlog:
description: InsecureIgnoreTlog skips
transparency log verification.
type: boolean
rekorPubKey:
description: |-
RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor.
If set, this will be used to validate transparency log signatures from a custom Rekor.
type: string
tsaCertChain:
description: |-
TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must
contain the root CA certificate. Optionally may contain intermediate CA certificates, and
may contain the leaf TSA certificate if not present in the timestamurce.
type: string
url:
description: URL sets the url to the rekor
instance (by default the public rekor.sigstore.dev)
type: string
type: object
key:
description: Key defines the type of key to
validate the image.
properties:
data:
description: Data contains the inline
public key
type: string
hashAlgorithm:
description: |-
HashAlgorithm specifues signature algorithm for public keys. Supported values are
sha224, sha256, sha384 and sha512. Defaults to sha256.
type: string
kms:
description: |-
KMS contains the KMS url of the public key
Supported formats differ based on the KMS system used.
type: string
secretRef:
description: SecretRef sets a reference
to a secret with the key.
properties:
name:
description: name is unique within
a namespace to reference a secret
resource.
type: string
namespace:
description: namespace defines the
space within which the secret name
must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
type: object
keyless:
description: Keyless sets the configuration
to verify the authority against a Fulcio
instance.
properties:
identities:
description: Identities sets a list of
identities.
items:
description: |-
Identity may contain the issuer and/or the subject found in the transparency
log.
Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp
apply a regexp for matching.
properties:
issuer:
description: Issuer defines the
issuer for this identity.
type: string
issuerRegExp:
description: IssuerRegExp specifies
a regular expression to match
the issuer for this identity.
type: string
subject:
description: Subject defines the
subject for this identity.
type: string
subjectRegExp:
description: SubjectRegExp specifies
a regular expression to match
the subject for this identity.
type: string
type: object
type: array
roots:
description: |-
Roots is an optional set of PEM encoded trusted root certificates.
If not provided, the system roots are used.
type: string
required:
- identities
type: object
source:
description: Sources sets the configuration
to specify the sources from where to consume
the signature and attestations.
properties:
PullSecrets:
description: |-
SignaturePullSecrets is an optional list of references to secrets in the
same namespace as the deploying resource for pulling any of the signatures
used by this Source.
items:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
type: object
x-kubernetes-map-type: atomic
type: array
repository:
description: Repository defines the location
from where to pull the signature / attestations.
type: string
tagPrefix:
description: |-
TagPrefix is an optional prefix that signature and attestations have.
This is the 'tag based discovery' and in the future once references are
fully supported that should likely be the preferred way to handle these.
type: string
type: object
tuf:
description: TUF defines the configuration
to fetch sigstore root
properties:
mirror:
description: Mirror is the base URL of
Sigstore TUF repository
type: string
root:
description: Root defines the path or
data of the trusted root
properties:
data:
description: Data is the base64 encoded
TUF root
type: string
path:
description: Path is the URL or File
location of the TUF root
type: string
type: object
type: object
type: object
name:
description: Name is the name for this attestor.
It is used to refer to the attestor in verification
type: string
notary:
description: Notary defines attestor configuration
for Notary based signatures
properties:
certs:
description: Certs define the cert chain for
Notary signature verification
type: string
tsaCerts:
description: TSACerts define the cert chain
for verifying timestamps of notary signature
type: string
required:
- certs
type: object
required:
- name
type: object
type: array
credentials:
description: Credentials provides credentials that will
be used for authentication with registry.
properties:
allowInsecureRegistry:
description: AllowInsecureRegistry allows insecure
access to a registry.
type: boolean
providers:
description: |-
Providers specifies a list of OCI Registry names, whose authentication providers are provided.
It can be of one of these values: default,google,azure,amazon,github.
items:
description: CredentialsProvidersType provides
the list of credential providers required.
enum:
- default
- amazon
- azure
- google
- github
type: string
type: array
secrets:
description: |-
Secrets specifies a list of secrets that are provided for credentials.
Secrets must live in the Kyverno namespace.
items:
type: string
type: array
type: object
evaluation:
description: EvaluationConfiguration defines the configuration
for the policy evaluation.
properties:
admission:
description: Admission controls policy evaluation
during admission.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied during admission.
Optional. Default value is "true".
type: boolean
type: object
background:
description: Background controls policy evaluation
during background scan.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied to existing resources during a background scan.
Optional. Default value is "true". The value must be set to "false" if the policy rule
uses variables that are only available in the admission review request (e.g. user name).
type: boolean
type: object
mode:
description: |-
Mode is the mode of policy evaluation.
Allowed values are "Kubernetes" or "JSON".
Optional. Default value is "Kubernetes".
type: string
type: object
failurePolicy:
description: |-
FailurePolicy defines how to handle failures for the admission policy. Failures can
occur from CEL expression parse errors, type check errors, runtime errors and invalid
or mis-configured policy definitions or bindings.
type: string
imageRules:
description: |-
ImagesRules is a list of Glob and CELExpressions to match images.
Any image that matches one of the rules is considered for validation
Any image that does not match a rule is skipped, even when they are passed as arguments to
image verification functions
items:
description: ImageRule defines a Glob or a CEL expression
for matching images
properties:
cel:
description: Cel defines CEL Expressions for matching
images
type: string
glob:
description: Glob defines a globbing pattern for
matching images
type: string
type: object
type: array
images:
description: Images is a list of CEL expression to extract
images from the resource
items:
properties:
expression:
description: Expression defines CEL expression
to extact images from the resource.
type: string
name:
description: Name is the name for this imageList.
It is used to refer to the images in verification
block as images.<name>
type: string
required:
- expression
- name
type: object
type: array
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be validated.
Match conditions filter requests that have already been matched by the rules,
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
There are a maximum of 64 match conditions allowed.
items:
description: MatchCondition represents a condition which
must by fulfilled for a request to be sent to a webhook.
description: MatchCondition represents a condition
which must by fulfilled for a request to be sent
to a webhook.
properties:
expression:
description: |-
@ -1036,18 +1383,16 @@ spec:
type: object
type: array
matchConstraints:
description: |-
MatchResources decides whether to run the admission control policy on an object based
on whether it meets the match criteria.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
description: MatchConstraints specifies what resources
this policy is designed to validate.
properties:
excludeResourceRules:
description: |-
ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1074,15 +1419,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1188,15 +1534,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1245,15 +1592,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1291,8 +1639,8 @@ spec:
ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches.
The policy cares about an operation if it matches _any_ Rule.
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1319,15 +1667,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1370,33 +1719,84 @@ spec:
x-kubernetes-list-type: atomic
type: object
x-kubernetes-map-type: atomic
validations:
mutateDigest:
default: true
description: |-
MutateDigest enables replacement of image tags with digests.
Defaults to true.
type: boolean
required:
default: true
description: Required validates that images are verified
i.e. have matched passed a signature or attestation
check.
type: boolean
validationActions:
description: |-
ValidationAction specifies the action to be taken when the matched resource violates the policy.
Required.
items:
description: Validation specifies the CEL expression which
is used to apply the validation.
description: ValidationAction specifies a policy enforcement
action.
type: string
type: array
x-kubernetes-list-type: set
variables:
description: |-
Variables contain definitions of variables that can be used in composition of other expressions.
Each variable is defined as a named CEL expression.
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
properties:
expression:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
type: object
x-kubernetes-map-type: atomic
type: array
verifications:
description: Verifications contain CEL expressions which
is used to apply the image verification checks.
items:
description: Validation specifies the CEL expression
which is used to apply the validation.
properties:
expression:
description: "Expression represents the expression
which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL
expressions have access to the contents of the API
request/response, organized into CEL variables as
well as some other useful variables:\n\n- 'object'
- The object from the incoming request. The value
is null for DELETE requests.\n- 'oldObject' - The
existing object. The value is null for CREATE requests.\n-
'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by the
policy binding being evaluated. Only populated if
the policy has a ParamKind.\n- 'namespaceObject'
expressions have access to the contents of the
API request/response, organized into CEL variables
as well as some other useful variables:\n\n-
'object' - The object from the incoming request.
The value is null for DELETE requests.\n- 'oldObject'
- The existing object. The value is null for
CREATE requests.\n- 'request' - Attributes of
the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by
the policy binding being evaluated. Only populated
if the policy has a ParamKind.\n- 'namespaceObject'
- The namespace object that the incoming object
belongs to. The value is null for cluster-scoped
resources.\n- 'variables' - Map of composited variables,
from its name to its lazily evaluated value.\n For
example, a variable named 'foo' can be accessed
as 'variables.foo'.\n- 'authorizer' - A CEL Authorizer.
May be used to perform authorization checks for
the principal (user or service account) of the request.\n
\ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
resources.\n- 'variables' - Map of composited
variables, from its name to its lazily evaluated
value.\n For example, a variable named 'foo'
can be accessed as 'variables.foo'.\n- 'authorizer'
- A CEL Authorizer. May be used to perform authorization
checks for the principal (user or service account)
of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
'authorizer.requestResource' - A CEL ResourceCheck
constructed from the 'authorizer' and configured
with the\n request resource.\n\nThe `apiVersion`,
@ -1404,35 +1804,39 @@ spec:
are always accessible from the root of the\nobject.
No other metadata properties are accessible.\n\nOnly
property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`
are accessible.\nAccessible property names are escaped
according to the following rules when accessed in
the expression:\n- '__' escapes to '__underscores__'\n-
'.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n-
'/' escapes to '__slash__'\n- Property names that
exactly match a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\", \"null\",
\"in\", \"as\", \"break\", \"const\", \"continue\",
\"else\", \"for\", \"function\", \"if\",\n\t \"import\",
\"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n
are accessible.\nAccessible property names are
escaped according to the following rules when
accessed in the expression:\n- '__' escapes
to '__underscores__'\n- '.' escapes to '__dot__'\n-
'-' escapes to '__dash__'\n- '/' escapes to
'__slash__'\n- Property names that exactly match
a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\",
\"null\", \"in\", \"as\", \"break\", \"const\",
\"continue\", \"else\", \"for\", \"function\",
\"if\",\n\t \"import\", \"let\", \"loop\",
\"package\", \"namespace\", \"return\".\nExamples:\n
\ - Expression accessing a property named \"namespace\":
{\"Expression\": \"object.__namespace__ > 0\"}\n
\ - Expression accessing a property named \"x-prop\":
{\"Expression\": \"object.x__dash__prop > 0\"}\n
\ - Expression accessing a property named \"redact__d\":
{\"Expression\": \"object.redact__underscores__d
> 0\"}\n\nEquality on arrays with list type of 'set'
or 'map' ignores element order, i.e. [1, 2] == [2,
1].\nConcatenation on arrays with x-kubernetes-list-type
use the semantics of the list type:\n - 'set':
`X + Y` performs a union where the array positions
of all elements in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their partial
order.\n - 'map': `X + Y` performs a merge where
the array positions of all keys in `X` are preserved
but the values\n are overwritten by values in
`Y` when the key sets of `X` and `Y` intersect.
Elements in `Y` with\n non-intersecting keys
are appended, retaining their partial order.\nRequired."
> 0\"}\n\nEquality on arrays with list type
of 'set' or 'map' ignores element order, i.e.
[1, 2] == [2, 1].\nConcatenation on arrays with
x-kubernetes-list-type use the semantics of
the list type:\n - 'set': `X + Y` performs
a union where the array positions of all elements
in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their
partial order.\n - 'map': `X + Y` performs
a merge where the array positions of all keys
in `X` are preserved but the values\n are
overwritten by values in `Y` when the key sets
of `X` and `Y` intersect. Elements in `Y` with\n
\ non-intersecting keys are appended, retaining
their partial order.\nRequired."
type: string
message:
description: |-
@ -1470,29 +1874,30 @@ spec:
- expression
type: object
type: array
variables:
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
x-kubernetes-list-type: atomic
verifyDigest:
default: true
description: VerifyDigest validates that images have
a digest.
type: boolean
webhookConfiguration:
description: WebhookConfiguration defines the configuration
for the webhook.
properties:
expression:
timeoutSeconds:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy.
After the configured time expires, the admission request may fail, or may simply ignore the policy results,
based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds.
format: int32
type: integer
type: object
x-kubernetes-map-type: atomic
type: array
required:
- attestors
- verifications
type: object
required:
- spec
type: object
type: array
type: object
@ -1552,10 +1957,6 @@ spec:
- type
type: object
type: array
generated:
description: Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy
is generated from the policy or not
type: boolean
message:
description: |-
Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
@ -1566,11 +1967,11 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View file

@ -1328,8 +1328,6 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec

View file

@ -50,6 +50,7 @@ import (
webhooksglobalcontext "github.com/kyverno/kyverno/pkg/webhooks/globalcontext"
webhookspolicy "github.com/kyverno/kyverno/pkg/webhooks/policy"
webhooksresource "github.com/kyverno/kyverno/pkg/webhooks/resource"
"github.com/kyverno/kyverno/pkg/webhooks/resource/ivpol"
"github.com/kyverno/kyverno/pkg/webhooks/resource/vpol"
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
@ -605,7 +606,8 @@ func main() {
setup.Logger.Error(err, "failed to create cel context provider")
os.Exit(1)
}
var celEngine celengine.Engine
var vpolEngine celengine.Engine
var ivpolEngine celengine.ImageVerifyEngine
{
// create a controller manager
scheme := kruntime.NewScheme()
@ -644,7 +646,7 @@ func main() {
setup.Logger.Error(err, "failed to create policy provider")
os.Exit(1)
}
celEngine = celengine.NewEngine(
vpolEngine = celengine.NewEngine(
provider.CompiledValidationPolicies,
func(name string) *corev1.Namespace {
ns, err := setup.KubeClient.CoreV1().Namespaces().Get(context.TODO(), name, metav1.GetOptions{})
@ -655,6 +657,19 @@ func main() {
},
matching.NewMatcher(),
)
ivpolEngine = celengine.NewImageVerifyEngine(
provider.ImageVerificationPolicies,
func(name string) *corev1.Namespace {
ns, err := setup.KubeClient.CoreV1().Namespaces().Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil
}
return ns
},
matching.NewMatcher(),
setup.KubeClient.CoreV1().Secrets(""),
nil,
)
}
ephrs, err := breaker.StartAdmissionReportsCounter(signalCtx, setup.MetadataClient)
if err != nil {
@ -691,11 +706,15 @@ func main() {
reportsBreaker,
)
voplHandlers := vpol.New(
celEngine,
vpolEngine,
contextProvider,
setup.KyvernoClient,
reportsBreaker,
)
ivpolHandlers := ivpol.New(
ivpolEngine,
contextProvider,
)
exceptionHandlers := webhooksexception.NewHandlers(exception.ValidationOptions{
Enabled: internal.PolicyExceptionEnabled(),
Namespace: internal.ExceptionNamespace(),
@ -715,6 +734,7 @@ func main() {
Mutation: webhooks.HandlerFunc(resourceHandlers.Mutate),
Validation: webhooks.HandlerFunc(resourceHandlers.Validate),
ValidatingPolicies: webhooks.HandlerFunc(voplHandlers.Validate),
ImageVerificationPolicies: webhooks.HandlerFunc(ivpolHandlers.Validate),
},
webhooks.ExceptionHandlers{
Validation: webhooks.HandlerFunc(exceptionHandlers.Validate),

View file

@ -18,7 +18,14 @@ spec:
singular: imageverificationpolicy
scope: Cluster
versions:
- name: v1alpha1
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
- jsonPath: .status.ready
name: READY
type: string
name: v1alpha1
schema:
openAPIV3Schema:
properties:
@ -944,63 +951,403 @@ spec:
description: Status contains policy runtime data.
properties:
autogen:
description: AutogenStatus contains autogen status information.
properties:
rules:
description: Rules is a list of Rule instances. It contains auto
generated rules added for pod controllers
items:
properties:
auditAnnotations:
items:
description: AuditAnnotation describes how to produce
an audit annotation for an API request.
metadata:
type: object
spec:
description: ImageVerificationPolicySpec is the specification
of the desired behavior of the ImageVerificationPolicy.
properties:
key:
description: |-
key specifies the audit annotation key. The audit annotation keys of
a ValidatingAdmissionPolicy must be unique. The key must be a qualified
name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length.
The key is combined with the resource name of the
ValidatingAdmissionPolicy to construct an audit annotation key:
"{ValidatingAdmissionPolicy name}/{key}".
If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy
and the same audit annotation key, the annotation key will be identical.
In this case, the first annotation written with the key will be included
in the audit event and all subsequent annotations with the same key
will be discarded.
Required.
type: string
valueExpression:
description: |-
valueExpression represents the expression which is evaluated by CEL to
produce an audit annotation value. The expression must evaluate to either
a string or null value. If the expression evaluates to a string, the
audit annotation is included with the string value. If the expression
evaluates to null or empty string the audit annotation will be omitted.
The valueExpression may be no longer than 5kb in length.
If the result of the valueExpression is more than 10kb in length, it
will be truncated to 10kb.
If multiple ValidatingAdmissionPolicyBinding resources match an
API request, then the valueExpression will be evaluated for
each binding. All unique values produced by the valueExpressions
will be joined together in a comma-separated list.
Required.
attestations:
description: Attestations provides a list of image metadata
to verify
items:
description: Attestation defines the identification
details of the metadata that has to be verified
properties:
intoto:
description: InToto defines the details of attestation
attached using intoto format
properties:
type:
description: Type defines the type of attestation
contained within the statement.
type: string
required:
- key
- valueExpression
- type
type: object
name:
description: Name is the name for this attestation.
It is used to refer to the attestation in verification
type: string
referrer:
description: Referrer defines the details of attestation
attached using OCI 1.1 format
properties:
type:
description: Type defines the type of attestation
attached to the image.
type: string
required:
- type
type: object
required:
- name
type: object
type: array
attestors:
description: Attestors provides a list of trusted authorities.
items:
description: Attestor is an identity that confirms
or verifies the authenticity of an image or an attestation
properties:
cosign:
description: Cosign defines attestor configuration
for Cosign based signatures
properties:
annotations:
additionalProperties:
type: string
description: |-
Annotations are used for image verification.
Every specified key-value pair must exist and match in the verified payload.
The payload may contain other key-value pairs.
type: object
certificate:
description: Certificate defines the configuration
for local signature verification
properties:
cert:
description: Certificate is the to the
public certificate for local signature
verification.
type: string
certChain:
description: |-
CertificateChain is the list of CA certificates in PEM format which will be needed
when building the certificate chain for the signing certificate. Must start with the
parent intermediate CA certificate of the signing certificate and end with the root certificate
type: string
type: object
ctlog:
description: CTLog sets the configuration
to verify the authority against a Rekor
instance.
properties:
ctLogPubKey:
description: CTLogPubKey, if set, is used
to validate SCTs against a custom source.
type: string
insecureIgnoreSCT:
description: |-
IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate
timestamp. Default is false. Set to true if this was opted out during signing.
type: boolean
insecureIgnoreTlog:
description: InsecureIgnoreTlog skips
transparency log verification.
type: boolean
rekorPubKey:
description: |-
RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor.
If set, this will be used to validate transparency log signatures from a custom Rekor.
type: string
tsaCertChain:
description: |-
TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must
contain the root CA certificate. Optionally may contain intermediate CA certificates, and
may contain the leaf TSA certificate if not present in the timestamurce.
type: string
url:
description: URL sets the url to the rekor
instance (by default the public rekor.sigstore.dev)
type: string
type: object
key:
description: Key defines the type of key to
validate the image.
properties:
data:
description: Data contains the inline
public key
type: string
hashAlgorithm:
description: |-
HashAlgorithm specifues signature algorithm for public keys. Supported values are
sha224, sha256, sha384 and sha512. Defaults to sha256.
type: string
kms:
description: |-
KMS contains the KMS url of the public key
Supported formats differ based on the KMS system used.
type: string
secretRef:
description: SecretRef sets a reference
to a secret with the key.
properties:
name:
description: name is unique within
a namespace to reference a secret
resource.
type: string
namespace:
description: namespace defines the
space within which the secret name
must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
type: object
keyless:
description: Keyless sets the configuration
to verify the authority against a Fulcio
instance.
properties:
identities:
description: Identities sets a list of
identities.
items:
description: |-
Identity may contain the issuer and/or the subject found in the transparency
log.
Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp
apply a regexp for matching.
properties:
issuer:
description: Issuer defines the
issuer for this identity.
type: string
issuerRegExp:
description: IssuerRegExp specifies
a regular expression to match
the issuer for this identity.
type: string
subject:
description: Subject defines the
subject for this identity.
type: string
subjectRegExp:
description: SubjectRegExp specifies
a regular expression to match
the subject for this identity.
type: string
type: object
type: array
roots:
description: |-
Roots is an optional set of PEM encoded trusted root certificates.
If not provided, the system roots are used.
type: string
required:
- identities
type: object
source:
description: Sources sets the configuration
to specify the sources from where to consume
the signature and attestations.
properties:
PullSecrets:
description: |-
SignaturePullSecrets is an optional list of references to secrets in the
same namespace as the deploying resource for pulling any of the signatures
used by this Source.
items:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
type: object
x-kubernetes-map-type: atomic
type: array
repository:
description: Repository defines the location
from where to pull the signature / attestations.
type: string
tagPrefix:
description: |-
TagPrefix is an optional prefix that signature and attestations have.
This is the 'tag based discovery' and in the future once references are
fully supported that should likely be the preferred way to handle these.
type: string
type: object
tuf:
description: TUF defines the configuration
to fetch sigstore root
properties:
mirror:
description: Mirror is the base URL of
Sigstore TUF repository
type: string
root:
description: Root defines the path or
data of the trusted root
properties:
data:
description: Data is the base64 encoded
TUF root
type: string
path:
description: Path is the URL or File
location of the TUF root
type: string
type: object
type: object
type: object
name:
description: Name is the name for this attestor.
It is used to refer to the attestor in verification
type: string
notary:
description: Notary defines attestor configuration
for Notary based signatures
properties:
certs:
description: Certs define the cert chain for
Notary signature verification
type: string
tsaCerts:
description: TSACerts define the cert chain
for verifying timestamps of notary signature
type: string
required:
- certs
type: object
required:
- name
type: object
type: array
credentials:
description: Credentials provides credentials that will
be used for authentication with registry.
properties:
allowInsecureRegistry:
description: AllowInsecureRegistry allows insecure
access to a registry.
type: boolean
providers:
description: |-
Providers specifies a list of OCI Registry names, whose authentication providers are provided.
It can be of one of these values: default,google,azure,amazon,github.
items:
description: CredentialsProvidersType provides
the list of credential providers required.
enum:
- default
- amazon
- azure
- google
- github
type: string
type: array
secrets:
description: |-
Secrets specifies a list of secrets that are provided for credentials.
Secrets must live in the Kyverno namespace.
items:
type: string
type: array
type: object
evaluation:
description: EvaluationConfiguration defines the configuration
for the policy evaluation.
properties:
admission:
description: Admission controls policy evaluation
during admission.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied during admission.
Optional. Default value is "true".
type: boolean
type: object
background:
description: Background controls policy evaluation
during background scan.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied to existing resources during a background scan.
Optional. Default value is "true". The value must be set to "false" if the policy rule
uses variables that are only available in the admission review request (e.g. user name).
type: boolean
type: object
mode:
description: |-
Mode is the mode of policy evaluation.
Allowed values are "Kubernetes" or "JSON".
Optional. Default value is "Kubernetes".
type: string
type: object
failurePolicy:
description: |-
FailurePolicy defines how to handle failures for the admission policy. Failures can
occur from CEL expression parse errors, type check errors, runtime errors and invalid
or mis-configured policy definitions or bindings.
type: string
imageRules:
description: |-
ImagesRules is a list of Glob and CELExpressions to match images.
Any image that matches one of the rules is considered for validation
Any image that does not match a rule is skipped, even when they are passed as arguments to
image verification functions
items:
description: ImageRule defines a Glob or a CEL expression
for matching images
properties:
cel:
description: Cel defines CEL Expressions for matching
images
type: string
glob:
description: Glob defines a globbing pattern for
matching images
type: string
type: object
type: array
images:
description: Images is a list of CEL expression to extract
images from the resource
items:
properties:
expression:
description: Expression defines CEL expression
to extact images from the resource.
type: string
name:
description: Name is the name for this imageList.
It is used to refer to the images in verification
block as images.<name>
type: string
required:
- expression
- name
type: object
type: array
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be validated.
Match conditions filter requests that have already been matched by the rules,
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
There are a maximum of 64 match conditions allowed.
items:
description: MatchCondition represents a condition which
must by fulfilled for a request to be sent to a webhook.
description: MatchCondition represents a condition
which must by fulfilled for a request to be sent
to a webhook.
properties:
expression:
description: |-
@ -1036,18 +1383,16 @@ spec:
type: object
type: array
matchConstraints:
description: |-
MatchResources decides whether to run the admission control policy on an object based
on whether it meets the match criteria.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
description: MatchConstraints specifies what resources
this policy is designed to validate.
properties:
excludeResourceRules:
description: |-
ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1074,15 +1419,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1188,15 +1534,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1245,15 +1592,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -1291,8 +1639,8 @@ spec:
ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches.
The policy cares about an operation if it matches _any_ Rule.
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -1319,15 +1667,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -1370,33 +1719,84 @@ spec:
x-kubernetes-list-type: atomic
type: object
x-kubernetes-map-type: atomic
validations:
mutateDigest:
default: true
description: |-
MutateDigest enables replacement of image tags with digests.
Defaults to true.
type: boolean
required:
default: true
description: Required validates that images are verified
i.e. have matched passed a signature or attestation
check.
type: boolean
validationActions:
description: |-
ValidationAction specifies the action to be taken when the matched resource violates the policy.
Required.
items:
description: Validation specifies the CEL expression which
is used to apply the validation.
description: ValidationAction specifies a policy enforcement
action.
type: string
type: array
x-kubernetes-list-type: set
variables:
description: |-
Variables contain definitions of variables that can be used in composition of other expressions.
Each variable is defined as a named CEL expression.
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
properties:
expression:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
type: object
x-kubernetes-map-type: atomic
type: array
verifications:
description: Verifications contain CEL expressions which
is used to apply the image verification checks.
items:
description: Validation specifies the CEL expression
which is used to apply the validation.
properties:
expression:
description: "Expression represents the expression
which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL
expressions have access to the contents of the API
request/response, organized into CEL variables as
well as some other useful variables:\n\n- 'object'
- The object from the incoming request. The value
is null for DELETE requests.\n- 'oldObject' - The
existing object. The value is null for CREATE requests.\n-
'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by the
policy binding being evaluated. Only populated if
the policy has a ParamKind.\n- 'namespaceObject'
expressions have access to the contents of the
API request/response, organized into CEL variables
as well as some other useful variables:\n\n-
'object' - The object from the incoming request.
The value is null for DELETE requests.\n- 'oldObject'
- The existing object. The value is null for
CREATE requests.\n- 'request' - Attributes of
the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by
the policy binding being evaluated. Only populated
if the policy has a ParamKind.\n- 'namespaceObject'
- The namespace object that the incoming object
belongs to. The value is null for cluster-scoped
resources.\n- 'variables' - Map of composited variables,
from its name to its lazily evaluated value.\n For
example, a variable named 'foo' can be accessed
as 'variables.foo'.\n- 'authorizer' - A CEL Authorizer.
May be used to perform authorization checks for
the principal (user or service account) of the request.\n
\ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
resources.\n- 'variables' - Map of composited
variables, from its name to its lazily evaluated
value.\n For example, a variable named 'foo'
can be accessed as 'variables.foo'.\n- 'authorizer'
- A CEL Authorizer. May be used to perform authorization
checks for the principal (user or service account)
of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
'authorizer.requestResource' - A CEL ResourceCheck
constructed from the 'authorizer' and configured
with the\n request resource.\n\nThe `apiVersion`,
@ -1404,35 +1804,39 @@ spec:
are always accessible from the root of the\nobject.
No other metadata properties are accessible.\n\nOnly
property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`
are accessible.\nAccessible property names are escaped
according to the following rules when accessed in
the expression:\n- '__' escapes to '__underscores__'\n-
'.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n-
'/' escapes to '__slash__'\n- Property names that
exactly match a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\", \"null\",
\"in\", \"as\", \"break\", \"const\", \"continue\",
\"else\", \"for\", \"function\", \"if\",\n\t \"import\",
\"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n
are accessible.\nAccessible property names are
escaped according to the following rules when
accessed in the expression:\n- '__' escapes
to '__underscores__'\n- '.' escapes to '__dot__'\n-
'-' escapes to '__dash__'\n- '/' escapes to
'__slash__'\n- Property names that exactly match
a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\",
\"null\", \"in\", \"as\", \"break\", \"const\",
\"continue\", \"else\", \"for\", \"function\",
\"if\",\n\t \"import\", \"let\", \"loop\",
\"package\", \"namespace\", \"return\".\nExamples:\n
\ - Expression accessing a property named \"namespace\":
{\"Expression\": \"object.__namespace__ > 0\"}\n
\ - Expression accessing a property named \"x-prop\":
{\"Expression\": \"object.x__dash__prop > 0\"}\n
\ - Expression accessing a property named \"redact__d\":
{\"Expression\": \"object.redact__underscores__d
> 0\"}\n\nEquality on arrays with list type of 'set'
or 'map' ignores element order, i.e. [1, 2] == [2,
1].\nConcatenation on arrays with x-kubernetes-list-type
use the semantics of the list type:\n - 'set':
`X + Y` performs a union where the array positions
of all elements in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their partial
order.\n - 'map': `X + Y` performs a merge where
the array positions of all keys in `X` are preserved
but the values\n are overwritten by values in
`Y` when the key sets of `X` and `Y` intersect.
Elements in `Y` with\n non-intersecting keys
are appended, retaining their partial order.\nRequired."
> 0\"}\n\nEquality on arrays with list type
of 'set' or 'map' ignores element order, i.e.
[1, 2] == [2, 1].\nConcatenation on arrays with
x-kubernetes-list-type use the semantics of
the list type:\n - 'set': `X + Y` performs
a union where the array positions of all elements
in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their
partial order.\n - 'map': `X + Y` performs
a merge where the array positions of all keys
in `X` are preserved but the values\n are
overwritten by values in `Y` when the key sets
of `X` and `Y` intersect. Elements in `Y` with\n
\ non-intersecting keys are appended, retaining
their partial order.\nRequired."
type: string
message:
description: |-
@ -1470,29 +1874,30 @@ spec:
- expression
type: object
type: array
variables:
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
x-kubernetes-list-type: atomic
verifyDigest:
default: true
description: VerifyDigest validates that images have
a digest.
type: boolean
webhookConfiguration:
description: WebhookConfiguration defines the configuration
for the webhook.
properties:
expression:
timeoutSeconds:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy.
After the configured time expires, the admission request may fail, or may simply ignore the policy results,
based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds.
format: int32
type: integer
type: object
x-kubernetes-map-type: atomic
type: array
required:
- attestors
- verifications
type: object
required:
- spec
type: object
type: array
type: object
@ -1552,10 +1957,6 @@ spec:
- type
type: object
type: array
generated:
description: Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy
is generated from the policy or not
type: boolean
message:
description: |-
Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
@ -1566,11 +1967,11 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View file

@ -1328,8 +1328,6 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec

View file

@ -48619,7 +48619,14 @@ spec:
singular: imageverificationpolicy
scope: Cluster
versions:
- name: v1alpha1
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
- jsonPath: .status.ready
name: READY
type: string
name: v1alpha1
schema:
openAPIV3Schema:
properties:
@ -49545,63 +49552,403 @@ spec:
description: Status contains policy runtime data.
properties:
autogen:
description: AutogenStatus contains autogen status information.
properties:
rules:
description: Rules is a list of Rule instances. It contains auto
generated rules added for pod controllers
items:
properties:
auditAnnotations:
items:
description: AuditAnnotation describes how to produce
an audit annotation for an API request.
metadata:
type: object
spec:
description: ImageVerificationPolicySpec is the specification
of the desired behavior of the ImageVerificationPolicy.
properties:
key:
description: |-
key specifies the audit annotation key. The audit annotation keys of
a ValidatingAdmissionPolicy must be unique. The key must be a qualified
name ([A-Za-z0-9][-A-Za-z0-9_.]*) no more than 63 bytes in length.
The key is combined with the resource name of the
ValidatingAdmissionPolicy to construct an audit annotation key:
"{ValidatingAdmissionPolicy name}/{key}".
If an admission webhook uses the same resource name as this ValidatingAdmissionPolicy
and the same audit annotation key, the annotation key will be identical.
In this case, the first annotation written with the key will be included
in the audit event and all subsequent annotations with the same key
will be discarded.
Required.
type: string
valueExpression:
description: |-
valueExpression represents the expression which is evaluated by CEL to
produce an audit annotation value. The expression must evaluate to either
a string or null value. If the expression evaluates to a string, the
audit annotation is included with the string value. If the expression
evaluates to null or empty string the audit annotation will be omitted.
The valueExpression may be no longer than 5kb in length.
If the result of the valueExpression is more than 10kb in length, it
will be truncated to 10kb.
If multiple ValidatingAdmissionPolicyBinding resources match an
API request, then the valueExpression will be evaluated for
each binding. All unique values produced by the valueExpressions
will be joined together in a comma-separated list.
Required.
attestations:
description: Attestations provides a list of image metadata
to verify
items:
description: Attestation defines the identification
details of the metadata that has to be verified
properties:
intoto:
description: InToto defines the details of attestation
attached using intoto format
properties:
type:
description: Type defines the type of attestation
contained within the statement.
type: string
required:
- key
- valueExpression
- type
type: object
name:
description: Name is the name for this attestation.
It is used to refer to the attestation in verification
type: string
referrer:
description: Referrer defines the details of attestation
attached using OCI 1.1 format
properties:
type:
description: Type defines the type of attestation
attached to the image.
type: string
required:
- type
type: object
required:
- name
type: object
type: array
attestors:
description: Attestors provides a list of trusted authorities.
items:
description: Attestor is an identity that confirms
or verifies the authenticity of an image or an attestation
properties:
cosign:
description: Cosign defines attestor configuration
for Cosign based signatures
properties:
annotations:
additionalProperties:
type: string
description: |-
Annotations are used for image verification.
Every specified key-value pair must exist and match in the verified payload.
The payload may contain other key-value pairs.
type: object
certificate:
description: Certificate defines the configuration
for local signature verification
properties:
cert:
description: Certificate is the to the
public certificate for local signature
verification.
type: string
certChain:
description: |-
CertificateChain is the list of CA certificates in PEM format which will be needed
when building the certificate chain for the signing certificate. Must start with the
parent intermediate CA certificate of the signing certificate and end with the root certificate
type: string
type: object
ctlog:
description: CTLog sets the configuration
to verify the authority against a Rekor
instance.
properties:
ctLogPubKey:
description: CTLogPubKey, if set, is used
to validate SCTs against a custom source.
type: string
insecureIgnoreSCT:
description: |-
IgnoreSCT defines whether to use the Signed Certificate Timestamp (SCT) log to check for a certificate
timestamp. Default is false. Set to true if this was opted out during signing.
type: boolean
insecureIgnoreTlog:
description: InsecureIgnoreTlog skips
transparency log verification.
type: boolean
rekorPubKey:
description: |-
RekorPubKey is an optional PEM-encoded public key to use for a custom Rekor.
If set, this will be used to validate transparency log signatures from a custom Rekor.
type: string
tsaCertChain:
description: |-
TSACertChain, if set, is the PEM-encoded certificate chain file for the RFC3161 timestamp authority. Must
contain the root CA certificate. Optionally may contain intermediate CA certificates, and
may contain the leaf TSA certificate if not present in the timestamurce.
type: string
url:
description: URL sets the url to the rekor
instance (by default the public rekor.sigstore.dev)
type: string
type: object
key:
description: Key defines the type of key to
validate the image.
properties:
data:
description: Data contains the inline
public key
type: string
hashAlgorithm:
description: |-
HashAlgorithm specifues signature algorithm for public keys. Supported values are
sha224, sha256, sha384 and sha512. Defaults to sha256.
type: string
kms:
description: |-
KMS contains the KMS url of the public key
Supported formats differ based on the KMS system used.
type: string
secretRef:
description: SecretRef sets a reference
to a secret with the key.
properties:
name:
description: name is unique within
a namespace to reference a secret
resource.
type: string
namespace:
description: namespace defines the
space within which the secret name
must be unique.
type: string
type: object
x-kubernetes-map-type: atomic
type: object
keyless:
description: Keyless sets the configuration
to verify the authority against a Fulcio
instance.
properties:
identities:
description: Identities sets a list of
identities.
items:
description: |-
Identity may contain the issuer and/or the subject found in the transparency
log.
Issuer/Subject uses a strict match, while IssuerRegExp and SubjectRegExp
apply a regexp for matching.
properties:
issuer:
description: Issuer defines the
issuer for this identity.
type: string
issuerRegExp:
description: IssuerRegExp specifies
a regular expression to match
the issuer for this identity.
type: string
subject:
description: Subject defines the
subject for this identity.
type: string
subjectRegExp:
description: SubjectRegExp specifies
a regular expression to match
the subject for this identity.
type: string
type: object
type: array
roots:
description: |-
Roots is an optional set of PEM encoded trusted root certificates.
If not provided, the system roots are used.
type: string
required:
- identities
type: object
source:
description: Sources sets the configuration
to specify the sources from where to consume
the signature and attestations.
properties:
PullSecrets:
description: |-
SignaturePullSecrets is an optional list of references to secrets in the
same namespace as the deploying resource for pulling any of the signatures
used by this Source.
items:
description: |-
LocalObjectReference contains enough information to let you locate the
referenced object inside the same namespace.
properties:
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
type: object
x-kubernetes-map-type: atomic
type: array
repository:
description: Repository defines the location
from where to pull the signature / attestations.
type: string
tagPrefix:
description: |-
TagPrefix is an optional prefix that signature and attestations have.
This is the 'tag based discovery' and in the future once references are
fully supported that should likely be the preferred way to handle these.
type: string
type: object
tuf:
description: TUF defines the configuration
to fetch sigstore root
properties:
mirror:
description: Mirror is the base URL of
Sigstore TUF repository
type: string
root:
description: Root defines the path or
data of the trusted root
properties:
data:
description: Data is the base64 encoded
TUF root
type: string
path:
description: Path is the URL or File
location of the TUF root
type: string
type: object
type: object
type: object
name:
description: Name is the name for this attestor.
It is used to refer to the attestor in verification
type: string
notary:
description: Notary defines attestor configuration
for Notary based signatures
properties:
certs:
description: Certs define the cert chain for
Notary signature verification
type: string
tsaCerts:
description: TSACerts define the cert chain
for verifying timestamps of notary signature
type: string
required:
- certs
type: object
required:
- name
type: object
type: array
credentials:
description: Credentials provides credentials that will
be used for authentication with registry.
properties:
allowInsecureRegistry:
description: AllowInsecureRegistry allows insecure
access to a registry.
type: boolean
providers:
description: |-
Providers specifies a list of OCI Registry names, whose authentication providers are provided.
It can be of one of these values: default,google,azure,amazon,github.
items:
description: CredentialsProvidersType provides
the list of credential providers required.
enum:
- default
- amazon
- azure
- google
- github
type: string
type: array
secrets:
description: |-
Secrets specifies a list of secrets that are provided for credentials.
Secrets must live in the Kyverno namespace.
items:
type: string
type: array
type: object
evaluation:
description: EvaluationConfiguration defines the configuration
for the policy evaluation.
properties:
admission:
description: Admission controls policy evaluation
during admission.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied during admission.
Optional. Default value is "true".
type: boolean
type: object
background:
description: Background controls policy evaluation
during background scan.
properties:
enabled:
default: true
description: |-
Enabled controls if rules are applied to existing resources during a background scan.
Optional. Default value is "true". The value must be set to "false" if the policy rule
uses variables that are only available in the admission review request (e.g. user name).
type: boolean
type: object
mode:
description: |-
Mode is the mode of policy evaluation.
Allowed values are "Kubernetes" or "JSON".
Optional. Default value is "Kubernetes".
type: string
type: object
failurePolicy:
description: |-
FailurePolicy defines how to handle failures for the admission policy. Failures can
occur from CEL expression parse errors, type check errors, runtime errors and invalid
or mis-configured policy definitions or bindings.
type: string
imageRules:
description: |-
ImagesRules is a list of Glob and CELExpressions to match images.
Any image that matches one of the rules is considered for validation
Any image that does not match a rule is skipped, even when they are passed as arguments to
image verification functions
items:
description: ImageRule defines a Glob or a CEL expression
for matching images
properties:
cel:
description: Cel defines CEL Expressions for matching
images
type: string
glob:
description: Glob defines a globbing pattern for
matching images
type: string
type: object
type: array
images:
description: Images is a list of CEL expression to extract
images from the resource
items:
properties:
expression:
description: Expression defines CEL expression
to extact images from the resource.
type: string
name:
description: Name is the name for this imageList.
It is used to refer to the images in verification
block as images.<name>
type: string
required:
- expression
- name
type: object
type: array
matchConditions:
description: |-
MatchConditions is a list of conditions that must be met for a request to be validated.
Match conditions filter requests that have already been matched by the rules,
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
There are a maximum of 64 match conditions allowed.
items:
description: MatchCondition represents a condition which
must by fulfilled for a request to be sent to a webhook.
description: MatchCondition represents a condition
which must by fulfilled for a request to be sent
to a webhook.
properties:
expression:
description: |-
@ -49637,18 +49984,16 @@ spec:
type: object
type: array
matchConstraints:
description: |-
MatchResources decides whether to run the admission control policy on an object based
on whether it meets the match criteria.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
description: MatchConstraints specifies what resources
this policy is designed to validate.
properties:
excludeResourceRules:
description: |-
ExcludeResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy should not care about.
The exclude rules take precedence over include rules (if a resource matches both, it is excluded)
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -49675,15 +50020,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -49789,15 +50135,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -49846,15 +50193,16 @@ spec:
properties:
matchExpressions:
description: matchExpressions is a list of label
selector requirements. The requirements are ANDed.
selector requirements. The requirements are
ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the
selector applies to.
description: key is the label key that
the selector applies to.
type: string
operator:
description: |-
@ -49892,8 +50240,8 @@ spec:
ResourceRules describes what operations on what resources/subresources the ValidatingAdmissionPolicy matches.
The policy cares about an operation if it matches _any_ Rule.
items:
description: NamedRuleWithOperations is a tuple of
Operations and Resources with ResourceNames.
description: NamedRuleWithOperations is a tuple
of Operations and Resources with ResourceNames.
properties:
apiGroups:
description: |-
@ -49920,15 +50268,16 @@ spec:
If '*' is present, the length of the slice must be one.
Required.
items:
description: OperationType specifies an operation
for a request.
description: OperationType specifies an
operation for a request.
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white
list of names that the rule applies to. An
empty set means that everything is allowed.
description: ResourceNames is an optional
white list of names that the rule applies
to. An empty set means that everything
is allowed.
items:
type: string
type: array
@ -49971,33 +50320,84 @@ spec:
x-kubernetes-list-type: atomic
type: object
x-kubernetes-map-type: atomic
validations:
mutateDigest:
default: true
description: |-
MutateDigest enables replacement of image tags with digests.
Defaults to true.
type: boolean
required:
default: true
description: Required validates that images are verified
i.e. have matched passed a signature or attestation
check.
type: boolean
validationActions:
description: |-
ValidationAction specifies the action to be taken when the matched resource violates the policy.
Required.
items:
description: Validation specifies the CEL expression which
is used to apply the validation.
description: ValidationAction specifies a policy enforcement
action.
type: string
type: array
x-kubernetes-list-type: set
variables:
description: |-
Variables contain definitions of variables that can be used in composition of other expressions.
Each variable is defined as a named CEL expression.
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
properties:
expression:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
type: object
x-kubernetes-map-type: atomic
type: array
verifications:
description: Verifications contain CEL expressions which
is used to apply the image verification checks.
items:
description: Validation specifies the CEL expression
which is used to apply the validation.
properties:
expression:
description: "Expression represents the expression
which will be evaluated by CEL.\nref: https://github.com/google/cel-spec\nCEL
expressions have access to the contents of the API
request/response, organized into CEL variables as
well as some other useful variables:\n\n- 'object'
- The object from the incoming request. The value
is null for DELETE requests.\n- 'oldObject' - The
existing object. The value is null for CREATE requests.\n-
'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by the
policy binding being evaluated. Only populated if
the policy has a ParamKind.\n- 'namespaceObject'
expressions have access to the contents of the
API request/response, organized into CEL variables
as well as some other useful variables:\n\n-
'object' - The object from the incoming request.
The value is null for DELETE requests.\n- 'oldObject'
- The existing object. The value is null for
CREATE requests.\n- 'request' - Attributes of
the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).\n-
'params' - Parameter resource referred to by
the policy binding being evaluated. Only populated
if the policy has a ParamKind.\n- 'namespaceObject'
- The namespace object that the incoming object
belongs to. The value is null for cluster-scoped
resources.\n- 'variables' - Map of composited variables,
from its name to its lazily evaluated value.\n For
example, a variable named 'foo' can be accessed
as 'variables.foo'.\n- 'authorizer' - A CEL Authorizer.
May be used to perform authorization checks for
the principal (user or service account) of the request.\n
\ See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
resources.\n- 'variables' - Map of composited
variables, from its name to its lazily evaluated
value.\n For example, a variable named 'foo'
can be accessed as 'variables.foo'.\n- 'authorizer'
- A CEL Authorizer. May be used to perform authorization
checks for the principal (user or service account)
of the request.\n See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz\n-
'authorizer.requestResource' - A CEL ResourceCheck
constructed from the 'authorizer' and configured
with the\n request resource.\n\nThe `apiVersion`,
@ -50005,35 +50405,39 @@ spec:
are always accessible from the root of the\nobject.
No other metadata properties are accessible.\n\nOnly
property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*`
are accessible.\nAccessible property names are escaped
according to the following rules when accessed in
the expression:\n- '__' escapes to '__underscores__'\n-
'.' escapes to '__dot__'\n- '-' escapes to '__dash__'\n-
'/' escapes to '__slash__'\n- Property names that
exactly match a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\", \"null\",
\"in\", \"as\", \"break\", \"const\", \"continue\",
\"else\", \"for\", \"function\", \"if\",\n\t \"import\",
\"let\", \"loop\", \"package\", \"namespace\", \"return\".\nExamples:\n
are accessible.\nAccessible property names are
escaped according to the following rules when
accessed in the expression:\n- '__' escapes
to '__underscores__'\n- '.' escapes to '__dot__'\n-
'-' escapes to '__dash__'\n- '/' escapes to
'__slash__'\n- Property names that exactly match
a CEL RESERVED keyword escape to '__{keyword}__'.
The keywords are:\n\t \"true\", \"false\",
\"null\", \"in\", \"as\", \"break\", \"const\",
\"continue\", \"else\", \"for\", \"function\",
\"if\",\n\t \"import\", \"let\", \"loop\",
\"package\", \"namespace\", \"return\".\nExamples:\n
\ - Expression accessing a property named \"namespace\":
{\"Expression\": \"object.__namespace__ > 0\"}\n
\ - Expression accessing a property named \"x-prop\":
{\"Expression\": \"object.x__dash__prop > 0\"}\n
\ - Expression accessing a property named \"redact__d\":
{\"Expression\": \"object.redact__underscores__d
> 0\"}\n\nEquality on arrays with list type of 'set'
or 'map' ignores element order, i.e. [1, 2] == [2,
1].\nConcatenation on arrays with x-kubernetes-list-type
use the semantics of the list type:\n - 'set':
`X + Y` performs a union where the array positions
of all elements in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their partial
order.\n - 'map': `X + Y` performs a merge where
the array positions of all keys in `X` are preserved
but the values\n are overwritten by values in
`Y` when the key sets of `X` and `Y` intersect.
Elements in `Y` with\n non-intersecting keys
are appended, retaining their partial order.\nRequired."
> 0\"}\n\nEquality on arrays with list type
of 'set' or 'map' ignores element order, i.e.
[1, 2] == [2, 1].\nConcatenation on arrays with
x-kubernetes-list-type use the semantics of
the list type:\n - 'set': `X + Y` performs
a union where the array positions of all elements
in `X` are preserved and\n non-intersecting
elements in `Y` are appended, retaining their
partial order.\n - 'map': `X + Y` performs
a merge where the array positions of all keys
in `X` are preserved but the values\n are
overwritten by values in `Y` when the key sets
of `X` and `Y` intersect. Elements in `Y` with\n
\ non-intersecting keys are appended, retaining
their partial order.\nRequired."
type: string
message:
description: |-
@ -50071,29 +50475,30 @@ spec:
- expression
type: object
type: array
variables:
items:
description: Variable is the definition of a variable
that is used for composition. A variable is defined
as a named expression.
x-kubernetes-list-type: atomic
verifyDigest:
default: true
description: VerifyDigest validates that images have
a digest.
type: boolean
webhookConfiguration:
description: WebhookConfiguration defines the configuration
for the webhook.
properties:
expression:
timeoutSeconds:
description: |-
Expression is the expression that will be evaluated as the value of the variable.
The CEL expression has access to the same identifiers as the CEL expressions in Validation.
type: string
name:
description: |-
Name is the name of the variable. The name must be a valid CEL identifier and unique among all variables.
The variable can be accessed in other expressions through `variables`
For example, if name is "foo", the variable will be available as `variables.foo`
type: string
required:
- expression
- name
TimeoutSeconds specifies the maximum time in seconds allowed to apply this policy.
After the configured time expires, the admission request may fail, or may simply ignore the policy results,
based on the failure policy. The default timeout is 10s, the value must be between 1 and 30 seconds.
format: int32
type: integer
type: object
x-kubernetes-map-type: atomic
type: array
required:
- attestors
- verifications
type: object
required:
- spec
type: object
type: array
type: object
@ -50153,10 +50558,6 @@ spec:
- type
type: object
type: array
generated:
description: Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy
is generated from the policy or not
type: boolean
message:
description: |-
Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
@ -50167,14 +50568,14 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
@ -51512,8 +51913,6 @@ spec:
The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy's status.
type: boolean
required:
- message
type: object
required:
- spec

View file

@ -10560,8 +10560,8 @@ EvaluationConfiguration
<td>
<code>status</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.PolicyStatus">
PolicyStatus
<a href="#policies.kyverno.io/v1alpha1.IvpolStatus">
IvpolStatus
</a>
</em>
</td>
@ -10807,8 +10807,8 @@ EvaluationConfiguration
<td>
<code>status</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.PolicyStatus">
PolicyStatus
<a href="#policies.kyverno.io/v1alpha1.VpolStatus">
VpolStatus
</a>
</em>
</td>
@ -11053,7 +11053,7 @@ Kubernetes admissionregistration/v1.MatchResources
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.PolicyStatus">PolicyStatus</a>)
<a href="#policies.kyverno.io/v1alpha1.VpolStatus">VpolStatus</a>)
</p>
<p>
<p>AutogenStatus contains autogen status information.</p>
@ -11304,6 +11304,66 @@ parent intermediate CA certificate of the signing certificate and end with the r
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.ConditionStatus">ConditionStatus
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.IvpolStatus">IvpolStatus</a>,
<a href="#policies.kyverno.io/v1alpha1.VpolStatus">VpolStatus</a>)
</p>
<p>
<p>ConditionStatus is the shared status across all policy types</p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>ready</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy&rsquo;s status.</p>
</td>
</tr>
<tr>
<td>
<code>conditions</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#condition-v1-meta">
[]Kubernetes meta/v1.Condition
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
<tr>
<td>
<code>message</code><br/>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated.</p>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.Cosign">Cosign
</h3>
<p>
@ -11726,7 +11786,8 @@ string
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy</a>)
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy</a>,
<a href="#policies.kyverno.io/v1alpha1.IvpolAutogen">IvpolAutogen</a>)
</p>
<p>
<p>ImageVerificationPolicySpec is the specification of the desired behavior of the ImageVerificationPolicy.</p>
@ -11997,6 +12058,355 @@ string
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.IvpolAutogen">IvpolAutogen
</h3>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>metadata</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#objectmeta-v1-meta">
Kubernetes meta/v1.ObjectMeta
</a>
</em>
</td>
<td>
Refer to the Kubernetes API documentation for the fields of the
<code>metadata</code> field.
</td>
</tr>
<tr>
<td>
<code>spec</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicySpec">
ImageVerificationPolicySpec
</a>
</em>
</td>
<td>
<br/>
<br/>
<table class="table table-striped">
<tr>
<td>
<code>matchConstraints</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchresources-v1-admissionregistration">
Kubernetes admissionregistration/v1.MatchResources
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>MatchConstraints specifies what resources this policy is designed to validate.</p>
</td>
</tr>
<tr>
<td>
<code>failurePolicy</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#failurepolicytype-v1-admissionregistration">
Kubernetes admissionregistration/v1.FailurePolicyType
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>FailurePolicy defines how to handle failures for the admission policy. Failures can
occur from CEL expression parse errors, type check errors, runtime errors and invalid
or mis-configured policy definitions or bindings.</p>
</td>
</tr>
<tr>
<td>
<code>validationActions</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validationaction-v1-admissionregistration">
[]Kubernetes admissionregistration/v1.ValidationAction
</a>
</em>
</td>
<td>
<p>ValidationAction specifies the action to be taken when the matched resource violates the policy.
Required.</p>
</td>
</tr>
<tr>
<td>
<code>matchConditions</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#matchcondition-v1-admissionregistration">
[]Kubernetes admissionregistration/v1.MatchCondition
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>MatchConditions is a list of conditions that must be met for a request to be validated.
Match conditions filter requests that have already been matched by the rules,
namespaceSelector, and objectSelector. An empty list of matchConditions matches all requests.
There are a maximum of 64 match conditions allowed.</p>
</td>
</tr>
<tr>
<td>
<code>variables</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#variable-v1-admissionregistration">
[]Kubernetes admissionregistration/v1.Variable
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Variables contain definitions of variables that can be used in composition of other expressions.
Each variable is defined as a named CEL expression.</p>
</td>
</tr>
<tr>
<td>
<code>imageRules</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.ImageRule">
[]ImageRule
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>ImagesRules is a list of Glob and CELExpressions to match images.
Any image that matches one of the rules is considered for validation
Any image that does not match a rule is skipped, even when they are passed as arguments to
image verification functions</p>
</td>
</tr>
<tr>
<td>
<code>mutateDigest</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>MutateDigest enables replacement of image tags with digests.
Defaults to true.</p>
</td>
</tr>
<tr>
<td>
<code>verifyDigest</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>VerifyDigest validates that images have a digest.</p>
</td>
</tr>
<tr>
<td>
<code>required</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Required validates that images are verified i.e. have matched passed a signature or attestation check.</p>
</td>
</tr>
<tr>
<td>
<code>credentials</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.Credentials">
Credentials
</a>
</em>
</td>
<td>
<p>Credentials provides credentials that will be used for authentication with registry.</p>
</td>
</tr>
<tr>
<td>
<code>images</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.Image">
[]Image
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Images is a list of CEL expression to extract images from the resource</p>
</td>
</tr>
<tr>
<td>
<code>attestors</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.Attestor">
[]Attestor
</a>
</em>
</td>
<td>
<p>Attestors provides a list of trusted authorities.</p>
</td>
</tr>
<tr>
<td>
<code>attestations</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.Attestation">
[]Attestation
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Attestations provides a list of image metadata to verify</p>
</td>
</tr>
<tr>
<td>
<code>verifications</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#validation-v1-admissionregistration">
[]Kubernetes admissionregistration/v1.Validation
</a>
</em>
</td>
<td>
<p>Verifications contain CEL expressions which is used to apply the image verification checks.</p>
</td>
</tr>
<tr>
<td>
<code>webhookConfiguration</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.WebhookConfiguration">
WebhookConfiguration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>WebhookConfiguration defines the configuration for the webhook.</p>
</td>
</tr>
<tr>
<td>
<code>evaluation</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.EvaluationConfiguration">
EvaluationConfiguration
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>EvaluationConfiguration defines the configuration for the policy evaluation.</p>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.IvpolAutogenStatus">IvpolAutogenStatus
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.IvpolStatus">IvpolStatus</a>)
</p>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>rules</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.*github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1.IvpolAutogen">
[]*github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1.IvpolAutogen
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.IvpolStatus">IvpolStatus
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy</a>)
</p>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>ConditionStatus</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.ConditionStatus">
ConditionStatus
</a>
</em>
</td>
<td>
<p>
(Members of <code>ConditionStatus</code> are embedded into this type.)
</p>
</td>
</tr>
<tr>
<td>
<code>autogen</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.IvpolAutogenStatus">
IvpolAutogenStatus
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.Key">Key
</h3>
<p>
@ -12205,89 +12615,6 @@ string
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.PolicyStatus">PolicyStatus
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.ImageVerificationPolicy">ImageVerificationPolicy</a>,
<a href="#policies.kyverno.io/v1alpha1.ValidatingPolicy">ValidatingPolicy</a>)
</p>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>ready</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>The ready of a policy is a high-level summary of where the policy is in its lifecycle.
The conditions array, the reason and message fields contain more detail about the policy&rsquo;s status.</p>
</td>
</tr>
<tr>
<td>
<code>conditions</code><br/>
<em>
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#condition-v1-meta">
[]Kubernetes meta/v1.Condition
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
<tr>
<td>
<code>autogen</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.AutogenStatus">
AutogenStatus
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
<tr>
<td>
<code>generated</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy is generated from the policy or not</p>
</td>
</tr>
<tr>
<td>
<code>message</code><br/>
<em>
string
</em>
</td>
<td>
<p>Message is a human readable message indicating details about the generation of ValidatingAdmissionPolicy/MutatingAdmissionPolicy
It is an empty string when ValidatingAdmissionPolicy/MutatingAdmissionPolicy is successfully generated.</p>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.Referrer">Referrer
</h3>
<p>
@ -12661,6 +12988,65 @@ EvaluationConfiguration
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.VpolStatus">VpolStatus
</h3>
<p>
(<em>Appears on:</em>
<a href="#policies.kyverno.io/v1alpha1.ValidatingPolicy">ValidatingPolicy</a>)
</p>
<p>
</p>
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>ConditionStatus</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.ConditionStatus">
ConditionStatus
</a>
</em>
</td>
<td>
<p>
(Members of <code>ConditionStatus</code> are embedded into this type.)
</p>
</td>
</tr>
<tr>
<td>
<code>autogen</code><br/>
<em>
<a href="#policies.kyverno.io/v1alpha1.AutogenStatus">
AutogenStatus
</a>
</em>
</td>
<td>
<em>(Optional)</em>
</td>
</tr>
<tr>
<td>
<code>generated</code><br/>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>Generated indicates whether a ValidatingAdmissionPolicy/MutatingAdmissionPolicy is generated from the policy or not</p>
</td>
</tr>
</tbody>
</table>
<hr />
<h3 id="policies.kyverno.io/v1alpha1.WebhookConfiguration">WebhookConfiguration
</h3>
<p>

View file

@ -9,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
)
func GetAutogenRulesImageVerify(policy *policiesv1alpha1.ImageVerificationPolicy) ([]*policiesv1alpha1.ImageVerificationPolicy, error) {
func GetAutogenRulesImageVerify(policy *policiesv1alpha1.ImageVerificationPolicy) ([]*policiesv1alpha1.IvpolAutogen, error) {
if policy == nil {
return nil, nil
}
@ -27,7 +27,6 @@ func GetAutogenRulesImageVerify(policy *policiesv1alpha1.ImageVerificationPolicy
} else {
actualControllers = sets.New(strings.Split(actualControllersString, ",")...)
}
genRules, err := autogenIvPols(policy, actualControllers)
if err != nil {
return nil, err
@ -36,8 +35,8 @@ func GetAutogenRulesImageVerify(policy *policiesv1alpha1.ImageVerificationPolicy
return genRules, nil
}
func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSet sets.Set[string]) ([]*policiesv1alpha1.ImageVerificationPolicy, error) {
genPolicy := func(resource autogencontroller, controllers string) (*policiesv1alpha1.ImageVerificationPolicy, error) {
func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSet sets.Set[string]) ([]*policiesv1alpha1.IvpolAutogen, error) {
genPolicy := func(resource autogencontroller, controllers string) (policy *policiesv1alpha1.IvpolAutogen, err error) {
if len(controllers) == 0 {
return nil, nil
}
@ -45,8 +44,11 @@ func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSe
if ivpol == nil {
return nil, nil
}
var err error
policy := ivpol.DeepCopy()
policy = &policiesv1alpha1.IvpolAutogen{}
copied := ivpol.DeepCopy()
policy.ObjectMeta = copied.ObjectMeta
policy.Spec = copied.Spec
if controllers == "cronjobs" {
policy.Name = "autogen-cronjobs-" + policy.Name
} else {
@ -57,7 +59,7 @@ func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSe
policy.Spec.MatchConstraints = createMatchConstraints(controllers, operations)
// convert match conditions
policy.Spec.MatchConditions, err = convertMatchconditions(ivpol.Spec.MatchConditions, resource)
policy.Spec.MatchConditions, err = convertMatchConditions(policy.Spec.MatchConditions, resource)
if err != nil {
return nil, err
}
@ -74,7 +76,7 @@ func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSe
return policy, nil
}
ivpols := make([]*policiesv1alpha1.ImageVerificationPolicy, 0)
ivpols := make([]*policiesv1alpha1.IvpolAutogen, 0)
if controllerSet.Has("cronjobs") {
p, err := genPolicy(CRONJOBS, "cronjobs")
if err != nil {
@ -85,7 +87,8 @@ func autogenIvPols(ivpol *policiesv1alpha1.ImageVerificationPolicy, controllerSe
}
}
p, err := genPolicy(PODS, strings.Join(sets.List(controllerSet.Delete("cronjobs")), ","))
controllerSetCopied := controllerSet.Clone()
p, err := genPolicy(PODS, strings.Join(sets.List(controllerSetCopied.Delete("cronjobs")), ","))
if err != nil {
return nil, err
}

View file

@ -17,56 +17,36 @@ var (
CRONJOBS autogencontroller = "cronjobs"
)
func generateRuleForControllers(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string, resource autogencontroller) (*policiesv1alpha1.AutogenRule, error) {
func generateRuleForControllers(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string, resource autogencontroller) (autogenRule *policiesv1alpha1.AutogenRule, err error) {
operations := spec.MatchConstraints.ResourceRules[0].Operations
newSpec := &policiesv1alpha1.ValidatingPolicySpec{}
// create a resource rule for pod controllers
matchConstraints := createMatchConstraints(controllers, operations)
newSpec.MatchConstraints = createMatchConstraints(controllers, operations)
// convert match conditions
matchConditions, err := convertMatchconditions(spec.MatchConditions, resource)
newSpec.MatchConditions, err = convertMatchConditions(spec.MatchConditions, resource)
if err != nil {
return nil, err
}
// convert validations
validations := spec.Validations
if bytes, err := json.Marshal(validations); err != nil {
newSpec.Validations = spec.Validations
newSpec.AuditAnnotations = spec.AuditAnnotations
newSpec.Variables = spec.Variables
if bytes, err := json.Marshal(newSpec); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &validations); err != nil {
return nil, err
}
}
// convert audit annotations
auditAnnotations := spec.AuditAnnotations
if bytes, err := json.Marshal(auditAnnotations); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &auditAnnotations); err != nil {
return nil, err
}
}
// convert variables
variables := spec.Variables
if bytes, err := json.Marshal(variables); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &variables); err != nil {
if err := json.Unmarshal(bytes, &newSpec); err != nil {
return nil, err
}
}
return &policiesv1alpha1.AutogenRule{
MatchConstraints: matchConstraints,
MatchConditions: matchConditions,
Validations: validations,
AuditAnnotation: auditAnnotations,
Variables: variables,
MatchConstraints: newSpec.MatchConstraints,
MatchConditions: newSpec.MatchConditions,
Validations: newSpec.Validations,
AuditAnnotation: newSpec.AuditAnnotations,
Variables: newSpec.Variables,
}, nil
}
@ -124,15 +104,15 @@ func createMatchConstraints(controllers string, operations []admissionregistrati
}
}
func convertMatchconditions(conditions []admissionregistrationv1.MatchCondition, resource autogencontroller) (matchConditions []admissionregistrationv1.MatchCondition, err error) {
func convertMatchConditions(conditions []admissionregistrationv1.MatchCondition, resource autogencontroller) (matchConditions []admissionregistrationv1.MatchCondition, err error) {
var name, expression string
switch resource {
case PODS:
name = podControllerMatchConditionName
expression = podControllersMatchConditionExpression
expression = PodControllersMatchConditionExpression
case CRONJOBS:
name = cronjobMatchConditionName
expression = cronJobMatchConditionExpression
expression = CronJobMatchConditionExpression
}
for _, m := range conditions {
@ -140,22 +120,22 @@ func convertMatchconditions(conditions []admissionregistrationv1.MatchCondition,
m.Expression = expression + m.Expression
matchConditions = append(matchConditions, m)
}
if bytes, err := json.Marshal(matchConditions); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &matchConditions); err != nil {
return nil, err
}
}
// if bytes, err := json.Marshal(matchConditions); err != nil {
// return nil, err
// } else {
// bytes = updateFields(bytes, resource)
// if err := json.Unmarshal(bytes, &matchConditions); err != nil {
// return nil, err
// }
// }
return matchConditions, nil
}
var (
podControllerMatchConditionName = "autogen-"
podControllersMatchConditionExpression = "!(object.kind =='Deployment' || object.kind =='ReplicaSet' || object.kind =='StatefulSet' || object.kind =='DaemonSet') || "
PodControllersMatchConditionExpression = "!(object.kind =='Deployment' || object.kind =='ReplicaSet' || object.kind =='StatefulSet' || object.kind =='DaemonSet') || "
cronjobMatchConditionName = "autogen-cronjobs-"
cronJobMatchConditionExpression = "!(object.kind =='CronJob') || "
CronJobMatchConditionExpression = "!(object.kind =='CronJob') || "
)
func updateFields(data []byte, resource autogencontroller) []byte {

View file

@ -6,7 +6,6 @@ import (
"fmt"
"reflect"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/api/kyverno"
contextlib "github.com/kyverno/kyverno/pkg/cel/libs/context"
"github.com/kyverno/kyverno/pkg/cel/matching"
@ -31,7 +30,6 @@ type ImageVerifyEngine interface {
}
type ivengine struct {
logger logr.Logger
provider ImageVerifyPolProviderFunc
nsResolver NamespaceResolver
matcher matching.Matcher
@ -39,9 +37,8 @@ type ivengine struct {
registryOpts []imagedataloader.Option
}
func NewImageVerifyEngine(logger logr.Logger, provider ImageVerifyPolProviderFunc, nsResolver NamespaceResolver, matcher matching.Matcher, lister k8scorev1.SecretInterface, registryOpts []imagedataloader.Option) ImageVerifyEngine {
func NewImageVerifyEngine(provider ImageVerifyPolProviderFunc, nsResolver NamespaceResolver, matcher matching.Matcher, lister k8scorev1.SecretInterface, registryOpts []imagedataloader.Option) ImageVerifyEngine {
return &ivengine{
logger: logger,
provider: provider,
nsResolver: nsResolver,
matcher: matcher,
@ -203,7 +200,7 @@ func (e *ivengine) handleMutation(ctx context.Context, policies []CompiledImageV
Actions: ivpol.Actions,
}
if p, errList := c.Compile(e.logger, ivpol.Policy); errList != nil {
if p, errList := c.Compile(ivpol.Policy); errList != nil {
response.Result = *engineapi.RuleError("evaluation", engineapi.ImageVerify, "failed to compile policy", errList.ToAggregate(), nil)
} else {
result, err := p.Evaluate(ctx, ictx, attr, request, namespace, true)
@ -227,7 +224,7 @@ func (e *ivengine) handleMutation(ctx context.Context, policies []CompiledImageV
if err != nil {
return nil, nil, err
}
patches, err := eval.MakeImageVerifyOutcomePatch(len(ann) != 0, e.logger, results)
patches, err := eval.MakeImageVerifyOutcomePatch(len(ann) != 0, results)
if err != nil {
return nil, nil, err
}

View file

@ -5,7 +5,6 @@ import (
"encoding/json"
"testing"
"github.com/go-logr/logr"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
contextlib "github.com/kyverno/kyverno/pkg/cel/libs/context"
"github.com/kyverno/kyverno/pkg/cel/matching"
@ -148,7 +147,7 @@ uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
)
func Test_ImageVerifyEngine(t *testing.T) {
engine := NewImageVerifyEngine(logr.Discard(), ivfunc, nsResolver, matching.NewMatcher(), nil, nil)
engine := NewImageVerifyEngine(ivfunc, nsResolver, matching.NewMatcher(), nil, nil)
engineRequest := EngineRequest{
request: v1.AdmissionRequest{
Operation: v1.Create,

View file

@ -304,7 +304,10 @@ func (r *ivpolpolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
Name: p.Name,
}
r.policies[namespacedName.String()] = CompiledImageVerificationPolicy{
Policy: p,
Policy: &policiesv1alpha1.ImageVerificationPolicy{
ObjectMeta: p.ObjectMeta,
Spec: p.Spec,
},
Actions: actions,
}
}

View file

@ -54,6 +54,8 @@ const (
VerifyMutatingWebhookName = "monitor-webhooks.kyverno.svc"
// ValidatingPolicyWebhookName defines default webhook name for validatingpolicies
ValidatingPolicyWebhookName = "vpol.validate.kyverno.svc"
// ImageVerificationPolicyWebhookName defines default webhook name for imageverificationpolicies
ImageVerificationPolicyWebhookName = "ivpol.validate.kyverno.svc"
)
// paths
@ -62,8 +64,12 @@ const (
PolicyValidatingWebhookServicePath = "/policyvalidate"
// ValidatingWebhookServicePath is the path for validation webhook
ValidatingWebhookServicePath = "/validate"
// ValidatingPolicyServicePath is the path for validating policies execution
ValidatingPolicyServicePath = "/policies"
// PolicyServicePath is the prefix path for policies execution
PolicyServicePath = "/policies"
// ValidatingPolicyServicePath is the sub path for validatingpolicies execution
ValidatingPolicyServicePath = "/vpol"
// ImageVerificationPolicyServicePath is the sub path for imageverificationpolicies execution
ImageVerificationPolicyServicePath = "/ivpol"
// ExceptionValidatingWebhookServicePath is the path for policy exception validation webhook(used to validate policy exception resource)
ExceptionValidatingWebhookServicePath = "/exceptionvalidate"
// CELExceptionValidatingWebhookServicePath is the path for CELPolicyException validation webhook(used to validate CELPolicyException resource)

View file

@ -8,15 +8,15 @@ import (
"github.com/go-logr/logr"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
auth "github.com/kyverno/kyverno/pkg/auth/checker"
vpolautogen "github.com/kyverno/kyverno/pkg/cel/autogen"
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
policiesv1alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/policies.kyverno.io/v1alpha1"
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/controllers"
"github.com/kyverno/kyverno/pkg/controllers/webhook"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
datautils "github.com/kyverno/kyverno/pkg/utils/data"
"go.uber.org/multierr"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/workqueue"
@ -76,27 +76,54 @@ func (c *controller) watchdog(ctx context.Context, logger logr.Logger) {
}
func (c controller) reconcile(ctx context.Context, logger logr.Logger, key string, namespace string, name string) error {
vpol, err := c.client.PoliciesV1alpha1().ValidatingPolicies().Get(ctx, name, metav1.GetOptions{})
polType, polName := webhook.ParsePolicyKey(key)
if polType == webhook.ValidatingPolicyType {
vpol, err := c.client.PoliciesV1alpha1().ValidatingPolicies().Get(ctx, polName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
logger.V(4).Info("validating policy not found", "name", name)
logger.V(4).Info("validating policy not found", "name", polName)
return nil
}
return err
}
return c.updateStatus(ctx, vpol)
return c.updateVpolStatus(ctx, vpol)
}
if polType == webhook.ImageVerificationPolicy {
ivpol, err := c.client.PoliciesV1alpha1().ImageVerificationPolicies().Get(ctx, polName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
logger.V(4).Info("imageVerification policy not found", "name", polName)
return nil
}
return err
}
return c.updateIvpolStatus(ctx, ivpol)
}
return nil
}
func (c controller) reconcileConditions(ctx context.Context, vpol *policiesv1alpha1.ValidatingPolicy) {
if ready, ok := c.vpolStateRecorder.Ready(vpol.GetName()); ready {
vpol.GetStatus().SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeWebhookConfigured, metav1.ConditionTrue, "Webhook configured.")
func (c controller) reconcileConditions(ctx context.Context, policy engineapi.GenericPolicy) {
var key string
var matchConstraints admissionregistrationv1.MatchResources
status := &policiesv1alpha1.ConditionStatus{}
switch policy.GetKind() {
case webhook.ValidatingPolicyType:
key = webhook.BuildPolicyKey(webhook.ValidatingPolicyType, policy.GetName())
matchConstraints = policy.AsValidatingPolicy().GetMatchConstraints()
case webhook.ImageVerificationPolicy:
key = webhook.BuildPolicyKey(webhook.ImageVerificationPolicy, policy.GetName())
matchConstraints = policy.AsImageVerificationPolicy().GetMatchConstraints()
}
if ready, ok := c.vpolStateRecorder.Ready(key); ready {
status.SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeWebhookConfigured, metav1.ConditionTrue, "Webhook configured.")
} else if ok {
vpol.GetStatus().SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeWebhookConfigured, metav1.ConditionFalse, "Policy is not configured in the webhook.")
status.SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeWebhookConfigured, metav1.ConditionFalse, "Policy is not configured in the webhook.")
}
gvrs := []metav1.GroupVersionResource{}
for _, rule := range vpol.GetMatchConstraints().ResourceRules {
for _, rule := range matchConstraints.ResourceRules {
for _, g := range rule.RuleWithOperations.APIGroups {
for _, v := range rule.RuleWithOperations.APIVersions {
for _, r := range rule.RuleWithOperations.Resources {
@ -123,57 +150,8 @@ func (c controller) reconcileConditions(ctx context.Context, vpol *policiesv1alp
}
if errs != nil {
vpol.GetStatus().SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeRBACPermissionsGranted, metav1.ConditionFalse, fmt.Sprintf("Policy is not ready for reporting, missing permissions: %v.", multierr.Combine(errs...)))
status.SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeRBACPermissionsGranted, metav1.ConditionFalse, fmt.Sprintf("Policy is not ready for reporting, missing permissions: %v.", multierr.Combine(errs...)))
} else {
vpol.GetStatus().SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeRBACPermissionsGranted, metav1.ConditionTrue, "Policy is ready for reporting.")
status.SetReadyByCondition(policiesv1alpha1.PolicyConditionTypeRBACPermissionsGranted, metav1.ConditionTrue, "Policy is ready for reporting.")
}
}
func (c controller) updateStatus(ctx context.Context, vpol *policiesv1alpha1.ValidatingPolicy) error {
updateFunc := func(vpol *policiesv1alpha1.ValidatingPolicy) error {
c.reconcileConditions(ctx, vpol)
status := vpol.GetStatus()
status.Autogen.Rules = nil
rules := vpolautogen.ComputeRules(vpol)
status.Autogen.Rules = append(status.Autogen.Rules, rules...)
ready := true
for _, condition := range status.Conditions {
if condition.Status != metav1.ConditionTrue {
ready = false
break
}
}
if status.Ready == nil || *status.Ready != ready {
status.Ready = &ready
}
return nil
}
err := controllerutils.UpdateStatus(ctx,
vpol,
c.client.PoliciesV1alpha1().ValidatingPolicies(),
updateFunc,
func(current, expect *policiesv1alpha1.ValidatingPolicy) bool {
if current.GetStatus().Ready == nil || current.GetStatus().IsReady() != expect.GetStatus().IsReady() {
return false
}
if len(current.GetStatus().Conditions) != len(expect.GetStatus().Conditions) {
return false
}
for _, condition := range current.GetStatus().Conditions {
for _, expectCondition := range expect.GetStatus().Conditions {
if condition.Type == expectCondition.Type && condition.Status != expectCondition.Status {
return false
}
}
}
return datautils.DeepEqual(current.GetStatus().Autogen, expect.GetStatus().Autogen)
},
)
return err
}

View file

@ -0,0 +1,69 @@
package policystatus
import (
"context"
"fmt"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
celautogen "github.com/kyverno/kyverno/pkg/cel/autogen"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
datautils "github.com/kyverno/kyverno/pkg/utils/data"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (c controller) updateIvpolStatus(ctx context.Context, ivpol *policiesv1alpha1.ImageVerificationPolicy) error {
updateFunc := func(ivpol *policiesv1alpha1.ImageVerificationPolicy) error {
p := engineapi.NewImageVerificationPolicy(ivpol)
c.reconcileConditions(ctx, p)
status := ivpol.GetStatus()
status.Autogen.Rules = nil
autogeneratedIvPols, err := celautogen.GetAutogenRulesImageVerify(ivpol)
if err != nil {
return fmt.Errorf("failed to build autogen rules for ivpol %s: %v", ivpol.GetName(), err)
}
status.Autogen.Rules = append(status.Autogen.Rules, autogeneratedIvPols...)
ready := true
conditionStatus := status.GetConditionStatus()
for _, condition := range conditionStatus.Conditions {
if condition.Status != metav1.ConditionTrue {
ready = false
break
}
}
if conditionStatus.Ready == nil || conditionStatus.IsReady() != ready {
conditionStatus.Ready = &ready
}
status.ConditionStatus = conditionStatus
return nil
}
err := controllerutils.UpdateStatus(ctx,
ivpol,
c.client.PoliciesV1alpha1().ImageVerificationPolicies(),
updateFunc,
func(current, expect *policiesv1alpha1.ImageVerificationPolicy) bool {
if current.GetStatus().GetConditionStatus().Ready == nil || current.GetStatus().GetConditionStatus().IsReady() != expect.GetStatus().GetConditionStatus().IsReady() {
return false
}
if len(current.GetStatus().GetConditionStatus().Conditions) != len(expect.GetStatus().GetConditionStatus().Conditions) {
return false
}
for _, condition := range current.GetStatus().GetConditionStatus().Conditions {
for _, expectCondition := range expect.GetStatus().GetConditionStatus().Conditions {
if condition.Type == expectCondition.Type && condition.Status != expectCondition.Status {
return false
}
}
}
return datautils.DeepEqual(current.GetStatus().Autogen, expect.GetStatus().Autogen)
},
)
return err
}

View file

@ -0,0 +1,64 @@
package policystatus
import (
"context"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
vpolautogen "github.com/kyverno/kyverno/pkg/cel/autogen"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
datautils "github.com/kyverno/kyverno/pkg/utils/data"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (c controller) updateVpolStatus(ctx context.Context, vpol *policiesv1alpha1.ValidatingPolicy) error {
updateFunc := func(vpol *policiesv1alpha1.ValidatingPolicy) error {
p := engineapi.NewValidatingPolicy(vpol)
c.reconcileConditions(ctx, p)
status := vpol.GetStatus()
status.Autogen.Rules = nil
rules := vpolautogen.ComputeRules(vpol)
status.Autogen.Rules = append(status.Autogen.Rules, rules...)
ready := true
conditionStatus := status.GetConditionStatus()
for _, condition := range conditionStatus.Conditions {
if condition.Status != metav1.ConditionTrue {
ready = false
break
}
}
if conditionStatus.Ready == nil || conditionStatus.IsReady() != ready {
conditionStatus.Ready = &ready
}
status.ConditionStatus = conditionStatus
return nil
}
err := controllerutils.UpdateStatus(ctx,
vpol,
c.client.PoliciesV1alpha1().ValidatingPolicies(),
updateFunc,
func(current, expect *policiesv1alpha1.ValidatingPolicy) bool {
if current.GetStatus().GetConditionStatus().Ready == nil || current.GetStatus().GetConditionStatus().IsReady() != expect.GetStatus().GetConditionStatus().IsReady() {
return false
}
if len(current.GetStatus().GetConditionStatus().Conditions) != len(expect.GetStatus().GetConditionStatus().Conditions) {
return false
}
for _, condition := range current.GetStatus().GetConditionStatus().Conditions {
for _, expectCondition := range expect.GetStatus().GetConditionStatus().Conditions {
if condition.Type == expectCondition.Type && condition.Status != expectCondition.Status {
return false
}
}
}
return datautils.DeepEqual(current.GetStatus().Autogen, expect.GetStatus().Autogen)
},
)
return err
}

View file

@ -520,7 +520,7 @@ func (c *controller) updatePolicyStatus(ctx context.Context, policy engineapi.Ge
} else if vpol := policy.AsValidatingPolicy(); vpol != nil {
latest := vpol.DeepCopy()
latest.Status.Generated = generated
latest.Status.Message = msg
latest.Status.GetConditionStatus().Message = msg
new, err := c.kyvernoClient.PoliciesV1alpha1().ValidatingPolicies().UpdateStatus(ctx, latest, metav1.UpdateOptions{})
if err != nil {

View file

@ -380,7 +380,7 @@ func (c *controller) enqueueVerifyWebhook() {
c.queue.Add(config.VerifyMutatingWebhookConfigurationName)
}
func (c *controller) recordPolicyState(webhookConfigurationName string, policies ...kyvernov1.PolicyInterface) {
func (c *controller) recordKyvernoPolicyState(webhookConfigurationName string, policies ...kyvernov1.PolicyInterface) {
c.lock.Lock()
defer c.lock.Unlock()
if _, ok := c.policyState[webhookConfigurationName]; !ok {
@ -397,9 +397,11 @@ func (c *controller) recordPolicyState(webhookConfigurationName string, policies
}
}
func (c *controller) recordValidatingPolicyState(validatingpolicies ...engineapi.GenericPolicy) {
for _, policy := range validatingpolicies {
c.vpolStateRecorder.Record(policy.GetName())
func (c *controller) recordPolicyState(policies ...engineapi.GenericPolicy) {
for _, policy := range policies {
if key := BuildPolicyKey(policy.GetKind(), policy.GetName()); key != "" {
c.vpolStateRecorder.Record(key)
}
}
}
@ -822,7 +824,7 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Conte
return nil, err
}
var fineGrainedIgnoreList, fineGrainedFailList []*webhook
c.recordPolicyState(config.MutatingWebhookConfigurationName, policies...)
c.recordKyvernoPolicyState(config.MutatingWebhookConfigurationName, policies...)
for _, p := range policies {
if p.AdmissionProcessingEnabled() {
spec := p.GetSpec()
@ -852,7 +854,7 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Conte
webhooks = append(webhooks, fineGrainedFailList...)
result.Webhooks = c.buildResourceMutatingWebhookRules(caBundle, webhookCfg, &noneOnDryRun, webhooks)
} else {
c.recordPolicyState(config.MutatingWebhookConfigurationName)
c.recordKyvernoPolicyState(config.MutatingWebhookConfigurationName)
}
return &result, nil
}
@ -968,22 +970,31 @@ func (c *controller) buildForValidatingPolicies(cfg config.Configuration, caBund
return nil
}
var policies []engineapi.GenericPolicy
pols, err := c.getValidatingPolicies()
if err != nil {
return err
}
policies = append(policies, pols...)
result.Webhooks = append(result.Webhooks, buildWebhookRules(cfg,
c.server,
config.ValidatingPolicyWebhookName,
config.PolicyServicePath+config.ValidatingPolicyServicePath,
c.servicePort,
caBundle,
pols)...)
ivpols, err := c.getImageVerificationPolicy()
if err != nil {
return err
}
policies = append(policies, ivpols...)
result.Webhooks = append(result.Webhooks, buildWebhookRules(cfg,
c.server,
config.ImageVerificationPolicyWebhookName,
config.PolicyServicePath+config.ImageVerificationPolicyServicePath,
c.servicePort,
caBundle,
ivpols)...)
webhooks := buildWebhookRules(cfg, c.server, c.servicePort, caBundle, policies)
result.Webhooks = append(result.Webhooks, webhooks...)
c.recordValidatingPolicyState(policies...)
c.recordPolicyState(append(pols, ivpols...)...)
return nil
}
@ -998,7 +1009,7 @@ func (c *controller) buildForPolicies(ctx context.Context, cfg config.Configurat
}
var fineGrainedIgnoreList, fineGrainedFailList []*webhook
c.recordPolicyState(config.ValidatingWebhookConfigurationName, policies...)
c.recordKyvernoPolicyState(config.ValidatingWebhookConfigurationName, policies...)
for _, p := range policies {
if p.AdmissionProcessingEnabled() {
spec := p.GetSpec()
@ -1032,7 +1043,7 @@ func (c *controller) buildForPolicies(ctx context.Context, cfg config.Configurat
webhooks = append(webhooks, fineGrainedFailList...)
result.Webhooks = c.buildResourceValidatingWebhookRules(caBundle, webhookCfg, sideEffects, webhooks)
} else {
c.recordPolicyState(config.ValidatingWebhookConfigurationName)
c.recordKyvernoPolicyState(config.ValidatingWebhookConfigurationName)
}
return nil
}

View file

@ -174,3 +174,28 @@ func less[T cmp.Ordered](a []T, b []T) int {
}
return 0
}
const (
ValidatingPolicyType = "ValidatingPolicy"
ImageVerificationPolicy = "ImageVerificationPolicy"
)
// ParsePolicyKey builds policy key in kind/name format
func BuildPolicyKey(policyType, name string) string {
switch policyType {
case ValidatingPolicyType:
return ValidatingPolicyType + "/" + name
case ImageVerificationPolicy:
return ImageVerificationPolicy + "/" + name
}
return ""
}
// ParsePolicyKey parses policy key in kind/name format
func ParsePolicyKey(key string) (policyType, name string) {
vars := strings.Split(key, "/")
if len(vars) < 2 {
return "", ""
}
return vars[0], vars[1]
}

View file

@ -9,20 +9,20 @@ import (
"k8s.io/utils/ptr"
)
func buildWebhookRules(cfg config.Configuration, server string, servicePort int32, caBundle []byte, policies []engineapi.GenericPolicy) (webhooks []admissionregistrationv1.ValidatingWebhook) {
func buildWebhookRules(cfg config.Configuration, server, name, path string, servicePort int32, caBundle []byte, policies []engineapi.GenericPolicy) (webhooks []admissionregistrationv1.ValidatingWebhook) {
var (
webhookIgnoreList []admissionregistrationv1.ValidatingWebhook
webhookFailList []admissionregistrationv1.ValidatingWebhook
webhookIgnore = admissionregistrationv1.ValidatingWebhook{
Name: config.ValidatingPolicyWebhookName + "-ignore",
ClientConfig: newClientConfig(server, servicePort, caBundle, config.ValidatingPolicyServicePath+"/ignore"),
Name: name + "-ignore",
ClientConfig: newClientConfig(server, servicePort, caBundle, path+"/ignore"),
FailurePolicy: ptr.To(admissionregistrationv1.Ignore),
SideEffects: &noneOnDryRun,
AdmissionReviewVersions: []string{"v1"},
}
webhookFail = admissionregistrationv1.ValidatingWebhook{
Name: config.ValidatingPolicyWebhookName + "-fail",
ClientConfig: newClientConfig(server, servicePort, caBundle, config.ValidatingPolicyServicePath+"/fail"),
Name: name + "-fail",
ClientConfig: newClientConfig(server, servicePort, caBundle, path+"/fail"),
FailurePolicy: ptr.To(admissionregistrationv1.Fail),
SideEffects: &noneOnDryRun,
AdmissionReviewVersions: []string{"v1"},
@ -45,6 +45,7 @@ func buildWebhookRules(cfg config.Configuration, server string, servicePort int3
matchResource = vpol.Spec.MatchConstraints
} else if ivpol := pol.AsImageVerificationPolicy(); ivpol != nil {
p = ivpol
matchResource = ivpol.Spec.MatchConstraints
}
webhook := admissionregistrationv1.ValidatingWebhook{}
@ -91,16 +92,29 @@ func buildWebhookRules(cfg config.Configuration, server string, servicePort int3
}
}
if ivpol, ok := p.(*policiesv1alpha1.ImageVerificationPolicy); ok {
autogeneratedIvPols, err := autogen.GetAutogenRulesImageVerify(ivpol)
if err != nil {
continue
}
for _, p := range autogeneratedIvPols {
webhook.MatchConditions = append(webhook.MatchConditions, p.Spec.MatchConditions...)
for _, match := range p.Spec.MatchConstraints.ResourceRules {
webhook.Rules = append(webhook.Rules, match.RuleWithOperations)
}
}
}
if fineGrainedWebhook {
webhook.SideEffects = &noneOnDryRun
webhook.AdmissionReviewVersions = []string{"v1"}
if failurePolicyIgnore {
webhook.Name = config.ValidatingPolicyWebhookName + "-ignore-finegrained-" + p.GetName()
webhook.ClientConfig = newClientConfig(server, servicePort, caBundle, config.ValidatingPolicyServicePath+"/ignore"+config.FineGrainedWebhookPath+"/"+p.GetName())
webhook.Name = name + "-ignore-finegrained-" + p.GetName()
webhook.ClientConfig = newClientConfig(server, servicePort, caBundle, path+"/ignore"+config.FineGrainedWebhookPath+"/"+p.GetName())
webhookIgnoreList = append(webhookIgnoreList, webhook)
} else {
webhook.Name = config.ValidatingPolicyWebhookName + "-fail-finegrained-" + p.GetName()
webhook.ClientConfig = newClientConfig(server, servicePort, caBundle, config.ValidatingPolicyServicePath+"/fail"+config.FineGrainedWebhookPath+"/"+p.GetName())
webhook.Name = name + "-fail-finegrained-" + p.GetName()
webhook.ClientConfig = newClientConfig(server, servicePort, caBundle, path+"/fail"+config.FineGrainedWebhookPath+"/"+p.GetName())
webhookFailList = append(webhookFailList, webhook)
}
} else {

View file

@ -1,9 +1,12 @@
package webhook
import (
"fmt"
"testing"
"github.com/kyverno/kyverno/api/kyverno"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
celautogen "github.com/kyverno/kyverno/pkg/cel/autogen"
"github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/stretchr/testify/assert"
@ -12,7 +15,7 @@ import (
"k8s.io/utils/ptr"
)
func TestBuildWebhookRules(t *testing.T) {
func TestBuildWebhookRules_ValidatingPolicy(t *testing.T) {
tests := []struct {
name string
vpols []*policiesv1alpha1.ValidatingPolicy
@ -136,7 +139,7 @@ func TestBuildWebhookRules(t *testing.T) {
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
{
Name: config.ValidatingPolicyWebhookName + "-ignore-finegrained-test-fine-grained-ignore",
ClientConfig: newClientConfig("", 0, nil, "/policies/ignore"+config.FineGrainedWebhookPath+"/test-fine-grained-ignore"),
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/ignore"+config.FineGrainedWebhookPath+"/test-fine-grained-ignore"),
Rules: []admissionregistrationv1.RuleWithOperations{
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
@ -194,7 +197,7 @@ func TestBuildWebhookRules(t *testing.T) {
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
{
Name: config.ValidatingPolicyWebhookName + "-fail-finegrained-test-fine-grained-fail",
ClientConfig: newClientConfig("", 0, nil, "/policies/fail"+config.FineGrainedWebhookPath+"/test-fine-grained-fail"),
ClientConfig: newClientConfig("", 0, nil, "/policies/vpol/fail"+config.FineGrainedWebhookPath+"/test-fine-grained-fail"),
Rules: []admissionregistrationv1.RuleWithOperations{
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
@ -226,7 +229,8 @@ func TestBuildWebhookRules(t *testing.T) {
for _, vpol := range tt.vpols {
vpols = append(vpols, engineapi.NewValidatingPolicy(vpol))
}
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", 0, nil, vpols)
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", config.ValidatingPolicyWebhookName,
config.PolicyServicePath+config.ValidatingPolicyServicePath, 0, nil, vpols)
assert.Equal(t, len(tt.expectedWebhooks), len(webhooks))
for i, expect := range tt.expectedWebhooks {
assert.Equal(t, expect.Name, webhooks[i].Name)
@ -249,3 +253,215 @@ func TestBuildWebhookRules(t *testing.T) {
})
}
}
func TestBuildWebhookRules_ImageVerificationPolicy(t *testing.T) {
tests := []struct {
name string
ivpols []*policiesv1alpha1.ImageVerificationPolicy
expectedWebhooks []admissionregistrationv1.ValidatingWebhook
}{
{
name: "Autogen Single Ignore Policy",
ivpols: []*policiesv1alpha1.ImageVerificationPolicy{
{
Spec: policiesv1alpha1.ImageVerificationPolicySpec{
FailurePolicy: ptr.To(admissionregistrationv1.Ignore),
MatchConstraints: &admissionregistrationv1.MatchResources{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
},
},
},
},
},
},
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
{
Name: config.ImageVerificationPolicyWebhookName + "-ignore",
Rules: []admissionregistrationv1.RuleWithOperations{
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"daemonsets", "deployments", "replicasets", "statefulsets"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"batch"},
APIVersions: []string{"v1"},
Resources: []string{"jobs"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"batch"},
APIVersions: []string{"v1"},
Resources: []string{"cronjobs"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
},
FailurePolicy: ptr.To(admissionregistrationv1.Ignore),
},
},
},
{
name: "Autogen Fine-grained Ignore Policy",
ivpols: []*policiesv1alpha1.ImageVerificationPolicy{
{
ObjectMeta: metav1.ObjectMeta{
Name: "ivpol-sample",
Annotations: map[string]string{
kyverno.AnnotationAutogenControllers: "deployments,jobs,cronjobs",
},
},
Spec: policiesv1alpha1.ImageVerificationPolicySpec{
FailurePolicy: ptr.To(admissionregistrationv1.Ignore),
MatchConstraints: &admissionregistrationv1.MatchResources{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
},
},
},
MatchConditions: []admissionregistrationv1.MatchCondition{
{
Name: "check-prod-label",
Expression: "has(object.metadata.labels) && has(object.metadata.labels.prod) && object.metadata.labels.prod == 'true'",
},
},
},
},
},
expectedWebhooks: []admissionregistrationv1.ValidatingWebhook{
{
Name: config.ImageVerificationPolicyWebhookName + "-ignore-finegrained-ivpol-sample",
ClientConfig: newClientConfig("", 0, nil, "/policies/ivpol/ignore"+config.FineGrainedWebhookPath+"/ivpol-sample"),
Rules: []admissionregistrationv1.RuleWithOperations{
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"batch"},
APIVersions: []string{"v1"},
Resources: []string{"jobs"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
{
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"batch"},
APIVersions: []string{"v1"},
Resources: []string{"cronjobs"},
Scope: ptr.To(admissionregistrationv1.ScopeType("*")),
},
},
},
FailurePolicy: ptr.To(admissionregistrationv1.Ignore),
MatchConditions: []admissionregistrationv1.MatchCondition{
{
Name: "check-prod-label",
Expression: "!(object.kind == 'Pod') || has(object.metadata.labels) && has(object.metadata.labels.prod) && object.metadata.labels.prod == 'true'",
},
{
Name: "autogen-check-prod-label",
Expression: celautogen.PodControllersMatchConditionExpression + "has(object.spec.template.metadata.labels) && has(object.spec.template.metadata.labels.prod) && object.spec.template.metadata.labels.prod == 'true'",
},
{
Name: "autogen-cronjobs-check-prod-label",
Expression: celautogen.CronJobMatchConditionExpression + "has(object.spec.jobTemplate.spec.template.metadata.labels) && has(object.spec.jobTemplate.spec.template.metadata.labels.prod) && object.spec.jobTemplate.spec.template.metadata.labels.prod == 'true'",
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var ivpols []engineapi.GenericPolicy
for _, ivpol := range tt.ivpols {
ivpols = append(ivpols, engineapi.NewImageVerificationPolicy(ivpol))
}
webhooks := buildWebhookRules(config.NewDefaultConfiguration(false), "", config.ImageVerificationPolicyWebhookName,
config.PolicyServicePath+config.ImageVerificationPolicyServicePath, 0, nil, ivpols)
assert.Equal(t, len(tt.expectedWebhooks), len(webhooks), tt.name)
for i, expect := range tt.expectedWebhooks {
assert.Equal(t, expect.Name, webhooks[i].Name)
assert.Equal(t, expect.FailurePolicy, webhooks[i].FailurePolicy)
assert.Equal(t, len(expect.Rules), len(webhooks[i].Rules), fmt.Sprintf("expected: %v,\n got: %v", expect.Rules, webhooks[i].Rules))
if expect.MatchConditions != nil {
for m, mExpect := range expect.MatchConditions {
for n, mActual := range webhooks[i].MatchConditions {
if mExpect.Name != mActual.Name {
continue
}
assert.Equal(t, expect.MatchConditions[m], webhooks[i].MatchConditions[n])
}
}
}
if expect.MatchPolicy != nil {
assert.Equal(t, expect.MatchPolicy, webhooks[i].MatchPolicy)
}
if expect.TimeoutSeconds != nil {
assert.Equal(t, expect.TimeoutSeconds, webhooks[i].TimeoutSeconds)
}
if expect.ClientConfig.Service != nil {
assert.Equal(t, *webhooks[i].ClientConfig.Service.Path, *expect.ClientConfig.Service.Path)
}
}
})
}
}

View file

@ -1,7 +1,6 @@
package eval
import (
"github.com/go-logr/logr"
"github.com/google/cel-go/cel"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
engine "github.com/kyverno/kyverno/pkg/cel"
@ -32,7 +31,7 @@ const (
)
type Compiler interface {
Compile(logr.Logger, *policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList)
Compile(*policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList)
}
func NewCompiler(ictx imagedataloader.ImageContext, lister k8scorev1.SecretInterface, reqGVR *metav1.GroupVersionResource) Compiler {
@ -49,7 +48,7 @@ type compiler struct {
reqGVR *metav1.GroupVersionResource
}
func (c *compiler) Compile(logger logr.Logger, ivpolicy *policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList) {
func (c *compiler) Compile(ivpolicy *policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList) {
var allErrs field.ErrorList
base, err := engine.NewEnv()
if err != nil {
@ -77,7 +76,7 @@ func (c *compiler) Compile(logger logr.Logger, ivpolicy *policiesv1alpha1.ImageV
for _, declType := range declTypes {
options = append(options, cel.Types(declType.CelType()))
}
options = append(options, imageverifierfunctions.Lib(logger, c.ictx, ivpolicy, c.lister), context.Lib(), http.Lib(), user.Lib())
options = append(options, imageverifierfunctions.Lib(c.ictx, ivpolicy, c.lister), context.Lib(), http.Lib(), user.Lib())
env, err := base.Extend(options...)
if err != nil {
return nil, append(allErrs, field.InternalError(nil, err))

View file

@ -4,7 +4,6 @@ import (
"context"
"fmt"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
"github.com/kyverno/kyverno/pkg/imageverification/imagedataloader"
admissionv1 "k8s.io/api/admission/v1"
@ -14,7 +13,7 @@ import (
k8scorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
)
func Evaluate(ctx context.Context, logger logr.Logger, ivpols []*v1alpha1.ImageVerificationPolicy, request interface{}, admissionAttr admission.Attributes, namespace runtime.Object, lister k8scorev1.SecretInterface, registryOpts ...imagedataloader.Option) (map[string]*EvaluationResult, error) {
func Evaluate(ctx context.Context, ivpols []*v1alpha1.ImageVerificationPolicy, request interface{}, admissionAttr admission.Attributes, namespace runtime.Object, lister k8scorev1.SecretInterface, registryOpts ...imagedataloader.Option) (map[string]*EvaluationResult, error) {
ictx, err := imagedataloader.NewImageContext(lister, registryOpts...)
if err != nil {
return nil, err
@ -32,7 +31,7 @@ func Evaluate(ctx context.Context, logger logr.Logger, ivpols []*v1alpha1.ImageV
c := NewCompiler(ictx, lister, gvr)
results := make(map[string]*EvaluationResult, len(policies))
for _, ivpol := range policies {
p, errList := c.Compile(logger, ivpol)
p, errList := c.Compile(ivpol)
if errList != nil {
return nil, fmt.Errorf("failed to compile policy %v", errList)
}

View file

@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/go-logr/logr"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
"github.com/stretchr/testify/assert"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
@ -92,12 +91,12 @@ uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
)
func Test_Eval(t *testing.T) {
result, err := Evaluate(context.Background(), logr.Discard(), []*policiesv1alpha1.ImageVerificationPolicy{ivpol}, obj(signedImage), nil, nil, nil)
result, err := Evaluate(context.Background(), []*policiesv1alpha1.ImageVerificationPolicy{ivpol}, obj(signedImage), nil, nil, nil)
assert.NoError(t, err)
assert.True(t, len(result) == 1)
assert.True(t, result[ivpol.Name].Result)
result, err = Evaluate(context.Background(), logr.Discard(), []*policiesv1alpha1.ImageVerificationPolicy{ivpol}, obj(unsignedImage), nil, nil, nil)
result, err = Evaluate(context.Background(), []*policiesv1alpha1.ImageVerificationPolicy{ivpol}, obj(unsignedImage), nil, nil, nil)
assert.NoError(t, err)
assert.True(t, len(result) == 1)
assert.False(t, result[ivpol.Name].Result)

View file

@ -0,0 +1,5 @@
package eval
import "github.com/kyverno/kyverno/pkg/logging"
var logger = logging.WithName("ivpol/evaluator")

View file

@ -4,7 +4,6 @@ import (
"encoding/json"
"strings"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/api/kyverno"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
@ -55,7 +54,7 @@ func outcomeFromPolicyResponse(responses map[string]ImageVerifyPolicyResponse) m
return outcomes
}
func MakeImageVerifyOutcomePatch(hasAnnotations bool, log logr.Logger, responses map[string]ImageVerifyPolicyResponse) ([]jsonpatch.JsonPatchOperation, error) {
func MakeImageVerifyOutcomePatch(hasAnnotations bool, responses map[string]ImageVerifyPolicyResponse) ([]jsonpatch.JsonPatchOperation, error) {
patches := make([]jsonpatch.JsonPatchOperation, 0)
annotationKey := "/metadata/annotations/" + strings.ReplaceAll(kyverno.AnnotationImageVerifyOutcomes, "/", "~1")
if !hasAnnotations {
@ -64,7 +63,7 @@ func MakeImageVerifyOutcomePatch(hasAnnotations bool, log logr.Logger, responses
Path: "/metadata/annotations",
Value: map[string]string{},
}
log.V(4).Info("adding annotation patch", "patch", patch)
logger.V(4).Info("adding annotation patch", "patch", patch)
patches = append(patches, patch)
}
@ -80,7 +79,7 @@ func MakeImageVerifyOutcomePatch(hasAnnotations bool, log logr.Logger, responses
Value: string(data),
}
log.V(4).Info("adding image verification patch", "patch", patch)
logger.V(4).Info("adding image verification patch", "patch", patch)
patches = append(patches, patch)
return patches, nil
}

View file

@ -3,7 +3,6 @@ package imageverifierfunctions
import (
"testing"
"github.com/go-logr/logr"
"github.com/google/cel-go/cel"
"github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
"github.com/kyverno/kyverno/pkg/imageverification/imagedataloader"
@ -57,7 +56,7 @@ uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
func Test_impl_verify_image_signature_string_stringarray(t *testing.T) {
imgCtx, err := imagedataloader.NewImageContext(nil)
assert.NoError(t, err)
opts := Lib(logr.Discard(), imgCtx, ivpol, nil)
opts := Lib(imgCtx, ivpol, nil)
env, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, env)
@ -79,7 +78,7 @@ func Test_impl_verify_image_signature_string_stringarray(t *testing.T) {
func Test_impl_verify_image_attestations_string_string_stringarray(t *testing.T) {
imgCtx, err := imagedataloader.NewImageContext(nil)
assert.NoError(t, err)
opts := Lib(logr.Discard(), imgCtx, ivpol, nil)
opts := Lib(imgCtx, ivpol, nil)
env, err := cel.NewEnv(opts)
assert.NoError(t, err)
assert.NotNil(t, env)

View file

@ -21,7 +21,7 @@ type lib struct {
lister k8scorev1.SecretInterface
}
func Lib(logger logr.Logger, imgCtx imagedataloader.ImageContext, ivpol *v1alpha1.ImageVerificationPolicy, lister k8scorev1.SecretInterface) cel.EnvOption {
func Lib(imgCtx imagedataloader.ImageContext, ivpol *v1alpha1.ImageVerificationPolicy, lister k8scorev1.SecretInterface) cel.EnvOption {
// create the cel lib env option
return cel.Lib(&lib{
imgCtx: imgCtx,

View file

@ -70,6 +70,7 @@ func NewServer(
globalContextLogger := logger.WithName("globalcontext")
verifyLogger := logger.WithName("verify")
vpolLogger := logger.WithName("vpol")
ivpolLogger := logger.WithName("ivpol")
registerWebhookHandlersWithAll(
mux,
"MUTATE",
@ -106,7 +107,7 @@ func NewServer(
registerWebhookHandlers(
mux,
"VPOL",
config.ValidatingPolicyServicePath,
config.PolicyServicePath+config.ValidatingPolicyServicePath,
resourceHandlers.ValidatingPolicies,
func(handler handlers.AdmissionHandler) handlers.HttpHandler {
return handler.
@ -119,6 +120,22 @@ func NewServer(
WithAdmission(vpolLogger.WithName("validate"))
},
)
registerWebhookHandlers(
mux,
"IVPOL",
config.PolicyServicePath+config.ImageVerificationPolicyServicePath,
resourceHandlers.ImageVerificationPolicies,
func(handler handlers.AdmissionHandler) handlers.HttpHandler {
return handler.
WithFilter(configuration).
WithProtection(toggle.FromContext(ctx).ProtectManagedResources()).
WithDump(debugModeOpts.DumpPayload).
WithTopLevelGVK(discovery).
WithRoles(rbLister, crbLister).
WithMetrics(resourceLogger, metricsConfig.Config(), metrics.WebhookValidating).
WithAdmission(ivpolLogger.WithName("validate"))
},
)
mux.HandlerFunc(
"POST",
config.PolicyMutatingWebhookServicePath,

View file

@ -54,4 +54,6 @@ type ResourceHandlers struct {
Validation Handler
// ValidatingPolicies evaluates validating policies against kube resources
ValidatingPolicies Handler
// ImageVerificationPolicies evaluates imageverificationpolicies against kube resources
ImageVerificationPolicies Handler
}

View file

@ -11,7 +11,7 @@ webhooks:
service:
name: kyverno-svc
namespace: kyverno
path: /policies/fail/finegrained/disallow-privilege-escalation
path: /policies/vpol/fail/finegrained/disallow-privilege-escalation
port: 443
failurePolicy: Fail
matchConditions:

View file

@ -11,7 +11,7 @@ webhooks:
service:
name: kyverno-svc
namespace: kyverno
path: /policies/fail
path: /policies/vpol/fail
port: 443
failurePolicy: Fail
matchPolicy: Equivalent

View file

@ -11,7 +11,7 @@ webhooks:
service:
name: kyverno-svc
namespace: kyverno
path: /policies/fail
path: /policies/vpol/fail
port: 443
failurePolicy: Fail
matchPolicy: Equivalent