2019-04-26 18:16:22 -07:00
|
|
|
package violation
|
|
|
|
|
2019-04-29 14:34:54 -07:00
|
|
|
import (
|
|
|
|
"fmt"
|
2019-05-03 16:41:45 -07:00
|
|
|
"log"
|
|
|
|
|
2019-05-06 09:12:37 -07:00
|
|
|
kubeClient "github.com/nirmata/kube-policy/kubeclient"
|
2019-04-29 14:34:54 -07:00
|
|
|
types "github.com/nirmata/kube-policy/pkg/apis/policy/v1alpha1"
|
2019-05-10 00:05:21 -07:00
|
|
|
policyclientset "github.com/nirmata/kube-policy/pkg/client/clientset/versioned"
|
|
|
|
policylister "github.com/nirmata/kube-policy/pkg/client/listers/policy/v1alpha1"
|
|
|
|
event "github.com/nirmata/kube-policy/pkg/event"
|
2019-04-29 14:34:54 -07:00
|
|
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
2019-05-10 00:05:21 -07:00
|
|
|
"k8s.io/client-go/tools/cache"
|
2019-04-29 14:34:54 -07:00
|
|
|
)
|
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
type PolicyViolationGenerator interface {
|
|
|
|
Add(info ViolationInfo) error
|
2019-04-26 18:16:22 -07:00
|
|
|
}
|
2019-04-29 14:34:54 -07:00
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
type policyViolationBuilder struct {
|
|
|
|
kubeClient *kubeClient.KubeClient
|
|
|
|
policyLister policylister.PolicyLister
|
|
|
|
policyInterface policyclientset.Interface
|
|
|
|
eventBuilder event.EventGenerator
|
|
|
|
logger *log.Logger
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
type PolicyViolationBuilder interface {
|
|
|
|
PolicyViolationGenerator
|
|
|
|
processViolation(info ViolationInfo) error
|
|
|
|
isActive(kind string, resource string) (bool, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPolicyViolationBuilder(
|
2019-05-06 09:12:37 -07:00
|
|
|
kubeClient *kubeClient.KubeClient,
|
2019-05-10 00:05:21 -07:00
|
|
|
policyLister policylister.PolicyLister,
|
|
|
|
policyInterface policyclientset.Interface,
|
|
|
|
eventController event.EventGenerator,
|
|
|
|
logger *log.Logger) PolicyViolationBuilder {
|
2019-04-29 14:34:54 -07:00
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
builder := &policyViolationBuilder{
|
|
|
|
kubeClient: kubeClient,
|
|
|
|
policyLister: policyLister,
|
|
|
|
policyInterface: policyInterface,
|
|
|
|
eventBuilder: eventController,
|
|
|
|
logger: logger,
|
2019-05-06 12:08:31 -07:00
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
return builder
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
func (pvb *policyViolationBuilder) Add(info ViolationInfo) error {
|
|
|
|
return pvb.processViolation(info)
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
func (pvb *policyViolationBuilder) processViolation(info ViolationInfo) error {
|
2019-05-06 09:12:37 -07:00
|
|
|
// Get the policy
|
2019-05-10 00:05:21 -07:00
|
|
|
namespace, name, err := cache.SplitMetaNamespaceKey(info.Policy)
|
|
|
|
if err != nil {
|
|
|
|
utilruntime.HandleError(fmt.Errorf("unable to extract namespace and name for %s", info.Policy))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
policy, err := pvb.policyLister.Policies(namespace).Get(name)
|
2019-04-29 14:34:54 -07:00
|
|
|
if err != nil {
|
2019-04-30 17:13:44 -07:00
|
|
|
utilruntime.HandleError(err)
|
|
|
|
return err
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|
2019-05-06 09:12:37 -07:00
|
|
|
modifiedPolicy := policy.DeepCopy()
|
|
|
|
modifiedViolations := []types.Violation{}
|
2019-04-30 17:13:44 -07:00
|
|
|
|
2019-05-06 10:30:44 -07:00
|
|
|
// Create new violation
|
|
|
|
newViolation := types.Violation{
|
|
|
|
Kind: info.Kind,
|
|
|
|
Resource: info.Resource,
|
|
|
|
Rule: info.Rule,
|
|
|
|
Reason: info.Reason,
|
|
|
|
Message: info.Message,
|
|
|
|
}
|
2019-05-06 17:03:37 -07:00
|
|
|
|
|
|
|
for _, violation := range modifiedPolicy.Status.Violations {
|
2019-05-10 00:05:21 -07:00
|
|
|
ok, err := pvb.isActive(info.Kind, violation.Resource)
|
2019-05-06 09:12:37 -07:00
|
|
|
if err != nil {
|
|
|
|
utilruntime.HandleError(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !ok {
|
2019-05-10 00:05:21 -07:00
|
|
|
pvb.logger.Printf("removed violation ")
|
2019-04-30 17:13:44 -07:00
|
|
|
}
|
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
// If violation already exists for this rule, we update the violation
|
|
|
|
//TODO: update violation, instead of re-creating one every time
|
2019-05-06 10:30:44 -07:00
|
|
|
modifiedViolations = append(modifiedViolations, newViolation)
|
|
|
|
|
2019-05-06 17:03:37 -07:00
|
|
|
modifiedPolicy.Status.Violations = modifiedViolations
|
|
|
|
// Violations are part of the status sub resource, so we can use the Update Status api instead of updating the policy object
|
2019-05-10 00:05:21 -07:00
|
|
|
_, err = pvb.policyInterface.NirmataV1alpha1().Policies(namespace).UpdateStatus(modifiedPolicy)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2019-04-30 17:13:44 -07:00
|
|
|
}
|
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
func (pvb *policyViolationBuilder) isActive(kind string, resource string) (bool, error) {
|
2019-05-06 09:12:37 -07:00
|
|
|
// Generate Merge Patch
|
2019-05-10 00:05:21 -07:00
|
|
|
_, err := pvb.kubeClient.GetResource(kind, resource)
|
2019-04-29 14:34:54 -07:00
|
|
|
if err != nil {
|
2019-05-06 09:12:37 -07:00
|
|
|
utilruntime.HandleError(fmt.Errorf("unable to get resource %s ", resource))
|
2019-04-30 17:13:44 -07:00
|
|
|
return false, err
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|
2019-04-30 17:13:44 -07:00
|
|
|
return true, nil
|
2019-04-29 14:34:54 -07:00
|
|
|
}
|