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

148 lines
4.7 KiB
Go
Raw Normal View History

2019-11-15 12:03:58 -08:00
package policyviolation
import (
"fmt"
2020-03-17 16:25:34 -07:00
"github.com/go-logr/logr"
2019-11-15 12:03:58 -08:00
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1"
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
client "github.com/nirmata/kyverno/pkg/dclient"
"github.com/nirmata/kyverno/pkg/policystatus"
2019-11-26 18:07:15 -08:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2019-11-15 12:03:58 -08:00
)
2019-11-26 18:07:15 -08:00
//ClusterPV ...
type clusterPV struct {
// dynamic client
dclient *client.Client
// get/list cluster policy violation
cpvLister kyvernolister.ClusterPolicyViolationLister
// policy violation interface
kyvernoInterface kyvernov1.KyvernoV1Interface
2020-03-17 16:25:34 -07:00
// logger
log logr.Logger
// update policy stats with violationCount
policyStatusListener policystatus.Listener
2019-11-15 12:03:58 -08:00
}
2020-03-17 16:25:34 -07:00
func newClusterPV(log logr.Logger, dclient *client.Client,
2019-11-26 18:07:15 -08:00
cpvLister kyvernolister.ClusterPolicyViolationLister,
kyvernoInterface kyvernov1.KyvernoV1Interface,
policyStatus policystatus.Listener,
2019-11-26 18:07:15 -08:00
) *clusterPV {
cpv := clusterPV{
dclient: dclient,
cpvLister: cpvLister,
kyvernoInterface: kyvernoInterface,
log: log,
policyStatusListener: policyStatus,
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
return &cpv
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
2019-12-12 16:35:37 -08:00
func (cpv *clusterPV) create(pv kyverno.PolicyViolationTemplate) error {
2019-11-26 18:07:15 -08:00
newPv := kyverno.ClusterPolicyViolation(pv)
2019-11-15 12:03:58 -08:00
// PV already exists
2019-11-26 18:07:15 -08:00
oldPv, err := cpv.getExisting(newPv)
2019-11-15 12:03:58 -08:00
if err != nil {
2019-11-26 18:07:15 -08:00
return err
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
if oldPv == nil {
// create a new policy violation
return cpv.createPV(&newPv)
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
// policy violation exists
// skip if there is not change, else update the violation
return cpv.updatePV(&newPv, oldPv)
}
2019-11-15 12:03:58 -08:00
2019-11-26 18:07:15 -08:00
func (cpv *clusterPV) getExisting(newPv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) {
2020-03-17 16:25:34 -07:00
logger := cpv.log.WithValues("namespace", newPv.Namespace, "name", newPv.Name)
2019-12-11 11:15:13 -08:00
var err error
// use labels
policyLabelmap := map[string]string{"policy": newPv.Spec.Policy, "resource": newPv.Spec.ResourceSpec.ToKey()}
ls, err := converLabelToSelector(policyLabelmap)
if err != nil {
return nil, err
}
pvs, err := cpv.cpvLister.List(ls)
2019-11-15 12:03:58 -08:00
if err != nil {
2020-03-17 16:25:34 -07:00
logger.Error(err, "failed to list cluster policy violations")
2019-11-26 18:07:15 -08:00
return nil, err
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
for _, pv := range pvs {
// find a policy on same resource and policy combination
if pv.Spec.Policy == newPv.Spec.Policy &&
pv.Spec.ResourceSpec.Kind == newPv.Spec.ResourceSpec.Kind &&
pv.Spec.ResourceSpec.Name == newPv.Spec.ResourceSpec.Name {
return pv, nil
}
}
return nil, nil
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
func (cpv *clusterPV) createPV(newPv *kyverno.ClusterPolicyViolation) error {
var err error
2020-03-17 16:25:34 -07:00
logger := cpv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name)
logger.V(4).Info("creating new policy violation")
2019-12-02 17:15:47 -08:00
obj, err := retryGetResource(cpv.dclient, newPv.Spec.ResourceSpec)
2019-11-26 18:07:15 -08:00
if err != nil {
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err)
2019-11-15 12:03:58 -08:00
}
if obj.GetDeletionTimestamp() != nil {
return nil
}
2019-11-26 18:07:15 -08:00
// set owner reference to resource
ownerRef, ok := createOwnerReference(obj)
if !ok {
return nil
}
2019-11-26 18:07:15 -08:00
newPv.SetOwnerReferences([]metav1.OwnerReference{ownerRef})
2019-11-15 12:03:58 -08:00
2019-11-26 18:07:15 -08:00
// create resource
_, err = cpv.kyvernoInterface.ClusterPolicyViolations().Create(newPv)
if err != nil {
2020-03-17 16:25:34 -07:00
logger.Error(err, "failed to create cluster policy violation")
2019-11-26 18:07:15 -08:00
return err
2019-11-15 12:03:58 -08:00
}
2020-02-26 00:26:09 +05:30
if newPv.Annotations["fromSync"] != "true" {
cpv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules})
2020-02-26 00:26:09 +05:30
}
2020-03-17 16:25:34 -07:00
logger.Info("cluster policy violation created")
2019-11-26 18:07:15 -08:00
return nil
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
func (cpv *clusterPV) updatePV(newPv, oldPv *kyverno.ClusterPolicyViolation) error {
2020-03-17 16:25:34 -07:00
logger := cpv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name)
2019-11-26 18:07:15 -08:00
var err error
// check if there is any update
if !hasViolationSpecChanged(newPv.Spec.DeepCopy(), oldPv.Spec.DeepCopy()) {
2020-03-17 16:25:34 -07:00
logger.V(4).Info("policy violation spec did not change, not upadating the resource")
2019-11-26 18:07:15 -08:00
return nil
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
// set name
newPv.SetName(oldPv.Name)
2019-12-11 11:15:13 -08:00
newPv.SetResourceVersion(oldPv.ResourceVersion)
2020-05-26 17:18:42 -07:00
newPv.SetOwnerReferences(oldPv.GetOwnerReferences())
2019-11-15 12:03:58 -08:00
2019-11-26 18:07:15 -08:00
// update resource
_, err = cpv.kyvernoInterface.ClusterPolicyViolations().Update(newPv)
2019-11-15 12:03:58 -08:00
if err != nil {
2019-11-26 18:07:15 -08:00
return fmt.Errorf("failed to update cluster policy violation: %v", err)
2019-11-15 12:03:58 -08:00
}
2020-05-26 17:18:42 -07:00
logger.Info("cluster policy violation updated")
2019-11-15 12:03:58 -08:00
2020-02-26 00:26:09 +05:30
if newPv.Annotations["fromSync"] != "true" {
cpv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules})
2020-02-26 00:26:09 +05:30
}
2019-11-26 18:07:15 -08:00
return nil
2019-11-15 12:03:58 -08:00
}