mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
- remove policy violation created on owner and related logic; - use generic call to create violation info
This commit is contained in:
parent
9194251a38
commit
ecbbd04bc5
9 changed files with 95 additions and 377 deletions
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
|
@ -15,55 +14,10 @@ func (nsc *NamespaceController) report(engineResponses []response.EngineResponse
|
|||
eventInfos := generateEvents(engineResponses)
|
||||
nsc.eventGen.Add(eventInfos...)
|
||||
// generate policy violations
|
||||
pvInfos := generatePVs(engineResponses)
|
||||
pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses)
|
||||
nsc.pvGenerator.Add(pvInfos...)
|
||||
}
|
||||
|
||||
func generatePVs(ers []response.EngineResponse) []policyviolation.Info {
|
||||
var pvInfos []policyviolation.Info
|
||||
for _, er := range ers {
|
||||
// ignore creation of PV for resoruces that are yet to be assigned a name
|
||||
if er.PolicyResponse.Resource.Name == "" {
|
||||
glog.V(4).Infof("resource %v, has not been assigned a name, not creating a policy violation for it", er.PolicyResponse.Resource)
|
||||
continue
|
||||
}
|
||||
if er.IsSuccesful() {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("Building policy violation for engine response %v", er)
|
||||
// build policy violation info
|
||||
pvInfos = append(pvInfos, buildPVInfo(er))
|
||||
}
|
||||
|
||||
return pvInfos
|
||||
}
|
||||
|
||||
func buildPVInfo(er response.EngineResponse) policyviolation.Info {
|
||||
info := policyviolation.Info{
|
||||
Blocked: false,
|
||||
PolicyName: er.PolicyResponse.Policy,
|
||||
Resource: er.PatchedResource,
|
||||
Rules: buildViolatedRules(er),
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func buildViolatedRules(er response.EngineResponse) []kyverno.ViolatedRule {
|
||||
var violatedRules []kyverno.ViolatedRule
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Success {
|
||||
continue
|
||||
}
|
||||
vrule := kyverno.ViolatedRule{
|
||||
Name: rule.Name,
|
||||
Type: rule.Type,
|
||||
Message: rule.Message,
|
||||
}
|
||||
violatedRules = append(violatedRules, vrule)
|
||||
}
|
||||
return violatedRules
|
||||
}
|
||||
|
||||
func generateEvents(ers []response.EngineResponse) []event.Info {
|
||||
var eventInfos []event.Info
|
||||
for _, er := range ers {
|
||||
|
|
|
@ -7,84 +7,52 @@ import (
|
|||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1"
|
||||
dclient "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func (pc *PolicyController) cleanUpPolicyViolation(pResponse response.PolicyResponse) {
|
||||
// 1- check if there is violation on resource (label:Selector)
|
||||
// 2- check if there is violation on owner
|
||||
// - recursively get owner by queries the api server for owner information of the resource
|
||||
|
||||
// there can be multiple violations as a resource can have multiple owners
|
||||
// - check if there is violation on resource (label:Selector)
|
||||
if pResponse.Resource.Namespace == "" {
|
||||
pvs, err := getClusterPVs(pc.cpvLister, pc.client, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Name)
|
||||
pv, err := getClusterPV(pc.cpvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to cleanUp violations: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, pv := range pvs {
|
||||
if reflect.DeepEqual(pv, kyverno.ClusterPolicyViolation{}) {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("cleanup cluster violation %s on %s", pv.Name, pv.Spec.ResourceSpec.ToKey())
|
||||
if err := pc.pvControl.DeleteClusterPolicyViolation(pv.Name); err != nil {
|
||||
glog.Errorf("failed to delete cluster policy violation %s on %s: %v", pv.Name, pv.Spec.ResourceSpec.ToKey(), err)
|
||||
continue
|
||||
}
|
||||
if reflect.DeepEqual(pv, kyverno.ClusterPolicyViolation{}) {
|
||||
return
|
||||
}
|
||||
|
||||
glog.V(4).Infof("cleanup cluster violation %s on %s", pv.Name, pv.Spec.ResourceSpec.ToKey())
|
||||
if err := pc.pvControl.DeleteClusterPolicyViolation(pv.Name); err != nil {
|
||||
glog.Errorf("failed to delete cluster policy violation %s on %s: %v", pv.Name, pv.Spec.ResourceSpec.ToKey(), err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nspvs, err := getNamespacedPVs(pc.nspvLister, pc.client, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Namespace, pResponse.Resource.Name)
|
||||
// namespace policy violation
|
||||
nspv, err := getNamespacedPV(pc.nspvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Namespace, pResponse.Resource.Name)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, pv := range nspvs {
|
||||
if reflect.DeepEqual(pv, kyverno.PolicyViolation{}) {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("cleanup namespaced violation %s on %s.%s", pv.Name, pResponse.Resource.Namespace, pv.Spec.ResourceSpec.ToKey())
|
||||
if err := pc.pvControl.DeleteNamespacedPolicyViolation(pv.Namespace, pv.Name); err != nil {
|
||||
glog.Errorf("failed to delete namespaced policy violation %s on %s: %v", pv.Name, pv.Spec.ResourceSpec.ToKey(), err)
|
||||
continue
|
||||
}
|
||||
if reflect.DeepEqual(nspv, kyverno.PolicyViolation{}) {
|
||||
return
|
||||
}
|
||||
glog.V(4).Infof("cleanup namespaced violation %s on %s.%s", nspv.Name, pResponse.Resource.Namespace, nspv.Spec.ResourceSpec.ToKey())
|
||||
if err := pc.pvControl.DeleteNamespacedPolicyViolation(nspv.Namespace, nspv.Name); err != nil {
|
||||
glog.Errorf("failed to delete namespaced policy violation %s on %s: %v", nspv.Name, nspv.Spec.ResourceSpec.ToKey(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func getClusterPVs(pvLister kyvernolister.ClusterPolicyViolationLister, client *dclient.Client, policyName, kind, name string) ([]kyverno.ClusterPolicyViolation, error) {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
// Wont do the claiming of objects, just lookup based on selectors
|
||||
func getClusterPV(pvLister kyvernolister.ClusterPolicyViolationLister, policyName, rkind, rname string) (kyverno.ClusterPolicyViolation, error) {
|
||||
var err error
|
||||
// Check Violation on resource
|
||||
pv, err := getClusterPVOnResource(pvLister, policyName, kind, name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching violation on existing resource: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(pv, kyverno.ClusterPolicyViolation{}) {
|
||||
// found a violation on resource
|
||||
pvs = append(pvs, pv)
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
// Check Violations on owner
|
||||
pvs, err = getClusterPVonOwnerRef(pvLister, client, policyName, kind, name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching pv: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
// Wont do the claiming of objects, just lookup based on selectors and owner references
|
||||
func getClusterPVOnResource(pvLister kyvernolister.ClusterPolicyViolationLister, policyName, kind, name string) (kyverno.ClusterPolicyViolation, error) {
|
||||
pvs, err := pvLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.V(2).Infof("unable to list policy violations : %v", err)
|
||||
|
@ -94,65 +62,16 @@ func getClusterPVOnResource(pvLister kyvernolister.ClusterPolicyViolationLister,
|
|||
for _, pv := range pvs {
|
||||
// find a policy on same resource and policy combination
|
||||
if pv.Spec.Policy == policyName &&
|
||||
pv.Spec.ResourceSpec.Kind == kind &&
|
||||
pv.Spec.ResourceSpec.Name == name {
|
||||
pv.Spec.ResourceSpec.Kind == rkind &&
|
||||
pv.Spec.ResourceSpec.Name == rname {
|
||||
return *pv, nil
|
||||
}
|
||||
}
|
||||
return kyverno.ClusterPolicyViolation{}, nil
|
||||
}
|
||||
|
||||
func getClusterPVonOwnerRef(pvLister kyvernolister.ClusterPolicyViolationLister, dclient *dclient.Client, policyName, kind, name string) ([]kyverno.ClusterPolicyViolation, error) {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
// get resource
|
||||
resource, err := dclient.GetResource(kind, "", name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching the resource: %v", err)
|
||||
return pvs, fmt.Errorf("error while fetching the resource: %v", err)
|
||||
}
|
||||
|
||||
// getOwners returns nil if there is any error
|
||||
owners := map[kyverno.ResourceSpec]interface{}{}
|
||||
policyviolation.GetOwner(dclient, owners, *resource)
|
||||
// as we can have multiple top level owners to a resource
|
||||
// check if pv exists on each one
|
||||
for owner := range owners {
|
||||
pv, err := getClusterPVOnResource(pvLister, policyName, owner.Kind, owner.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("error while fetching resource owners: %v", err)
|
||||
continue
|
||||
}
|
||||
pvs = append(pvs, pv)
|
||||
}
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
func getNamespacedPVs(nspvLister kyvernolister.PolicyViolationLister, client *dclient.Client, policyName, kind, namespace, name string) ([]kyverno.PolicyViolation, error) {
|
||||
var pvs []kyverno.PolicyViolation
|
||||
var err error
|
||||
pv, err := getNamespacedPVOnResource(nspvLister, policyName, kind, namespace, name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching violation on existing resource: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(pv, kyverno.PolicyViolation{}) {
|
||||
// found a violation on resource
|
||||
pvs = append(pvs, pv)
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
// Check Violations on owner
|
||||
pvs, err = getNamespacedPVonOwnerRef(nspvLister, client, policyName, kind, namespace, name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching pv: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
func getNamespacedPVOnResource(nspvLister kyvernolister.PolicyViolationLister, policyName, kind, namespace, name string) (kyverno.PolicyViolation, error) {
|
||||
nspvs, err := nspvLister.PolicyViolations(namespace).List(labels.Everything())
|
||||
func getNamespacedPV(nspvLister kyvernolister.PolicyViolationLister, policyName, rkind, rnamespace, rname string) (kyverno.PolicyViolation, error) {
|
||||
nspvs, err := nspvLister.PolicyViolations(rnamespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.V(2).Infof("failed to list namespaced pv: %v", err)
|
||||
return kyverno.PolicyViolation{}, fmt.Errorf("failed to list namespaced pv: %v", err)
|
||||
|
@ -161,39 +80,15 @@ func getNamespacedPVOnResource(nspvLister kyvernolister.PolicyViolationLister, p
|
|||
for _, nspv := range nspvs {
|
||||
// find a policy on same resource and policy combination
|
||||
if nspv.Spec.Policy == policyName &&
|
||||
nspv.Spec.ResourceSpec.Kind == kind &&
|
||||
nspv.Spec.ResourceSpec.Name == name {
|
||||
nspv.Spec.ResourceSpec.Kind == rkind &&
|
||||
nspv.Spec.ResourceSpec.Name == rname {
|
||||
return *nspv, nil
|
||||
}
|
||||
}
|
||||
|
||||
return kyverno.PolicyViolation{}, nil
|
||||
}
|
||||
|
||||
func getNamespacedPVonOwnerRef(nspvLister kyvernolister.PolicyViolationLister, dclient *dclient.Client, policyName, kind, namespace, name string) ([]kyverno.PolicyViolation, error) {
|
||||
var pvs []kyverno.PolicyViolation
|
||||
// get resource
|
||||
resource, err := dclient.GetResource(kind, namespace, name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while fetching the resource: %v", err)
|
||||
return pvs, err
|
||||
}
|
||||
|
||||
// getOwners returns nil if there is any error
|
||||
owners := map[kyverno.ResourceSpec]interface{}{}
|
||||
policyviolation.GetOwner(dclient, owners, *resource)
|
||||
// as we can have multiple top level owners to a resource
|
||||
// check if pv exists on each one
|
||||
for owner := range owners {
|
||||
pv, err := getNamespacedPVOnResource(nspvLister, policyName, owner.Kind, namespace, owner.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("error while fetching resource owners: %v", err)
|
||||
continue
|
||||
}
|
||||
pvs = append(pvs, pv)
|
||||
}
|
||||
return pvs, nil
|
||||
}
|
||||
|
||||
func converLabelToSelector(labelMap map[string]string) (labels.Selector, error) {
|
||||
ls := &metav1.LabelSelector{}
|
||||
err := metav1.Convert_Map_string_To_string_To_v1_LabelSelector(&labelMap, ls, nil)
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
|
@ -12,13 +11,13 @@ import (
|
|||
|
||||
// for each policy-resource response
|
||||
// - has violation -> report
|
||||
// - no violation -> cleanup policy violations(resource or resource owner)
|
||||
// - no violation -> cleanup policy violations
|
||||
func (pc *PolicyController) cleanupAndReport(engineResponses []response.EngineResponse) {
|
||||
// generate Events
|
||||
eventInfos := generateEvents(engineResponses)
|
||||
pc.eventGen.Add(eventInfos...)
|
||||
// create policy violation
|
||||
pvInfos := generatePVs(engineResponses)
|
||||
pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses)
|
||||
pc.pvGenerator.Add(pvInfos...)
|
||||
// cleanup existing violations if any
|
||||
// if there is any error in clean up, we dont re-queue the resource
|
||||
|
@ -39,51 +38,6 @@ func (pc *PolicyController) cleanUp(ers []response.EngineResponse) {
|
|||
}
|
||||
}
|
||||
|
||||
func generatePVs(ers []response.EngineResponse) []policyviolation.Info {
|
||||
var pvInfos []policyviolation.Info
|
||||
for _, er := range ers {
|
||||
// ignore creation of PV for resoruces that are yet to be assigned a name
|
||||
if er.PolicyResponse.Resource.Name == "" {
|
||||
glog.V(4).Infof("resource %v, has not been assigned a name, not creating a policy violation for it", er.PolicyResponse.Resource)
|
||||
continue
|
||||
}
|
||||
if er.IsSuccesful() {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("Building policy violation for engine response %v", er)
|
||||
// build policy violation info
|
||||
pvInfos = append(pvInfos, buildPVInfo(er))
|
||||
}
|
||||
|
||||
return pvInfos
|
||||
}
|
||||
|
||||
func buildPVInfo(er response.EngineResponse) policyviolation.Info {
|
||||
info := policyviolation.Info{
|
||||
Blocked: false,
|
||||
PolicyName: er.PolicyResponse.Policy,
|
||||
Resource: er.PatchedResource,
|
||||
Rules: buildViolatedRules(er),
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func buildViolatedRules(er response.EngineResponse) []kyverno.ViolatedRule {
|
||||
var violatedRules []kyverno.ViolatedRule
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Success {
|
||||
continue
|
||||
}
|
||||
vrule := kyverno.ViolatedRule{
|
||||
Name: rule.Name,
|
||||
Type: rule.Type,
|
||||
Message: rule.Message,
|
||||
}
|
||||
violatedRules = append(violatedRules, vrule)
|
||||
}
|
||||
return violatedRules
|
||||
}
|
||||
|
||||
func generateEvents(ers []response.EngineResponse) []event.Info {
|
||||
var eventInfos []event.Info
|
||||
for _, er := range ers {
|
||||
|
|
|
@ -3,14 +3,34 @@ package policyviolation
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
)
|
||||
|
||||
func GeneratePVsFromEngineResponse(ers []response.EngineResponse) (pvInfos []Info) {
|
||||
for _, er := range ers {
|
||||
// ignore creation of PV for resoruces that are yet to be assigned a name
|
||||
if er.PolicyResponse.Resource.Name == "" {
|
||||
glog.V(4).Infof("resource %v, has not been assigned a name, not creating a policy violation for it", er.PolicyResponse.Resource)
|
||||
continue
|
||||
}
|
||||
if er.IsSuccesful() {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("Building policy violation for engine response %v", er)
|
||||
// build policy violation info
|
||||
pvInfos = append(pvInfos, buildPVInfo(er))
|
||||
}
|
||||
|
||||
return pvInfos
|
||||
}
|
||||
|
||||
// Builder builds Policy Violation struct
|
||||
// this is base type of namespaced and cluster policy violation
|
||||
type Builder interface {
|
||||
generate(info Info) []kyverno.PolicyViolationTemplate
|
||||
generate(info Info) kyverno.PolicyViolationTemplate
|
||||
build(policy, kind, namespace, name string, rules []kyverno.ViolatedRule) *kyverno.PolicyViolationTemplate
|
||||
}
|
||||
|
||||
|
@ -25,33 +45,10 @@ func newPvBuilder(dclient *client.Client) *pvBuilder {
|
|||
}
|
||||
return &pvb
|
||||
}
|
||||
func (pvb *pvBuilder) generate(info Info) []kyverno.PolicyViolationTemplate {
|
||||
var owners []kyverno.ResourceSpec
|
||||
// get the owners if the resource is blocked or
|
||||
// TODO: https://github.com/nirmata/kyverno/issues/535
|
||||
if info.Blocked {
|
||||
// get resource owners
|
||||
owners = GetOwners(pvb.dclient, info.Resource)
|
||||
}
|
||||
pvs := pvb.buildPolicyViolations(owners, info)
|
||||
return pvs
|
||||
}
|
||||
|
||||
func (pvb *pvBuilder) buildPolicyViolations(owners []kyverno.ResourceSpec, info Info) []kyverno.PolicyViolationTemplate {
|
||||
var pvs []kyverno.PolicyViolationTemplate
|
||||
if len(owners) != 0 {
|
||||
// there are resource owners
|
||||
// generate PV on them
|
||||
for _, resource := range owners {
|
||||
pv := pvb.build(info.PolicyName, resource.Kind, resource.Namespace, resource.Name, info.Rules)
|
||||
pvs = append(pvs, *pv)
|
||||
}
|
||||
} else {
|
||||
// generate PV on resource
|
||||
pv := pvb.build(info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName(), info.Rules)
|
||||
pvs = append(pvs, *pv)
|
||||
}
|
||||
return pvs
|
||||
func (pvb *pvBuilder) generate(info Info) kyverno.PolicyViolationTemplate {
|
||||
pv := pvb.build(info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName(), info.Rules)
|
||||
return *pv
|
||||
}
|
||||
|
||||
func (pvb *pvBuilder) build(policy, kind, namespace, name string, rules []kyverno.ViolatedRule) *kyverno.PolicyViolationTemplate {
|
||||
|
@ -77,3 +74,28 @@ func (pvb *pvBuilder) build(policy, kind, namespace, name string, rules []kyvern
|
|||
pv.SetGenerateName(fmt.Sprintf("%s-", policy))
|
||||
return pv
|
||||
}
|
||||
|
||||
func buildPVInfo(er response.EngineResponse) Info {
|
||||
info := Info{
|
||||
PolicyName: er.PolicyResponse.Policy,
|
||||
Resource: er.PatchedResource,
|
||||
Rules: buildViolatedRules(er),
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func buildViolatedRules(er response.EngineResponse) []kyverno.ViolatedRule {
|
||||
var violatedRules []kyverno.ViolatedRule
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Success {
|
||||
continue
|
||||
}
|
||||
vrule := kyverno.ViolatedRule{
|
||||
Name: rule.Name,
|
||||
Type: rule.Type,
|
||||
Message: rule.Message,
|
||||
}
|
||||
violatedRules = append(violatedRules, vrule)
|
||||
}
|
||||
return violatedRules
|
||||
}
|
||||
|
|
|
@ -56,50 +56,6 @@ func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) (*unstr
|
|||
return obj, nil
|
||||
}
|
||||
|
||||
// GetOwners returns a list of owners
|
||||
func GetOwners(dclient *client.Client, resource unstructured.Unstructured) []kyverno.ResourceSpec {
|
||||
ownerMap := map[kyverno.ResourceSpec]interface{}{}
|
||||
GetOwner(dclient, ownerMap, resource)
|
||||
var owners []kyverno.ResourceSpec
|
||||
for owner := range ownerMap {
|
||||
owners = append(owners, owner)
|
||||
}
|
||||
return owners
|
||||
}
|
||||
|
||||
// GetOwner of a resource by iterating over ownerReferences
|
||||
func GetOwner(dclient *client.Client, ownerMap map[kyverno.ResourceSpec]interface{}, resource unstructured.Unstructured) {
|
||||
var emptyInterface interface{}
|
||||
resourceSpec := kyverno.ResourceSpec{
|
||||
Kind: resource.GetKind(),
|
||||
Namespace: resource.GetNamespace(),
|
||||
Name: resource.GetName(),
|
||||
}
|
||||
if _, ok := ownerMap[resourceSpec]; ok {
|
||||
// owner seen before
|
||||
// breaking loop
|
||||
return
|
||||
}
|
||||
rOwners := resource.GetOwnerReferences()
|
||||
// if there are no resource owners then its top level resource
|
||||
if len(rOwners) == 0 {
|
||||
// add resource to map
|
||||
ownerMap[resourceSpec] = emptyInterface
|
||||
return
|
||||
}
|
||||
for _, rOwner := range rOwners {
|
||||
// lookup resource via client
|
||||
// owner has to be in same namespace
|
||||
owner, err := dclient.GetResource(rOwner.Kind, resource.GetNamespace(), rOwner.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to get resource owner for %s/%s/%s, err: %v", rOwner.Kind, resource.GetNamespace(), rOwner.Name, err)
|
||||
// as we want to process other owners
|
||||
continue
|
||||
}
|
||||
GetOwner(dclient, ownerMap, *owner)
|
||||
}
|
||||
}
|
||||
|
||||
func converLabelToSelector(labelMap map[string]string) (labels.Selector, error) {
|
||||
ls := &metav1.LabelSelector{}
|
||||
err := metav1.Convert_Map_string_To_string_To_v1_LabelSelector(&labelMap, ls, nil)
|
||||
|
|
|
@ -77,7 +77,6 @@ func (ds *dataStore) delete(keyHash string) {
|
|||
|
||||
//Info is a request to create PV
|
||||
type Info struct {
|
||||
Blocked bool
|
||||
PolicyName string
|
||||
Resource unstructured.Unstructured
|
||||
Rules []kyverno.ViolatedRule
|
||||
|
@ -85,7 +84,6 @@ type Info struct {
|
|||
|
||||
func (i Info) toKey() string {
|
||||
keys := []string{
|
||||
strconv.FormatBool(i.Blocked),
|
||||
i.PolicyName,
|
||||
i.Resource.GetKind(),
|
||||
i.Resource.GetNamespace(),
|
||||
|
@ -230,20 +228,17 @@ func (gen *Generator) syncHandler(info Info) error {
|
|||
}
|
||||
|
||||
failure := false
|
||||
// Generate Policy Violations
|
||||
// as there can be multiple owners we can have multiple violations
|
||||
pvs := builder.generate(info)
|
||||
for _, pv := range pvs {
|
||||
// Create Policy Violations
|
||||
glog.V(3).Infof("Creating policy violation: %s", info.toKey())
|
||||
err := handler.create(pv)
|
||||
if err != nil {
|
||||
failure = true
|
||||
glog.V(3).Infof("Failed to create policy violation: %v", err)
|
||||
} else {
|
||||
glog.V(3).Infof("Policy violation created: %s", info.toKey())
|
||||
}
|
||||
pv := builder.generate(info)
|
||||
|
||||
// Create Policy Violations
|
||||
glog.V(3).Infof("Creating policy violation: %s", info.toKey())
|
||||
if err := handler.create(pv); err != nil {
|
||||
failure = true
|
||||
glog.V(3).Infof("Failed to create policy violation: %v", err)
|
||||
} else {
|
||||
glog.V(3).Infof("Policy violation created: %s", info.toKey())
|
||||
}
|
||||
|
||||
if failure {
|
||||
// even if there is a single failure we requeue the request
|
||||
return errors.New("Failed to process some policy violations, re-queuing")
|
||||
|
|
|
@ -43,7 +43,7 @@ func getErrorMsg(engineReponses []response.EngineResponse) string {
|
|||
if !er.IsSuccesful() {
|
||||
// resource in engineReponses is identical as this was called per admission request
|
||||
resourceInfo = fmt.Sprintf("%s/%s/%s", er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name)
|
||||
str = append(str, fmt.Sprintf("failed policy %s", er.PolicyResponse.Policy))
|
||||
str = append(str, fmt.Sprintf("failed policy %s:", er.PolicyResponse.Policy))
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if !rule.Success {
|
||||
str = append(str, rule.ToString())
|
||||
|
@ -51,7 +51,7 @@ func getErrorMsg(engineReponses []response.EngineResponse) string {
|
|||
}
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("Resource %s: %s", resourceInfo, strings.Join(str, "\n"))
|
||||
return fmt.Sprintf("Resource %s %s", resourceInfo, strings.Join(str, ";"))
|
||||
}
|
||||
|
||||
//ArrayFlags to store filterkinds
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package webhooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/nirmata/kyverno/pkg/event"
|
||||
|
@ -105,57 +103,3 @@ func generateEvents(engineResponses []response.EngineResponse, onUpdate bool) []
|
|||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func generatePV(ers []response.EngineResponse, blocked bool) []policyviolation.Info {
|
||||
var pvInfos []policyviolation.Info
|
||||
// generate PV for each
|
||||
for _, er := range ers {
|
||||
// ignore creation of PV for resoruces that are yet to be assigned a name
|
||||
if er.IsSuccesful() {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("Building policy violation for engine response %v", er)
|
||||
// build policy violation info
|
||||
pvInfos = append(pvInfos, buildPVInfo(er, blocked))
|
||||
}
|
||||
return pvInfos
|
||||
}
|
||||
|
||||
func buildPVInfo(er response.EngineResponse, blocked bool) policyviolation.Info {
|
||||
info := policyviolation.Info{
|
||||
Blocked: blocked,
|
||||
PolicyName: er.PolicyResponse.Policy,
|
||||
Resource: er.PatchedResource,
|
||||
Rules: buildViolatedRules(er, blocked),
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func buildViolatedRules(er response.EngineResponse, blocked bool) []kyverno.ViolatedRule {
|
||||
blockMsg := fmt.Sprintf("Request Blocked for resource %s/%s; ", er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Kind)
|
||||
var violatedRules []kyverno.ViolatedRule
|
||||
// if resource was blocked we create dependent
|
||||
dependant := kyverno.ManagedResourceSpec{
|
||||
Kind: er.PolicyResponse.Resource.Kind,
|
||||
CreationBlocked: true,
|
||||
}
|
||||
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Success {
|
||||
continue
|
||||
}
|
||||
vrule := kyverno.ViolatedRule{
|
||||
Name: rule.Name,
|
||||
Type: rule.Type,
|
||||
}
|
||||
|
||||
if blocked {
|
||||
vrule.Message = blockMsg + rule.Message
|
||||
vrule.ManagedResource = dependant
|
||||
} else {
|
||||
vrule.Message = rule.Message
|
||||
}
|
||||
violatedRules = append(violatedRules, vrule)
|
||||
}
|
||||
return violatedRules
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/engine/context"
|
||||
"github.com/nirmata/kyverno/pkg/engine/response"
|
||||
policyctr "github.com/nirmata/kyverno/pkg/policy"
|
||||
"github.com/nirmata/kyverno/pkg/policyviolation"
|
||||
"github.com/nirmata/kyverno/pkg/utils"
|
||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
)
|
||||
|
@ -99,20 +100,17 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol
|
|||
|
||||
// If Validation fails then reject the request
|
||||
// no violations will be created on "enforce"
|
||||
// event will be reported on "owner"
|
||||
// the event will be reported on owner by k8s
|
||||
blocked := toBlockResource(engineResponses)
|
||||
if blocked {
|
||||
glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName())
|
||||
// ADD EVENTS
|
||||
events := generateEvents(engineResponses, (request.Operation == v1beta1.Update))
|
||||
ws.eventGen.Add(events...)
|
||||
sendStat(true)
|
||||
return false, getErrorMsg(engineResponses)
|
||||
}
|
||||
|
||||
// ADD POLICY VIOLATIONS
|
||||
// violations are created with resource on "audit"
|
||||
|
||||
pvInfos := generatePV(engineResponses, blocked)
|
||||
pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses)
|
||||
ws.pvGenerator.Add(pvInfos...)
|
||||
// ADD EVENTS
|
||||
events := generateEvents(engineResponses, (request.Operation == v1beta1.Update))
|
||||
|
|
Loading…
Add table
Reference in a new issue