1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-09 09:26:54 +00:00
kyverno/pkg/violation/builder.go

147 lines
3.9 KiB
Go
Raw Normal View History

2019-05-13 18:17:28 -07:00
package violation
2019-04-26 18:16:22 -07:00
import (
"errors"
"reflect"
"github.com/golang/glog"
2019-05-21 11:00:09 -07:00
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
v1alpha1 "github.com/nirmata/kyverno/pkg/client/listers/policy/v1alpha1"
client "github.com/nirmata/kyverno/pkg/dclient"
2019-05-21 11:00:09 -07:00
event "github.com/nirmata/kyverno/pkg/event"
"github.com/nirmata/kyverno/pkg/sharedinformer"
)
2019-05-10 10:38:38 -07:00
//Generator to generate policy violation
type Generator interface {
2019-06-27 11:43:07 -07:00
Add(infos ...*Info) error
2019-04-26 18:16:22 -07:00
}
2019-05-10 10:38:38 -07:00
type builder struct {
2019-05-15 12:29:09 -07:00
client *client.Client
policyLister v1alpha1.PolicyLister
eventBuilder event.Generator
}
2019-05-10 10:38:38 -07:00
//Builder is to build policy violations
type Builder interface {
Generator
2019-06-27 11:43:07 -07:00
processViolation(info *Info) error
isActive(kind string, rname string, rnamespace string) (bool, error)
2019-05-10 00:05:21 -07:00
}
2019-05-10 10:38:38 -07:00
//NewPolicyViolationBuilder returns new violation builder
func NewPolicyViolationBuilder(client *client.Client,
2019-05-15 12:29:09 -07:00
sharedInfomer sharedinformer.PolicyInformer,
eventController event.Generator) Builder {
2019-05-10 10:38:38 -07:00
builder := &builder{
2019-05-15 12:29:09 -07:00
client: client,
policyLister: sharedInfomer.GetLister(),
eventBuilder: eventController,
2019-05-06 12:08:31 -07:00
}
2019-05-10 00:05:21 -07:00
return builder
}
2019-06-27 11:43:07 -07:00
func (b *builder) Add(infos ...*Info) error {
for _, info := range infos {
return b.processViolation(info)
}
return nil
}
2019-06-27 11:43:07 -07:00
func (b *builder) processViolation(info *Info) error {
currentViolations := []interface{}{}
statusMap := map[string]interface{}{}
var ok bool
//TODO: hack get from client
p1, err := b.client.GetResource("Policy", "", info.Policy, "status")
if err != nil {
2019-04-30 17:13:44 -07:00
return err
}
unstr := p1.UnstructuredContent()
// check if "status" field exists
status, ok := unstr["status"]
if ok {
// status is already present then we append violations
if statusMap, ok = status.(map[string]interface{}); !ok {
return errors.New("Unable to parse status subresource")
}
violations, ok := statusMap["violations"]
if !ok {
glog.Info("violation not present")
}
glog.Info(reflect.TypeOf(violations))
if currentViolations, ok = violations.([]interface{}); !ok {
return errors.New("Unable to parse violations")
2019-04-30 17:13:44 -07:00
}
}
newViolation := info.Violation
for _, violation := range currentViolations {
glog.Info(reflect.TypeOf(violation))
if v, ok := violation.(map[string]interface{}); ok {
if name, ok := v["name"].(string); ok {
if namespace, ok := v["namespace"].(string); ok {
ok, err := b.isActive(info.Kind, name, namespace)
if err != nil {
glog.Error(err)
continue
}
if !ok {
//TODO remove the violation as it corresponds to resource that does not exist
glog.Info("removed violation")
}
}
}
}
}
currentViolations = append(currentViolations, newViolation)
// update violations
// set the updated status
statusMap["violations"] = currentViolations
unstr["status"] = statusMap
p1.SetUnstructuredContent(unstr)
_, err = b.client.UpdateStatusResource("policies", "", p1, false)
2019-05-10 00:05:21 -07:00
if err != nil {
return err
}
return nil
2019-04-30 17:13:44 -07:00
}
2019-07-08 17:51:37 -07:00
func (b *builder) isActive(kind, rname, rnamespace string) (bool, error) {
// Generate Merge Patch
_, err := b.client.GetResource(b.client.DiscoveryClient.GetGVRFromKind(kind).Resource, rnamespace, rname)
if err != nil {
glog.Errorf("unable to get resource %s/%s ", rnamespace, rname)
2019-04-30 17:13:44 -07:00
return false, err
}
2019-04-30 17:13:44 -07:00
return true, nil
}
2019-05-10 12:36:55 -07:00
//NewViolation return new policy violation
2019-07-08 17:51:37 -07:00
func NewViolation(reason event.Reason, policyName, kind, rname, rnamespace, msg string) *Info {
return &Info{Policy: policyName,
2019-05-10 12:36:55 -07:00
Violation: types.Violation{
2019-06-26 18:02:01 -07:00
Kind: kind,
Name: rname,
Namespace: rnamespace,
2019-07-08 17:51:37 -07:00
Reason: reason.String(),
Message: msg,
2019-06-26 18:02:01 -07:00
},
2019-05-10 12:36:55 -07:00
}
}
2019-06-27 11:43:07 -07:00
//NewViolationFromEvent returns violation info from event
2019-07-08 17:51:37 -07:00
func NewViolationFromEvent(e *event.Info, pName, rKind, rName, rnamespace string) *Info {
2019-06-27 11:43:07 -07:00
return &Info{
Policy: pName,
Violation: types.Violation{
Kind: rKind,
Name: rName,
Namespace: rnamespace,
Reason: e.Reason,
Message: e.Message,
2019-06-27 11:43:07 -07:00
},
}
}