1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00
kyverno/cmd/cli/kubectl-kyverno/report/report.go
Charles-Edouard Brétéché dbad967150
fix: namespace in kyverno-test.yaml seems to have no effect in case of exclude (#8354)
* fix: namespace in kyverno-test.yaml seems to have no effect in case of exclude

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix tests

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* 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>
2023-09-12 14:33:26 +00:00

130 lines
4.9 KiB
Go

package report
import (
"github.com/kyverno/kyverno/api/kyverno"
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy/annotations"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
)
func ComputePolicyReportResult(auditWarn bool, engineResponse engineapi.EngineResponse, ruleResponse engineapi.RuleResponse) policyreportv1alpha2.PolicyReportResult {
policy := engineResponse.Policy()
policyName := cache.MetaObjectToName(policy.MetaObject()).String()
audit := engineResponse.GetValidationFailureAction().Audit()
scored := annotations.Scored(policy.GetAnnotations())
category := annotations.Category(policy.GetAnnotations())
severity := annotations.Severity(policy.GetAnnotations())
result := policyreportv1alpha2.PolicyReportResult{
Policy: policyName,
Resources: []corev1.ObjectReference{
{
Kind: engineResponse.Resource.GetKind(),
Namespace: engineResponse.Resource.GetNamespace(),
APIVersion: engineResponse.Resource.GetAPIVersion(),
Name: engineResponse.Resource.GetName(),
UID: engineResponse.Resource.GetUID(),
},
},
Scored: scored,
Category: category,
Severity: severity,
}
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 || (audit && auditWarn) {
result.Result = policyreportv1alpha2.StatusWarn
} else {
result.Result = policyreportv1alpha2.StatusFail
}
} else {
result.Result = policyreportv1alpha2.StatusError
}
if policy.GetType() == engineapi.KyvernoPolicyType {
result.Rule = ruleResponse.Name()
}
result.Message = ruleResponse.Message()
result.Source = kyverno.ValueKyvernoApp
result.Timestamp = metav1.Timestamp{Seconds: ruleResponse.Stats().Timestamp()}
return result
}
func ComputePolicyReportResultsPerPolicy(auditWarn bool, engineResponses ...engineapi.EngineResponse) map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult {
results := map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult{}
for _, engineResponse := range engineResponses {
if len(engineResponse.PolicyResponse.Rules) == 0 {
continue
}
policy := engineResponse.Policy()
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
// TODO only validation is managed here ?
// if ruleResponse.RuleType() != engineapi.Validation && ruleResponse.RuleType() != engineapi.ImageVerify {
// continue
// }
results[policy] = append(results[policy], ComputePolicyReportResult(auditWarn, engineResponse, ruleResponse))
}
}
if len(results) == 0 {
return nil
}
return results
}
func ComputePolicyReports(auditWarn bool, engineResponses ...engineapi.EngineResponse) ([]policyreportv1alpha2.ClusterPolicyReport, []policyreportv1alpha2.PolicyReport) {
var clustered []policyreportv1alpha2.ClusterPolicyReport
var namespaced []policyreportv1alpha2.PolicyReport
perPolicyResults := ComputePolicyReportResultsPerPolicy(auditWarn, engineResponses...)
for policy, results := range perPolicyResults {
if policy.GetNamespace() == "" {
report := policyreportv1alpha2.ClusterPolicyReport{
TypeMeta: metav1.TypeMeta{
APIVersion: policyreportv1alpha2.SchemeGroupVersion.String(),
Kind: "ClusterPolicyReport",
},
Results: results,
Summary: reportutils.CalculateSummary(results),
}
report.SetName(policy.GetName())
clustered = append(clustered, report)
} else {
report := policyreportv1alpha2.PolicyReport{
TypeMeta: metav1.TypeMeta{
APIVersion: policyreportv1alpha2.SchemeGroupVersion.String(),
Kind: "PolicyReport",
},
Results: results,
Summary: reportutils.CalculateSummary(results),
}
report.SetName(policy.GetName())
report.SetNamespace(policy.GetNamespace())
namespaced = append(namespaced, report)
}
}
return clustered, namespaced
}
func MergeClusterReports(clustered []policyreportv1alpha2.ClusterPolicyReport) policyreportv1alpha2.ClusterPolicyReport {
var results []policyreportv1alpha2.PolicyReportResult
for _, report := range clustered {
results = append(results, report.Results...)
}
return policyreportv1alpha2.ClusterPolicyReport{
TypeMeta: metav1.TypeMeta{
Kind: "ClusterPolicyReport",
APIVersion: policyreportv1alpha2.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "merged",
},
Results: results,
Summary: reportutils.CalculateSummary(results),
}
}