2019-11-15 12:03:58 -08:00
package policyviolation
import (
"fmt"
"reflect"
"github.com/golang/glog"
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"
2020-02-25 20:55:07 +05:30
"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-02-24 20:12:39 +05:30
// update policy stats with violationCount
2020-02-25 20:55:07 +05:30
policyStatus * policyStatus . Sync
2019-11-15 12:03:58 -08:00
}
2019-11-26 18:07:15 -08:00
func newClusterPV ( dclient * client . Client ,
cpvLister kyvernolister . ClusterPolicyViolationLister ,
kyvernoInterface kyvernov1 . KyvernoV1Interface ,
2020-02-25 20:55:07 +05:30
policyStatus * policyStatus . Sync ,
2019-11-26 18:07:15 -08:00
) * clusterPV {
cpv := clusterPV {
dclient : dclient ,
cpvLister : cpvLister ,
kyvernoInterface : kyvernoInterface ,
2020-02-24 20:12:39 +05:30
policyStatus : 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 ) {
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 {
2019-11-26 18:07:15 -08:00
glog . Errorf ( "unable to list cluster policy violations : %v" , err )
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
glog . V ( 4 ) . Infof ( "creating new policy violation for policy %s & resource %s/%s" , newPv . Spec . Policy , newPv . Spec . ResourceSpec . Kind , newPv . Spec . ResourceSpec . Name )
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
}
2019-11-26 18:07:15 -08:00
// set owner reference to resource
ownerRef := createOwnerReference ( obj )
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 {
glog . V ( 4 ) . Infof ( "failed to create Cluster Policy Violation: %v" , err )
return err
2019-11-15 12:03:58 -08:00
}
2020-02-24 20:12:39 +05:30
2020-02-26 00:26:09 +05:30
if newPv . Annotations [ "fromSync" ] != "true" {
2020-03-04 13:35:49 +05:30
cpv . policyStatus . Listener <- updatePolicyStatusWithViolationCount ( newPv . Spec . Policy , newPv . Spec . ViolatedRules )
2020-02-26 00:26:09 +05:30
}
2019-11-26 18:07:15 -08:00
glog . Infof ( "policy violation created for resource %v" , newPv . Spec . ResourceSpec )
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 {
var err error
// check if there is any update
if reflect . DeepEqual ( newPv . Spec , oldPv . Spec ) {
glog . V ( 4 ) . Infof ( "policy violation spec %v did not change so not updating it" , newPv . Spec )
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 )
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
}
2019-11-26 18:07:15 -08:00
glog . Infof ( "cluster policy violation updated for resource %v" , newPv . Spec . ResourceSpec )
2019-11-15 12:03:58 -08:00
2020-02-26 00:26:09 +05:30
if newPv . Annotations [ "fromSync" ] != "true" {
2020-03-04 13:35:49 +05:30
cpv . policyStatus . Listener <- updatePolicyStatusWithViolationCount ( newPv . Spec . Policy , 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
}