mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +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
|
//Interface to manage context operations
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
//AddJSON merges the json with context
|
|
||||||
|
// AddJSON merges the json with context
|
||||||
AddJSON(dataRaw []byte) error
|
AddJSON(dataRaw []byte) error
|
||||||
//AddResource merges resource json under request.object
|
|
||||||
|
// AddResource merges resource json under request.object
|
||||||
AddResource(dataRaw []byte) error
|
AddResource(dataRaw []byte) error
|
||||||
//AddUserInfo merges userInfo json under kyverno.userInfo
|
|
||||||
|
// AddUserInfo merges userInfo json under kyverno.userInfo
|
||||||
AddUserInfo(userInfo kyverno.UserInfo) error
|
AddUserInfo(userInfo kyverno.UserInfo) error
|
||||||
//AddSA merges serrviceaccount
|
|
||||||
AddSA(userName string) error
|
// AddServiceAccount merges ServiceAccount types
|
||||||
|
AddServiceAccount(userName string) error
|
||||||
|
|
||||||
EvalInterface
|
EvalInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +131,8 @@ func (ctx *Context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
|
||||||
return ctx.AddJSON(objRaw)
|
return ctx.AddJSON(objRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddSA removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
|
//AddServiceAccount removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
|
||||||
func (ctx *Context) AddSA(userName string) error {
|
func (ctx *Context) AddServiceAccount(userName string) error {
|
||||||
saPrefix := "system:serviceaccount:"
|
saPrefix := "system:serviceaccount:"
|
||||||
var sa string
|
var sa string
|
||||||
saName := ""
|
saName := ""
|
||||||
|
|
|
@ -93,7 +93,7 @@ func Test_addResourceAndUserContext(t *testing.T) {
|
||||||
t.Error("exected result does not match")
|
t.Error("exected result does not match")
|
||||||
}
|
}
|
||||||
// Add service account Name
|
// Add service account Name
|
||||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,16 @@ import (
|
||||||
// 1. validate variables to be substitute in the general ruleInfo (match,exclude,condition)
|
// 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
|
// - 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
|
// 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)
|
return filterRules(policyContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterRules(policyContext PolicyContext) response.EngineResponse {
|
func filterRules(policyContext PolicyContext) *response.EngineResponse {
|
||||||
kind := policyContext.NewResource.GetKind()
|
kind := policyContext.NewResource.GetKind()
|
||||||
name := policyContext.NewResource.GetName()
|
name := policyContext.NewResource.GetName()
|
||||||
namespace := policyContext.NewResource.GetNamespace()
|
namespace := policyContext.NewResource.GetNamespace()
|
||||||
|
|
||||||
resp := response.EngineResponse{
|
resp := &response.EngineResponse{
|
||||||
PolicyResponse: response.PolicyResponse{
|
PolicyResponse: response.PolicyResponse{
|
||||||
Policy: policyContext.Policy.Name,
|
Policy: policyContext.Policy.Name,
|
||||||
Resource: response.ResourceSpec{
|
Resource: response.ResourceSpec{
|
||||||
|
@ -57,7 +57,7 @@ func filterRule(rule kyverno.Rule, policyContext PolicyContext) *response.RuleRe
|
||||||
newResource := policyContext.NewResource
|
newResource := policyContext.NewResource
|
||||||
oldResource := policyContext.OldResource
|
oldResource := policyContext.OldResource
|
||||||
admissionInfo := policyContext.AdmissionInfo
|
admissionInfo := policyContext.AdmissionInfo
|
||||||
ctx := policyContext.Context
|
ctx := policyContext.JSONContext
|
||||||
resCache := policyContext.ResourceCache
|
resCache := policyContext.ResourceCache
|
||||||
jsonContext := policyContext.JSONContext
|
jsonContext := policyContext.JSONContext
|
||||||
excludeGroupRole := policyContext.ExcludeGroupRole
|
excludeGroupRole := policyContext.ExcludeGroupRole
|
||||||
|
|
|
@ -22,11 +22,12 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mutate performs mutation. Overlay first and then mutation patches
|
// 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()
|
startTime := time.Now()
|
||||||
policy := policyContext.Policy
|
policy := policyContext.Policy
|
||||||
patchedResource := policyContext.NewResource
|
patchedResource := policyContext.NewResource
|
||||||
ctx := policyContext.Context
|
ctx := policyContext.JSONContext
|
||||||
|
|
||||||
resCache := policyContext.ResourceCache
|
resCache := policyContext.ResourceCache
|
||||||
jsonContext := policyContext.JSONContext
|
jsonContext := policyContext.JSONContext
|
||||||
|
@ -35,10 +36,10 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||||
|
|
||||||
logger.V(4).Info("start policy processing", "startTime", startTime)
|
logger.V(4).Info("start policy processing", "startTime", startTime)
|
||||||
|
|
||||||
startMutateResultResponse(&resp, policy, patchedResource)
|
startMutateResultResponse(resp, policy, patchedResource)
|
||||||
defer endMutateResultResponse(logger, &resp, startTime)
|
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())
|
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
|
resp.PatchedResource = patchedResource
|
||||||
return
|
return
|
||||||
|
@ -58,6 +59,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||||
if len(policyContext.ExcludeGroupRole) > 0 {
|
if len(policyContext.ExcludeGroupRole) > 0 {
|
||||||
excludeResource = policyContext.ExcludeGroupRole
|
excludeResource = policyContext.ExcludeGroupRole
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := MatchesResourceDescription(patchedResource, rule, policyContext.AdmissionInfo, excludeResource); err != nil {
|
if err := MatchesResourceDescription(patchedResource, rule, policyContext.AdmissionInfo, excludeResource); err != nil {
|
||||||
logger.V(3).Info("resource not matched", "reason", err.Error())
|
logger.V(3).Info("resource not matched", "reason", err.Error())
|
||||||
continue
|
continue
|
||||||
|
@ -79,7 +81,6 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mutation := rule.Mutation.DeepCopy()
|
mutation := rule.Mutation.DeepCopy()
|
||||||
|
|
||||||
mutateHandler := mutate.CreateMutateHandler(rule.Name, mutation, patchedResource, ctx, logger)
|
mutateHandler := mutate.CreateMutateHandler(rule.Name, mutation, patchedResource, ctx, logger)
|
||||||
ruleResponse, patchedResource = mutateHandler.Handle()
|
ruleResponse, patchedResource = mutateHandler.Handle()
|
||||||
if ruleResponse.Success {
|
if ruleResponse.Success {
|
||||||
|
@ -87,11 +88,12 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) {
|
||||||
if ruleResponse.Patches == nil {
|
if ruleResponse.Patches == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.V(4).Info("mutate rule applied successfully", "ruleName", rule.Name)
|
logger.V(4).Info("mutate rule applied successfully", "ruleName", rule.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
||||||
incrementAppliedRuleCount(&resp)
|
incrementAppliedRuleCount(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.PatchedResource = patchedResource
|
resp.PatchedResource = patchedResource
|
||||||
|
@ -103,9 +105,11 @@ func incrementAppliedRuleCount(resp *response.EngineResponse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured) {
|
func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured) {
|
||||||
// set policy information
|
if resp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp.PolicyResponse.Policy = policy.Name
|
resp.PolicyResponse.Policy = policy.Name
|
||||||
// resource details
|
|
||||||
resp.PolicyResponse.Resource.Name = resource.GetName()
|
resp.PolicyResponse.Resource.Name = resource.GetName()
|
||||||
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
|
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
|
||||||
resp.PolicyResponse.Resource.Kind = resource.GetKind()
|
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) {
|
func endMutateResultResponse(logger logr.Logger, resp *response.EngineResponse, startTime time.Time) {
|
||||||
|
if resp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
||||||
logger.V(4).Info("finished processing policy", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "mutationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
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 {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
policyContext := PolicyContext{
|
policyContext := &PolicyContext{
|
||||||
Policy: policy,
|
Policy: policy,
|
||||||
Context: ctx,
|
JSONContext: ctx,
|
||||||
NewResource: *resourceUnstructured}
|
NewResource: *resourceUnstructured}
|
||||||
er := Mutate(policyContext)
|
er := Mutate(policyContext)
|
||||||
t.Log(string(expectedPatch))
|
t.Log(string(expectedPatch))
|
||||||
|
@ -155,9 +155,9 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
||||||
err = ctx.AddResource(resourceRaw)
|
err = ctx.AddResource(resourceRaw)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
policyContext := PolicyContext{
|
policyContext := &PolicyContext{
|
||||||
Policy: policy,
|
Policy: policy,
|
||||||
Context: ctx,
|
JSONContext: ctx,
|
||||||
NewResource: *resourceUnstructured}
|
NewResource: *resourceUnstructured}
|
||||||
er := Mutate(policyContext)
|
er := Mutate(policyContext)
|
||||||
expectedErrorStr := "variable request.object.metadata.name1 not resolved at path /spec/name"
|
expectedErrorStr := "variable request.object.metadata.name1 not resolved at path /spec/name"
|
||||||
|
|
|
@ -26,9 +26,6 @@ type PolicyContext struct {
|
||||||
// Dynamic client - used by generate
|
// Dynamic client - used by generate
|
||||||
Client *client.Client
|
Client *client.Client
|
||||||
|
|
||||||
// Contexts to store resources
|
|
||||||
Context context.EvalInterface
|
|
||||||
|
|
||||||
// Config handler
|
// Config handler
|
||||||
ExcludeGroupRole []string
|
ExcludeGroupRole []string
|
||||||
|
|
||||||
|
|
|
@ -269,10 +269,15 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func copyConditions(original []kyverno.Condition) []kyverno.Condition {
|
func copyConditions(original []kyverno.Condition) []kyverno.Condition {
|
||||||
|
if original == nil || len(original) == 0 {
|
||||||
|
return []kyverno.Condition{}
|
||||||
|
}
|
||||||
|
|
||||||
var copy []kyverno.Condition
|
var copy []kyverno.Condition
|
||||||
for _, condition := range original {
|
for _, condition := range original {
|
||||||
copy = append(copy, *condition.DeepCopy())
|
copy = append(copy, *condition.DeepCopy())
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +293,10 @@ func excludeResource(resource unstructured.Unstructured) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SkipPolicyApplication returns true:
|
// ManagedPodResource returns true:
|
||||||
// - if the policy has auto-gen annotation && resource == Pod
|
// - if the policy has auto-gen annotation && resource == Pod
|
||||||
// - if the auto-gen contains cronJob && resource == Job
|
// - 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) {
|
if policy.HasAutoGenAnnotation() && excludeResource(resource) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,238 +14,192 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/validate"
|
"github.com/kyverno/kyverno/pkg/engine/validate"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||||
"github.com/kyverno/kyverno/pkg/resourcecache"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Validate applies validation rules from policy on the resource
|
//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()
|
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)
|
logger.V(4).Info("start processing", "startTime", startTime)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
buildResponse(logger, policyContext, resp, startTime)
|
||||||
|
logger.V(4).Info("finished processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return validateResource(logger, policyContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
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{}) {
|
if reflect.DeepEqual(resp, response.EngineResponse{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var resource unstructured.Unstructured
|
var resource unstructured.Unstructured
|
||||||
if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) {
|
if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) {
|
||||||
// for delete requests patched resource will be oldR since newR is empty
|
// for delete requests patched resource will be oldResource since newResource is empty
|
||||||
if reflect.DeepEqual(newR, unstructured.Unstructured{}) {
|
if reflect.DeepEqual(ctx.NewResource, unstructured.Unstructured{}) {
|
||||||
resource = oldR
|
resource = ctx.OldResource
|
||||||
} else {
|
} else {
|
||||||
resource = newR
|
resource = ctx.NewResource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range resp.PolicyResponse.Rules {
|
for i := range resp.PolicyResponse.Rules {
|
||||||
messageInterface, err := variables.SubstituteVars(logger, ctx, resp.PolicyResponse.Rules[i].Message)
|
messageInterface, err := variables.SubstituteVars(logger, ctx.JSONContext, resp.PolicyResponse.Rules[i].Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.V(4).Info("failed to substitute variables", "error", err.Error())
|
logger.V(4).Info("failed to substitute variables", "error", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.PolicyResponse.Rules[i].Message, _ = messageInterface.(string)
|
resp.PolicyResponse.Rules[i].Message, _ = messageInterface.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.PatchedResource = resource
|
resp.PatchedResource = resource
|
||||||
startResultResponse(&resp, policy, resource)
|
setResponse(resp, ctx.Policy, resource, startTime)
|
||||||
endResultResponse(logger, &resp, startTime)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// 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{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func startResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, newR unstructured.Unstructured) {
|
func setResponse(resp *response.EngineResponse, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, startTime time.Time) {
|
||||||
// set policy information
|
|
||||||
resp.PolicyResponse.Policy = policy.Name
|
resp.PolicyResponse.Policy = policy.Name
|
||||||
// resource details
|
resp.PolicyResponse.Resource.Name = resource.GetName()
|
||||||
resp.PolicyResponse.Resource.Name = newR.GetName()
|
resp.PolicyResponse.Resource.Namespace = resource.GetNamespace()
|
||||||
resp.PolicyResponse.Resource.Namespace = newR.GetNamespace()
|
resp.PolicyResponse.Resource.Kind = resource.GetKind()
|
||||||
resp.PolicyResponse.Resource.Kind = newR.GetKind()
|
resp.PolicyResponse.Resource.APIVersion = resource.GetAPIVersion()
|
||||||
resp.PolicyResponse.Resource.APIVersion = newR.GetAPIVersion()
|
|
||||||
resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
|
resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction
|
||||||
}
|
|
||||||
|
|
||||||
func endResultResponse(log logr.Logger, resp *response.EngineResponse, startTime time.Time) {
|
|
||||||
resp.PolicyResponse.ProcessingTime = time.Since(startTime)
|
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) {
|
func incrementAppliedCount(resp *response.EngineResponse) {
|
||||||
// rules applied successfully count
|
|
||||||
resp.PolicyResponse.RulesAppliedCount++
|
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{}
|
resp := &response.EngineResponse{}
|
||||||
if SkipPolicyApplication(policy, resource) {
|
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", policy.GetName())
|
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
|
return resp
|
||||||
}
|
}
|
||||||
excludeResource := []string{}
|
|
||||||
if len(excludeGroupRole) > 0 {
|
for _, rule := range ctx.Policy.Spec.Rules {
|
||||||
excludeResource = excludeGroupRole
|
|
||||||
}
|
|
||||||
for _, rule := range policy.Spec.Rules {
|
|
||||||
if !rule.HasValidate() {
|
if !rule.HasValidate() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// add configmap json data to context
|
// 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())
|
log.V(4).Info("cannot add configmaps to context", "reason", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := MatchesResourceDescription(resource, rule, admissionInfo, excludeResource); err != nil {
|
if !matches(log, rule, ctx) {
|
||||||
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())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// operate on the copy of the conditions, as we perform variable substitution
|
// operate on the copy of the conditions, as we perform variable substitution
|
||||||
preconditionsCopy := copyConditions(rule.Conditions)
|
preconditionsCopy := copyConditions(rule.Conditions)
|
||||||
|
|
||||||
// evaluate pre-conditions
|
// evaluate pre-conditions
|
||||||
// - handle variable substitutions
|
// - handle variable substitutions
|
||||||
if !variables.EvaluateConditions(log, ctx, preconditionsCopy) {
|
if !variables.EvaluateConditions(log, ctx.JSONContext, preconditionsCopy) {
|
||||||
log.V(4).Info("resource fails the preconditions")
|
log.V(4).Info("resource fails the preconditions")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if rule.Validation.Pattern != nil || rule.Validation.AnyPattern != nil {
|
if rule.Validation.Pattern != nil || rule.Validation.AnyPattern != nil {
|
||||||
ruleResponse := validatePatterns(log, ctx, resource, rule)
|
ruleResponse := validateResourceWithRule(log, ctx, rule)
|
||||||
if common.IsConditionalAnchorError(ruleResponse.Message) {
|
if !common.IsConditionalAnchorError(ruleResponse.Message) {
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
incrementAppliedCount(resp)
|
incrementAppliedCount(resp)
|
||||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse)
|
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, ruleResp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSameResponse(oldResponse, newResponse *response.EngineResponse) bool {
|
func validateResourceWithRule(log logr.Logger, ctx *PolicyContext, rule kyverno.Rule) (resp response.RuleResponse) {
|
||||||
// if the response are same then return true
|
if reflect.DeepEqual(ctx.OldResource, unstructured.Unstructured{}) {
|
||||||
return isSamePolicyResponse(oldResponse.PolicyResponse, newResponse.PolicyResponse)
|
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 {
|
// matches checks if either the new or old resource satisfies the filter conditions defined in the rule
|
||||||
// can skip policy and resource checks as they will be same
|
func matches(logger logr.Logger, rule kyverno.Rule, ctx *PolicyContext) bool {
|
||||||
// compare rules
|
err := MatchesResourceDescription(ctx.NewResource, rule, ctx.AdmissionInfo, ctx.ExcludeGroupRole)
|
||||||
return isSameRules(oldPolicyRespone.Rules, newPolicyResponse.Rules)
|
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 {
|
func isSameRuleResponse(r1 response.RuleResponse, r2 response.RuleResponse) bool {
|
||||||
if len(oldRules) != len(newRules) {
|
if r1.Name != r2.Name {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// as the rules are always processed in order the indices wil be same
|
|
||||||
for idx, oldrule := range oldRules {
|
if r1.Type != r2.Type {
|
||||||
newrule := newRules[idx]
|
|
||||||
// Name
|
|
||||||
if oldrule.Name != newrule.Name {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Type
|
|
||||||
if oldrule.Type != newrule.Type {
|
if r1.Message != r2.Message {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Message
|
|
||||||
if oldrule.Message != newrule.Message {
|
if r1.Success != r2.Success {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// skip patches
|
|
||||||
if oldrule.Success != newrule.Success {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
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)
|
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 {
|
func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool {
|
||||||
// AND the conditions
|
|
||||||
for _, condition := range conditions {
|
for _, condition := range conditions {
|
||||||
if !Evaluate(log, ctx, condition) {
|
if !Evaluate(log, ctx, condition) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.AddSA(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
err = ctx.AddServiceAccount(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to load UserInfo in context")
|
logger.Error(err, "failed to load UserInfo in context")
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -124,7 +124,6 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
|
||||||
policyContext := engine.PolicyContext{
|
policyContext := engine.PolicyContext{
|
||||||
NewResource: resource,
|
NewResource: resource,
|
||||||
Policy: *policyObj,
|
Policy: *policyObj,
|
||||||
Context: ctx,
|
|
||||||
AdmissionInfo: gr.Spec.Context.UserRequestInfo,
|
AdmissionInfo: gr.Spec.Context.UserRequestInfo,
|
||||||
ExcludeGroupRole: c.Config.GetExcludeGroupRole(),
|
ExcludeGroupRole: c.Config.GetExcludeGroupRole(),
|
||||||
ExcludeResourceFunc: c.Config.ToFilter,
|
ExcludeResourceFunc: c.Config.ToFilter,
|
||||||
|
@ -187,7 +186,6 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
||||||
// - - substitute values
|
// - - substitute values
|
||||||
policy := policyContext.Policy
|
policy := policyContext.Policy
|
||||||
resource := policyContext.NewResource
|
resource := policyContext.NewResource
|
||||||
ctx := policyContext.Context
|
|
||||||
|
|
||||||
resCache := policyContext.ResourceCache
|
resCache := policyContext.ResourceCache
|
||||||
jsonContext := policyContext.JSONContext
|
jsonContext := policyContext.JSONContext
|
||||||
|
@ -222,7 +220,7 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
log.Error(err, "failed to apply generate rule", "policy", policy.Name,
|
log.Error(err, "failed to apply generate rule", "policy", policy.Name,
|
||||||
"rule", rule.Name, "resource", resource.GetName())
|
"rule", rule.Name, "resource", resource.GetName())
|
||||||
|
|
|
@ -144,7 +144,9 @@ func Command() *cobra.Command {
|
||||||
return cmd
|
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)
|
kubernetesConfig := genericclioptions.NewConfigFlags(true)
|
||||||
|
|
||||||
if valuesFile != "" && variablesString != "" {
|
if valuesFile != "" && variablesString != "" {
|
||||||
|
@ -230,8 +232,8 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = &resultCounts{}
|
rc = &resultCounts{}
|
||||||
engineResponses := make([]response.EngineResponse, 0)
|
engineResponses := make([]*response.EngineResponse, 0)
|
||||||
validateEngineResponses = make([]response.EngineResponse, 0)
|
validateEngineResponses = make([]*response.EngineResponse, 0)
|
||||||
skippedPolicies = make([]SkippedPolicy, 0)
|
skippedPolicies = make([]SkippedPolicy, 0)
|
||||||
|
|
||||||
for _, policy := range mutatedPolicies {
|
for _, policy := range mutatedPolicies {
|
||||||
|
@ -276,6 +278,7 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
|
||||||
if err != nil {
|
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)
|
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...)
|
engineResponses = append(engineResponses, ers...)
|
||||||
validateEngineResponses = append(validateEngineResponses, validateErs)
|
validateEngineResponses = append(validateEngineResponses, validateErs)
|
||||||
}
|
}
|
||||||
|
@ -407,7 +410,7 @@ func getResourceAccordingToResourcePath(resourcePaths []string, cluster bool, po
|
||||||
}
|
}
|
||||||
|
|
||||||
// printReportOrViolation - printing policy report/violations
|
// 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 {
|
if policyReport {
|
||||||
os.Setenv("POLICY-TYPE", pkgCommon.PolicyReport)
|
os.Setenv("POLICY-TYPE", pkgCommon.PolicyReport)
|
||||||
resps := buildPolicyReports(validateEngineResponses, skippedPolicies)
|
resps := buildPolicyReports(validateEngineResponses, skippedPolicies)
|
||||||
|
@ -435,9 +438,12 @@ func printReportOrViolation(policyReport bool, validateEngineResponses []respons
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyPolicyOnResource - function to apply policy on resource
|
// 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
|
responseError := false
|
||||||
engineResponses := make([]response.EngineResponse, 0)
|
engineResponses := make([]*response.EngineResponse, 0)
|
||||||
|
|
||||||
resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
|
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)
|
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)
|
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)
|
engineResponses = append(engineResponses, mutateResponse)
|
||||||
|
|
||||||
if !mutateResponse.IsSuccessful() {
|
if !mutateResponse.IsSuccessful() {
|
||||||
|
@ -483,7 +489,7 @@ func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
|
||||||
} else {
|
} else {
|
||||||
err := printMutatedOutput(mutateLogPath, mutateLogPathIsDir, string(yamlEncodedResource), resource.GetName()+"-mutated")
|
err := printMutatedOutput(mutateLogPath, mutateLogPathIsDir, string(yamlEncodedResource), resource.GetName()+"-mutated")
|
||||||
if err != nil {
|
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.")
|
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 !policyReport {
|
||||||
if !validateResponse.IsSuccessful() {
|
if !validateResponse.IsSuccessful() {
|
||||||
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
|
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
const clusterpolicyreport = "clusterpolicyreport"
|
const clusterpolicyreport = "clusterpolicyreport"
|
||||||
|
|
||||||
// resps is the engine responses generated for a single policy
|
// 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 raw []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ func buildPolicyReports(resps []response.EngineResponse, skippedPolicies []Skipp
|
||||||
|
|
||||||
// buildPolicyResults returns a string-PolicyReportResult map
|
// buildPolicyResults returns a string-PolicyReportResult map
|
||||||
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
|
// 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)
|
results := make(map[string][]*report.PolicyReportResult)
|
||||||
infos := policyreport.GeneratePRsFromEngineResponse(resps, log.Log)
|
infos := policyreport.GeneratePRsFromEngineResponse(resps, log.Log)
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
)
|
)
|
||||||
|
|
||||||
var engineResponses = []response.EngineResponse{
|
var engineResponses = []*response.EngineResponse{
|
||||||
{
|
{
|
||||||
PatchedResource: unstructured.Unstructured{
|
PatchedResource: unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
|
|
|
@ -19,7 +19,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// applyPolicy applies policy on a resource
|
// 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()
|
startTime := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
name := resource.GetKind() + "/" + resource.GetName()
|
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())
|
logger.V(3).Info("applyPolicy", "resource", name, "processingTime", time.Since(startTime).String())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []*response.EngineResponse
|
||||||
var engineResponseMutation, engineResponseValidation response.EngineResponse
|
var engineResponseMutation, engineResponseValidation *response.EngineResponse
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
ctx := context.NewContext()
|
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")
|
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 {
|
if err != nil {
|
||||||
logger.Error(err, "failed to process mutation rule")
|
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))
|
engineResponses = append(engineResponses, mergeRuleRespose(engineResponseMutation, engineResponseValidation))
|
||||||
|
|
||||||
return engineResponses
|
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() {
|
if !engineResponse.IsSuccessful() {
|
||||||
log.V(4).Info("failed to apply mutation rules; reporting them")
|
log.V(4).Info("failed to apply mutation rules; reporting them")
|
||||||
return engineResponse, nil
|
return engineResponse, nil
|
||||||
|
@ -69,11 +77,11 @@ func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured,
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFailedOverallRuleInfo gets detailed info for over-all mutation failure
|
// 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()
|
rawResource, err := resource.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to marshall resource")
|
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
|
// 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))
|
patch, err := jsonpatch.DecodePatch(utils.JoinPatches(patches))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to decode JSON patch", "patches", patches)
|
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
|
// apply the patches returned by mutate to the original resource
|
||||||
patchedResource, err := patch.Apply(rawResource)
|
patchedResource, err := patch.Apply(rawResource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "failed to apply JSON patch", "patches", patches)
|
log.Error(err, "failed to apply JSON patch", "patches", patches)
|
||||||
return response.EngineResponse{}, err
|
return &response.EngineResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !jsonpatch.Equal(patchedResource, rawResource) {
|
if !jsonpatch.Equal(patchedResource, rawResource) {
|
||||||
|
@ -126,7 +134,7 @@ func extractPatchPath(patches [][]byte, log logr.Logger) string {
|
||||||
return strings.Join(resultPath, ";")
|
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...)
|
mutation.PolicyResponse.Rules = append(mutation.PolicyResponse.Rules, validation.PolicyResponse.Rules...)
|
||||||
return mutation
|
return mutation
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (pc *PolicyController) applyAndReportPerNamespace(policy *kyverno.ClusterPo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []*response.EngineResponse
|
||||||
for _, resource := range rMap {
|
for _, resource := range rMap {
|
||||||
responses := pc.applyPolicy(policy, resource, logger)
|
responses := pc.applyPolicy(policy, resource, logger)
|
||||||
engineResponses = append(engineResponses, responses...)
|
engineResponses = append(engineResponses, responses...)
|
||||||
|
@ -68,7 +68,7 @@ func (pc *PolicyController) applyAndReportPerNamespace(policy *kyverno.ClusterPo
|
||||||
pc.report(policy.Name, engineResponses, logger)
|
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
|
// 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()) {
|
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())
|
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
|
// excludeAutoGenResources filter out the pods / jobs with ownerReference
|
||||||
func excludeAutoGenResources(policy kyverno.ClusterPolicy, resourceMap map[string]unstructured.Unstructured, log logr.Logger) {
|
func excludeAutoGenResources(policy kyverno.ClusterPolicy, resourceMap map[string]unstructured.Unstructured, log logr.Logger) {
|
||||||
for uid, r := range resourceMap {
|
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())
|
log.V(4).Info("exclude resource", "namespace", r.GetNamespace(), "kind", r.GetKind(), "name", r.GetName())
|
||||||
delete(resourceMap, uid)
|
delete(resourceMap, uid)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/policyreport"
|
"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)
|
eventInfos := generateEvents(logger, engineResponses)
|
||||||
pc.eventGen.Add(eventInfos...)
|
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())
|
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
|
var eventInfos []event.Info
|
||||||
for _, er := range ers {
|
for _, er := range ers {
|
||||||
if er.IsSuccessful() {
|
if er.IsSuccessful() {
|
||||||
|
@ -33,7 +33,7 @@ func generateEvents(log logr.Logger, ers []response.EngineResponse) []event.Info
|
||||||
return eventInfos
|
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
|
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)
|
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
|
//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 {
|
for _, er := range ers {
|
||||||
// ignore creation of PV for resources that are yet to be assigned a name
|
// ignore creation of PV for resources that are yet to be assigned a name
|
||||||
if er.PolicyResponse.Resource.Name == "" {
|
if er.PolicyResponse.Resource.Name == "" {
|
||||||
|
@ -210,7 +210,7 @@ func calculateSummary(results []*report.PolicyReportResult) (summary report.Poli
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPVInfo(er response.EngineResponse) Info {
|
func buildPVInfo(er *response.EngineResponse) Info {
|
||||||
info := Info{
|
info := Info{
|
||||||
PolicyName: er.PolicyResponse.Policy,
|
PolicyName: er.PolicyResponse.Policy,
|
||||||
Namespace: er.PatchedResource.GetNamespace(),
|
Namespace: er.PatchedResource.GetNamespace(),
|
||||||
|
@ -224,7 +224,7 @@ func buildPVInfo(er response.EngineResponse) Info {
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildViolatedRules(er response.EngineResponse) []kyverno.ViolatedRule {
|
func buildViolatedRules(er *response.EngineResponse) []kyverno.ViolatedRule {
|
||||||
var violatedRules []kyverno.ViolatedRule
|
var violatedRules []kyverno.ViolatedRule
|
||||||
for _, rule := range er.PolicyResponse.Rules {
|
for _, rule := range er.PolicyResponse.Rules {
|
||||||
vrule := kyverno.ViolatedRule{
|
vrule := kyverno.ViolatedRule{
|
||||||
|
|
|
@ -126,9 +126,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
|
||||||
t.FailNow()
|
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---")
|
t.Log("---Mutation---")
|
||||||
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
|
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
|
||||||
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
|
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
|
||||||
|
@ -138,7 +136,7 @@ func runTestCase(t *testing.T, tc scaseT) bool {
|
||||||
resource = &er.PatchedResource
|
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---")
|
t.Log("---Validation---")
|
||||||
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)
|
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)
|
||||||
|
|
||||||
|
@ -235,7 +233,7 @@ func validateResponse(t *testing.T, er response.PolicyResponse, expected respons
|
||||||
|
|
||||||
// rules
|
// rules
|
||||||
if len(er.Rules) != len(expected.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
|
return
|
||||||
}
|
}
|
||||||
if len(er.Rules) == len(expected.Rules) {
|
if len(er.Rules) == len(expected.Rules) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ var operationToPastTense = map[string]string{
|
||||||
"test": "tested",
|
"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
|
var annotations map[string]string
|
||||||
|
|
||||||
for _, er := range engineResponses {
|
for _, er := range engineResponses {
|
||||||
|
@ -94,7 +94,7 @@ func generateAnnotationPatches(engineResponses []response.EngineResponse, log lo
|
||||||
return patchByte
|
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)
|
var annotationContent = make(map[string]string)
|
||||||
for _, engineResponse := range engineResponses {
|
for _, engineResponse := range engineResponses {
|
||||||
if !engineResponse.IsSuccessful() {
|
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 {
|
func newEngineResponse(policy, rule string, patchesStr []string, success bool, annotation map[string]string) *response.EngineResponse {
|
||||||
return response.EngineResponse{
|
return &response.EngineResponse{
|
||||||
PatchedResource: unstructured.Unstructured{
|
PatchedResource: unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
"metadata": 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" }`
|
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, nil)
|
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"}}`
|
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)
|
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" }`
|
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation)
|
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"}}`
|
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)
|
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" }`
|
patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }`
|
||||||
engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation)
|
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"}}`
|
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)
|
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)
|
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)
|
assert.Assert(t, annPatches == nil)
|
||||||
|
|
||||||
engineResponseNew := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{""}, true, annotation)
|
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)
|
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)
|
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)
|
assert.Assert(t, annPatches == nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// isResponseSuccessful return true if all responses are successful
|
// isResponseSuccessful return true if all responses are successful
|
||||||
func isResponseSuccessful(engineReponses []response.EngineResponse) bool {
|
func isResponseSuccessful(engineReponses []*response.EngineResponse) bool {
|
||||||
for _, er := range engineReponses {
|
for _, er := range engineReponses {
|
||||||
if !er.IsSuccessful() {
|
if !er.IsSuccessful() {
|
||||||
return false
|
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 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
|
// 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 {
|
for _, er := range engineReponses {
|
||||||
if !er.IsSuccessful() && er.PolicyResponse.ValidationFailureAction == common.Enforce {
|
if !er.IsSuccessful() && er.PolicyResponse.ValidationFailureAction == common.Enforce {
|
||||||
log.Info("spec.ValidationFailureAction set to enforce blocking resource request", "policy", er.PolicyResponse.Policy)
|
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
|
// 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{})
|
policyToRule := make(map[string]interface{})
|
||||||
var resourceName string
|
var resourceName string
|
||||||
for _, er := range engineResponses {
|
for _, er := range engineResponses {
|
||||||
|
@ -61,7 +61,7 @@ func getEnforceFailureErrorMsg(engineResponses []response.EngineResponse) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// getErrorMsg gets all failed engine response message
|
// getErrorMsg gets all failed engine response message
|
||||||
func getErrorMsg(engineReponses []response.EngineResponse) string {
|
func getErrorMsg(engineReponses []*response.EngineResponse) string {
|
||||||
var str []string
|
var str []string
|
||||||
var resourceInfo 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) {
|
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 := 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")
|
logger.V(4).Info("incoming request")
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []*response.EngineResponse
|
||||||
|
|
||||||
if len(policies) == 0 {
|
if len(policies) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -44,7 +44,6 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
||||||
NewResource: new,
|
NewResource: new,
|
||||||
OldResource: old,
|
OldResource: old,
|
||||||
AdmissionInfo: userRequestInfo,
|
AdmissionInfo: userRequestInfo,
|
||||||
Context: ctx,
|
|
||||||
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
||||||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||||
ResourceCache: ws.resCache,
|
ResourceCache: ws.resCache,
|
||||||
|
@ -86,7 +85,7 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic
|
||||||
return
|
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")
|
logger.V(4).Info("querying all generate requests")
|
||||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||||
"policyName": engineResponse.PolicyResponse.Policy,
|
"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,
|
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 {
|
for _, er := range engineResponses {
|
||||||
gr := transform(userRequestInfo, er)
|
gr := transform(userRequestInfo, er)
|
||||||
|
@ -122,8 +121,7 @@ func applyGenerateRequest(gnGenerator generate.GenerateRequests, userRequestInfo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func transform(userRequestInfo kyverno.RequestInfo, er response.EngineResponse) kyverno.GenerateRequestSpec {
|
func transform(userRequestInfo kyverno.RequestInfo, er *response.EngineResponse) kyverno.GenerateRequestSpec {
|
||||||
|
|
||||||
gr := kyverno.GenerateRequestSpec{
|
gr := kyverno.GenerateRequestSpec{
|
||||||
Policy: er.PolicyResponse.Policy,
|
Policy: er.PolicyResponse.Policy,
|
||||||
Resource: kyverno.ResourceSpec{
|
Resource: kyverno.ResourceSpec{
|
||||||
|
@ -135,11 +133,12 @@ func transform(userRequestInfo kyverno.RequestInfo, er response.EngineResponse)
|
||||||
UserRequestInfo: userRequestInfo,
|
UserRequestInfo: userRequestInfo,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return gr
|
return gr
|
||||||
}
|
}
|
||||||
|
|
||||||
type generateStats struct {
|
type generateStats struct {
|
||||||
resp response.EngineResponse
|
resp *response.EngineResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs generateStats) PolicyName() string {
|
func (gs generateStats) PolicyName() string {
|
||||||
|
|
|
@ -36,11 +36,10 @@ func (ws *WebhookServer) HandleMutation(
|
||||||
logger := ws.log.WithValues("action", "mutate", "resource", resourceName, "operation", request.Operation)
|
logger := ws.log.WithValues("action", "mutate", "resource", resourceName, "operation", request.Operation)
|
||||||
|
|
||||||
var patches [][]byte
|
var patches [][]byte
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []*response.EngineResponse
|
||||||
policyContext := engine.PolicyContext{
|
policyContext := &engine.PolicyContext{
|
||||||
NewResource: resource,
|
NewResource: resource,
|
||||||
AdmissionInfo: userRequestInfo,
|
AdmissionInfo: userRequestInfo,
|
||||||
Context: ctx,
|
|
||||||
ExcludeGroupRole: ws.configHandler.GetExcludeGroupRole(),
|
ExcludeGroupRole: ws.configHandler.GetExcludeGroupRole(),
|
||||||
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
ExcludeResourceFunc: ws.configHandler.ToFilter,
|
||||||
ResourceCache: ws.resCache,
|
ResourceCache: ws.resCache,
|
||||||
|
@ -117,7 +116,7 @@ func (ws *WebhookServer) HandleMutation(
|
||||||
}
|
}
|
||||||
|
|
||||||
type mutateStats struct {
|
type mutateStats struct {
|
||||||
resp response.EngineResponse
|
resp *response.EngineResponse
|
||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ import (
|
||||||
|
|
||||||
func Test_GenerateStats(t *testing.T) {
|
func Test_GenerateStats(t *testing.T) {
|
||||||
testCase := struct {
|
testCase := struct {
|
||||||
generateStats []response.EngineResponse
|
generateStats []*response.EngineResponse
|
||||||
expectedOutput []byte
|
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}]}}`),
|
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{
|
PolicyResponse: response.PolicyResponse{
|
||||||
Policy: "policy1",
|
Policy: "policy1",
|
||||||
|
@ -79,11 +79,11 @@ func Test_GenerateStats(t *testing.T) {
|
||||||
|
|
||||||
func Test_MutateStats(t *testing.T) {
|
func Test_MutateStats(t *testing.T) {
|
||||||
testCase := struct {
|
testCase := struct {
|
||||||
mutateStats []response.EngineResponse
|
mutateStats []*response.EngineResponse
|
||||||
expectedOutput []byte
|
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}]}}`),
|
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{
|
PolicyResponse: response.PolicyResponse{
|
||||||
Policy: "policy1",
|
Policy: "policy1",
|
||||||
|
@ -145,11 +145,11 @@ func Test_MutateStats(t *testing.T) {
|
||||||
|
|
||||||
func Test_ValidateStats(t *testing.T) {
|
func Test_ValidateStats(t *testing.T) {
|
||||||
testCase := struct {
|
testCase := struct {
|
||||||
validateStats []response.EngineResponse
|
validateStats []*response.EngineResponse
|
||||||
expectedOutput []byte
|
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}]}}`),
|
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{
|
PolicyResponse: response.PolicyResponse{
|
||||||
Policy: "policy1",
|
Policy: "policy1",
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
//generateEvents generates event info for the engine responses
|
//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
|
var events []event.Info
|
||||||
|
|
||||||
// - Admission-Response is SUCCESS
|
// - Admission-Response is SUCCESS
|
||||||
|
|
|
@ -330,7 +330,7 @@ func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to load userInfo in context")
|
logger.Error(err, "failed to load userInfo in context")
|
||||||
}
|
}
|
||||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to load service account in context")
|
logger.Error(err, "failed to load service account in context")
|
||||||
}
|
}
|
||||||
|
@ -441,7 +441,7 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) *
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to load userInfo in context")
|
logger.Error(err, "failed to load userInfo in context")
|
||||||
}
|
}
|
||||||
err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username)
|
err = ctx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to load service account in context")
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to load userInfo in context")
|
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 {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to load service account in context")
|
return errors.Wrap(err, "failed to load service account in context")
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,10 +68,9 @@ func HandleValidation(
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
policyContext := engine.PolicyContext{
|
policyContext := &engine.PolicyContext{
|
||||||
NewResource: newR,
|
NewResource: newR,
|
||||||
OldResource: oldR,
|
OldResource: oldR,
|
||||||
Context: ctx,
|
|
||||||
AdmissionInfo: userRequestInfo,
|
AdmissionInfo: userRequestInfo,
|
||||||
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
ExcludeGroupRole: dynamicConfig.GetExcludeGroupRole(),
|
||||||
ExcludeResourceFunc: dynamicConfig.ToFilter,
|
ExcludeResourceFunc: dynamicConfig.ToFilter,
|
||||||
|
@ -79,7 +78,7 @@ func HandleValidation(
|
||||||
JSONContext: ctx,
|
JSONContext: ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
var engineResponses []response.EngineResponse
|
var engineResponses []*response.EngineResponse
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
|
|
||||||
logger.V(3).Info("evaluating policy", "policy", policy.Name)
|
logger.V(3).Info("evaluating policy", "policy", policy.Name)
|
||||||
|
@ -152,7 +151,7 @@ func buildDeletionPrInfo(oldR unstructured.Unstructured) policyreport.Info {
|
||||||
}
|
}
|
||||||
|
|
||||||
type validateStats struct {
|
type validateStats struct {
|
||||||
resp response.EngineResponse
|
resp *response.EngineResponse
|
||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ expected:
|
||||||
kind: Pod
|
kind: Pod
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
# this is set to pass resource NS check
|
# 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'
|
namespace: 'default'
|
||||||
name: myapp-pod
|
name: myapp-pod
|
||||||
rules:
|
rules:
|
||||||
|
|
Loading…
Add table
Reference in a new issue