mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
feat: generate events for CEL policies that generate VAPs (#8564)
Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
parent
5882ed32a3
commit
8cbe66a06a
3 changed files with 64 additions and 25 deletions
|
@ -116,6 +116,7 @@ func createrLeaderControllers(
|
||||||
runtime runtimeutils.Runtime,
|
runtime runtimeutils.Runtime,
|
||||||
servicePort int32,
|
servicePort int32,
|
||||||
configuration config.Configuration,
|
configuration config.Configuration,
|
||||||
|
eventGenerator event.Interface,
|
||||||
) ([]internal.Controller, func(context.Context) error, error) {
|
) ([]internal.Controller, func(context.Context) error, error) {
|
||||||
var leaderControllers []internal.Controller
|
var leaderControllers []internal.Controller
|
||||||
|
|
||||||
|
@ -188,6 +189,7 @@ func createrLeaderControllers(
|
||||||
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
||||||
kubeInformer.Admissionregistration().V1alpha1().ValidatingAdmissionPolicies(),
|
kubeInformer.Admissionregistration().V1alpha1().ValidatingAdmissionPolicies(),
|
||||||
kubeInformer.Admissionregistration().V1alpha1().ValidatingAdmissionPolicyBindings(),
|
kubeInformer.Admissionregistration().V1alpha1().ValidatingAdmissionPolicyBindings(),
|
||||||
|
eventGenerator,
|
||||||
)
|
)
|
||||||
leaderControllers = append(leaderControllers, internal.NewController(vapcontroller.ControllerName, vapController, vapcontroller.Workers))
|
leaderControllers = append(leaderControllers, internal.NewController(vapcontroller.ControllerName, vapController, vapcontroller.Workers))
|
||||||
}
|
}
|
||||||
|
@ -409,6 +411,7 @@ func main() {
|
||||||
runtime,
|
runtime,
|
||||||
int32(servicePort),
|
int32(servicePort),
|
||||||
setup.Configuration,
|
setup.Configuration,
|
||||||
|
eventGenerator,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to create leader controllers")
|
logger.Error(err, "failed to create leader controllers")
|
||||||
|
|
|
@ -11,11 +11,12 @@ import (
|
||||||
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/controllers"
|
"github.com/kyverno/kyverno/pkg/controllers"
|
||||||
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
"github.com/kyverno/kyverno/pkg/logging"
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||||
"k8s.io/api/admissionregistration/v1alpha1"
|
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
admissionregistrationv1alpha1informers "k8s.io/client-go/informers/admissionregistration/v1alpha1"
|
admissionregistrationv1alpha1informers "k8s.io/client-go/informers/admissionregistration/v1alpha1"
|
||||||
|
@ -45,6 +46,8 @@ type controller struct {
|
||||||
|
|
||||||
// queue
|
// queue
|
||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
|
|
||||||
|
eventGen event.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewController(
|
func NewController(
|
||||||
|
@ -55,6 +58,7 @@ func NewController(
|
||||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||||
vapInformer admissionregistrationv1alpha1informers.ValidatingAdmissionPolicyInformer,
|
vapInformer admissionregistrationv1alpha1informers.ValidatingAdmissionPolicyInformer,
|
||||||
vapbindingInformer admissionregistrationv1alpha1informers.ValidatingAdmissionPolicyBindingInformer,
|
vapbindingInformer admissionregistrationv1alpha1informers.ValidatingAdmissionPolicyBindingInformer,
|
||||||
|
eventGen event.Interface,
|
||||||
) controllers.Controller {
|
) controllers.Controller {
|
||||||
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
queue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), ControllerName)
|
||||||
c := &controller{
|
c := &controller{
|
||||||
|
@ -65,6 +69,7 @@ func NewController(
|
||||||
vapLister: vapInformer.Lister(),
|
vapLister: vapInformer.Lister(),
|
||||||
vapbindingLister: vapbindingInformer.Lister(),
|
vapbindingLister: vapbindingInformer.Lister(),
|
||||||
queue: queue,
|
queue: queue,
|
||||||
|
eventGen: eventGen,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up an event handler for when Kyverno policies change
|
// Set up an event handler for when Kyverno policies change
|
||||||
|
@ -126,22 +131,22 @@ func (c *controller) enqueuePolicy(obj kyvernov1.PolicyInterface) {
|
||||||
c.queue.Add(key)
|
c.queue.Add(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) addVAP(obj *v1alpha1.ValidatingAdmissionPolicy) {
|
func (c *controller) addVAP(obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicy) {
|
||||||
c.enqueueVAP(obj)
|
c.enqueueVAP(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) updateVAP(old, obj *v1alpha1.ValidatingAdmissionPolicy) {
|
func (c *controller) updateVAP(old, obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicy) {
|
||||||
if datautils.DeepEqual(old.Spec, obj.Spec) {
|
if datautils.DeepEqual(old.Spec, obj.Spec) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.enqueueVAP(obj)
|
c.enqueueVAP(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) deleteVAP(obj *v1alpha1.ValidatingAdmissionPolicy) {
|
func (c *controller) deleteVAP(obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicy) {
|
||||||
c.enqueueVAP(obj)
|
c.enqueueVAP(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) enqueueVAP(v *v1alpha1.ValidatingAdmissionPolicy) {
|
func (c *controller) enqueueVAP(v *admissionregistrationv1alpha1.ValidatingAdmissionPolicy) {
|
||||||
if len(v.OwnerReferences) == 1 {
|
if len(v.OwnerReferences) == 1 {
|
||||||
if v.OwnerReferences[0].Kind == "ClusterPolicy" {
|
if v.OwnerReferences[0].Kind == "ClusterPolicy" {
|
||||||
cpol, err := c.cpolLister.Get(v.OwnerReferences[0].Name)
|
cpol, err := c.cpolLister.Get(v.OwnerReferences[0].Name)
|
||||||
|
@ -153,22 +158,22 @@ func (c *controller) enqueueVAP(v *v1alpha1.ValidatingAdmissionPolicy) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) addVAPbinding(obj *v1alpha1.ValidatingAdmissionPolicyBinding) {
|
func (c *controller) addVAPbinding(obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||||
c.enqueueVAPbinding(obj)
|
c.enqueueVAPbinding(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) updateVAPbinding(old, obj *v1alpha1.ValidatingAdmissionPolicyBinding) {
|
func (c *controller) updateVAPbinding(old, obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||||
if datautils.DeepEqual(old.Spec, obj.Spec) {
|
if datautils.DeepEqual(old.Spec, obj.Spec) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.enqueueVAPbinding(obj)
|
c.enqueueVAPbinding(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) deleteVAPbinding(obj *v1alpha1.ValidatingAdmissionPolicyBinding) {
|
func (c *controller) deleteVAPbinding(obj *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||||
c.enqueueVAPbinding(obj)
|
c.enqueueVAPbinding(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) enqueueVAPbinding(vb *v1alpha1.ValidatingAdmissionPolicyBinding) {
|
func (c *controller) enqueueVAPbinding(vb *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||||
if len(vb.OwnerReferences) == 1 {
|
if len(vb.OwnerReferences) == 1 {
|
||||||
if vb.OwnerReferences[0].Kind == "ClusterPolicy" {
|
if vb.OwnerReferences[0].Kind == "ClusterPolicy" {
|
||||||
cpol, err := c.cpolLister.Get(vb.OwnerReferences[0].Name)
|
cpol, err := c.cpolLister.Get(vb.OwnerReferences[0].Name)
|
||||||
|
@ -188,7 +193,7 @@ func (c *controller) getClusterPolicy(name string) (*kyvernov1.ClusterPolicy, er
|
||||||
return cpolicy, nil
|
return cpolicy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) getValidatingAdmissionPolicy(name string) (*v1alpha1.ValidatingAdmissionPolicy, error) {
|
func (c *controller) getValidatingAdmissionPolicy(name string) (*admissionregistrationv1alpha1.ValidatingAdmissionPolicy, error) {
|
||||||
vap, err := c.vapLister.Get(name)
|
vap, err := c.vapLister.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -196,7 +201,7 @@ func (c *controller) getValidatingAdmissionPolicy(name string) (*v1alpha1.Valida
|
||||||
return vap, nil
|
return vap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) getValidatingAdmissionPolicyBinding(name string) (*v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
func (c *controller) getValidatingAdmissionPolicyBinding(name string) (*admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||||
vapbinding, err := c.vapbindingLister.Get(name)
|
vapbinding, err := c.vapbindingLister.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -204,7 +209,7 @@ func (c *controller) getValidatingAdmissionPolicyBinding(name string) (*v1alpha1
|
||||||
return vapbinding, nil
|
return vapbinding, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) buildValidatingAdmissionPolicy(vap *v1alpha1.ValidatingAdmissionPolicy, cpol kyvernov1.PolicyInterface) error {
|
func (c *controller) buildValidatingAdmissionPolicy(vap *admissionregistrationv1alpha1.ValidatingAdmissionPolicy, cpol kyvernov1.PolicyInterface) error {
|
||||||
// set owner reference
|
// set owner reference
|
||||||
vap.OwnerReferences = []metav1.OwnerReference{
|
vap.OwnerReferences = []metav1.OwnerReference{
|
||||||
{
|
{
|
||||||
|
@ -216,8 +221,8 @@ func (c *controller) buildValidatingAdmissionPolicy(vap *v1alpha1.ValidatingAdmi
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct validating admission policy resource rules
|
// construct validating admission policy resource rules
|
||||||
var matchResources v1alpha1.MatchResources
|
var matchResources admissionregistrationv1alpha1.MatchResources
|
||||||
var matchRules []v1alpha1.NamedRuleWithOperations
|
var matchRules []admissionregistrationv1alpha1.NamedRuleWithOperations
|
||||||
|
|
||||||
rule := cpol.GetSpec().Rules[0]
|
rule := cpol.GetSpec().Rules[0]
|
||||||
match := rule.MatchResources
|
match := rule.MatchResources
|
||||||
|
@ -239,7 +244,7 @@ func (c *controller) buildValidatingAdmissionPolicy(vap *v1alpha1.ValidatingAdmi
|
||||||
}
|
}
|
||||||
|
|
||||||
// set validating admission policy spec
|
// set validating admission policy spec
|
||||||
vap.Spec = v1alpha1.ValidatingAdmissionPolicySpec{
|
vap.Spec = admissionregistrationv1alpha1.ValidatingAdmissionPolicySpec{
|
||||||
MatchConstraints: &matchResources,
|
MatchConstraints: &matchResources,
|
||||||
ParamKind: rule.Validation.CEL.ParamKind,
|
ParamKind: rule.Validation.CEL.ParamKind,
|
||||||
Variables: rule.Validation.CEL.Variables,
|
Variables: rule.Validation.CEL.Variables,
|
||||||
|
@ -253,7 +258,7 @@ func (c *controller) buildValidatingAdmissionPolicy(vap *v1alpha1.ValidatingAdmi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) buildValidatingAdmissionPolicyBinding(vapbinding *v1alpha1.ValidatingAdmissionPolicyBinding, cpol kyvernov1.PolicyInterface) error {
|
func (c *controller) buildValidatingAdmissionPolicyBinding(vapbinding *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding, cpol kyvernov1.PolicyInterface) error {
|
||||||
// set owner reference
|
// set owner reference
|
||||||
vapbinding.OwnerReferences = []metav1.OwnerReference{
|
vapbinding.OwnerReferences = []metav1.OwnerReference{
|
||||||
{
|
{
|
||||||
|
@ -265,18 +270,18 @@ func (c *controller) buildValidatingAdmissionPolicyBinding(vapbinding *v1alpha1.
|
||||||
}
|
}
|
||||||
|
|
||||||
// set validation action for vap binding
|
// set validation action for vap binding
|
||||||
var validationActions []v1alpha1.ValidationAction
|
var validationActions []admissionregistrationv1alpha1.ValidationAction
|
||||||
action := cpol.GetSpec().ValidationFailureAction
|
action := cpol.GetSpec().ValidationFailureAction
|
||||||
if action.Enforce() {
|
if action.Enforce() {
|
||||||
validationActions = append(validationActions, v1alpha1.Deny)
|
validationActions = append(validationActions, admissionregistrationv1alpha1.Deny)
|
||||||
} else if action.Audit() {
|
} else if action.Audit() {
|
||||||
validationActions = append(validationActions, v1alpha1.Audit)
|
validationActions = append(validationActions, admissionregistrationv1alpha1.Audit)
|
||||||
validationActions = append(validationActions, v1alpha1.Warn)
|
validationActions = append(validationActions, admissionregistrationv1alpha1.Warn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set validating admission policy binding spec
|
// set validating admission policy binding spec
|
||||||
rule := cpol.GetSpec().Rules[0]
|
rule := cpol.GetSpec().Rules[0]
|
||||||
vapbinding.Spec = v1alpha1.ValidatingAdmissionPolicyBindingSpec{
|
vapbinding.Spec = admissionregistrationv1alpha1.ValidatingAdmissionPolicyBindingSpec{
|
||||||
PolicyName: cpol.GetName(),
|
PolicyName: cpol.GetName(),
|
||||||
ParamRef: rule.Validation.CEL.ParamRef,
|
ParamRef: rule.Validation.CEL.ParamRef,
|
||||||
ValidationActions: validationActions,
|
ValidationActions: validationActions,
|
||||||
|
@ -314,7 +319,7 @@ func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, nam
|
||||||
c.updateClusterPolicyStatus(ctx, *policy, false, err.Error())
|
c.updateClusterPolicyStatus(ctx, *policy, false, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
observedVAP = &v1alpha1.ValidatingAdmissionPolicy{
|
observedVAP = &admissionregistrationv1alpha1.ValidatingAdmissionPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: polName,
|
Name: polName,
|
||||||
},
|
},
|
||||||
|
@ -327,7 +332,7 @@ func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, nam
|
||||||
c.updateClusterPolicyStatus(ctx, *policy, false, err.Error())
|
c.updateClusterPolicyStatus(ctx, *policy, false, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
observedVAPbinding = &v1alpha1.ValidatingAdmissionPolicyBinding{
|
observedVAPbinding = &admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: polName + "-binding",
|
Name: polName + "-binding",
|
||||||
},
|
},
|
||||||
|
@ -350,7 +355,7 @@ func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, nam
|
||||||
ctx,
|
ctx,
|
||||||
observedVAP,
|
observedVAP,
|
||||||
c.client.AdmissionregistrationV1alpha1().ValidatingAdmissionPolicies(),
|
c.client.AdmissionregistrationV1alpha1().ValidatingAdmissionPolicies(),
|
||||||
func(observed *v1alpha1.ValidatingAdmissionPolicy) error {
|
func(observed *admissionregistrationv1alpha1.ValidatingAdmissionPolicy) error {
|
||||||
return c.buildValidatingAdmissionPolicy(observed, policy)
|
return c.buildValidatingAdmissionPolicy(observed, policy)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -375,7 +380,7 @@ func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, nam
|
||||||
ctx,
|
ctx,
|
||||||
observedVAPbinding,
|
observedVAPbinding,
|
||||||
c.client.AdmissionregistrationV1alpha1().ValidatingAdmissionPolicyBindings(),
|
c.client.AdmissionregistrationV1alpha1().ValidatingAdmissionPolicyBindings(),
|
||||||
func(observed *v1alpha1.ValidatingAdmissionPolicyBinding) error {
|
func(observed *admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) error {
|
||||||
return c.buildValidatingAdmissionPolicyBinding(observed, policy)
|
return c.buildValidatingAdmissionPolicyBinding(observed, policy)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -385,6 +390,9 @@ func (c *controller) reconcile(ctx context.Context, logger logr.Logger, key, nam
|
||||||
}
|
}
|
||||||
|
|
||||||
c.updateClusterPolicyStatus(ctx, *policy, true, "")
|
c.updateClusterPolicyStatus(ctx, *policy, true, "")
|
||||||
|
// generate events
|
||||||
|
e := event.NewValidatingAdmissionPolicyEvent(policy, observedVAP.Name, observedVAPbinding.Name)
|
||||||
|
c.eventGen.Add(e...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,34 @@ func NewCleanupPolicyEvent(policy kyvernov2alpha1.CleanupPolicyInterface, resour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewValidatingAdmissionPolicyEvent(policy kyvernov1.PolicyInterface, vapName, vapBindingName string) []Info {
|
||||||
|
vapEvent := Info{
|
||||||
|
Kind: policy.GetKind(),
|
||||||
|
Namespace: policy.GetNamespace(),
|
||||||
|
Name: policy.GetName(),
|
||||||
|
RelatedAPIVersion: "admissionregistration.k8s.io/v1alpha1",
|
||||||
|
RelatedKind: "ValidatingAdmissionPolicy",
|
||||||
|
RelatedName: vapName,
|
||||||
|
Source: GeneratePolicyController,
|
||||||
|
Action: ResourceGenerated,
|
||||||
|
Reason: PolicyApplied,
|
||||||
|
Message: fmt.Sprintf("successfully generated validating admission policy %s from policy %s", vapName, policy.GetName()),
|
||||||
|
}
|
||||||
|
vapBindingEvent := Info{
|
||||||
|
Kind: policy.GetKind(),
|
||||||
|
Namespace: policy.GetNamespace(),
|
||||||
|
Name: policy.GetName(),
|
||||||
|
RelatedAPIVersion: "admissionregistration.k8s.io/v1alpha1",
|
||||||
|
RelatedKind: "ValidatingAdmissionPolicyBinding",
|
||||||
|
RelatedName: vapBindingName,
|
||||||
|
Source: GeneratePolicyController,
|
||||||
|
Action: ResourceGenerated,
|
||||||
|
Reason: PolicyApplied,
|
||||||
|
Message: fmt.Sprintf("successfully generated validating admission policy binding %s from policy %s", vapBindingName, policy.GetName()),
|
||||||
|
}
|
||||||
|
return []Info{vapEvent, vapBindingEvent}
|
||||||
|
}
|
||||||
|
|
||||||
func NewFailedEvent(err error, policy, rule string, source Source, resource kyvernov1.ResourceSpec) Info {
|
func NewFailedEvent(err error, policy, rule string, source Source, resource kyvernov1.ResourceSpec) Info {
|
||||||
return Info{
|
return Info{
|
||||||
Kind: resource.GetKind(),
|
Kind: resource.GetKind(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue