mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
refactor: remove obsolete structs from CLI (#6802)
* feat: add policy reporter to the dev lab Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor: remove obsolete structs from CLI Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more 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 Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * codegen 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 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
d08a50a641
commit
4c740e6999
10 changed files with 305 additions and 373 deletions
|
@ -1,17 +0,0 @@
|
|||
package v1
|
||||
|
||||
// ViolatedRule stores the information regarding the rule.
|
||||
type ViolatedRule struct {
|
||||
// Name specifies violated rule name.
|
||||
Name string `json:"name" yaml:"name"`
|
||||
|
||||
// Type specifies violated rule type.
|
||||
Type string `json:"type" yaml:"type"`
|
||||
|
||||
// Message specifies violation message.
|
||||
// +optional
|
||||
Message string `json:"message" yaml:"message"`
|
||||
|
||||
// Status shows the rule response status
|
||||
Status string `json:"status" yaml:"status"`
|
||||
}
|
|
@ -1423,18 +1423,3 @@ func (in *Variable) DeepCopy() *Variable {
|
|||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ViolatedRule) DeepCopyInto(out *ViolatedRule) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ViolatedRule.
|
||||
func (in *ViolatedRule) DeepCopy() *ViolatedRule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ViolatedRule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@ import (
|
|||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
policy2 "github.com/kyverno/kyverno/pkg/policy"
|
||||
gitutils "github.com/kyverno/kyverno/pkg/utils/git"
|
||||
|
@ -175,7 +177,7 @@ func Command() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
PrintReportOrViolation(applyCommandConfig.PolicyReport, rc, applyCommandConfig.ResourcePaths, len(resources), skipInvalidPolicies, applyCommandConfig.Stdin, pvInfos, applyCommandConfig.warnExitCode, applyCommandConfig.warnNoPassed)
|
||||
PrintReportOrViolation(applyCommandConfig.PolicyReport, rc, applyCommandConfig.ResourcePaths, len(resources), skipInvalidPolicies, applyCommandConfig.Stdin, pvInfos, applyCommandConfig.warnExitCode, applyCommandConfig.warnNoPassed, applyCommandConfig.AuditWarn)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -199,7 +201,7 @@ func Command() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, resources []*unstructured.Unstructured, skipInvalidPolicies SkippedInvalidPolicies, pvInfos []common.Info, err error) {
|
||||
func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, resources []*unstructured.Unstructured, skipInvalidPolicies SkippedInvalidPolicies, responses []engineapi.EngineResponse, err error) {
|
||||
store.SetMock(true)
|
||||
store.SetRegistryAccess(c.RegistryAccess)
|
||||
if c.Cluster {
|
||||
|
@ -208,48 +210,48 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
fs := memfs.New()
|
||||
|
||||
if c.ValuesFile != "" && c.VariablesString != "" {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("pass the values either using set flag or values_file flag", err)
|
||||
}
|
||||
|
||||
variables, globalValMap, valuesMap, namespaceSelectorMap, subresources, err := common.GetVariable(c.VariablesString, c.ValuesFile, fs, false, "")
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to decode yaml", err)
|
||||
}
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
|
||||
openApiManager, err := openapi.NewManager(log.Log)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to initialize openAPIController", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to initialize openAPIController", err)
|
||||
}
|
||||
|
||||
var dClient dclient.Interface
|
||||
if c.Cluster {
|
||||
restConfig, err := config.CreateClientConfigWithContext(c.KubeConfig, c.Context)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
kubeClient, err := kubernetes.NewForConfig(restConfig)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
dynamicClient, err := dynamic.NewForConfig(restConfig)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
dClient, err = dclient.NewClient(context.Background(), dynamicClient, kubeClient, 15*time.Minute)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.PolicyPaths) == 0 {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("require policy", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("require policy", err)
|
||||
}
|
||||
|
||||
if (len(c.PolicyPaths) > 0 && c.PolicyPaths[0] == "-") && len(c.ResourcePaths) > 0 && c.ResourcePaths[0] == "-" {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("a stdin pipe can be used for either policies or resources, not both", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("a stdin pipe can be used for either policies or resources, not both", err)
|
||||
}
|
||||
|
||||
var policies []kyvernov1.PolicyInterface
|
||||
|
@ -282,7 +284,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
}
|
||||
policyYamls, err := gitutils.ListYamls(fs, gitPathToYamls)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to list YAMLs in repository", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to list YAMLs in repository", err)
|
||||
}
|
||||
sort.Strings(policyYamls)
|
||||
c.PolicyPaths = policyYamls
|
||||
|
@ -294,15 +296,15 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
}
|
||||
|
||||
if len(c.ResourcePaths) == 0 && !c.Cluster {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("resource file(s) or cluster required", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("resource file(s) or cluster required", err)
|
||||
}
|
||||
|
||||
mutateLogPathIsDir, err := checkMutateLogPath(c.MutateLogPath)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to create file/folder", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to create file/folder", err)
|
||||
}
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, 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)
|
||||
|
@ -313,15 +315,15 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
_, err := os.OpenFile(c.MutateLogPath, os.O_TRUNC|os.O_WRONLY, 0o600) // #nosec G304
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to truncate the existing file at "+c.MutateLogPath, err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to truncate the existing file at "+c.MutateLogPath, err)
|
||||
}
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, err
|
||||
return rc, resources, skipInvalidPolicies, responses, err
|
||||
}
|
||||
}
|
||||
|
||||
err = common.PrintMutatedPolicy(policies)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("failed to marshal mutated policy", err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("failed to marshal mutated policy", err)
|
||||
}
|
||||
|
||||
resources, err = common.GetResourceAccordingToResourcePath(fs, c.ResourcePaths, c.Cluster, policies, dClient, c.Namespace, c.PolicyReport, false, "")
|
||||
|
@ -331,7 +333,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
}
|
||||
|
||||
if (len(resources) > 1 || len(policies) > 1) && c.VariablesString != "" {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError("currently `set` flag supports variable for single policy applied on single resource ", nil)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError("currently `set` flag supports variable for single policy applied on single resource ", nil)
|
||||
}
|
||||
|
||||
// get the user info as request info from a different file
|
||||
|
@ -415,7 +417,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
for _, resource := range resources {
|
||||
thisPolicyResourceValues, err := common.CheckVariableForPolicy(valuesMap, globalValMap, policy.GetName(), resource.GetName(), resource.GetKind(), variables, kindOnwhichPolicyIsApplied, variable)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.GetName(), resource.GetName()), err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError(fmt.Sprintf("policy `%s` have variables. pass the values for the variables for resource `%s` using set/values_file flag", policy.GetName(), resource.GetName()), err)
|
||||
}
|
||||
applyPolicyConfig := common.ApplyPolicyConfig{
|
||||
Policy: policy,
|
||||
|
@ -433,15 +435,60 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
|||
AuditWarn: c.AuditWarn,
|
||||
Subresources: subresources,
|
||||
}
|
||||
_, info, err := common.ApplyPolicyOnResource(applyPolicyConfig)
|
||||
ers, err := common.ApplyPolicyOnResource(applyPolicyConfig)
|
||||
if err != nil {
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.GetName(), resource.GetName()).Error(), err)
|
||||
return rc, resources, skipInvalidPolicies, responses, sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.GetName(), resource.GetName()).Error(), err)
|
||||
}
|
||||
for _, response := range ers {
|
||||
if !response.IsEmpty() {
|
||||
for _, rule := range autogen.ComputeRules(response.Policy) {
|
||||
if rule.HasValidate() || rule.HasVerifyImageChecks() || rule.HasVerifyImages() {
|
||||
ruleFoundInEngineResponse := false
|
||||
for _, valResponseRule := range response.PolicyResponse.Rules {
|
||||
if rule.Name == valResponseRule.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
switch valResponseRule.Status() {
|
||||
case engineapi.RuleStatusPass:
|
||||
rc.Pass++
|
||||
case engineapi.RuleStatusFail:
|
||||
ann := policy.GetAnnotations()
|
||||
if scored, ok := ann[kyvernov1.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
rc.Warn++
|
||||
break
|
||||
} else if applyPolicyConfig.AuditWarn && response.GetValidationFailureAction().Audit() {
|
||||
rc.Warn++
|
||||
} else {
|
||||
rc.Fail++
|
||||
}
|
||||
case engineapi.RuleStatusError:
|
||||
rc.Error++
|
||||
case engineapi.RuleStatusWarn:
|
||||
rc.Warn++
|
||||
case engineapi.RuleStatusSkip:
|
||||
rc.Skip++
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !ruleFoundInEngineResponse {
|
||||
rc.Skip++
|
||||
response.PolicyResponse.Rules = append(response.PolicyResponse.Rules,
|
||||
*engineapi.RuleSkip(
|
||||
rule.Name,
|
||||
engineapi.Validation,
|
||||
rule.Validation.Message,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
responses = append(responses, response)
|
||||
}
|
||||
pvInfos = append(pvInfos, info)
|
||||
}
|
||||
}
|
||||
|
||||
return rc, resources, skipInvalidPolicies, pvInfos, nil
|
||||
return rc, resources, skipInvalidPolicies, responses, nil
|
||||
}
|
||||
|
||||
// checkMutateLogPath - checking path for printing mutated resource (-o flag)
|
||||
|
@ -467,7 +514,7 @@ func checkMutateLogPath(mutateLogPath string) (mutateLogPathIsDir bool, err erro
|
|||
}
|
||||
|
||||
// PrintReportOrViolation - printing policy report/violations
|
||||
func PrintReportOrViolation(policyReport bool, rc *common.ResultCounts, resourcePaths []string, resourcesLen int, skipInvalidPolicies SkippedInvalidPolicies, stdin bool, pvInfos []common.Info, warnExitCode int, warnNoPassed bool) {
|
||||
func PrintReportOrViolation(policyReport bool, rc *common.ResultCounts, resourcePaths []string, resourcesLen int, skipInvalidPolicies SkippedInvalidPolicies, stdin bool, engineResponses []engineapi.EngineResponse, warnExitCode int, warnNoPassed bool, auditWarn bool) {
|
||||
divider := "----------------------------------------------------------------------"
|
||||
|
||||
if len(skipInvalidPolicies.skipped) > 0 {
|
||||
|
@ -488,7 +535,7 @@ func PrintReportOrViolation(policyReport bool, rc *common.ResultCounts, resource
|
|||
}
|
||||
|
||||
if policyReport {
|
||||
resps := buildPolicyReports(pvInfos)
|
||||
resps := buildPolicyReports(auditWarn, engineResponses...)
|
||||
if len(resps) > 0 || resourcesLen == 0 {
|
||||
fmt.Println(divider)
|
||||
fmt.Println("POLICY REPORT:")
|
||||
|
@ -502,8 +549,7 @@ func PrintReportOrViolation(policyReport bool, rc *common.ResultCounts, resource
|
|||
}
|
||||
} else {
|
||||
if !stdin {
|
||||
fmt.Printf("\npass: %d, fail: %d, warn: %d, error: %d, skip: %d \n",
|
||||
rc.Pass, rc.Fail, rc.Warn, rc.Error, rc.Skip)
|
||||
fmt.Printf("\npass: %d, fail: %d, warn: %d, error: %d, skip: %d \n", rc.Pass, rc.Fail, rc.Warn, rc.Error, rc.Skip)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ func Test_Apply(t *testing.T) {
|
|||
_, _, _, info, err := tc.config.applyCommandHelper()
|
||||
assert.NilError(t, err, desc)
|
||||
|
||||
resps := buildPolicyReports(info)
|
||||
resps := buildPolicyReports(tc.config.AuditWarn, info...)
|
||||
assert.Assert(t, len(resps) > 0, "policy reports should not be empty: %s", desc)
|
||||
for i, resp := range resps {
|
||||
compareSummary(tc.expectedPolicyReports[i].Summary, resp.UnstructuredContent()["summary"].(map[string]interface{}), desc)
|
||||
|
|
|
@ -8,24 +8,22 @@ import (
|
|||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
)
|
||||
|
||||
const clusterpolicyreport = "clusterpolicyreport"
|
||||
|
||||
// resps is the engine responses generated for a single policy
|
||||
func buildPolicyReports(pvInfos []common.Info) (res []*unstructured.Unstructured) {
|
||||
func buildPolicyReports(auditWarn bool, engineResponses ...engineapi.EngineResponse) (res []*unstructured.Unstructured) {
|
||||
var raw []byte
|
||||
var err error
|
||||
|
||||
resultsMap := buildPolicyResults(pvInfos)
|
||||
resultsMap := buildPolicyResults(auditWarn, engineResponses...)
|
||||
for scope, result := range resultsMap {
|
||||
if scope == clusterpolicyreport {
|
||||
report := &policyreportv1alpha2.ClusterPolicyReport{
|
||||
|
@ -74,46 +72,63 @@ func buildPolicyReports(pvInfos []common.Info) (res []*unstructured.Unstructured
|
|||
|
||||
// buildPolicyResults returns a string-PolicyReportResult map
|
||||
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
|
||||
func buildPolicyResults(infos []common.Info) map[string][]policyreportv1alpha2.PolicyReportResult {
|
||||
func buildPolicyResults(auditWarn bool, engineResponses ...engineapi.EngineResponse) map[string][]policyreportv1alpha2.PolicyReportResult {
|
||||
results := make(map[string][]policyreportv1alpha2.PolicyReportResult)
|
||||
now := metav1.Timestamp{Seconds: time.Now().Unix()}
|
||||
|
||||
for _, info := range infos {
|
||||
for _, engineResponse := range engineResponses {
|
||||
policy := engineResponse.Policy
|
||||
var appname string
|
||||
ns := info.Namespace
|
||||
ns := policy.GetNamespace()
|
||||
if ns != "" {
|
||||
appname = fmt.Sprintf("policyreport-ns-%s", ns)
|
||||
} else {
|
||||
appname = clusterpolicyreport
|
||||
}
|
||||
|
||||
for _, infoResult := range info.Results {
|
||||
for _, rule := range infoResult.Rules {
|
||||
if rule.Type != string(engineapi.Validation) {
|
||||
continue
|
||||
}
|
||||
|
||||
result := policyreportv1alpha2.PolicyReportResult{
|
||||
Policy: info.PolicyName,
|
||||
Resources: []corev1.ObjectReference{
|
||||
{
|
||||
Kind: infoResult.Resource.Kind,
|
||||
Namespace: infoResult.Resource.Namespace,
|
||||
APIVersion: infoResult.Resource.APIVersion,
|
||||
Name: infoResult.Resource.Name,
|
||||
UID: types.UID(infoResult.Resource.UID),
|
||||
},
|
||||
},
|
||||
Scored: true,
|
||||
}
|
||||
|
||||
result.Rule = rule.Name
|
||||
result.Message = rule.Message
|
||||
result.Result = policyreportv1alpha2.PolicyResult(rule.Status)
|
||||
result.Source = kyvernov1.ValueKyvernoApp
|
||||
result.Timestamp = now
|
||||
results[appname] = append(results[appname], result)
|
||||
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
||||
if ruleResponse.RuleType() != engineapi.Validation {
|
||||
continue
|
||||
}
|
||||
|
||||
result := policyreportv1alpha2.PolicyReportResult{
|
||||
Policy: policy.GetName(),
|
||||
Resources: []corev1.ObjectReference{
|
||||
{
|
||||
Kind: engineResponse.Resource.GetKind(),
|
||||
Namespace: engineResponse.Resource.GetNamespace(),
|
||||
APIVersion: engineResponse.Resource.GetAPIVersion(),
|
||||
Name: engineResponse.Resource.GetName(),
|
||||
UID: engineResponse.Resource.GetUID(),
|
||||
},
|
||||
},
|
||||
Scored: true,
|
||||
}
|
||||
|
||||
ann := engineResponse.Policy.GetAnnotations()
|
||||
if ruleResponse.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusPass {
|
||||
result.Result = policyreportv1alpha2.StatusPass
|
||||
} else if ruleResponse.Status() == engineapi.RuleStatusFail {
|
||||
if scored, ok := ann[kyvernov1.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
result.Result = policyreportv1alpha2.StatusWarn
|
||||
} else if auditWarn && engineResponse.GetValidationFailureAction().Audit() {
|
||||
result.Result = policyreportv1alpha2.StatusWarn
|
||||
} else {
|
||||
result.Result = policyreportv1alpha2.StatusFail
|
||||
}
|
||||
} else {
|
||||
fmt.Println(ruleResponse)
|
||||
}
|
||||
|
||||
result.Rule = ruleResponse.Name()
|
||||
result.Message = ruleResponse.Message()
|
||||
result.Source = kyvernov1.ValueKyvernoApp
|
||||
result.Timestamp = now
|
||||
results[appname] = append(results[appname], result)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
preport "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
kyvCommon "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"gotest.tools/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
@ -84,8 +82,6 @@ var rawPolicy = []byte(`
|
|||
`)
|
||||
|
||||
func Test_buildPolicyReports(t *testing.T) {
|
||||
rc := &kyvCommon.ResultCounts{}
|
||||
var pvInfos []common.Info
|
||||
var policy kyverno.ClusterPolicy
|
||||
err := json.Unmarshal(rawPolicy, &policy)
|
||||
assert.NilError(t, err)
|
||||
|
@ -106,10 +102,7 @@ func Test_buildPolicyReports(t *testing.T) {
|
|||
),
|
||||
)
|
||||
|
||||
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)
|
||||
pvInfos = append(pvInfos, info)
|
||||
|
||||
reports := buildPolicyReports(pvInfos)
|
||||
reports := buildPolicyReports(false, er)
|
||||
assert.Assert(t, len(reports) == 1, len(reports))
|
||||
|
||||
for _, report := range reports {
|
||||
|
@ -132,8 +125,6 @@ func Test_buildPolicyReports(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_buildPolicyResults(t *testing.T) {
|
||||
rc := &kyvCommon.ResultCounts{}
|
||||
var pvInfos []common.Info
|
||||
var policy kyverno.ClusterPolicy
|
||||
err := json.Unmarshal(rawPolicy, &policy)
|
||||
assert.NilError(t, err)
|
||||
|
@ -153,10 +144,7 @@ func Test_buildPolicyResults(t *testing.T) {
|
|||
),
|
||||
)
|
||||
|
||||
info := kyvCommon.ProcessValidateEngineResponse(&policy, &er, "", rc, true, false)
|
||||
pvInfos = append(pvInfos, info)
|
||||
|
||||
results := buildPolicyResults(pvInfos)
|
||||
results := buildPolicyResults(false, er)
|
||||
|
||||
for _, result := range results {
|
||||
assert.Assert(t, len(result) == 2, len(result))
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5"
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
|
@ -33,7 +32,6 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
@ -189,7 +187,7 @@ func Command() *cobra.Command {
|
|||
manifest.PrintValidate()
|
||||
} else {
|
||||
store.SetRegistryAccess(registryAccess)
|
||||
_, err = testCommandExecute(dirPath, fileName, gitBranch, testCase, failOnly, removeColor)
|
||||
_, err = testCommandExecute(dirPath, fileName, gitBranch, testCase, failOnly, removeColor, false)
|
||||
if err != nil {
|
||||
log.Log.V(3).Info("a directory is required")
|
||||
return err
|
||||
|
@ -232,7 +230,15 @@ type testFilter struct {
|
|||
|
||||
var ftable []Table
|
||||
|
||||
func testCommandExecute(dirPath []string, fileName string, gitBranch string, testCase string, failOnly bool, removeColor bool) (rc *resultCounts, err error) {
|
||||
func testCommandExecute(
|
||||
dirPath []string,
|
||||
fileName string,
|
||||
gitBranch string,
|
||||
testCase string,
|
||||
failOnly bool,
|
||||
removeColor bool,
|
||||
auditWarn bool,
|
||||
) (rc *resultCounts, err error) {
|
||||
var errors []error
|
||||
fs := memfs.New()
|
||||
rc = &resultCounts{}
|
||||
|
@ -352,7 +358,7 @@ func testCommandExecute(dirPath []string, fileName string, gitBranch string, tes
|
|||
errors = append(errors, sanitizederror.NewWithError("failed to convert to JSON", err))
|
||||
continue
|
||||
}
|
||||
if err := applyPoliciesFromPath(fs, policyBytes, true, policyresoucePath, rc, openApiManager, tf, failOnly, removeColor); err != nil {
|
||||
if err := applyPoliciesFromPath(fs, policyBytes, true, policyresoucePath, rc, openApiManager, tf, failOnly, removeColor, auditWarn); err != nil {
|
||||
return rc, sanitizederror.NewWithError("failed to apply test command", err)
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +370,7 @@ func testCommandExecute(dirPath []string, fileName string, gitBranch string, tes
|
|||
} else {
|
||||
var testFiles int
|
||||
path := filepath.Clean(dirPath[0])
|
||||
errors = getLocalDirTestFiles(fs, path, fileName, rc, &testFiles, openApiManager, tf, failOnly, removeColor)
|
||||
errors = getLocalDirTestFiles(fs, path, fileName, rc, &testFiles, openApiManager, tf, failOnly, removeColor, auditWarn)
|
||||
|
||||
if testFiles == 0 {
|
||||
fmt.Printf("\n No test files found. Please provide test YAML files named kyverno-test.yaml \n")
|
||||
|
@ -393,7 +399,18 @@ func testCommandExecute(dirPath []string, fileName string, gitBranch string, tes
|
|||
return rc, nil
|
||||
}
|
||||
|
||||
func getLocalDirTestFiles(fs billy.Filesystem, path, fileName string, rc *resultCounts, testFiles *int, openApiManager openapi.Manager, tf *testFilter, failOnly, removeColor bool) []error {
|
||||
func getLocalDirTestFiles(
|
||||
fs billy.Filesystem,
|
||||
path string,
|
||||
fileName string,
|
||||
rc *resultCounts,
|
||||
testFiles *int,
|
||||
openApiManager openapi.Manager,
|
||||
tf *testFilter,
|
||||
failOnly bool,
|
||||
removeColor bool,
|
||||
auditWarn bool,
|
||||
) []error {
|
||||
var errors []error
|
||||
|
||||
files, err := os.ReadDir(path)
|
||||
|
@ -402,7 +419,7 @@ func getLocalDirTestFiles(fs billy.Filesystem, path, fileName string, rc *result
|
|||
}
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
getLocalDirTestFiles(fs, filepath.Join(path, file.Name()), fileName, rc, testFiles, openApiManager, tf, failOnly, removeColor)
|
||||
getLocalDirTestFiles(fs, filepath.Join(path, file.Name()), fileName, rc, testFiles, openApiManager, tf, failOnly, removeColor, auditWarn)
|
||||
continue
|
||||
}
|
||||
if file.Name() == fileName {
|
||||
|
@ -418,7 +435,7 @@ func getLocalDirTestFiles(fs billy.Filesystem, path, fileName string, rc *result
|
|||
errors = append(errors, sanitizederror.NewWithError("failed to convert json", err))
|
||||
continue
|
||||
}
|
||||
if err := applyPoliciesFromPath(fs, valuesBytes, false, path, rc, openApiManager, tf, failOnly, removeColor); err != nil {
|
||||
if err := applyPoliciesFromPath(fs, valuesBytes, false, path, rc, openApiManager, tf, failOnly, removeColor, auditWarn); err != nil {
|
||||
errors = append(errors, sanitizederror.NewWithError(fmt.Sprintf("failed to apply test command from file %s", file.Name()), err))
|
||||
continue
|
||||
}
|
||||
|
@ -427,9 +444,15 @@ func getLocalDirTestFiles(fs billy.Filesystem, path, fileName string, rc *result
|
|||
return errors
|
||||
}
|
||||
|
||||
func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults []api.TestResults, infos []common.Info, policyResourcePath string, fs billy.Filesystem, isGit bool) (map[string]policyreportv1alpha2.PolicyReportResult, []api.TestResults) {
|
||||
results := make(map[string]policyreportv1alpha2.PolicyReportResult)
|
||||
now := metav1.Timestamp{Seconds: time.Now().Unix()}
|
||||
func buildPolicyResults(
|
||||
engineResponses []engineapi.EngineResponse,
|
||||
testResults []api.TestResults,
|
||||
policyResourcePath string,
|
||||
fs billy.Filesystem,
|
||||
isGit bool,
|
||||
auditWarn bool,
|
||||
) (map[string]policyreportv1alpha2.PolicyReportResult, []api.TestResults) {
|
||||
results := map[string]policyreportv1alpha2.PolicyReportResult{}
|
||||
|
||||
for _, resp := range engineResponses {
|
||||
policyName := resp.Policy.GetName()
|
||||
|
@ -573,75 +596,85 @@ func buildPolicyResults(engineResponses []*engineapi.EngineResponse, testResults
|
|||
results[resultKey] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
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)
|
||||
for _, key := range resultsKey {
|
||||
if val, ok := results[key]; ok {
|
||||
result = val
|
||||
resultKey = key
|
||||
} else {
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
if rule.RuleType() != engineapi.Mutation || test.Rule != rule.Name() {
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if rule.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else {
|
||||
var x string
|
||||
for _, path := range patchedResourcePath {
|
||||
result.Result = policyreportv1alpha2.StatusFail
|
||||
x = getAndCompareResource(path, resp.PatchedResource, isGit, policyResourcePath, fs, false)
|
||||
if x == "pass" {
|
||||
result.Result = policyreportv1alpha2.StatusPass
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results[resultKey] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
for _, infoResult := range info.Results {
|
||||
for _, rule := range infoResult.Rules {
|
||||
if rule.Type != string(engineapi.Validation) && rule.Type != string(engineapi.ImageVerify) {
|
||||
continue
|
||||
}
|
||||
|
||||
var result policyreportv1alpha2.PolicyReportResult
|
||||
var resultsKeys []string
|
||||
var resultsKey []string
|
||||
var resultKey string
|
||||
resultsKeys = GetAllPossibleResultsKey("", info.PolicyName, rule.Name, infoResult.Resource.Namespace, infoResult.Resource.Kind, infoResult.Resource.Name)
|
||||
for _, key := range resultsKeys {
|
||||
var result policyreportv1alpha2.PolicyReportResult
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name(), resourceNamespace, resourceKind, resourceName)
|
||||
for _, key := range resultsKey {
|
||||
if val, ok := results[key]; ok {
|
||||
result = val
|
||||
resultKey = key
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
if rule.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if rule.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else {
|
||||
var x string
|
||||
for _, path := range patchedResourcePath {
|
||||
result.Result = policyreportv1alpha2.StatusFail
|
||||
x = getAndCompareResource(path, resp.PatchedResource, isGit, policyResourcePath, fs, false)
|
||||
if x == "pass" {
|
||||
result.Result = policyreportv1alpha2.StatusPass
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results[resultKey] = result
|
||||
}
|
||||
}
|
||||
|
||||
for _, rule := range resp.PolicyResponse.Rules {
|
||||
if rule.RuleType() != engineapi.Validation && rule.RuleType() != engineapi.ImageVerify || test.Rule != rule.Name() {
|
||||
continue
|
||||
}
|
||||
|
||||
result.Rule = rule.Name
|
||||
result.Result = policyreportv1alpha2.PolicyResult(rule.Status)
|
||||
result.Source = kyvernov1.ValueKyvernoApp
|
||||
result.Timestamp = now
|
||||
results[resultKey] = result
|
||||
var resultsKey []string
|
||||
var resultKey string
|
||||
var result policyreportv1alpha2.PolicyReportResult
|
||||
resultsKey = GetAllPossibleResultsKey(policyNamespace, policyName, rule.Name(), resourceNamespace, resourceKind, resourceName)
|
||||
for _, key := range resultsKey {
|
||||
if val, ok := results[key]; ok {
|
||||
result = val
|
||||
resultKey = key
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
ann := resp.Policy.GetAnnotations()
|
||||
if rule.Status() == engineapi.RuleStatusSkip {
|
||||
result.Result = policyreportv1alpha2.StatusSkip
|
||||
} else if rule.Status() == engineapi.RuleStatusError {
|
||||
result.Result = policyreportv1alpha2.StatusError
|
||||
} else if rule.Status() == engineapi.RuleStatusPass {
|
||||
result.Result = policyreportv1alpha2.StatusPass
|
||||
} else if rule.Status() == engineapi.RuleStatusFail {
|
||||
if scored, ok := ann[kyvernov1.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
result.Result = policyreportv1alpha2.StatusWarn
|
||||
} else if auditWarn && resp.GetValidationFailureAction().Audit() {
|
||||
result.Result = policyreportv1alpha2.StatusWarn
|
||||
} else {
|
||||
result.Result = policyreportv1alpha2.StatusFail
|
||||
}
|
||||
} else {
|
||||
fmt.Println(rule)
|
||||
}
|
||||
|
||||
results[resultKey] = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results, testResults
|
||||
}
|
||||
|
||||
|
@ -707,7 +740,7 @@ func getAndCompareResource(path string, engineResource unstructured.Unstructured
|
|||
return status
|
||||
}
|
||||
|
||||
func buildMessage(resp *engineapi.EngineResponse) string {
|
||||
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())
|
||||
|
@ -730,12 +763,22 @@ func getFullPath(paths []string, policyResourcePath string, isGit bool) []string
|
|||
return paths
|
||||
}
|
||||
|
||||
func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, isGit bool, policyResourcePath string, rc *resultCounts, openApiManager openapi.Manager, tf *testFilter, failOnly, removeColor bool) (err error) {
|
||||
engineResponses := make([]*engineapi.EngineResponse, 0)
|
||||
func applyPoliciesFromPath(
|
||||
fs billy.Filesystem,
|
||||
policyBytes []byte,
|
||||
isGit bool,
|
||||
policyResourcePath string,
|
||||
rc *resultCounts,
|
||||
openApiManager openapi.Manager,
|
||||
tf *testFilter,
|
||||
failOnly bool,
|
||||
removeColor bool,
|
||||
auditWarn bool,
|
||||
) (err error) {
|
||||
engineResponses := make([]engineapi.EngineResponse, 0)
|
||||
var dClient dclient.Interface
|
||||
values := &api.Test{}
|
||||
var variablesString string
|
||||
var pvInfos []common.Info
|
||||
var resultCounts common.ResultCounts
|
||||
|
||||
store.SetMock(true)
|
||||
|
@ -911,15 +954,14 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, isGit bool,
|
|||
Client: dClient,
|
||||
Subresources: subresources,
|
||||
}
|
||||
ers, info, err := common.ApplyPolicyOnResource(applyPolicyConfig)
|
||||
ers, err := common.ApplyPolicyOnResource(applyPolicyConfig)
|
||||
if err != nil {
|
||||
return sanitizederror.NewWithError(fmt.Errorf("failed to apply policy %v on resource %v", policy.GetName(), resource.GetName()).Error(), err)
|
||||
}
|
||||
engineResponses = append(engineResponses, ers...)
|
||||
pvInfos = append(pvInfos, info)
|
||||
}
|
||||
}
|
||||
resultsMap, testResults := buildPolicyResults(engineResponses, values.Results, pvInfos, policyResourcePath, fs, isGit)
|
||||
resultsMap, testResults := buildPolicyResults(engineResponses, values.Results, policyResourcePath, fs, isGit, auditWarn)
|
||||
resultErr := printTestResult(resultsMap, testResults, rc, failOnly, removeColor)
|
||||
if resultErr != nil {
|
||||
return sanitizederror.NewWithError("failed to print test result:", resultErr)
|
||||
|
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/go-git/go-billy/v5"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
|
@ -369,8 +368,8 @@ func GetVariable(variablesString, valuesFile string, fs billy.Filesystem, isGit
|
|||
}
|
||||
|
||||
// ApplyPolicyOnResource - function to apply policy on resource
|
||||
func ApplyPolicyOnResource(c ApplyPolicyConfig) ([]*engineapi.EngineResponse, Info, error) {
|
||||
var engineResponses []*engineapi.EngineResponse
|
||||
func ApplyPolicyOnResource(c ApplyPolicyConfig) ([]engineapi.EngineResponse, error) {
|
||||
var engineResponses []engineapi.EngineResponse
|
||||
namespaceLabels := make(map[string]string)
|
||||
operationIsDelete := false
|
||||
|
||||
|
@ -416,7 +415,7 @@ OuterLoop:
|
|||
resourceNamespace := c.Resource.GetNamespace()
|
||||
namespaceLabels = c.NamespaceSelectorMap[c.Resource.GetNamespace()]
|
||||
if resourceNamespace != "default" && len(namespaceLabels) < 1 {
|
||||
return engineResponses, Info{}, sanitizederror.NewWithError(fmt.Sprintf("failed to get namespace labels for resource %s. use --values-file flag to pass the namespace labels", c.Resource.GetName()), nil)
|
||||
return engineResponses, sanitizederror.NewWithError(fmt.Sprintf("failed to get namespace labels for resource %s. use --values-file flag to pass the namespace labels", c.Resource.GetName()), nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,12 +491,12 @@ OuterLoop:
|
|||
WithResourceKind(gvk, subresource)
|
||||
|
||||
mutateResponse := eng.Mutate(context.Background(), policyContext)
|
||||
engineResponses = append(engineResponses, &mutateResponse)
|
||||
engineResponses = append(engineResponses, mutateResponse)
|
||||
|
||||
err = processMutateEngineResponse(c, &mutateResponse, resPath)
|
||||
if err != nil {
|
||||
if !sanitizederror.IsErrorSanitized(err) {
|
||||
return engineResponses, Info{}, sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
return engineResponses, sanitizederror.NewWithError("failed to print mutated result", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,21 +509,20 @@ OuterLoop:
|
|||
|
||||
policyContext = policyContext.WithNewResource(mutateResponse.PatchedResource)
|
||||
|
||||
var info Info
|
||||
var validateResponse engineapi.EngineResponse
|
||||
if policyHasValidate {
|
||||
validateResponse = eng.Validate(context.Background(), policyContext)
|
||||
info = ProcessValidateEngineResponse(c.Policy, &validateResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
ProcessValidateEngineResponse(c.Policy, validateResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
}
|
||||
|
||||
if !validateResponse.IsEmpty() {
|
||||
engineResponses = append(engineResponses, &validateResponse)
|
||||
engineResponses = append(engineResponses, validateResponse)
|
||||
}
|
||||
|
||||
verifyImageResponse, _ := eng.VerifyAndPatchImages(context.TODO(), policyContext)
|
||||
if !verifyImageResponse.IsEmpty() {
|
||||
engineResponses = append(engineResponses, &verifyImageResponse)
|
||||
info = ProcessValidateEngineResponse(c.Policy, &verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
engineResponses = append(engineResponses, verifyImageResponse)
|
||||
ProcessValidateEngineResponse(c.Policy, verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
}
|
||||
|
||||
var policyHasGenerate bool
|
||||
|
@ -543,12 +541,66 @@ OuterLoop:
|
|||
} else {
|
||||
generateResponse.PolicyResponse.Rules = newRuleResponse
|
||||
}
|
||||
engineResponses = append(engineResponses, &generateResponse)
|
||||
engineResponses = append(engineResponses, generateResponse)
|
||||
}
|
||||
updateResultCounts(c.Policy, &generateResponse, resPath, c.Rc, c.AuditWarn)
|
||||
}
|
||||
|
||||
return engineResponses, info, nil
|
||||
return engineResponses, nil
|
||||
}
|
||||
|
||||
func ProcessValidateEngineResponse(policy kyvernov1.PolicyInterface, validateResponse engineapi.EngineResponse, resPath string, rc *ResultCounts, policyReport bool, auditWarn bool) {
|
||||
printCount := 0
|
||||
for _, policyRule := range autogen.ComputeRules(policy) {
|
||||
ruleFoundInEngineResponse := false
|
||||
if !policyRule.HasValidate() && !policyRule.HasVerifyImageChecks() && !policyRule.HasVerifyImages() {
|
||||
continue
|
||||
}
|
||||
|
||||
for i, valResponseRule := range validateResponse.PolicyResponse.Rules {
|
||||
if policyRule.Name == valResponseRule.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
switch valResponseRule.Status() {
|
||||
case engineapi.RuleStatusPass:
|
||||
rc.Pass++
|
||||
case engineapi.RuleStatusFail:
|
||||
auditWarning := false
|
||||
ann := policy.GetAnnotations()
|
||||
if scored, ok := ann[kyvernov1.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
rc.Warn++
|
||||
break
|
||||
} else if auditWarn && validateResponse.GetValidationFailureAction().Audit() {
|
||||
rc.Warn++
|
||||
auditWarning = true
|
||||
} else {
|
||||
rc.Fail++
|
||||
}
|
||||
if !policyReport {
|
||||
if printCount < 1 {
|
||||
if auditWarning {
|
||||
fmt.Printf("\npolicy %s -> resource %s failed as audit warning: \n", policy.GetName(), resPath)
|
||||
} else {
|
||||
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.GetName(), resPath)
|
||||
}
|
||||
printCount++
|
||||
}
|
||||
|
||||
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name(), valResponseRule.Message())
|
||||
}
|
||||
case engineapi.RuleStatusError:
|
||||
rc.Error++
|
||||
case engineapi.RuleStatusWarn:
|
||||
rc.Warn++
|
||||
case engineapi.RuleStatusSkip:
|
||||
rc.Skip++
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !ruleFoundInEngineResponse {
|
||||
rc.Skip++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrintMutatedOutput - function to print output in provided file or directory
|
||||
|
@ -697,105 +749,6 @@ func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []str
|
|||
return resources, err
|
||||
}
|
||||
|
||||
func ProcessValidateEngineResponse(policy kyvernov1.PolicyInterface, validateResponse *engineapi.EngineResponse, resPath string, rc *ResultCounts, policyReport bool, auditWarn bool) Info {
|
||||
var violatedRules []kyvernov1.ViolatedRule
|
||||
|
||||
printCount := 0
|
||||
for _, policyRule := range autogen.ComputeRules(policy) {
|
||||
ruleFoundInEngineResponse := false
|
||||
if !policyRule.HasValidate() && !policyRule.HasVerifyImageChecks() && !policyRule.HasVerifyImages() {
|
||||
continue
|
||||
}
|
||||
|
||||
for i, valResponseRule := range validateResponse.PolicyResponse.Rules {
|
||||
if policyRule.Name == valResponseRule.Name() {
|
||||
ruleFoundInEngineResponse = true
|
||||
vrule := kyvernov1.ViolatedRule{
|
||||
Name: valResponseRule.Name(),
|
||||
Type: string(valResponseRule.RuleType()),
|
||||
Message: valResponseRule.Message(),
|
||||
}
|
||||
|
||||
switch valResponseRule.Status() {
|
||||
case engineapi.RuleStatusPass:
|
||||
rc.Pass++
|
||||
vrule.Status = policyreportv1alpha2.StatusPass
|
||||
|
||||
case engineapi.RuleStatusFail:
|
||||
auditWarning := false
|
||||
ann := policy.GetAnnotations()
|
||||
if scored, ok := ann[kyvernov1.AnnotationPolicyScored]; ok && scored == "false" {
|
||||
rc.Warn++
|
||||
vrule.Status = policyreportv1alpha2.StatusWarn
|
||||
break
|
||||
} else if auditWarn && validateResponse.GetValidationFailureAction().Audit() {
|
||||
rc.Warn++
|
||||
auditWarning = true
|
||||
vrule.Status = policyreportv1alpha2.StatusWarn
|
||||
} else {
|
||||
rc.Fail++
|
||||
vrule.Status = policyreportv1alpha2.StatusFail
|
||||
}
|
||||
|
||||
if !policyReport {
|
||||
if printCount < 1 {
|
||||
if auditWarning {
|
||||
fmt.Printf("\npolicy %s -> resource %s failed as audit warning: \n", policy.GetName(), resPath)
|
||||
} else {
|
||||
fmt.Printf("\npolicy %s -> resource %s failed: \n", policy.GetName(), resPath)
|
||||
}
|
||||
printCount++
|
||||
}
|
||||
|
||||
fmt.Printf("%d. %s: %s \n", i+1, valResponseRule.Name(), valResponseRule.Message())
|
||||
}
|
||||
|
||||
case engineapi.RuleStatusError:
|
||||
rc.Error++
|
||||
vrule.Status = policyreportv1alpha2.StatusError
|
||||
|
||||
case engineapi.RuleStatusWarn:
|
||||
rc.Warn++
|
||||
vrule.Status = policyreportv1alpha2.StatusWarn
|
||||
|
||||
case engineapi.RuleStatusSkip:
|
||||
rc.Skip++
|
||||
vrule.Status = policyreportv1alpha2.StatusSkip
|
||||
}
|
||||
|
||||
violatedRules = append(violatedRules, vrule)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !ruleFoundInEngineResponse {
|
||||
rc.Skip++
|
||||
vruleSkip := kyvernov1.ViolatedRule{
|
||||
Name: policyRule.Name,
|
||||
Type: "Validation",
|
||||
Message: policyRule.Validation.Message,
|
||||
Status: policyreportv1alpha2.StatusSkip,
|
||||
}
|
||||
violatedRules = append(violatedRules, vruleSkip)
|
||||
}
|
||||
}
|
||||
return buildPVInfo(validateResponse, violatedRules)
|
||||
}
|
||||
|
||||
func buildPVInfo(er *engineapi.EngineResponse, violatedRules []kyvernov1.ViolatedRule) Info {
|
||||
info := Info{
|
||||
PolicyName: er.Policy.GetName(),
|
||||
Namespace: er.PatchedResource.GetNamespace(),
|
||||
Results: []EngineResponseResult{
|
||||
{
|
||||
Resource: er.GetResourceSpec(),
|
||||
Rules: violatedRules,
|
||||
},
|
||||
},
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func updateResultCounts(policy kyvernov1.PolicyInterface, engineResponse *engineapi.EngineResponse, resPath string, rc *ResultCounts, auditWarn bool) {
|
||||
printCount := 0
|
||||
for _, policyRule := range autogen.ComputeRules(policy) {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
)
|
||||
|
||||
// Info stores the policy application results for all matched resources
|
||||
// Namespace is set to empty "" if resource is cluster wide resource
|
||||
type Info struct {
|
||||
PolicyName string
|
||||
Namespace string
|
||||
Results []EngineResponseResult
|
||||
}
|
||||
|
||||
type EngineResponseResult struct {
|
||||
Resource engineapi.ResourceSpec
|
||||
Rules []kyvernov1.ViolatedRule
|
||||
}
|
|
@ -3866,67 +3866,6 @@ expression evaluates to nil</p>
|
|||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h3 id="kyverno.io/v1.ViolatedRule">ViolatedRule
|
||||
</h3>
|
||||
<p>
|
||||
<p>ViolatedRule stores the information regarding the rule.</p>
|
||||
</p>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<code>name</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Name specifies violated rule name.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>type</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Type specifies violated rule type.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>message</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Message specifies violation message.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>status</code><br/>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<p>Status shows the rule response status</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
<h2 id="kyverno.io/v1alpha2">kyverno.io/v1alpha2</h2>
|
||||
<p>
|
||||
<p>Package v1alpha2 contains API Schema definitions for the policy v1alpha2 API group</p>
|
||||
|
|
Loading…
Reference in a new issue