mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +00:00
feat: trigger generate on existing matched resource (#3819)
* feat: trigger generate on existing matched resource Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * refactor the triggers and fix review comments Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * add trigger for other matching kinds Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * implement match exclude using dynamic client Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * refactor generate trigger Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * increase sleep timeout Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * optimize unstructured list Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * fix review comments Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com> * log refactor and clean debug comments Signed-off-by: prateekpandey14 <prateek.pandey@nirmata.com>
This commit is contained in:
parent
bbe65959bc
commit
8b6d3d1f6a
11 changed files with 295 additions and 66 deletions
|
@ -68,6 +68,12 @@ type Spec struct {
|
|||
// Default value is "false".
|
||||
// +optional
|
||||
MutateExistingOnPolicyUpdate bool `json:"mutateExistingOnPolicyUpdate,omitempty" yaml:"mutateExistingOnPolicyUpdate,omitempty"`
|
||||
|
||||
// GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources
|
||||
// If is set to "true" generate rule will be triggered and applied to existing matched resources.
|
||||
// Defaults to "false" if not specified.
|
||||
// +optional
|
||||
GenerateExistingOnPolicyUpdate bool `json:"generateExistingOnPolicyUpdate,omitempty" yaml:"generateExistingOnPolicyUpdate,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Spec) SetRules(rules []Rule) {
|
||||
|
@ -163,6 +169,11 @@ func (s *Spec) GetMutateExistingOnPolicyUpdate() bool {
|
|||
return s.MutateExistingOnPolicyUpdate
|
||||
}
|
||||
|
||||
// IsGenerateExistingOnPolicyUpdate return GenerateExistingOnPolicyUpdate set value
|
||||
func (s *Spec) IsGenerateExistingOnPolicyUpdate() bool {
|
||||
return s.GenerateExistingOnPolicyUpdate
|
||||
}
|
||||
|
||||
// GetFailurePolicy returns the failure policy to be applied
|
||||
func (s *Spec) GetFailurePolicy() FailurePolicyType {
|
||||
if s.FailurePolicy == nil {
|
||||
|
|
|
@ -64,6 +64,9 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources If is set to "true" generate rule will be triggered and applied to existing matched resources. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting policy is applied on policy events. Default value is "false".
|
||||
type: boolean
|
||||
|
@ -2409,6 +2412,9 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources If is set to "true" generate rule will be triggered and applied to existing matched resources. Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting policy is applied on policy events. Default value is "false".
|
||||
type: boolean
|
||||
|
|
|
@ -68,6 +68,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
|
|
@ -69,6 +69,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
|
|
@ -85,6 +85,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
@ -3591,6 +3597,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
|
|
@ -83,6 +83,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
@ -3585,6 +3591,12 @@ spec:
|
|||
- Ignore
|
||||
- Fail
|
||||
type: string
|
||||
generateExistingOnPolicyUpdate:
|
||||
description: GenerateExistingOnPolicyUpdate controls wether to trigger
|
||||
generate rule in existing resources If is set to "true" generate
|
||||
rule will be triggered and applied to existing matched resources.
|
||||
Defaults to "false" if not specified.
|
||||
type: boolean
|
||||
mutateExistingOnPolicyUpdate:
|
||||
description: MutateExistingOnPolicyUpdate controls if a mutateExisting
|
||||
policy is applied on policy events. Default value is "false".
|
||||
|
|
|
@ -202,6 +202,20 @@ bool
|
|||
Default value is “false”.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>generateExistingOnPolicyUpdate</code></br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources
|
||||
If is set to “true” generate rule will be triggered and applied to existing matched resources.
|
||||
Defaults to “false” if not specified.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -395,6 +409,20 @@ bool
|
|||
Default value is “false”.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>generateExistingOnPolicyUpdate</code></br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources
|
||||
If is set to “true” generate rule will be triggered and applied to existing matched resources.
|
||||
Defaults to “false” if not specified.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -2954,6 +2982,20 @@ bool
|
|||
Default value is “false”.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>generateExistingOnPolicyUpdate</code></br>
|
||||
<em>
|
||||
bool
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>GenerateExistingOnPolicyUpdate controls wether to trigger generate rule in existing resources
|
||||
If is set to “true” generate rule will be triggered and applied to existing matched resources.
|
||||
Defaults to “false” if not specified.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
|
|
|
@ -349,8 +349,8 @@ func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext
|
|||
return nil, processExisting, err
|
||||
}
|
||||
|
||||
if !processExisting {
|
||||
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy.GetName(), ur)
|
||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() || !processExisting {
|
||||
genResource, err = applyRule(log, c.client, rule, resource, jsonContext, policy, ur)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to apply generate rule", "policy", policy.GetName(),
|
||||
"rule", rule.Name, "resource", resource.GetName(), "suggestion", "users need to grant Kyverno's service account additional privileges")
|
||||
|
@ -359,6 +359,10 @@ func (c *GenerateController) applyGeneratePolicy(log logr.Logger, policyContext
|
|||
ruleNameToProcessingTime[rule.Name] = time.Since(startTime)
|
||||
genResources = append(genResources, genResource)
|
||||
}
|
||||
|
||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
||||
processExisting = false
|
||||
}
|
||||
}
|
||||
|
||||
return genResources, processExisting, nil
|
||||
|
@ -384,7 +388,7 @@ func getResourceInfo(object map[string]interface{}) (kind, name, namespace, apiv
|
|||
return
|
||||
}
|
||||
|
||||
func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, ur urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy kyverno.PolicyInterface, ur urkyverno.UpdateRequest) (kyverno.ResourceSpec, error) {
|
||||
var rdata map[string]interface{}
|
||||
var err error
|
||||
var mode ResourceMode
|
||||
|
@ -420,7 +424,7 @@ func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, res
|
|||
}
|
||||
|
||||
if len(genClone) != 0 {
|
||||
rdata, mode, err = manageClone(logger, genAPIVersion, genKind, genNamespace, genName, policy, genClone, client)
|
||||
rdata, mode, err = manageClone(logger, genAPIVersion, genKind, genNamespace, genName, policy.GetName(), genClone, client)
|
||||
} else {
|
||||
rdata, mode, err = manageData(logger, genAPIVersion, genKind, genNamespace, genName, genData, client)
|
||||
}
|
||||
|
@ -455,7 +459,13 @@ func applyRule(log logr.Logger, client dclient.Interface, rule kyverno.Rule, res
|
|||
common.ManageLabels(newResource, resource)
|
||||
// Add Synchronize label
|
||||
label := newResource.GetLabels()
|
||||
label["policy.kyverno.io/policy-name"] = policy
|
||||
|
||||
// Add background gen-rule label if generate rule applied on existing resource
|
||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
||||
label["kyverno.io/background-gen-rule"] = rule.Name
|
||||
}
|
||||
|
||||
label["policy.kyverno.io/policy-name"] = policy.GetName()
|
||||
label["policy.kyverno.io/gr-name"] = ur.Name
|
||||
if mode == Create {
|
||||
if rule.Generation.Synchronize {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
utilscommon "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
|
||||
|
@ -30,6 +30,7 @@ import (
|
|||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
informers "k8s.io/client-go/informers/core/v1"
|
||||
|
@ -177,7 +178,7 @@ func (pc *PolicyController) addPolicy(obj interface{}) {
|
|||
go pc.registerPolicyChangesMetricAddPolicy(logger, p)
|
||||
|
||||
if p.Spec.Background == nil || p.Spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
pol, _ := common.MutatePolicy(p, logger)
|
||||
pol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyverno.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add policy ")
|
||||
|
@ -203,7 +204,7 @@ func (pc *PolicyController) updatePolicy(old, cur interface{}) {
|
|||
go pc.registerPolicyChangesMetricUpdatePolicy(logger, oldP, curP)
|
||||
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
pol, _ := common.MutatePolicy(curP, logger)
|
||||
pol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().ClusterPolicies().Update(context.TODO(), pol.(*kyverno.ClusterPolicy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update policy ")
|
||||
|
@ -273,7 +274,7 @@ func (pc *PolicyController) addNsPolicy(obj interface{}) {
|
|||
|
||||
spec := p.GetSpec()
|
||||
if spec.Background == nil || spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
|
||||
nsPol, _ := common.MutatePolicy(p, logger)
|
||||
nsPol, _ := utilscommon.MutatePolicy(p, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(p.Namespace).Update(context.TODO(), nsPol.(*kyverno.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to add namespace policy")
|
||||
|
@ -297,7 +298,7 @@ func (pc *PolicyController) updateNsPolicy(old, cur interface{}) {
|
|||
go pc.registerPolicyChangesMetricUpdatePolicy(logger, oldP, curP)
|
||||
|
||||
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
|
||||
nsPol, _ := common.MutatePolicy(curP, logger)
|
||||
nsPol, _ := utilscommon.MutatePolicy(curP, logger)
|
||||
_, err := pc.kyvernoClient.KyvernoV1().Policies(curP.GetNamespace()).Update(context.TODO(), nsPol.(*kyverno.Policy), metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update namespace policy ")
|
||||
|
@ -481,7 +482,10 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
}
|
||||
return err
|
||||
} else {
|
||||
pc.updateUR(key, policy)
|
||||
err = pc.updateUR(key, policy)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to updateUR on Policy update")
|
||||
}
|
||||
}
|
||||
|
||||
pc.processExistingResources(policy)
|
||||
|
@ -566,6 +570,21 @@ func getTrigger(rd kyverno.ResourceDescription) []*kyverno.ResourceSpec {
|
|||
return specs
|
||||
}
|
||||
|
||||
func generateTriggers(client client.Interface, rule kyverno.Rule, log logr.Logger) []*unstructured.Unstructured {
|
||||
list := &unstructured.UnstructuredList{}
|
||||
|
||||
kinds := fetchUniqueKinds(rule)
|
||||
|
||||
for _, kind := range kinds {
|
||||
mlist, err := client.ListResource("", kind, "", rule.MatchResources.Selector)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to list matched resource")
|
||||
}
|
||||
list.Items = append(list.Items, mlist.Items...)
|
||||
}
|
||||
return convertlist(list.Items)
|
||||
}
|
||||
|
||||
func deleteUR(kyvernoClient kyvernoclient.Interface, policyKey string, grList []*urkyverno.UpdateRequest, logger logr.Logger) {
|
||||
for _, v := range grList {
|
||||
if policyKey == v.Spec.Policy {
|
||||
|
|
|
@ -7,71 +7,119 @@ import (
|
|||
"github.com/gardener/controller-manager-library/pkg/logger"
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
common "github.com/kyverno/kyverno/pkg/background/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInterface) {
|
||||
func (pc *PolicyController) updateUR(policyKey string, policy kyverno.PolicyInterface) error {
|
||||
logger := pc.log.WithName("updateUR").WithName(policyKey)
|
||||
|
||||
// TODO: add check for genExisting
|
||||
if !policy.GetSpec().MutateExistingOnPolicyUpdate {
|
||||
logger.V(4).Info("skip policy application on policy event", "policyKey", policyKey, "mutateExiting", policy.GetSpec().MutateExistingOnPolicyUpdate)
|
||||
return
|
||||
if !policy.GetSpec().MutateExistingOnPolicyUpdate && !policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
||||
logger.V(4).Info("skip policy application on policy event", "policyKey", policyKey, "mutateExiting", policy.GetSpec().MutateExistingOnPolicyUpdate, "generateExisting", policy.GetSpec().IsGenerateExistingOnPolicyUpdate())
|
||||
return nil
|
||||
}
|
||||
|
||||
logger.Info("update URs on policy event")
|
||||
|
||||
var errors []error
|
||||
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)
|
||||
triggers := generateTriggers(pc.client, rule, pc.log)
|
||||
for _, trigger := range triggers {
|
||||
var urs []*urkyverno.UpdateRequest
|
||||
if ruleType == urkyverno.Mutate {
|
||||
urs = pc.listMutateURs(policyKey, trigger)
|
||||
} else {
|
||||
urs = pc.listGenerateURs(policyKey, trigger)
|
||||
}
|
||||
murs := pc.listMutateURs(policyKey, trigger)
|
||||
|
||||
logger.V(4).Info("UR was created", "rule", rule.Name, "rule type", ruleType, "trigger", trigger.Namespace+trigger.Name)
|
||||
|
||||
if urs != nil {
|
||||
if murs != nil {
|
||||
logger.V(4).Info("UR was created", "rule", rule.Name, "rule type", ruleType, "trigger", trigger.GetNamespace()+trigger.GetName())
|
||||
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{})
|
||||
err := pc.handleUpdateRequest(ur, trigger, rule, policy)
|
||||
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))
|
||||
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
|
||||
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))
|
||||
"target", fmt.Sprintf("%s/%s/%s/%s", trigger.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
|
||||
}
|
||||
}
|
||||
}
|
||||
if policy.GetSpec().IsGenerateExistingOnPolicyUpdate() {
|
||||
ruleType = urkyverno.Generate
|
||||
triggers := generateTriggers(pc.client, rule, pc.log)
|
||||
for _, trigger := range triggers {
|
||||
gurs := pc.listGenerateURs(policyKey, trigger)
|
||||
|
||||
if gurs != nil {
|
||||
logger.V(4).Info("UR was created", "rule", rule.Name, "rule type", ruleType, "trigger", trigger.GetNamespace()+"/"+trigger.GetName())
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info("creating new UR")
|
||||
ur := newUR(policy, trigger, ruleType)
|
||||
err := pc.handleUpdateRequest(ur, trigger, rule, policy)
|
||||
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.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
|
||||
errors = append(errors, err)
|
||||
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.GetAPIVersion(), trigger.GetKind(), trigger.GetNamespace(), trigger.GetName()))
|
||||
}
|
||||
}
|
||||
err := engineutils.CombineErrors(errors)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *PolicyController) handleUpdateRequest(ur *urkyverno.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyverno.Rule, policy kyverno.PolicyInterface) error {
|
||||
policyContext, _, err := common.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, nil, pc.log)
|
||||
if err != nil {
|
||||
pc.log.WithName(rule.Name).Error(err, "failed to build policy context for existing")
|
||||
}
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
|
||||
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
||||
if ruleResponse.Status != response.RuleStatusPass {
|
||||
pc.log.Error(err, "can not create new UR for genExisting rule on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status)
|
||||
continue
|
||||
}
|
||||
|
||||
new, err := pc.kyvernoClient.KyvernoV1beta1().UpdateRequests(config.KyvernoNamespace).Create(context.TODO(), ur, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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")
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (pc *PolicyController) listMutateURs(policyKey string, trigger *kyverno.ResourceSpec) []*urkyverno.UpdateRequest {
|
||||
func (pc *PolicyController) listMutateURs(policyKey string, trigger *unstructured.Unstructured) []*urkyverno.UpdateRequest {
|
||||
selector := createMutateLabels(policyKey, trigger)
|
||||
mutateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
|
||||
if err != nil {
|
||||
|
@ -81,7 +129,7 @@ func (pc *PolicyController) listMutateURs(policyKey string, trigger *kyverno.Res
|
|||
return mutateURs
|
||||
}
|
||||
|
||||
func (pc *PolicyController) listGenerateURs(policyKey string, trigger *kyverno.ResourceSpec) []*urkyverno.UpdateRequest {
|
||||
func (pc *PolicyController) listGenerateURs(policyKey string, trigger *unstructured.Unstructured) []*urkyverno.UpdateRequest {
|
||||
selector := createGenerateLabels(policyKey, trigger)
|
||||
generateURs, err := pc.urLister.List(labels.SelectorFromSet(selector))
|
||||
if err != nil {
|
||||
|
@ -91,7 +139,7 @@ func (pc *PolicyController) listGenerateURs(policyKey string, trigger *kyverno.R
|
|||
return generateURs
|
||||
}
|
||||
|
||||
func newUR(policy kyverno.PolicyInterface, trigger *kyverno.ResourceSpec, ruleType urkyverno.RequestType) *urkyverno.UpdateRequest {
|
||||
func newUR(policy kyverno.PolicyInterface, trigger *unstructured.Unstructured, ruleType urkyverno.RequestType) *urkyverno.UpdateRequest {
|
||||
var policyNameNamespaceKey string
|
||||
|
||||
if policy.IsNamespaced() {
|
||||
|
@ -117,16 +165,16 @@ func newUR(policy kyverno.PolicyInterface, trigger *kyverno.ResourceSpec, ruleTy
|
|||
Type: ruleType,
|
||||
Policy: policyNameNamespaceKey,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
Kind: trigger.Kind,
|
||||
Namespace: trigger.Namespace,
|
||||
Name: trigger.Name,
|
||||
APIVersion: trigger.APIVersion,
|
||||
Kind: trigger.GetKind(),
|
||||
Namespace: trigger.GetNamespace(),
|
||||
Name: trigger.GetName(),
|
||||
APIVersion: trigger.GetAPIVersion(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createMutateLabels(policyKey string, trigger *kyverno.ResourceSpec) labels.Set {
|
||||
func createMutateLabels(policyKey string, trigger *unstructured.Unstructured) labels.Set {
|
||||
var selector labels.Set
|
||||
if trigger == nil {
|
||||
selector = labels.Set(map[string]string{
|
||||
|
@ -135,20 +183,21 @@ func createMutateLabels(policyKey string, trigger *kyverno.ResourceSpec) labels.
|
|||
} else {
|
||||
selector = labels.Set(map[string]string{
|
||||
urkyverno.URMutatePolicyLabel: policyKey,
|
||||
urkyverno.URMutateTriggerNameLabel: trigger.Name,
|
||||
urkyverno.URMutateTriggerNSLabel: trigger.Namespace,
|
||||
urkyverno.URMutatetriggerKindLabel: trigger.Kind,
|
||||
urkyverno.URMutateTriggerNameLabel: trigger.GetName(),
|
||||
urkyverno.URMutateTriggerNSLabel: trigger.GetNamespace(),
|
||||
urkyverno.URMutatetriggerKindLabel: trigger.GetKind(),
|
||||
})
|
||||
|
||||
if trigger.APIVersion != "" {
|
||||
selector[urkyverno.URMutatetriggerAPIVersionLabel] = trigger.APIVersion
|
||||
if trigger.GetAPIVersion() != "" {
|
||||
selector[urkyverno.URMutatetriggerAPIVersionLabel] = trigger.GetAPIVersion()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return selector
|
||||
}
|
||||
|
||||
func createGenerateLabels(policyKey string, trigger *kyverno.ResourceSpec) labels.Set {
|
||||
func createGenerateLabels(policyKey string, trigger *unstructured.Unstructured) labels.Set {
|
||||
var selector labels.Set
|
||||
if trigger == nil {
|
||||
selector = labels.Set(map[string]string{
|
||||
|
@ -157,9 +206,9 @@ func createGenerateLabels(policyKey string, trigger *kyverno.ResourceSpec) label
|
|||
} 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,
|
||||
"generate.kyverno.io/resource-name": trigger.GetName(),
|
||||
"generate.kyverno.io/resource-kind": trigger.GetKind(),
|
||||
"generate.kyverno.io/resource-namespace": trigger.GetNamespace(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package policy
|
||||
|
||||
import "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
import (
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func isRunningPod(obj unstructured.Unstructured) bool {
|
||||
objMap := obj.UnstructuredContent()
|
||||
|
@ -11,3 +14,56 @@ func isRunningPod(obj unstructured.Unstructured) bool {
|
|||
|
||||
return phase == "Running"
|
||||
}
|
||||
|
||||
// check if all slice elements are same
|
||||
func isMatchResourcesAllValid(rule kyverno.Rule) bool {
|
||||
var kindlist []string
|
||||
for _, all := range rule.MatchResources.All {
|
||||
kindlist = append(kindlist, all.Kinds...)
|
||||
}
|
||||
|
||||
if len(kindlist) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 1; i < len(kindlist); i++ {
|
||||
if kindlist[i] != kindlist[0] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func fetchUniqueKinds(rule kyverno.Rule) []string {
|
||||
var kindlist []string
|
||||
|
||||
kindlist = append(kindlist, rule.MatchResources.Kinds...)
|
||||
|
||||
for _, all := range rule.MatchResources.Any {
|
||||
kindlist = append(kindlist, all.Kinds...)
|
||||
}
|
||||
|
||||
if isMatchResourcesAllValid(rule) {
|
||||
for _, all := range rule.MatchResources.All {
|
||||
kindlist = append(kindlist, all.Kinds...)
|
||||
}
|
||||
}
|
||||
|
||||
inResult := make(map[string]bool)
|
||||
var result []string
|
||||
for _, kind := range kindlist {
|
||||
if _, ok := inResult[kind]; !ok {
|
||||
inResult[kind] = true
|
||||
result = append(result, kind)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func convertlist(ulists []unstructured.Unstructured) []*unstructured.Unstructured {
|
||||
var result []*unstructured.Unstructured
|
||||
for _, list := range ulists {
|
||||
result = append(result, list.DeepCopy())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue