mirror of
https://github.com/kyverno/kyverno.git
synced 2025-04-09 10:42:22 +00:00
flag, violations
This commit is contained in:
parent
129ced1b2a
commit
f9b5ac9a27
12 changed files with 452 additions and 222 deletions
|
@ -21,16 +21,13 @@ spec:
|
|||
spec:
|
||||
required:
|
||||
- rules
|
||||
# set as required, as we cannot set default yet. check below for more details
|
||||
- mode
|
||||
properties:
|
||||
mode:
|
||||
# default values to be handled by user
|
||||
validationFailureAction:
|
||||
type: string
|
||||
# default can only be set if CustomResourceDefaulting feature gate is enabled
|
||||
# default: blockChanges
|
||||
enum:
|
||||
- blockChanges
|
||||
- reportViolation
|
||||
- block
|
||||
- report
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
|
@ -186,7 +183,8 @@ spec:
|
|||
serviceAccountName: kyverno-service-account
|
||||
containers:
|
||||
- name: kyverno
|
||||
image: nirmata/kyverno:dev-testing
|
||||
image: nirmata/kyverno:latest
|
||||
# image: registry-v2.nirmata.io/nirmata/kyverno:testImage
|
||||
args: ["--filterKind","Nodes,Events,APIService,SubjectAccessReview"]
|
||||
ports:
|
||||
- containerPort: 443
|
||||
|
|
|
@ -88,7 +88,7 @@ func (pc *controller) handleErr(err error, key interface{}) {
|
|||
}
|
||||
pc.queue.Forget(key)
|
||||
glog.Error(err)
|
||||
glog.Warningf("Dropping the key %q out of the queue: %v", key, err)
|
||||
glog.Warningf("Dropping the key out of the queue: %v", err)
|
||||
}
|
||||
|
||||
func (c *controller) syncHandler(obj interface{}) error {
|
||||
|
|
|
@ -105,6 +105,26 @@ func (in *Generation) DeepCopyInto(out *Generation) {
|
|||
}
|
||||
}
|
||||
|
||||
// return true -> if there were any removals
|
||||
// return false -> if it looks the same
|
||||
func (v *Violation) RemoveRulesOfType(ruleType string) bool {
|
||||
removed := false
|
||||
updatedRules := []FailedRule{}
|
||||
for _, r := range v.Rules {
|
||||
if r.Type == ruleType {
|
||||
removed = true
|
||||
continue
|
||||
}
|
||||
updatedRules = append(updatedRules, r)
|
||||
}
|
||||
|
||||
if removed {
|
||||
v.Rules = updatedRules
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//IsEqual Check if violatiosn are equal
|
||||
func (v *Violation) IsEqual(nv Violation) bool {
|
||||
// We do not need to compare resource info as it will be same
|
||||
|
|
|
@ -162,7 +162,7 @@ func (pc *PolicyController) handleErr(err error, key interface{}) {
|
|||
}
|
||||
pc.queue.Forget(key)
|
||||
glog.Error(err)
|
||||
glog.Warningf("Dropping the key %q out of the queue: %v", key, err)
|
||||
glog.Warningf("Dropping the key out of the queue: %v", err)
|
||||
}
|
||||
|
||||
func (pc *PolicyController) syncHandler(obj interface{}) error {
|
||||
|
@ -192,12 +192,12 @@ func (pc *PolicyController) syncHandler(obj interface{}) error {
|
|||
//TODO: processPolicy
|
||||
glog.Infof("process policy %s on existing resources", policy.GetName())
|
||||
policyInfos := engine.ProcessExisting(pc.client, policy)
|
||||
events, _ := pc.createEventsAndViolations(policyInfos)
|
||||
events, violations := pc.createEventsAndViolations(policyInfos)
|
||||
pc.eventController.Add(events...)
|
||||
// err = pc.violationBuilder.Add(violations...)
|
||||
// if err != nil {
|
||||
// glog.Error(err)
|
||||
// }
|
||||
err = pc.violationBuilder.Add(violations...)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
// add annotations to resources
|
||||
pc.createAnnotations(policyInfos)
|
||||
|
|
|
@ -101,6 +101,10 @@ func applyPolicy(client *client.Client, policy *types.Policy, res *resourceInfo)
|
|||
|
||||
func mutation(p *types.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]*info.RuleInfo, error) {
|
||||
patches, ruleInfos := Mutate(*p, rawResource, *gvk)
|
||||
if len(ruleInfos) == 0 {
|
||||
// no rules were processed
|
||||
return nil, nil
|
||||
}
|
||||
// option 2: (original Resource + patch) compare with (original resource)
|
||||
mergePatches := JoinPatches(patches)
|
||||
// merge the patches
|
||||
|
|
|
@ -159,6 +159,9 @@ func RulesSuccesfuly(rules []*RuleInfo) bool {
|
|||
|
||||
//AddRuleInfos sets the rule information
|
||||
func (pi *PolicyInfo) AddRuleInfos(rules []*RuleInfo) {
|
||||
if rules == nil {
|
||||
return
|
||||
}
|
||||
if !RulesSuccesfuly(rules) {
|
||||
pi.success = false
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
event "github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/info"
|
||||
"github.com/nirmata/kyverno/pkg/sharedinformer"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
//Generator to generate policy violation
|
||||
|
@ -48,6 +49,9 @@ func NewPolicyViolationBuilder(client *client.Client,
|
|||
}
|
||||
|
||||
func (b *builder) Add(infos ...*Info) error {
|
||||
if infos == nil {
|
||||
return nil
|
||||
}
|
||||
for _, info := range infos {
|
||||
return b.processViolation(info)
|
||||
}
|
||||
|
@ -55,97 +59,297 @@ func (b *builder) Add(infos ...*Info) error {
|
|||
}
|
||||
|
||||
func (b *builder) processViolation(info *Info) error {
|
||||
currVs := map[string]interface{}{}
|
||||
statusMap := map[string]interface{}{}
|
||||
var ok bool
|
||||
//TODO: hack get from client
|
||||
p1, err := b.client.GetResource("Policy", "", info.Policy, "status")
|
||||
violationsMap := map[string]interface{}{}
|
||||
violationMap := map[string]interface{}{}
|
||||
var violations interface{}
|
||||
var violation interface{}
|
||||
// Get Policy
|
||||
obj, err := b.client.GetResource("Policy", "", info.Policy, "status")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unstr := p1.UnstructuredContent()
|
||||
// check if "status" field exists
|
||||
unstr := obj.UnstructuredContent()
|
||||
// get "status" subresource
|
||||
status, ok := unstr["status"]
|
||||
if ok {
|
||||
// status exists
|
||||
// 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"]
|
||||
// get policy violations
|
||||
violations, ok = statusMap["violations"]
|
||||
if !ok {
|
||||
glog.Info("violation not present")
|
||||
}
|
||||
// Violations map[string][]Violations
|
||||
glog.Info(reflect.TypeOf(violations))
|
||||
if currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
return errors.New("Unable to parse violations")
|
||||
}
|
||||
}
|
||||
// Info:
|
||||
// Key - Kind, Namespace, Name
|
||||
// policy - Name
|
||||
// violation, ok := currVs[info.getKey()]
|
||||
// Key -> resource
|
||||
// 1> Check if there were any previous violations for the given key
|
||||
// 2> If No, create a new one
|
||||
if !ok {
|
||||
currVs[info.getKey()] = info.Violation
|
||||
} else {
|
||||
currV := currVs[info.getKey()]
|
||||
glog.Info(reflect.TypeOf(currV))
|
||||
v, ok := currV.(map[string]interface{})
|
||||
if !ok {
|
||||
glog.Info("type not matching")
|
||||
}
|
||||
// get rules
|
||||
rules, ok := v["rules"]
|
||||
if !ok {
|
||||
glog.Info("rules not found")
|
||||
}
|
||||
glog.Info(reflect.TypeOf(rules))
|
||||
rs, ok := rules.([]interface{})
|
||||
if !ok {
|
||||
glog.Info("type not matching")
|
||||
}
|
||||
// check if rules are samre
|
||||
if isRuleNamesEqual(rs, info.Violation.Rules) {
|
||||
return nil
|
||||
}
|
||||
// else update the errors
|
||||
currVs[info.getKey()] = info.Violation
|
||||
violationsMap, ok = violations.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Unable to get status.violations subresource")
|
||||
}
|
||||
// check if the resource has a violation
|
||||
violation, ok = violationsMap[info.getKey()]
|
||||
if !ok {
|
||||
// add resource violation
|
||||
violationsMap[info.getKey()] = info.Violation
|
||||
statusMap["violations"] = violationsMap
|
||||
unstr["status"] = statusMap
|
||||
} else {
|
||||
violationMap, ok = violation.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Unable to get status.violations.violation subresource")
|
||||
}
|
||||
// we check if the new violation updates are different from stored violation info
|
||||
v := v1alpha1.Violation{}
|
||||
err := runtime.DefaultUnstructuredConverter.FromUnstructured(violationMap, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// compare v & info.Violation
|
||||
if v.IsEqual(info.Violation) {
|
||||
// no updates to violation
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
// update the violation
|
||||
violationsMap[info.getKey()] = info.Violation
|
||||
statusMap["violations"] = violationsMap
|
||||
unstr["status"] = statusMap
|
||||
}
|
||||
} else {
|
||||
violationsMap[info.getKey()] = info.Violation
|
||||
statusMap["violations"] = violationsMap
|
||||
unstr["status"] = statusMap
|
||||
}
|
||||
// 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"] = currVs
|
||||
unstr["status"] = statusMap
|
||||
p1.SetUnstructuredContent(unstr)
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", p1, false)
|
||||
|
||||
obj.SetUnstructuredContent(unstr)
|
||||
// update the status sub-resource for policy
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", obj, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *builder) RemoveInactiveViolation(policy, rKind, rNs, rName string, ruleType info.RuleType) error {
|
||||
statusMap := map[string]interface{}{}
|
||||
violationsMap := map[string]interface{}{}
|
||||
violationMap := map[string]interface{}{}
|
||||
var violations interface{}
|
||||
var violation interface{}
|
||||
// Get Policy
|
||||
obj, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unstr := obj.UnstructuredContent()
|
||||
// get "status" subresource
|
||||
status, ok := unstr["status"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
// status exists
|
||||
// status is already present then we append violations
|
||||
if statusMap, ok = status.(map[string]interface{}); !ok {
|
||||
return errors.New("Unable to parse status subresource")
|
||||
}
|
||||
// get policy violations
|
||||
violations, ok = statusMap["violations"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
violationsMap, ok = violations.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Unable to get status.violations subresource")
|
||||
}
|
||||
// check if the resource has a violation
|
||||
violation, ok = violationsMap[BuildKey(rKind, rNs, rName)]
|
||||
if !ok {
|
||||
// no violation for this resource
|
||||
return nil
|
||||
}
|
||||
violationMap, ok = violation.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Unable to get status.violations.violation subresource")
|
||||
}
|
||||
// check remove the rules of the given type
|
||||
// this is called when the policy is applied succesfully, so we can remove the previous failed rules
|
||||
// if all rules are to be removed, the deleted the violation
|
||||
v := v1alpha1.Violation{}
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(violationMap, &v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !v.RemoveRulesOfType(ruleType.String()) {
|
||||
// no rule of given type found,
|
||||
// no need to remove rule
|
||||
return nil
|
||||
}
|
||||
// if there are no faile rules remove the violation
|
||||
if len(v.Rules) == 0 {
|
||||
delete(violationsMap, BuildKey(rKind, rNs, rName))
|
||||
} else {
|
||||
// update the rules
|
||||
violationsMap[BuildKey(rKind, rNs, rName)] = v
|
||||
}
|
||||
statusMap["violations"] = violationsMap
|
||||
unstr["status"] = statusMap
|
||||
|
||||
obj.SetUnstructuredContent(unstr)
|
||||
// update the status sub-resource for policy
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", obj, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *builder) ResourceRemoval(policy, rKind, rNs, rName string) error {
|
||||
statusMap := map[string]interface{}{}
|
||||
violationsMap := map[string]interface{}{}
|
||||
var violations interface{}
|
||||
// Get Policy
|
||||
obj, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unstr := obj.UnstructuredContent()
|
||||
// get "status" subresource
|
||||
status, ok := unstr["status"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
// status exists
|
||||
// status is already present then we append violations
|
||||
if statusMap, ok = status.(map[string]interface{}); !ok {
|
||||
return errors.New("Unable to parse status subresource")
|
||||
}
|
||||
// get policy violations
|
||||
violations, ok = statusMap["violations"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
violationsMap, ok = violations.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Unable to get status.violations subresource")
|
||||
}
|
||||
|
||||
// check if the resource has a violation
|
||||
_, ok = violationsMap[BuildKey(rKind, rNs, rName)]
|
||||
if !ok {
|
||||
// no violation for this resource
|
||||
return nil
|
||||
}
|
||||
// remove the pair from the map
|
||||
delete(violationsMap, BuildKey(rKind, rNs, rName))
|
||||
if len(violationsMap) == 0 {
|
||||
delete(statusMap, "violations")
|
||||
} else {
|
||||
statusMap["violations"] = violationsMap
|
||||
}
|
||||
unstr["status"] = statusMap
|
||||
|
||||
obj.SetUnstructuredContent(unstr)
|
||||
// update the status sub-resource for policy
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", obj, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (b *builder) processViolation(info *Info) error {
|
||||
// currVs := map[string]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 {
|
||||
// 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")
|
||||
// }
|
||||
// // Violations map[string][]Violations
|
||||
// glog.Info(reflect.TypeOf(violations))
|
||||
// if currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
// return errors.New("Unable to parse violations")
|
||||
// }
|
||||
// }
|
||||
// // Info:
|
||||
// // Key - Kind, Namespace, Name
|
||||
// // policy - Name
|
||||
// // violation, ok := currVs[info.getKey()]
|
||||
// // Key -> resource
|
||||
// // 1> Check if there were any previous violations for the given key
|
||||
// // 2> If No, create a new one
|
||||
// if !ok {
|
||||
// currVs[info.getKey()] = info.Violation
|
||||
// } else {
|
||||
// currV := currVs[info.getKey()]
|
||||
// glog.Info(reflect.TypeOf(currV))
|
||||
// v, ok := currV.(map[string]interface{})
|
||||
// if !ok {
|
||||
// glog.Info("type not matching")
|
||||
// }
|
||||
// // get rules
|
||||
// rules, ok := v["rules"]
|
||||
// if !ok {
|
||||
// glog.Info("rules not found")
|
||||
// }
|
||||
// glog.Info(reflect.TypeOf(rules))
|
||||
// rs, ok := rules.([]interface{})
|
||||
// if !ok {
|
||||
// glog.Info("type not matching")
|
||||
// }
|
||||
// // check if rules are samre
|
||||
// if isRuleNamesEqual(rs, info.Violation.Rules) {
|
||||
// return nil
|
||||
// }
|
||||
// // else update the errors
|
||||
// currVs[info.getKey()] = info.Violation
|
||||
// }
|
||||
// // 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"] = currVs
|
||||
// unstr["status"] = statusMap
|
||||
// p1.SetUnstructuredContent(unstr)
|
||||
// _, err = b.client.UpdateStatusResource("Policy", "", p1, false)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
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)
|
||||
|
@ -254,124 +458,124 @@ func isRuleNamesEqual(currRules []interface{}, newRules []v1alpha1.FailedRule) b
|
|||
return true
|
||||
}
|
||||
|
||||
//RemoveViolation will remove the violation for the resource if there was one
|
||||
func (b *builder) RemoveInactiveViolation(policy, rKind, rNs, rName string, ruleType info.RuleType) error {
|
||||
// Remove the <resource, Violation> pair from map
|
||||
statusMap := map[string]interface{}{}
|
||||
currVs := map[string]interface{}{}
|
||||
// Get the policy
|
||||
p, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
if err != nil {
|
||||
glog.Infof("policy %s not found", policy)
|
||||
return err
|
||||
}
|
||||
unstr := p.UnstructuredContent()
|
||||
// //RemoveViolation will remove the violation for the resource if there was one
|
||||
// func (b *builder) RemoveInactiveViolation(policy, rKind, rNs, rName string, ruleType info.RuleType) error {
|
||||
// // Remove the <resource, Violation> pair from map
|
||||
// statusMap := map[string]interface{}{}
|
||||
// currVs := map[string]interface{}{}
|
||||
// // Get the policy
|
||||
// p, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
// if err != nil {
|
||||
// glog.Infof("policy %s not found", policy)
|
||||
// return err
|
||||
// }
|
||||
// unstr := p.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 currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
return errors.New("Unable to parse violations")
|
||||
}
|
||||
currV, ok := currVs[BuildKey(rKind, rNs, rName)]
|
||||
if !ok {
|
||||
// No Violation present
|
||||
return nil
|
||||
}
|
||||
glog.Info(reflect.TypeOf(currV))
|
||||
v, ok := currV.(map[string]interface{})
|
||||
if !ok {
|
||||
glog.Info("type not matching")
|
||||
}
|
||||
// get rules
|
||||
rules, ok := v["rules"]
|
||||
if !ok {
|
||||
glog.Info("rules not found")
|
||||
}
|
||||
glog.Info(reflect.TypeOf(rules))
|
||||
rs, ok := rules.([]interface{})
|
||||
if !ok {
|
||||
glog.Info("type not matching")
|
||||
}
|
||||
// Remove rules of defined type
|
||||
newrs, err := removeRuleTypes(rs, ruleType)
|
||||
if err != nil {
|
||||
glog.Info(err)
|
||||
}
|
||||
if newrs == nil {
|
||||
// all records are removed and is empty
|
||||
glog.Info("can remove the record")
|
||||
delete(currVs, BuildKey(rKind, rNs, rName))
|
||||
} else {
|
||||
v["rules"] = newrs
|
||||
// update the violation with new rule
|
||||
currVs[BuildKey(rKind, rNs, rName)] = v
|
||||
}
|
||||
// update violations
|
||||
statusMap["violations"] = currVs
|
||||
// update status
|
||||
unstr["status"] = statusMap
|
||||
p.SetUnstructuredContent(unstr)
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", p, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// // 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 currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
// return errors.New("Unable to parse violations")
|
||||
// }
|
||||
// currV, ok := currVs[BuildKey(rKind, rNs, rName)]
|
||||
// if !ok {
|
||||
// // No Violation present
|
||||
// return nil
|
||||
// }
|
||||
// glog.Info(reflect.TypeOf(currV))
|
||||
// v, ok := currV.(map[string]interface{})
|
||||
// if !ok {
|
||||
// glog.Info("type not matching")
|
||||
// }
|
||||
// // get rules
|
||||
// rules, ok := v["rules"]
|
||||
// if !ok {
|
||||
// glog.Info("rules not found")
|
||||
// }
|
||||
// glog.Info(reflect.TypeOf(rules))
|
||||
// rs, ok := rules.([]interface{})
|
||||
// if !ok {
|
||||
// glog.Info("type not matching")
|
||||
// }
|
||||
// // Remove rules of defined type
|
||||
// newrs, err := removeRuleTypes(rs, ruleType)
|
||||
// if err != nil {
|
||||
// glog.Info(err)
|
||||
// }
|
||||
// if newrs == nil {
|
||||
// // all records are removed and is empty
|
||||
// glog.Info("can remove the record")
|
||||
// delete(currVs, BuildKey(rKind, rNs, rName))
|
||||
// } else {
|
||||
// v["rules"] = newrs
|
||||
// // update the violation with new rule
|
||||
// currVs[BuildKey(rKind, rNs, rName)] = v
|
||||
// }
|
||||
// // update violations
|
||||
// statusMap["violations"] = currVs
|
||||
// // update status
|
||||
// unstr["status"] = statusMap
|
||||
// p.SetUnstructuredContent(unstr)
|
||||
// _, err = b.client.UpdateStatusResource("Policy", "", p, false)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (b *builder) ResourceRemoval(policy, rKind, rNs, rName string) error {
|
||||
// Remove the <resource, Violation> pair from map
|
||||
statusMap := map[string]interface{}{}
|
||||
currVs := map[string]interface{}{}
|
||||
// Get the policy
|
||||
p, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
if err != nil {
|
||||
glog.Infof("policy %s not found", policy)
|
||||
return err
|
||||
}
|
||||
unstr := p.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 currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
return errors.New("Unable to parse violations")
|
||||
}
|
||||
_, ok = currVs[BuildKey(rKind, rNs, rName)]
|
||||
if !ok {
|
||||
// No Violation for this resource
|
||||
return nil
|
||||
}
|
||||
// remove the pair from the map
|
||||
delete(currVs, BuildKey(rKind, rNs, rName))
|
||||
glog.Info("Removed Violation")
|
||||
// update violations
|
||||
statusMap["violations"] = currVs
|
||||
// update status
|
||||
unstr["status"] = statusMap
|
||||
p.SetUnstructuredContent(unstr)
|
||||
_, err = b.client.UpdateStatusResource("Policy", "", p, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// func (b *builder) ResourceRemoval(policy, rKind, rNs, rName string) error {
|
||||
// // Remove the <resource, Violation> pair from map
|
||||
// statusMap := map[string]interface{}{}
|
||||
// currVs := map[string]interface{}{}
|
||||
// // Get the policy
|
||||
// p, err := b.client.GetResource("Policy", "", policy, "status")
|
||||
// if err != nil {
|
||||
// glog.Infof("policy %s not found", policy)
|
||||
// return err
|
||||
// }
|
||||
// unstr := p.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 currVs, ok = violations.(map[string]interface{}); !ok {
|
||||
// return errors.New("Unable to parse violations")
|
||||
// }
|
||||
// _, ok = currVs[BuildKey(rKind, rNs, rName)]
|
||||
// if !ok {
|
||||
// // No Violation for this resource
|
||||
// return nil
|
||||
// }
|
||||
// // remove the pair from the map
|
||||
// delete(currVs, BuildKey(rKind, rNs, rName))
|
||||
// glog.Info("Removed Violation")
|
||||
// // update violations
|
||||
// statusMap["violations"] = currVs
|
||||
// // update status
|
||||
// unstr["status"] = statusMap
|
||||
// p.SetUnstructuredContent(unstr)
|
||||
// _, err = b.client.UpdateStatusResource("Policy", "", p, false)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
)
|
||||
|
||||
func (ws *WebhookServer) removePolicyViolation(request *v1beta1.AdmissionRequest) error {
|
||||
return nil
|
||||
// Get the list of policies that apply on the resource
|
||||
policies, err := ws.policyLister.List(labels.NewSelector())
|
||||
if err != nil {
|
||||
|
@ -21,9 +20,10 @@ func (ws *WebhookServer) removePolicyViolation(request *v1beta1.AdmissionRequest
|
|||
if !StringInSlice(request.Kind.Kind, getApplicableKindsForPolicy(policy)) {
|
||||
continue
|
||||
}
|
||||
rname := engine.ParseNameFromObject(request.Object.Raw)
|
||||
rns := engine.ParseNamespaceFromObject(request.Object.Raw)
|
||||
rkind := engine.ParseKindFromObject(request.Object.Raw)
|
||||
// get the details from the request
|
||||
rname := request.Name
|
||||
rns := request.Namespace
|
||||
rkind := request.Kind.Kind
|
||||
// check if the resource meets the policy Resource description
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
ok := engine.ResourceMeetsDescription(request.Object.Raw, rule.ResourceDescription, request.Kind)
|
||||
|
|
|
@ -56,7 +56,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
|
|||
glog.Warning(r.Msgs)
|
||||
}
|
||||
} else {
|
||||
// CleanUp Violations if exists
|
||||
// // CleanUp Violations if exists
|
||||
// err := ws.violationBuilder.RemoveInactiveViolation(policy.Name, request.Kind.Kind, rns, rname, info.Mutation)
|
||||
// if err != nil {
|
||||
// glog.Info(err)
|
||||
|
@ -82,7 +82,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
|
|||
}
|
||||
|
||||
if len(allPatches) > 0 {
|
||||
eventsInfo, _ := newEventInfoFromPolicyInfo(policyInfos, (request.Operation == v1beta1.Update), false)
|
||||
eventsInfo, _ := newEventInfoFromPolicyInfo(policyInfos, (request.Operation == v1beta1.Update), info.Mutation)
|
||||
ws.eventController.Add(eventsInfo...)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
//TODO: change validation from bool -> enum(validation, mutation)
|
||||
func newEventInfoFromPolicyInfo(policyInfoList []*info.PolicyInfo, onUpdate bool, validation bool) ([]*event.Info, []*violation.Info) {
|
||||
func newEventInfoFromPolicyInfo(policyInfoList []*info.PolicyInfo, onUpdate bool, ruleType info.RuleType) ([]*event.Info, []*violation.Info) {
|
||||
var eventsInfo []*event.Info
|
||||
var violations []*violation.Info
|
||||
ok, msg := isAdmSuccesful(policyInfoList)
|
||||
|
@ -40,7 +40,7 @@ func newEventInfoFromPolicyInfo(policyInfoList []*info.PolicyInfo, onUpdate bool
|
|||
glog.V(3).Infof("Request blocked events info has prepared for %s/%s and %s/%s\n", policyKind, pi.Name, pi.RKind, pi.RName)
|
||||
}
|
||||
// if report flag is set
|
||||
if pi.ValidationFailureAction == ReportViolation && validation {
|
||||
if pi.ValidationFailureAction == ReportViolation && ruleType == info.Validation {
|
||||
// Create Violations
|
||||
v := violation.BuldNewViolation(pi.Name, pi.RKind, pi.RNamespace, pi.RName, event.PolicyViolation.String(), pi.GetFailedRules())
|
||||
violations = append(violations, v)
|
||||
|
|
|
@ -89,6 +89,8 @@ const (
|
|||
ReportViolation = "report"
|
||||
)
|
||||
|
||||
// returns true -> if there is even one policy that blocks resource requst
|
||||
// returns false -> if all the policies are meant to report only, we dont block resource request
|
||||
func toBlock(pis []*info.PolicyInfo) bool {
|
||||
for _, pi := range pis {
|
||||
if pi.ValidationFailureAction != ReportViolation {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
engine "github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/info"
|
||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -16,7 +15,7 @@ import (
|
|||
func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
|
||||
policyInfos := []*info.PolicyInfo{}
|
||||
// var violations []*violation.Info
|
||||
var eventsInfo []*event.Info
|
||||
// var eventsInfo []*event.Info
|
||||
policies, err := ws.policyLister.List(labels.NewSelector())
|
||||
if err != nil {
|
||||
// Unable to connect to policy Lister to access policies
|
||||
|
@ -64,11 +63,11 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
|
|||
glog.Warning(r.Msgs)
|
||||
}
|
||||
} else {
|
||||
// // CleanUp Violations if exists
|
||||
// err := ws.violationBuilder.RemoveInactiveViolation(policy.Name, request.Kind.Kind, rns, rname, info.Validation)
|
||||
// if err != nil {
|
||||
// glog.Info(err)
|
||||
// }
|
||||
// CleanUp Violations if exists
|
||||
err := ws.violationBuilder.RemoveInactiveViolation(policy.Name, request.Kind.Kind, rns, rname, info.Validation)
|
||||
if err != nil {
|
||||
glog.Info(err)
|
||||
}
|
||||
|
||||
if len(ruleInfos) > 0 {
|
||||
glog.Infof("Validation from policy %s has applied succesfully to %s %s/%s", policy.Name, request.Kind.Kind, rname, rns)
|
||||
|
@ -89,10 +88,10 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest) *v1
|
|||
}
|
||||
|
||||
if len(policyInfos) > 0 && len(policyInfos[0].Rules) != 0 {
|
||||
eventsInfo, _ = newEventInfoFromPolicyInfo(policyInfos, (request.Operation == v1beta1.Update), true)
|
||||
eventsInfo, violations := newEventInfoFromPolicyInfo(policyInfos, (request.Operation == v1beta1.Update), info.Validation)
|
||||
// If the validationFailureAction flag is set "report",
|
||||
// then we dont block the request and report the violations
|
||||
// ws.violationBuilder.Add(violations...)
|
||||
ws.violationBuilder.Add(violations...)
|
||||
ws.eventController.Add(eventsInfo...)
|
||||
}
|
||||
// add annotations
|
||||
|
|
Loading…
Add table
Reference in a new issue