1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

added different logic for policy report in CLI

Signed-off-by: NoSkillGirl <singhpooja240393@gmail.com>
This commit is contained in:
NoSkillGirl 2021-09-02 00:02:55 +05:30
parent 1e6b4bdcee
commit 868537f04d
7 changed files with 106 additions and 68 deletions

View file

@ -19,6 +19,7 @@ import (
"github.com/kyverno/kyverno/pkg/kyverno/store" "github.com/kyverno/kyverno/pkg/kyverno/store"
"github.com/kyverno/kyverno/pkg/openapi" "github.com/kyverno/kyverno/pkg/openapi"
policy2 "github.com/kyverno/kyverno/pkg/policy" policy2 "github.com/kyverno/kyverno/pkg/policy"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
@ -121,12 +122,12 @@ func Command() *cobra.Command {
} }
}() }()
validateEngineResponses, rc, resources, skippedPolicies, err := applyCommandHelper(resourcePaths, cluster, policyReport, mutateLogPath, variablesString, valuesFile, namespace, policyPaths, stdin) validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err := applyCommandHelper(resourcePaths, cluster, policyReport, mutateLogPath, variablesString, valuesFile, namespace, policyPaths, stdin)
if err != nil { if err != nil {
return err return err
} }
printReportOrViolation(policyReport, validateEngineResponses, rc, resourcePaths, len(resources), skippedPolicies, stdin) printReportOrViolation(policyReport, validateEngineResponses, rc, resourcePaths, len(resources), skippedPolicies, stdin, pvInfos)
return nil return nil
}, },
} }
@ -144,48 +145,48 @@ func Command() *cobra.Command {
} }
func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool, mutateLogPath string, func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool, mutateLogPath string,
variablesString string, valuesFile string, namespace string, policyPaths []string, stdin bool) (validateEngineResponses []*response.EngineResponse, rc *common.ResultCounts, resources []*unstructured.Unstructured, skippedPolicies []string, err error) { variablesString string, valuesFile string, namespace string, policyPaths []string, stdin bool) (validateEngineResponses []*response.EngineResponse, rc *common.ResultCounts, resources []*unstructured.Unstructured, skippedPolicies []string, pvInfos []policyreport.Info, err error) {
store.SetMock(true) store.SetMock(true)
kubernetesConfig := genericclioptions.NewConfigFlags(true) kubernetesConfig := genericclioptions.NewConfigFlags(true)
fs := memfs.New() fs := memfs.New()
if valuesFile != "" && variablesString != "" { if valuesFile != "" && variablesString != "" {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err)
} }
variables, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, valuesFile, fs, false, "") variables, valuesMap, namespaceSelectorMap, err := common.GetVariable(variablesString, valuesFile, fs, false, "")
if err != nil { if err != nil {
if !sanitizederror.IsErrorSanitized(err) { if !sanitizederror.IsErrorSanitized(err) {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to decode yaml", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to decode yaml", err)
} }
return validateEngineResponses, rc, resources, skippedPolicies, err return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err
} }
openAPIController, err := openapi.NewOpenAPIController() openAPIController, err := openapi.NewOpenAPIController()
if err != nil { if err != nil {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to initialize openAPIController", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to initialize openAPIController", err)
} }
var dClient *client.Client var dClient *client.Client
if cluster { if cluster {
restConfig, err := kubernetesConfig.ToRESTConfig() restConfig, err := kubernetesConfig.ToRESTConfig()
if err != nil { if err != nil {
return validateEngineResponses, rc, resources, skippedPolicies, err return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err
} }
dClient, err = client.NewClient(restConfig, 15*time.Minute, make(chan struct{}), log.Log) dClient, err = client.NewClient(restConfig, 15*time.Minute, make(chan struct{}), log.Log)
if err != nil { if err != nil {
return validateEngineResponses, rc, resources, skippedPolicies, err return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err
} }
} }
if len(policyPaths) == 0 { if len(policyPaths) == 0 {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError(fmt.Sprintf("require policy"), err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("require policy"), err)
} }
if (len(policyPaths) > 0 && policyPaths[0] == "-") && len(resourcePaths) > 0 && resourcePaths[0] == "-" { if (len(policyPaths) > 0 && policyPaths[0] == "-") && len(resourcePaths) > 0 && resourcePaths[0] == "-" {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("a stdin pipe can be used for either policies or resources, not both", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("a stdin pipe can be used for either policies or resources, not both", err)
} }
policies, err := common.GetPoliciesFromPaths(fs, policyPaths, false, "") policies, err := common.GetPoliciesFromPaths(fs, policyPaths, false, "")
@ -195,15 +196,15 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
} }
if len(resourcePaths) == 0 && !cluster { if len(resourcePaths) == 0 && !cluster {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError(fmt.Sprintf("resource file(s) or cluster required"), err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("resource file(s) or cluster required"), err)
} }
mutateLogPathIsDir, err := checkMutateLogPath(mutateLogPath) mutateLogPathIsDir, err := checkMutateLogPath(mutateLogPath)
if err != nil { if err != nil {
if !sanitizederror.IsErrorSanitized(err) { if !sanitizederror.IsErrorSanitized(err) {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to create file/folder", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to create file/folder", err)
} }
return validateEngineResponses, rc, resources, skippedPolicies, err return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err
} }
// empty the previous contents of the file just in case if the file already existed before with some content(so as to perform overwrites) // empty the previous contents of the file just in case if the file already existed before with some content(so as to perform overwrites)
@ -212,23 +213,23 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
_, err := os.OpenFile(mutateLogPath, os.O_TRUNC|os.O_WRONLY, 0644) _, err := os.OpenFile(mutateLogPath, os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil { if err != nil {
if !sanitizederror.IsErrorSanitized(err) { if !sanitizederror.IsErrorSanitized(err) {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to truncate the existing file at "+mutateLogPath, err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to truncate the existing file at "+mutateLogPath, err)
} }
return validateEngineResponses, rc, resources, skippedPolicies, err return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, err
} }
} }
mutatedPolicies, err := common.MutatePolices(policies) mutatedPolicies, err := common.MutatePolices(policies)
if err != nil { if err != nil {
if !sanitizederror.IsErrorSanitized(err) { if !sanitizederror.IsErrorSanitized(err) {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to mutate policy", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to mutate policy", err)
} }
} }
for _, policy := range mutatedPolicies { for _, policy := range mutatedPolicies {
p, err := json.Marshal(policy) p, err := json.Marshal(policy)
if err != nil { if err != nil {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("failed to marsal mutated policy", err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("failed to marsal mutated policy", err)
} }
log.Log.V(5).Info("mutated Policy:", string(p)) log.Log.V(5).Info("mutated Policy:", string(p))
@ -241,7 +242,7 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
} }
if (len(resources) > 1 || len(mutatedPolicies) > 1) && variablesString != "" { if (len(resources) > 1 || len(mutatedPolicies) > 1) && variablesString != "" {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError("currently `set` flag supports variable for single policy applied on single resource ", nil) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError("currently `set` flag supports variable for single policy applied on single resource ", nil)
} }
if variablesString != "" { if variablesString != "" {
@ -311,20 +312,21 @@ func applyCommandHelper(resourcePaths []string, cluster bool, policyReport bool,
// skipping the variable check for non matching kind // skipping the variable check for non matching kind
if _, ok := kindOnwhichPolicyIsApplied[resource.GetKind()]; ok { if _, ok := kindOnwhichPolicyIsApplied[resource.GetKind()]; ok {
if len(variable) > 0 && len(thisPolicyResourceValues) == 0 && len(store.GetContext().Policies) == 0 { if len(variable) > 0 && len(thisPolicyResourceValues) == 0 && len(store.GetContext().Policies) == 0 {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.Name, resource.GetName()), err)
} }
} }
validateErs, err := common.ApplyPolicyOnResource(policy, resource, mutateLogPath, mutateLogPathIsDir, thisPolicyResourceValues, policyReport, namespaceSelectorMap, stdin, rc) validateErs, info, err := common.ApplyPolicyOnResource(policy, resource, mutateLogPath, mutateLogPathIsDir, thisPolicyResourceValues, policyReport, namespaceSelectorMap, stdin, rc)
if err != nil { if err != nil {
return validateEngineResponses, rc, resources, skippedPolicies, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err) return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err)
} }
pvInfos = append(pvInfos, info)
validateEngineResponses = append(validateEngineResponses, validateErs) validateEngineResponses = append(validateEngineResponses, validateErs)
} }
} }
return validateEngineResponses, rc, resources, skippedPolicies, nil return validateEngineResponses, rc, resources, skippedPolicies, pvInfos, nil
} }
// checkMutateLogPath - checking path for printing mutated resource (-o flag) // checkMutateLogPath - checking path for printing mutated resource (-o flag)
@ -350,7 +352,7 @@ func checkMutateLogPath(mutateLogPath string) (mutateLogPathIsDir bool, err erro
} }
// printReportOrViolation - printing policy report/violations // printReportOrViolation - printing policy report/violations
func printReportOrViolation(policyReport bool, validateEngineResponses []*response.EngineResponse, rc *common.ResultCounts, resourcePaths []string, resourcesLen int, skippedPolicies []string, stdin bool) { func printReportOrViolation(policyReport bool, validateEngineResponses []*response.EngineResponse, rc *common.ResultCounts, resourcePaths []string, resourcesLen int, skippedPolicies []string, stdin bool, pvInfos []policyreport.Info) {
if len(skippedPolicies) > 0 { if len(skippedPolicies) > 0 {
fmt.Println("----------------------------------------------------------------------\nPolicies Skipped(as required variables are not provided by the users):") fmt.Println("----------------------------------------------------------------------\nPolicies Skipped(as required variables are not provided by the users):")
for i, policyName := range skippedPolicies { for i, policyName := range skippedPolicies {
@ -361,7 +363,7 @@ func printReportOrViolation(policyReport bool, validateEngineResponses []*respon
if policyReport { if policyReport {
os.Setenv("POLICY-TYPE", pkgCommon.PolicyReport) os.Setenv("POLICY-TYPE", pkgCommon.PolicyReport)
resps := buildPolicyReports(validateEngineResponses) resps := buildPolicyReports(validateEngineResponses, pvInfos)
if len(resps) > 0 || resourcesLen == 0 { if len(resps) > 0 || resourcesLen == 0 {
fmt.Println("\n----------------------------------------------------------------------\nPOLICY REPORT:\n----------------------------------------------------------------------") fmt.Println("\n----------------------------------------------------------------------\nPOLICY REPORT:\n----------------------------------------------------------------------")
report, _ := generateCLIRaw(resps) report, _ := generateCLIRaw(resps)

View file

@ -56,8 +56,8 @@ func Test_Apply(t *testing.T) {
} }
for _, tc := range testcases { for _, tc := range testcases {
validateEngineResponses, _, _, _, _ := applyCommandHelper(tc.ResourcePaths, false, true, "", "", "", "", tc.PolicyPaths, false) validateEngineResponses, _, _, _, info, _ := applyCommandHelper(tc.ResourcePaths, false, true, "", "", "", "", tc.PolicyPaths, false)
resps := buildPolicyReports(validateEngineResponses) resps := buildPolicyReports(validateEngineResponses, info)
for i, resp := range resps { for i, resp := range resps {
compareSummary(tc.expectedPolicyReports[i].Summary, resp.UnstructuredContent()["summary"].(map[string]interface{})) compareSummary(tc.expectedPolicyReports[i].Summary, resp.UnstructuredContent()["summary"].(map[string]interface{}))
} }

View file

@ -21,11 +21,11 @@ import (
const clusterpolicyreport = "clusterpolicyreport" const clusterpolicyreport = "clusterpolicyreport"
// resps is the engine responses generated for a single policy // resps is the engine responses generated for a single policy
func buildPolicyReports(resps []*response.EngineResponse) (res []*unstructured.Unstructured) { func buildPolicyReports(resps []*response.EngineResponse, pvInfos []policyreport.Info) (res []*unstructured.Unstructured) {
var raw []byte var raw []byte
var err error var err error
resultsMap := buildPolicyResults(resps) resultsMap := buildPolicyResults(resps, pvInfos)
for scope, result := range resultsMap { for scope, result := range resultsMap {
if scope == clusterpolicyreport { if scope == clusterpolicyreport {
report := &report.ClusterPolicyReport{ report := &report.ClusterPolicyReport{
@ -74,9 +74,8 @@ func buildPolicyReports(resps []*response.EngineResponse) (res []*unstructured.U
// buildPolicyResults returns a string-PolicyReportResult map // buildPolicyResults returns a string-PolicyReportResult map
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>" // the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
func buildPolicyResults(resps []*response.EngineResponse) map[string][]*report.PolicyReportResult { func buildPolicyResults(resps []*response.EngineResponse, infos []policyreport.Info) map[string][]*report.PolicyReportResult {
results := make(map[string][]*report.PolicyReportResult) results := make(map[string][]*report.PolicyReportResult)
infos := policyreport.GeneratePRsFromEngineResponse(resps, log.Log)
now := metav1.Timestamp{Seconds: time.Now().Unix()} now := metav1.Timestamp{Seconds: time.Now().Unix()}
for _, info := range infos { for _, info := range infos {

View file

@ -72,7 +72,7 @@ var engineResponses = []*response.EngineResponse{
func Test_buildPolicyReports(t *testing.T) { func Test_buildPolicyReports(t *testing.T) {
os.Setenv("POLICY-TYPE", common.PolicyReport) os.Setenv("POLICY-TYPE", common.PolicyReport)
reports := buildPolicyReports(engineResponses) reports := buildPolicyReports(engineResponses, nil)
assert.Assert(t, len(reports) == 2, len(reports)) assert.Assert(t, len(reports) == 2, len(reports))
for _, report := range reports { for _, report := range reports {
@ -97,7 +97,7 @@ func Test_buildPolicyReports(t *testing.T) {
func Test_buildPolicyResults(t *testing.T) { func Test_buildPolicyResults(t *testing.T) {
os.Setenv("POLICY-TYPE", common.PolicyReport) os.Setenv("POLICY-TYPE", common.PolicyReport)
results := buildPolicyResults(engineResponses) results := buildPolicyResults(engineResponses, nil)
assert.Assert(t, len(results[clusterpolicyreport]) == 2, len(results[clusterpolicyreport])) assert.Assert(t, len(results[clusterpolicyreport]) == 2, len(results[clusterpolicyreport]))
assert.Assert(t, len(results["policyreport-ns-policy1-namespace"]) == 2, len(results["policyreport-ns-policy1-namespace"])) assert.Assert(t, len(results["policyreport-ns-policy1-namespace"]) == 2, len(results["policyreport-ns-policy1-namespace"]))

View file

@ -16,6 +16,7 @@ import (
"github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5"
"github.com/go-logr/logr" "github.com/go-logr/logr"
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1" v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
report "github.com/kyverno/kyverno/pkg/api/policyreport/v1alpha2"
pkgcommon "github.com/kyverno/kyverno/pkg/common" pkgcommon "github.com/kyverno/kyverno/pkg/common"
client "github.com/kyverno/kyverno/pkg/dclient" client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/engine" "github.com/kyverno/kyverno/pkg/engine"
@ -25,6 +26,7 @@ import (
sanitizederror "github.com/kyverno/kyverno/pkg/kyverno/sanitizedError" sanitizederror "github.com/kyverno/kyverno/pkg/kyverno/sanitizedError"
"github.com/kyverno/kyverno/pkg/kyverno/store" "github.com/kyverno/kyverno/pkg/kyverno/store"
"github.com/kyverno/kyverno/pkg/policymutation" "github.com/kyverno/kyverno/pkg/policymutation"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/utils" "github.com/kyverno/kyverno/pkg/utils"
ut "github.com/kyverno/kyverno/pkg/utils" ut "github.com/kyverno/kyverno/pkg/utils"
yamlv2 "gopkg.in/yaml.v2" yamlv2 "gopkg.in/yaml.v2"
@ -514,7 +516,7 @@ func MutatePolices(policies []*v1.ClusterPolicy) ([]*v1.ClusterPolicy, error) {
// ApplyPolicyOnResource - function to apply policy on resource // ApplyPolicyOnResource - function to apply policy on resource
func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured, func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured,
mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, policyReport bool, namespaceSelectorMap map[string]map[string]string, stdin bool, rc *ResultCounts) (*response.EngineResponse, error) { mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, policyReport bool, namespaceSelectorMap map[string]map[string]string, stdin bool, rc *ResultCounts) (*response.EngineResponse, policyreport.Info, error) {
operationIsDelete := false operationIsDelete := false
@ -539,7 +541,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
resourceNamespace := resource.GetNamespace() resourceNamespace := resource.GetNamespace()
namespaceLabels = namespaceSelectorMap[resource.GetNamespace()] namespaceLabels = namespaceSelectorMap[resource.GetNamespace()]
if resourceNamespace != "default" && len(namespaceLabels) < 1 { if resourceNamespace != "default" && len(namespaceLabels) < 1 {
return &response.EngineResponse{}, sanitizederror.NewWithError(fmt.Sprintf("failed to get namesapce labels for resource %s. use --values-file flag to pass the namespace labels", resource.GetName()), nil) return &response.EngineResponse{}, policyreport.Info{}, sanitizederror.NewWithError(fmt.Sprintf("failed to get namesapce labels for resource %s. use --values-file flag to pass the namespace labels", resource.GetName()), nil)
} }
} }
@ -579,7 +581,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
if len(mutateResponse.PolicyResponse.Rules) > 0 { if len(mutateResponse.PolicyResponse.Rules) > 0 {
yamlEncodedResource, err := yamlv2.Marshal(mutateResponse.PatchedResource.Object) yamlEncodedResource, err := yamlv2.Marshal(mutateResponse.PatchedResource.Object)
if err != nil { if err != nil {
return &response.EngineResponse{}, sanitizederror.NewWithError("failed to marshal", err) return &response.EngineResponse{}, policyreport.Info{}, sanitizederror.NewWithError("failed to marshal", err)
} }
if mutateLogPath == "" { if mutateLogPath == "" {
@ -594,7 +596,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
} else { } else {
err := PrintMutatedOutput(mutateLogPath, mutateLogPathIsDir, string(yamlEncodedResource), resource.GetName()+"-mutated") err := PrintMutatedOutput(mutateLogPath, mutateLogPathIsDir, string(yamlEncodedResource), resource.GetName()+"-mutated")
if err != nil { if err != nil {
return &response.EngineResponse{}, sanitizederror.NewWithError("failed to print mutated result", err) return &response.EngineResponse{}, policyreport.Info{}, sanitizederror.NewWithError("failed to print mutated result", err)
} }
fmt.Printf("\n\nMutation:\nMutation has been applied successfully. Check the files.") fmt.Printf("\n\nMutation:\nMutation has been applied successfully. Check the files.")
} }
@ -612,34 +614,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
policyCtx := &engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource, JSONContext: ctx, NamespaceLabels: namespaceLabels} policyCtx := &engine.PolicyContext{Policy: *policy, NewResource: mutateResponse.PatchedResource, JSONContext: ctx, NamespaceLabels: namespaceLabels}
validateResponse := engine.Validate(policyCtx) validateResponse := engine.Validate(policyCtx)
printCount := 0 info := checkValidateEngineResponse(policy, validateResponse, resPath, rc)
if !policyReport {
for _, policyRule := range policy.Spec.Rules {
ruleFoundInEngineResponse := false
for i, valResponseRule := range validateResponse.PolicyResponse.Rules {
if policyRule.Name == valResponseRule.Name {
ruleFoundInEngineResponse = true
if valResponseRule.Success {
rc.Pass++
} else {
if printCount < 1 {
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
printCount++
}
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name, valResponseRule.Message)
rc.Fail++
}
continue
}
}
if !ruleFoundInEngineResponse {
rc.Skip++
}
}
}
var policyHasGenerate bool var policyHasGenerate bool
for _, rule := range policy.Spec.Rules { for _, rule := range policy.Spec.Rules {
@ -673,7 +648,7 @@ func ApplyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unst
} }
} }
return validateResponse, nil return validateResponse, info, nil
} }
// PrintMutatedOutput - function to print output in provided file or directory // PrintMutatedOutput - function to print output in provided file or directory
@ -798,3 +773,65 @@ func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []str
} }
return resources, err return resources, err
} }
func checkValidateEngineResponse(policy *v1.ClusterPolicy, validateResponse *response.EngineResponse, resPath string, rc *ResultCounts) policyreport.Info {
var violatedRules []v1.ViolatedRule
printCount := 0
for _, policyRule := range policy.Spec.Rules {
ruleFoundInEngineResponse := false
for i, valResponseRule := range validateResponse.PolicyResponse.Rules {
if policyRule.Name == valResponseRule.Name {
ruleFoundInEngineResponse = true
vrule := v1.ViolatedRule{
Name: valResponseRule.Name,
Type: valResponseRule.Type,
Message: valResponseRule.Message,
}
if valResponseRule.Success {
rc.Pass++
vrule.Check = report.StatusPass
} else {
if printCount < 1 {
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.Name, resPath)
printCount++
}
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name, valResponseRule.Message)
rc.Fail++
vrule.Check = report.StatusFail
}
violatedRules = append(violatedRules, vrule)
continue
}
}
if !ruleFoundInEngineResponse {
rc.Skip++
vruleSkip := v1.ViolatedRule{
Name: policyRule.Name,
Type: "Validation",
Message: policyRule.Validation.Message,
Check: report.StatusSkip,
}
violatedRules = append(violatedRules, vruleSkip)
}
}
return buildPVInfo(validateResponse, violatedRules)
}
func buildPVInfo(er *response.EngineResponse, violatedRules []v1.ViolatedRule) policyreport.Info {
info := policyreport.Info{
PolicyName: er.PolicyResponse.Policy.Name,
Namespace: er.PatchedResource.GetNamespace(),
Results: []policyreport.EngineResponseResult{
{
Resource: er.GetResourceSpec(),
Rules: violatedRules,
},
},
}
return info
}

View file

@ -85,7 +85,7 @@ func Test_NamespaceSelector(t *testing.T) {
for _, tc := range testcases { for _, tc := range testcases {
policyArray, _ := ut.GetPolicy(tc.policy) policyArray, _ := ut.GetPolicy(tc.policy)
resourceArray, _ := GetResource(tc.resource) resourceArray, _ := GetResource(tc.resource)
validateErs, _ := ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, false, tc.namespaceSelectorMap, false, nil) validateErs, _, _ := ApplyPolicyOnResource(policyArray[0], resourceArray[0], "", false, nil, false, tc.namespaceSelectorMap, false, nil)
assert.Assert(t, tc.success == validateErs.IsSuccessful()) assert.Assert(t, tc.success == validateErs.IsSuccessful())
} }
} }

View file

@ -394,7 +394,7 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, valuesFile s
return sanitizederror.NewWithError(fmt.Sprintf("policy %s have variables. pass the values for the variables using set/values_file flag", policy.Name), err) return sanitizederror.NewWithError(fmt.Sprintf("policy %s have variables. pass the values for the variables using set/values_file flag", policy.Name), err)
} }
validateErs, err := common.ApplyPolicyOnResource(policy, resource, "", false, thisPolicyResourceValues, true, namespaceSelectorMap, false, nil) validateErs, _, err := common.ApplyPolicyOnResource(policy, resource, "", false, thisPolicyResourceValues, true, namespaceSelectorMap, false, nil)
if err != nil { if err != nil {
return sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err) return sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.Name, resource.GetName()).Error(), err)
} }