mirror of
https://github.com/kyverno/kyverno.git
synced 2025-04-15 00:36:28 +00:00
refactor: engine rule response creation (#6784)
* refactor: engine rule response creation Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * private fields Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more private Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix unit tests Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
6f8ef4fd30
commit
784ca07419
54 changed files with 718 additions and 826 deletions
|
@ -3,6 +3,7 @@ package apply
|
|||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
preport "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
|
@ -83,8 +84,6 @@ var rawPolicy = []byte(`
|
|||
}
|
||||
`)
|
||||
|
||||
var rawEngRes = []byte(`{"PatchedResource":{"apiVersion":"v1","kind":"Pod","metadata":{"name":"nginx1","namespace":"default"},"spec":{"containers":[{"image":"nginx","imagePullPolicy":"IfNotPresent","name":"nginx","resources":{"limits":{"cpu":"200m","memory":"100Mi"},"requests":{"cpu":"100m","memory":"50Mi"}}}]}},"PolicyResponse":{"policy":{"name":"pod-requirements","namespace":""},"resource":{"kind":"Pod","apiVersion":"v1","namespace":"default","name":"nginx1","uid":""},"processingTime":974958,"rulesAppliedCount":2,"policyExecutionTimestamp":1630527712,"rules":[{"name":"pods-require-account","type":"Validation","message":"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/","status":"fail","processingTime":28833,"ruleExecutionTimestamp":1630527712},{"name":"pods-require-limits","type":"Validation","message":"validation rule 'pods-require-limits' passed.","status":"pass","processingTime":578625,"ruleExecutionTimestamp":1630527712}],"ValidationFailureAction":"audit"}}`)
|
||||
|
||||
func Test_buildPolicyReports(t *testing.T) {
|
||||
rc := &kyvCommon.ResultCounts{}
|
||||
var pvInfos []common.Info
|
||||
|
@ -92,10 +91,18 @@ func Test_buildPolicyReports(t *testing.T) {
|
|||
err := json.Unmarshal(rawPolicy, &policy)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var er engineapi.EngineResponse
|
||||
err = json.Unmarshal(rawEngRes, &er)
|
||||
er := engineapi.EngineResponse{}
|
||||
er.Policy = &policy
|
||||
assert.NilError(t, err)
|
||||
er.PolicyResponse.Add(time.Now(), time.Now(), *engineapi.RuleFail(
|
||||
"pods-require-account",
|
||||
engineapi.Validation,
|
||||
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/"),
|
||||
)
|
||||
er.PolicyResponse.Add(time.Now(), time.Now(), *engineapi.RulePass(
|
||||
"pods-require-limits",
|
||||
engineapi.Validation,
|
||||
"validation rule 'pods-require-limits' passed."),
|
||||
)
|
||||
|
||||
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)
|
||||
pvInfos = append(pvInfos, info)
|
||||
|
@ -129,10 +136,18 @@ func Test_buildPolicyResults(t *testing.T) {
|
|||
err := json.Unmarshal(rawPolicy, &policy)
|
||||
assert.NilError(t, err)
|
||||
|
||||
var er engineapi.EngineResponse
|
||||
err = json.Unmarshal(rawEngRes, &er)
|
||||
er := engineapi.EngineResponse{}
|
||||
er.Policy = &policy
|
||||
assert.NilError(t, err)
|
||||
er.PolicyResponse.Add(time.Now(), time.Now(), *engineapi.RuleFail(
|
||||
"pods-require-account",
|
||||
engineapi.Validation,
|
||||
"validation error: User pods must include an account for charging. Rule pods-require-account failed at path /metadata/labels/"),
|
||||
)
|
||||
er.PolicyResponse.Add(time.Now(), time.Now(), *engineapi.RulePass(
|
||||
"pods-require-limits",
|
||||
engineapi.Validation,
|
||||
"validation rule 'pods-require-limits' passed."),
|
||||
)
|
||||
|
||||
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)
|
||||
pvInfos = append(pvInfos, info)
|
||||
|
|
|
@ -440,7 +440,7 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
|
||||
var rules []string
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
rules = append(rules, rule.Name)
|
||||
rules = append(rules, rule.Name())
|
||||
}
|
||||
|
||||
result := policyreportv1alpha2.PolicyReportResult{
|
||||
|
@ -542,14 +542,14 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
if rule.Type != engineapi.Generation || test.Rule != rule.Name {
|
||||
if rule.RuleType() != engineapi.Generation || test.Rule != rule.Name() {
|
||||
continue
|
||||
}
|
||||
|
||||
var resultsKey []string
|
||||
var resultKey string
|
||||
var result policyreportv1alpha2.PolicyReportResult
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name, resourceNamespace, resourceKind, resourceName)
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name(), resourceNamespace, resourceKind, resourceName)
|
||||
for _, key := range resultsKey {
|
||||
if val, ok := results[key]; ok {
|
||||
result = val
|
||||
|
@ -558,14 +558,14 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
continue
|
||||
}
|
||||
|
||||
if rule.Status == engineapi.RuleStatusSkip {
|
||||
if rule.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if rule.Status == engineapi.RuleStatusError {
|
||||
} else if rule.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else {
|
||||
var x string
|
||||
result.Result = policyreportv1alpha2.StatusFail
|
||||
x = getAndCompareResource(test.GeneratedResource, rule.GeneratedResource, isGit, policyResourcePath, fs, true)
|
||||
x = getAndCompareResource(test.GeneratedResource, rule.GeneratedResource(), isGit, policyResourcePath, fs, true)
|
||||
if x == "pass" {
|
||||
result.Result = policyreportv1alpha2.StatusPass
|
||||
}
|
||||
|
@ -576,14 +576,14 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
if rule.Type != engineapi.Mutation {
|
||||
if rule.RuleType() != engineapi.Mutation {
|
||||
continue
|
||||
}
|
||||
|
||||
var resultsKey []string
|
||||
var resultKey string
|
||||
var result policyreportv1alpha2.PolicyReportResult
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name, resourceNamespace, resourceKind, resourceName)
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name(), resourceNamespace, resourceKind, resourceName)
|
||||
for _, key := range resultsKey {
|
||||
if val, ok := results[key]; ok {
|
||||
result = val
|
||||
|
@ -592,9 +592,9 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
continue
|
||||
}
|
||||
|
||||
if rule.Status == engineapi.RuleStatusSkip {
|
||||
if rule.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if rule.Status == engineapi.RuleStatusError {
|
||||
} else if rule.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else {
|
||||
var x string
|
||||
|
@ -710,8 +710,8 @@ func getAndCompareResource(path string, engineResource unstructured.Unstructured
|
|||
func buildMessage(resp *engineapi.EngineResponse) string {
|
||||
var bldr strings.Builder
|
||||
for _, ruleResp := range resp.PolicyResponse.Rules {
|
||||
fmt.Fprintf(&bldr, " %s: %s \n", ruleResp.Name, ruleResp.Status)
|
||||
fmt.Fprintf(&bldr, " %s \n", ruleResp.Message)
|
||||
fmt.Fprintf(&bldr, " %s: %s \n", ruleResp.Name(), ruleResp.Status())
|
||||
fmt.Fprintf(&bldr, " %s \n", ruleResp.Message())
|
||||
}
|
||||
|
||||
return bldr.String()
|
||||
|
|
|
@ -708,15 +708,15 @@ func ProcessValidateEngineResponse(policy kyvernov1.PolicyInterface, validateRes
|
|||
}
|
||||
|
||||
for i, valResponseRule := range validateResponse.PolicyResponse.Rules {
|
||||
if policyRule.Name == valResponseRule.Name {
|
||||
if policyRule.Name == valResponseRule.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
vrule := kyvernov1.ViolatedRule{
|
||||
Name: valResponseRule.Name,
|
||||
Type: string(valResponseRule.Type),
|
||||
Message: valResponseRule.Message,
|
||||
Name: valResponseRule.Name(),
|
||||
Type: string(valResponseRule.RuleType()),
|
||||
Message: valResponseRule.Message(),
|
||||
}
|
||||
|
||||
switch valResponseRule.Status {
|
||||
switch valResponseRule.Status() {
|
||||
case engineapi.RuleStatusPass:
|
||||
rc.Pass++
|
||||
vrule.Status = policyreportv1alpha2.StatusPass
|
||||
|
@ -747,7 +747,7 @@ func ProcessValidateEngineResponse(policy kyvernov1.PolicyInterface, validateRes
|
|||
printCount++
|
||||
}
|
||||
|
||||
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name, valResponseRule.Message)
|
||||
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name(), valResponseRule.Message())
|
||||
}
|
||||
|
||||
case engineapi.RuleStatusError:
|
||||
|
@ -801,17 +801,17 @@ func updateResultCounts(policy kyvernov1.PolicyInterface, engineResponse *engine
|
|||
for _, policyRule := range autogen.ComputeRules(policy) {
|
||||
ruleFoundInEngineResponse := false
|
||||
for i, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
||||
if policyRule.Name == ruleResponse.Name {
|
||||
if policyRule.Name == ruleResponse.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
|
||||
if ruleResponse.Status == engineapi.RuleStatusPass {
|
||||
if ruleResponse.Status() == engineapi.RuleStatusPass {
|
||||
rc.Pass++
|
||||
} else {
|
||||
if printCount < 1 {
|
||||
fmt.Println("\ninvalid resource", "policy", policy.GetName(), "resource", resPath)
|
||||
printCount++
|
||||
}
|
||||
fmt.Printf("%d. %s - %s\n", i+1, ruleResponse.Name, ruleResponse.Message)
|
||||
fmt.Printf("%d. %s - %s\n", i+1, ruleResponse.Name(), ruleResponse.Message())
|
||||
|
||||
if auditWarn && engineResponse.GetValidationFailureAction().Audit() {
|
||||
rc.Warn++
|
||||
|
@ -877,23 +877,23 @@ func processMutateEngineResponse(c ApplyPolicyConfig, mutateResponse *engineapi.
|
|||
for _, policyRule := range autogen.ComputeRules(c.Policy) {
|
||||
ruleFoundInEngineResponse := false
|
||||
for i, mutateResponseRule := range mutateResponse.PolicyResponse.Rules {
|
||||
if policyRule.Name == mutateResponseRule.Name {
|
||||
if policyRule.Name == mutateResponseRule.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
if mutateResponseRule.Status == engineapi.RuleStatusPass {
|
||||
if mutateResponseRule.Status() == engineapi.RuleStatusPass {
|
||||
c.Rc.Pass++
|
||||
printMutatedRes = true
|
||||
} else if mutateResponseRule.Status == engineapi.RuleStatusSkip {
|
||||
} else if mutateResponseRule.Status() == engineapi.RuleStatusSkip {
|
||||
fmt.Printf("\nskipped mutate policy %s -> resource %s", c.Policy.GetName(), resPath)
|
||||
c.Rc.Skip++
|
||||
} else if mutateResponseRule.Status == engineapi.RuleStatusError {
|
||||
fmt.Printf("\nerror while applying mutate policy %s -> resource %s\nerror: %s", c.Policy.GetName(), resPath, mutateResponseRule.Message)
|
||||
} else if mutateResponseRule.Status() == engineapi.RuleStatusError {
|
||||
fmt.Printf("\nerror while applying mutate policy %s -> resource %s\nerror: %s", c.Policy.GetName(), resPath, mutateResponseRule.Message())
|
||||
c.Rc.Error++
|
||||
} else {
|
||||
if printCount < 1 {
|
||||
fmt.Printf("\nfailed to apply mutate policy %s -> resource %s", c.Policy.GetName(), resPath)
|
||||
printCount++
|
||||
}
|
||||
fmt.Printf("%d. %s - %s \n", i+1, mutateResponseRule.Name, mutateResponseRule.Message)
|
||||
fmt.Printf("%d. %s - %s \n", i+1, mutateResponseRule.Name(), mutateResponseRule.Message())
|
||||
c.Rc.Fail++
|
||||
}
|
||||
continue
|
||||
|
@ -1089,7 +1089,7 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
|
|||
objects := []runtime.Object{&resource}
|
||||
resources := []*unstructured.Unstructured{}
|
||||
for _, rule := range generateResponse.PolicyResponse.Rules {
|
||||
if path, ok := ruleToCloneSourceResource[rule.Name]; ok {
|
||||
if path, ok := ruleToCloneSourceResource[rule.Name()]; ok {
|
||||
resourceBytes, err := getFileBytes(path)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to get resource bytes\n")
|
||||
|
@ -1128,20 +1128,17 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
|
|||
var newRuleResponse []engineapi.RuleResponse
|
||||
|
||||
for _, rule := range generateResponse.PolicyResponse.Rules {
|
||||
genResource, err := c.ApplyGeneratePolicy(log.Log, &policyContext, gr, []string{rule.Name})
|
||||
genResource, err := c.ApplyGeneratePolicy(log.Log, &policyContext, gr, []string{rule.Name()})
|
||||
if err != nil {
|
||||
rule.Status = engineapi.RuleStatusError
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unstrGenResource, err := c.GetUnstrResource(genResource[0])
|
||||
if err != nil {
|
||||
rule.Status = engineapi.RuleStatusError
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rule.GeneratedResource = *unstrGenResource
|
||||
newRuleResponse = append(newRuleResponse, rule)
|
||||
newRuleResponse = append(newRuleResponse, *rule.WithGeneratedResource(*unstrGenResource))
|
||||
}
|
||||
|
||||
return newRuleResponse, nil
|
||||
|
|
|
@ -223,7 +223,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
|
|||
var applicableRules []string
|
||||
// Removing UR if rule is failed. Used when the generate condition failed but ur exist
|
||||
for _, r := range engineResponse.PolicyResponse.Rules {
|
||||
if r.Status != engineapi.RuleStatusPass {
|
||||
if r.Status() != engineapi.RuleStatusPass {
|
||||
logger.V(4).Info("querying all update requests")
|
||||
selector := labels.SelectorFromSet(labels.Set(map[string]string{
|
||||
kyvernov1beta1.URGeneratePolicyLabel: engineResponse.Policy.GetName(),
|
||||
|
@ -244,7 +244,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
|
|||
}
|
||||
}
|
||||
} else {
|
||||
applicableRules = append(applicableRules, r.Name)
|
||||
applicableRules = append(applicableRules, r.Name())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,17 +149,16 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
|
|||
|
||||
er := c.engine.Mutate(context.TODO(), policyContext)
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
patched := r.PatchedTarget
|
||||
patchedTargetSubresourceName := r.PatchedTargetSubresourceName
|
||||
switch r.Status {
|
||||
patched, parentGVR, patchedSubresource := r.PatchedTarget()
|
||||
switch r.Status() {
|
||||
case engineapi.RuleStatusFail, engineapi.RuleStatusError, engineapi.RuleStatusWarn:
|
||||
err := fmt.Errorf("failed to mutate existing resource, rule response%v: %s", r.Status, r.Message)
|
||||
err := fmt.Errorf("failed to mutate existing resource, rule response%v: %s", r.Status(), r.Message())
|
||||
logger.Error(err, "")
|
||||
errs = append(errs, err)
|
||||
c.report(err, ur.Spec.Policy, rule.Name, patched)
|
||||
|
||||
case engineapi.RuleStatusSkip:
|
||||
logger.Info("mutate existing rule skipped", "rule", r.Name, "message", r.Message)
|
||||
logger.Info("mutate existing rule skipped", "rule", r.Name(), "message", r.Message())
|
||||
c.report(err, ur.Spec.Policy, rule.Name, patched)
|
||||
|
||||
case engineapi.RuleStatusPass:
|
||||
|
@ -171,18 +170,18 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
|
|||
}
|
||||
|
||||
if patchedNew == nil {
|
||||
logger.Error(ErrEmptyPatch, "", "rule", r.Name, "message", r.Message)
|
||||
logger.Error(ErrEmptyPatch, "", "rule", r.Name(), "message", r.Message())
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if r.Status == engineapi.RuleStatusPass {
|
||||
if r.Status() == engineapi.RuleStatusPass {
|
||||
patchedNew.SetResourceVersion(patched.GetResourceVersion())
|
||||
var updateErr error
|
||||
if patchedTargetSubresourceName == "status" {
|
||||
if patchedSubresource == "status" {
|
||||
_, updateErr = c.client.UpdateStatusResource(context.TODO(), patchedNew.GetAPIVersion(), patchedNew.GetKind(), patchedNew.GetNamespace(), patchedNew.Object, false)
|
||||
} else if patchedTargetSubresourceName != "" {
|
||||
parentResourceGVR := r.PatchedTargetParentResourceGVR
|
||||
} else if patchedSubresource != "" {
|
||||
parentResourceGVR := parentGVR
|
||||
parentResourceGV := schema.GroupVersion{Group: parentResourceGVR.Group, Version: parentResourceGVR.Version}
|
||||
parentResourceGVK, err := c.client.Discovery().GetGVKFromGVR(parentResourceGV.WithResource(parentResourceGVR.Resource))
|
||||
if err != nil {
|
||||
|
@ -190,7 +189,7 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
|
|||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
_, updateErr = c.client.UpdateResource(context.TODO(), parentResourceGV.String(), parentResourceGVK.Kind, patchedNew.GetNamespace(), patchedNew.Object, false, patchedTargetSubresourceName)
|
||||
_, updateErr = c.client.UpdateResource(context.TODO(), parentResourceGV.String(), parentResourceGVK.Kind, patchedNew.GetNamespace(), patchedNew.Object, false, patchedSubresource)
|
||||
} else {
|
||||
_, updateErr = c.client.UpdateResource(context.TODO(), patchedNew.GetAPIVersion(), patchedNew.GetKind(), patchedNew.GetNamespace(), patchedNew.Object, false)
|
||||
}
|
||||
|
@ -261,7 +260,7 @@ func addAnnotation(policy kyvernov1.PolicyInterface, patched *unstructured.Unstr
|
|||
patchedNew = patched
|
||||
var rulePatches []utils.RulePatch
|
||||
|
||||
for _, patch := range r.Patches {
|
||||
for _, patch := range r.Patches() {
|
||||
var patchmap map[string]interface{}
|
||||
if err := json.Unmarshal(patch, &patchmap); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON patch bytes: %v", err)
|
||||
|
@ -272,7 +271,7 @@ func addAnnotation(policy kyvernov1.PolicyInterface, patched *unstructured.Unstr
|
|||
Op string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
}{
|
||||
RuleName: r.Name,
|
||||
RuleName: r.Name(),
|
||||
Op: patchmap["op"].(string),
|
||||
Path: patchmap["path"].(string),
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ func generateSuccessEvents(log logr.Logger, ers ...engineapi.EngineResponse) (ev
|
|||
func generateExceptionEvents(log logr.Logger, ers ...engineapi.EngineResponse) (eventInfos []event.Info) {
|
||||
for _, er := range ers {
|
||||
for i, ruleResp := range er.PolicyResponse.Rules {
|
||||
isException := ruleResp.Exception != nil
|
||||
if ruleResp.Status == engineapi.RuleStatusSkip && isException {
|
||||
if ruleResp.Status() == engineapi.RuleStatusSkip && ruleResp.IsException() {
|
||||
eventInfos = append(eventInfos, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i], event.PolicyController)...)
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +58,7 @@ func generateFailEventsPerEr(log logr.Logger, er engineapi.EngineResponse) []eve
|
|||
"name", er.Resource.GetName(),
|
||||
)
|
||||
for i, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Status != engineapi.RuleStatusPass && rule.Status != engineapi.RuleStatusSkip {
|
||||
if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip {
|
||||
eventResource := event.NewResourceViolationEvent(event.PolicyController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i])
|
||||
eventInfos = append(eventInfos, eventResource)
|
||||
eventPolicy := event.NewPolicyFailEvent(event.PolicyController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i], false)
|
||||
|
|
|
@ -124,9 +124,7 @@ func (er EngineResponse) IsNil() bool {
|
|||
func (er EngineResponse) GetPatches() [][]byte {
|
||||
var patches [][]byte
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
if r.Patches != nil {
|
||||
patches = append(patches, r.Patches...)
|
||||
}
|
||||
patches = append(patches, r.Patches()...)
|
||||
}
|
||||
return patches
|
||||
}
|
||||
|
@ -161,7 +159,7 @@ func (er EngineResponse) getRules(predicate func(RuleResponse) bool) []string {
|
|||
var rules []string
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
if predicate(r) {
|
||||
rules = append(rules, r.Name)
|
||||
rules = append(rules, r.Name())
|
||||
}
|
||||
}
|
||||
return rules
|
||||
|
@ -171,7 +169,7 @@ func (er EngineResponse) getRulesWithErrors(predicate func(RuleResponse) bool) [
|
|||
var rules []string
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
if predicate(r) {
|
||||
rules = append(rules, fmt.Sprintf("%s: %s", r.Name, r.Message))
|
||||
rules = append(rules, fmt.Sprintf("%s: %s", r.Name(), r.Message()))
|
||||
}
|
||||
}
|
||||
return rules
|
||||
|
|
|
@ -113,18 +113,18 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
}{{
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -134,9 +134,9 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -146,9 +146,9 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -158,9 +158,9 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -199,45 +199,45 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
|
@ -273,45 +273,45 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
|
@ -347,45 +347,45 @@ func TestEngineResponse_IsFailed(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
|
@ -421,45 +421,45 @@ func TestEngineResponse_IsError(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
|
@ -493,76 +493,63 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
|
|||
}{{
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "skip",
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "warn",
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("warn", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "pass",
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail",
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"fail"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail-1",
|
||||
Status: RuleStatusFail,
|
||||
}, {
|
||||
Name: "fail-2",
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleFail("fail-2", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"fail-1", "fail-2"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail-1",
|
||||
Status: RuleStatusFail,
|
||||
}, {
|
||||
Name: "error-1",
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"fail-1", "error-1"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "error-1",
|
||||
Status: RuleStatusError,
|
||||
}, {
|
||||
Name: "error-2",
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleError("error-2", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"error-1", "error-2"},
|
||||
|
@ -596,113 +583,91 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
|
|||
}{{
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "skip",
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "warn",
|
||||
Status: RuleStatusWarn,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleWarn("warn", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "pass-1",
|
||||
Status: RuleStatusPass,
|
||||
}, {
|
||||
Name: "pass-2",
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass-1", Validation, ""),
|
||||
*RulePass("pass-2", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"pass-1", "pass-2"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "pass",
|
||||
Status: RuleStatusPass,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"pass"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "pass",
|
||||
Status: RuleStatusPass,
|
||||
}, {
|
||||
Name: "fail",
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RuleFail("fail", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"pass"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "pass",
|
||||
Status: RuleStatusPass,
|
||||
}, {
|
||||
Name: "skip",
|
||||
Status: RuleStatusSkip,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RulePass("pass", Validation, ""),
|
||||
*RuleSkip("skip", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []string{"pass"},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail",
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail-1",
|
||||
Status: RuleStatusFail,
|
||||
}, {
|
||||
Name: "fail-2",
|
||||
Status: RuleStatusFail,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleFail("fail-2", Validation, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "fail-1",
|
||||
Status: RuleStatusFail,
|
||||
}, {
|
||||
Name: "error-1",
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleFail("fail-1", Validation, ""),
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{
|
||||
Name: "error-1",
|
||||
Status: RuleStatusError,
|
||||
}, {
|
||||
Name: "error-2",
|
||||
Status: RuleStatusError,
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
*RuleError("error-1", Validation, "", nil),
|
||||
*RuleError("error-2", Validation, "", nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
@ -984,20 +949,21 @@ func TestEngineResponse_GetPatches(t *testing.T) {
|
|||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{}, {
|
||||
Patches: [][]byte{{0, 1, 2}, {3, 4, 5}},
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
{},
|
||||
*RuleResponse{}.WithPatches([][]byte{{0, 1, 2}, {3, 4, 5}}...),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: [][]byte{{0, 1, 2}, {3, 4, 5}},
|
||||
}, {
|
||||
fields: fields{
|
||||
PolicyResponse: PolicyResponse{
|
||||
Rules: []RuleResponse{{}, {
|
||||
Patches: [][]byte{{0, 1, 2}, {3, 4, 5}},
|
||||
}, {
|
||||
Patches: [][]byte{{7, 8, 9}},
|
||||
}},
|
||||
Rules: []RuleResponse{
|
||||
{},
|
||||
*RuleResponse{}.WithPatches([][]byte{{0, 1, 2}, {3, 4, 5}}...),
|
||||
*RuleResponse{}.WithPatches([][]byte{{7, 8, 9}}...),
|
||||
},
|
||||
},
|
||||
},
|
||||
want: [][]byte{{0, 1, 2}, {3, 4, 5}, {7, 8, 9}},
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package api
|
||||
|
||||
import "time"
|
||||
|
||||
// PolicyResponse policy application response
|
||||
type PolicyResponse struct {
|
||||
// Stats contains policy statistics
|
||||
|
@ -8,11 +10,12 @@ type PolicyResponse struct {
|
|||
Rules []RuleResponse
|
||||
}
|
||||
|
||||
func (pr *PolicyResponse) Add(rr RuleResponse) {
|
||||
pr.Rules = append(pr.Rules, rr)
|
||||
if rr.Status == RuleStatusPass || rr.Status == RuleStatusFail {
|
||||
func (pr *PolicyResponse) Add(startTime, endTime time.Time, response RuleResponse) {
|
||||
pr.Rules = append(pr.Rules, response.WithStats(startTime, endTime))
|
||||
status := response.Status()
|
||||
if status == RuleStatusPass || status == RuleStatusFail {
|
||||
pr.Stats.RulesAppliedCount++
|
||||
} else if rr.Status == RuleStatusError {
|
||||
} else if status == RuleStatusError {
|
||||
pr.Stats.RulesErrorCount++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||
pssutils "github.com/kyverno/kyverno/pkg/pss/utils"
|
||||
|
@ -22,36 +23,145 @@ type PodSecurityChecks struct {
|
|||
|
||||
// RuleResponse details for each rule application
|
||||
type RuleResponse struct {
|
||||
// Name is the rule name specified in policy
|
||||
Name string
|
||||
// Type is the rule type (Mutation,Generation,Validation) for Kyverno Policy
|
||||
Type RuleType
|
||||
// Message is the message response from the rule application
|
||||
Message string
|
||||
// Patches are JSON patches, for mutation rules
|
||||
Patches [][]byte
|
||||
// GeneratedResource is the generated by the generate rules of a policy
|
||||
GeneratedResource unstructured.Unstructured
|
||||
// Status rule status
|
||||
Status RuleStatus
|
||||
// Stats contains rule statistics
|
||||
Stats ExecutionStats
|
||||
// PatchedTarget is the patched resource for mutate.targets
|
||||
PatchedTarget *unstructured.Unstructured
|
||||
// PatchedTargetSubresourceName is the name of the subresource which is patched, empty if the resource patched is not a subresource.
|
||||
PatchedTargetSubresourceName string
|
||||
// PatchedTargetParentResourceGVR is the GVR of the parent resource of the PatchedTarget. This is only populated when PatchedTarget is a subresource.
|
||||
PatchedTargetParentResourceGVR metav1.GroupVersionResource
|
||||
// PodSecurityChecks contains pod security checks (only if this is a pod security rule)
|
||||
PodSecurityChecks *PodSecurityChecks
|
||||
// Exception is the exception applied (if any)
|
||||
Exception *kyvernov2alpha1.PolicyException
|
||||
// name is the rule name specified in policy
|
||||
name string
|
||||
// ruleType is the rule type (Mutation,Generation,Validation) for Kyverno Policy
|
||||
ruleType RuleType
|
||||
// message is the message response from the rule application
|
||||
message string
|
||||
// status rule status
|
||||
status RuleStatus
|
||||
// patches are JSON patches, for mutation rules
|
||||
patches [][]byte
|
||||
// stats contains rule statistics
|
||||
stats ExecutionStats
|
||||
// generatedResource is the generated by the generate rules of a policy
|
||||
generatedResource unstructured.Unstructured
|
||||
// patchedTarget is the patched resource for mutate.targets
|
||||
patchedTarget *unstructured.Unstructured
|
||||
// patchedTargetParentResourceGVR is the GVR of the parent resource of the PatchedTarget. This is only populated when PatchedTarget is a subresource.
|
||||
patchedTargetParentResourceGVR metav1.GroupVersionResource
|
||||
// patchedTargetSubresourceName is the name of the subresource which is patched, empty if the resource patched is not a subresource.
|
||||
patchedTargetSubresourceName string
|
||||
// podSecurityChecks contains pod security checks (only if this is a pod security rule)
|
||||
podSecurityChecks *PodSecurityChecks
|
||||
// exception is the exception applied (if any)
|
||||
exception *kyvernov2alpha1.PolicyException
|
||||
}
|
||||
|
||||
func NewRuleResponse(name string, ruleType RuleType, msg string, status RuleStatus) *RuleResponse {
|
||||
return &RuleResponse{
|
||||
name: name,
|
||||
ruleType: ruleType,
|
||||
message: msg,
|
||||
status: status,
|
||||
}
|
||||
}
|
||||
|
||||
func RuleError(name string, ruleType RuleType, msg string, err error) *RuleResponse {
|
||||
if err != nil {
|
||||
return NewRuleResponse(name, ruleType, fmt.Sprintf("%s: %s", msg, err.Error()), RuleStatusError)
|
||||
}
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusError)
|
||||
}
|
||||
|
||||
func RuleSkip(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusSkip)
|
||||
}
|
||||
|
||||
func RuleWarn(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusWarn)
|
||||
}
|
||||
|
||||
func RulePass(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusPass)
|
||||
}
|
||||
|
||||
func RuleFail(name string, ruleType RuleType, msg string) *RuleResponse {
|
||||
return NewRuleResponse(name, ruleType, msg, RuleStatusFail)
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithException(exception *kyvernov2alpha1.PolicyException) *RuleResponse {
|
||||
r.exception = exception
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithPodSecurityChecks(checks PodSecurityChecks) *RuleResponse {
|
||||
r.podSecurityChecks = &checks
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithPatchedTarget(patchedTarget *unstructured.Unstructured, gvr metav1.GroupVersionResource, subresource string) *RuleResponse {
|
||||
r.patchedTarget = patchedTarget
|
||||
r.patchedTargetParentResourceGVR = gvr
|
||||
r.patchedTargetSubresourceName = subresource
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithGeneratedResource(resource unstructured.Unstructured) *RuleResponse {
|
||||
r.generatedResource = resource
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithPatches(patches ...[]byte) *RuleResponse {
|
||||
r.patches = patches
|
||||
return &r
|
||||
}
|
||||
|
||||
func (r RuleResponse) WithStats(startTime, endTime time.Time) RuleResponse {
|
||||
r.stats = NewExecutionStats(startTime)
|
||||
r.stats.Done(endTime)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Stats() ExecutionStats {
|
||||
return r.stats
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Exception() *kyvernov2alpha1.PolicyException {
|
||||
return r.exception
|
||||
}
|
||||
|
||||
func (r *RuleResponse) IsException() bool {
|
||||
return r.exception != nil
|
||||
}
|
||||
|
||||
func (r *RuleResponse) PodSecurityChecks() *PodSecurityChecks {
|
||||
return r.podSecurityChecks
|
||||
}
|
||||
|
||||
func (r *RuleResponse) PatchedTarget() (*unstructured.Unstructured, metav1.GroupVersionResource, string) {
|
||||
return r.patchedTarget, r.patchedTargetParentResourceGVR, r.patchedTargetSubresourceName
|
||||
}
|
||||
|
||||
func (r *RuleResponse) GeneratedResource() unstructured.Unstructured {
|
||||
return r.generatedResource
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Patches() [][]byte {
|
||||
return r.patches
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Message() string {
|
||||
return r.message
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Name() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r *RuleResponse) RuleType() RuleType {
|
||||
return r.ruleType
|
||||
}
|
||||
|
||||
func (r *RuleResponse) Status() RuleStatus {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// HasStatus checks if rule status is in a given list
|
||||
func (r RuleResponse) HasStatus(status ...RuleStatus) bool {
|
||||
func (r *RuleResponse) HasStatus(status ...RuleStatus) bool {
|
||||
for _, s := range status {
|
||||
if r.Status == s {
|
||||
if r.status == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +169,6 @@ func (r RuleResponse) HasStatus(status ...RuleStatus) bool {
|
|||
}
|
||||
|
||||
// String implements Stringer interface
|
||||
func (r RuleResponse) String() string {
|
||||
return fmt.Sprintf("rule %s (%s): %v", r.Name, r.Type, r.Message)
|
||||
func (r *RuleResponse) String() string {
|
||||
return fmt.Sprintf("rule %s (%s): %v", r.name, r.ruleType, r.message)
|
||||
}
|
||||
|
|
|
@ -2,24 +2,14 @@ package api
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func TestRuleResponse_String(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Type RuleType
|
||||
Message string
|
||||
Patches [][]byte
|
||||
GeneratedResource unstructured.Unstructured
|
||||
Status RuleStatus
|
||||
Stats ExecutionStats
|
||||
PatchedTarget *unstructured.Unstructured
|
||||
PatchedTargetSubresourceName string
|
||||
PatchedTargetParentResourceGVR metav1.GroupVersionResource
|
||||
PodSecurityChecks *PodSecurityChecks
|
||||
Name string
|
||||
Type RuleType
|
||||
Message string
|
||||
Status RuleStatus
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -56,19 +46,12 @@ func TestRuleResponse_String(t *testing.T) {
|
|||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rr := RuleResponse{
|
||||
Name: tt.fields.Name,
|
||||
Type: tt.fields.Type,
|
||||
Message: tt.fields.Message,
|
||||
Patches: tt.fields.Patches,
|
||||
GeneratedResource: tt.fields.GeneratedResource,
|
||||
Status: tt.fields.Status,
|
||||
Stats: tt.fields.Stats,
|
||||
PatchedTarget: tt.fields.PatchedTarget,
|
||||
PatchedTargetSubresourceName: tt.fields.PatchedTargetSubresourceName,
|
||||
PatchedTargetParentResourceGVR: tt.fields.PatchedTargetParentResourceGVR,
|
||||
PodSecurityChecks: tt.fields.PodSecurityChecks,
|
||||
}
|
||||
rr := NewRuleResponse(
|
||||
tt.fields.Name,
|
||||
tt.fields.Type,
|
||||
tt.fields.Message,
|
||||
tt.fields.Status,
|
||||
)
|
||||
if got := rr.String(); got != tt.want {
|
||||
t.Errorf("RuleResponse.ToString() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
@ -78,17 +61,10 @@ func TestRuleResponse_String(t *testing.T) {
|
|||
|
||||
func TestRuleResponse_HasStatus(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Type RuleType
|
||||
Message string
|
||||
Patches [][]byte
|
||||
GeneratedResource unstructured.Unstructured
|
||||
Status RuleStatus
|
||||
Stats ExecutionStats
|
||||
PatchedTarget *unstructured.Unstructured
|
||||
PatchedTargetSubresourceName string
|
||||
PatchedTargetParentResourceGVR metav1.GroupVersionResource
|
||||
PodSecurityChecks *PodSecurityChecks
|
||||
Name string
|
||||
Type RuleType
|
||||
Message string
|
||||
Status RuleStatus
|
||||
}
|
||||
type args struct {
|
||||
status []RuleStatus
|
||||
|
@ -138,19 +114,12 @@ func TestRuleResponse_HasStatus(t *testing.T) {
|
|||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := RuleResponse{
|
||||
Name: tt.fields.Name,
|
||||
Type: tt.fields.Type,
|
||||
Message: tt.fields.Message,
|
||||
Patches: tt.fields.Patches,
|
||||
GeneratedResource: tt.fields.GeneratedResource,
|
||||
Status: tt.fields.Status,
|
||||
Stats: tt.fields.Stats,
|
||||
PatchedTarget: tt.fields.PatchedTarget,
|
||||
PatchedTargetSubresourceName: tt.fields.PatchedTargetSubresourceName,
|
||||
PatchedTargetParentResourceGVR: tt.fields.PatchedTargetParentResourceGVR,
|
||||
PodSecurityChecks: tt.fields.PodSecurityChecks,
|
||||
}
|
||||
r := NewRuleResponse(
|
||||
tt.fields.Name,
|
||||
tt.fields.Type,
|
||||
tt.fields.Message,
|
||||
tt.fields.Status,
|
||||
)
|
||||
if got := r.HasStatus(tt.args.status...); got != tt.want {
|
||||
t.Errorf("RuleResponse.HasStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func (e *engine) filterRules(
|
|||
logger := internal.LoggerWithRule(logger, rule)
|
||||
if ruleResp := e.filterRule(rule, logger, policyContext); ruleResp != nil {
|
||||
resp.Rules = append(resp.Rules, *ruleResp)
|
||||
if applyRules == kyvernov1.ApplyOne && ruleResp.Status != engineapi.RuleStatusSkip {
|
||||
if applyRules == kyvernov1.ApplyOne && ruleResp.Status() != engineapi.RuleStatusSkip {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -67,8 +67,6 @@ func (e *engine) filterRule(
|
|||
return ruleResp
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
newResource := policyContext.NewResource()
|
||||
oldResource := policyContext.OldResource()
|
||||
admissionInfo := policyContext.AdmissionInfo()
|
||||
|
@ -81,15 +79,7 @@ func (e *engine) filterRule(
|
|||
if ruleType == engineapi.Generation {
|
||||
// if the oldResource matched, return "false" to delete GR for it
|
||||
if err = engineutils.MatchesResourceDescription(oldResource, rule, admissionInfo, namespaceLabels, policy.GetNamespace(), gvk, subresource, policyContext.Operation()); err == nil {
|
||||
return &engineapi.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Stats: engineapi.ExecutionStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
Timestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
return engineapi.RuleFail(rule.Name, ruleType, "")
|
||||
}
|
||||
}
|
||||
logger.V(4).Info("rule not matched", "reason", err.Error())
|
||||
|
@ -122,17 +112,9 @@ func (e *engine) filterRule(
|
|||
// evaluate pre-conditions
|
||||
if !variables.EvaluateConditions(logger, ctx, copyConditions) {
|
||||
logger.V(4).Info("skip rule as preconditions are not met", "rule", ruleCopy.Name)
|
||||
return internal.RuleSkip(*ruleCopy, ruleType, "")
|
||||
return engineapi.RuleSkip(ruleCopy.Name, ruleType, "")
|
||||
}
|
||||
|
||||
// build rule Response
|
||||
return &engineapi.RuleResponse{
|
||||
Name: ruleCopy.Name,
|
||||
Type: ruleType,
|
||||
Status: engineapi.RuleStatusPass,
|
||||
Stats: engineapi.ExecutionStats{
|
||||
ProcessingTime: time.Since(startTime),
|
||||
Timestamp: startTime.Unix(),
|
||||
},
|
||||
}
|
||||
return engineapi.RulePass(ruleCopy.Name, ruleType, "")
|
||||
}
|
||||
|
|
|
@ -227,13 +227,13 @@ func (e *engine) invokeRuleHandler(
|
|||
return resource, nil
|
||||
}
|
||||
if handlerFactory == nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to instantiate handler", nil))
|
||||
return resource, handlers.WithError(rule, ruleType, "failed to instantiate handler", nil)
|
||||
} else if handler, err := handlerFactory(); err != nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to instantiate handler", err))
|
||||
return resource, handlers.WithError(rule, ruleType, "failed to instantiate handler", err)
|
||||
} else if handler != nil {
|
||||
// check if there's an exception
|
||||
if ruleResp := e.hasPolicyExceptions(logger, ruleType, policyContext, rule); ruleResp != nil {
|
||||
return resource, handlers.RuleResponses(ruleResp)
|
||||
return resource, handlers.WithResponses(ruleResp)
|
||||
}
|
||||
// load rule context
|
||||
contextLoader := e.ContextLoader(policyContext.Policy(), rule)
|
||||
|
@ -243,15 +243,15 @@ func (e *engine) invokeRuleHandler(
|
|||
} else {
|
||||
logger.Error(err, "failed to load context")
|
||||
}
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to load context", err))
|
||||
return resource, handlers.WithError(rule, ruleType, "failed to load context", err)
|
||||
}
|
||||
// check preconditions
|
||||
preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions())
|
||||
if err != nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to evaluate preconditions", err))
|
||||
return resource, handlers.WithError(rule, ruleType, "failed to evaluate preconditions", err)
|
||||
}
|
||||
if !preconditionsPassed {
|
||||
return resource, handlers.RuleResponses(internal.RuleSkip(rule, ruleType, "preconditions not met"))
|
||||
return resource, handlers.WithSkip(rule, ruleType, "preconditions not met")
|
||||
}
|
||||
// process handler
|
||||
return handler.Process(ctx, logger, policyContext, resource, rule, contextLoader)
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
matched "github.com/kyverno/kyverno/pkg/utils/match"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
@ -79,18 +78,19 @@ func (e *engine) hasPolicyExceptions(
|
|||
) *engineapi.RuleResponse {
|
||||
// if matches, check if there is a corresponding policy exception
|
||||
exception, err := matchesException(e.exceptionSelector, ctx, rule, e.configuration)
|
||||
var response *engineapi.RuleResponse
|
||||
// if we found an exception
|
||||
if err == nil && exception != nil {
|
||||
key, err := cache.MetaNamespaceKeyFunc(exception)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
|
||||
response = internal.RuleError(rule, ruleType, "failed to compute exception key", err)
|
||||
} else {
|
||||
logger.V(3).Info("policy rule skipped due to policy exception", "exception", key)
|
||||
response = internal.RuleSkip(rule, ruleType, "rule skipped due to policy exception "+key)
|
||||
response.Exception = exception
|
||||
}
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to match exceptions")
|
||||
return nil
|
||||
}
|
||||
if exception == nil {
|
||||
return nil
|
||||
}
|
||||
key, err := cache.MetaNamespaceKeyFunc(exception)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
|
||||
return engineapi.RuleError(rule.Name, ruleType, "failed to compute exception key", err)
|
||||
} else {
|
||||
logger.V(3).Info("policy rule skipped due to policy exception", "exception", key)
|
||||
return engineapi.RuleSkip(rule.Name, ruleType, "rule skipped due to policy exception "+key).WithException(exception)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ func applyForEachMutate(name string, foreach []kyvernov1.ForEachMutation, resour
|
|||
func applyPatches(name string, mergePatch apiextensions.JSON, jsonPatch string, resource unstructured.Unstructured, logger logr.Logger) (unstructured.Unstructured, error) {
|
||||
patcher := mutate.NewPatcher(name, mergePatch, jsonPatch, resource, logger)
|
||||
resp, mutatedResource := patcher.Patch()
|
||||
if resp.Status != engineapi.RuleStatusPass {
|
||||
return mutatedResource, fmt.Errorf("mutate status %q: %s", resp.Status, resp.Message)
|
||||
if resp.Status() != engineapi.RuleStatusPass {
|
||||
return mutatedResource, fmt.Errorf("mutate status %q: %s", resp.Status(), resp.Message())
|
||||
}
|
||||
|
||||
return mutatedResource, nil
|
||||
|
|
|
@ -20,7 +20,23 @@ type Handler interface {
|
|||
) (unstructured.Unstructured, []engineapi.RuleResponse)
|
||||
}
|
||||
|
||||
func RuleResponses(rrs ...*engineapi.RuleResponse) []engineapi.RuleResponse {
|
||||
func WithError(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, err error) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleError(rule.Name, ruleType, msg, err))
|
||||
}
|
||||
|
||||
func WithSkip(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleSkip(rule.Name, ruleType, msg))
|
||||
}
|
||||
|
||||
func WithPass(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RulePass(rule.Name, ruleType, msg))
|
||||
}
|
||||
|
||||
func WithFail(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) []engineapi.RuleResponse {
|
||||
return WithResponses(engineapi.RuleFail(rule.Name, ruleType, msg))
|
||||
}
|
||||
|
||||
func WithResponses(rrs ...*engineapi.RuleResponse) []engineapi.RuleResponse {
|
||||
var out []engineapi.RuleResponse
|
||||
for _, rr := range rrs {
|
||||
if rr != nil {
|
||||
|
|
|
@ -134,15 +134,21 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F
|
|||
}
|
||||
|
||||
func buildRuleResponse(rule *kyvernov1.Rule, mutateResp *mutate.Response, info resourceInfo) *engineapi.RuleResponse {
|
||||
resp := internal.RuleResponse(*rule, engineapi.Mutation, mutateResp.Message, mutateResp.Status)
|
||||
if resp.Status == engineapi.RuleStatusPass {
|
||||
resp.Patches = mutateResp.Patches
|
||||
resp.Message = buildSuccessMessage(mutateResp.PatchedResource)
|
||||
message := mutateResp.Message
|
||||
if mutateResp.Status == engineapi.RuleStatusPass {
|
||||
message = buildSuccessMessage(mutateResp.PatchedResource)
|
||||
}
|
||||
if len(rule.Mutation.Targets) != 0 {
|
||||
resp.PatchedTarget = &mutateResp.PatchedResource
|
||||
resp.PatchedTargetSubresourceName = info.subresource
|
||||
resp.PatchedTargetParentResourceGVR = info.parentResourceGVR
|
||||
resp := engineapi.NewRuleResponse(
|
||||
rule.Name,
|
||||
engineapi.Mutation,
|
||||
message,
|
||||
mutateResp.Status,
|
||||
)
|
||||
if mutateResp.Status == engineapi.RuleStatusPass {
|
||||
resp = resp.WithPatches(mutateResp.Patches...)
|
||||
if len(rule.Mutation.Targets) != 0 {
|
||||
resp = resp.WithPatchedTarget(&mutateResp.PatchedResource, info.parentResourceGVR, info.subresource)
|
||||
}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func (h mutateExistingHandler) Process(
|
|||
logger.V(3).Info("processing mutate rule")
|
||||
targets, err := loadTargets(h.client, rule.Mutation.Targets, policyContext, logger)
|
||||
if err != nil {
|
||||
rr := internal.RuleError(rule, engineapi.Mutation, "", err)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "", err)
|
||||
responses = append(responses, *rr)
|
||||
}
|
||||
|
||||
|
@ -52,19 +52,19 @@ func (h mutateExistingHandler) Process(
|
|||
}
|
||||
// load target specific context
|
||||
if err := contextLoader(ctx, target.context, policyContext.JSONContext()); err != nil {
|
||||
rr := internal.RuleError(rule, engineapi.Mutation, "failed to load context", err)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to load context", err)
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
// load target specific preconditions
|
||||
preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), target.preconditions)
|
||||
if err != nil {
|
||||
rr := internal.RuleError(rule, engineapi.Mutation, "failed to evaluate preconditions", err)
|
||||
rr := engineapi.RuleError(rule.Name, engineapi.Mutation, "failed to evaluate preconditions", err)
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
if !preconditionsPassed {
|
||||
rr := internal.RuleSkip(rule, engineapi.Mutation, "preconditions not met")
|
||||
rr := engineapi.RuleSkip(rule.Name, engineapi.Mutation, "preconditions not met")
|
||||
responses = append(responses, *rr)
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ func (h mutateImageHandler) Process(
|
|||
jsonContext := policyContext.JSONContext()
|
||||
ruleCopy, err := substituteVariables(rule, jsonContext, logger)
|
||||
if err != nil {
|
||||
return resource, handlers.RuleResponses(
|
||||
internal.RuleError(rule, engineapi.ImageVerify, "failed to substitute variables", err),
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to substitute variables", err),
|
||||
)
|
||||
}
|
||||
iv := internal.NewImageVerifier(logger, h.rclient, policyContext, *ruleCopy, h.ivm)
|
||||
|
@ -70,7 +70,7 @@ func (h mutateImageHandler) Process(
|
|||
for _, imageVerify := range ruleCopy.VerifyImages {
|
||||
engineResponses = append(engineResponses, iv.Verify(ctx, imageVerify, h.images, h.configuration)...)
|
||||
}
|
||||
return resource, handlers.RuleResponses(engineResponses...)
|
||||
return resource, handlers.WithResponses(engineResponses...)
|
||||
}
|
||||
|
||||
func substituteVariables(rule kyvernov1.Rule, ctx enginecontext.EvalInterface, logger logr.Logger) (*kyvernov1.Rule, error) {
|
||||
|
|
|
@ -56,5 +56,5 @@ func (h mutateResourceHandler) Process(
|
|||
if mutateResp == nil {
|
||||
return resource, nil
|
||||
}
|
||||
return mutateResp.PatchedResource, handlers.RuleResponses(buildRuleResponse(&rule, mutateResp, resourceInfo))
|
||||
return mutateResp.PatchedResource, handlers.WithResponses(buildRuleResponse(&rule, mutateResp, resourceInfo))
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/handlers"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -57,13 +56,13 @@ func (h validateImageHandler) Process(
|
|||
|
||||
logger.V(4).Info("validating image", "image", image)
|
||||
if err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleResponse(rule, engineapi.ImageVerify, err.Error(), engineapi.RuleStatusFail))
|
||||
return resource, handlers.WithFail(rule, engineapi.ImageVerify, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.V(4).Info("validated image", "rule", rule.Name)
|
||||
return resource, handlers.RuleResponses(internal.RulePass(rule, engineapi.Validation, "image verified"))
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, "image verified")
|
||||
}
|
||||
|
||||
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) error {
|
||||
|
|
|
@ -62,13 +62,13 @@ func (h validateManifestHandler) Process(
|
|||
verified, reason, err := h.verifyManifest(ctx, logger, policyContext, *rule.Validation.Manifests)
|
||||
if err != nil {
|
||||
logger.V(3).Info("verifyManifest return err", "error", err.Error())
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "error occurred during manifest verification", err))
|
||||
return resource, handlers.WithError(rule, engineapi.Validation, "error occurred during manifest verification", err)
|
||||
}
|
||||
logger.V(3).Info("verifyManifest result", "verified", strconv.FormatBool(verified), "reason", reason)
|
||||
if !verified {
|
||||
return resource, handlers.RuleResponses(internal.RuleResponse(rule, engineapi.Validation, reason, engineapi.RuleStatusFail))
|
||||
return resource, handlers.WithFail(rule, engineapi.Validation, reason)
|
||||
}
|
||||
return resource, handlers.RuleResponses(internal.RulePass(rule, engineapi.Validation, reason))
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, reason)
|
||||
}
|
||||
|
||||
func (h validateManifestHandler) verifyManifest(
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/engine/handlers"
|
||||
"github.com/kyverno/kyverno/pkg/engine/internal"
|
||||
"github.com/kyverno/kyverno/pkg/pss"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
|
@ -36,7 +35,7 @@ func (h validatePssHandler) Process(
|
|||
podSecurity := rule.Validation.PodSecurity
|
||||
podSpec, metadata, err := getSpec(resource)
|
||||
if err != nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "Error while getting new resource", err))
|
||||
return resource, handlers.WithError(rule, engineapi.Validation, "Error while getting new resource", err)
|
||||
}
|
||||
pod := &corev1.Pod{
|
||||
Spec: *podSpec,
|
||||
|
@ -44,23 +43,23 @@ func (h validatePssHandler) Process(
|
|||
}
|
||||
allowed, pssChecks, err := pss.EvaluatePod(podSecurity, pod)
|
||||
if err != nil {
|
||||
return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to parse pod security api version", err))
|
||||
return resource, handlers.WithError(rule, engineapi.Validation, "failed to parse pod security api version", err)
|
||||
}
|
||||
podSecurityChecks := &engineapi.PodSecurityChecks{
|
||||
podSecurityChecks := engineapi.PodSecurityChecks{
|
||||
Level: podSecurity.Level,
|
||||
Version: podSecurity.Version,
|
||||
Checks: pssChecks,
|
||||
}
|
||||
if allowed {
|
||||
msg := fmt.Sprintf("Validation rule '%s' passed.", rule.Name)
|
||||
rspn := internal.RulePass(rule, engineapi.Validation, msg)
|
||||
rspn.PodSecurityChecks = podSecurityChecks
|
||||
return resource, handlers.RuleResponses(rspn)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RulePass(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
|
||||
)
|
||||
} else {
|
||||
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, rule.Name, podSecurity.Level, podSecurity.Version, pss.FormatChecksPrint(pssChecks))
|
||||
rspn := internal.RuleResponse(rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
rspn.PodSecurityChecks = podSecurityChecks
|
||||
return resource, handlers.RuleResponses(rspn)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleFail(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ func (h validateResourceHandler) Process(
|
|||
contextLoader engineapi.EngineContextLoader,
|
||||
) (unstructured.Unstructured, []engineapi.RuleResponse) {
|
||||
v := newValidator(logger, contextLoader, policyContext, rule)
|
||||
return resource, handlers.RuleResponses(v.validate(ctx))
|
||||
return resource, handlers.WithResponses(v.validate(ctx))
|
||||
}
|
||||
|
||||
type validator struct {
|
||||
|
@ -99,14 +99,14 @@ func newForEachValidator(
|
|||
|
||||
func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
||||
if err := v.loadContext(ctx); err != nil {
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to load context", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to load context", err)
|
||||
}
|
||||
preconditionsPassed, err := internal.CheckPreconditions(v.log, v.policyContext.JSONContext(), v.anyAllConditions)
|
||||
if err != nil {
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to evaluate preconditions", err)
|
||||
}
|
||||
if !preconditionsPassed {
|
||||
return internal.RuleSkip(v.rule, engineapi.Validation, "preconditions not met")
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, "preconditions not met")
|
||||
}
|
||||
|
||||
if v.deny != nil {
|
||||
|
@ -115,7 +115,7 @@ func (v *validator) validate(ctx context.Context) *engineapi.RuleResponse {
|
|||
|
||||
if v.pattern != nil || v.anyPattern != nil {
|
||||
if err = v.substitutePatterns(); err != nil {
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "variable substitution failed", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "variable substitution failed", err)
|
||||
}
|
||||
|
||||
ruleResponse := v.validateResourceWithRule()
|
||||
|
@ -140,7 +140,7 @@ func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse
|
|||
continue
|
||||
}
|
||||
resp, count := v.validateElements(ctx, foreach, elements, foreach.ElementScope)
|
||||
if resp.Status != engineapi.RuleStatusPass {
|
||||
if resp.Status() != engineapi.RuleStatusPass {
|
||||
return resp
|
||||
}
|
||||
applyCount += count
|
||||
|
@ -149,9 +149,9 @@ func (v *validator) validateForEach(ctx context.Context) *engineapi.RuleResponse
|
|||
if v.forEach == nil {
|
||||
return nil
|
||||
}
|
||||
return internal.RuleSkip(v.rule, engineapi.Validation, "rule skipped")
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, "rule skipped")
|
||||
}
|
||||
return internal.RulePass(v.rule, engineapi.Validation, "rule passed")
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, "rule passed")
|
||||
}
|
||||
|
||||
func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForEachValidation, elements []interface{}, elementScope *bool) (*engineapi.RuleResponse, int) {
|
||||
|
@ -168,38 +168,40 @@ func (v *validator) validateElements(ctx context.Context, foreach kyvernov1.ForE
|
|||
policyContext := v.policyContext.Copy()
|
||||
if err := engineutils.AddElementToContext(policyContext, element, index, v.nesting, elementScope); err != nil {
|
||||
v.log.Error(err, "failed to add element to context")
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to process foreach", err), applyCount
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to process foreach", err), applyCount
|
||||
}
|
||||
|
||||
foreachValidator, err := newForEachValidator(foreach, v.contextLoader, v.nesting+1, v.rule, policyContext, v.log)
|
||||
if err != nil {
|
||||
v.log.Error(err, "failed to create foreach validator")
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to create foreach validator", err), applyCount
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to create foreach validator", err), applyCount
|
||||
}
|
||||
|
||||
r := foreachValidator.validate(ctx)
|
||||
if r == nil {
|
||||
v.log.V(2).Info("skip rule due to empty result")
|
||||
continue
|
||||
} else if r.Status == engineapi.RuleStatusSkip {
|
||||
v.log.V(2).Info("skip rule", "reason", r.Message)
|
||||
}
|
||||
status := r.Status()
|
||||
if status == engineapi.RuleStatusSkip {
|
||||
v.log.V(2).Info("skip rule", "reason", r.Message())
|
||||
continue
|
||||
} else if r.Status != engineapi.RuleStatusPass {
|
||||
if r.Status == engineapi.RuleStatusError {
|
||||
} else if status != engineapi.RuleStatusPass {
|
||||
if status == engineapi.RuleStatusError {
|
||||
if index < len(elements)-1 {
|
||||
continue
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message())
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status), applyCount
|
||||
}
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message)
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, msg, r.Status), applyCount
|
||||
msg := fmt.Sprintf("validation failure: %v", r.Message())
|
||||
return engineapi.NewRuleResponse(v.rule.Name, engineapi.Validation, msg, status), applyCount
|
||||
}
|
||||
|
||||
applyCount++
|
||||
}
|
||||
|
||||
return internal.RulePass(v.rule, engineapi.Validation, ""), applyCount
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, ""), applyCount
|
||||
}
|
||||
|
||||
func (v *validator) loadContext(ctx context.Context) error {
|
||||
|
@ -216,12 +218,12 @@ func (v *validator) loadContext(ctx context.Context) error {
|
|||
|
||||
func (v *validator) validateDeny() *engineapi.RuleResponse {
|
||||
if deny, err := internal.CheckDenyPreconditions(v.log, v.policyContext.JSONContext(), v.deny.GetAnyAllConditions()); err != nil {
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to check deny preconditions", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to check deny preconditions", err)
|
||||
} else {
|
||||
if deny {
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, v.getDenyMessage(deny), engineapi.RuleStatusFail)
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny))
|
||||
}
|
||||
return internal.RulePass(v.rule, engineapi.Validation, v.getDenyMessage(deny))
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.getDenyMessage(deny))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,22 +269,22 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
|
||||
|
||||
if pe.Skip {
|
||||
return internal.RuleSkip(v.rule, engineapi.Validation, pe.Error())
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, pe.Error())
|
||||
}
|
||||
|
||||
if pe.Path == "" {
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, v.buildErrorMessage(err, ""), engineapi.RuleStatusError)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil)
|
||||
}
|
||||
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusFail)
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path))
|
||||
}
|
||||
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, v.buildErrorMessage(err, pe.Path), engineapi.RuleStatusError)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path), nil)
|
||||
}
|
||||
|
||||
v.log.V(4).Info("successfully processed rule")
|
||||
msg := fmt.Sprintf("validation rule '%s' passed.", v.rule.Name)
|
||||
return internal.RulePass(v.rule, engineapi.Validation, msg)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg)
|
||||
}
|
||||
|
||||
if v.anyPattern != nil {
|
||||
|
@ -292,14 +294,14 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
|
||||
anyPatterns, err := deserializeAnyPattern(v.anyPattern)
|
||||
if err != nil {
|
||||
return internal.RuleError(v.rule, engineapi.Validation, "failed to deserialize anyPattern, expected type array", err)
|
||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, "failed to deserialize anyPattern, expected type array", err)
|
||||
}
|
||||
|
||||
for idx, pattern := range anyPatterns {
|
||||
err := validate.MatchPattern(v.log, resource.Object, pattern)
|
||||
if err == nil {
|
||||
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
||||
return internal.RulePass(v.rule, engineapi.Validation, msg)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, msg)
|
||||
}
|
||||
|
||||
if pe, ok := err.(*validate.PatternError); ok {
|
||||
|
@ -327,7 +329,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
errorStr = append(errorStr, err.Error())
|
||||
}
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' skipped. %s", v.rule.Name, errorStr))
|
||||
return internal.RuleSkip(v.rule, engineapi.Validation, strings.Join(errorStr, " "))
|
||||
return engineapi.RuleSkip(v.rule.Name, engineapi.Validation, strings.Join(errorStr, " "))
|
||||
} else if len(failedAnyPatternsErrors) > 0 {
|
||||
var errorStr []string
|
||||
for _, err := range failedAnyPatternsErrors {
|
||||
|
@ -336,11 +338,11 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
|||
|
||||
v.log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", v.rule.Name, errorStr))
|
||||
msg := buildAnyPatternErrorMessage(v.rule, errorStr)
|
||||
return internal.RuleResponse(v.rule, engineapi.Validation, msg, engineapi.RuleStatusFail)
|
||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, msg)
|
||||
}
|
||||
}
|
||||
|
||||
return internal.RulePass(v.rule, engineapi.Validation, v.rule.Validation.Message)
|
||||
return engineapi.RulePass(v.rule.Name, engineapi.Validation, v.rule.Validation.Message)
|
||||
}
|
||||
|
||||
func deserializeAnyPattern(anyPattern apiextensions.JSON) ([]interface{}, error) {
|
||||
|
|
|
@ -53,10 +53,9 @@ func (e *engine) verifyAndPatchImages(
|
|||
engineapi.ImageVerify,
|
||||
)
|
||||
matchedResource = resource
|
||||
endTime := time.Now()
|
||||
for _, ruleResp := range ruleResp {
|
||||
ruleResp := ruleResp
|
||||
internal.AddRuleResponse(&resp, &ruleResp, startTime)
|
||||
logger.V(4).Info("finished processing rule", "processingTime", ruleResp.Stats.ProcessingTime.String())
|
||||
resp.Add(startTime, endTime, ruleResp)
|
||||
}
|
||||
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
|
||||
break
|
||||
|
|
|
@ -194,9 +194,9 @@ func Test_CosignMockAttest(t *testing.T) {
|
|||
|
||||
er, ivm := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass,
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass,
|
||||
fmt.Sprintf("expected: %v, got: %v, failure: %v",
|
||||
engineapi.RuleStatusPass, er.PolicyResponse.Rules[0].Status, er.PolicyResponse.Rules[0].Message))
|
||||
engineapi.RuleStatusPass, er.PolicyResponse.Rules[0].Status(), er.PolicyResponse.Rules[0].Message()))
|
||||
assert.Equal(t, ivm.IsEmpty(), false)
|
||||
assert.Equal(t, ivm.IsVerified("ghcr.io/jimbugwadia/pause2:latest"), true)
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ func Test_CosignMockAttest_fail(t *testing.T) {
|
|||
|
||||
er, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
}
|
||||
|
||||
func buildContext(t *testing.T, policy, resource string, oldResource string) *PolicyContext {
|
||||
|
@ -465,7 +465,7 @@ func Test_ConfigMapMissingFailure(t *testing.T) {
|
|||
cosign.ClearMock()
|
||||
resp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), resolver, policyContext, cfg)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError, resp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusError, resp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignatureGoodSigned(t *testing.T) {
|
||||
|
@ -474,9 +474,9 @@ func Test_SignatureGoodSigned(t *testing.T) {
|
|||
cosign.ClearMock()
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules[0].Patches), 1)
|
||||
patch := engineResp.PolicyResponse.Rules[0].Patches[0]
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message())
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules[0].Patches()), 1)
|
||||
patch := engineResp.PolicyResponse.Rules[0].Patches()[0]
|
||||
assert.Equal(t, string(patch), "{\"op\":\"replace\",\"path\":\"/spec/containers/0/image\",\"value\":\"ghcr.io/kyverno/test-verify-image:signed@sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105\"}")
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ func Test_SignatureUnsigned(t *testing.T) {
|
|||
policyContext := buildContext(t, testSampleSingleKeyPolicy, unsigned, "")
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignatureWrongKey(t *testing.T) {
|
||||
|
@ -495,7 +495,7 @@ func Test_SignatureWrongKey(t *testing.T) {
|
|||
policyContext := buildContext(t, testSampleSingleKeyPolicy, otherKey, "")
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignaturesMultiKey(t *testing.T) {
|
||||
|
@ -506,7 +506,7 @@ func Test_SignaturesMultiKey(t *testing.T) {
|
|||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignaturesMultiKeyFail(t *testing.T) {
|
||||
|
@ -516,7 +516,7 @@ func Test_SignaturesMultiKeyFail(t *testing.T) {
|
|||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail, engineResp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignaturesMultiKeyOneGoodKey(t *testing.T) {
|
||||
|
@ -527,7 +527,7 @@ func Test_SignaturesMultiKeyOneGoodKey(t *testing.T) {
|
|||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
engineResp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, engineResp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, engineResp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_SignaturesMultiKeyZeroGoodKey(t *testing.T) {
|
||||
|
@ -538,7 +538,7 @@ func Test_SignaturesMultiKeyZeroGoodKey(t *testing.T) {
|
|||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
resp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail, resp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail, resp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func Test_RuleSelectorImageVerify(t *testing.T) {
|
||||
|
@ -554,14 +554,14 @@ func Test_RuleSelectorImageVerify(t *testing.T) {
|
|||
|
||||
resp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 2)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[1].Status, engineapi.RuleStatusFail, resp.PolicyResponse.Rules[1].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[1].Status(), engineapi.RuleStatusFail, resp.PolicyResponse.Rules[1].Message())
|
||||
|
||||
applyOne := kyverno.ApplyOne
|
||||
spec.ApplyRules = &applyOne
|
||||
resp, _ = testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
||||
}
|
||||
|
||||
func newStaticKeyRule(name, imageReference, key string) *kyverno.Rule {
|
||||
|
@ -665,7 +665,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
err, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
policy = strings.Replace(testNestedAttestorPolicy, "KEY1", testVerifyImageKey, -1)
|
||||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
|
@ -673,7 +673,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policyContext = buildContext(t, policy, testSampleResource, "")
|
||||
err, _ = testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
|
||||
policy = strings.Replace(testNestedAttestorPolicy, "KEY1", testVerifyImageKey, -1)
|
||||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
|
@ -681,7 +681,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policyContext = buildContext(t, policy, testSampleResource, "")
|
||||
err, _ = testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func Test_ExpandKeys(t *testing.T) {
|
||||
|
@ -773,7 +773,7 @@ func Test_MarkImageVerified(t *testing.T) {
|
|||
|
||||
engineResponse, verifiedImages := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResponse.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
assert.Assert(t, verifiedImages.Data != nil)
|
||||
assert.Equal(t, len(verifiedImages.Data), 1)
|
||||
|
@ -864,7 +864,7 @@ func Test_ParsePEMDelimited(t *testing.T) {
|
|||
|
||||
engineResponse, verifiedImages := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||
assert.Equal(t, len(engineResponse.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
assert.Assert(t, verifiedImages.Data != nil)
|
||||
assert.Equal(t, len(verifiedImages.Data), 1)
|
||||
|
|
|
@ -197,7 +197,7 @@ func (iv *ImageVerifier) Verify(
|
|||
if HasImageVerifiedAnnotationChanged(iv.policyContext, iv.logger) {
|
||||
msg := engineapi.ImageVerifyAnnotationKey + " annotation cannot be changed"
|
||||
iv.logger.Info("image verification error", "reason", msg)
|
||||
responses = append(responses, RuleResponse(iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail))
|
||||
responses = append(responses, engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -219,12 +219,12 @@ func (iv *ImageVerifier) Verify(
|
|||
if imageVerify.MutateDigest {
|
||||
patch, retrievedDigest, err := iv.handleMutateDigest(ctx, digest, imageInfo)
|
||||
if err != nil {
|
||||
responses = append(responses, RuleError(iv.rule, engineapi.ImageVerify, "failed to update digest", err))
|
||||
responses = append(responses, engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "failed to update digest", err))
|
||||
} else if patch != nil {
|
||||
if ruleResp == nil {
|
||||
ruleResp = RulePass(iv.rule, engineapi.ImageVerify, "mutated image digest")
|
||||
ruleResp = engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, "mutated image digest")
|
||||
}
|
||||
ruleResp.Patches = append(ruleResp.Patches, patch)
|
||||
ruleResp = ruleResp.WithPatches(patch)
|
||||
imageInfo.Digest = retrievedDigest
|
||||
image = imageInfo.String()
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ func (iv *ImageVerifier) Verify(
|
|||
|
||||
if ruleResp != nil {
|
||||
if len(imageVerify.Attestors) > 0 || len(imageVerify.Attestations) > 0 {
|
||||
iv.ivm.Add(image, ruleResp.Status == engineapi.RuleStatusPass)
|
||||
iv.ivm.Add(image, ruleResp.Status() == engineapi.RuleStatusPass)
|
||||
}
|
||||
responses = append(responses, ruleResp)
|
||||
}
|
||||
|
@ -253,14 +253,14 @@ func (iv *ImageVerifier) verifyImage(
|
|||
iv.logger.V(2).Info("verifying image signatures", "image", image, "attestors", len(imageVerify.Attestors), "attestations", len(imageVerify.Attestations))
|
||||
if err := iv.policyContext.JSONContext().AddImageInfo(imageInfo, cfg); err != nil {
|
||||
iv.logger.Error(err, "failed to add image to context")
|
||||
return RuleError(iv.rule, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), ""
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to add image to context %s", image), err), ""
|
||||
}
|
||||
if len(imageVerify.Attestors) > 0 {
|
||||
if !matchImageReferences(imageVerify.ImageReferences, image) {
|
||||
return nil, ""
|
||||
}
|
||||
ruleResp, cosignResp := iv.verifyAttestors(ctx, imageVerify.Attestors, imageVerify, imageInfo, "")
|
||||
if ruleResp.Status != engineapi.RuleStatusPass {
|
||||
if ruleResp.Status() != engineapi.RuleStatusPass {
|
||||
return ruleResp, ""
|
||||
}
|
||||
if len(imageVerify.Attestations) == 0 {
|
||||
|
@ -299,10 +299,10 @@ func (iv *ImageVerifier) verifyAttestors(
|
|||
}
|
||||
}
|
||||
if cosignResponse == nil {
|
||||
return RuleError(iv.rule, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil")), nil
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, "invalid response", fmt.Errorf("nil")), nil
|
||||
}
|
||||
msg := fmt.Sprintf("verified image signatures for %s", image)
|
||||
return RulePass(iv.rule, engineapi.ImageVerify, msg), cosignResponse
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg), cosignResponse
|
||||
}
|
||||
|
||||
// handle registry network errors as a rule error (instead of a policy failure)
|
||||
|
@ -310,9 +310,9 @@ func (iv *ImageVerifier) handleRegistryErrors(image string, err error) *engineap
|
|||
msg := fmt.Sprintf("failed to verify image %s: %s", image, err.Error())
|
||||
var netErr *net.OpError
|
||||
if errors.As(err, &netErr) {
|
||||
return RuleError(iv.rule, engineapi.ImageVerify, fmt.Sprintf("failed to verify image %s", image), err)
|
||||
return engineapi.RuleError(iv.rule.Name, engineapi.ImageVerify, fmt.Sprintf("failed to verify image %s", image), err)
|
||||
}
|
||||
return RuleResponse(iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail)
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg)
|
||||
}
|
||||
|
||||
func (iv *ImageVerifier) verifyAttestations(
|
||||
|
@ -326,7 +326,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
path := fmt.Sprintf(".attestations[%d]", i)
|
||||
|
||||
if attestation.PredicateType == "" {
|
||||
return RuleResponse(iv.rule, engineapi.ImageVerify, path+": missing predicateType", engineapi.RuleStatusFail), ""
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, path+": missing predicateType"), ""
|
||||
}
|
||||
|
||||
if len(attestation.Attestors) == 0 {
|
||||
|
@ -356,7 +356,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
attestationError = iv.verifyAttestation(cosignResp.Statements, attestation, imageInfo)
|
||||
if attestationError != nil {
|
||||
attestationError = fmt.Errorf("%s: %w", entryPath+subPath, attestationError)
|
||||
return RuleResponse(iv.rule, engineapi.ImageVerify, attestationError.Error(), engineapi.RuleStatusFail), ""
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, attestationError.Error()), ""
|
||||
}
|
||||
|
||||
verifiedCount++
|
||||
|
@ -368,7 +368,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
|
||||
if verifiedCount < requiredCount {
|
||||
msg := fmt.Sprintf("image attestations verification failed, verifiedCount: %v, requiredCount: %v", verifiedCount, requiredCount)
|
||||
return RuleResponse(iv.rule, engineapi.ImageVerify, msg, engineapi.RuleStatusFail), ""
|
||||
return engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg), ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,7 +377,7 @@ func (iv *ImageVerifier) verifyAttestations(
|
|||
|
||||
msg := fmt.Sprintf("verified image attestations for %s", image)
|
||||
iv.logger.V(2).Info(msg)
|
||||
return RulePass(iv.rule, engineapi.ImageVerify, msg), imageInfo.Digest
|
||||
return engineapi.RulePass(iv.rule.Name, engineapi.ImageVerify, msg), imageInfo.Digest
|
||||
}
|
||||
|
||||
func (iv *ImageVerifier) verifyAttestorSet(
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
)
|
||||
|
||||
func RuleError(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, err error) *engineapi.RuleResponse {
|
||||
return RuleResponse(rule, ruleType, fmt.Sprintf("%s: %s", msg, err.Error()), engineapi.RuleStatusError)
|
||||
}
|
||||
|
||||
func RuleSkip(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) *engineapi.RuleResponse {
|
||||
return RuleResponse(rule, ruleType, msg, engineapi.RuleStatusSkip)
|
||||
}
|
||||
|
||||
func RulePass(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string) *engineapi.RuleResponse {
|
||||
return RuleResponse(rule, ruleType, msg, engineapi.RuleStatusPass)
|
||||
}
|
||||
|
||||
func RuleResponse(rule kyvernov1.Rule, ruleType engineapi.RuleType, msg string, status engineapi.RuleStatus) *engineapi.RuleResponse {
|
||||
resp := &engineapi.RuleResponse{
|
||||
Name: rule.Name,
|
||||
Type: ruleType,
|
||||
Message: msg,
|
||||
Status: status,
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func AddRuleResponse(resp *engineapi.PolicyResponse, ruleResp *engineapi.RuleResponse, startTime time.Time) {
|
||||
ruleResp.Stats.ProcessingTime = time.Since(startTime)
|
||||
ruleResp.Stats.Timestamp = startTime.Unix()
|
||||
resp.Rules = append(resp.Rules, *ruleResp)
|
||||
if ruleResp.Status == engineapi.RuleStatusPass || ruleResp.Status == engineapi.RuleStatusFail {
|
||||
resp.Stats.RulesAppliedCount++
|
||||
} else if ruleResp.Status == engineapi.RuleStatusError {
|
||||
resp.Stats.RulesErrorCount++
|
||||
}
|
||||
}
|
||||
|
||||
func BuildResponse(ctx engineapi.PolicyContext, resp *engineapi.EngineResponse, startTime time.Time) *engineapi.EngineResponse {
|
||||
if resp.PatchedResource.Object == nil {
|
||||
// for delete requests patched resource will be oldResource since newResource is empty
|
||||
resource := ctx.NewResource()
|
||||
if resource.Object == nil {
|
||||
resource = ctx.OldResource()
|
||||
}
|
||||
resp.PatchedResource = resource
|
||||
}
|
||||
resp.Stats.ProcessingTime = time.Since(startTime)
|
||||
resp.Stats.Timestamp = startTime.Unix()
|
||||
return resp
|
||||
}
|
|
@ -35,10 +35,10 @@ func (e *engine) reportMetrics(
|
|||
resourceKind := resourceSpec.GetKind()
|
||||
resourceNamespace := resourceSpec.GetNamespace()
|
||||
for _, rule := range response.PolicyResponse.Rules {
|
||||
ruleName := rule.Name
|
||||
ruleName := rule.Name()
|
||||
ruleType := metrics.ParseRuleTypeFromEngineRuleResponse(rule)
|
||||
var ruleResult metrics.RuleResult
|
||||
switch rule.Status {
|
||||
switch rule.Status() {
|
||||
case engineapi.RuleStatusPass:
|
||||
ruleResult = metrics.Pass
|
||||
case engineapi.RuleStatusFail:
|
||||
|
@ -88,7 +88,7 @@ func (e *engine) reportMetrics(
|
|||
attribute.String("rule_type", string(ruleType)),
|
||||
attribute.String("rule_execution_cause", string(executionCause)),
|
||||
}
|
||||
e.durationHistogram.Record(ctx, rule.Stats.ProcessingTime.Seconds(), commonLabels...)
|
||||
e.durationHistogram.Record(ctx, rule.Stats().ProcessingTime.Seconds(), commonLabels...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,11 +48,11 @@ func Mutate(rule *kyvernov1.Rule, ctx context.Interface, resource unstructured.U
|
|||
}
|
||||
|
||||
resp, patchedResource := patcher.Patch()
|
||||
if resp.Status != engineapi.RuleStatusPass {
|
||||
return NewResponse(resp.Status, resource, nil, resp.Message)
|
||||
if resp.Status() != engineapi.RuleStatusPass {
|
||||
return NewResponse(resp.Status(), resource, nil, resp.Message())
|
||||
}
|
||||
|
||||
if resp.Patches == nil {
|
||||
if resp.Patches() == nil {
|
||||
return NewResponse(engineapi.RuleStatusSkip, resource, nil, "no patches applied")
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ func Mutate(rule *kyvernov1.Rule, ctx context.Interface, resource unstructured.U
|
|||
}
|
||||
}
|
||||
|
||||
return NewResponse(engineapi.RuleStatusPass, patchedResource, resp.Patches, resp.Message)
|
||||
return NewResponse(engineapi.RuleStatusPass, patchedResource, resp.Patches(), resp.Message())
|
||||
}
|
||||
|
||||
func ForEach(name string, foreach kyvernov1.ForEachMutation, policyContext engineapi.PolicyContext, resource unstructured.Unstructured, element interface{}, logger logr.Logger) *Response {
|
||||
|
@ -82,11 +82,11 @@ func ForEach(name string, foreach kyvernov1.ForEachMutation, policyContext engin
|
|||
}
|
||||
|
||||
resp, patchedResource := patcher.Patch()
|
||||
if resp.Status != engineapi.RuleStatusPass {
|
||||
return NewResponse(resp.Status, unstructured.Unstructured{}, nil, resp.Message)
|
||||
if resp.Status() != engineapi.RuleStatusPass {
|
||||
return NewResponse(resp.Status(), unstructured.Unstructured{}, nil, resp.Message())
|
||||
}
|
||||
|
||||
if resp.Patches == nil {
|
||||
if resp.Patches() == nil {
|
||||
return NewResponse(engineapi.RuleStatusSkip, unstructured.Unstructured{}, nil, "no patches applied")
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ func ForEach(name string, foreach kyvernov1.ForEachMutation, policyContext engin
|
|||
return NewErrorResponse("failed to update patched resource in the JSON context", err)
|
||||
}
|
||||
|
||||
return NewResponse(engineapi.RuleStatusPass, patchedResource, resp.Patches, resp.Message)
|
||||
return NewResponse(engineapi.RuleStatusPass, patchedResource, resp.Patches(), resp.Message())
|
||||
}
|
||||
|
||||
func substituteAllInForEach(fe kyvernov1.ForEachMutation, ctx context.Interface, logger logr.Logger) (*kyvernov1.ForEachMutation, error) {
|
||||
|
|
|
@ -48,20 +48,10 @@ const endpointsDocument string = `{
|
|||
|
||||
func applyPatches(rule *types.Rule, resource unstructured.Unstructured) (*engineapi.RuleResponse, unstructured.Unstructured) {
|
||||
mutateResp := Mutate(rule, context.NewContext(), resource, logr.Discard())
|
||||
|
||||
if mutateResp.Status != engineapi.RuleStatusPass {
|
||||
return &engineapi.RuleResponse{
|
||||
Type: engineapi.Mutation,
|
||||
Status: mutateResp.Status,
|
||||
Message: mutateResp.Message,
|
||||
}, resource
|
||||
return engineapi.NewRuleResponse("", engineapi.Mutation, mutateResp.Message, mutateResp.Status), resource
|
||||
}
|
||||
|
||||
return &engineapi.RuleResponse{
|
||||
Type: engineapi.Mutation,
|
||||
Status: engineapi.RuleStatusPass,
|
||||
Patches: mutateResp.Patches,
|
||||
}, mutateResp.PatchedResource
|
||||
return engineapi.RulePass("", engineapi.Mutation, mutateResp.Message).WithPatches(mutateResp.Patches...), mutateResp.PatchedResource
|
||||
}
|
||||
|
||||
func TestProcessPatches_EmptyPatches(t *testing.T) {
|
||||
|
@ -72,8 +62,8 @@ func TestProcessPatches_EmptyPatches(t *testing.T) {
|
|||
}
|
||||
|
||||
rr, _ := applyPatches(emptyRule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusError)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusError)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func makeAddIsMutatedLabelPatch() jsonPatch {
|
||||
|
@ -106,15 +96,15 @@ func makeRuleWithPatches(t *testing.T, patches []jsonPatch) *types.Rule {
|
|||
func TestProcessPatches_EmptyDocument(t *testing.T) {
|
||||
rule := makeRuleWithPatch(t, makeAddIsMutatedLabelPatch())
|
||||
rr, _ := applyPatches(rule, unstructured.Unstructured{})
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusFail)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusFail)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_AllEmpty(t *testing.T) {
|
||||
emptyRule := &types.Rule{}
|
||||
rr, _ := applyPatches(emptyRule, unstructured.Unstructured{})
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusError)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusError)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_AddPathDoesntExist(t *testing.T) {
|
||||
|
@ -126,8 +116,8 @@ func TestProcessPatches_AddPathDoesntExist(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_RemovePathDoesntExist(t *testing.T) {
|
||||
|
@ -138,8 +128,8 @@ func TestProcessPatches_RemovePathDoesntExist(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_AddAndRemovePathsDontExist_EmptyResult(t *testing.T) {
|
||||
|
@ -151,8 +141,8 @@ func TestProcessPatches_AddAndRemovePathsDontExist_EmptyResult(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, len(rr.Patches), 1)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusPass)
|
||||
assert.Equal(t, len(rr.Patches()), 1)
|
||||
}
|
||||
|
||||
func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResult(t *testing.T) {
|
||||
|
@ -166,9 +156,9 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul
|
|||
}
|
||||
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass)
|
||||
assert.Assert(t, len(rr.Patches) != 0)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, rr.Patches[0])
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusPass)
|
||||
assert.Assert(t, len(rr.Patches()) != 0)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, rr.Patches()[0])
|
||||
}
|
||||
|
||||
func TestProcessPatches_RemovePathDoesntExist_EmptyResult(t *testing.T) {
|
||||
|
@ -179,8 +169,8 @@ func TestProcessPatches_RemovePathDoesntExist_EmptyResult(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches) == 0)
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusSkip)
|
||||
assert.Assert(t, len(rr.Patches()) == 0)
|
||||
}
|
||||
|
||||
func TestProcessPatches_RemovePathDoesntExist_NotEmptyResult(t *testing.T) {
|
||||
|
@ -192,9 +182,9 @@ func TestProcessPatches_RemovePathDoesntExist_NotEmptyResult(t *testing.T) {
|
|||
t.Error(err)
|
||||
}
|
||||
rr, _ := applyPatches(rule, *resourceUnstructured)
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass)
|
||||
assert.Assert(t, len(rr.Patches) == 1)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, rr.Patches[0])
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusPass)
|
||||
assert.Assert(t, len(rr.Patches()) == 1)
|
||||
assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, rr.Patches()[0])
|
||||
}
|
||||
|
||||
func assertEqStringAndData(t *testing.T, str string, data []byte) {
|
||||
|
|
|
@ -12,58 +12,42 @@ import (
|
|||
)
|
||||
|
||||
// ProcessPatchJSON6902 ...
|
||||
func ProcessPatchJSON6902(ruleName string, patchesJSON6902 []byte, resource unstructured.Unstructured, log logr.Logger) (resp engineapi.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
func ProcessPatchJSON6902(ruleName string, patchesJSON6902 []byte, resource unstructured.Unstructured, log logr.Logger) (engineapi.RuleResponse, unstructured.Unstructured) {
|
||||
logger := log.WithValues("rule", ruleName)
|
||||
startTime := time.Now()
|
||||
logger.V(4).Info("started JSON6902 patch", "startTime", startTime)
|
||||
resp.Name = ruleName
|
||||
resp.Type = engineapi.Mutation
|
||||
defer func() {
|
||||
resp.Stats.ProcessingTime = time.Since(startTime)
|
||||
resp.Stats.Timestamp = startTime.Unix()
|
||||
logger.V(4).Info("applied JSON6902 patch", "processingTime", resp.Stats.ProcessingTime.String())
|
||||
logger.V(4).Info("applied JSON6902 patch", "processingTime", time.Since(startTime))
|
||||
}()
|
||||
|
||||
resourceRaw, err := resource.MarshalJSON()
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
logger.Error(err, "failed to marshal resource")
|
||||
resp.Message = fmt.Sprintf("failed to marshal resource: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to marshal resource: %v", err)), resource
|
||||
}
|
||||
|
||||
patchedResourceRaw, err := applyPatchesWithOptions(resourceRaw, patchesJSON6902)
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
logger.Error(err, "failed to apply JSON Patch")
|
||||
resp.Message = fmt.Sprintf("failed to apply JSON Patch: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to apply JSON Patch: %v", err)), resource
|
||||
}
|
||||
|
||||
patchesBytes, err := generatePatches(resourceRaw, patchedResourceRaw)
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
logger.Error(err, "unable generate patch bytes from base and patched document, apply patchesJSON6902 directly")
|
||||
resp.Message = fmt.Sprintf("unable generate patch bytes from base and patched document, apply patchesJSON6902 directly: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(
|
||||
ruleName,
|
||||
engineapi.Mutation,
|
||||
fmt.Sprintf("unable generate patch bytes from base and patched document, apply patchesJSON6902 directly: %v", err),
|
||||
), resource
|
||||
}
|
||||
|
||||
for _, p := range patchesBytes {
|
||||
log.V(4).Info("generated JSON Patch (RFC 6902)", "patch", string(p))
|
||||
}
|
||||
|
||||
var patchedResource unstructured.Unstructured
|
||||
err = patchedResource.UnmarshalJSON(patchedResourceRaw)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to unmarshal resource")
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
resp.Message = fmt.Sprintf("failed to unmarshal resource: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to unmarshal resource: %v", err)), resource
|
||||
}
|
||||
|
||||
resp.Status = engineapi.RuleStatusPass
|
||||
resp.Message = string("applied JSON Patch")
|
||||
resp.Patches = patchesBytes
|
||||
return resp, patchedResource
|
||||
return *engineapi.RulePass(ruleName, engineapi.Mutation, "applied JSON Patch").WithPatches(patchesBytes...), patchedResource
|
||||
}
|
||||
|
||||
func applyPatchesWithOptions(resource, patch []byte) ([]byte, error) {
|
||||
|
|
|
@ -51,12 +51,12 @@ func TestTypeConversion(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
// apply patches
|
||||
resp, _ := ProcessPatchJSON6902("type-conversion", jsonPatches, resource, logr.Discard())
|
||||
if !assert.Equal(t, engineapi.RuleStatusPass, resp.Status) {
|
||||
t.Fatal(resp.Message)
|
||||
if !assert.Equal(t, engineapi.RuleStatusPass, resp.Status()) {
|
||||
t.Fatal(resp.Message())
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedPatches, resp.Patches,
|
||||
fmt.Sprintf("expectedPatches: %s\ngeneratedPatches: %s", string(expectedPatches[0]), string(resp.Patches[0])))
|
||||
assert.Equal(t, expectedPatches, resp.Patches(),
|
||||
fmt.Sprintf("expectedPatches: %s\ngeneratedPatches: %s", string(expectedPatches[0]), string(resp.Patches()[0])))
|
||||
}
|
||||
|
||||
func TestJsonPatch(t *testing.T) {
|
||||
|
|
|
@ -50,16 +50,16 @@ func NewPatchesJSON6902(ruleName string, patches string, patchedResource unstruc
|
|||
}
|
||||
}
|
||||
|
||||
func (h patchesJSON6902Handler) Patch() (resp engineapi.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
resp.Name = h.ruleName
|
||||
resp.Type = engineapi.Mutation
|
||||
|
||||
func (h patchesJSON6902Handler) Patch() (engineapi.RuleResponse, unstructured.Unstructured) {
|
||||
patchesJSON6902, err := ConvertPatchesToJSON(h.patches)
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
resp := engineapi.RuleFail(
|
||||
h.ruleName,
|
||||
engineapi.Mutation,
|
||||
err.Error(),
|
||||
)
|
||||
h.logger.Error(err, "error in type conversion")
|
||||
resp.Message = err.Error()
|
||||
return resp, unstructured.Unstructured{}
|
||||
return *resp, unstructured.Unstructured{}
|
||||
}
|
||||
|
||||
return ProcessPatchJSON6902(h.ruleName, patchesJSON6902, h.patchedResource, h.logger)
|
||||
|
|
|
@ -15,49 +15,38 @@ import (
|
|||
)
|
||||
|
||||
// ProcessStrategicMergePatch ...
|
||||
func ProcessStrategicMergePatch(ruleName string, overlay interface{}, resource unstructured.Unstructured, log logr.Logger) (resp engineapi.RuleResponse, patchedResource unstructured.Unstructured) {
|
||||
func ProcessStrategicMergePatch(ruleName string, overlay interface{}, resource unstructured.Unstructured, log logr.Logger) (engineapi.RuleResponse, unstructured.Unstructured) {
|
||||
startTime := time.Now()
|
||||
logger := log.WithName("ProcessStrategicMergePatch").WithValues("rule", ruleName)
|
||||
logger.V(4).Info("started applying strategicMerge patch", "startTime", startTime)
|
||||
resp.Name = ruleName
|
||||
resp.Type = engineapi.Mutation
|
||||
|
||||
defer func() {
|
||||
resp.Stats.ProcessingTime = time.Since(startTime)
|
||||
resp.Stats.Timestamp = startTime.Unix()
|
||||
logger.V(4).Info("finished applying strategicMerge patch", "processingTime", resp.Stats.ProcessingTime.String())
|
||||
logger.V(4).Info("finished applying strategicMerge patch", "processingTime", time.Since(startTime))
|
||||
}()
|
||||
|
||||
overlayBytes, err := json.Marshal(overlay)
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
logger.Error(err, "failed to marshal resource")
|
||||
resp.Message = fmt.Sprintf("failed to process patchStrategicMerge: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to process patchStrategicMerge: %v", err)), resource
|
||||
}
|
||||
|
||||
base, err := json.Marshal(resource.Object)
|
||||
if err != nil {
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
logger.Error(err, "failed to marshal resource")
|
||||
resp.Message = fmt.Sprintf("failed to process patchStrategicMerge: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to process patchStrategicMerge: %v", err)), resource
|
||||
}
|
||||
patchedBytes, err := strategicMergePatch(logger, string(base), string(overlayBytes))
|
||||
if err != nil {
|
||||
log.Error(err, "failed to apply patchStrategicMerge")
|
||||
msg := fmt.Sprintf("failed to apply patchStrategicMerge: %v", err)
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
resp.Message = msg
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, msg), resource
|
||||
}
|
||||
|
||||
var patchedResource unstructured.Unstructured
|
||||
err = patchedResource.UnmarshalJSON(patchedBytes)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to unmarshal resource")
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
resp.Message = fmt.Sprintf("failed to process patchStrategicMerge: %v", err)
|
||||
return resp, resource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, fmt.Sprintf("failed to process patchStrategicMerge: %v", err)), resource
|
||||
}
|
||||
|
||||
log.V(6).Info("generating JSON patches from patched resource", "patchedResource", patchedResource.Object)
|
||||
|
@ -65,20 +54,15 @@ func ProcessStrategicMergePatch(ruleName string, overlay interface{}, resource u
|
|||
jsonPatches, err := generatePatches(base, patchedBytes)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to generated JSON patches from patched resource: %v", err.Error())
|
||||
resp.Status = engineapi.RuleStatusFail
|
||||
log.V(2).Info(msg)
|
||||
resp.Message = msg
|
||||
return resp, patchedResource
|
||||
return *engineapi.RuleFail(ruleName, engineapi.Mutation, msg), patchedResource
|
||||
}
|
||||
|
||||
for _, p := range jsonPatches {
|
||||
log.V(5).Info("generated patch", "patch", string(p))
|
||||
}
|
||||
|
||||
resp.Status = engineapi.RuleStatusPass
|
||||
resp.Patches = jsonPatches
|
||||
resp.Message = "applied strategic merge patch"
|
||||
return resp, patchedResource
|
||||
return *engineapi.RulePass(ruleName, engineapi.Mutation, "applied strategic merge patch").WithPatches(jsonPatches...), patchedResource
|
||||
}
|
||||
|
||||
func strategicMergePatch(logger logr.Logger, base, overlay string) ([]byte, error) {
|
||||
|
|
|
@ -50,10 +50,9 @@ func (e *engine) mutate(
|
|||
engineapi.Mutation,
|
||||
)
|
||||
matchedResource = resource
|
||||
endTime := time.Now()
|
||||
for _, ruleResp := range ruleResp {
|
||||
ruleResp := ruleResp
|
||||
internal.AddRuleResponse(&resp, &ruleResp, startTime)
|
||||
logger.V(4).Info("finished processing rule", "processingTime", ruleResp.Stats.ProcessingTime.String())
|
||||
resp.Add(startTime, endTime, ruleResp)
|
||||
}
|
||||
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
|
||||
break
|
||||
|
|
|
@ -124,9 +124,9 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
|||
t.Log(string(expectedPatch))
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 1)
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches()[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("patches dont match")
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
|||
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message(), "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
||||
func Test_variableSubstitutionCLI(t *testing.T) {
|
||||
|
@ -291,10 +291,10 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
|||
),
|
||||
)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 1)
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches()[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("patches don't match")
|
||||
}
|
||||
}
|
||||
|
@ -399,11 +399,11 @@ func Test_chained_rules(t *testing.T) {
|
|||
assert.Equal(t, containers[0].(map[string]interface{})["image"], "otherregistry.corp.com/foo/bash:5.0")
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 2)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches()), 1)
|
||||
|
||||
assert.Equal(t, string(er.PolicyResponse.Rules[0].Patches[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"myregistry.corp.com/foo/bash:5.0"}`)
|
||||
assert.Equal(t, string(er.PolicyResponse.Rules[1].Patches[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"otherregistry.corp.com/foo/bash:5.0"}`)
|
||||
assert.Equal(t, string(er.PolicyResponse.Rules[0].Patches()[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"myregistry.corp.com/foo/bash:5.0"}`)
|
||||
assert.Equal(t, string(er.PolicyResponse.Rules[1].Patches()[0]), `{"op":"replace","path":"/spec/containers/0/image","value":"otherregistry.corp.com/foo/bash:5.0"}`)
|
||||
}
|
||||
|
||||
func Test_precondition(t *testing.T) {
|
||||
|
@ -480,8 +480,8 @@ func Test_precondition(t *testing.T) {
|
|||
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil))
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches()[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("patches don't match")
|
||||
}
|
||||
}
|
||||
|
@ -574,8 +574,8 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
|||
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil))
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches()[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("patches don't match")
|
||||
}
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ func Test_foreach(t *testing.T) {
|
|||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
|
@ -766,7 +766,7 @@ func Test_foreach_element_mutation(t *testing.T) {
|
|||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
|
@ -887,7 +887,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
|
|||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
|
@ -992,7 +992,7 @@ func Test_foreach_order_mutation_(t *testing.T) {
|
|||
er := testApplyPolicyToResource(t, policyRaw, resourceRaw)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
|
@ -1140,8 +1140,8 @@ func Test_mutate_nested_foreach(t *testing.T) {
|
|||
|
||||
er := testApplyPolicyToResource(t, policyRaw, resourceRaw)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 2)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 2)
|
||||
|
||||
tlsArr, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "tls")
|
||||
assert.NilError(t, err)
|
||||
|
@ -1580,9 +1580,9 @@ func Test_mutate_existing_resources(t *testing.T) {
|
|||
er := testMutate(context.TODO(), dclient, registryclient.NewOrDie(), policyContext, nil)
|
||||
|
||||
for _, rr := range er.PolicyResponse.Rules {
|
||||
for i, p := range rr.Patches {
|
||||
assert.Equal(t, test.patches[i], string(p), "test %s failed:\nGot %s\nExpected: %s", test.name, rr.Patches[i], test.patches[i])
|
||||
assert.Equal(t, rr.Status, engineapi.RuleStatusPass, rr.Status)
|
||||
for i, p := range rr.Patches() {
|
||||
assert.Equal(t, test.patches[i], string(p), "test %s failed:\nGot %s\nExpected: %s", test.name, rr.Patches()[i], test.patches[i])
|
||||
assert.Equal(t, rr.Status(), engineapi.RuleStatusPass, rr.Status())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1686,13 +1686,13 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
|
||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 2)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches()), 1)
|
||||
|
||||
if !reflect.DeepEqual(expectedPatch1, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
if !reflect.DeepEqual(expectedPatch1, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("rule 1 patches dont match")
|
||||
}
|
||||
if !reflect.DeepEqual(expectedPatch2, er.PolicyResponse.Rules[1].Patches[0]) {
|
||||
if !reflect.DeepEqual(expectedPatch2, er.PolicyResponse.Rules[1].Patches()[0]) {
|
||||
t.Errorf("rule 2 patches dont match")
|
||||
}
|
||||
|
||||
|
@ -1701,9 +1701,9 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
|
||||
er = testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches()), 1)
|
||||
|
||||
if !reflect.DeepEqual(expectedPatch1, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
if !reflect.DeepEqual(expectedPatch1, er.PolicyResponse.Rules[0].Patches()[0]) {
|
||||
t.Error("rule 1 patches dont match")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,10 +68,9 @@ func (e *engine) validate(
|
|||
engineapi.Validation,
|
||||
)
|
||||
matchedResource = resource
|
||||
endTime := time.Now()
|
||||
for _, ruleResp := range ruleResp {
|
||||
ruleResp := ruleResp
|
||||
internal.AddRuleResponse(&resp, &ruleResp, startTime)
|
||||
logger.V(4).Info("finished processing rule", "processingTime", ruleResp.Stats.ProcessingTime.String())
|
||||
resp.Add(startTime, endTime, ruleResp)
|
||||
}
|
||||
if applyRules == kyvernov1.ApplyOne && resp.Stats.RulesAppliedCount > 0 {
|
||||
break
|
||||
|
|
|
@ -138,7 +138,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
|
|||
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
|
@ -238,7 +238,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
|||
}
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), NewPolicyContextWithJsonContext(kyverno.Create, enginecontext.NewContext()).WithPolicy(&policy).WithNewResource(*resourceUnstructured), cfg, nil)
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
|||
|
||||
msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"}
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
|||
msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
|||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -575,7 +575,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
|||
msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
@ -645,7 +645,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
|
@ -792,7 +792,7 @@ func TestValidate_inequality_List_Processing(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
|
@ -872,7 +872,7 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
|
@ -946,7 +946,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
|||
msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
@ -1021,8 +1021,8 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
t.Log(r.Message)
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
t.Log(r.Message())
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -1236,7 +1236,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
|||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -1324,7 +1324,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
|||
msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
@ -1411,7 +1411,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
|||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
@ -1483,8 +1483,8 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
|
|||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message(), "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
||||
func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSubstitutionFails(t *testing.T) {
|
||||
|
@ -1573,8 +1573,8 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
|
|||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message(), "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
||||
func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
|
||||
|
@ -1629,8 +1629,8 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
|
|||
|
||||
policyContext := NewPolicyContextWithJsonContext(kyverno.Create, ctx).WithPolicy(&policy).WithNewResource(*resourceUnstructured)
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/")
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message(), "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/")
|
||||
}
|
||||
|
||||
func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *testing.T) {
|
||||
|
@ -1719,8 +1719,8 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
|
|||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusError)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message(), "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
||||
func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatternSatisfy(t *testing.T) {
|
||||
|
@ -1808,8 +1808,8 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
|
|||
policyContext := NewPolicyContextWithJsonContext(kyverno.Create, ctx).WithPolicy(&policy).WithNewResource(*resourceUnstructured)
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message,
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message(),
|
||||
"validation error: rule test-path-not-exist[0] failed at path /spec/template/spec/containers/0/name/ rule test-path-not-exist[1] failed at path /spec/template/spec/containers/0/name/")
|
||||
}
|
||||
|
||||
|
@ -1909,8 +1909,8 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
|
|||
|
||||
policyContext := NewPolicyContextWithJsonContext(kyverno.Create, ctx).WithPolicy(&policy).WithNewResource(*resourceUnstructured)
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message(), "The animal cow is not in the allowed list of animals.")
|
||||
}
|
||||
|
||||
func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
|
||||
|
@ -1961,8 +1961,8 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
|
|||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||
|
||||
for i, rule := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, er.PolicyResponse.Rules[i].Status, test.expectedResults[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedResults[i], er.PolicyResponse.Rules[i].Status)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[i].Message, test.expectedMessages[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedMessages[i], rule.Message)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[i].Status(), test.expectedResults[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedResults[i], er.PolicyResponse.Rules[i].Status())
|
||||
assert.Equal(t, er.PolicyResponse.Rules[i].Message(), test.expectedMessages[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedMessages[i], rule.Message())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2223,7 +2223,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
|
|||
),
|
||||
)
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
assert.Equal(t, r.Message(), msgs[index])
|
||||
}
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
@ -3088,9 +3088,9 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
|
|||
WithNewResource(*resourceUnstructured)
|
||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, contextLoader)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, status)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status(), status)
|
||||
if msg != "" {
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, msg)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message(), msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3151,7 +3151,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
|||
|
||||
engineResponseCreate := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextCreate, cfg, nil)
|
||||
assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusFail)
|
||||
|
||||
policyContextDelete := NewPolicyContextWithJsonContext(kyverno.Create, ctx).
|
||||
WithPolicy(&policy).
|
||||
|
|
|
@ -28,13 +28,13 @@ func buildPolicyEventMessage(resp *engineapi.RuleResponse, resource engineapi.Re
|
|||
fmt.Fprintf(&b, "%s %s", resource.Kind, resource.Name)
|
||||
}
|
||||
|
||||
fmt.Fprintf(&b, ": [%s] %s", resp.Name, resp.Status)
|
||||
fmt.Fprintf(&b, ": [%s] %s", resp.Name(), resp.Status())
|
||||
if blocked {
|
||||
fmt.Fprintf(&b, " (blocked)")
|
||||
}
|
||||
|
||||
if resp.Message != "" {
|
||||
fmt.Fprintf(&b, "; %s", resp.Message)
|
||||
if resp.Message() != "" {
|
||||
fmt.Fprintf(&b, "; %s", resp.Message())
|
||||
}
|
||||
|
||||
return b.String()
|
||||
|
@ -73,7 +73,7 @@ func NewResourceViolationEvent(source Source, reason Reason, engineResponse engi
|
|||
defer bldr.Reset()
|
||||
|
||||
fmt.Fprintf(&bldr, "policy %s/%s %s: %s", engineResponse.Policy.GetName(),
|
||||
ruleResp.Name, ruleResp.Status, ruleResp.Message)
|
||||
ruleResp.Name(), ruleResp.Status(), ruleResp.Message())
|
||||
resource := engineResponse.GetResourceSpec()
|
||||
|
||||
return Info{
|
||||
|
@ -124,13 +124,14 @@ func NewBackgroundSuccessEvent(policy, rule string, source Source, r *unstructur
|
|||
}
|
||||
|
||||
func NewPolicyExceptionEvents(engineResponse engineapi.EngineResponse, ruleResp *engineapi.RuleResponse, source Source) []Info {
|
||||
exceptionName, exceptionNamespace := ruleResp.Exception.GetName(), ruleResp.Exception.GetNamespace()
|
||||
policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", resourceKey(engineResponse.PatchedResource), ruleResp.Name, exceptionNamespace, exceptionName)
|
||||
exception := ruleResp.Exception()
|
||||
exceptionName, exceptionNamespace := exception.GetName(), exception.GetNamespace()
|
||||
policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", resourceKey(engineResponse.PatchedResource), ruleResp.Name(), exceptionNamespace, exceptionName)
|
||||
var exceptionMessage string
|
||||
if engineResponse.Policy.GetNamespace() == "" {
|
||||
exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetName(), ruleResp.Name)
|
||||
exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetName(), ruleResp.Name())
|
||||
} else {
|
||||
exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetNamespace(), engineResponse.Policy.GetName(), ruleResp.Name)
|
||||
exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetNamespace(), engineResponse.Policy.GetName(), ruleResp.Name())
|
||||
}
|
||||
policyEvent := Info{
|
||||
Kind: getPolicyKind(engineResponse.Policy),
|
||||
|
|
|
@ -54,7 +54,7 @@ func ParseResourceRequestOperation(requestOperationStr string) (ResourceRequestO
|
|||
}
|
||||
|
||||
func ParseRuleTypeFromEngineRuleResponse(rule engineapi.RuleResponse) RuleType {
|
||||
switch rule.Type {
|
||||
switch rule.RuleType() {
|
||||
case "Validation":
|
||||
return Validate
|
||||
case "Mutation":
|
||||
|
|
|
@ -416,8 +416,8 @@ func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest
|
|||
}
|
||||
|
||||
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
||||
if ruleResponse.Status != engineapi.RuleStatusPass {
|
||||
pc.log.Error(err, "can not create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status)
|
||||
if ruleResponse.Status() != engineapi.RuleStatusPass {
|
||||
pc.log.Error(err, "can not create new UR on policy update", "policy", policy.GetName(), "rule", rule.Name, "rule.Status", ruleResponse.Status())
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -122,14 +122,14 @@ func annotationFromEngineResponses(engineResponses []engineapi.EngineResponse, l
|
|||
func annotationFromPolicyResponse(policyResponse engineapi.PolicyResponse, log logr.Logger) []RulePatch {
|
||||
var RulePatches []RulePatch
|
||||
for _, ruleInfo := range policyResponse.Rules {
|
||||
for _, patch := range ruleInfo.Patches {
|
||||
for _, patch := range ruleInfo.Patches() {
|
||||
var patchmap map[string]interface{}
|
||||
if err := json.Unmarshal(patch, &patchmap); err != nil {
|
||||
log.Error(err, "Failed to parse JSON patch bytes")
|
||||
continue
|
||||
}
|
||||
rp := RulePatch{
|
||||
RuleName: ruleInfo.Name,
|
||||
RuleName: ruleInfo.Name(),
|
||||
Op: patchmap["op"].(string),
|
||||
Path: patchmap["path"].(string),
|
||||
}
|
||||
|
|
|
@ -20,11 +20,7 @@ func newPolicyResponse(rule string, patchesStr []string, status engineapi.RuleSt
|
|||
|
||||
return engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: rule,
|
||||
Patches: patches,
|
||||
Status: status,
|
||||
},
|
||||
*engineapi.NewRuleResponse(rule, engineapi.Mutation, "", status).WithPatches(patches...),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,9 +89,9 @@ func EngineResponseToReportResults(response engineapi.EngineResponse) []policyre
|
|||
result := policyreportv1alpha2.PolicyReportResult{
|
||||
Source: kyvernov1.ValueKyvernoApp,
|
||||
Policy: key,
|
||||
Rule: ruleResult.Name,
|
||||
Message: ruleResult.Message,
|
||||
Result: toPolicyResult(ruleResult.Status),
|
||||
Rule: ruleResult.Name(),
|
||||
Message: ruleResult.Message(),
|
||||
Result: toPolicyResult(ruleResult.Status()),
|
||||
Scored: annotations[kyvernov1.AnnotationPolicyScored] != "false",
|
||||
Timestamp: metav1.Timestamp{
|
||||
Seconds: time.Now().Unix(),
|
||||
|
@ -99,9 +99,10 @@ func EngineResponseToReportResults(response engineapi.EngineResponse) []policyre
|
|||
Category: annotations[kyvernov1.AnnotationPolicyCategory],
|
||||
Severity: severityFromString(annotations[kyvernov1.AnnotationPolicySeverity]),
|
||||
}
|
||||
if ruleResult.PodSecurityChecks != nil {
|
||||
pss := ruleResult.PodSecurityChecks()
|
||||
if pss != nil {
|
||||
var controls []string
|
||||
for _, check := range ruleResult.PodSecurityChecks.Checks {
|
||||
for _, check := range pss.Checks {
|
||||
if !check.CheckResult.Allowed {
|
||||
controls = append(controls, check.ID)
|
||||
}
|
||||
|
@ -109,8 +110,8 @@ func EngineResponseToReportResults(response engineapi.EngineResponse) []policyre
|
|||
if len(controls) > 0 {
|
||||
sort.Strings(controls)
|
||||
result.Properties = map[string]string{
|
||||
"standard": string(ruleResult.PodSecurityChecks.Level),
|
||||
"version": ruleResult.PodSecurityChecks.Version,
|
||||
"standard": string(pss.Level),
|
||||
"version": pss.Version,
|
||||
"controls": strings.Join(controls, ","),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ func getAppliedRules(policy kyvernov1.PolicyInterface, applied []engineapi.RuleR
|
|||
continue
|
||||
}
|
||||
for _, applied := range applied {
|
||||
if applied.Name == rule.Name && applied.Type == engineapi.Generation {
|
||||
if applied.Name() == rule.Name && applied.RuleType() == engineapi.Generation {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
@ -113,9 +113,9 @@ func (h *generationHandler) handleTrigger(
|
|||
}
|
||||
engineResponse := h.engine.ApplyBackgroundChecks(ctx, policyContext)
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status == engineapi.RuleStatusPass {
|
||||
if rule.Status() == engineapi.RuleStatusPass {
|
||||
appliedRules = append(appliedRules, rule)
|
||||
} else if rule.Status == engineapi.RuleStatusFail {
|
||||
} else if rule.Status() == engineapi.RuleStatusFail {
|
||||
failedRules = append(failedRules, rule)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ func (h *resourceHandlers) handleMutateExisting(ctx context.Context, logger logr
|
|||
engineResponse := h.engine.ApplyBackgroundChecks(ctx, policyContext)
|
||||
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status == engineapi.RuleStatusPass {
|
||||
if rule.Status() == engineapi.RuleStatusPass {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1072,8 +1072,8 @@ func TestValidate_failure_action_overrides(t *testing.T) {
|
|||
)
|
||||
if tc.blocked && tc.messages != nil {
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
msg := tc.messages[r.Name]
|
||||
assert.Equal(t, r.Message, msg)
|
||||
msg := tc.messages[r.Name()]
|
||||
assert.Equal(t, r.Message(), msg)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ func GetBlockedMessages(engineResponses []engineapi.EngineResponse) string {
|
|||
for _, er := range engineResponses {
|
||||
ruleToReason := make(map[string]string)
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Status != engineapi.RuleStatusPass {
|
||||
ruleToReason[rule.Name] = rule.Message
|
||||
if rule.Status == engineapi.RuleStatusFail {
|
||||
if rule.Status() != engineapi.RuleStatusPass {
|
||||
ruleToReason[rule.Name()] = rule.Message()
|
||||
if rule.Status() == engineapi.RuleStatusFail {
|
||||
hasViolations = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,11 +87,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-fail",
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Message: "message fail",
|
||||
},
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -105,11 +101,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-fail",
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Message: "message fail",
|
||||
},
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -123,11 +115,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-error",
|
||||
Status: engineapi.RuleStatusError,
|
||||
Message: "message error",
|
||||
},
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -141,11 +129,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-error",
|
||||
Status: engineapi.RuleStatusError,
|
||||
Message: "message error",
|
||||
},
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -159,11 +143,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-warning",
|
||||
Status: engineapi.RuleStatusWarn,
|
||||
Message: "message warning",
|
||||
},
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -177,11 +157,7 @@ func TestBlockRequest(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, auditPolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-warning",
|
||||
Status: engineapi.RuleStatusWarn,
|
||||
Message: "message warning",
|
||||
},
|
||||
*engineapi.NewRuleResponse("rule-warning", engineapi.Validation, "message warning", engineapi.RuleStatusWarn),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -229,11 +205,7 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-fail",
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Message: "message fail",
|
||||
},
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -245,11 +217,7 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-error",
|
||||
Status: engineapi.RuleStatusError,
|
||||
Message: "message error",
|
||||
},
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
@ -261,16 +229,8 @@ func TestGetBlockedMessages(t *testing.T) {
|
|||
engineResponses: []engineapi.EngineResponse{
|
||||
engineapi.NewEngineResponse(resource, enforcePolicy, nil, &engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-fail",
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Message: "message fail",
|
||||
},
|
||||
{
|
||||
Name: "rule-error",
|
||||
Status: engineapi.RuleStatusError,
|
||||
Message: "message error",
|
||||
},
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
},
|
||||
}, time.Now()),
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ func GetErrorMsg(engineReponses []engineapi.EngineResponse) string {
|
|||
resourceInfo = fmt.Sprintf("%s/%s/%s", er.Resource.GetKind(), er.Resource.GetNamespace(), er.Resource.GetName())
|
||||
str = append(str, fmt.Sprintf("failed policy %s:", er.Policy.GetName()))
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Status != engineapi.RuleStatusPass {
|
||||
if rule.Status() != engineapi.RuleStatusPass {
|
||||
str = append(str, rule.String())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func GenerateEvents(engineResponses []engineapi.EngineResponse, blocked bool) []
|
|||
}
|
||||
if !er.IsSuccessful() {
|
||||
for i, ruleResp := range er.PolicyResponse.Rules {
|
||||
if ruleResp.Status == engineapi.RuleStatusFail || ruleResp.Status == engineapi.RuleStatusError {
|
||||
if ruleResp.Status() == engineapi.RuleStatusFail || ruleResp.Status() == engineapi.RuleStatusError {
|
||||
e := event.NewPolicyFailEvent(event.AdmissionController, event.PolicyViolation, er, &er.PolicyResponse.Rules[i], blocked)
|
||||
events = append(events, e)
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ func GenerateEvents(engineResponses []engineapi.EngineResponse, blocked bool) []
|
|||
}
|
||||
} else if er.IsSkipped() { // Handle PolicyException Event
|
||||
for i, ruleResp := range er.PolicyResponse.Rules {
|
||||
isException := ruleResp.Exception != nil
|
||||
if ruleResp.Status == engineapi.RuleStatusSkip && !blocked && isException {
|
||||
if ruleResp.Status() == engineapi.RuleStatusSkip && !blocked && ruleResp.IsException() {
|
||||
events = append(events, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i], event.AdmissionController)...)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ func GetWarningMessages(engineResponses []engineapi.EngineResponse) []string {
|
|||
var warnings []string
|
||||
for _, er := range engineResponses {
|
||||
for _, rule := range er.PolicyResponse.Rules {
|
||||
if rule.Status != engineapi.RuleStatusPass && rule.Status != engineapi.RuleStatusSkip {
|
||||
msg := fmt.Sprintf("policy %s.%s: %s", er.Policy.GetName(), rule.Name, rule.Message)
|
||||
if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip {
|
||||
msg := fmt.Sprintf("policy %s.%s: %s", er.Policy.GetName(), rule.Name(), rule.Message())
|
||||
warnings = append(warnings, msg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,7 @@ func TestGetWarningMessages(t *testing.T) {
|
|||
},
|
||||
PolicyResponse: engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule",
|
||||
Status: engineapi.RuleStatusWarn,
|
||||
Message: "message warn",
|
||||
},
|
||||
*engineapi.NewRuleResponse("rule", engineapi.Validation, "message warn", engineapi.RuleStatusWarn),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -59,31 +55,11 @@ func TestGetWarningMessages(t *testing.T) {
|
|||
},
|
||||
PolicyResponse: engineapi.PolicyResponse{
|
||||
Rules: []engineapi.RuleResponse{
|
||||
{
|
||||
Name: "rule-pass",
|
||||
Status: engineapi.RuleStatusPass,
|
||||
Message: "message pass",
|
||||
},
|
||||
{
|
||||
Name: "rule-warn",
|
||||
Status: engineapi.RuleStatusWarn,
|
||||
Message: "message warn",
|
||||
},
|
||||
{
|
||||
Name: "rule-fail",
|
||||
Status: engineapi.RuleStatusFail,
|
||||
Message: "message fail",
|
||||
},
|
||||
{
|
||||
Name: "rule-error",
|
||||
Status: engineapi.RuleStatusError,
|
||||
Message: "message error",
|
||||
},
|
||||
{
|
||||
Name: "rule-skip",
|
||||
Status: engineapi.RuleStatusSkip,
|
||||
Message: "message skip",
|
||||
},
|
||||
*engineapi.RulePass("rule-pass", engineapi.Validation, "message pass"),
|
||||
*engineapi.NewRuleResponse("rule-warn", engineapi.Validation, "message warn", engineapi.RuleStatusWarn),
|
||||
*engineapi.RuleFail("rule-fail", engineapi.Validation, "message fail"),
|
||||
*engineapi.RuleError("rule-error", engineapi.Validation, "message error", nil),
|
||||
*engineapi.RuleSkip("rule-skip", engineapi.Validation, "message skip"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue