2023-09-01 11:20:39 +02:00
|
|
|
package report
|
2020-10-15 17:29:07 -07:00
|
|
|
|
|
|
|
import (
|
2023-07-06 10:00:36 +02:00
|
|
|
"github.com/kyverno/kyverno/api/kyverno"
|
2022-05-17 13:12:43 +02:00
|
|
|
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
2023-09-01 01:42:08 +02:00
|
|
|
annotationsutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/annotations"
|
2023-01-30 12:41:09 +01:00
|
|
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
2023-07-04 18:28:22 +02:00
|
|
|
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
2020-10-15 17:29:07 -07:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2020-10-16 16:27:04 -07:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2020-10-15 17:29:07 -07:00
|
|
|
)
|
|
|
|
|
2023-09-04 11:34:27 +02:00
|
|
|
func ComputePolicyReportResult(auditWarn bool, engineResponse engineapi.EngineResponse, ruleResponse engineapi.RuleResponse) policyreportv1alpha2.PolicyReportResult {
|
|
|
|
policy := engineResponse.Policy()
|
|
|
|
policyName := policy.GetName()
|
|
|
|
audit := engineResponse.GetValidationFailureAction().Audit()
|
|
|
|
scored := annotationsutils.Scored(policy.GetAnnotations())
|
|
|
|
category := annotationsutils.Category(policy.GetAnnotations())
|
|
|
|
severity := annotationsutils.Severity(policy.GetAnnotations())
|
|
|
|
result := policyreportv1alpha2.PolicyReportResult{
|
|
|
|
// TODO policy name looks wrong, it should consider the namespace too
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-09-01 11:20:39 +02:00
|
|
|
func ComputePolicyReportResultsPerPolicy(auditWarn bool, engineResponses ...engineapi.EngineResponse) map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult {
|
|
|
|
results := make(map[engineapi.GenericPolicy][]policyreportv1alpha2.PolicyReportResult)
|
2023-04-12 14:51:03 +02:00
|
|
|
for _, engineResponse := range engineResponses {
|
2023-09-01 11:20:39 +02:00
|
|
|
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2023-08-15 22:41:43 +03:00
|
|
|
policy := engineResponse.Policy()
|
2023-04-12 14:51:03 +02:00
|
|
|
for _, ruleResponse := range engineResponse.PolicyResponse.Rules {
|
2023-09-01 11:20:39 +02:00
|
|
|
// TODO only validation is managed here ?
|
2023-09-04 11:34:27 +02:00
|
|
|
// if ruleResponse.RuleType() != engineapi.Validation && ruleResponse.RuleType() != engineapi.ImageVerify {
|
|
|
|
// continue
|
|
|
|
// }
|
|
|
|
result := ComputePolicyReportResult(auditWarn, engineResponse, ruleResponse)
|
2023-09-01 11:20:39 +02:00
|
|
|
results[policy] = append(results[policy], result)
|
2020-10-15 17:29:07 -07:00
|
|
|
}
|
|
|
|
}
|
2020-10-31 01:55:05 +05:30
|
|
|
return results
|
2020-10-15 17:29:07 -07:00
|
|
|
}
|
2023-09-01 11:20:39 +02:00
|
|
|
|
|
|
|
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, namespaced []policyreportv1alpha2.PolicyReport) policyreportv1alpha2.ClusterPolicyReport {
|
|
|
|
var results []policyreportv1alpha2.PolicyReportResult
|
|
|
|
for _, report := range clustered {
|
|
|
|
results = append(results, report.Results...)
|
|
|
|
}
|
|
|
|
// TODO why this ?
|
|
|
|
for _, report := range namespaced {
|
|
|
|
if report.GetNamespace() != "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
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),
|
|
|
|
}
|
|
|
|
}
|