2020-10-15 17:29:07 -07:00
|
|
|
package apply
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
2021-08-21 19:35:17 +02:00
|
|
|
"time"
|
2020-10-15 17:29:07 -07:00
|
|
|
|
2022-09-28 13:45:16 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2022-05-17 13:12:43 +02:00
|
|
|
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
2022-11-02 09:06:44 +00:00
|
|
|
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
2022-04-06 21:04:08 +02:00
|
|
|
"github.com/kyverno/kyverno/pkg/engine/response"
|
2023-01-03 13:02:15 +01:00
|
|
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
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
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
2020-12-21 11:04:19 -08:00
|
|
|
"k8s.io/apimachinery/pkg/types"
|
2020-10-15 17:29:07 -07:00
|
|
|
log "sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
|
)
|
|
|
|
|
|
|
|
const clusterpolicyreport = "clusterpolicyreport"
|
|
|
|
|
2020-10-27 00:41:16 +05:30
|
|
|
// resps is the engine responses generated for a single policy
|
2022-11-02 09:06:44 +00:00
|
|
|
func buildPolicyReports(pvInfos []common.Info) (res []*unstructured.Unstructured) {
|
2020-10-15 17:29:07 -07:00
|
|
|
var raw []byte
|
|
|
|
var err error
|
|
|
|
|
2021-09-02 01:06:29 +05:30
|
|
|
resultsMap := buildPolicyResults(pvInfos)
|
2020-10-15 17:29:07 -07:00
|
|
|
for scope, result := range resultsMap {
|
|
|
|
if scope == clusterpolicyreport {
|
2022-05-17 13:12:43 +02:00
|
|
|
report := &policyreportv1alpha2.ClusterPolicyReport{
|
2020-10-16 16:27:04 -07:00
|
|
|
TypeMeta: metav1.TypeMeta{
|
2022-05-17 13:12:43 +02:00
|
|
|
APIVersion: policyreportv1alpha2.SchemeGroupVersion.String(),
|
2020-10-16 16:27:04 -07:00
|
|
|
Kind: "ClusterPolicyReport",
|
|
|
|
},
|
2020-10-15 17:29:07 -07:00
|
|
|
Results: result,
|
|
|
|
Summary: calculateSummary(result),
|
|
|
|
}
|
|
|
|
|
|
|
|
report.SetName(scope)
|
|
|
|
if raw, err = json.Marshal(report); err != nil {
|
2020-12-21 11:04:19 -08:00
|
|
|
log.Log.V(3).Info("failed to serialize policy report", "name", report.Name, "scope", scope, "error", err)
|
2020-10-15 17:29:07 -07:00
|
|
|
}
|
|
|
|
} else {
|
2022-05-17 13:12:43 +02:00
|
|
|
report := &policyreportv1alpha2.PolicyReport{
|
2020-10-16 16:27:04 -07:00
|
|
|
TypeMeta: metav1.TypeMeta{
|
2022-05-17 13:12:43 +02:00
|
|
|
APIVersion: policyreportv1alpha2.SchemeGroupVersion.String(),
|
2020-10-16 16:27:04 -07:00
|
|
|
Kind: "PolicyReport",
|
|
|
|
},
|
2020-10-15 17:29:07 -07:00
|
|
|
Results: result,
|
|
|
|
Summary: calculateSummary(result),
|
|
|
|
}
|
|
|
|
|
|
|
|
ns := strings.ReplaceAll(scope, "policyreport-ns-", "")
|
|
|
|
report.SetName(scope)
|
|
|
|
report.SetNamespace(ns)
|
2020-10-16 16:27:04 -07:00
|
|
|
|
|
|
|
if raw, err = json.Marshal(report); err != nil {
|
2020-12-21 11:04:19 -08:00
|
|
|
log.Log.V(3).Info("failed to serialize policy report", "name", report.Name, "scope", scope, "error", err)
|
2020-10-16 16:27:04 -07:00
|
|
|
}
|
2020-10-15 17:29:07 -07:00
|
|
|
}
|
|
|
|
|
2023-01-03 13:02:15 +01:00
|
|
|
reportUnstructured, err := kubeutils.BytesToUnstructured(raw)
|
2020-10-15 17:29:07 -07:00
|
|
|
if err != nil {
|
2020-11-19 15:56:14 +05:30
|
|
|
log.Log.V(3).Info("failed to convert policy report", "scope", scope, "error", err)
|
2020-10-15 17:29:07 -07:00
|
|
|
continue
|
|
|
|
}
|
2020-10-16 16:27:04 -07:00
|
|
|
|
2020-10-15 17:29:07 -07:00
|
|
|
res = append(res, reportUnstructured)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// buildPolicyResults returns a string-PolicyReportResult map
|
|
|
|
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
|
2022-11-02 09:06:44 +00:00
|
|
|
func buildPolicyResults(infos []common.Info) map[string][]policyreportv1alpha2.PolicyReportResult {
|
2022-05-17 13:12:43 +02:00
|
|
|
results := make(map[string][]policyreportv1alpha2.PolicyReportResult)
|
2021-08-21 19:35:17 +02:00
|
|
|
now := metav1.Timestamp{Seconds: time.Now().Unix()}
|
2020-10-15 17:29:07 -07:00
|
|
|
|
|
|
|
for _, info := range infos {
|
|
|
|
var appname string
|
2020-12-21 11:04:19 -08:00
|
|
|
ns := info.Namespace
|
2020-10-15 17:29:07 -07:00
|
|
|
if ns != "" {
|
|
|
|
appname = fmt.Sprintf("policyreport-ns-%s", ns)
|
|
|
|
} else {
|
2022-05-09 18:55:35 +02:00
|
|
|
appname = clusterpolicyreport
|
2020-10-15 17:29:07 -07:00
|
|
|
}
|
|
|
|
|
2020-12-21 11:04:19 -08:00
|
|
|
for _, infoResult := range info.Results {
|
|
|
|
for _, rule := range infoResult.Rules {
|
2022-04-06 21:04:08 +02:00
|
|
|
if rule.Type != string(response.Validation) {
|
2020-12-21 11:04:19 -08:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-05-17 13:12:43 +02:00
|
|
|
result := policyreportv1alpha2.PolicyReportResult{
|
2020-12-21 11:04:19 -08:00
|
|
|
Policy: info.PolicyName,
|
2022-04-28 11:11:14 +02:00
|
|
|
Resources: []corev1.ObjectReference{
|
2020-12-21 11:04:19 -08:00
|
|
|
{
|
|
|
|
Kind: infoResult.Resource.Kind,
|
|
|
|
Namespace: infoResult.Resource.Namespace,
|
|
|
|
APIVersion: infoResult.Resource.APIVersion,
|
|
|
|
Name: infoResult.Resource.Name,
|
|
|
|
UID: types.UID(infoResult.Resource.UID),
|
|
|
|
},
|
2020-10-16 16:27:04 -07:00
|
|
|
},
|
2020-12-21 11:04:19 -08:00
|
|
|
Scored: true,
|
|
|
|
}
|
2020-10-15 17:29:07 -07:00
|
|
|
|
2020-12-21 11:04:19 -08:00
|
|
|
result.Rule = rule.Name
|
|
|
|
result.Message = rule.Message
|
2022-05-17 13:12:43 +02:00
|
|
|
result.Result = policyreportv1alpha2.PolicyResult(rule.Status)
|
2022-09-28 13:45:16 +02:00
|
|
|
result.Source = kyvernov1.ValueKyvernoApp
|
2021-08-21 19:35:17 +02:00
|
|
|
result.Timestamp = now
|
2022-04-28 11:11:14 +02:00
|
|
|
results[appname] = append(results[appname], result)
|
2020-12-21 11:04:19 -08:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2022-05-17 13:12:43 +02:00
|
|
|
func calculateSummary(results []policyreportv1alpha2.PolicyReportResult) (summary policyreportv1alpha2.PolicyReportSummary) {
|
2020-10-15 17:29:07 -07:00
|
|
|
for _, res := range results {
|
2021-08-21 19:35:17 +02:00
|
|
|
switch string(res.Result) {
|
2022-05-17 13:12:43 +02:00
|
|
|
case policyreportv1alpha2.StatusPass:
|
2020-11-10 10:49:29 +05:30
|
|
|
summary.Pass++
|
2022-05-17 13:12:43 +02:00
|
|
|
case policyreportv1alpha2.StatusFail:
|
2020-10-15 17:29:07 -07:00
|
|
|
summary.Fail++
|
2020-10-16 16:27:04 -07:00
|
|
|
case "warn":
|
2020-10-15 17:29:07 -07:00
|
|
|
summary.Warn++
|
2020-10-16 16:27:04 -07:00
|
|
|
case "error":
|
2020-10-15 17:29:07 -07:00
|
|
|
summary.Error++
|
2020-10-16 16:27:04 -07:00
|
|
|
case "skip":
|
2020-10-15 17:29:07 -07:00
|
|
|
summary.Skip++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|