mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-21 07:12:42 +00:00
feat: reconcile ivpol.status
(#12392)
* 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:
parent
af550f54d5
commit
5c5a5fc0b0
43 changed files with 5090 additions and 2554 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -13,5 +13,4 @@ type GenericPolicy interface {
|
|||
GetFailurePolicy() admissionregistrationv1.FailurePolicyType
|
||||
GetWebhookConfiguration() *WebhookConfiguration
|
||||
GetVariables() []admissionregistrationv1.Variable
|
||||
GetStatus() *PolicyStatus
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
Ready: ptr.To(true),
|
||||
status: VpolStatus{
|
||||
ConditionStatus: &ConditionStatus{
|
||||
Ready: ptr.To(true),
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
name: "false",
|
||||
status: PolicyStatus{
|
||||
Ready: ptr.To(false),
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
@ -712,9 +731,10 @@ func main() {
|
|||
Validation: webhooks.HandlerFunc(policyHandlers.Validate),
|
||||
},
|
||||
webhooks.ResourceHandlers{
|
||||
Mutation: webhooks.HandlerFunc(resourceHandlers.Mutate),
|
||||
Validation: webhooks.HandlerFunc(resourceHandlers.Validate),
|
||||
ValidatingPolicies: webhooks.HandlerFunc(voplHandlers.Validate),
|
||||
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),
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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’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’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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
logger.V(4).Info("validating policy not found", "name", name)
|
||||
return nil
|
||||
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", polName)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
69
pkg/controllers/policystatus/ivpol.go
Normal file
69
pkg/controllers/policystatus/ivpol.go
Normal 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
|
||||
}
|
64
pkg/controllers/policystatus/vpol.go
Normal file
64
pkg/controllers/policystatus/vpol.go
Normal 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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
5
pkg/imageverification/evaluator/log.go
Normal file
5
pkg/imageverification/evaluator/log.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package eval
|
||||
|
||||
import "github.com/kyverno/kyverno/pkg/logging"
|
||||
|
||||
var logger = logging.WithName("ivpol/evaluator")
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -11,7 +11,7 @@ webhooks:
|
|||
service:
|
||||
name: kyverno-svc
|
||||
namespace: kyverno
|
||||
path: /policies/fail
|
||||
path: /policies/vpol/fail
|
||||
port: 443
|
||||
failurePolicy: Fail
|
||||
matchPolicy: Equivalent
|
||||
|
|
|
@ -11,7 +11,7 @@ webhooks:
|
|||
service:
|
||||
name: kyverno-svc
|
||||
namespace: kyverno
|
||||
path: /policies/fail
|
||||
path: /policies/vpol/fail
|
||||
port: 443
|
||||
failurePolicy: Fail
|
||||
matchPolicy: Equivalent
|
||||
|
|
Loading…
Add table
Reference in a new issue