mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
update validation logic
This commit is contained in:
parent
d0347afa59
commit
e2f10c6f83
30 changed files with 393 additions and 377 deletions
|
@ -15,14 +15,19 @@ import (
|
|||
|
||||
//Interface to manage context operations
|
||||
type Interface interface {
|
||||
//AddJSON merges the json with context
|
||||
|
||||
// AddJSON merges the json with context
|
||||
AddJSON(dataRaw []byte) error
|
||||
//AddResource merges resource json under request.object
|
||||
|
||||
// AddResource merges resource json under request.object
|
||||
AddResource(dataRaw []byte) error
|
||||
//AddUserInfo merges userInfo json under kyverno.userInfo
|
||||
|
||||
// AddUserInfo merges userInfo json under kyverno.userInfo
|
||||
AddUserInfo(userInfo kyverno.UserInfo) error
|
||||
//AddSA merges serrviceaccount
|
||||
AddSA(userName string) error
|
||||
|
||||
// AddServiceAccount merges ServiceAccount types
|
||||
AddServiceAccount(userName string) error
|
||||
|
||||
EvalInterface
|
||||
}
|
||||
|
||||
|
@ -126,8 +131,8 @@ func (ctx *Context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
|
|||
return ctx.AddJSON(objRaw)
|
||||
}
|
||||
|
||||
//AddSA removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
|
||||
func (ctx *Context) AddSA(userName string) error {
|
||||
//AddServiceAccount removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
|
||||
func (ctx *Context) AddServiceAccount(userName string) error {
|
||||
saPrefix := "system:serviceaccount:"
|
||||
var sa string
|
||||
saName := ""
|
||||
|
|
|
@ -93,7 +93,7 @@ func Test_addResourceAndUserContext(t *testing.T) {
|
|||
t.Error("exected result does not match")
|
||||
}
|
||||
// Add service account Name
|
||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
||||
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
@ -12,16 +12,16 @@ import (
|
|||
// 1. validate variables to be substitute in the general ruleInfo (match,exclude,condition)
|
||||
// - the caller has to check the ruleResponse to determine whether the path exist
|
||||
// 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
|
||||
func Generate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||
func Generate(policyContext PolicyContext) (resp *response.EngineResponse) {
|
||||
return filterRules(policyContext)
|
||||
}
|
||||
|
||||
func filterRules(policyContext PolicyContext) response.EngineResponse {
|
||||
func filterRules(policyContext PolicyContext) *response.EngineResponse {
|
||||
kind := policyContext.NewResource.GetKind()
|
||||
name := policyContext.NewResource.GetName()
|
||||
namespace := policyContext.NewResource.GetNamespace()
|
||||
|
||||
resp := response.EngineResponse{
|
||||
resp := &response.EngineResponse{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: policyContext.Policy.Name,
|
||||
Resource: response.ResourceSpec{
|
||||
|
@ -57,7 +57,7 @@ func filterRule(rule kyverno.Rule, policyContext PolicyContext) *response.RuleRe
|
|||
newResource := policyContext.NewResource
|
||||
oldResource := policyContext.OldResource
|
||||
admissionInfo := policyContext.AdmissionInfo
|
||||
ctx := policyContext.Context
|
||||
ctx := policyContext.JSONContext
|
||||
resCache := policyContext.ResourceCache
|
||||
jsonContext := policyContext.JSONContext
|
||||
excludeGroupRole := policyContext.ExcludeGroupRole
|
||||
|
|
|
@ -22,11 +22,12 @@ const (
|
|||
)
|
||||
|
||||
// Mutate performs mutation. Overlay first and then mutation patches
|
||||
func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||
func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
resp = &response.EngineResponse{}
|
||||
startTime := time.Now()
|
||||
policy := policyContext.Policy
|
||||
patchedResource := policyContext.NewResource
|
||||
ctx := policyContext.Context
|
||||
ctx := policyContext.JSONContext
|
||||
|
||||
resCache := policyContext.ResourceCache
|
||||
jsonContext := policyContext.JSONContext
|
||||
|
@ -35,10 +36,10 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
|
||||
logger.V(4).Info("start policy processing", "startTime", startTime)
|
||||
|
||||
startMutateResultResponse(&resp, policy, patchedResource)
|
||||
defer endMutateResultResponse(logger, &resp, startTime)
|
||||
startMutateResultResponse(resp, policy, patchedResource)
|
||||
defer endMutateResultResponse(logger, resp, startTime)
|
||||
|
||||
if SkipPolicyApplication(policy, patchedResource) {
|
||||
if ManagedPodResource(policy, patchedResource) {
|
||||
logger.V(5).Info("skip applying policy as direct changes to pods managed by workload controllers are not allowed", "policy", policy.GetName())
|
||||
resp.PatchedResource = patchedResource
|
||||
return
|
||||
|
@ -58,6 +59,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
if len(policyContext.ExcludeGroupRole) > 0 {
|
||||
excludeResource = policyContext.ExcludeGroupRole
|
||||
}
|
||||
|
||||
if err := MatchesResourceDescription(patchedResource, rule, policyContext.AdmissionInfo, excludeResource); err != nil {
|
||||
logger.V(3).Info("resource not matched", "reason", err.Error())
|
||||
continue
|
||||
|
@ -79,7 +81,6 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
}
|
||||
|
||||
mutation := rule.Mutation.DeepCopy()
|
||||
|
||||
mutateHandler := mutate.CreateMutateHandler(rule.Name, mutation, patchedResource, ctx, logger)
|
||||
ruleResponse, patchedResource = mutateHandler.Handle()
|
||||
if ruleResponse.Success {
|
||||
|
@ -87,11 +88,12 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
|||
if ruleResponse.Patches == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
logger.V(4).Info("mutate rule applied successfully", "ruleName", rule.Name)
|
||||
}
|
||||
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
||||
incrementAppliedRuleCount(&resp)
|
||||
incrementAppliedRuleCount(resp)
|
||||
}
|
||||
|
||||
resp.PatchedResource = patchedResource
|
||||
|
@ -103,9 +105,11 @@ func incrementAppliedRuleCount(resp *response.EngineResponse) {
|
|||
}
|
||||
|
||||
func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured) {
|
||||
// set policy information
|
||||
if resp == nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp.PolicyResponse.Policy = policy.Name
|
||||
// resource details
|
||||
resp.PolicyResponse.Resource.Name = resource.GetName()
|
||||
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
|
||||
resp.PolicyResponse.Resource.Kind = resource.GetKind()
|
||||
|
@ -113,6 +117,10 @@ func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.Clu
|
|||
}
|
||||
|
||||
func endMutateResultResponse(logger logr.Logger, resp *response.EngineResponse, startTime time.Time) {
|
||||
if resp == nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
||||
logger.V(4).Info("finished processing policy", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "mutationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
}
|
||||
|
|
|
@ -84,9 +84,9 @@ func Test_VariableSubstitutionOverlay(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
policyContext := PolicyContext{
|
||||
policyContext := &PolicyContext{
|
||||
Policy: policy,
|
||||
Context: ctx,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
|
@ -155,9 +155,9 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
|||
err = ctx.AddResource(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
|
||||
policyContext := PolicyContext{
|
||||
policyContext := &PolicyContext{
|
||||
Policy: policy,
|
||||
Context: ctx,
|
||||
JSONContext: ctx,
|
||||
NewResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
expectedErrorStr := "variable request.object.metadata.name1 not resolved at path /spec/name"
|
||||
|
|
|
@ -26,9 +26,6 @@ type PolicyContext struct {
|
|||
// Dynamic client - used by generate
|
||||
Client *client.Client
|
||||
|
||||
// Contexts to store resources
|
||||
Context context.EvalInterface
|
||||
|
||||
// Config handler
|
||||
ExcludeGroupRole []string
|
||||
|
||||
|
|
|
@ -269,10 +269,15 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
|
|||
return nil
|
||||
}
|
||||
func copyConditions(original []kyverno.Condition) []kyverno.Condition {
|
||||
if original == nil || len(original) == 0 {
|
||||
return []kyverno.Condition{}
|
||||
}
|
||||
|
||||
var copy []kyverno.Condition
|
||||
for _, condition := range original {
|
||||
copy = append(copy, *condition.DeepCopy())
|
||||
}
|
||||
|
||||
return copy
|
||||
}
|
||||
|
||||
|
@ -288,10 +293,10 @@ func excludeResource(resource unstructured.Unstructured) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// SkipPolicyApplication returns true:
|
||||
// ManagedPodResource returns true:
|
||||
// - if the policy has auto-gen annotation && resource == Pod
|
||||
// - if the auto-gen contains cronJob && resource == Job
|
||||
func SkipPolicyApplication(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) bool {
|
||||
func ManagedPodResource(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) bool {
|
||||
if policy.HasAutoGenAnnotation() && excludeResource(resource) {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -14,238 +14,192 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/validate"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/resourcecache"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
//Validate applies validation rules from policy on the resource
|
||||
func Validate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||
func Validate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
resp = &response.EngineResponse{}
|
||||
startTime := time.Now()
|
||||
policy := policyContext.Policy
|
||||
newR := policyContext.NewResource
|
||||
oldR := policyContext.OldResource
|
||||
ctx := policyContext.Context
|
||||
admissionInfo := policyContext.AdmissionInfo
|
||||
|
||||
resCache := policyContext.ResourceCache
|
||||
jsonContext := policyContext.JSONContext
|
||||
logger := log.Log.WithName("EngineValidate").WithValues("policy", policy.Name)
|
||||
|
||||
if reflect.DeepEqual(newR, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", oldR.GetKind(), "namespace", oldR.GetNamespace(), "name", oldR.GetName())
|
||||
} else {
|
||||
logger = logger.WithValues("kind", newR.GetKind(), "namespace", newR.GetNamespace(), "name", newR.GetName())
|
||||
}
|
||||
|
||||
logger := buildLogger(policyContext)
|
||||
logger.V(4).Info("start processing", "startTime", startTime)
|
||||
defer func() {
|
||||
if reflect.DeepEqual(resp, response.EngineResponse{}) {
|
||||
return
|
||||
}
|
||||
var resource unstructured.Unstructured
|
||||
if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) {
|
||||
// for delete requests patched resource will be oldR since newR is empty
|
||||
if reflect.DeepEqual(newR, unstructured.Unstructured{}) {
|
||||
resource = oldR
|
||||
} else {
|
||||
resource = newR
|
||||
}
|
||||
}
|
||||
for i := range resp.PolicyResponse.Rules {
|
||||
messageInterface, err := variables.SubstituteVars(logger, ctx, resp.PolicyResponse.Rules[i].Message)
|
||||
if err != nil {
|
||||
logger.V(4).Info("failed to substitute variables", "error", err.Error())
|
||||
continue
|
||||
}
|
||||
resp.PolicyResponse.Rules[i].Message, _ = messageInterface.(string)
|
||||
}
|
||||
resp.PatchedResource = resource
|
||||
startResultResponse(&resp, policy, resource)
|
||||
endResultResponse(logger, &resp, startTime)
|
||||
buildResponse(logger, policyContext, resp, startTime)
|
||||
logger.V(4).Info("finished processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
}()
|
||||
|
||||
// If request is delete, newR will be empty
|
||||
if reflect.DeepEqual(newR, unstructured.Unstructured{}) {
|
||||
return *isRequestDenied(logger, ctx, policy, oldR, admissionInfo, policyContext.ExcludeGroupRole, resCache, jsonContext)
|
||||
}
|
||||
|
||||
if denyResp := isRequestDenied(logger, ctx, policy, newR, admissionInfo, policyContext.ExcludeGroupRole, resCache, jsonContext); !denyResp.IsSuccessful() {
|
||||
return *denyResp
|
||||
}
|
||||
if reflect.DeepEqual(oldR, unstructured.Unstructured{}) {
|
||||
return *validateResource(logger, ctx, policy, newR, admissionInfo, policyContext.ExcludeGroupRole, resCache, jsonContext)
|
||||
}
|
||||
|
||||
oldResponse := validateResource(logger, ctx, policy, oldR, admissionInfo, policyContext.ExcludeGroupRole, resCache, jsonContext)
|
||||
newResponse := validateResource(logger, ctx, policy, newR, admissionInfo, policyContext.ExcludeGroupRole, resCache, jsonContext)
|
||||
if !isSameResponse(oldResponse, newResponse) {
|
||||
return *newResponse
|
||||
}
|
||||
return response.EngineResponse{}
|
||||
return validateResource(logger, policyContext)
|
||||
}
|
||||
|
||||
func startResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, newR unstructured.Unstructured) {
|
||||
// set policy information
|
||||
func buildLogger(ctx *PolicyContext) logr.Logger {
|
||||
logger := log.Log.WithName("EngineValidate").WithValues("policy", ctx.Policy.Name)
|
||||
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||
logger = logger.WithValues("kind", ctx.OldResource.GetKind(), "namespace", ctx.OldResource.GetNamespace(), "name", ctx.OldResource.GetName())
|
||||
} else {
|
||||
logger = logger.WithValues("kind", ctx.NewResource.GetKind(), "namespace", ctx.NewResource.GetNamespace(), "name", ctx.NewResource.GetName())
|
||||
}
|
||||
|
||||
return logger
|
||||
}
|
||||
|
||||
func buildResponse(logger logr.Logger, ctx *PolicyContext, resp *response.EngineResponse, startTime time.Time) {
|
||||
if reflect.DeepEqual(resp, response.EngineResponse{}) {
|
||||
return
|
||||
}
|
||||
|
||||
var resource unstructured.Unstructured
|
||||
if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) {
|
||||
// for delete requests patched resource will be oldResource since newResource is empty
|
||||
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||
resource = ctx.OldResource
|
||||
} else {
|
||||
resource = ctx.NewResource
|
||||
}
|
||||
}
|
||||
|
||||
for i := range resp.PolicyResponse.Rules {
|
||||
messageInterface, err := variables.SubstituteVars(logger, ctx.JSONContext, resp.PolicyResponse.Rules[i].Message)
|
||||
if err != nil {
|
||||
logger.V(4).Info("failed to substitute variables", "error", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
resp.PolicyResponse.Rules[i].Message, _ = messageInterface.(string)
|
||||
}
|
||||
|
||||
resp.PatchedResource = resource
|
||||
setResponse(resp, ctx.Policy, resource, startTime)
|
||||
}
|
||||
|
||||
func setResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, startTime time.Time) {
|
||||
resp.PolicyResponse.Policy = policy.Name
|
||||
// resource details
|
||||
resp.PolicyResponse.Resource.Name = newR.GetName()
|
||||
resp.PolicyResponse.Resource.Namespace = newR.GetNamespace()
|
||||
resp.PolicyResponse.Resource.Kind = newR.GetKind()
|
||||
resp.PolicyResponse.Resource.APIVersion = newR.GetAPIVersion()
|
||||
resp.PolicyResponse.Resource.Name = resource.GetName()
|
||||
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
|
||||
resp.PolicyResponse.Resource.Kind = resource.GetKind()
|
||||
resp.PolicyResponse.Resource.APIVersion = resource.GetAPIVersion()
|
||||
resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
|
||||
}
|
||||
|
||||
func endResultResponse(log logr.Logger, resp *response.EngineResponse, startTime time.Time) {
|
||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
||||
log.V(4).Info("finished processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
}
|
||||
|
||||
func incrementAppliedCount(resp *response.EngineResponse) {
|
||||
// rules applied successfully count
|
||||
resp.PolicyResponse.RulesAppliedCount++
|
||||
}
|
||||
|
||||
func isRequestDenied(log logr.Logger, ctx context.EvalInterface, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, excludeGroupRole []string, resCache resourcecache.ResourceCacheIface, jsonContext *context.Context) *response.EngineResponse {
|
||||
func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineResponse {
|
||||
resp := &response.EngineResponse{}
|
||||
if SkipPolicyApplication(policy, resource) {
|
||||
log.V(5).Info("skip applying policy as direct changes to pods managed by workload controllers are not allowed", "policy", policy.GetName())
|
||||
if ManagedPodResource(ctx.Policy, ctx.NewResource) {
|
||||
log.V(5).Info("skip applying policy as direct changes to pods managed by workload controllers are not allowed", "policy", ctx.Policy.GetName())
|
||||
return resp
|
||||
}
|
||||
excludeResource := []string{}
|
||||
if len(excludeGroupRole) > 0 {
|
||||
excludeResource = excludeGroupRole
|
||||
}
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
|
||||
for _, rule := range ctx.Policy.Spec.Rules {
|
||||
if !rule.HasValidate() {
|
||||
continue
|
||||
}
|
||||
|
||||
// add configmap json data to context
|
||||
if err := AddResourceToContext(log, rule.Context, resCache, jsonContext); err != nil {
|
||||
if err := AddResourceToContext(log, rule.Context, ctx.ResourceCache, ctx.JSONContext); err != nil {
|
||||
log.V(4).Info("cannot add configmaps to context", "reason", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if err := MatchesResourceDescription(resource, rule, admissionInfo, excludeResource); err != nil {
|
||||
log.V(4).Info("resource fails the match description", "reason", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
preconditionsCopy := copyConditions(rule.Conditions)
|
||||
|
||||
if !variables.EvaluateConditions(log, ctx, preconditionsCopy) {
|
||||
log.V(4).Info("resource fails the preconditions")
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.Validation.Deny != nil {
|
||||
denyConditionsCopy := copyConditions(rule.Validation.Deny.Conditions)
|
||||
if len(rule.Validation.Deny.Conditions) == 0 || variables.EvaluateConditions(log, ctx, denyConditionsCopy) {
|
||||
ruleResp := response.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: utils.Validation.String(),
|
||||
Message: rule.Validation.Message,
|
||||
Success: false,
|
||||
}
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResp)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func validateResource(log logr.Logger, ctx context.EvalInterface, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, excludeGroupRole []string, resCache resourcecache.ResourceCacheIface, jsonContext *context.Context) *response.EngineResponse {
|
||||
resp := &response.EngineResponse{}
|
||||
|
||||
if SkipPolicyApplication(policy, resource) {
|
||||
log.V(5).Info("skip applying policy as direct changes to pods managed by workload controllers are not allowed", "policy", policy.GetName())
|
||||
return resp
|
||||
}
|
||||
|
||||
excludeResource := []string{}
|
||||
if len(excludeGroupRole) > 0 {
|
||||
excludeResource = excludeGroupRole
|
||||
}
|
||||
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
if !rule.HasValidate() {
|
||||
continue
|
||||
}
|
||||
|
||||
// check if the resource satisfies the filter conditions defined in the rule
|
||||
if err := MatchesResourceDescription(resource, rule, admissionInfo, excludeResource); err != nil {
|
||||
log.V(4).Info("resource fails the match description", "reason", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// add configmap json data to context
|
||||
if err := AddResourceToContext(log, rule.Context, resCache, jsonContext); err != nil {
|
||||
log.V(4).Info("cannot add configmaps to context", "reason", err.Error())
|
||||
if !matches(log, rule, ctx) {
|
||||
continue
|
||||
}
|
||||
|
||||
// operate on the copy of the conditions, as we perform variable substitution
|
||||
preconditionsCopy := copyConditions(rule.Conditions)
|
||||
|
||||
// evaluate pre-conditions
|
||||
// - handle variable substitutions
|
||||
if !variables.EvaluateConditions(log, ctx, preconditionsCopy) {
|
||||
if !variables.EvaluateConditions(log, ctx.JSONContext, preconditionsCopy) {
|
||||
log.V(4).Info("resource fails the preconditions")
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.Validation.Pattern != nil || rule.Validation.AnyPattern != nil {
|
||||
ruleResponse := validatePatterns(log, ctx, resource, rule)
|
||||
if common.IsConditionalAnchorError(ruleResponse.Message) {
|
||||
continue
|
||||
ruleResponse := validateResourceWithRule(log, ctx, rule)
|
||||
if !common.IsConditionalAnchorError(ruleResponse.Message) {
|
||||
incrementAppliedCount(resp)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
||||
}
|
||||
|
||||
} else if rule.Validation.Deny != nil {
|
||||
|
||||
// validate new resource if available - otherwise old resource
|
||||
resource := ctx.NewResource
|
||||
if reflect.DeepEqual(resource, unstructured.Unstructured{}) {
|
||||
resource = ctx.OldResource
|
||||
}
|
||||
|
||||
denyConditionsCopy := copyConditions(rule.Validation.Deny.Conditions)
|
||||
deny := variables.EvaluateConditions(log, ctx.JSONContext, denyConditionsCopy)
|
||||
ruleResp := response.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: utils.Validation.String(),
|
||||
Message: rule.Validation.Message,
|
||||
Success: !deny,
|
||||
}
|
||||
|
||||
incrementAppliedCount(resp)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResp)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func isSameResponse(oldResponse, newResponse *response.EngineResponse) bool {
|
||||
// if the response are same then return true
|
||||
return isSamePolicyResponse(oldResponse.PolicyResponse, newResponse.PolicyResponse)
|
||||
func validateResourceWithRule(log logr.Logger, ctx *PolicyContext, rule kyverno.Rule) (resp response.RuleResponse) {
|
||||
if reflect.DeepEqual(ctx.OldResource, unstructured.Unstructured{}) {
|
||||
return validatePatterns(log, ctx.JSONContext, ctx.NewResource, rule)
|
||||
}
|
||||
|
||||
oldResp := validatePatterns(log, ctx.JSONContext, ctx.OldResource, rule)
|
||||
newResp := validatePatterns(log, ctx.JSONContext, ctx.NewResource, rule)
|
||||
if !isSameRuleResponse(oldResp, newResp) {
|
||||
return newResp
|
||||
}
|
||||
|
||||
return response.RuleResponse{}
|
||||
}
|
||||
|
||||
func isSamePolicyResponse(oldPolicyRespone, newPolicyResponse response.PolicyResponse) bool {
|
||||
// can skip policy and resource checks as they will be same
|
||||
// compare rules
|
||||
return isSameRules(oldPolicyRespone.Rules, newPolicyResponse.Rules)
|
||||
// matches checks if either the new or old resource satisfies the filter conditions defined in the rule
|
||||
func matches(logger logr.Logger, rule kyverno.Rule, ctx *PolicyContext) bool {
|
||||
err := MatchesResourceDescription(ctx.NewResource, rule, ctx.AdmissionInfo, ctx.ExcludeGroupRole)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ctx.OldResource, unstructured.Unstructured{}) {
|
||||
err := MatchesResourceDescription(ctx.OldResource, rule, ctx.AdmissionInfo, ctx.ExcludeGroupRole)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
logger.V(4).Info("resource fails the match description", "reason", err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
func isSameRules(oldRules []response.RuleResponse, newRules []response.RuleResponse) bool {
|
||||
if len(oldRules) != len(newRules) {
|
||||
func isSameRuleResponse(r1 response.RuleResponse, r2 response.RuleResponse) bool {
|
||||
if r1.Name != r2.Name {
|
||||
return false
|
||||
}
|
||||
// as the rules are always processed in order the indices wil be same
|
||||
for idx, oldrule := range oldRules {
|
||||
newrule := newRules[idx]
|
||||
// Name
|
||||
if oldrule.Name != newrule.Name {
|
||||
return false
|
||||
}
|
||||
// Type
|
||||
if oldrule.Type != newrule.Type {
|
||||
return false
|
||||
}
|
||||
// Message
|
||||
if oldrule.Message != newrule.Message {
|
||||
return false
|
||||
}
|
||||
// skip patches
|
||||
if oldrule.Success != newrule.Success {
|
||||
return false
|
||||
}
|
||||
|
||||
if r1.Type != r2.Type {
|
||||
return false
|
||||
}
|
||||
|
||||
if r1.Message != r2.Message {
|
||||
return false
|
||||
}
|
||||
|
||||
if r1.Success != r2.Success {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -17,13 +17,13 @@ func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Cond
|
|||
return handle.Evaluate(condition.Key, condition.Value)
|
||||
}
|
||||
|
||||
//EvaluateConditions evaluates multiple conditions
|
||||
//EvaluateConditions evaluates multiple conditions as a logical AND operation
|
||||
func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool {
|
||||
// AND the conditions
|
||||
for _, condition := range conditions {
|
||||
if !Evaluate(log, ctx, condition) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = ctx.AddSA(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||
err = ctx.AddServiceAccount(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load UserInfo in context")
|
||||
return nil, err
|
||||
|
@ -124,7 +124,6 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
|||
policyContext := engine.PolicyContext{
|
||||
NewResource: resource,
|
||||
Policy: *policyObj,
|
||||
Context: ctx,
|
||||
AdmissionInfo: gr.Spec.Context.UserRequestInfo,
|
||||
ExcludeGroupRole: c.Config.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: c.Config.ToFilter,
|
||||
|
@ -187,7 +186,6 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
|||
// - - substitute values
|
||||
policy := policyContext.Policy
|
||||
resource := policyContext.NewResource
|
||||
ctx := policyContext.Context
|
||||
|
||||
resCache := policyContext.ResourceCache
|
||||
jsonContext := policyContext.JSONContext
|
||||
|
@ -222,7 +220,7 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
|||
return nil, err
|
||||
}
|
||||
|
||||
genResource, err := applyRule(log, c.client, rule, resource, ctx, policy.Name, gr, processExisting)
|
||||
genResource, err := applyRule(log, c.client, rule, resource, jsonContext, policy.Name, gr, processExisting)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to apply generate rule", "policy", policy.Name,
|
||||
"rule", rule.Name, "resource", resource.GetName())
|
||||
|
|
|
@ -144,7 +144,9 @@ func Command() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool, mutateLogPath string, variablesString string, valuesFile string, namespace string, policyPaths []string) (validateEngineResponses []response.EngineResponse, rc *resultCounts, resources []*unstructured.Unstructured, skippedPolicies []SkippedPolicy, err error) {
|
||||
func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool, mutateLogPath string,
|
||||
variablesString string, valuesFile string, namespace string, policyPaths []string) (validateEngineResponses []*response.EngineResponse, rc *resultCounts, resources []*unstructured.Unstructured, skippedPolicies []SkippedPolicy, err error) {
|
||||
|
||||
kubernetesConfig := genericclioptions.NewConfigFlags(true)
|
||||
|
||||
if valuesFile != "" && variablesString != "" {
|
||||
|
@ -230,8 +232,8 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
|||
}
|
||||
|
||||
rc = &resultCounts{}
|
||||
engineResponses := make([]response.EngineResponse, 0)
|
||||
validateEngineResponses = make([]response.EngineResponse, 0)
|
||||
engineResponses := make([]*response.EngineResponse, 0)
|
||||
validateEngineResponses = make([]*response.EngineResponse, 0)
|
||||
skippedPolicies = make([]SkippedPolicy, 0)
|
||||
|
||||
for _, policy := range mutatedPolicies {
|
||||
|
@ -276,6 +278,7 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
|||
if err != nil {
|
||||
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err)
|
||||
}
|
||||
|
||||
engineResponses = append(engineResponses, ers...)
|
||||
validateEngineResponses = append(validateEngineResponses, validateErs)
|
||||
}
|
||||
|
@ -407,7 +410,7 @@ func getResourceAccordingToResourcePath(resourcePaths []string, cluster bool, po
|
|||
}
|
||||
|
||||
// printReportOrViolation - printing policy report/violations
|
||||
func printReportOrViolation(policyReport bool, validateEngineResponses []response.EngineResponse, rc *resultCounts, resourcePaths []string, resourcesLen int, skippedPolicies []SkippedPolicy) {
|
||||
func printReportOrViolation(policyReport bool, validateEngineResponses []*response.EngineResponse, rc *resultCounts, resourcePaths []string, resourcesLen int, skippedPolicies []SkippedPolicy) {
|
||||
if policyReport {
|
||||
os.Setenv("POLICY-TYPE", pkgCommon.PolicyReport)
|
||||
resps := buildPolicyReports(validateEngineResponses, skippedPolicies)
|
||||
|
@ -435,9 +438,12 @@ func printReportOrViolation(policyReport bool, validateEngineResponses []respons
|
|||
}
|
||||
|
||||
// applyPolicyOnResource - function to apply policy on resource
|
||||
func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured, mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, rc *resultCounts, policyReport bool) ([]response.EngineResponse, response.EngineResponse, error) {
|
||||
func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured,
|
||||
mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string,
|
||||
rc *resultCounts, policyReport bool) ([]*response.EngineResponse, *response.EngineResponse, error) {
|
||||
|
||||
responseError := false
|
||||
engineResponses := make([]response.EngineResponse, 0)
|
||||
engineResponses := make([]*response.EngineResponse, 0)
|
||||
|
||||
resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
|
||||
log.Log.V(3).Info("applying policy on resource", "policy", policy.Name, "resource", resPath)
|
||||
|
@ -457,7 +463,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
|
|||
ctx.AddJSON(jsonData)
|
||||
}
|
||||
|
||||
mutateResponse := engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource, Context: ctx})
|
||||
mutateResponse := engine.Mutate(&engine.PolicyContext{Policy: *policy, NewResource: *resource, JSONContext: ctx})
|
||||
engineResponses = append(engineResponses, mutateResponse)
|
||||
|
||||
if !mutateResponse.IsSuccessful() {
|
||||
|
@ -483,7 +489,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
|
|||
} else {
|
||||
err := printMutatedOutput(mutateLogPath, mutateLogPathIsDir, string(yamlEncodedResource), resource.GetName()+"-mutated")
|
||||
if err != nil {
|
||||
return engineResponses, response.EngineResponse{}, sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
return engineResponses, &response.EngineResponse{}, sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
}
|
||||
fmt.Printf("\n\nMutation:\nMutation has been applied successfully. Check the files.")
|
||||
}
|
||||
|
@ -499,7 +505,8 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
|
|||
}
|
||||
}
|
||||
|
||||
validateResponse := engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource, Context: ctx})
|
||||
policyCtx := &engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource, JSONContext: ctx}
|
||||
validateResponse := engine.Validate(policyCtx)
|
||||
if !policyReport {
|
||||
if !validateResponse.IsSuccessful() {
|
||||
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
const clusterpolicyreport = "clusterpolicyreport"
|
||||
|
||||
// resps is the engine responses generated for a single policy
|
||||
func buildPolicyReports(resps []response.EngineResponse, skippedPolicies []SkippedPolicy) (res []*unstructured.Unstructured) {
|
||||
func buildPolicyReports(resps []*response.EngineResponse, skippedPolicies []SkippedPolicy) (res []*unstructured.Unstructured) {
|
||||
var raw []byte
|
||||
var err error
|
||||
|
||||
|
@ -107,7 +107,7 @@ func buildPolicyReports(resps []response.EngineResponse, skippedPolicies []Skipp
|
|||
|
||||
// buildPolicyResults returns a string-PolicyReportResult map
|
||||
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
|
||||
func buildPolicyResults(resps []response.EngineResponse) map[string][]*report.PolicyReportResult {
|
||||
func buildPolicyResults(resps []*response.EngineResponse) map[string][]*report.PolicyReportResult {
|
||||
results := make(map[string][]*report.PolicyReportResult)
|
||||
infos := policyreport.GeneratePRsFromEngineResponse(resps, log.Log)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
var engineResponses = []response.EngineResponse{
|
||||
var engineResponses = []*response.EngineResponse{
|
||||
{
|
||||
PatchedResource: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
|
|
|
@ -19,7 +19,8 @@ import (
|
|||
)
|
||||
|
||||
// applyPolicy applies policy on a resource
|
||||
func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, logger logr.Logger, excludeGroupRole []string, resCache resourcecache.ResourceCacheIface) (responses []response.EngineResponse) {
|
||||
func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructured,
|
||||
logger logr.Logger, excludeGroupRole []string, resCache resourcecache.ResourceCacheIface) (responses []*response.EngineResponse) {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
name := resource.GetKind() + "/" + resource.GetName()
|
||||
|
@ -31,8 +32,8 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
|||
logger.V(3).Info("applyPolicy", "resource", name, "processingTime", time.Since(startTime).String())
|
||||
}()
|
||||
|
||||
var engineResponses []response.EngineResponse
|
||||
var engineResponseMutation, engineResponseValidation response.EngineResponse
|
||||
var engineResponses []*response.EngineResponse
|
||||
var engineResponseMutation, engineResponseValidation *response.EngineResponse
|
||||
var err error
|
||||
|
||||
ctx := context.NewContext()
|
||||
|
@ -41,20 +42,27 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure
|
|||
logger.Error(err, "enable to add transform resource to ctx")
|
||||
}
|
||||
|
||||
engineResponseMutation, err = mutation(policy, resource, ctx, logger, resCache, ctx)
|
||||
engineResponseMutation, err = mutation(policy, resource, logger, resCache, ctx)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to process mutation rule")
|
||||
}
|
||||
|
||||
engineResponseValidation = engine.Validate(engine.PolicyContext{Policy: policy, Context: ctx, NewResource: resource, ExcludeGroupRole: excludeGroupRole, ResourceCache: resCache, JSONContext: ctx})
|
||||
engineResponseValidation = engine.Validate(&engine.PolicyContext{Policy: policy, NewResource: resource, ExcludeGroupRole: excludeGroupRole, ResourceCache: resCache, JSONContext: ctx})
|
||||
engineResponses = append(engineResponses, mergeRuleRespose(engineResponseMutation, engineResponseValidation))
|
||||
|
||||
return engineResponses
|
||||
}
|
||||
|
||||
func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, ctx context.EvalInterface, log logr.Logger, resCache resourcecache.ResourceCacheIface, jsonContext *context.Context) (response.EngineResponse, error) {
|
||||
func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, log logr.Logger, resCache resourcecache.ResourceCacheIface, jsonContext *context.Context) (*response.EngineResponse, error) {
|
||||
|
||||
engineResponse := engine.Mutate(engine.PolicyContext{Policy: policy, NewResource: resource, Context: ctx, ResourceCache: resCache, JSONContext: jsonContext})
|
||||
policyContext := &engine.PolicyContext{
|
||||
Policy: policy,
|
||||
NewResource: resource,
|
||||
ResourceCache: resCache,
|
||||
JSONContext: jsonContext,
|
||||
}
|
||||
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
if !engineResponse.IsSuccessful() {
|
||||
log.V(4).Info("failed to apply mutation rules; reporting them")
|
||||
return engineResponse, nil
|
||||
|
@ -69,11 +77,11 @@ func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured,
|
|||
}
|
||||
|
||||
// getFailedOverallRuleInfo gets detailed info for over-all mutation failure
|
||||
func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse response.EngineResponse, log logr.Logger) (response.EngineResponse, error) {
|
||||
func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse *response.EngineResponse, log logr.Logger) (*response.EngineResponse, error) {
|
||||
rawResource, err := resource.MarshalJSON()
|
||||
if err != nil {
|
||||
log.Error(err, "failed to marshall resource")
|
||||
return response.EngineResponse{}, err
|
||||
return &response.EngineResponse{}, err
|
||||
}
|
||||
|
||||
// resource does not match so there was a mutation rule violated
|
||||
|
@ -85,14 +93,14 @@ func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse
|
|||
patch, err := jsonpatch.DecodePatch(utils.JoinPatches(patches))
|
||||
if err != nil {
|
||||
log.Error(err, "failed to decode JSON patch", "patches", patches)
|
||||
return response.EngineResponse{}, err
|
||||
return &response.EngineResponse{}, err
|
||||
}
|
||||
|
||||
// apply the patches returned by mutate to the original resource
|
||||
patchedResource, err := patch.Apply(rawResource)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to apply JSON patch", "patches", patches)
|
||||
return response.EngineResponse{}, err
|
||||
return &response.EngineResponse{}, err
|
||||
}
|
||||
|
||||
if !jsonpatch.Equal(patchedResource, rawResource) {
|
||||
|
@ -126,7 +134,7 @@ func extractPatchPath(patches [][]byte, log logr.Logger) string {
|
|||
return strings.Join(resultPath, ";")
|
||||
}
|
||||
|
||||
func mergeRuleRespose(mutation, validation response.EngineResponse) response.EngineResponse {
|
||||
func mergeRuleRespose(mutation, validation *response.EngineResponse) *response.EngineResponse {
|
||||
mutation.PolicyResponse.Rules = append(mutation.PolicyResponse.Rules, validation.PolicyResponse.Rules...)
|
||||
return mutation
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func (pc *PolicyController) applyAndReportPerNamespace(policy *kyverno.ClusterPo
|
|||
return
|
||||
}
|
||||
|
||||
var engineResponses []response.EngineResponse
|
||||
var engineResponses []*response.EngineResponse
|
||||
for _, resource := range rMap {
|
||||
responses := pc.applyPolicy(policy, resource, logger)
|
||||
engineResponses = append(engineResponses, responses...)
|
||||
|
@ -68,7 +68,7 @@ func (pc *PolicyController) applyAndReportPerNamespace(policy *kyverno.ClusterPo
|
|||
pc.report(policy.Name, engineResponses, logger)
|
||||
}
|
||||
|
||||
func (pc *PolicyController) applyPolicy(policy *kyverno.ClusterPolicy, resource unstructured.Unstructured, logger logr.Logger) (engineResponses []response.EngineResponse) {
|
||||
func (pc *PolicyController) applyPolicy(policy *kyverno.ClusterPolicy, resource unstructured.Unstructured, logger logr.Logger) (engineResponses []*response.EngineResponse) {
|
||||
// pre-processing, check if the policy and resource version has been processed before
|
||||
if !pc.rm.ProcessResource(policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion()) {
|
||||
logger.V(4).Info("policy and resource already processed", "policyResourceVersion", policy.ResourceVersion, "resourceResourceVersion", resource.GetResourceVersion(), "kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName())
|
||||
|
@ -86,7 +86,7 @@ func (pc *PolicyController) applyPolicy(policy *kyverno.ClusterPolicy, resource
|
|||
// excludeAutoGenResources filter out the pods / jobs with ownerReference
|
||||
func excludeAutoGenResources(policy kyverno.ClusterPolicy, resourceMap map[string]unstructured.Unstructured, log logr.Logger) {
|
||||
for uid, r := range resourceMap {
|
||||
if engine.SkipPolicyApplication(policy, r) {
|
||||
if engine.ManagedPodResource(policy, r) {
|
||||
log.V(4).Info("exclude resource", "namespace", r.GetNamespace(), "kind", r.GetKind(), "name", r.GetName())
|
||||
delete(resourceMap, uid)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/policyreport"
|
||||
)
|
||||
|
||||
func (pc *PolicyController) report(policy string, engineResponses []response.EngineResponse, logger logr.Logger) {
|
||||
func (pc *PolicyController) report(policy string, engineResponses []*response.EngineResponse, logger logr.Logger) {
|
||||
eventInfos := generateEvents(logger, engineResponses)
|
||||
pc.eventGen.Add(eventInfos...)
|
||||
|
||||
|
@ -22,7 +22,7 @@ func (pc *PolicyController) report(policy string, engineResponses []response.Eng
|
|||
logger.V(4).Info("added a request to RCR generator", "key", info.ToKey())
|
||||
}
|
||||
|
||||
func generateEvents(log logr.Logger, ers []response.EngineResponse) []event.Info {
|
||||
func generateEvents(log logr.Logger, ers []*response.EngineResponse) []event.Info {
|
||||
var eventInfos []event.Info
|
||||
for _, er := range ers {
|
||||
if er.IsSuccessful() {
|
||||
|
@ -33,7 +33,7 @@ func generateEvents(log logr.Logger, ers []response.EngineResponse) []event.Info
|
|||
return eventInfos
|
||||
}
|
||||
|
||||
func generateEventsPerEr(log logr.Logger, er response.EngineResponse) []event.Info {
|
||||
func generateEventsPerEr(log logr.Logger, er *response.EngineResponse) []event.Info {
|
||||
var eventInfos []event.Info
|
||||
|
||||
logger := log.WithValues("policy", er.PolicyResponse.Policy, "kind", er.PolicyResponse.Resource.Kind, "namespace", er.PolicyResponse.Resource.Namespace, "name", er.PolicyResponse.Resource.Name)
|
||||
|
|
|
@ -41,7 +41,7 @@ func generatePolicyReportName(ns string) string {
|
|||
}
|
||||
|
||||
//GeneratePRsFromEngineResponse generate Violations from engine responses
|
||||
func GeneratePRsFromEngineResponse(ers []response.EngineResponse, log logr.Logger) (pvInfos []Info) {
|
||||
func GeneratePRsFromEngineResponse(ers []*response.EngineResponse, log logr.Logger) (pvInfos []Info) {
|
||||
for _, er := range ers {
|
||||
// ignore creation of PV for resources that are yet to be assigned a name
|
||||
if er.PolicyResponse.Resource.Name == "" {
|
||||
|
@ -210,7 +210,7 @@ func calculateSummary(results []*report.PolicyReportResult) (summary report.Poli
|
|||
return
|
||||
}
|
||||
|
||||
func buildPVInfo(er response.EngineResponse) Info {
|
||||
func buildPVInfo(er *response.EngineResponse) Info {
|
||||
info := Info{
|
||||
PolicyName: er.PolicyResponse.Policy,
|
||||
Namespace: er.PatchedResource.GetNamespace(),
|
||||
|
@ -224,7 +224,7 @@ func buildPVInfo(er response.EngineResponse) Info {
|
|||
return info
|
||||
}
|
||||
|
||||
func buildViolatedRules(er response.EngineResponse) []kyverno.ViolatedRule {
|
||||
func buildViolatedRules(er *response.EngineResponse) []kyverno.ViolatedRule {
|
||||
var violatedRules []kyverno.ViolatedRule
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
vrule := kyverno.ViolatedRule{
|
||||
|
|
|
@ -126,9 +126,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
|
|||
t.FailNow()
|
||||
}
|
||||
|
||||
var er response.EngineResponse
|
||||
|
||||
er = engine.Mutate(engine.PolicyContext{Policy: *policy, NewResource: *resource, ExcludeGroupRole: []string{}})
|
||||
er := engine.Mutate(&engine.PolicyContext{Policy: *policy, NewResource: *resource, ExcludeGroupRole: []string{}})
|
||||
t.Log("---Mutation---")
|
||||
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
|
||||
|
@ -138,7 +136,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
|
|||
resource = &er.PatchedResource
|
||||
}
|
||||
|
||||
er = engine.Validate(engine.PolicyContext{Policy: *policy, NewResource: *resource, ExcludeGroupRole: []string{}})
|
||||
er = engine.Validate(&engine.PolicyContext{Policy: *policy, NewResource: *resource, ExcludeGroupRole: []string{}})
|
||||
t.Log("---Validation---")
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)
|
||||
|
||||
|
@ -235,7 +233,7 @@ func validateResponse(t *testing.T, er response.PolicyResponse, expected respons
|
|||
|
||||
// rules
|
||||
if len(er.Rules) != len(expected.Rules) {
|
||||
t.Errorf("rule count error, er.Rules=%d, expected.Rules=%d", len(er.Rules), len(expected.Rules))
|
||||
t.Errorf("rule count error, er.Rules=%v, expected.Rules=%v", er.Rules, expected.Rules)
|
||||
return
|
||||
}
|
||||
if len(er.Rules) == len(expected.Rules) {
|
||||
|
|
|
@ -36,7 +36,7 @@ var operationToPastTense = map[string]string{
|
|||
"test": "tested",
|
||||
}
|
||||
|
||||
func generateAnnotationPatches(engineResponses []response.EngineResponse, log logr.Logger) []byte {
|
||||
func generateAnnotationPatches(engineResponses []*response.EngineResponse, log logr.Logger) []byte {
|
||||
var annotations map[string]string
|
||||
|
||||
for _, er := range engineResponses {
|
||||
|
@ -94,7 +94,7 @@ func generateAnnotationPatches(engineResponses []response.EngineResponse, log lo
|
|||
return patchByte
|
||||
}
|
||||
|
||||
func annotationFromEngineResponses(engineResponses []response.EngineResponse, log logr.Logger) []byte {
|
||||
func annotationFromEngineResponses(engineResponses []*response.EngineResponse, log logr.Logger) []byte {
|
||||
var annotationContent = make(map[string]string)
|
||||
for _, engineResponse := range engineResponses {
|
||||
if !engineResponse.IsSuccessful() {
|
||||
|
|
|
@ -26,8 +26,8 @@ func newPolicyResponse(policy, rule string, patchesStr []string, success bool) r
|
|||
}
|
||||
}
|
||||
|
||||
func newEngineResponse(policy, rule string, patchesStr []string, success bool, annotation map[string]string) response.EngineResponse {
|
||||
return response.EngineResponse{
|
||||
func newEngineResponse(policy, rule string, patchesStr []string, success bool, annotation map[string]string) *response.EngineResponse {
|
||||
return &response.EngineResponse{
|
||||
PatchedResource: unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
|
@ -43,7 +43,7 @@ func Test_empty_annotation(t *testing.T) {
|
|||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, nil)
|
||||
|
||||
annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}`
|
||||
assert.Assert(t, string(annPatches) == expectedPatches)
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func Test_exist_annotation(t *testing.T) {
|
|||
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation)
|
||||
annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
|
||||
expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}`
|
||||
assert.Assert(t, string(annPatches) == expectedPatches)
|
||||
|
@ -68,7 +68,7 @@ func Test_exist_kyverno_annotation(t *testing.T) {
|
|||
|
||||
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation)
|
||||
annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
|
||||
expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}`
|
||||
assert.Assert(t, string(annPatches) == expectedPatches)
|
||||
|
@ -80,11 +80,11 @@ func Test_annotation_nil_patch(t *testing.T) {
|
|||
}
|
||||
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, true, annotation)
|
||||
annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
assert.Assert(t, annPatches == nil)
|
||||
|
||||
engineResponseNew := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{""}, true, annotation)
|
||||
annPatchesNew := generateAnnotationPatches([]response.EngineResponse{engineResponseNew}, log.Log)
|
||||
annPatchesNew := generateAnnotationPatches([]*response.EngineResponse{engineResponseNew}, log.Log)
|
||||
assert.Assert(t, annPatchesNew == nil)
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ func Test_annotation_failed_Patch(t *testing.T) {
|
|||
}
|
||||
|
||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, false, annotation)
|
||||
annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log)
|
||||
annPatches := generateAnnotationPatches([]*response.EngineResponse{engineResponse}, log.Log)
|
||||
|
||||
assert.Assert(t, annPatches == nil)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// isResponseSuccessful return true if all responses are successful
|
||||
func isResponseSuccessful(engineReponses []response.EngineResponse) bool {
|
||||
func isResponseSuccessful(engineReponses []*response.EngineResponse) bool {
|
||||
for _, er := range engineReponses {
|
||||
if !er.IsSuccessful() {
|
||||
return false
|
||||
|
@ -27,7 +27,7 @@ func isResponseSuccessful(engineReponses []response.EngineResponse) bool {
|
|||
|
||||
// returns true -> if there is even one policy that blocks resource request
|
||||
// returns false -> if all the policies are meant to report only, we dont block resource request
|
||||
func toBlockResource(engineReponses []response.EngineResponse, log logr.Logger) bool {
|
||||
func toBlockResource(engineReponses []*response.EngineResponse, log logr.Logger) bool {
|
||||
for _, er := range engineReponses {
|
||||
if !er.IsSuccessful() && er.PolicyResponse.ValidationFailureAction == common.Enforce {
|
||||
log.Info("spec.ValidationFailureAction set to enforce blocking resource request", "policy", er.PolicyResponse.Policy)
|
||||
|
@ -39,7 +39,7 @@ func toBlockResource(engineReponses []response.EngineResponse, log logr.Logger)
|
|||
}
|
||||
|
||||
// getEnforceFailureErrorMsg gets the error messages for failed enforce policy
|
||||
func getEnforceFailureErrorMsg(engineResponses []response.EngineResponse) string {
|
||||
func getEnforceFailureErrorMsg(engineResponses []*response.EngineResponse) string {
|
||||
policyToRule := make(map[string]interface{})
|
||||
var resourceName string
|
||||
for _, er := range engineResponses {
|
||||
|
@ -61,7 +61,7 @@ func getEnforceFailureErrorMsg(engineResponses []response.EngineResponse) string
|
|||
}
|
||||
|
||||
// getErrorMsg gets all failed engine response message
|
||||
func getErrorMsg(engineReponses []response.EngineResponse) string {
|
||||
func getErrorMsg(engineReponses []*response.EngineResponse) string {
|
||||
var str []string
|
||||
var resourceInfo string
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, policies []*kyverno.ClusterPolicy, ctx *context.Context, userRequestInfo kyverno.RequestInfo, dynamicConfig config.Interface) {
|
||||
logger := ws.log.WithValues("action", "generation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
|
||||
logger.V(4).Info("incoming request")
|
||||
var engineResponses []response.EngineResponse
|
||||
var engineResponses []*response.EngineResponse
|
||||
|
||||
if len(policies) == 0 {
|
||||
return
|
||||
|
@ -44,7 +44,6 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
NewResource: new,
|
||||
OldResource: old,
|
||||
AdmissionInfo: userRequestInfo,
|
||||
Context: ctx,
|
||||
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||
ResourceCache: ws.resCache,
|
||||
|
@ -86,7 +85,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
|||
return
|
||||
}
|
||||
|
||||
func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse response.EngineResponse) {
|
||||
func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse *response.EngineResponse) {
|
||||
logger.V(4).Info("querying all generate requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
"policyName": engineResponse.PolicyResponse.Policy,
|
||||
|
@ -110,7 +109,7 @@ func (ws *WebhookServer) deleteGR(logger logr.Logger, engineResponse response.En
|
|||
}
|
||||
|
||||
func applyGenerateRequest(gnGenerator generate.GenerateRequests, userRequestInfo kyverno.RequestInfo,
|
||||
action v1beta1.Operation, engineResponses ...response.EngineResponse) (failedGenerateRequest []generateRequestResponse) {
|
||||
action v1beta1.Operation, engineResponses ...*response.EngineResponse) (failedGenerateRequest []generateRequestResponse) {
|
||||
|
||||
for _, er := range engineResponses {
|
||||
gr := transform(userRequestInfo, er)
|
||||
|
@ -122,8 +121,7 @@ func applyGenerateRequest(gnGenerator generate.GenerateRequests, userRequestInfo
|
|||
return
|
||||
}
|
||||
|
||||
func transform(userRequestInfo kyverno.RequestInfo, er response.EngineResponse) kyverno.GenerateRequestSpec {
|
||||
|
||||
func transform(userRequestInfo kyverno.RequestInfo, er *response.EngineResponse) kyverno.GenerateRequestSpec {
|
||||
gr := kyverno.GenerateRequestSpec{
|
||||
Policy: er.PolicyResponse.Policy,
|
||||
Resource: kyverno.ResourceSpec{
|
||||
|
@ -135,11 +133,12 @@ func transform(userRequestInfo kyverno.RequestInfo, er response.EngineResponse)
|
|||
UserRequestInfo: userRequestInfo,
|
||||
},
|
||||
}
|
||||
|
||||
return gr
|
||||
}
|
||||
|
||||
type generateStats struct {
|
||||
resp response.EngineResponse
|
||||
resp *response.EngineResponse
|
||||
}
|
||||
|
||||
func (gs generateStats) PolicyName() string {
|
||||
|
|
|
@ -36,11 +36,10 @@ func (ws *WebhookServer) HandleMutation(
|
|||
logger := ws.log.WithValues("action", "mutate", "resource", resourceName, "operation", request.Operation)
|
||||
|
||||
var patches [][]byte
|
||||
var engineResponses []response.EngineResponse
|
||||
policyContext := engine.PolicyContext{
|
||||
var engineResponses []*response.EngineResponse
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: resource,
|
||||
AdmissionInfo: userRequestInfo,
|
||||
Context: ctx,
|
||||
ExcludeGroupRole: ws.configHandler.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||
ResourceCache: ws.resCache,
|
||||
|
@ -117,7 +116,7 @@ func (ws *WebhookServer) HandleMutation(
|
|||
}
|
||||
|
||||
type mutateStats struct {
|
||||
resp response.EngineResponse
|
||||
resp *response.EngineResponse
|
||||
namespace string
|
||||
}
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ import (
|
|||
|
||||
func Test_GenerateStats(t *testing.T) {
|
||||
testCase := struct {
|
||||
generateStats []response.EngineResponse
|
||||
generateStats []*response.EngineResponse
|
||||
expectedOutput []byte
|
||||
}{
|
||||
expectedOutput: []byte(`{"policy1":{"averageExecutionTime":"494ns","rulesFailedCount":1,"rulesAppliedCount":1,"ruleStatus":[{"ruleName":"rule5","averageExecutionTime":"243ns","appliedCount":1},{"ruleName":"rule6","averageExecutionTime":"251ns","failedCount":1}]},"policy2":{"averageExecutionTime":"433ns","rulesFailedCount":1,"rulesAppliedCount":1,"ruleStatus":[{"ruleName":"rule5","averageExecutionTime":"222ns","appliedCount":1},{"ruleName":"rule6","averageExecutionTime":"211ns","failedCount":1}]}}`),
|
||||
generateStats: []response.EngineResponse{
|
||||
generateStats: []*response.EngineResponse{
|
||||
{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: "policy1",
|
||||
|
@ -79,11 +79,11 @@ func Test_GenerateStats(t *testing.T) {
|
|||
|
||||
func Test_MutateStats(t *testing.T) {
|
||||
testCase := struct {
|
||||
mutateStats []response.EngineResponse
|
||||
mutateStats []*response.EngineResponse
|
||||
expectedOutput []byte
|
||||
}{
|
||||
expectedOutput: []byte(`{"policy1":{"averageExecutionTime":"494ns","rulesFailedCount":1,"rulesAppliedCount":1,"resourcesMutatedCount":1,"ruleStatus":[{"ruleName":"rule1","averageExecutionTime":"243ns","appliedCount":1,"resourcesMutatedCount":1},{"ruleName":"rule2","averageExecutionTime":"251ns","failedCount":1}]},"policy2":{"averageExecutionTime":"433ns","rulesFailedCount":1,"rulesAppliedCount":1,"resourcesMutatedCount":1,"ruleStatus":[{"ruleName":"rule1","averageExecutionTime":"222ns","appliedCount":1,"resourcesMutatedCount":1},{"ruleName":"rule2","averageExecutionTime":"211ns","failedCount":1}]}}`),
|
||||
mutateStats: []response.EngineResponse{
|
||||
mutateStats: []*response.EngineResponse{
|
||||
{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: "policy1",
|
||||
|
@ -145,11 +145,11 @@ func Test_MutateStats(t *testing.T) {
|
|||
|
||||
func Test_ValidateStats(t *testing.T) {
|
||||
testCase := struct {
|
||||
validateStats []response.EngineResponse
|
||||
validateStats []*response.EngineResponse
|
||||
expectedOutput []byte
|
||||
}{
|
||||
expectedOutput: []byte(`{"policy1":{"averageExecutionTime":"494ns","rulesFailedCount":1,"rulesAppliedCount":1,"resourcesBlockedCount":1,"ruleStatus":[{"ruleName":"rule3","averageExecutionTime":"243ns","appliedCount":1},{"ruleName":"rule4","averageExecutionTime":"251ns","failedCount":1,"resourcesBlockedCount":1}]},"policy2":{"averageExecutionTime":"433ns","rulesFailedCount":1,"rulesAppliedCount":1,"ruleStatus":[{"ruleName":"rule3","averageExecutionTime":"222ns","appliedCount":1},{"ruleName":"rule4","averageExecutionTime":"211ns","failedCount":1}]}}`),
|
||||
validateStats: []response.EngineResponse{
|
||||
validateStats: []*response.EngineResponse{
|
||||
{
|
||||
PolicyResponse: response.PolicyResponse{
|
||||
Policy: "policy1",
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
//generateEvents generates event info for the engine responses
|
||||
func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate bool, log logr.Logger) []event.Info {
|
||||
func generateEvents(engineResponses []*response.EngineResponse, blocked, onUpdate bool, log logr.Logger) []event.Info {
|
||||
var events []event.Info
|
||||
|
||||
// - Admission-Response is SUCCESS
|
||||
|
|
|
@ -330,7 +330,7 @@ func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1
|
|||
if err != nil {
|
||||
logger.Error(err, "failed to load userInfo in context")
|
||||
}
|
||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
||||
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load service account in context")
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
|||
if err != nil {
|
||||
logger.Error(err, "failed to load userInfo in context")
|
||||
}
|
||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
||||
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to load service account in context")
|
||||
}
|
||||
|
|
|
@ -166,7 +166,7 @@ func (h *auditHandler) process(request *v1beta1.AdmissionRequest) error {
|
|||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load userInfo in context")
|
||||
}
|
||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
||||
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load service account in context")
|
||||
}
|
||||
|
|
|
@ -68,10 +68,9 @@ func HandleValidation(
|
|||
return true, ""
|
||||
}
|
||||
|
||||
policyContext := engine.PolicyContext{
|
||||
policyContext := &engine.PolicyContext{
|
||||
NewResource: newR,
|
||||
OldResource: oldR,
|
||||
Context: ctx,
|
||||
AdmissionInfo: userRequestInfo,
|
||||
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
||||
ExcludeResourceFunc: dynamicConfig.ToFilter,
|
||||
|
@ -79,7 +78,7 @@ func HandleValidation(
|
|||
JSONContext: ctx,
|
||||
}
|
||||
|
||||
var engineResponses []response.EngineResponse
|
||||
var engineResponses []*response.EngineResponse
|
||||
for _, policy := range policies {
|
||||
|
||||
logger.V(3).Info("evaluating policy", "policy", policy.Name)
|
||||
|
@ -152,7 +151,7 @@ func buildDeletionPrInfo(oldR unstructured.Unstructured) policyreport.Info {
|
|||
}
|
||||
|
||||
type validateStats struct {
|
||||
resp response.EngineResponse
|
||||
resp *response.EngineResponse
|
||||
namespace string
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ expected:
|
|||
kind: Pod
|
||||
apiVersion: v1
|
||||
# this is set to pass resource NS check
|
||||
# actual valiation is defined through rule success=false
|
||||
# actual validation is defined through rule success=false
|
||||
namespace: 'default'
|
||||
name: myapp-pod
|
||||
rules:
|
||||
|
|
Loading…
Reference in a new issue