1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

feat: stop mutating rules (#3410)

* feat: stop adding autogen annotation

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* feat: stop mutating rules

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* feat: stop mutating rules

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* fix: use toggle

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* fix: review comments

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2022-03-28 16:01:27 +02:00 committed by GitHub
parent 2ce205b9e9
commit 20069c13c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 324 additions and 214 deletions

View file

@ -62,7 +62,9 @@ jobs:
- name: e2e testing
run: |
echo ">>> Install Kyverno"
sed 's/imagePullPolicy:.*$/imagePullPolicy: IfNotPresent/g' ${GITHUB_WORKSPACE}/config/install.yaml | kubectl apply -f -
cat ${GITHUB_WORKSPACE}/config/install.yaml | \
sed -e 's/imagePullPolicy:.*$/imagePullPolicy: IfNotPresent/g' | \
kubectl apply -f -
kubectl apply -f ${GITHUB_WORKSPACE}/config/github/rbac.yaml
chmod a+x ${GITHUB_WORKSPACE}/scripts/verify-deployment.sh
sleep 50

View file

@ -68,6 +68,10 @@ jobs:
run: make verify-codegen
tests:
strategy:
fail-fast: false
matrix:
autogen-internals: [true, false]
runs-on: ubuntu-latest
needs: pre-checks
steps:
@ -93,4 +97,5 @@ jobs:
- name: Kyverno unit test
run: |
export PROJECT_PATH=$(pwd)
export FLAG_AUTOGEN_INTERNALS=${{ matrix.autogen-internals }}
make test-unit

View file

@ -294,10 +294,8 @@ test-unit: $(GO_ACC)
@echo " running unit tests"
go-acc ./... -o $(CODE_COVERAGE_FILE_TXT)
code-cov-report:
# generate code coverage report
code-cov-report: ## Generate code coverage report
@echo " generating code coverage report"
GO111MODULE=on go test -v -coverprofile=coverage.out ./...
go tool cover -func=coverage.out -o $(CODE_COVERAGE_FILE_TXT)
go tool cover -html=coverage.out -o $(CODE_COVERAGE_FILE_HTML)
@ -359,16 +357,15 @@ release-notes:
##################################
.PHONY: kyverno-crd
kyverno-crd: controller-gen
kyverno-crd: controller-gen ## Generate Kyverno CRDs
$(CONTROLLER_GEN) crd paths=./api/kyverno/... crd:crdVersions=v1 output:dir=./config/crds
.PHONY: report-crd
report-crd: controller-gen
report-crd: controller-gen ## Generate policy reports CRDs
$(CONTROLLER_GEN) crd paths=./api/policyreport/... crd:crdVersions=v1 output:dir=./config/crds
# install the right version of controller-gen
.PHONY: install-controller-gen
install-controller-gen:
install-controller-gen: ## Install controller-gen
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
@ -379,9 +376,8 @@ install-controller-gen:
}
CONTROLLER_GEN=$(GOPATH)/bin/controller-gen
# setup controller-gen with the right version, if necessary
.PHONY: controller-gen
controller-gen:
controller-gen: ## Setup controller-gen
ifeq (, $(shell which controller-gen))
@{ \
echo "controller-gen not found!";\

View file

@ -31,16 +31,6 @@ type ClusterPolicy struct {
Status PolicyStatus `json:"status,omitempty" yaml:"status,omitempty"`
}
// GetSpec returns the policy spec
func (p *ClusterPolicy) GetSpec() Spec {
return p.Spec
}
// GetRules returns the policy rules
func (p *ClusterPolicy) GetRules() []Rule {
return p.Spec.GetRules()
}
// HasAutoGenAnnotation checks if a policy has auto-gen annotation
func (p *ClusterPolicy) HasAutoGenAnnotation() bool {
annotations := p.GetAnnotations()
@ -86,6 +76,11 @@ func (p *ClusterPolicy) BackgroundProcessingEnabled() bool {
return p.Spec.BackgroundProcessingEnabled()
}
// GetSpec returns the policy spec
func (p *ClusterPolicy) GetSpec() Spec {
return p.Spec
}
// IsNamespaced indicates if the policy is namespace scoped
func (p *ClusterPolicy) IsNamespaced() bool {
return p.GetNamespace() != ""

View file

@ -32,16 +32,6 @@ type Policy struct {
Status PolicyStatus `json:"status,omitempty" yaml:"status,omitempty"`
}
// GetSpec returns the policy spec
func (p *Policy) GetSpec() Spec {
return p.Spec
}
// GetRules returns the policy rules
func (p *Policy) GetRules() []Rule {
return p.Spec.GetRules()
}
// HasAutoGenAnnotation checks if a policy has auto-gen annotation
func (p *Policy) HasAutoGenAnnotation() bool {
annotations := p.GetAnnotations()
@ -87,6 +77,11 @@ func (p *Policy) BackgroundProcessingEnabled() bool {
return p.Spec.BackgroundProcessingEnabled()
}
// GetSpec returns the policy spec
func (p *Policy) GetSpec() Spec {
return p.Spec
}
// IsNamespaced indicates if the policy is namespace scoped
func (p *Policy) IsNamespaced() bool {
return false

View file

@ -88,7 +88,7 @@ func Test_Validate_RuleType_MultipleRule(t *testing.T) {
var policy *ClusterPolicy
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
for _, rule := range policy.GetRules() {
for _, rule := range policy.Spec.Rules {
path := field.NewPath("dummy")
errs := rule.Validate(path, false, nil)
assert.Assert(t, len(errs) != 0)
@ -143,7 +143,7 @@ func Test_Validate_RuleType_SingleRule(t *testing.T) {
var policy *ClusterPolicy
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
for _, rule := range policy.GetRules() {
for _, rule := range policy.Spec.Rules {
path := field.NewPath("dummy")
errs := rule.Validate(path, false, nil)
assert.Assert(t, len(errs) == 0)

View file

@ -65,11 +65,6 @@ type Spec struct {
WebhookTimeoutSeconds *int32 `json:"webhookTimeoutSeconds,omitempty" yaml:"webhookTimeoutSeconds,omitempty"`
}
// GetRules returns the spec rules
func (s *Spec) GetRules() []Rule {
return s.Rules
}
func (s *Spec) SetRules(rules []Rule) {
s.Rules = rules
}

View file

@ -97,7 +97,7 @@ The command removes all the Kubernetes components associated with the chart and
| dnsPolicy | string | `"ClusterFirst"` | `dnsPolicy` determines the manner in which DNS resolution happens in the cluster. In case of `hostNetwork: true`, usually, the `dnsPolicy` is suitable to be `ClusterFirstWithHostNet`. For further reference: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy. |
| envVarsInit | object | `{}` | Env variables for initContainers. |
| envVars | object | `{}` | Env variables for containers. |
| extraArgs | list | `[]` | Extra arguments to give to the binary. |
| extraArgs | list | `["--autogenInternals=false"]` | Extra arguments to give to the binary. |
| resources.limits | object | `{"memory":"384Mi"}` | Pod resource limits |
| resources.requests | object | `{"cpu":"100m","memory":"128Mi"}` | Pod resource requests |
| initResources.limits | object | `{"cpu":"100m","memory":"256Mi"}` | Pod resource limits |

View file

@ -143,8 +143,8 @@ envVarsInit: {}
envVars: {}
# -- Extra arguments to give to the binary.
extraArgs: []
# - --webhookTimeout=4
extraArgs:
- --autogenInternals=false
resources:
# -- Pod resource limits

View file

@ -103,7 +103,7 @@ func main() {
flag.BoolVar(&autoUpdateWebhooks, "autoUpdateWebhooks", true, "Set this flag to 'false' to disable auto-configuration of the webhook.")
flag.Float64Var(&clientRateLimitQPS, "clientRateLimitQPS", 0, "Configure the maximum QPS to the master from Kyverno. Uses the client default if zero.")
flag.IntVar(&clientRateLimitBurst, "clientRateLimitBurst", 0, "Configure the maximum burst for throttle. Uses the client default if zero.")
flag.BoolVar(&toggle.AutogenInternals, "autogenInternals", toggle.DefaultAutogenInternals, "Enables autogen internal policies. When this is 'true' policy rules should not be mutated.")
flag.Func(toggle.AutogenInternalsFlagName, toggle.AutogenInternalsDescription, toggle.AutogenInternalsFlag)
flag.DurationVar(&webhookRegistrationTimeout, "webhookRegistrationTimeout", 120*time.Second, "Timeout for webhook registration, e.g., 30s, 1m, 5m.")
if err := flag.Set("v", "2"); err != nil {

View file

@ -10971,6 +10971,7 @@ spec:
- args:
- --filterK8sResources=[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][*,kyverno,kyverno*][Binding,*,*][ReplicaSet,*,*][ReportChangeRequest,*,*][ClusterReportChangeRequest,*,*][PolicyReport,*,*][ClusterPolicyReport,*,*]
- -v=2
- --autogenInternals=false
env:
- name: INIT_CONFIG
value: kyverno

View file

@ -78,6 +78,7 @@ spec:
# configure the workers for generate controller
# - --genWorkers=20
- "-v=2"
- --autogenInternals=false
ports:
- containerPort: 9443
name: https

View file

@ -9,8 +9,10 @@ import (
jsonpatch "github.com/evanphx/json-patch"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/toggle"
"github.com/kyverno/kyverno/pkg/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
log "sigs.k8s.io/controller-runtime/pkg/log"
)
const (
@ -240,3 +242,106 @@ func GenerateRulePatches(spec *kyverno.Spec, controllers string, log logr.Logger
}
return
}
type Policy interface {
GetAnnotations() map[string]string
GetSpec() kyverno.Spec
}
// podControllersKey annotation could be:
// scenario A: not exist, set default to "all", which generates on all pod controllers
// - if name / selector exist in resource description -> skip
// as these fields may not be applicable to pod controllers
// scenario B: "none", user explicitly disable this feature -> skip
// scenario C: some certain controllers that user set -> generate on defined controllers
// copy entire match / exclude block, it's users' responsibility to
// make sure all fields are applicable to pod controllers
// GenerateRules generates rule for podControllers based on scenario A and C
func GenerateRules(spec *kyverno.Spec, controllers string, log logr.Logger) []kyverno.Rule {
var rules []kyverno.Rule
for _, rule := range spec.Rules {
// handle all other controllers other than CronJob
if genRule := generateRuleForControllers(*rule.DeepCopy(), stripCronJob(controllers), log); genRule != nil {
if convRule, err := convertRule(*genRule, "Pod"); err == nil {
rules = append(rules, *convRule)
}
}
// handle CronJob, it appends an additional rule
if genRule := generateCronJobRule(*rule.DeepCopy(), controllers, log); genRule != nil {
if convRule, err := convertRule(*genRule, "Cronjob"); err == nil {
rules = append(rules, *convRule)
}
}
}
return rules
}
func convertRule(rule kyvernoRule, kind string) (*kyverno.Rule, error) {
if bytes, err := json.Marshal(rule); err != nil {
return nil, err
} else {
bytes = updateGenRuleByte(bytes, kind, rule)
if err := json.Unmarshal(bytes, &rule); err != nil {
return nil, err
}
}
out := kyverno.Rule{
Name: rule.Name,
VerifyImages: rule.VerifyImages,
}
if rule.MatchResources != nil {
out.MatchResources = *rule.MatchResources
}
if rule.ExcludeResources != nil {
out.ExcludeResources = *rule.ExcludeResources
}
if rule.Context != nil {
out.Context = *rule.Context
}
if rule.AnyAllConditions != nil {
out.SetAnyAllConditions(*rule.AnyAllConditions)
}
if rule.Mutation != nil {
out.Mutation = *rule.Mutation
}
if rule.Validation != nil {
out.Validation = *rule.Validation
}
return &out, nil
}
func ComputeRules(p Policy) []kyverno.Rule {
spec := p.GetSpec()
if !toggle.AutogenInternals() {
return spec.Rules
}
applyAutoGen, desiredControllers := CanAutoGen(&spec, log.Log)
if !applyAutoGen {
desiredControllers = "none"
}
ann := p.GetAnnotations()
actualControllers, ok := ann[kyverno.PodControllersAnnotation]
if !ok || !applyAutoGen {
actualControllers = desiredControllers
} else {
if !applyAutoGen {
actualControllers = desiredControllers
}
}
if actualControllers == "none" {
return spec.Rules
}
genRules := GenerateRules(spec.DeepCopy(), actualControllers, log.Log)
if len(genRules) == 0 {
return spec.Rules
}
var out []kyverno.Rule
out = append(out, spec.Rules...)
out = append(out, genRules...)
return out
}

View file

@ -260,7 +260,7 @@ func Test_Any(t *testing.T) {
}
policy := policies[0]
policy.GetRules()[0].MatchResources.Any = kyverno.ResourceFilters{
policy.Spec.Rules[0].MatchResources.Any = kyverno.ResourceFilters{
{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Pod"},
@ -298,7 +298,7 @@ func Test_All(t *testing.T) {
}
policy := policies[0]
policy.GetRules()[0].MatchResources.All = kyverno.ResourceFilters{
policy.Spec.Rules[0].MatchResources.All = kyverno.ResourceFilters{
{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Pod"},
@ -336,7 +336,7 @@ func Test_Exclude(t *testing.T) {
}
policy := policies[0]
policy.GetRules()[0].ExcludeResources.Namespaces = []string{"fake-namespce"}
policy.Spec.Rules[0].ExcludeResources.Namespaces = []string{"fake-namespce"}
rulePatches, errs := GenerateRulePatches(&policy.Spec, PodControllers, log.Log)
if len(errs) != 0 {
@ -400,7 +400,7 @@ func Test_ForEachPod(t *testing.T) {
}
policy := policies[0]
policy.GetRules()[0].ExcludeResources.Namespaces = []string{"fake-namespce"}
policy.Spec.Rules[0].ExcludeResources.Namespaces = []string{"fake-namespce"}
rulePatches, errs := GenerateRulePatches(&policy.Spec, PodControllers, log.Log)
if len(errs) != 0 {
@ -439,10 +439,10 @@ func Test_CronJob_hasExclude(t *testing.T) {
kyverno.PodControllersAnnotation: controllers,
})
rule := policy.GetRules()[0].DeepCopy()
rule := policy.Spec.Rules[0].DeepCopy()
rule.ExcludeResources.Kinds = []string{"Pod"}
rule.ExcludeResources.Namespaces = []string{"test"}
policy.GetRules()[0] = *rule
policy.Spec.Rules[0] = *rule
rulePatches, errs := GenerateRulePatches(&policy.Spec, controllers, log.Log)
if len(errs) != 0 {
@ -529,7 +529,7 @@ func Test_Deny(t *testing.T) {
}
policy := policies[0]
policy.GetRules()[0].MatchResources.Any = kyverno.ResourceFilters{
policy.Spec.Rules[0].MatchResources.Any = kyverno.ResourceFilters{
{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Pod"},

View file

@ -418,11 +418,11 @@ func updateGenRuleByte(pbyte []byte, kind string, genRule kyvernoRule) (obj []by
return obj
}
if kind == "Pod" {
obj = []byte(strings.Replace(string(pbyte), "request.object.spec", "request.object.spec.template.spec", -1))
obj = []byte(strings.ReplaceAll(string(pbyte), "request.object.spec", "request.object.spec.template.spec"))
}
if kind == "Cronjob" {
obj = []byte(strings.Replace(string(pbyte), "request.object.spec", "request.object.spec.jobTemplate.spec.template.spec", -1))
obj = []byte(strings.ReplaceAll(string(pbyte), "request.object.spec", "request.object.spec.jobTemplate.spec.template.spec"))
}
obj = []byte(strings.Replace(string(obj), "request.object.metadata", "request.object.spec.template.metadata", -1))
obj = []byte(strings.ReplaceAll(string(obj), "request.object.metadata", "request.object.spec.template.metadata"))
return obj
}

View file

@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/kyverno/kyverno/pkg/autogen"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
@ -94,7 +95,7 @@ func AddCloneLabel(client *dclient.Client, pInformer kyvernoinformer.ClusterPoli
}
for _, policy := range policies {
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasGenerate() {
clone := rule.Generation.Clone
if clone.Name != "" {

View file

@ -19,7 +19,8 @@ func ForceMutate(ctx *context.Context, policy kyverno.ClusterPolicy, resource un
"namespace", resource.GetNamespace(), "name", resource.GetName())
patchedResource := resource
for _, rule := range policy.GetRules() {
// TODO: if we apply autogen, tests will fail
for _, rule := range policy.Spec.Rules {
if !rule.HasMutate() {
continue
}

View file

@ -3,6 +3,7 @@ package engine
import (
"time"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/common"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
@ -48,7 +49,7 @@ func filterRules(policyContext *PolicyContext, startTime time.Time) *response.En
return resp
}
for _, rule := range policyContext.Policy.GetRules() {
for _, rule := range autogen.ComputeRules(&policyContext.Policy) {
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
}

View file

@ -6,6 +6,7 @@ import (
"time"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/registryclient"
"github.com/pkg/errors"
@ -48,7 +49,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (resp *response.EngineRe
}
}
rules := policyContext.Policy.GetRules()
rules := autogen.ComputeRules(&policyContext.Policy)
for i := range rules {
rule := &rules[i]
if len(rule.VerifyImages) == 0 {

View file

@ -5,6 +5,7 @@ import (
"testing"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
assertnew "github.com/stretchr/testify/assert"
"gotest.tools/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@ -242,7 +243,7 @@ func Test_PolicyDeserilize(t *testing.T) {
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
overlayPatches := policy.GetRules()[0].Mutation.GetPatchStrategicMerge()
overlayPatches := autogen.ComputeRules(&policy)[0].Mutation.GetPatchStrategicMerge()
patchString, err := json.Marshal(overlayPatches)
assert.NilError(t, err)

View file

@ -8,6 +8,7 @@ import (
"github.com/go-logr/logr"
gojmespath "github.com/jmespath/go-jmespath"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/mutate"
"github.com/kyverno/kyverno/pkg/engine/response"
"github.com/kyverno/kyverno/pkg/engine/utils"
@ -37,7 +38,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
var err error
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(&policy) {
if !rule.HasMutate() {
continue
}

View file

@ -5,6 +5,7 @@ import (
"testing"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/utils"
"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -897,7 +898,7 @@ func TestMatchesResourceDescription(t *testing.T) {
}
resource, _ := utils.ConvertToUnstructured(tc.Resource)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(&policy) {
err := MatchesResourceDescription(*resource, rule, tc.AdmissionInfo, []string{}, nil, "")
if err != nil {
if !tc.areErrorsExpected {

View file

@ -8,6 +8,7 @@ import (
"time"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/common"
"github.com/pkg/errors"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@ -87,7 +88,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
ctx.JSONContext.Checkpoint()
defer ctx.JSONContext.Restore()
rules := ctx.Policy.GetRules()
rules := autogen.ComputeRules(&ctx.Policy)
for i := range rules {
rule := &rules[i]
if !rule.HasValidate() {

View file

@ -7,6 +7,7 @@ import (
"k8s.io/client-go/kubernetes"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/autogen"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
@ -141,7 +142,7 @@ func (c *Controller) deletePolicy(obj interface{}) {
// clean up the GR
// Get the corresponding GR
// get the list of GR for the current Policy version
rules := p.GetRules()
rules := autogen.ComputeRules(p)
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, c.client, p.GetName(), logger)

View file

@ -11,6 +11,7 @@ import (
"time"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/response"
"github.com/go-logr/logr"
@ -259,7 +260,7 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext *engine.
// To manage existing resources, we compare the creation time for the default resource to be generated and policy creation time
ruleNameToProcessingTime := make(map[string]time.Duration)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(&policy) {
var err error
if !rule.HasGenerate() {
continue

View file

@ -9,6 +9,7 @@ import (
"k8s.io/client-go/kubernetes"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/autogen"
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
@ -258,7 +259,7 @@ func (c *Controller) updatePolicy(old, cur interface{}) {
}
var policyHasGenerate bool
for _, rule := range curP.GetRules() {
for _, rule := range autogen.ComputeRules(curP) {
if rule.HasGenerate() {
policyHasGenerate = true
}

View file

@ -15,7 +15,6 @@ import (
"github.com/kyverno/kyverno/pkg/openapi"
policy2 "github.com/kyverno/kyverno/pkg/policy"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/toggle"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/cli-runtime/pkg/genericclioptions"
@ -131,7 +130,6 @@ func Command() *cobra.Command {
return nil
},
}
cmd.Flags().StringArrayVarP(&resourcePaths, "resource", "r", []string{}, "Path to resource files")
cmd.Flags().BoolVarP(&cluster, "cluster", "c", false, "Checks if policies should be applied to cluster in the current context")
cmd.Flags().StringVarP(&mutateLogPath, "output", "o", "", "Prints the mutated resources in provided file/directory")
@ -141,7 +139,6 @@ func Command() *cobra.Command {
cmd.Flags().BoolVarP(&policyReport, "policy-report", "", false, "Generates policy report when passed (default policyviolation r")
cmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Optional Policy parameter passed with cluster flag")
cmd.Flags().BoolVarP(&stdin, "stdin", "i", false, "Optional mutate policy parameter to pipe directly through to kubectl")
cmd.Flags().BoolVarP(&toggle.AutogenInternals, "autogenInternals", "", toggle.DefaultAutogenInternals, "Use autogen internals")
cmd.Flags().BoolVarP(&registryAccess, "registry", "", false, "If set to true, access the image registry using local docker credentials to populate external data")
return cmd
}

View file

@ -63,12 +63,11 @@ func Test_Apply(t *testing.T) {
}
compareSummary := func(expected preport.PolicyReportSummary, actual map[string]interface{}) {
assert.Assert(t, actual[preport.StatusPass].(int64) == int64(expected.Pass))
assert.Assert(t, actual[preport.StatusFail].(int64) == int64(expected.Fail))
assert.Assert(t, actual[preport.StatusSkip].(int64) == int64(expected.Skip))
assert.Assert(t, actual[preport.StatusWarn].(int64) == int64(expected.Warn))
assert.Assert(t, actual[preport.StatusError].(int64) == int64(expected.Error))
assert.Equal(t, actual[preport.StatusPass].(int64), int64(expected.Pass))
assert.Equal(t, actual[preport.StatusFail].(int64), int64(expected.Fail))
assert.Equal(t, actual[preport.StatusSkip].(int64), int64(expected.Skip))
assert.Equal(t, actual[preport.StatusWarn].(int64), int64(expected.Warn))
assert.Equal(t, actual[preport.StatusError].(int64), int64(expected.Error))
}
for _, tc := range testcases {

View file

@ -13,8 +13,8 @@ import (
"reflect"
"strings"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/toggle"
jsonpatch "github.com/evanphx/json-patch/v5"
"github.com/go-git/go-billy/v5"
@ -175,8 +175,8 @@ func GetPolicies(paths []string) (policies []*v1.ClusterPolicy, errors []error)
}
// MutatePolicy - applies mutation to a policy
func MutatePolicy(policy *v1.ClusterPolicy, autogenInternals bool, logger logr.Logger) (*v1.ClusterPolicy, error) {
patches, _ := policymutation.GenerateJSONPatchesForDefaults(policy, autogenInternals, logger)
func MutatePolicy(policy *v1.ClusterPolicy, logger logr.Logger) (*v1.ClusterPolicy, error) {
patches, _ := policymutation.GenerateJSONPatchesForDefaults(policy, logger)
if len(patches) == 0 {
return policy, nil
}
@ -444,7 +444,7 @@ func MutatePolicies(policies []*v1.ClusterPolicy) ([]*v1.ClusterPolicy, error) {
logger := log.Log.WithName("apply")
for _, policy := range policies {
p, err := MutatePolicy(policy, toggle.AutogenInternals, logger)
p, err := MutatePolicy(policy, logger)
if err != nil {
if !sanitizederror.IsErrorSanitized(err) {
return nil, sanitizederror.NewWithError("failed to mutate policy.", err)
@ -472,7 +472,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
policyWithNamespaceSelector := false
OuterLoop:
for _, p := range policy.GetRules() {
for _, p := range autogen.ComputeRules(policy) {
if p.MatchResources.ResourceDescription.NamespaceSelector != nil ||
p.ExcludeResources.ResourceDescription.NamespaceSelector != nil {
policyWithNamespaceSelector = true
@ -574,7 +574,7 @@ OuterLoop:
}
var policyHasValidate bool
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasValidate() {
policyHasValidate = true
}
@ -592,7 +592,7 @@ OuterLoop:
}
var policyHasGenerate bool
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasGenerate() {
policyHasGenerate = true
}
@ -770,7 +770,7 @@ func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []str
func ProcessValidateEngineResponse(policy *v1.ClusterPolicy, validateResponse *response.EngineResponse, resPath string, rc *ResultCounts, policyReport bool) policyreport.Info {
var violatedRules []v1.ViolatedRule
printCount := 0
for _, policyRule := range policy.GetRules() {
for _, policyRule := range autogen.ComputeRules(policy) {
ruleFoundInEngineResponse := false
if !policyRule.HasValidate() {
continue
@ -851,7 +851,7 @@ func buildPVInfo(er *response.EngineResponse, violatedRules []v1.ViolatedRule) p
func processGenerateEngineResponse(policy *v1.ClusterPolicy, generateResponse *response.EngineResponse, resPath string, rc *ResultCounts) {
printCount := 0
for _, policyRule := range policy.GetRules() {
for _, policyRule := range autogen.ComputeRules(policy) {
ruleFoundInEngineResponse := false
for i, genResponseRule := range generateResponse.PolicyResponse.Rules {
if policyRule.Name == genResponseRule.Name {
@ -879,7 +879,7 @@ func SetInStoreContext(mutatedPolicies []*v1.ClusterPolicy, variables map[string
storePolicies := make([]store.Policy, 0)
for _, policy := range mutatedPolicies {
storeRules := make([]store.Rule, 0)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
contextVal := make(map[string]string)
if len(rule.Context) != 0 {
for _, contextVar := range rule.Context {
@ -911,7 +911,7 @@ func SetInStoreContext(mutatedPolicies []*v1.ClusterPolicy, variables map[string
func processMutateEngineResponse(policy *v1.ClusterPolicy, mutateResponse *response.EngineResponse, resPath string, rc *ResultCounts, mutateLogPath string, stdin bool, mutateLogPathIsDir bool, resourceName string, printPatchResource bool) error {
var policyHasMutate bool
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasMutate() {
policyHasMutate = true
}
@ -922,7 +922,7 @@ func processMutateEngineResponse(policy *v1.ClusterPolicy, mutateResponse *respo
printCount := 0
printMutatedRes := false
for _, policyRule := range policy.GetRules() {
for _, policyRule := range autogen.ComputeRules(policy) {
ruleFoundInEngineResponse := false
for i, mutateResponseRule := range mutateResponse.PolicyResponse.Rules {
if policyRule.Name == mutateResponseRule.Name {
@ -1021,7 +1021,7 @@ func CheckVariableForPolicy(valuesMap map[string]map[string]Resource, globalValM
func GetKindsFromPolicy(policy *v1.ClusterPolicy) map[string]struct{} {
var kindOnwhichPolicyIsApplied = make(map[string]struct{})
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.ResourceDescription.Kinds {
kindOnwhichPolicyIsApplied[kind] = struct{}{}
}

View file

@ -3,6 +3,7 @@ package common
import (
"testing"
"github.com/kyverno/kyverno/pkg/toggle"
ut "github.com/kyverno/kyverno/pkg/utils"
"gotest.tools/assert"
)
@ -73,7 +74,7 @@ func Test_NamespaceSelector(t *testing.T) {
Fail: 1,
Warn: 0,
Error: 0,
Skip: 0,
Skip: 2,
},
},
{
@ -89,7 +90,7 @@ func Test_NamespaceSelector(t *testing.T) {
Fail: 1,
Warn: 0,
Error: 0,
Skip: 0,
Skip: 4,
},
},
}
@ -99,10 +100,15 @@ func Test_NamespaceSelector(t *testing.T) {
policyArray, _ := ut.GetPolicy(tc.policy)
resourceArray, _ := GetResource(tc.resource)
ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, false, tc.namespaceSelectorMap, false, rc, false)
assert.Assert(t, int64(rc.Pass) == int64(tc.result.Pass))
assert.Assert(t, int64(rc.Fail) == int64(tc.result.Fail))
assert.Assert(t, int64(rc.Skip) == int64(tc.result.Skip))
assert.Assert(t, int64(rc.Warn) == int64(tc.result.Warn))
assert.Assert(t, int64(rc.Error) == int64(tc.result.Error))
assert.Equal(t, int64(rc.Pass), int64(tc.result.Pass))
assert.Equal(t, int64(rc.Fail), int64(tc.result.Fail))
// TODO: autogen rules seem to not be present when autogen internals is disabled
if toggle.AutogenInternals() {
assert.Equal(t, int64(rc.Skip), int64(tc.result.Skip))
} else {
assert.Equal(t, int64(rc.Skip), int64(0))
}
assert.Equal(t, int64(rc.Warn), int64(tc.result.Warn))
assert.Equal(t, int64(rc.Error), int64(tc.result.Error))
}
}

View file

@ -10,6 +10,7 @@ import (
"github.com/go-git/go-billy/v5"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
client "github.com/kyverno/kyverno/pkg/dclient"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/utils"
@ -31,7 +32,7 @@ func GetResources(policies []*v1.ClusterPolicy, resourcePaths []string, dClient
var resourceTypes []string
for _, policy := range policies {
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
resourceTypesInRule := GetKindsFromRule(rule)
for resourceKind := range resourceTypesInRule {
resourceTypesMap[resourceKind] = true
@ -120,7 +121,7 @@ func GetResourcesWithTest(fs billy.Filesystem, policies []*v1.ClusterPolicy, res
var resourceTypesMap = make(map[string]bool)
var resourceTypes []string
for _, policy := range policies {
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
resourceTypesMap[kind] = true
}

View file

@ -18,6 +18,7 @@ import (
"github.com/kataras/tablewriter"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
report "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
"github.com/kyverno/kyverno/pkg/autogen"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/engine/response"
"github.com/kyverno/kyverno/pkg/engine/utils"
@ -775,7 +776,7 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, isGit bool,
for _, p := range filteredPolicies {
var filteredRules = []v1.Rule{}
for _, rule := range p.GetRules() {
for _, rule := range autogen.ComputeRules(p) {
for _, res := range values.Results {
if rule.Name == res.Rule {
filteredRules = append(filteredRules, rule)

View file

@ -13,7 +13,6 @@ import (
sanitizederror "github.com/kyverno/kyverno/pkg/kyverno/sanitizedError"
"github.com/kyverno/kyverno/pkg/openapi"
policy2 "github.com/kyverno/kyverno/pkg/policy"
"github.com/kyverno/kyverno/pkg/toggle"
"github.com/kyverno/kyverno/pkg/utils"
"github.com/spf13/cobra"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@ -88,7 +87,6 @@ func Command() *cobra.Command {
}
cmd.Flags().StringVarP(&outputType, "output", "o", "", "Prints the mutated policy in yaml or json format")
cmd.Flags().StringArrayVarP(&crdPaths, "crd", "c", []string{}, "Path to CRD files")
cmd.Flags().BoolVarP(&toggle.AutogenInternals, "autogenInternals", "", toggle.DefaultAutogenInternals, "Use autogen internals")
return cmd
}
@ -180,7 +178,7 @@ func validatePolicies(policies []*v1.ClusterPolicy, v1crd apiextensions.CustomRe
fmt.Printf("Policy %s is valid.\n\n", policy.Name)
if outputType != "" {
logger := log.Log.WithName("validate")
p, err := common.MutatePolicy(policy, toggle.AutogenInternals, logger)
p, err := common.MutatePolicy(policy, logger)
if err != nil {
if !sanitizederror.IsErrorSanitized(err) {
return sanitizederror.NewWithError("failed to mutate policy.", err)

View file

@ -4,6 +4,7 @@ import (
"fmt"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/metrics"
prom "github.com/prometheus/client_golang/prometheus"
)
@ -73,7 +74,7 @@ func (pc PromConfig) AddPolicy(policy interface{}) error {
policyName := inputPolicy.GetName()
ready := inputPolicy.IsReady()
// registering the metrics on a per-rule basis
for _, rule := range inputPolicy.GetRules() {
for _, rule := range autogen.ComputeRules(inputPolicy) {
ruleName := rule.Name
ruleType := metrics.ParseRuleType(rule)
@ -93,7 +94,7 @@ func (pc PromConfig) AddPolicy(policy interface{}) error {
policyName := inputPolicy.GetName()
ready := inputPolicy.IsReady()
// registering the metrics on a per-rule basis
for _, rule := range inputPolicy.GetRules() {
for _, rule := range autogen.ComputeRules(inputPolicy) {
ruleName := rule.Name
ruleType := metrics.ParseRuleType(rule)
@ -110,7 +111,7 @@ func (pc PromConfig) AddPolicy(policy interface{}) error {
func (pc PromConfig) RemovePolicy(policy interface{}) error {
switch inputPolicy := policy.(type) {
case *kyverno.ClusterPolicy:
for _, rule := range inputPolicy.GetRules() {
for _, rule := range autogen.ComputeRules(inputPolicy) {
policyValidationMode, err := metrics.ParsePolicyValidationMode(inputPolicy.Spec.ValidationFailureAction)
if err != nil {
return err
@ -129,7 +130,7 @@ func (pc PromConfig) RemovePolicy(policy interface{}) error {
}
return nil
case *kyverno.Policy:
for _, rule := range inputPolicy.GetRules() {
for _, rule := range autogen.ComputeRules(inputPolicy) {
policyValidationMode, err := metrics.ParsePolicyValidationMode(inputPolicy.Spec.ValidationFailureAction)
if err != nil {
return err

View file

@ -13,6 +13,7 @@ import (
openapiv2 "github.com/googleapis/gnostic/openapiv2"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/data"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/utils"
@ -138,7 +139,7 @@ func (o *Controller) ValidateResource(patchedResource unstructured.Unstructured,
// ValidatePolicyMutation ...
func (o *Controller) ValidatePolicyMutation(policy v1.ClusterPolicy) error {
var kindToRules = make(map[string][]v1.Rule)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(&policy) {
if rule.HasMutate() {
for _, kind := range rule.MatchResources.Kinds {
kindToRules[kind] = append(kindToRules[common.GetFormatedKind(kind)], rule)

View file

@ -6,6 +6,7 @@ import (
"strings"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/variables"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@ -19,7 +20,7 @@ func containsUserVariables(policy *kyverno.ClusterPolicy, vars [][]string) error
return fmt.Errorf("variable %s is not allowed", s[0])
}
}
rules := policy.GetRules()
rules := autogen.ComputeRules(policy)
for idx := range rules {
if err := hasUserMatchExclude(idx, &rules[idx]); err != nil {
return err

View file

@ -8,6 +8,7 @@ import (
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/response"
@ -24,7 +25,7 @@ func (pc *PolicyController) processExistingResources(policy *kyverno.ClusterPoli
// Parse through all the resources drops the cache after configured rebuild time
pc.rm.Drop()
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if !rule.HasValidate() && !rule.HasVerifyImages() {
continue
}

View file

@ -23,7 +23,6 @@ import (
"github.com/kyverno/kyverno/pkg/kyverno/common"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/toggle"
"github.com/kyverno/kyverno/pkg/utils"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
@ -195,7 +194,7 @@ func (pc *PolicyController) addPolicy(obj interface{}) {
go pc.registerPolicyChangesMetricAddPolicy(logger, p)
if p.Spec.Background == nil || p.Spec.ValidationFailureAction == "" || missingAutoGenRules(p, logger) {
pol, _ := common.MutatePolicy(p, toggle.AutogenInternals, logger)
pol, _ := common.MutatePolicy(p, logger)
pol.SetGroupVersionKind(schema.GroupVersionKind{Group: "kyverno.io", Version: "v1", Kind: "ClusterPolicy"})
_, err := pc.client.UpdateResource("kyverno.io/v1", "ClusterPolicy", "", pol, false)
if err != nil {
@ -222,7 +221,7 @@ func (pc *PolicyController) updatePolicy(old, cur interface{}) {
go pc.registerPolicyChangesMetricUpdatePolicy(logger, oldP, curP)
if curP.Spec.Background == nil || curP.Spec.ValidationFailureAction == "" || missingAutoGenRules(curP, logger) {
pol, _ := common.MutatePolicy(curP, toggle.AutogenInternals, logger)
pol, _ := common.MutatePolicy(curP, logger)
pol.SetGroupVersionKind(schema.GroupVersionKind{Group: "kyverno.io", Version: "v1", Kind: "ClusterPolicy"})
_, err := pc.client.UpdateResource("kyverno.io/v1", "ClusterPolicy", "", pol, false)
if err != nil {
@ -271,7 +270,7 @@ func (pc *PolicyController) deletePolicy(obj interface{}) {
// we process policies that are not set of background processing
// as we need to clean up GRs when a policy is deleted
// skip generate policies with clone
rules := p.GetRules()
rules := autogen.ComputeRules(p)
generatePolicyWithClone := pkgCommon.ProcessDeletePolicyForCloneGenerateRule(rules, pc.client, p.GetName(), logger)
@ -294,7 +293,7 @@ func (pc *PolicyController) addNsPolicy(obj interface{}) {
pol := ConvertPolicyToClusterPolicy(p)
if pol.Spec.Background == nil || pol.Spec.ValidationFailureAction == "" || missingAutoGenRules(pol, logger) {
nsPol, _ := common.MutatePolicy(pol, toggle.AutogenInternals, logger)
nsPol, _ := common.MutatePolicy(pol, logger)
nsPol.SetGroupVersionKind(schema.GroupVersionKind{Group: "kyverno.io", Version: "v1", Kind: "Policy"})
_, err := pc.client.UpdateResource("kyverno.io/v1", "Policy", p.Namespace, nsPol, false)
if err != nil {
@ -321,7 +320,7 @@ func (pc *PolicyController) updateNsPolicy(old, cur interface{}) {
ncurP := ConvertPolicyToClusterPolicy(curP)
if ncurP.Spec.Background == nil || ncurP.Spec.ValidationFailureAction == "" || missingAutoGenRules(ncurP, logger) {
nsPol, _ := common.MutatePolicy(ncurP, toggle.AutogenInternals, logger)
nsPol, _ := common.MutatePolicy(ncurP, logger)
nsPol.SetGroupVersionKind(schema.GroupVersionKind{Group: "kyverno.io", Version: "v1", Kind: "Policy"})
_, err := pc.client.UpdateResource("kyverno.io/v1", "Policy", ncurP.GetNamespace(), nsPol, false)
if err != nil {
@ -377,11 +376,11 @@ func (pc *PolicyController) deleteNsPolicy(obj interface{}) {
func (pc *PolicyController) enqueueRCRDeletedRule(old, cur *kyverno.ClusterPolicy) {
curRule := make(map[string]bool)
for _, rule := range cur.GetRules() {
for _, rule := range autogen.ComputeRules(cur) {
curRule[rule.Name] = true
}
for _, rule := range old.GetRules() {
for _, rule := range autogen.ComputeRules(old) {
if !curRule[rule.Name] {
pc.prGenerator.Add(policyreport.Info{
PolicyName: cur.GetName(),
@ -566,7 +565,7 @@ func missingAutoGenRules(policy *kyverno.ClusterPolicy, log logr.Logger) bool {
var podRuleName []string
ruleCount := 1
if canApplyAutoGen, _ := autogen.CanAutoGen(&policy.Spec, log); canApplyAutoGen {
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
podRuleName = append(podRuleName, rule.Name)
}
}
@ -593,7 +592,7 @@ func missingAutoGenRules(policy *kyverno.ClusterPolicy, log logr.Logger) bool {
}
}
if len(policy.GetRules()) != (ruleCount * len(podRuleName)) {
if len(autogen.ComputeRules(policy)) != (ruleCount * len(podRuleName)) {
return true
}
}

View file

@ -9,6 +9,7 @@ import (
"strings"
"github.com/distribution/distribution/reference"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/context"
jsonpatch "github.com/evanphx/json-patch/v5"
@ -110,8 +111,7 @@ func Validate(policy *kyverno.ClusterPolicy, client *dclient.Client, mock bool,
if errs := policy.Validate(clusterResources); len(errs) != 0 {
return nil, errs.ToAggregate()
}
rules := policy.GetRules()
rules := autogen.ComputeRules(policy)
rulesPath := specPath.Child("rules")
for i, rule := range rules {
rulePath := rulesPath.Index(i)
@ -365,7 +365,7 @@ func ValidateVariables(p *kyverno.ClusterPolicy, backgroundMode bool) error {
// hasInvalidVariables - checks for unexpected variables in the policy
func hasInvalidVariables(policy *kyverno.ClusterPolicy, background bool) error {
for _, r := range policy.GetRules() {
for _, r := range autogen.ComputeRules(policy) {
ruleCopy := r.DeepCopy()
if err := ruleForbiddenSectionsHaveVariables(ruleCopy); err != nil {

View file

@ -6,6 +6,7 @@ import (
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
kyvernolister "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
"github.com/kyverno/kyverno/pkg/common"
policy2 "github.com/kyverno/kyverno/pkg/policy"
@ -124,7 +125,7 @@ func (m *pMap) add(policy *kyverno.ClusterPolicy) {
pName = pSpace + "/" + pName
}
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
@ -230,7 +231,7 @@ func (m *pMap) remove(policy *kyverno.ClusterPolicy) {
pName = pSpace + "/" + pName
}
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if len(rule.MatchResources.Any) > 0 {
for _, rmr := range rule.MatchResources.Any {
removeCacheHelper(rmr, m, pName)

View file

@ -6,6 +6,7 @@ import (
"testing"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
lv1 "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
"gotest.tools/assert"
"k8s.io/apimachinery/pkg/labels"
@ -49,7 +50,7 @@ func Test_All(t *testing.T) {
policy := newPolicy(t)
//add
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
// get
@ -82,7 +83,7 @@ func Test_Add_Duplicate_Policy(t *testing.T) {
pCache.Add(policy)
pCache.Add(policy)
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
mutate := pCache.get(Mutate, kind, "")
@ -111,7 +112,7 @@ func Test_Add_Validate_Audit(t *testing.T) {
policy.Spec.ValidationFailureAction = "audit"
pCache.Add(policy)
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
validateEnforce := pCache.get(ValidateEnforce, kind, "")
@ -930,7 +931,7 @@ func Test_Ns_All(t *testing.T) {
//add
pCache.Add(policy)
nspace := policy.GetNamespace()
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
// get
@ -963,7 +964,7 @@ func Test_Ns_Add_Duplicate_Policy(t *testing.T) {
pCache.Add(policy)
pCache.Add(policy)
nspace := policy.GetNamespace()
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
mutate := pCache.get(Mutate, kind, nspace)
@ -992,7 +993,7 @@ func Test_Ns_Add_Validate_Audit(t *testing.T) {
policy.Spec.ValidationFailureAction = "audit"
pCache.Add(policy)
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
validateEnforce := pCache.get(ValidateEnforce, kind, nspace)
@ -1031,7 +1032,7 @@ func Test_GVk_Cache(t *testing.T) {
policy := newGVKPolicy(t)
//add
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
generate := pCache.get(Generate, kind, "")
@ -1065,7 +1066,7 @@ func Test_Add_Validate_Enforce(t *testing.T) {
nspace := policy.GetNamespace()
//add
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
validateEnforce := pCache.get(ValidateEnforce, kind, nspace)
if len(validateEnforce) != 1 {
@ -1100,7 +1101,7 @@ func Test_Mutate_Policy(t *testing.T) {
pCache.Add(policy)
pCache.Add(policy)
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
// get
@ -1117,7 +1118,7 @@ func Test_Generate_Policy(t *testing.T) {
policy := newgenratePolicy(t)
//add
pCache.Add(policy)
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
for _, kind := range rule.MatchResources.Kinds {
// get

View file

@ -10,6 +10,7 @@ import (
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/toggle"
"github.com/kyverno/kyverno/pkg/utils"
)
@ -17,7 +18,7 @@ import (
// - ValidationFailureAction
// - Background
// - auto-gen annotation and rules
func GenerateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, autogenInternals bool, log logr.Logger) ([]byte, []string) {
func GenerateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, log logr.Logger) ([]byte, []string) {
var patches [][]byte
var updateMsgs []string
@ -38,16 +39,19 @@ func GenerateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, autogenIntern
updateMsgs = append(updateMsgs, updateMsg)
}
patch, errs := GeneratePodControllerRule(*policy, autogenInternals, log)
if len(errs) > 0 {
var errMsgs []string
for _, err := range errs {
errMsgs = append(errMsgs, err.Error())
log.Error(err, "failed to generate pod controller rule")
// if autogenInternals is enabled, we don't mutate rules in the webhook
if !toggle.AutogenInternals() {
patch, errs := GeneratePodControllerRule(*policy, log)
if len(errs) > 0 {
var errMsgs []string
for _, err := range errs {
errMsgs = append(errMsgs, err.Error())
log.Error(err, "failed to generate pod controller rule")
}
updateMsgs = append(updateMsgs, strings.Join(errMsgs, ";"))
}
updateMsgs = append(updateMsgs, strings.Join(errMsgs, ";"))
patches = append(patches, patch...)
}
patches = append(patches, patch...)
formatedGVK, errs := checkForGVKFormatPatch(policy, log)
if len(errs) > 0 {
@ -65,7 +69,7 @@ func GenerateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, autogenIntern
func checkForGVKFormatPatch(policy *kyverno.ClusterPolicy, log logr.Logger) (patches [][]byte, errs []error) {
patches = make([][]byte, 0)
for i, rule := range policy.GetRules() {
for i, rule := range autogen.ComputeRules(policy) {
patchByte, err := convertGVKForKinds(fmt.Sprintf("/spec/rules/%s/match/resources/kinds", strconv.Itoa(i)), rule.MatchResources.Kinds, log)
if err == nil && patchByte != nil {
patches = append(patches, patchByte)
@ -248,7 +252,7 @@ func defaultFailurePolicy(spec *kyverno.Spec, log logr.Logger) ([]byte, string)
// make sure all fields are applicable to pod controllers
// GeneratePodControllerRule returns two patches: rulePatches and annotation patch(if necessary)
func GeneratePodControllerRule(policy kyverno.ClusterPolicy, autogenInternals bool, log logr.Logger) (patches [][]byte, errs []error) {
func GeneratePodControllerRule(policy kyverno.ClusterPolicy, log logr.Logger) (patches [][]byte, errs []error) {
applyAutoGen, desiredControllers := autogen.CanAutoGen(&policy.Spec, log)
if !applyAutoGen {
@ -262,13 +266,11 @@ func GeneratePodControllerRule(policy kyverno.ClusterPolicy, autogenInternals bo
// - predefined controllers are invalid, overwrite the value
if !ok || !applyAutoGen {
actualControllers = desiredControllers
if !autogenInternals {
annPatch, err := defaultPodControllerAnnotation(ann, actualControllers)
if err != nil {
errs = append(errs, fmt.Errorf("failed to generate pod controller annotation for policy '%s': %v", policy.Name, err))
} else {
patches = append(patches, annPatch)
}
annPatch, err := defaultPodControllerAnnotation(ann, actualControllers)
if err != nil {
errs = append(errs, fmt.Errorf("failed to generate pod controller annotation for policy '%s': %v", policy.Name, err))
} else {
patches = append(patches, annPatch)
}
} else {
if !applyAutoGen {

View file

@ -1,5 +1,45 @@
package toggle
const DefaultAutogenInternals = false
import (
"os"
"strconv"
)
var AutogenInternals = DefaultAutogenInternals
const (
AutogenInternalsFlagName = "autogenInternals"
AutogenInternalsDescription = "Enables autogen internal policies. When this is 'true' policy rules should not be mutated."
AutogenInternalsEnvVar = "FLAG_AUTOGEN_INTERNALS"
DefaultAutogenInternals = false
)
var autogenInternals *bool
func getBool(in string) (*bool, error) {
if in == "" {
return nil, nil
}
value, err := strconv.ParseBool(in)
if err != nil {
return nil, err
}
return &value, nil
}
func AutogenInternalsFlag(in string) error {
if value, err := getBool(in); err != nil {
return err
} else {
autogenInternals = value
return nil
}
}
func AutogenInternals() bool {
if autogenInternals != nil {
return *autogenInternals
}
if value, err := getBool(os.Getenv(AutogenInternalsEnvVar)); err == nil && value != nil {
return *value
}
return DefaultAutogenInternals
}

View file

@ -1,12 +1,5 @@
package utils
import (
"encoding/json"
"reflect"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
)
// JoinPatches joins array of serialized JSON patches to the single JSONPatch array
func JoinPatches(patches [][]byte) []byte {
var result []byte
@ -24,43 +17,3 @@ func JoinPatches(patches [][]byte) []byte {
result = append(result, []byte("\n]")...)
return result
}
// MarshalPolicy accurately marshals a policy to JSON,
// normal marshal would cause empty sub structs in
// policy to be non nil.
// TODO This needs to be removed. A simpler way to encode and decode Policy is needed.
func MarshalPolicy(policy v1.ClusterPolicy) []byte {
var rules []interface{}
policyRules := policy.GetRules()
rulesRaw, _ := json.Marshal(policyRules)
_ = json.Unmarshal(rulesRaw, &rules)
for i, r := range rules {
rule, _ := r.(map[string]interface{})
if reflect.DeepEqual(policyRules[i].Mutation, v1.Mutation{}) {
delete(rule, "mutate")
}
if reflect.DeepEqual(policyRules[i].Validation, v1.Validation{}) {
delete(rule, "validate")
}
if reflect.DeepEqual(policyRules[i].Generation, v1.Generation{}) {
delete(rule, "generate")
}
rules[i] = rule
}
var policyRepresentation = make(map[string]interface{})
policyRaw, _ := json.Marshal(policy)
_ = json.Unmarshal(policyRaw, &policyRepresentation)
specRepresentation, _ := policyRepresentation["spec"].(map[string]interface{})
specRepresentation["rules"] = rules
policyRepresentation["spec"] = specRepresentation
policyRaw, _ = json.Marshal(policyRepresentation)
return policyRaw
}

View file

@ -441,17 +441,17 @@ func (m *webhookConfigManager) buildWebhooks(namespace string) (res []*webhook,
spec := p.GetSpec()
if spec.HasValidate() || spec.HasGenerate() {
if spec.FailurePolicy != nil && *spec.FailurePolicy == kyverno.Ignore {
m.mergeWebhook(validateIgnore, &spec, true)
m.mergeWebhook(validateIgnore, p, true)
} else {
m.mergeWebhook(validateFail, &spec, true)
m.mergeWebhook(validateFail, p, true)
}
}
if spec.HasMutate() || spec.HasVerifyImages() {
if spec.FailurePolicy != nil && *spec.FailurePolicy == kyverno.Ignore {
m.mergeWebhook(mutateIgnore, &spec, false)
m.mergeWebhook(mutateIgnore, p, false)
} else {
m.mergeWebhook(mutateFail, &spec, false)
m.mergeWebhook(mutateFail, p, false)
}
}
}
@ -734,9 +734,9 @@ func (m *webhookConfigManager) updateStatus(namespace, name string, ready bool)
}
// mergeWebhook merges the matching kinds of the policy to webhook.rule
func (m *webhookConfigManager) mergeWebhook(dst *webhook, spec *kyverno.Spec, updateValidate bool) {
func (m *webhookConfigManager) mergeWebhook(dst *webhook, policy policy, updateValidate bool) {
matchedGVK := make([]string, 0)
for _, rule := range spec.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
// matching kinds in generate policies need to be added to both webhook
if rule.HasGenerate() {
matchedGVK = append(matchedGVK, rule.MatchKinds()...)
@ -818,6 +818,7 @@ func (m *webhookConfigManager) mergeWebhook(dst *webhook, spec *kyverno.Spec, up
dst.rule[apiVersions] = removeDuplicates(versions)
dst.rule[resources] = removeDuplicates(rsrcs)
spec := policy.GetSpec()
if spec.WebhookTimeoutSeconds != nil {
if dst.maxWebhookTimeout < int64(*spec.WebhookTimeoutSeconds) {
dst.maxWebhookTimeout = int64(*spec.WebhookTimeoutSeconds)
@ -850,7 +851,7 @@ func webhookKey(webhookKind, failurePolicy string) string {
}
func hasWildcard(spec *kyverno.Spec) bool {
for _, rule := range spec.GetRules() {
for _, rule := range spec.Rules {
if kinds := rule.MatchKinds(); utils.ContainsString(kinds, "*") {
return true
}

View file

@ -7,6 +7,7 @@ import (
"github.com/go-logr/logr"
wildcard "github.com/kyverno/go-wildcard"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/response"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
yamlv2 "gopkg.in/yaml.v2"
@ -142,7 +143,7 @@ func processResourceWithPatches(patch []byte, resource []byte, log logr.Logger)
func containsRBACInfo(policies ...[]*kyverno.ClusterPolicy) bool {
for _, policySlice := range policies {
for _, policy := range policySlice {
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if checkForRBACInfo(rule) {
return true
}

View file

@ -11,6 +11,7 @@ import (
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/config"
client "github.com/kyverno/kyverno/pkg/dclient"
@ -236,7 +237,7 @@ func (ws *WebhookServer) handleUpdateGenerateTargetResource(request *v1beta1.Adm
return
}
for _, rule := range policy.GetRules() {
for _, rule := range autogen.ComputeRules(policy) {
if rule.Generation.Kind == targetSourceKind && rule.Generation.Name == targetSourceName {
updatedRule, err := getGeneratedByResource(newRes, resLabels, ws.client, rule, logger)
if err != nil {

View file

@ -10,7 +10,6 @@ import (
logr "github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/policymutation"
"github.com/kyverno/kyverno/pkg/toggle"
v1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -43,7 +42,7 @@ func (ws *WebhookServer) policyMutation(request *v1beta1.AdmissionRequest) *v1be
defer logger.V(3).Info("finished policy change mutation", "time", time.Since(startTime).String())
// Generate JSON Patches for defaults
patches, updateMsgs := policymutation.GenerateJSONPatchesForDefaults(policy, toggle.AutogenInternals, logger)
patches, updateMsgs := policymutation.GenerateJSONPatchesForDefaults(policy, logger)
if len(patches) != 0 {
patchType := v1beta1.PatchTypeJSONPatch
return &v1beta1.AdmissionResponse{

View file

@ -34,7 +34,7 @@ func TestGeneratePodControllerRule_NilAnnotation(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
p, err := utils.ApplyPatches(policyRaw, patches)
@ -67,7 +67,7 @@ func TestGeneratePodControllerRule_PredefinedAnnotation(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
assert.Assert(t, len(patches) == 1)
}
@ -118,7 +118,7 @@ func TestGeneratePodControllerRule_DisableFeature(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
assert.Assert(t, len(patches) == 0)
}
@ -169,7 +169,7 @@ func TestGeneratePodControllerRule_Mutate(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
p, err := utils.ApplyPatches(policyRaw, patches)
@ -303,7 +303,7 @@ func TestGeneratePodControllerRule_ExistOtherAnnotation(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
p, err := utils.ApplyPatches(policyRaw, patches)
@ -375,7 +375,7 @@ func TestGeneratePodControllerRule_ValidateAnyPattern(t *testing.T) {
var policy kyverno.ClusterPolicy
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
p, err := utils.ApplyPatches(policyRaw, patches)
@ -514,7 +514,7 @@ func TestGeneratePodControllerRule_ValidatePattern(t *testing.T) {
var policy kyverno.ClusterPolicy
// var policy, generatePolicy unstructured.Unstructured
assert.Assert(t, json.Unmarshal(policyRaw, &policy))
patches, errs := policymutation.GeneratePodControllerRule(policy, false, log.Log)
patches, errs := policymutation.GeneratePodControllerRule(policy, log.Log)
assert.Assert(t, len(errs) == 0)
p, err := utils.ApplyPatches(policyRaw, patches)