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

fix: cli engine invocation order (#8327)

* fix: cli engine invocation order

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* mutate

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* verify images

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* validate

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* generate

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix and tests

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix tests

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-09-11 15:41:36 +02:00 committed by GitHub
parent 7a982a4c2c
commit 10bb27b4da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 347 additions and 319 deletions

View file

@ -66,7 +66,6 @@ type ApplyCommandConfig struct {
warnNoPassed bool
}
// allow os.exit to be overwritten during unit tests
func Command() *cobra.Command {
var cmd *cobra.Command
var removeColor, detailedResults, table bool
@ -248,61 +247,58 @@ func (c *ApplyCommandConfig) applyPolicytoResource(
if vars != nil {
vars.SetInStore()
}
// validate policies
var validPolicies []kyvernov1.PolicyInterface
for _, pol := range policies {
// TODO we should return this info to the caller
_, err := policyvalidation.Validate(pol, nil, nil, true, openApiManager, config.KyvernoUserName(config.KyvernoServiceAccountName()))
if err != nil {
log.Log.Error(err, "policy validation error")
if strings.HasPrefix(err.Error(), "variable 'element.name'") {
skipInvalidPolicies.invalid = append(skipInvalidPolicies.invalid, pol.GetName())
} else {
skipInvalidPolicies.skipped = append(skipInvalidPolicies.skipped, pol.GetName())
}
continue
}
matches, err := policy.ExtractVariables(pol)
if err != nil {
log.Log.Error(err, "skipping invalid policy", "name", pol.GetName())
continue
}
if !vars.HasVariables() && variables.NeedsVariables(matches...) {
// check policy in variable file
if !vars.HasPolicyVariables(pol.GetName()) {
fmt.Printf("test skipped for policy %v (as required variables are not provided by the users) \n \n", pol.GetName())
continue
}
}
validPolicies = append(validPolicies, pol)
}
var rc processor.ResultCounts
var responses []engineapi.EngineResponse
for _, resource := range resources {
for _, pol := range policies {
_, err := policyvalidation.Validate(pol, nil, nil, true, openApiManager, config.KyvernoUserName(config.KyvernoServiceAccountName()))
if err != nil {
log.Log.Error(err, "policy validation error")
if strings.HasPrefix(err.Error(), "variable 'element.name'") {
skipInvalidPolicies.invalid = append(skipInvalidPolicies.invalid, pol.GetName())
} else {
skipInvalidPolicies.skipped = append(skipInvalidPolicies.skipped, pol.GetName())
}
continue
}
matches, err := policy.ExtractVariables(pol)
if err != nil {
log.Log.Error(err, "skipping invalid policy", "name", pol.GetName())
continue
}
if !vars.HasVariables() && variables.NeedsVariables(matches...) {
// check policy in variable file
if !vars.HasPolicyVariables(pol.GetName()) {
skipInvalidPolicies.skipped = append(skipInvalidPolicies.skipped, pol.GetName())
continue
}
}
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(pol, vars.Subresources(), dClient)
resourceValues, err := vars.ComputeVariables(pol.GetName(), resource.GetName(), resource.GetKind(), kindOnwhichPolicyIsApplied, matches...)
if err != nil {
return &rc, resources, responses, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", pol.GetName(), resource.GetName()), err)
}
processor := processor.PolicyProcessor{
Policy: pol,
Resource: resource,
MutateLogPath: c.MutateLogPath,
MutateLogPathIsDir: mutateLogPathIsDir,
Variables: resourceValues,
UserInfo: userInfo,
PolicyReport: c.PolicyReport,
NamespaceSelectorMap: vars.NamespaceSelectors(),
Stdin: c.Stdin,
Rc: &rc,
PrintPatchResource: true,
Client: dClient,
AuditWarn: c.AuditWarn,
Subresources: vars.Subresources(),
}
ers, err := processor.ApplyPolicyOnResource()
if err != nil {
return &rc, resources, responses, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", pol.GetName(), resource.GetName()).Error(), err)
}
responses = append(responses, processSkipEngineResponses(ers)...)
processor := processor.PolicyProcessor{
Policies: validPolicies,
Resource: *resource,
MutateLogPath: c.MutateLogPath,
MutateLogPathIsDir: mutateLogPathIsDir,
Variables: vars,
UserInfo: userInfo,
PolicyReport: c.PolicyReport,
NamespaceSelectorMap: vars.NamespaceSelectors(),
Stdin: c.Stdin,
Rc: &rc,
PrintPatchResource: true,
Client: dClient,
AuditWarn: c.AuditWarn,
Subresources: vars.Subresources(),
}
ers, err := processor.ApplyPoliciesOnResource()
if err != nil {
return &rc, resources, responses, sanitizederror.NewWithError(fmt.Errorf("failed to apply policies on resource %v", resource.GetName()).Error(), err)
}
responses = append(responses, processSkipEngineResponses(ers)...)
}
return &rc, resources, responses, nil
}

View file

@ -329,7 +329,9 @@ func Test_Apply(t *testing.T) {
}
for _, tc := range testcases {
verifyTestcase(t, tc, compareSummary)
t.Run("", func(t *testing.T) {
verifyTestcase(t, tc, compareSummary)
})
}
}

View file

@ -3,6 +3,7 @@ package test
import (
"fmt"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/log"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/pluralize"
@ -112,11 +113,8 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
}
}
}
// execute engine
fmt.Println(" Applying", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), "to", len(uniques), pluralize.Pluralize(len(uniques), "resource", "resources"), "...")
var engineResponses []engineapi.EngineResponse
var resultCounts processor.ResultCounts
// TODO loop through resources first, then through policies second
// validate policies
var validPolicies []kyvernov1.PolicyInterface
for _, pol := range policies {
// TODO we should return this info to the caller
_, err := policyvalidation.Validate(pol, nil, nil, true, openApiManager, config.KyvernoUserName(config.KyvernoServiceAccountName()))
@ -133,42 +131,36 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b
// check policy in variable file
if !vars.HasPolicyVariables(pol.GetName()) {
fmt.Printf("test skipped for policy %v (as required variables are not provided by the users) \n \n", pol.GetName())
// TODO continue ? return error ?
// continue
}
}
validPolicies = append(validPolicies, pol)
}
// execute engine
fmt.Println(" Applying", len(policies), pluralize.Pluralize(len(policies), "policy", "policies"), "to", len(uniques), pluralize.Pluralize(len(uniques), "resource", "resources"), "...")
var engineResponses []engineapi.EngineResponse
var resultCounts processor.ResultCounts
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(pol, vars.Subresources(), dClient)
for _, resource := range uniques {
resourceValues, err := vars.ComputeVariables(pol.GetName(), resource.GetName(), resource.GetKind(), kindOnwhichPolicyIsApplied, matches...)
if err != nil {
message := fmt.Sprintf(
"policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag",
pol.GetName(),
resource.GetName(),
)
return nil, sanitizederror.NewWithError(message, err)
}
processor := processor.PolicyProcessor{
Policy: pol,
Resource: resource,
MutateLogPath: "",
Variables: resourceValues,
UserInfo: userInfo,
PolicyReport: true,
NamespaceSelectorMap: vars.NamespaceSelectors(),
Rc: &resultCounts,
RuleToCloneSourceResource: ruleToCloneSourceResource,
Client: dClient,
Subresources: vars.Subresources(),
}
ers, err := processor.ApplyPolicyOnResource()
if err != nil {
message := fmt.Sprintf("failed to apply policy %v on resource %v", pol.GetName(), resource.GetName())
return nil, sanitizederror.NewWithError(message, err)
}
engineResponses = append(engineResponses, ers...)
for _, resource := range uniques {
processor := processor.PolicyProcessor{
Policies: validPolicies,
Resource: *resource,
MutateLogPath: "",
Variables: vars,
UserInfo: userInfo,
PolicyReport: true,
NamespaceSelectorMap: vars.NamespaceSelectors(),
Rc: &resultCounts,
RuleToCloneSourceResource: ruleToCloneSourceResource,
Client: dClient,
Subresources: vars.Subresources(),
}
ers, err := processor.ApplyPoliciesOnResource()
if err != nil {
message := fmt.Sprintf("failed to apply policies on resource %v", resource.GetName())
return nil, sanitizederror.NewWithError(message, err)
}
engineResponses = append(engineResponses, ers...)
}
for _, resource := range uniques {
processor := processor.ValidatingAdmissionPolicyProcessor{

View file

@ -12,7 +12,9 @@ import (
valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/log"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/store"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/variables"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config"
@ -21,20 +23,20 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/policycontext"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
yamlv2 "gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type PolicyProcessor struct {
Policy kyvernov1.PolicyInterface
Resource *unstructured.Unstructured
Policies []kyvernov1.PolicyInterface
Resource unstructured.Unstructured
MutateLogPath string
MutateLogPathIsDir bool
Variables map[string]interface{}
Variables *variables.Variables
UserInfo *kyvernov1beta1.RequestInfo
PolicyReport bool
NamespaceSelectorMap map[string]map[string]string
@ -47,45 +49,28 @@ type PolicyProcessor struct {
Subresources []valuesapi.Subresource
}
func (p *PolicyProcessor) ApplyPolicyOnResource() ([]engineapi.EngineResponse, error) {
jp := jmespath.New(config.NewDefaultConfiguration(false))
var engineResponses []engineapi.EngineResponse
namespaceLabels := make(map[string]string)
operation := kyvernov1.Create
if p.Variables["request.operation"] == "DELETE" {
operation = kyvernov1.Delete
}
rules := autogen.ComputeRules(p.Policy)
if needsNamespaceLabels(rules...) {
resourceNamespace := p.Resource.GetNamespace()
namespaceLabels = p.NamespaceSelectorMap[p.Resource.GetNamespace()]
if resourceNamespace != "default" && len(namespaceLabels) < 1 {
return engineResponses, sanitizederror.NewWithError(fmt.Sprintf("failed to get namespace labels for resource %s. use --values-file flag to pass the namespace labels", p.Resource.GetName()), nil)
}
}
resPath := fmt.Sprintf("%s/%s/%s", p.Resource.GetNamespace(), p.Resource.GetKind(), p.Resource.GetName())
log.Log.V(3).Info("applying policy on resource", "policy", p.Policy.GetName(), "resource", resPath)
resourceRaw, err := p.Resource.MarshalJSON()
if err != nil {
log.Log.Error(err, "failed to marshal resource")
}
updatedResource, err := kubeutils.BytesToUnstructured(resourceRaw)
if err != nil {
log.Log.Error(err, "unable to convert raw resource to unstructured")
}
if err != nil {
log.Log.Error(err, "failed to load resource in context")
}
func (p *PolicyProcessor) ApplyPoliciesOnResource() ([]engineapi.EngineResponse, error) {
cfg := config.NewDefaultConfiguration(false)
gvk, subresource := updatedResource.GroupVersionKind(), ""
jp := jmespath.New(cfg)
resource := p.Resource
namespaceLabels := p.NamespaceSelectorMap[p.Resource.GetNamespace()]
var client engineapi.Client
if p.Client != nil {
client = adapters.Client(p.Client)
}
rclient := registryclient.NewOrDie()
eng := engine.NewEngine(
cfg,
config.NewDefaultMetricsConfiguration(),
jmespath.New(cfg),
client,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
store.ContextLoaderFactory(nil),
nil,
"",
)
gvk, subresource := resource.GroupVersionKind(), ""
// If --cluster flag is not set, then we need to find the top level resource GVK and subresource
if p.Client == nil {
for _, s := range p.Subresources {
@ -105,25 +90,114 @@ func (p *PolicyProcessor) ApplyPolicyOnResource() ([]engineapi.EngineResponse, e
}
}
}
var client engineapi.Client
if p.Client != nil {
client = adapters.Client(p.Client)
resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
var responses []engineapi.EngineResponse
// mutate
for _, policy := range p.Policies {
policyContext, err := p.makePolicyContext(jp, cfg, resource, policy, namespaceLabels, gvk, subresource)
if err != nil {
return responses, err
}
mutateResponse := eng.Mutate(context.Background(), policyContext)
combineRuleResponses(mutateResponse)
err = p.processMutateEngineResponse(mutateResponse, resPath)
if err != nil {
if !sanitizederror.IsErrorSanitized(err) {
return responses, sanitizederror.NewWithError("failed to print mutated result", err)
}
}
responses = append(responses, mutateResponse)
resource = mutateResponse.PatchedResource
}
// verify images
for _, policy := range p.Policies {
policyContext, err := p.makePolicyContext(jp, cfg, resource, policy, namespaceLabels, gvk, subresource)
if err != nil {
return responses, err
}
// TODO annotation
verifyImageResponse, _ := eng.VerifyAndPatchImages(context.TODO(), policyContext)
if !verifyImageResponse.IsEmpty() {
verifyImageResponse = combineRuleResponses(verifyImageResponse)
responses = append(responses, verifyImageResponse)
resource = verifyImageResponse.PatchedResource
}
}
// validate
for _, policy := range p.Policies {
policyContext, err := p.makePolicyContext(jp, cfg, resource, policy, namespaceLabels, gvk, subresource)
if err != nil {
return responses, err
}
validateResponse := eng.Validate(context.TODO(), policyContext)
if !validateResponse.IsEmpty() {
validateResponse = combineRuleResponses(validateResponse)
responses = append(responses, validateResponse)
resource = validateResponse.PatchedResource
}
}
// generate
for _, policy := range p.Policies {
var policyHasGenerate bool
for _, rule := range autogen.ComputeRules(policy) {
if rule.HasGenerate() {
policyHasGenerate = true
}
}
if policyHasGenerate {
policyContext, err := p.makePolicyContext(jp, cfg, resource, policy, namespaceLabels, gvk, subresource)
if err != nil {
return responses, err
}
generateResponse := eng.ApplyBackgroundChecks(context.TODO(), policyContext)
if !generateResponse.IsEmpty() {
newRuleResponse, err := handleGeneratePolicy(&generateResponse, *policyContext, p.RuleToCloneSourceResource)
if err != nil {
log.Log.Error(err, "failed to apply generate policy")
} else {
generateResponse.PolicyResponse.Rules = newRuleResponse
}
combineRuleResponses(generateResponse)
responses = append(responses, generateResponse)
}
p.Rc.addGenerateResponse(p.AuditWarn, resPath, generateResponse)
}
}
p.Rc.addEngineResponses(p.AuditWarn, responses...)
return responses, nil
}
func (p *PolicyProcessor) makePolicyContext(
jp jmespath.Interface,
cfg config.Configuration,
resource unstructured.Unstructured,
policy kyvernov1.PolicyInterface,
namespaceLabels map[string]string,
gvk schema.GroupVersionKind,
subresource string,
) (*policycontext.PolicyContext, error) {
operation := kyvernov1.Create
var resourceValues map[string]interface{}
if p.Variables != nil {
kindOnwhichPolicyIsApplied := common.GetKindsFromPolicy(policy, p.Variables.Subresources(), p.Client)
vals, err := p.Variables.ComputeVariables(policy.GetName(), resource.GetName(), resource.GetKind(), kindOnwhichPolicyIsApplied /*matches...*/)
if err != nil {
message := fmt.Sprintf(
"policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag",
policy.GetName(),
resource.GetName(),
)
return nil, sanitizederror.NewWithError(message, err)
}
resourceValues = vals
}
if resourceValues["request.operation"] == "DELETE" {
operation = kyvernov1.Delete
}
rclient := registryclient.NewOrDie()
eng := engine.NewEngine(
cfg,
config.NewDefaultMetricsConfiguration(),
jmespath.New(cfg),
client,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
store.ContextLoaderFactory(nil),
nil,
"",
)
policyContext, err := engine.NewPolicyContext(
jp,
*updatedResource,
resource,
operation,
p.UserInfo,
cfg,
@ -131,80 +205,17 @@ func (p *PolicyProcessor) ApplyPolicyOnResource() ([]engineapi.EngineResponse, e
if err != nil {
log.Log.Error(err, "failed to create policy context")
}
policyContext = policyContext.
WithPolicy(p.Policy).
WithPolicy(policy).
WithNamespaceLabels(namespaceLabels).
WithResourceKind(gvk, subresource)
for key, value := range p.Variables {
for key, value := range resourceValues {
err = policyContext.JSONContext().AddVariable(key, value)
if err != nil {
log.Log.Error(err, "failed to add variable to context")
}
}
mutateResponse := eng.Mutate(context.Background(), policyContext)
combineRuleResponses(mutateResponse)
engineResponses = append(engineResponses, mutateResponse)
err = p.processMutateEngineResponse(mutateResponse, resPath)
if err != nil {
if !sanitizederror.IsErrorSanitized(err) {
return engineResponses, sanitizederror.NewWithError("failed to print mutated result", err)
}
}
verifyImageResponse, _ := eng.VerifyAndPatchImages(context.TODO(), policyContext)
if !verifyImageResponse.IsEmpty() {
verifyImageResponse = combineRuleResponses(verifyImageResponse)
engineResponses = append(engineResponses, verifyImageResponse)
}
var policyHasValidate bool
for _, rule := range rules {
if rule.HasValidate() || rule.HasVerifyImageChecks() {
policyHasValidate = true
}
}
policyContext = policyContext.WithNewResource(mutateResponse.PatchedResource)
var validateResponse engineapi.EngineResponse
if policyHasValidate {
validateResponse = eng.Validate(context.Background(), policyContext)
validateResponse = combineRuleResponses(validateResponse)
}
if !validateResponse.IsEmpty() {
engineResponses = append(engineResponses, validateResponse)
}
var policyHasGenerate bool
for _, rule := range rules {
if rule.HasGenerate() {
policyHasGenerate = true
}
}
if policyHasGenerate {
generateResponse := eng.ApplyBackgroundChecks(context.TODO(), policyContext)
if !generateResponse.IsEmpty() {
newRuleResponse, err := handleGeneratePolicy(&generateResponse, *policyContext, p.RuleToCloneSourceResource)
if err != nil {
log.Log.Error(err, "failed to apply generate policy")
} else {
generateResponse.PolicyResponse.Rules = newRuleResponse
}
combineRuleResponses(generateResponse)
engineResponses = append(engineResponses, generateResponse)
}
p.Rc.addGenerateResponse(p.AuditWarn, resPath, generateResponse)
}
p.Rc.addEngineResponses(p.AuditWarn, engineResponses...)
return engineResponses, nil
return policyContext, nil
}
func (p *PolicyProcessor) processMutateEngineResponse(response engineapi.EngineResponse, resourcePath string) error {
@ -219,7 +230,7 @@ func (p *PolicyProcessor) processMutateEngineResponse(response engineapi.EngineR
mutatedResource := string(yamlEncodedResource) + string("\n---")
if len(strings.TrimSpace(mutatedResource)) > 0 {
if !p.Stdin {
fmt.Printf("\nmutate policy %s applied to %s:", p.Policy.GetName(), resourcePath)
fmt.Printf("\nmutate policy %s applied to %s:", response.Policy().GetName(), resourcePath)
}
fmt.Printf("\n" + mutatedResource + "\n")
}

View file

@ -0,0 +1,123 @@
package processor
import (
"testing"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"gotest.tools/assert"
)
var policyNamespaceSelector = []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "enforce-pod-name"
},
"spec": {
"validationFailureAction": "audit",
"background": true,
"rules": [
{
"name": "validate-name",
"match": {
"resources": {
"kinds": [
"Pod"
],
"namespaceSelector": {
"matchExpressions": [
{
"key": "foo.com/managed-state",
"operator": "In",
"values": [
"managed"
]
}
]
}
}
},
"validate": {
"message": "The Pod must end with -nginx",
"pattern": {
"metadata": {
"name": "*-nginx"
}
}
}
}
]
}
}
`)
func Test_NamespaceSelector(t *testing.T) {
type resultCounts struct {
pass int
fail int
warn int
err int
skip int
}
type TestCase struct {
policy []byte
resource []byte
namespaceSelectorMap map[string]map[string]string
result ResultCounts
}
testcases := []TestCase{
{
policy: policyNamespaceSelector,
resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"nginx","namespace":"test1"},"spec":{"containers":[{"image":"nginx:latest","name":"test-fail"}]}}`),
namespaceSelectorMap: map[string]map[string]string{
"test1": {
"foo.com/managed-state": "managed",
},
},
result: ResultCounts{
pass: 0,
fail: 1,
warn: 0,
err: 0,
skip: 2,
},
},
{
policy: policyNamespaceSelector,
resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"test-nginx","namespace":"test1"},"spec":{"containers":[{"image":"nginx:latest","name":"test-pass"}]}}`),
namespaceSelectorMap: map[string]map[string]string{
"test1": {
"foo.com/managed-state": "managed",
},
},
result: ResultCounts{
pass: 1,
fail: 1,
warn: 0,
err: 0,
skip: 4,
},
},
}
rc := &ResultCounts{}
for _, tc := range testcases {
policyArray, _, _ := yamlutils.GetPolicy(tc.policy)
resourceArray, _ := resource.GetUnstructuredResources(tc.resource)
processor := PolicyProcessor{
Policies: policyArray,
Resource: *resourceArray[0],
MutateLogPath: "",
UserInfo: nil,
NamespaceSelectorMap: tc.namespaceSelectorMap,
Rc: rc,
}
processor.ApplyPoliciesOnResource()
assert.Equal(t, int64(rc.Pass()), int64(tc.result.pass))
assert.Equal(t, int64(rc.Fail()), int64(tc.result.fail))
assert.Equal(t, int64(rc.Skip()), int64(tc.result.skip))
assert.Equal(t, int64(rc.Warn()), int64(tc.result.warn))
assert.Equal(t, int64(rc.Error()), int64(tc.result.err))
}
}

View file

@ -3,7 +3,6 @@ package processor
import (
"strings"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
)
@ -78,33 +77,3 @@ func combineRuleResponses(imageResponse engineapi.EngineResponse) engineapi.Engi
imageResponse.PolicyResponse.Rules = combineRuleResponses
return imageResponse
}
func needsNamespaceLabels(rules ...kyvernov1.Rule) bool {
for _, p := range rules {
if p.MatchResources.ResourceDescription.NamespaceSelector != nil ||
p.ExcludeResources.ResourceDescription.NamespaceSelector != nil {
return true
}
for _, m := range p.MatchResources.Any {
if m.ResourceDescription.NamespaceSelector != nil {
return true
}
}
for _, m := range p.MatchResources.All {
if m.ResourceDescription.NamespaceSelector != nil {
return true
}
}
for _, e := range p.ExcludeResources.Any {
if e.ResourceDescription.NamespaceSelector != nil {
return true
}
}
for _, e := range p.ExcludeResources.All {
if e.ResourceDescription.NamespaceSelector != nil {
return true
}
}
}
return false
}

View file

@ -4,9 +4,7 @@ import (
"testing"
valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/processor"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -55,76 +53,6 @@ var policyNamespaceSelector = []byte(`{
}
`)
func Test_NamespaceSelector(t *testing.T) {
type ResultCounts struct {
pass int
fail int
warn int
err int
skip int
}
type TestCase struct {
policy []byte
resource []byte
namespaceSelectorMap map[string]map[string]string
result ResultCounts
}
testcases := []TestCase{
{
policy: policyNamespaceSelector,
resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"nginx","namespace":"test1"},"spec":{"containers":[{"image":"nginx:latest","name":"test-fail"}]}}`),
namespaceSelectorMap: map[string]map[string]string{
"test1": {
"foo.com/managed-state": "managed",
},
},
result: ResultCounts{
pass: 0,
fail: 1,
warn: 0,
err: 0,
skip: 2,
},
},
{
policy: policyNamespaceSelector,
resource: []byte(`{"apiVersion":"v1","kind":"Pod","metadata":{"name":"test-nginx","namespace":"test1"},"spec":{"containers":[{"image":"nginx:latest","name":"test-pass"}]}}`),
namespaceSelectorMap: map[string]map[string]string{
"test1": {
"foo.com/managed-state": "managed",
},
},
result: ResultCounts{
pass: 1,
fail: 1,
warn: 0,
err: 0,
skip: 4,
},
},
}
rc := &processor.ResultCounts{}
for _, tc := range testcases {
policyArray, _, _ := yamlutils.GetPolicy(tc.policy)
resourceArray, _ := resource.GetUnstructuredResources(tc.resource)
processor := processor.PolicyProcessor{
Policy: policyArray[0],
Resource: resourceArray[0],
MutateLogPath: "",
UserInfo: nil,
NamespaceSelectorMap: tc.namespaceSelectorMap,
Rc: rc,
}
processor.ApplyPolicyOnResource()
assert.Equal(t, int64(rc.Pass()), int64(tc.result.pass))
assert.Equal(t, int64(rc.Fail()), int64(tc.result.fail))
assert.Equal(t, int64(rc.Skip()), int64(tc.result.skip))
assert.Equal(t, int64(rc.Warn()), int64(tc.result.warn))
assert.Equal(t, int64(rc.Error()), int64(tc.result.err))
}
}
func Test_GetGitBranchOrPolicyPaths(t *testing.T) {
type TestCase struct {
gitBranch string

View file

@ -10,11 +10,15 @@ spec:
containers:
- image: registry.digitalocean.com/runlevl4/nginxasdfasdf:latest
name: busybox01
securityContext:
runAsNonRoot: true
args:
- sleep
- "9999"
- image: registry.digitalocean.com/runlevl4/bbbbbbbbbb-ccccc:1.28
name: busybox02
securityContext:
runAsNonRoot: true
args:
- sleep
- "9999"

View file

@ -5,3 +5,5 @@ metadata:
annotations:
key1: "1"
key2: "1"
labels:
color: orange

View file

@ -3,6 +3,7 @@ kind: Pod
metadata:
labels:
foo: bar
color: orange
name: same-name-but-diff-namespace
namespace: testing
spec: