mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
resolve conflict
This commit is contained in:
commit
6a0a5132b5
20 changed files with 368 additions and 244 deletions
|
@ -1,7 +1,7 @@
|
|||
apiVersion: v1
|
||||
name: kyverno
|
||||
version: 1.1.10
|
||||
appVersion: v1.1.10
|
||||
version: 1.1.11
|
||||
appVersion: v1.1.11
|
||||
icon: https://github.com/nirmata/kyverno/blob/master/documentation/images/Kyverno_Horizontal.png
|
||||
description: Kubernetes Native Policy Management
|
||||
keywords:
|
||||
|
|
|
@ -131,6 +131,7 @@ rules:
|
|||
- limitranges
|
||||
- clusterroles
|
||||
- rolebindings
|
||||
- namespaces
|
||||
- clusterrolebindings
|
||||
{{- range .Values.generatecontrollerExtraResources }}
|
||||
- {{ . }}
|
||||
|
@ -139,6 +140,7 @@ rules:
|
|||
- create
|
||||
- update
|
||||
- delete
|
||||
- list
|
||||
- get
|
||||
# dynamic watches on trigger resources for generate rules
|
||||
# re-evaluate the policy if the resource is updated
|
||||
|
|
|
@ -211,6 +211,7 @@ func main() {
|
|||
pInformer.Kyverno().V1().Policies(),
|
||||
pInformer.Kyverno().V1().ClusterPolicyViolations(),
|
||||
pInformer.Kyverno().V1().PolicyViolations(),
|
||||
pInformer.Kyverno().V1().GenerateRequests(),
|
||||
configData,
|
||||
eventGenerator,
|
||||
pvgen,
|
||||
|
|
|
@ -1375,8 +1375,10 @@ rules:
|
|||
- rolebindings
|
||||
- clusterrolebindings
|
||||
- configmaps
|
||||
- namespaces
|
||||
verbs:
|
||||
- watch
|
||||
- list
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
|
@ -1706,7 +1708,7 @@ spec:
|
|||
fieldPath: metadata.namespace
|
||||
- name: KYVERNO_SVC
|
||||
value: kyverno-svc
|
||||
image: nirmata/kyverno:v1.1.10
|
||||
image: nirmata/kyverno:v1.1.11
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 4
|
||||
|
@ -1738,7 +1740,7 @@ spec:
|
|||
cpu: 100m
|
||||
memory: 50Mi
|
||||
initContainers:
|
||||
- image: nirmata/kyvernopre:v1.1.10
|
||||
- image: nirmata/kyvernopre:v1.1.11
|
||||
imagePullPolicy: Always
|
||||
name: kyverno-pre
|
||||
serviceAccountName: kyverno-service-account
|
||||
|
|
|
@ -1375,8 +1375,10 @@ rules:
|
|||
- rolebindings
|
||||
- clusterrolebindings
|
||||
- configmaps
|
||||
- namespaces
|
||||
verbs:
|
||||
- watch
|
||||
- list
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
|
|
|
@ -158,8 +158,10 @@ rules:
|
|||
- rolebindings
|
||||
- clusterrolebindings
|
||||
- configmaps
|
||||
- namespaces
|
||||
verbs:
|
||||
- watch
|
||||
- list
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
|
|
|
@ -8,7 +8,7 @@ resources:
|
|||
images:
|
||||
- name: nirmata/kyverno
|
||||
newName: nirmata/kyverno
|
||||
newTag: v1.1.10
|
||||
newTag: v1.1.11
|
||||
- name: nirmata/kyvernopre
|
||||
newName: nirmata/kyvernopre
|
||||
newTag: v1.1.10
|
||||
newTag: v1.1.11
|
||||
|
|
|
@ -832,8 +832,10 @@ rules:
|
|||
- rolebindings
|
||||
- clusterrolebindings
|
||||
- configmaps
|
||||
- namespaces
|
||||
verbs:
|
||||
- watch
|
||||
- list
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
|
@ -1075,7 +1077,7 @@ spec:
|
|||
fieldPath: metadata.namespace
|
||||
- name: KYVERNO_SVC
|
||||
value: kyverno-svc
|
||||
image: nirmata/kyverno:v1.1.10
|
||||
image: nirmata/kyverno:v1.1.11
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 4
|
||||
|
@ -1107,7 +1109,7 @@ spec:
|
|||
cpu: 100m
|
||||
memory: 50Mi
|
||||
initContainers:
|
||||
- image: nirmata/kyvernopre:v1.1.10
|
||||
- image: nirmata/kyvernopre:v1.1.11
|
||||
imagePullPolicy: Always
|
||||
name: kyverno-pre
|
||||
serviceAccountName: kyverno-service-account
|
||||
|
|
|
@ -243,7 +243,7 @@ type ResourceDescription struct {
|
|||
// Specifies list of namespaces
|
||||
Namespaces []string `json:"namespaces,omitempty" yaml:"namespaces,omitempty"`
|
||||
// Specifies map of annotations
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"namespaces,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||
// Specifies the set of selectors
|
||||
Selector *metav1.LabelSelector `json:"selector,omitempty" yaml:"selector,omitempty"`
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ type PolicyResponse struct {
|
|||
Rules []RuleResponse `json:"rules"`
|
||||
// ValidationFailureAction: audit(default if not set),enforce
|
||||
ValidationFailureAction string
|
||||
|
||||
}
|
||||
|
||||
//ResourceSpec resource action applied on
|
||||
|
|
|
@ -175,12 +175,14 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
for _, resource := range gr.Status.GeneratedResources {
|
||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||
return
|
||||
}
|
||||
labels := r.GetLabels()
|
||||
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
||||
if err := c.client.DeleteResource(r.GetAPIVersion(), r.GetKind(), r.GetNamespace(), r.GetName(), false); err != nil {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
|
||||
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
|
@ -20,6 +18,7 @@ import (
|
|||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -204,7 +203,8 @@ func (c *Controller) deleteGR(obj interface{}) {
|
|||
for _, resource := range gr.Status.GeneratedResources {
|
||||
r, err := c.client.GetResource(resource.APIVersion, resource.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil {
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", r.GetName())
|
||||
logger.Error(err, "Generated resource is not deleted", "Resource", resource.Name)
|
||||
continue
|
||||
}
|
||||
labels := r.GetLabels()
|
||||
if labels["policy.kyverno.io/synchronize"] == "enable" {
|
||||
|
|
|
@ -108,8 +108,8 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
|||
logger.V(4).Info("policy does not apply to resource")
|
||||
return nil, fmt.Errorf("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource)
|
||||
}
|
||||
|
||||
for i, r := range engineResponse.PolicyResponse.Rules {
|
||||
var rules []response.RuleResponse
|
||||
for _, r := range engineResponse.PolicyResponse.Rules {
|
||||
if !r.Success {
|
||||
grList, err := c.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
|
@ -123,14 +123,24 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
|||
}
|
||||
}
|
||||
}
|
||||
if len(engineResponse.PolicyResponse.Rules) > 1 {
|
||||
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
|
||||
continue
|
||||
} else if len(engineResponse.PolicyResponse.Rules) == 1 {
|
||||
} else {
|
||||
rules = append(rules, r)
|
||||
}
|
||||
}
|
||||
engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
|
||||
|
||||
for _, v := range policy.Spec.Rules {
|
||||
for _, r := range rules {
|
||||
if policy.Name == engineResponse.PolicyResponse.Policy && r.Name == v.Name {
|
||||
if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
|
||||
continue
|
||||
} else {
|
||||
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the generate rule on resource
|
||||
return c.applyGeneratePolicy(logger, policyContext, gr)
|
||||
}
|
||||
|
@ -160,7 +170,23 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
|||
continue
|
||||
}
|
||||
startTime := time.Now()
|
||||
genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr)
|
||||
|
||||
processExisting := false
|
||||
|
||||
for _, v := range policy.Spec.Rules {
|
||||
if policy.Name == gr.Spec.Policy {
|
||||
if len(v.MatchResources.ResourceDescription.Kinds) > 0 && (len(v.MatchResources.ResourceDescription.Annotations) == 0 || len(v.MatchResources.ResourceDescription.Selector.MatchLabels) == 0) {
|
||||
processExisting = func() bool {
|
||||
rcreationTime := resource.GetCreationTimestamp()
|
||||
pcreationTime := policy.GetCreationTimestamp()
|
||||
return rcreationTime.Before(&pcreationTime)
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr, processExisting)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -217,7 +243,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str
|
|||
return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond
|
||||
}
|
||||
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest) (kyverno.ResourceSpec, error) {
|
||||
func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, policy string, gr kyverno.GenerateRequest, processExisting bool) (kyverno.ResourceSpec, error) {
|
||||
var rdata map[string]interface{}
|
||||
var err error
|
||||
var mode ResourceMode
|
||||
|
@ -227,7 +253,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
if err != nil {
|
||||
return noGenResource, err
|
||||
}
|
||||
|
||||
// Variable substitutions
|
||||
// format : {{<variable_name}}
|
||||
// - if there is variables that are not defined the context -> results in error and rule is not applied
|
||||
|
@ -255,7 +280,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
if err != nil {
|
||||
return noGenResource, err
|
||||
}
|
||||
|
||||
// Resource to be generated
|
||||
newGenResource := kyverno.ResourceSpec{
|
||||
APIVersion: genAPIVersion,
|
||||
|
@ -271,7 +295,6 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
if err != nil {
|
||||
return noGenResource, err
|
||||
}
|
||||
|
||||
if genData != nil {
|
||||
rdata, mode, err = manageData(log, genAPIVersion, genKind, genNamespace, genName, genData, client, resource)
|
||||
} else {
|
||||
|
@ -286,7 +309,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
// existing resource contains the configuration
|
||||
return newGenResource, nil
|
||||
}
|
||||
|
||||
if processExisting {
|
||||
return noGenResource, nil
|
||||
}
|
||||
logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName)
|
||||
|
||||
// build the resource template
|
||||
|
@ -297,24 +322,23 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
if newResource.GetKind() == "" {
|
||||
newResource.SetKind(genKind)
|
||||
}
|
||||
|
||||
newResource.SetAPIVersion(genAPIVersion)
|
||||
// manage labels
|
||||
// - app.kubernetes.io/managed-by: kyverno
|
||||
// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
|
||||
manageLabels(newResource, resource)
|
||||
|
||||
// Add Synchronize label
|
||||
label := newResource.GetLabels()
|
||||
label["policy.kyverno.io/policy-name"] = policy
|
||||
label["policy.kyverno.io/gr-name"] = gr.Name
|
||||
newResource.SetLabels(label)
|
||||
if mode == Create {
|
||||
if rule.Generation.Synchronize {
|
||||
label["policy.kyverno.io/synchronize"] = "enable"
|
||||
} else {
|
||||
label["policy.kyverno.io/synchronize"] = "disable"
|
||||
}
|
||||
label["policy.kyverno.io/policy-name"] = policy
|
||||
label["policy.kyverno.io/gr-name"] = gr.Name
|
||||
newResource.SetLabels(label)
|
||||
|
||||
if mode == Create {
|
||||
// Reset resource version
|
||||
newResource.SetResourceVersion("")
|
||||
// Create the resource
|
||||
|
@ -327,11 +351,27 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
logger.V(4).Info("created new resource")
|
||||
|
||||
} else if mode == Update {
|
||||
var isUpdate bool
|
||||
label := newResource.GetLabels()
|
||||
if label != nil {
|
||||
isUpdate = false
|
||||
if rule.Generation.Synchronize {
|
||||
if label["policy.kyverno.io/synchronize"] == "enable" {
|
||||
isUpdate = true
|
||||
}
|
||||
} else {
|
||||
if label["policy.kyverno.io/synchronize"] == "enable" {
|
||||
isUpdate = true
|
||||
}
|
||||
}
|
||||
if rule.Generation.Synchronize {
|
||||
label["policy.kyverno.io/synchronize"] = "enable"
|
||||
} else {
|
||||
label["policy.kyverno.io/synchronize"] = "disable"
|
||||
}
|
||||
if isUpdate {
|
||||
logger.V(4).Info("updating existing resource")
|
||||
// Update the resource
|
||||
newResource.SetLabels(label)
|
||||
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
|
||||
if err != nil {
|
||||
logger.Error(err, "updating existing resource")
|
||||
|
@ -339,13 +379,20 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
return noGenResource, err
|
||||
}
|
||||
logger.V(4).Info("updated new resource")
|
||||
}else{
|
||||
resource := &unstructured.Unstructured{}
|
||||
resource.SetUnstructuredContent(rdata)
|
||||
resource.SetLabels(label)
|
||||
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, resource, false)
|
||||
if err != nil {
|
||||
logger.Error(err, "updating existing resource")
|
||||
// Failed to update resource
|
||||
return noGenResource, err
|
||||
}
|
||||
logger.V(4).Info("updated new resource")
|
||||
}
|
||||
logger.V(4).Info("Synchronize resource is disabled")
|
||||
|
||||
} else {
|
||||
logger.V(4).Info("Synchronize resource is disabled")
|
||||
}
|
||||
} else {
|
||||
logger.V(4).Info("Synchronize resource is disabled")
|
||||
}
|
||||
}
|
||||
return newGenResource, nil
|
||||
}
|
||||
|
@ -353,24 +400,19 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
|
|||
func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
||||
// check if resource to be generated exists
|
||||
obj, err := client.GetResource(apiVersion, kind, namespace, name)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
||||
return data, Create, nil
|
||||
}
|
||||
if err != nil {
|
||||
//something wrong while fetching resource
|
||||
// client-errors
|
||||
return nil, Skip, err
|
||||
}
|
||||
// Resource exists; verfiy the content of the resource
|
||||
err = checkResource(log, data, obj)
|
||||
if err == nil {
|
||||
// Existing resource does contain the mentioned configuration in spec, skip processing the resource as it is already in expected state
|
||||
return nil, Skip, nil
|
||||
}
|
||||
log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
||||
return data, Update, nil
|
||||
|
||||
updateObj := &unstructured.Unstructured{}
|
||||
updateObj.SetUnstructuredContent(data)
|
||||
updateObj.SetResourceVersion(obj.GetResourceVersion())
|
||||
return updateObj.UnstructuredContent(), Update, nil
|
||||
}
|
||||
|
||||
func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
|
||||
|
@ -409,13 +451,6 @@ func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clon
|
|||
return obj.UnstructuredContent(), Update, nil
|
||||
}
|
||||
|
||||
//TODO: check this
|
||||
if !apierrors.IsNotFound(err) {
|
||||
log.Error(err, "reference/clone resource is not found", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
|
||||
//something wrong while fetching resource
|
||||
return nil, Skip, err
|
||||
}
|
||||
|
||||
// create the resource based on the reference clone
|
||||
return obj.UnstructuredContent(), Create, nil
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
|
@ -13,11 +14,11 @@ import (
|
|||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
"github.com/googleapis/gnostic/compiler"
|
||||
|
||||
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
"github.com/nirmata/kyverno/pkg/constant"
|
||||
client "github.com/nirmata/kyverno/pkg/dclient"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
@ -157,7 +158,10 @@ func (o *Controller) ParseCRD(crd unstructured.Unstructured) {
|
|||
|
||||
parsedSchema, err := openapi_v2.NewSchema(schema, compiler.NewContext("schema", nil))
|
||||
if err != nil {
|
||||
v3valueFound := isOpenV3Error(err)
|
||||
if v3valueFound == false {
|
||||
log.Log.Error(err, "could not parse crd schema", "name", crdName)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -166,6 +170,18 @@ func (o *Controller) ParseCRD(crd unstructured.Unstructured) {
|
|||
o.definitions[crdName] = parsedSchema
|
||||
}
|
||||
|
||||
func isOpenV3Error(err error) bool {
|
||||
unsupportedValues := []string{"anyOf", "allOf", "not"}
|
||||
v3valueFound := false
|
||||
for _, value := range unsupportedValues {
|
||||
if !strings.Contains(err.Error(), fmt.Sprintf("has invalid property: %s", value)) {
|
||||
v3valueFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return v3valueFound
|
||||
}
|
||||
|
||||
// addingDefaultFieldsToSchema will add any default missing fields like apiVersion, metadata
|
||||
func addingDefaultFieldsToSchema(schemaRaw []byte) ([]byte, error) {
|
||||
var schema struct {
|
||||
|
|
|
@ -4,6 +4,9 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"fmt"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
@ -61,6 +64,9 @@ type PolicyController struct {
|
|||
// npLister can list/get namespace policy from the shared informer's store
|
||||
npLister kyvernolister.PolicyLister
|
||||
|
||||
// grLister can list/get generate request from the shared informer's store
|
||||
grLister kyvernolister.GenerateRequestLister
|
||||
|
||||
// pvLister can list/get policy violation from the shared informer's store
|
||||
cpvLister kyvernolister.ClusterPolicyViolationLister
|
||||
|
||||
|
@ -85,6 +91,8 @@ type PolicyController struct {
|
|||
// nsListerSynced returns true if the namespace store has been synced at least once
|
||||
nsListerSynced cache.InformerSynced
|
||||
|
||||
// grListerSynced returns true if the generate request store has been synced at least once
|
||||
grListerSynced cache.InformerSynced
|
||||
// Resource manager, manages the mapping for already processed resource
|
||||
rm resourceManager
|
||||
|
||||
|
@ -94,6 +102,7 @@ type PolicyController struct {
|
|||
// policy violation generator
|
||||
pvGenerator policyviolation.GeneratorInterface
|
||||
|
||||
|
||||
// resourceWebhookWatcher queues the webhook creation request, creates the webhook
|
||||
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister
|
||||
|
||||
|
@ -116,6 +125,7 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
|
|||
npInformer kyvernoinformer.PolicyInformer,
|
||||
cpvInformer kyvernoinformer.ClusterPolicyViolationInformer,
|
||||
nspvInformer kyvernoinformer.PolicyViolationInformer,
|
||||
grInformer kyvernoinformer.GenerateRequestInformer,
|
||||
configHandler config.Interface, eventGen event.Interface,
|
||||
pvGenerator policyviolation.GeneratorInterface,
|
||||
resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister,
|
||||
|
@ -185,11 +195,12 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset,
|
|||
pc.npLister = npInformer.Lister()
|
||||
|
||||
pc.nsLister = namespaces.Lister()
|
||||
|
||||
pc.grLister = grInformer.Lister()
|
||||
pc.pListerSynced = pInformer.Informer().HasSynced
|
||||
pc.npListerSynced = npInformer.Informer().HasSynced
|
||||
|
||||
pc.nsListerSynced = namespaces.Informer().HasSynced
|
||||
pc.grListerSynced = grInformer.Informer().HasSynced
|
||||
|
||||
// resource manager
|
||||
// rebuild after 300 seconds/ 5 mins
|
||||
|
@ -351,6 +362,7 @@ func (pc *PolicyController) Run(workers int, stopCh <-chan struct{}) {
|
|||
logger.Info("failed to sync informer cache")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
|
@ -402,7 +414,6 @@ func (pc *PolicyController) handleErr(err error, key interface{}) {
|
|||
}
|
||||
|
||||
func (pc *PolicyController) syncPolicy(key string) error {
|
||||
|
||||
logger := pc.log
|
||||
startTime := time.Now()
|
||||
logger.V(4).Info("started syncing policy", "key", key, "startTime", startTime)
|
||||
|
@ -413,6 +424,11 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
namespace, key, isNamespacedPolicy := getIsNamespacedPolicy(key)
|
||||
var policy *kyverno.ClusterPolicy
|
||||
var err error
|
||||
grList, err := pc.grLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to list generate request")
|
||||
}
|
||||
|
||||
if !isNamespacedPolicy {
|
||||
policy, err = pc.pLister.Get(key)
|
||||
} else {
|
||||
|
@ -420,6 +436,7 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
nspolicy, err = pc.npLister.Policies(namespace).Get(key)
|
||||
policy = ConvertPolicyToClusterPolicy(nspolicy)
|
||||
}
|
||||
|
||||
if errors.IsNotFound(err) {
|
||||
if os.Getenv("POLICY-TYPE") == "POLICYREPORT" {
|
||||
pc.policySync.mux.Lock()
|
||||
|
@ -427,18 +444,33 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
pc.policySync.mux.Unlock()
|
||||
return nil
|
||||
}
|
||||
for _, v := range grList {
|
||||
if key == v.Spec.Policy {
|
||||
err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Delete(v.GetName(),&metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to delete gr")
|
||||
}
|
||||
}
|
||||
}
|
||||
go pc.deletePolicyViolations(key)
|
||||
|
||||
// remove webhook configurations if there are no policies
|
||||
if err := pc.removeResourceWebhookConfiguration(); err != nil {
|
||||
logger.Error(err, "failed to remove resource webhook configurations")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, v := range grList {
|
||||
if policy.Name == v.Spec.Policy {
|
||||
v.SetLabels(map[string]string{
|
||||
"policy-update" :fmt.Sprintf("revision-count-%d",rand.Intn(100000)),
|
||||
})
|
||||
_,err := pc.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).Update(v)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to update gr")
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("POLICY-TYPE") == "POLICYREPORT" {
|
||||
pc.policySync.mux.Lock()
|
||||
|
@ -448,8 +480,8 @@ func (pc *PolicyController) syncPolicy(key string) error {
|
|||
pc.resourceWebhookWatcher.RegisterResourceWebhook()
|
||||
engineResponses := pc.processExistingResources(policy)
|
||||
pc.cleanupAndReport(engineResponses)
|
||||
pc.resourceWebhookWatcher.RegisterResourceWebhook()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,18 @@ func generateCronJobRule(rule kyverno.Rule, controllers string, log logr.Logger)
|
|||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Mutation != nil) && (jobRule.Mutation.PatchStrategicMerge != nil) {
|
||||
newMutation := &kyverno.Mutation{
|
||||
PatchStrategicMerge: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"jobTemplate": jobRule.Mutation.PatchStrategicMerge,
|
||||
},
|
||||
},
|
||||
}
|
||||
cronJobRule.Mutation = newMutation.DeepCopy()
|
||||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Validation != nil) && (jobRule.Validation.Pattern != nil) {
|
||||
newValidate := &kyverno.Validation{
|
||||
Message: rule.Validation.Message,
|
||||
|
|
|
@ -277,7 +277,7 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
|
|||
return kyvernoRule{}
|
||||
}
|
||||
|
||||
if rule.Mutation.Overlay == nil && !rule.HasValidate() {
|
||||
if rule.Mutation.Overlay == nil && !rule.HasValidate() && rule.Mutation.PatchStrategicMerge == nil {
|
||||
return kyvernoRule{}
|
||||
}
|
||||
|
||||
|
@ -336,6 +336,19 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
|
|||
return *controllerRule
|
||||
}
|
||||
|
||||
if rule.Mutation.PatchStrategicMerge != nil {
|
||||
newMutation := &kyverno.Mutation{
|
||||
PatchStrategicMerge: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"template": rule.Mutation.PatchStrategicMerge,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
controllerRule.Mutation = newMutation.DeepCopy()
|
||||
return *controllerRule
|
||||
}
|
||||
|
||||
if rule.Validation.Pattern != nil {
|
||||
newValidate := &kyverno.Validation{
|
||||
Message: rule.Validation.Message,
|
||||
|
|
|
@ -90,6 +90,7 @@ func (g *Generator) processApply() {
|
|||
|
||||
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec, action v1beta1.Operation) error {
|
||||
// create/update a generate request
|
||||
|
||||
if err := retryApplyResource(g.client, grSpec, g.log, action); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -125,10 +126,10 @@ func retryApplyResource(client *kyvernoclient.Clientset,
|
|||
}
|
||||
for i, v := range grList.Items {
|
||||
if grSpec.Policy == v.Spec.Policy && grSpec.Resource.Name == v.Spec.Resource.Name && grSpec.Resource.Kind == v.Spec.Resource.Kind && grSpec.Resource.Namespace == v.Spec.Resource.Namespace {
|
||||
|
||||
gr.SetLabels(map[string]string{
|
||||
"resources-update": "true",
|
||||
})
|
||||
|
||||
v.Spec.Context = gr.Spec.Context
|
||||
v.Spec.Policy = gr.Spec.Policy
|
||||
v.Spec.Resource = gr.Spec.Resource
|
||||
|
|
|
@ -47,10 +47,11 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
}
|
||||
|
||||
// engine.Generate returns a list of rules that are applicable on this resource
|
||||
var rules []response.RuleResponse
|
||||
for _, policy := range policies {
|
||||
policyContext.Policy = *policy
|
||||
engineResponse := engine.Generate(policyContext)
|
||||
for i, rule := range engineResponse.PolicyResponse.Rules {
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if !rule.Success {
|
||||
grList, err := ws.kyvernoClient.KyvernoV1().GenerateRequests(config.KubePolicyNamespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
|
@ -64,15 +65,14 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
}
|
||||
}
|
||||
}
|
||||
if len(engineResponse.PolicyResponse.Rules) > 1 {
|
||||
engineResponse.PolicyResponse.Rules = append(engineResponse.PolicyResponse.Rules[:i], engineResponse.PolicyResponse.Rules[i+1:]...)
|
||||
continue
|
||||
} else if len(engineResponse.PolicyResponse.Rules) == 1 {
|
||||
engineResponse.PolicyResponse.Rules = []response.RuleResponse{}
|
||||
}else{
|
||||
rules = append(rules,rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(engineResponse.PolicyResponse.Rules) > 0 {
|
||||
|
||||
|
||||
if len(rules) > 0 {
|
||||
engineResponse.PolicyResponse.Rules = rules
|
||||
// some generate rules do apply to the resource
|
||||
engineResponses = append(engineResponses, engineResponse)
|
||||
ws.statusListener.Send(generateStats{
|
||||
|
@ -81,6 +81,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// Adds Generate Request to a channel(queue size 1000) to generators
|
||||
if failedResponse := applyGenerateRequest(ws.grGenerator, userRequestInfo, request.Operation, engineResponses...); err != nil {
|
||||
// report failure event
|
||||
|
|
Loading…
Add table
Reference in a new issue