1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/policy/updaterequest.go

161 lines
5.2 KiB
Go
Raw Normal View History

package policy
import (
"context"
"fmt"
"github.com/gardener/controller-manager-library/pkg/logger"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInterface) {
logger := pc.log.WithName("updateUR").WithName(policyKey)
logger.Info("update URs on policy event")
mutateURs := pc.listMutateURs(policyKey, nil)
generateURs := pc.listGenerateURs(policyKey, nil)
updateUR(pc.kyvernoClient, policyKey, append(mutateURs, generateURs...), pc.log.WithName("updateUR"))
for _, rule := range policy.GetSpec().Rules {
var ruleType urkyverno.RequestType
if rule.IsMutateExisting() {
ruleType = urkyverno.Mutate
} else {
// TODO: assign generate ruleType
continue
}
triggers := getTriggers(rule)
for _, trigger := range triggers {
var urs []*urkyverno.UpdateRequest
if ruleType == urkyverno.Mutate {
urs = pc.listMutateURs(policyKey, trigger)
} else {
urs = pc.listGenerateURs(policyKey, trigger)
}
logger.V(4).Info("UR was created", "rule", rule.Name, "rule type", ruleType, "trigger", trigger.Namespace+trigger.Name)
if urs != nil {
continue
}
logger.Info("creating new UR")
ur := newUR(policy, trigger, ruleType)
new, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), ur, metav1.CreateOptions{})
if err != nil {
pc.log.Error(err, "failed to create new UR policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
continue
} else {
pc.log.V(4).Info("successfully created UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule type", ruleType,
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.APIVersion, trigger.Kind, trigger.Namespace, trigger.Name))
}
new.Status.State = urkyverno.Pending
if _, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).UpdateStatus(context.TODO(), new, metav1.UpdateOptions{}); err != nil {
pc.log.Error(err, "failed to set UpdateRequest state to Pending")
}
}
}
}
func (pc *PolicyController) listMutateURs(policyKey string, trigger *kyverno.ResourceSpec) []*urkyverno.UpdateRequest {
selector := createMutateLabels(policyKey, trigger)
mutateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
if err != nil {
logger.Error(err, "failed to list update request for mutate policy")
}
return mutateURs
}
func (pc *PolicyController) listGenerateURs(policyKey string, trigger *kyverno.ResourceSpec) []*urkyverno.UpdateRequest {
selector := createGenerateLabels(policyKey, trigger)
generateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
if err != nil {
logger.Error(err, "failed to list update request for generate policy")
}
return generateURs
}
func newUR(policy kyverno.PolicyInterface, trigger *kyverno.ResourceSpec, ruleType urkyverno.RequestType) *urkyverno.UpdateRequest {
var policyNameNamespaceKey string
if policy.IsNamespaced() {
policyNameNamespaceKey = policy.GetNamespace() + "/" + policy.GetName()
} else {
policyNameNamespaceKey = policy.GetName()
}
var label labels.Set
if ruleType == urkyverno.Mutate {
label = createMutateLabels(policyNameNamespaceKey, trigger)
} else {
label = createGenerateLabels(policyNameNamespaceKey, trigger)
}
return &urkyverno.UpdateRequest{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "ur-",
Namespace: config.KyvernoNamespace,
Labels: label,
},
Spec: urkyverno.UpdateRequestSpec{
Type: ruleType,
Policy: policyNameNamespaceKey,
Resource: kyverno.ResourceSpec{
Kind: trigger.Kind,
Namespace: trigger.Namespace,
Name: trigger.Name,
APIVersion: trigger.APIVersion,
},
},
}
}
func createMutateLabels(policyKey string, trigger *kyverno.ResourceSpec) labels.Set {
var selector labels.Set
if trigger == nil {
selector = labels.Set(map[string]string{
urkyverno.URMutatePolicyLabel: policyKey,
})
} else {
selector = labels.Set(map[string]string{
urkyverno.URMutatePolicyLabel: policyKey,
urkyverno.URMutateTriggerNameLabel: trigger.Name,
urkyverno.URMutateTriggerNSLabel: trigger.Namespace,
urkyverno.URMutatetriggerKindLabel: trigger.Kind,
})
if trigger.APIVersion != "" {
selector[urkyverno.URMutatetriggerAPIVersionLabel] = trigger.APIVersion
}
}
return selector
}
func createGenerateLabels(policyKey string, trigger *kyverno.ResourceSpec) labels.Set {
var selector labels.Set
if trigger == nil {
selector = labels.Set(map[string]string{
urkyverno.URGeneratePolicyLabel: policyKey,
})
} else {
selector = labels.Set(map[string]string{
urkyverno.URGeneratePolicyLabel: policyKey,
"generate.kyverno.io/resource-name": trigger.Name,
"generate.kyverno.io/resource-kind": trigger.Kind,
"generate.kyverno.io/resource-namespace": trigger.Namespace,
})
}
return selector
}