mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
Merge branch '504_bug' into v1.1.0
This commit is contained in:
commit
f4d1888184
25 changed files with 285 additions and 334 deletions
|
@ -94,7 +94,7 @@ func removeWebhookIfExists(client *client.Client, kind string, name string) erro
|
|||
return err
|
||||
}
|
||||
// Delete resource
|
||||
err = client.DeleteResouce(kind, "", name, false)
|
||||
err = client.DeleteResource(kind, "", name, false)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to delete resource %s(%s)", name, kind)
|
||||
return err
|
||||
|
|
|
@ -75,14 +75,11 @@ func main() {
|
|||
}
|
||||
|
||||
// WERBHOOK REGISTRATION CLIENT
|
||||
webhookRegistrationClient, err := webhookconfig.NewWebhookRegistrationClient(
|
||||
webhookRegistrationClient := webhookconfig.NewWebhookRegistrationClient(
|
||||
clientConfig,
|
||||
client,
|
||||
serverIP,
|
||||
int32(webhookTimeout))
|
||||
if err != nil {
|
||||
glog.Fatalf("Unable to register admission webhooks on cluster: %v\n", err)
|
||||
}
|
||||
|
||||
// KYVERNO CRD INFORMER
|
||||
// watches CRD resources:
|
||||
|
|
|
@ -261,8 +261,6 @@ spec:
|
|||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
|
@ -283,8 +281,6 @@ spec:
|
|||
properties:
|
||||
kind:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
creationBlocked:
|
||||
type: boolean
|
||||
---
|
||||
|
@ -326,8 +322,6 @@ spec:
|
|||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
|
@ -348,8 +342,6 @@ spec:
|
|||
properties:
|
||||
kind:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
creationBlocked:
|
||||
type: boolean
|
||||
---
|
||||
|
|
|
@ -261,8 +261,6 @@ spec:
|
|||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
|
@ -283,8 +281,6 @@ spec:
|
|||
properties:
|
||||
kind:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
creationBlocked:
|
||||
type: boolean
|
||||
---
|
||||
|
@ -326,8 +322,6 @@ spec:
|
|||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
rules:
|
||||
type: array
|
||||
items:
|
||||
|
@ -348,8 +342,6 @@ spec:
|
|||
properties:
|
||||
kind:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
creationBlocked:
|
||||
type: boolean
|
||||
---
|
||||
|
|
|
@ -189,7 +189,6 @@ type PolicyViolationSpec struct {
|
|||
// ResourceSpec information to identify the resource
|
||||
type ResourceSpec struct {
|
||||
Kind string `json:"kind"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
|
@ -201,9 +200,10 @@ type ViolatedRule struct {
|
|||
ManagedResource ManagedResourceSpec `json:"managedResource,omitempty"`
|
||||
}
|
||||
|
||||
// ManagedResourceSpec is used when the violations is created on resource owner
|
||||
// to determing the kind of child resource that caused the violation
|
||||
type ManagedResourceSpec struct {
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
CreationBlocked bool `json:"creationBlocked,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -212,5 +212,4 @@ type ManagedResourceSpec struct {
|
|||
// LastUpdateTime : the time the polivy violation was updated
|
||||
type PolicyViolationStatus struct {
|
||||
LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
|
||||
//TODO: having user information regarding the owner of resource can be helpful
|
||||
}
|
||||
|
|
|
@ -57,18 +57,5 @@ func (gen *Generation) DeepCopyInto(out *Generation) {
|
|||
|
||||
//ToKey generates the key string used for adding label to polivy violation
|
||||
func (rs ResourceSpec) ToKey() string {
|
||||
if rs.Namespace == "" {
|
||||
return rs.Kind + "." + rs.Name
|
||||
}
|
||||
return rs.Kind + "." + rs.Namespace + "." + rs.Name
|
||||
}
|
||||
|
||||
//BuildKey builds the key
|
||||
func BuildResourceKey(kind, namespace, name string) string {
|
||||
resource := ResourceSpec{
|
||||
Kind: kind,
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
}
|
||||
return resource.ToKey()
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
|
|||
|
||||
for _, csr := range csrList.Items {
|
||||
if csr.GetName() == req.ObjectMeta.Name {
|
||||
err := c.DeleteResouce(CSRs, "", csr.GetName(), false)
|
||||
err := c.DeleteResource(CSRs, "", csr.GetName(), false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to delete existing certificate request: %v", err)
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ func (c *Client) ListResource(kind string, namespace string, lselector *meta.Lab
|
|||
}
|
||||
|
||||
// DeleteResouce deletes the specified resource
|
||||
func (c *Client) DeleteResouce(kind string, namespace string, name string, dryRun bool) error {
|
||||
func (c *Client) DeleteResource(kind string, namespace string, name string, dryRun bool) error {
|
||||
options := meta.DeleteOptions{}
|
||||
if dryRun {
|
||||
options = meta.DeleteOptions{DryRun: []string{meta.DryRunAll}}
|
||||
|
|
|
@ -74,7 +74,7 @@ func TestCRUDResource(t *testing.T) {
|
|||
t.Errorf("ListResource not working: %s", err)
|
||||
}
|
||||
// DeleteResouce
|
||||
err = f.client.DeleteResouce("thekind", "ns-foo", "name-bar", false)
|
||||
err = f.client.DeleteResource("thekind", "ns-foo", "name-bar", false)
|
||||
if err != nil {
|
||||
t.Errorf("DeleteResouce not working: %s", err)
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ func getNamespacedPVs(nspvLister kyvernolister.NamespacedPolicyViolationLister,
|
|||
}
|
||||
|
||||
func getNamespacedPVOnResource(nspvLister kyvernolister.NamespacedPolicyViolationLister, policyName, kind, namespace, name string) (kyverno.NamespacedPolicyViolation, error) {
|
||||
nspvs, err := nspvLister.List(labels.Everything())
|
||||
nspvs, err := nspvLister.NamespacedPolicyViolations(namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.V(2).Infof("failed to list namespaced pv: %v", err)
|
||||
return kyverno.NamespacedPolicyViolation{}, fmt.Errorf("failed to list namespaced pv: %v", err)
|
||||
|
@ -162,7 +162,6 @@ func getNamespacedPVOnResource(nspvLister kyvernolister.NamespacedPolicyViolatio
|
|||
// find a policy on same resource and policy combination
|
||||
if nspv.Spec.Policy == policyName &&
|
||||
nspv.Spec.ResourceSpec.Kind == kind &&
|
||||
nspv.Spec.ResourceSpec.Namespace == namespace &&
|
||||
nspv.Spec.ResourceSpec.Name == name {
|
||||
return *nspv, nil
|
||||
}
|
||||
|
@ -185,7 +184,7 @@ func getNamespacedPVonOwnerRef(nspvLister kyvernolister.NamespacedPolicyViolatio
|
|||
// 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, owner.Namespace, owner.Name)
|
||||
pv, err := getNamespacedPVOnResource(nspvLister, policyName, owner.Kind, namespace, owner.Name)
|
||||
if err != nil {
|
||||
glog.Errorf("error while fetching resource owners: %v", err)
|
||||
continue
|
||||
|
|
|
@ -492,7 +492,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
engineResponses := pc.processExistingResources(*p)
|
||||
// report errors
|
||||
pc.cleanupAndReport(engineResponses)
|
||||
// fetch the policy again via the aggreagator to remain consistent
|
||||
// sync active
|
||||
return pc.syncStatusOnly(p, pvList, nspvList)
|
||||
}
|
||||
|
||||
|
|
152
pkg/policyviolation/clusterpv.go
Normal file
152
pkg/policyviolation/clusterpv.go
Normal file
|
@ -0,0 +1,152 @@
|
|||
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"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func createPVS(dclient *client.Client, pvs []kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
|
||||
for _, pv := range pvs {
|
||||
if err := createPVNew(dclient, pv, pvLister, pvInterface); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gen *Generator) createCusterPV(info Info) error {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
if !info.Blocked {
|
||||
pvs = append(pvs, buildPV(info))
|
||||
} else {
|
||||
// blocked
|
||||
// get owners
|
||||
pvs = buildPVWithOwners(gen.dclient, info)
|
||||
}
|
||||
// create policy violation
|
||||
if err := createPVS(gen.dclient, pvs, gen.pvLister, gen.pvInterface); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Created cluster policy violation policy=%s, resource=%s/%s/%s",
|
||||
info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
|
||||
return nil
|
||||
|
||||
}
|
||||
func createPVNew(dclient *client.Client, pv kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
|
||||
var err error
|
||||
// PV already exists
|
||||
ePV, err := getExistingPVIfAny(pvLister, pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to get existing pv on resource '%s' in namespace : %v", pv.Spec.ResourceSpec.ToKey(), pv.Namespace, err)
|
||||
}
|
||||
if ePV == nil {
|
||||
// Create a New PV
|
||||
glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s", pv.Spec.Policy, pv.Spec.ResourceSpec.Kind, pv.Spec.ResourceSpec.Name)
|
||||
err := retryGetResource(pv.Namespace, dclient, pv.Spec.ResourceSpec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", pv.Name, pv.Spec.Policy, err)
|
||||
}
|
||||
|
||||
_, err = pvInterface.ClusterPolicyViolations().Create(&pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to create cluster policy violation: %v", err)
|
||||
}
|
||||
glog.Infof("policy violation created for resource %v", pv.Spec.ResourceSpec)
|
||||
return nil
|
||||
}
|
||||
// Update existing PV if there any changes
|
||||
if reflect.DeepEqual(pv.Spec, ePV.Spec) {
|
||||
glog.V(4).Infof("policy violation spec %v did not change so not updating it", pv.Spec)
|
||||
return nil
|
||||
}
|
||||
|
||||
pv.SetName(ePV.Name)
|
||||
_, err = pvInterface.ClusterPolicyViolations().Update(&pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to update cluster polciy violation: %v", err)
|
||||
}
|
||||
glog.Infof("policy violation updated for resource %v", pv.Spec.ResourceSpec)
|
||||
return nil
|
||||
}
|
||||
|
||||
// build PV without owners
|
||||
func buildPV(info Info) kyverno.ClusterPolicyViolation {
|
||||
pv := buildPVObj(info.PolicyName, kyverno.ResourceSpec{
|
||||
Kind: info.Resource.GetKind(),
|
||||
Name: info.Resource.GetName(),
|
||||
}, info.Rules,
|
||||
)
|
||||
return pv
|
||||
}
|
||||
|
||||
// build PV object
|
||||
func buildPVObj(policyName string, resourceSpec kyverno.ResourceSpec, rules []kyverno.ViolatedRule) kyverno.ClusterPolicyViolation {
|
||||
pv := kyverno.ClusterPolicyViolation{
|
||||
Spec: kyverno.PolicyViolationSpec{
|
||||
Policy: policyName,
|
||||
ResourceSpec: resourceSpec,
|
||||
ViolatedRules: rules,
|
||||
},
|
||||
}
|
||||
|
||||
labelMap := map[string]string{
|
||||
"policy": policyName,
|
||||
"resource": resourceSpec.ToKey(),
|
||||
}
|
||||
pv.SetLabels(labelMap)
|
||||
pv.SetGenerateName("pv-")
|
||||
return pv
|
||||
}
|
||||
|
||||
// build PV with owners
|
||||
func buildPVWithOwners(dclient *client.Client, info Info) []kyverno.ClusterPolicyViolation {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
// as its blocked resource, the violation is created on owner
|
||||
ownerMap := map[kyverno.ResourceSpec]interface{}{}
|
||||
GetOwner(dclient, ownerMap, info.Resource)
|
||||
|
||||
// standaloneresource, set pvResourceSpec with resource itself
|
||||
if len(ownerMap) == 0 {
|
||||
pvResourceSpec := kyverno.ResourceSpec{
|
||||
Kind: info.Resource.GetKind(),
|
||||
Name: info.Resource.GetName(),
|
||||
}
|
||||
return append(pvs, buildPVObj(info.PolicyName, pvResourceSpec, info.Rules))
|
||||
}
|
||||
|
||||
// Generate owner on all owners
|
||||
for owner := range ownerMap {
|
||||
pv := buildPVObj(info.PolicyName, owner, info.Rules)
|
||||
pvs = append(pvs, pv)
|
||||
}
|
||||
return pvs
|
||||
}
|
||||
|
||||
func getExistingPVIfAny(pvLister kyvernolister.ClusterPolicyViolationLister, currpv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) {
|
||||
pvs, err := pvLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("unable to list policy violations : %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pv := range pvs {
|
||||
// find a policy on same resource and policy combination
|
||||
if pv.Spec.Policy == currpv.Spec.Policy &&
|
||||
pv.Spec.ResourceSpec.Kind == currpv.Spec.ResourceSpec.Kind &&
|
||||
pv.Spec.ResourceSpec.Name == currpv.Spec.ResourceSpec.Name {
|
||||
return pv, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
|
@ -210,13 +210,13 @@ func (pvc *PolicyViolationController) syncPolicyViolation(key string) error {
|
|||
// Deep-copy otherwise we are mutating our cache.
|
||||
// TODO: Deep-copy only when needed.
|
||||
pv := policyViolation.DeepCopy()
|
||||
// TODO: Update Status to update ObserverdGeneration
|
||||
// TODO: check if the policy violation refers to a resource thats active ? // done by policy controller
|
||||
// TODO: remove the PV, if the corresponding policy is not present
|
||||
// TODO: additional check on deleted webhook for a resource, to delete a policy violation it has a policy violation
|
||||
// list the resource with label selectors, but this can be expensive for each delete request of a resource
|
||||
// Check if the policy violation resource is active
|
||||
if err := pvc.syncActiveResource(pv); err != nil {
|
||||
glog.V(4).Infof("not syncing policy violation status")
|
||||
return err
|
||||
}
|
||||
// If policy violations is on resource owner,
|
||||
// check if the resource owner is active
|
||||
if err := pvc.syncBlockedResource(pv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -227,30 +227,19 @@ func (pvc *PolicyViolationController) syncActiveResource(curPv *kyverno.ClusterP
|
|||
// check if the resource is active or not ?
|
||||
rspec := curPv.Spec.ResourceSpec
|
||||
// get resource
|
||||
_, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
_, err := pvc.client.GetResource(rspec.Kind, "", rspec.Name)
|
||||
if errors.IsNotFound(err) {
|
||||
// TODO: does it help to retry?
|
||||
// resource is not found
|
||||
// remove the violation
|
||||
|
||||
if err := pvc.pvControl.RemovePolicyViolation(curPv.Name); err != nil {
|
||||
glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
|
||||
return err
|
||||
}
|
||||
glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Name)
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err)
|
||||
glog.V(4).Infof("error while retrieved resource %s/%s: %v", rspec.Kind, rspec.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// cleanup pv with dependant
|
||||
if err := pvc.syncBlockedResource(curPv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//TODO- if the policy is not present, remove the policy violation
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -264,7 +253,7 @@ func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.Cluster
|
|||
|
||||
// get resource
|
||||
blockedResource := violatedRule.ManagedResource
|
||||
resources, _ := pvc.client.ListResource(blockedResource.Kind, blockedResource.Namespace, nil)
|
||||
resources, _ := pvc.client.ListResource(blockedResource.Kind, "", nil)
|
||||
|
||||
for _, resource := range resources.Items {
|
||||
glog.V(4).Infof("getting owners for %s/%s/%s\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
||||
|
@ -286,8 +275,8 @@ func (pvc *PolicyViolationController) syncBlockedResource(curPv *kyverno.Cluster
|
|||
glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
|
||||
return err
|
||||
}
|
||||
glog.V(4).Infof("removed policy violation %s as the blocked resource %s/%s successfully created, owner: %s",
|
||||
curPv.Name, blockedResource.Kind, blockedResource.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
|
||||
glog.V(4).Infof("removed policy violation %s as the blocked resource %s successfully created, owner: %s",
|
||||
curPv.Name, blockedResource.Kind, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package policyviolation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -18,7 +17,6 @@ import (
|
|||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
dclient "github.com/nirmata/kyverno/pkg/dclient"
|
||||
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
@ -217,195 +215,12 @@ func (gen *Generator) processNextWorkitem() bool {
|
|||
|
||||
func (gen *Generator) syncHandler(info Info) error {
|
||||
glog.V(4).Infof("recieved info:%v", info)
|
||||
// cluster policy violations
|
||||
|
||||
// cluster scope resource generate a clusterpolicy violation
|
||||
// namespaced resources generated a namespaced policy violation in the namespace of the resource
|
||||
if info.Resource.GetNamespace() == "" {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
if !info.Blocked {
|
||||
pvs = append(pvs, buildPV(info))
|
||||
} else {
|
||||
// blocked
|
||||
// get owners
|
||||
pvs = buildPVWithOwners(gen.dclient, info)
|
||||
}
|
||||
// create policy violation
|
||||
if err := createPVS(gen.dclient, pvs, gen.pvLister, gen.pvInterface); err != nil {
|
||||
return err
|
||||
return gen.createCusterPV(info)
|
||||
}
|
||||
return gen.createNamespacedPV(info)
|
||||
|
||||
glog.V(3).Infof("Created cluster policy violation policy=%s, resource=%s/%s/%s",
|
||||
info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
|
||||
return nil
|
||||
}
|
||||
|
||||
// namespaced policy violations
|
||||
var pvs []kyverno.NamespacedPolicyViolation
|
||||
if !info.Blocked {
|
||||
pvs = append(pvs, buildNamespacedPV(info))
|
||||
} else {
|
||||
pvs = buildNamespacedPVWithOwner(gen.dclient, info)
|
||||
}
|
||||
|
||||
if err := createNamespacedPV(gen.dclient, gen.nspvLister, gen.pvInterface, pvs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Created namespaced policy violation policy=%s, resource=%s/%s/%s",
|
||||
info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPVS(dclient *client.Client, pvs []kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
|
||||
for _, pv := range pvs {
|
||||
if err := createPVNew(dclient, pv, pvLister, pvInterface); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPVNew(dclient *client.Client, pv kyverno.ClusterPolicyViolation, pvLister kyvernolister.ClusterPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface) error {
|
||||
var err error
|
||||
// PV already exists
|
||||
ePV, err := getExistingPVIfAny(pvLister, pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to get existing pv on resource '%s': %v", pv.Spec.ResourceSpec.ToKey(), err)
|
||||
}
|
||||
if ePV == nil {
|
||||
// Create a New PV
|
||||
glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s/%s", pv.Spec.Policy, pv.Spec.ResourceSpec.Kind, pv.Spec.ResourceSpec.Namespace, pv.Spec.ResourceSpec.Name)
|
||||
err := retryGetResource(dclient, pv.Spec.ResourceSpec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", pv.Name, pv.Spec.Policy, err)
|
||||
}
|
||||
|
||||
_, err = pvInterface.ClusterPolicyViolations().Create(&pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to create cluster policy violation: %v", err)
|
||||
}
|
||||
glog.Infof("policy violation created for resource %v", pv.Spec.ResourceSpec)
|
||||
return nil
|
||||
}
|
||||
// Update existing PV if there any changes
|
||||
if reflect.DeepEqual(pv.Spec, ePV.Spec) {
|
||||
glog.V(4).Infof("policy violation spec %v did not change so not updating it", pv.Spec)
|
||||
return nil
|
||||
}
|
||||
|
||||
pv.SetName(ePV.Name)
|
||||
_, err = pvInterface.ClusterPolicyViolations().Update(&pv)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return fmt.Errorf("failed to update cluster polciy violation: %v", err)
|
||||
}
|
||||
glog.Infof("policy violation updated for resource %v", pv.Spec.ResourceSpec)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getExistingPVIfAny(pvLister kyvernolister.ClusterPolicyViolationLister, currpv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) {
|
||||
pvs, err := pvLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorf("unable to list policy violations : %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pv := range pvs {
|
||||
// find a policy on same resource and policy combination
|
||||
if pv.Spec.Policy == currpv.Spec.Policy &&
|
||||
pv.Spec.ResourceSpec.Kind == currpv.Spec.ResourceSpec.Kind &&
|
||||
pv.Spec.ResourceSpec.Namespace == currpv.Spec.ResourceSpec.Namespace &&
|
||||
pv.Spec.ResourceSpec.Name == currpv.Spec.ResourceSpec.Name {
|
||||
return pv, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// build PV without owners
|
||||
func buildPV(info Info) kyverno.ClusterPolicyViolation {
|
||||
pv := buildPVObj(info.PolicyName, kyverno.ResourceSpec{
|
||||
Kind: info.Resource.GetKind(),
|
||||
Namespace: info.Resource.GetNamespace(),
|
||||
Name: info.Resource.GetName(),
|
||||
}, info.Rules,
|
||||
)
|
||||
return pv
|
||||
}
|
||||
|
||||
// build PV object
|
||||
func buildPVObj(policyName string, resourceSpec kyverno.ResourceSpec, rules []kyverno.ViolatedRule) kyverno.ClusterPolicyViolation {
|
||||
pv := kyverno.ClusterPolicyViolation{
|
||||
Spec: kyverno.PolicyViolationSpec{
|
||||
Policy: policyName,
|
||||
ResourceSpec: resourceSpec,
|
||||
ViolatedRules: rules,
|
||||
},
|
||||
}
|
||||
|
||||
labelMap := map[string]string{
|
||||
"policy": policyName,
|
||||
"resource": resourceSpec.ToKey(),
|
||||
}
|
||||
pv.SetGenerateName(fmt.Sprintf("%s-", policyName))
|
||||
pv.SetLabels(labelMap)
|
||||
return pv
|
||||
}
|
||||
|
||||
// build PV with owners
|
||||
func buildPVWithOwners(dclient *client.Client, info Info) []kyverno.ClusterPolicyViolation {
|
||||
var pvs []kyverno.ClusterPolicyViolation
|
||||
// as its blocked resource, the violation is created on owner
|
||||
ownerMap := map[kyverno.ResourceSpec]interface{}{}
|
||||
GetOwner(dclient, ownerMap, info.Resource)
|
||||
|
||||
// standaloneresource, set pvResourceSpec with resource itself
|
||||
if len(ownerMap) == 0 {
|
||||
pvResourceSpec := kyverno.ResourceSpec{
|
||||
Namespace: info.Resource.GetNamespace(),
|
||||
Kind: info.Resource.GetKind(),
|
||||
Name: info.Resource.GetName(),
|
||||
}
|
||||
return append(pvs, buildPVObj(info.PolicyName, pvResourceSpec, info.Rules))
|
||||
}
|
||||
|
||||
// Generate owner on all owners
|
||||
for owner := range ownerMap {
|
||||
pv := buildPVObj(info.PolicyName, owner, info.Rules)
|
||||
pvs = append(pvs, pv)
|
||||
}
|
||||
return pvs
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -30,21 +31,6 @@ func converLabelToSelector(labelMap map[string]string) (labels.Selector, error)
|
|||
return policyViolationSelector, nil
|
||||
}
|
||||
|
||||
func containsOwner(owners []kyverno.ResourceSpec, pvResourceSpec kyverno.ResourceSpec) bool {
|
||||
curOwner := kyverno.ResourceSpec{
|
||||
Kind: pvResourceSpec.Kind,
|
||||
Namespace: pvResourceSpec.Namespace,
|
||||
Name: pvResourceSpec.Name,
|
||||
}
|
||||
|
||||
for _, targetOwner := range owners {
|
||||
if reflect.DeepEqual(curOwner, targetOwner) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// validDependantForDeployment checks if resource (pod) matches the intent of the given deployment
|
||||
// explicitly handles deployment-replicaset-pod relationship
|
||||
func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec kyverno.ResourceSpec, resource unstructured.Unstructured) bool {
|
||||
|
@ -59,14 +45,13 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
|
|||
|
||||
owner := kyverno.ResourceSpec{
|
||||
Kind: pvResourceSpec.Kind,
|
||||
Namespace: pvResourceSpec.Namespace,
|
||||
Name: pvResourceSpec.Name,
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
deploy, err := client.Deployments(owner.Namespace).Get(owner.Name, metav1.GetOptions{})
|
||||
deploy, err := client.Deployments(resource.GetNamespace()).Get(owner.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Errorf("failed to get resourceOwner deployment %s/%s/%s: %v", owner.Kind, owner.Namespace, owner.Name, err)
|
||||
glog.Errorf("failed to get resourceOwner deployment %s/%s/%s: %v", owner.Kind, resource.GetNamespace(), owner.Name, err)
|
||||
return false
|
||||
}
|
||||
glog.V(4).Infof("Time getting deployment %v", time.Since(start))
|
||||
|
@ -74,12 +59,12 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
|
|||
// TODO(shuting): replace typed client AppsV1Interface
|
||||
expectReplicaset, err := deployutil.GetNewReplicaSet(deploy, client)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to get replicaset owned by %s/%s/%s: %v", owner.Kind, owner.Namespace, owner.Name, err)
|
||||
glog.Errorf("failed to get replicaset owned by %s/%s/%s: %v", owner.Kind, resource.GetNamespace(), owner.Name, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(expectReplicaset, v1.ReplicaSet{}) {
|
||||
glog.V(2).Infof("no replicaset found for deploy %s/%s/%s", owner.Namespace, owner.Kind, owner.Name)
|
||||
glog.V(2).Infof("no replicaset found for deploy %s/%s/%s", resource.GetNamespace(), owner.Kind, owner.Name)
|
||||
return false
|
||||
}
|
||||
var actualReplicaset *v1.ReplicaSet
|
||||
|
@ -105,3 +90,35 @@ func validDependantForDeployment(client appsv1.AppsV1Interface, pvResourceSpec k
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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(),
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,28 @@ import (
|
|||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func (gen *Generator) createNamespacedPV(info Info) error {
|
||||
// namespaced policy violations
|
||||
var pvs []kyverno.NamespacedPolicyViolation
|
||||
if !info.Blocked {
|
||||
pvs = append(pvs, buildNamespacedPV(info))
|
||||
} else {
|
||||
pvs = buildNamespacedPVWithOwner(gen.dclient, info)
|
||||
}
|
||||
|
||||
if err := createNamespacedPV(info.Resource.GetNamespace(), gen.dclient, gen.nspvLister, gen.pvInterface, pvs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(3).Infof("Created namespaced policy violation policy=%s, resource=%s/%s/%s",
|
||||
info.PolicyName, info.Resource.GetKind(), info.Resource.GetNamespace(), info.Resource.GetName())
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildNamespacedPV(info Info) kyverno.NamespacedPolicyViolation {
|
||||
return buildNamespacedPVObj(info.PolicyName,
|
||||
kyverno.ResourceSpec{
|
||||
Kind: info.Resource.GetKind(),
|
||||
Namespace: info.Resource.GetNamespace(),
|
||||
Name: info.Resource.GetName(),
|
||||
},
|
||||
info.Rules)
|
||||
|
@ -49,7 +66,6 @@ func buildNamespacedPVWithOwner(dclient *dclient.Client, info Info) (pvs []kyver
|
|||
// standaloneresource, set pvResourceSpec with resource itself
|
||||
if len(ownerMap) == 0 {
|
||||
pvResourceSpec := kyverno.ResourceSpec{
|
||||
Namespace: info.Resource.GetNamespace(),
|
||||
Kind: info.Resource.GetKind(),
|
||||
Name: info.Resource.GetName(),
|
||||
}
|
||||
|
@ -62,7 +78,7 @@ func buildNamespacedPVWithOwner(dclient *dclient.Client, info Info) (pvs []kyver
|
|||
return
|
||||
}
|
||||
|
||||
func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.NamespacedPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface, pvs []kyverno.NamespacedPolicyViolation) error {
|
||||
func createNamespacedPV(namespace string, dclient *dclient.Client, pvLister kyvernolister.NamespacedPolicyViolationLister, pvInterface kyvernov1.KyvernoV1Interface, pvs []kyverno.NamespacedPolicyViolation) error {
|
||||
for _, newPv := range pvs {
|
||||
glog.V(4).Infof("creating namespaced policyViolation resource for policy %s and resource %s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.ToKey())
|
||||
// check if there was a previous policy voilation for policy & resource combination
|
||||
|
@ -76,11 +92,11 @@ func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.Namespac
|
|||
if reflect.DeepEqual(curPv, kyverno.NamespacedPolicyViolation{}) {
|
||||
glog.V(4).Infof("creating new namespaced policy violation for policy %s & resource %s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.ToKey())
|
||||
|
||||
if err := retryGetResource(dclient, newPv.Spec.ResourceSpec); err != nil {
|
||||
if err := retryGetResource(newPv.Namespace, dclient, newPv.Spec.ResourceSpec); err != nil {
|
||||
return fmt.Errorf("failed to get resource for policy violation on resource '%s': %v", newPv.Spec.ResourceSpec.ToKey(), err)
|
||||
}
|
||||
|
||||
if _, err := pvInterface.NamespacedPolicyViolations(newPv.Spec.ResourceSpec.Namespace).Create(&newPv); err != nil {
|
||||
if _, err := pvInterface.NamespacedPolicyViolations(namespace).Create(&newPv); err != nil {
|
||||
return fmt.Errorf("failed to create namespaced policy violation: %v", err)
|
||||
}
|
||||
|
||||
|
@ -104,7 +120,7 @@ func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.Namespac
|
|||
glog.V(4).Infof("creating new policy violation for policy %s & resource %s", curPv.Spec.Policy, curPv.Spec.ResourceSpec.ToKey())
|
||||
//TODO: using a generic name, but would it be helpful to have naming convention for policy violations
|
||||
// as we can only have one policy violation for each (policy + resource) combination
|
||||
if _, err = pvInterface.NamespacedPolicyViolations(newPv.Spec.ResourceSpec.Namespace).Update(&newPv); err != nil {
|
||||
if _, err = pvInterface.NamespacedPolicyViolations(namespace).Update(&newPv); err != nil {
|
||||
return fmt.Errorf("failed to update namespaced policy violation: %v", err)
|
||||
}
|
||||
glog.Infof("namespaced policy violation updated for resource %s", newPv.Spec.ResourceSpec.ToKey())
|
||||
|
@ -114,7 +130,7 @@ func createNamespacedPV(dclient *dclient.Client, pvLister kyvernolister.Namespac
|
|||
|
||||
func getExistingNamespacedPVIfAny(nspvLister kyvernolister.NamespacedPolicyViolationLister, newPv kyverno.NamespacedPolicyViolation) (kyverno.NamespacedPolicyViolation, error) {
|
||||
// TODO(shuting): list pvs by labels
|
||||
pvs, err := nspvLister.List(labels.NewSelector())
|
||||
pvs, err := nspvLister.NamespacedPolicyViolations(newPv.GetNamespace()).List(labels.NewSelector())
|
||||
if err != nil {
|
||||
return kyverno.NamespacedPolicyViolation{}, fmt.Errorf("failed to list namespaced policy violations err: %v", err)
|
||||
}
|
||||
|
|
|
@ -209,15 +209,14 @@ func (pvc *NamespacedPolicyViolationController) syncPolicyViolation(key string)
|
|||
// Deep-copy otherwise we are mutating our cache.
|
||||
// TODO: Deep-copy only when needed.
|
||||
pv := policyViolation.DeepCopy()
|
||||
// TODO: Update Status to update ObserverdGeneration
|
||||
// TODO: check if the policy violation refers to a resource thats active ? // done by policy controller
|
||||
// TODO: remove the PV, if the corresponding policy is not present
|
||||
// TODO: additional check on deleted webhook for a resource, to delete a policy violation it has a policy violation
|
||||
// list the resource with label selectors, but this can be expensive for each delete request of a resource
|
||||
if err := pvc.syncActiveResource(pv); err != nil {
|
||||
glog.V(4).Infof("not syncing policy violation status")
|
||||
return err
|
||||
}
|
||||
// cleanup pv with dependant
|
||||
if err := pvc.syncBlockedResource(pv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return pvc.syncStatusOnly(pv)
|
||||
}
|
||||
|
@ -226,7 +225,7 @@ func (pvc *NamespacedPolicyViolationController) syncActiveResource(curPv *kyvern
|
|||
// check if the resource is active or not ?
|
||||
rspec := curPv.Spec.ResourceSpec
|
||||
// get resource
|
||||
_, err := pvc.client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
_, err := pvc.client.GetResource(rspec.Kind, curPv.Namespace, rspec.Name)
|
||||
if errors.IsNotFound(err) {
|
||||
// TODO: does it help to retry?
|
||||
// resource is not found
|
||||
|
@ -236,20 +235,13 @@ func (pvc *NamespacedPolicyViolationController) syncActiveResource(curPv *kyvern
|
|||
glog.Infof("unable to delete the policy violation %s: %v", curPv.Name, err)
|
||||
return err
|
||||
}
|
||||
glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
glog.V(4).Infof("removing policy violation %s as the corresponding resource %s/%s/%s does not exist anymore", curPv.Name, rspec.Kind, curPv.Namespace, rspec.Name)
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, rspec.Namespace, rspec.Name, err)
|
||||
glog.V(4).Infof("error while retrieved resource %s/%s/%s: %v", rspec.Kind, curPv.Namespace, rspec.Name, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// cleanup pv with dependant
|
||||
if err := pvc.syncBlockedResource(curPv); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//TODO- if the policy is not present, remove the policy violation
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -263,7 +255,7 @@ func (pvc *NamespacedPolicyViolationController) syncBlockedResource(curPv *kyver
|
|||
|
||||
// get resource
|
||||
blockedResource := violatedRule.ManagedResource
|
||||
resources, _ := pvc.client.ListResource(blockedResource.Kind, blockedResource.Namespace, nil)
|
||||
resources, _ := pvc.client.ListResource(blockedResource.Kind, curPv.Namespace, nil)
|
||||
|
||||
for _, resource := range resources.Items {
|
||||
glog.V(4).Infof("getting owners for %s/%s/%s\n", resource.GetKind(), resource.GetNamespace(), resource.GetName())
|
||||
|
@ -285,7 +277,7 @@ func (pvc *NamespacedPolicyViolationController) syncBlockedResource(curPv *kyver
|
|||
return err
|
||||
}
|
||||
glog.V(4).Infof("removed policy violation %s as the blocked resource %s/%s successfully created, owner: %s",
|
||||
curPv.Name, blockedResource.Kind, blockedResource.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
|
||||
curPv.Name, blockedResource.Kind, curPv.Namespace, strings.ReplaceAll(curPv.Spec.ResourceSpec.ToKey(), ".", "/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,11 +333,11 @@ func (r RealNamespacedPVControl) RemovePolicyViolation(ns, name string) error {
|
|||
return r.Client.KyvernoV1().NamespacedPolicyViolations(ns).Delete(name, &metav1.DeleteOptions{})
|
||||
}
|
||||
|
||||
func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) error {
|
||||
func retryGetResource(namespace string, client *client.Client, rspec kyverno.ResourceSpec) error {
|
||||
var i int
|
||||
getResource := func() error {
|
||||
_, err := client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
glog.V(5).Infof("retry %v getting %s/%s/%s", i, rspec.Kind, rspec.Namespace, rspec.Name)
|
||||
_, err := client.GetResource(rspec.Kind, namespace, rspec.Name)
|
||||
glog.V(5).Infof("retry %v getting %s/%s/%s", i, rspec.Kind, namespace, rspec.Name)
|
||||
i++
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -181,7 +181,8 @@ func runTestCase(t *testing.T, tc scaseT) bool {
|
|||
er = engine.Generate(policyContext)
|
||||
t.Log(("---Generation---"))
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse)
|
||||
validateGeneratedResources(t, client, *policy, tc.Expected.Generation.GeneratedResources)
|
||||
// Expected generate resource will be in same namesapces as resource
|
||||
validateGeneratedResources(t, client, *policy, resource.GetName(), tc.Expected.Generation.GeneratedResources)
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
@ -191,12 +192,12 @@ func createNamespace(client *client.Client, ns *unstructured.Unstructured) error
|
|||
_, err := client.CreateResource("Namespace", "", ns, false)
|
||||
return err
|
||||
}
|
||||
func validateGeneratedResources(t *testing.T, client *client.Client, policy kyverno.ClusterPolicy, expected []kyverno.ResourceSpec) {
|
||||
func validateGeneratedResources(t *testing.T, client *client.Client, policy kyverno.ClusterPolicy, namespace string, expected []kyverno.ResourceSpec) {
|
||||
t.Log("--validate if resources are generated---")
|
||||
// list of expected generated resources
|
||||
for _, resource := range expected {
|
||||
if _, err := client.GetResource(resource.Kind, resource.Namespace, resource.Name); err != nil {
|
||||
t.Errorf("generated resource %s/%s/%s not found. %v", resource.Kind, resource.Namespace, resource.Name, err)
|
||||
if _, err := client.GetResource(resource.Kind, namespace, resource.Name); err != nil {
|
||||
t.Errorf("generated resource %s/%s/%s not found. %v", resource.Kind, namespace, resource.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@ import (
|
|||
rbaclister "k8s.io/client-go/listers/rbac/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
clusterrolekind = "ClusterRole"
|
||||
rolekind = "Role"
|
||||
)
|
||||
|
||||
func GetRoleRef(rbLister rbaclister.RoleBindingLister, crbLister rbaclister.ClusterRoleBindingLister, request *v1beta1.AdmissionRequest) (roles []string, clusterRoles []string, err error) {
|
||||
// rolebindings
|
||||
roleBindings, err := rbLister.List(labels.NewSelector())
|
||||
|
@ -49,11 +54,10 @@ func getRoleRefByRoleBindings(roleBindings []*rbacv1.RoleBinding, userInfo authe
|
|||
continue
|
||||
}
|
||||
|
||||
// roleRefMap := roleRef.(map[string]interface{})
|
||||
switch rolebinding.RoleRef.Kind {
|
||||
case "role":
|
||||
case rolekind:
|
||||
roles = append(roles, rolebinding.Namespace+":"+rolebinding.RoleRef.Name)
|
||||
case "clusterRole":
|
||||
case clusterrolekind:
|
||||
clusterRoles = append(clusterRoles, rolebinding.RoleRef.Name)
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +74,7 @@ func getRoleRefByClusterRoleBindings(clusterroleBindings []*rbacv1.ClusterRoleBi
|
|||
continue
|
||||
}
|
||||
|
||||
if clusterRoleBinding.RoleRef.Kind == "clusterRole" {
|
||||
if clusterRoleBinding.RoleRef.Kind == clusterrolekind {
|
||||
clusterRoles = append(clusterRoles, clusterRoleBinding.RoleRef.Name)
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +84,7 @@ func getRoleRefByClusterRoleBindings(clusterroleBindings []*rbacv1.ClusterRoleBi
|
|||
|
||||
// matchSubjectsMap checks if userInfo found in subject
|
||||
// return true directly if found a match
|
||||
// subject["kind"] can only be ServiceAccount, User and Group
|
||||
// subject.kind can only be ServiceAccount, User and Group
|
||||
func matchSubjectsMap(subject rbacv1.Subject, userInfo authenticationv1.UserInfo) bool {
|
||||
// ServiceAccount
|
||||
if isServiceaccountUserInfo(userInfo.Username) {
|
||||
|
|
|
@ -181,7 +181,7 @@ func Test_getRoleRefByRoleBindings(t *testing.T) {
|
|||
},
|
||||
},
|
||||
rbacv1.RoleRef{
|
||||
Kind: "role",
|
||||
Kind: rolekind,
|
||||
Name: "myrole",
|
||||
},
|
||||
},
|
||||
|
@ -199,7 +199,7 @@ func Test_getRoleRefByRoleBindings(t *testing.T) {
|
|||
},
|
||||
},
|
||||
rbacv1.RoleRef{
|
||||
Kind: "clusterRole",
|
||||
Kind: clusterrolekind,
|
||||
Name: "myclusterrole",
|
||||
},
|
||||
},
|
||||
|
@ -232,7 +232,7 @@ func Test_getRoleRefByClusterRoleBindings(t *testing.T) {
|
|||
},
|
||||
},
|
||||
rbacv1.RoleRef{
|
||||
Kind: "clusterRole",
|
||||
Kind: clusterrolekind,
|
||||
Name: "fakeclusterrole",
|
||||
},
|
||||
},
|
||||
|
@ -249,7 +249,7 @@ func Test_getRoleRefByClusterRoleBindings(t *testing.T) {
|
|||
},
|
||||
},
|
||||
rbacv1.RoleRef{
|
||||
Kind: "clusterRole",
|
||||
Kind: clusterrolekind,
|
||||
Name: "myclusterrole",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -67,7 +67,7 @@ func (wrc *WebhookRegistrationClient) removeVerifyWebhookMutatingWebhookConfig()
|
|||
mutatingConfig = config.VerifyMutatingWebhookConfigurationName
|
||||
}
|
||||
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
|
||||
err = wrc.client.DeleteResouce(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
|
||||
err = wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
|
||||
if errorsapi.IsNotFound(err) {
|
||||
glog.V(4).Infof("verify webhook configuration %s, does not exits. not deleting", mutatingConfig)
|
||||
} else if err != nil {
|
||||
|
|
|
@ -118,7 +118,7 @@ func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() {
|
|||
validatingConfig = config.PolicyValidatingWebhookConfigurationName
|
||||
}
|
||||
glog.V(4).Infof("removing webhook configuration %s", validatingConfig)
|
||||
err = wrc.client.DeleteResouce(ValidatingWebhookConfigurationKind, "", validatingConfig, false)
|
||||
err = wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", validatingConfig, false)
|
||||
if errorsapi.IsNotFound(err) {
|
||||
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig)
|
||||
} else if err != nil {
|
||||
|
@ -136,7 +136,7 @@ func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() {
|
|||
}
|
||||
|
||||
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
|
||||
err = wrc.client.DeleteResouce(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
|
||||
err = wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
|
||||
if errorsapi.IsNotFound(err) {
|
||||
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig)
|
||||
} else if err != nil {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/nirmata/kyverno/pkg/config"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
admregapi "k8s.io/api/admissionregistration/v1beta1"
|
||||
errorsapi "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
@ -249,7 +250,7 @@ func (wrc *WebhookRegistrationClient) removePolicyMutatingWebhookConfiguration(w
|
|||
}
|
||||
|
||||
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
|
||||
err := wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{})
|
||||
err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
|
||||
if errorsapi.IsNotFound(err) {
|
||||
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig)
|
||||
} else if err != nil {
|
||||
|
@ -264,7 +265,6 @@ func (wrc *WebhookRegistrationClient) removePolicyMutatingWebhookConfiguration(w
|
|||
func (wrc *WebhookRegistrationClient) removePolicyValidatingWebhookConfiguration(wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
// Validating webhook configuration
|
||||
var err error
|
||||
var validatingConfig string
|
||||
if wrc.serverIP != "" {
|
||||
validatingConfig = config.PolicyValidatingWebhookConfigurationDebugName
|
||||
|
@ -272,7 +272,7 @@ func (wrc *WebhookRegistrationClient) removePolicyValidatingWebhookConfiguration
|
|||
validatingConfig = config.PolicyValidatingWebhookConfigurationName
|
||||
}
|
||||
glog.V(4).Infof("removing webhook configuration %s", validatingConfig)
|
||||
err = wrc.registrationClient.ValidatingWebhookConfigurations().Delete(validatingConfig, &v1.DeleteOptions{})
|
||||
err := wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", validatingConfig, false)
|
||||
if errorsapi.IsNotFound(err) {
|
||||
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig)
|
||||
} else if err != nil {
|
||||
|
|
|
@ -71,7 +71,7 @@ func (wrc *WebhookRegistrationClient) RemoveResourceMutatingWebhookConfiguration
|
|||
|
||||
configName := wrc.GetResourceMutatingWebhookConfigName()
|
||||
// delete webhook configuration
|
||||
err := wrc.client.DeleteResouce(MutatingWebhookConfigurationKind, "", configName, false)
|
||||
err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", configName, false)
|
||||
if errors.IsNotFound(err) {
|
||||
glog.V(4).Infof("resource webhook configuration %s does not exits, so not deleting", configName)
|
||||
return nil
|
||||
|
|
|
@ -128,7 +128,6 @@ func buildViolatedRules(er engine.EngineResponse, blocked bool) []kyverno.Violat
|
|||
// if resource was blocked we create dependent
|
||||
dependant := kyverno.ManagedResourceSpec{
|
||||
Kind: er.PolicyResponse.Resource.Kind,
|
||||
Namespace: er.PolicyResponse.Resource.Namespace,
|
||||
CreationBlocked: true,
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue