mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
add control names and images to PSS results (#9869)
* add control names and images to PSS results Signed-off-by: Jim Bugwadia <jim@nirmata.com> * remove init Signed-off-by: Jim Bugwadia <jim@nirmata.com> * fix tets Signed-off-by: Jim Bugwadia <jim@nirmata.com> * update chainsaw tests Signed-off-by: Jim Bugwadia <jim@nirmata.com> * add unit test Signed-off-by: Jim Bugwadia <jim@nirmata.com> --------- Signed-off-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
02838a3cf7
commit
befcd73ea1
10 changed files with 139 additions and 49 deletions
|
@ -89,7 +89,7 @@ func Command() *cobra.Command {
|
||||||
cmd.SilenceErrors = true
|
cmd.SilenceErrors = true
|
||||||
printSkippedAndInvalidPolicies(out, skipInvalidPolicies)
|
printSkippedAndInvalidPolicies(out, skipInvalidPolicies)
|
||||||
if applyCommandConfig.PolicyReport {
|
if applyCommandConfig.PolicyReport {
|
||||||
printReport(out, responses, applyCommandConfig.AuditWarn)
|
printReports(out, responses, applyCommandConfig.AuditWarn)
|
||||||
} else if table {
|
} else if table {
|
||||||
printTable(out, detailedResults, applyCommandConfig.AuditWarn, responses...)
|
printTable(out, detailedResults, applyCommandConfig.AuditWarn, responses...)
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,7 +167,7 @@ func (c *ApplyCommandConfig) applyCommandHelper(out io.Writer) (*processor.Resul
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rc, resources1, skipInvalidPolicies, responses1, fmt.Errorf("Error: failed to load exceptions (%s)", err)
|
return rc, resources1, skipInvalidPolicies, responses1, fmt.Errorf("Error: failed to load exceptions (%s)", err)
|
||||||
}
|
}
|
||||||
if !c.Stdin {
|
if !c.Stdin && !c.PolicyReport {
|
||||||
var policyRulesCount int
|
var policyRulesCount int
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
policyRulesCount += len(autogen.ComputeRules(policy))
|
policyRulesCount += len(autogen.ComputeRules(policy))
|
||||||
|
@ -446,18 +446,17 @@ func printSkippedAndInvalidPolicies(out io.Writer, skipInvalidPolicies SkippedIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printReport(out io.Writer, engineResponses []engineapi.EngineResponse, auditWarn bool) {
|
func printReports(out io.Writer, engineResponses []engineapi.EngineResponse, auditWarn bool) {
|
||||||
clustered, namespaced := report.ComputePolicyReports(auditWarn, engineResponses...)
|
clustered, namespaced := report.ComputePolicyReports(auditWarn, engineResponses...)
|
||||||
if len(clustered) > 0 || len(namespaced) > 0 {
|
if len(clustered) > 0 {
|
||||||
fmt.Fprintln(out, divider)
|
|
||||||
fmt.Fprintln(out, "POLICY REPORT:")
|
|
||||||
fmt.Fprintln(out, divider)
|
|
||||||
report := report.MergeClusterReports(clustered)
|
report := report.MergeClusterReports(clustered)
|
||||||
yamlReport, _ := yaml.Marshal(report)
|
yamlReport, _ := yaml.Marshal(report)
|
||||||
fmt.Fprintln(out, string(yamlReport))
|
fmt.Fprintln(out, string(yamlReport))
|
||||||
} else {
|
}
|
||||||
fmt.Fprintln(out, divider)
|
for _, r := range namespaced {
|
||||||
fmt.Fprintln(out, "POLICY REPORT: skip generating policy report (no validate policy found/resource skipped)")
|
fmt.Fprintln(out, string("---"))
|
||||||
|
yamlReport, _ := yaml.Marshal(r)
|
||||||
|
fmt.Fprintln(out, string(yamlReport))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ func (h validateImageHandler) Process(
|
||||||
for _, v := range rule.VerifyImages {
|
for _, v := range rule.VerifyImages {
|
||||||
imageVerify := v.Convert()
|
imageVerify := v.Convert()
|
||||||
for _, infoMap := range policyContext.JSONContext().ImageInfo() {
|
for _, infoMap := range policyContext.JSONContext().ImageInfo() {
|
||||||
for name, imageInfo := range infoMap {
|
for _, imageInfo := range infoMap {
|
||||||
image := imageInfo.String()
|
image := imageInfo.String()
|
||||||
|
|
||||||
if !engineutils.ImageMatches(image, imageVerify.ImageReferences) {
|
if !engineutils.ImageMatches(image, imageVerify.ImageReferences) {
|
||||||
|
@ -76,7 +76,7 @@ func (h validateImageHandler) Process(
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.V(4).Info("validating image", "image", image)
|
logger.V(4).Info("validating image", "image", image)
|
||||||
if v, err := validateImage(policyContext, imageVerify, name, imageInfo, logger); err != nil {
|
if v, err := validateImage(policyContext, imageVerify, imageInfo, logger); err != nil {
|
||||||
return resource, handlers.WithFail(rule, engineapi.ImageVerify, err.Error())
|
return resource, handlers.WithFail(rule, engineapi.ImageVerify, err.Error())
|
||||||
} else if v == engineapi.ImageVerificationSkip {
|
} else if v == engineapi.ImageVerificationSkip {
|
||||||
skippedImages = append(skippedImages, image)
|
skippedImages = append(skippedImages, image)
|
||||||
|
@ -98,7 +98,7 @@ func (h validateImageHandler) Process(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, name string, imageInfo apiutils.ImageInfo, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) {
|
func validateImage(ctx engineapi.PolicyContext, imageVerify *kyvernov1.ImageVerification, imageInfo apiutils.ImageInfo, log logr.Logger) (engineapi.ImageVerificationMetadataStatus, error) {
|
||||||
var verified engineapi.ImageVerificationMetadataStatus
|
var verified engineapi.ImageVerificationMetadataStatus
|
||||||
var err error
|
var err error
|
||||||
image := imageInfo.String()
|
image := imageInfo.String()
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||||
"github.com/kyverno/kyverno/pkg/pss"
|
"github.com/kyverno/kyverno/pkg/pss"
|
||||||
pssutils "github.com/kyverno/kyverno/pkg/pss/utils"
|
pssutils "github.com/kyverno/kyverno/pkg/pss/utils"
|
||||||
|
"github.com/kyverno/kyverno/pkg/utils/api"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
batchv1 "k8s.io/api/batch/v1"
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
@ -76,6 +78,7 @@ func (h validatePssHandler) Process(
|
||||||
}
|
}
|
||||||
allowed, pssChecks := pss.EvaluatePod(levelVersion, podSecurity.Exclude, pod)
|
allowed, pssChecks := pss.EvaluatePod(levelVersion, podSecurity.Exclude, pod)
|
||||||
pssChecks = convertChecks(pssChecks, resource.GetKind())
|
pssChecks = convertChecks(pssChecks, resource.GetKind())
|
||||||
|
pssChecks = addImages(pssChecks, policyContext.JSONContext().ImageInfo())
|
||||||
podSecurityChecks := engineapi.PodSecurityChecks{
|
podSecurityChecks := engineapi.PodSecurityChecks{
|
||||||
Level: podSecurity.Level,
|
Level: podSecurity.Level,
|
||||||
Version: podSecurity.Version,
|
Version: podSecurity.Version,
|
||||||
|
@ -134,12 +137,65 @@ func convertChecks(checks []pssutils.PSSCheckResult, kind string) (newChecks []p
|
||||||
return checks
|
return checks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract container names from PSS error details. Here are some example inputs:
|
||||||
|
// - "containers \"nginx\", \"busybox\" must set securityContext.allowPrivilegeEscalation=false"
|
||||||
|
// - "containers \"nginx\", \"busybox\" must set securityContext.capabilities.drop=[\"ALL\"]"
|
||||||
|
// - "pod or containers \"nginx\", \"busybox\" must set securityContext.runAsNonRoot=true"
|
||||||
|
// - "pod or containers \"nginx\", \"busybox\" must set securityContext.seccompProfile.type to \"RuntimeDefault\" or \"Localhost\""
|
||||||
|
// - "pod or container \"nginx\" must set securityContext.seccompProfile.type to \"RuntimeDefault\" or \"Localhost\""
|
||||||
|
// - "container \"nginx\" must set securityContext.allowPrivilegeEscalation=false"
|
||||||
|
var regexContainerNames = regexp.MustCompile(`container(?:s)?\s*(.*?)\s*must`)
|
||||||
|
|
||||||
|
func addImages(checks []pssutils.PSSCheckResult, imageInfos map[string]map[string]api.ImageInfo) []pssutils.PSSCheckResult {
|
||||||
|
for i, check := range checks {
|
||||||
|
text := check.CheckResult.ForbiddenDetail
|
||||||
|
matches := regexContainerNames.FindAllStringSubmatch(text, -1)
|
||||||
|
if len(matches) > 0 {
|
||||||
|
s := strings.ReplaceAll(matches[0][1], "\"", "")
|
||||||
|
s = strings.ReplaceAll(s, " ", "")
|
||||||
|
containerNames := strings.Split(s, ",")
|
||||||
|
checks[i].Images = getImages(containerNames, imageInfos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checks
|
||||||
|
}
|
||||||
|
|
||||||
|
// return image references for containers
|
||||||
|
func getImages(containerNames []string, imageInfos map[string]map[string]api.ImageInfo) []string {
|
||||||
|
var images []string
|
||||||
|
for _, cn := range containerNames {
|
||||||
|
image := getImageReference(cn, imageInfos)
|
||||||
|
images = append(images, image)
|
||||||
|
}
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an image references for a container name
|
||||||
|
// if the image is not found, the name is returned
|
||||||
|
func getImageReference(name string, imageInfos map[string]map[string]api.ImageInfo) string {
|
||||||
|
if containers, ok := imageInfos["containers"]; ok {
|
||||||
|
if imageInfo, ok := containers[name]; ok {
|
||||||
|
return imageInfo.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if initContainers, ok := imageInfos["initContainers"]; ok {
|
||||||
|
if imageInfo, ok := initContainers[name]; ok {
|
||||||
|
return imageInfo.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ephemeralContainers, ok := imageInfos["ephemeralContainers"]; ok {
|
||||||
|
if imageInfo, ok := ephemeralContainers[name]; ok {
|
||||||
|
return imageInfo.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metadata *metav1.ObjectMeta, err error) {
|
func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metadata *metav1.ObjectMeta, err error) {
|
||||||
kind := resource.GetKind()
|
kind := resource.GetKind()
|
||||||
|
|
||||||
if kind == "DaemonSet" || kind == "Deployment" || kind == "Job" || kind == "StatefulSet" || kind == "ReplicaSet" || kind == "ReplicationController" {
|
if kind == "DaemonSet" || kind == "Deployment" || kind == "Job" || kind == "StatefulSet" || kind == "ReplicaSet" || kind == "ReplicationController" {
|
||||||
var deployment appsv1.Deployment
|
var deployment appsv1.Deployment
|
||||||
|
|
||||||
resourceBytes, err := resource.MarshalJSON()
|
resourceBytes, err := resource.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -153,7 +209,6 @@ func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metad
|
||||||
return podSpec, metadata, nil
|
return podSpec, metadata, nil
|
||||||
} else if kind == "CronJob" {
|
} else if kind == "CronJob" {
|
||||||
var cronJob batchv1.CronJob
|
var cronJob batchv1.CronJob
|
||||||
|
|
||||||
resourceBytes, err := resource.MarshalJSON()
|
resourceBytes, err := resource.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -164,9 +219,9 @@ func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metad
|
||||||
}
|
}
|
||||||
podSpec = &cronJob.Spec.JobTemplate.Spec.Template.Spec
|
podSpec = &cronJob.Spec.JobTemplate.Spec.Template.Spec
|
||||||
metadata = &cronJob.Spec.JobTemplate.ObjectMeta
|
metadata = &cronJob.Spec.JobTemplate.ObjectMeta
|
||||||
|
return podSpec, metadata, nil
|
||||||
} else if kind == "Pod" {
|
} else if kind == "Pod" {
|
||||||
var pod corev1.Pod
|
var pod corev1.Pod
|
||||||
|
|
||||||
resourceBytes, err := resource.MarshalJSON()
|
resourceBytes, err := resource.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -178,11 +233,7 @@ func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metad
|
||||||
podSpec = &pod.Spec
|
podSpec = &pod.Spec
|
||||||
metadata = &pod.ObjectMeta
|
metadata = &pod.ObjectMeta
|
||||||
return podSpec, metadata, nil
|
return podSpec, metadata, nil
|
||||||
} else {
|
|
||||||
return nil, nil, fmt.Errorf("could not find correct resource type")
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
return nil, nil, fmt.Errorf("could not find correct resource type")
|
||||||
}
|
|
||||||
return podSpec, metadata, err
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,7 +331,7 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *engine
|
||||||
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path))
|
return engineapi.RuleFail(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path))
|
||||||
}
|
}
|
||||||
|
|
||||||
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, pe.Path), nil)
|
return engineapi.RuleError(v.rule.Name, engineapi.Validation, v.buildErrorMessage(err, ""), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.log.V(4).Info("successfully processed rule")
|
v.log.V(4).Info("successfully processed rule")
|
||||||
|
|
|
@ -77,7 +77,7 @@ func exemptExclusions(defaultCheckResults, excludeCheckResults []pssutils.PSSChe
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, excludeResult := range excludeCheckResults {
|
for _, excludeResult := range excludeCheckResults {
|
||||||
for _, checkID := range pssutils.PSS_controls_to_check_id[exclude.ControlName] {
|
for _, checkID := range pssutils.PSS_control_name_to_ids[exclude.ControlName] {
|
||||||
if excludeResult.ID == checkID {
|
if excludeResult.ID == checkID {
|
||||||
for _, excludeFieldErr := range *excludeResult.CheckResult.ErrList {
|
for _, excludeFieldErr := range *excludeResult.CheckResult.ErrList {
|
||||||
var excludeField, excludeContainerType string
|
var excludeField, excludeContainerType string
|
||||||
|
@ -313,7 +313,7 @@ func GetPodWithMatchingContainers(exclude kyvernov1.PodSecurityStandard, pod *co
|
||||||
|
|
||||||
// Get restrictedFields from Check.ID
|
// Get restrictedFields from Check.ID
|
||||||
func GetRestrictedFields(check policy.Check) []pssutils.RestrictedField {
|
func GetRestrictedFields(check policy.Check) []pssutils.RestrictedField {
|
||||||
for _, control := range pssutils.PSS_controls_to_check_id {
|
for _, control := range pssutils.PSS_control_name_to_ids {
|
||||||
for _, checkID := range control {
|
for _, checkID := range control {
|
||||||
if string(check.ID) == checkID {
|
if string(check.ID) == checkID {
|
||||||
return pssutils.PSS_controls[checkID]
|
return pssutils.PSS_controls[checkID]
|
||||||
|
|
|
@ -42,7 +42,7 @@ var PSS_container_level_control = []string{
|
||||||
// Translate PSS control to CheckResult.ID so that we can use PSS control in Kyverno policy
|
// Translate PSS control to CheckResult.ID so that we can use PSS control in Kyverno policy
|
||||||
// For PSS controls see: https://kubernetes.io/docs/concepts/security/pod-security-standards/
|
// For PSS controls see: https://kubernetes.io/docs/concepts/security/pod-security-standards/
|
||||||
// For CheckResult.ID see: https://github.com/kubernetes/pod-security-admission/tree/master/policy
|
// For CheckResult.ID see: https://github.com/kubernetes/pod-security-admission/tree/master/policy
|
||||||
var PSS_controls_to_check_id = map[string][]string{
|
var PSS_control_name_to_ids = map[string][]string{
|
||||||
// Controls with 2 different controls for each level
|
// Controls with 2 different controls for each level
|
||||||
// container-level control
|
// container-level control
|
||||||
"Capabilities": {
|
"Capabilities": {
|
||||||
|
@ -110,6 +110,20 @@ var PSS_controls_to_check_id = map[string][]string{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reverse mapping of PSS_control_name_to_ids
|
||||||
|
var pss_control_id_to_name = map[string]string{}
|
||||||
|
|
||||||
|
func PSSControlIDToName(id string) string {
|
||||||
|
if len(pss_control_id_to_name) == 0 {
|
||||||
|
for name, ids := range PSS_control_name_to_ids {
|
||||||
|
for _, id := range ids {
|
||||||
|
pss_control_id_to_name[id] = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pss_control_id_to_name[id]
|
||||||
|
}
|
||||||
|
|
||||||
var PSS_controls = map[string][]RestrictedField{
|
var PSS_controls = map[string][]RestrictedField{
|
||||||
// Control name as key, same as ID field in CheckResult
|
// Control name as key, same as ID field in CheckResult
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,5 @@ type PSSCheckResult struct {
|
||||||
ID string
|
ID string
|
||||||
CheckResult policy.CheckResult
|
CheckResult policy.CheckResult
|
||||||
RestrictedFields []RestrictedField
|
RestrictedFields []RestrictedField
|
||||||
|
Images []string
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
|
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||||
"k8s.io/api/admissionregistration/v1alpha1"
|
|
||||||
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
@ -169,7 +168,7 @@ func SetPolicyExceptionLabel(report kyvernov1alpha2.ReportInterface, exception k
|
||||||
controllerutils.SetLabel(report, PolicyExceptionLabel(exception), exception.GetResourceVersion())
|
controllerutils.SetLabel(report, PolicyExceptionLabel(exception), exception.GetResourceVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetValidatingAdmissionPolicyBindingLabel(report kyvernov1alpha2.ReportInterface, binding v1alpha1.ValidatingAdmissionPolicyBinding) {
|
func SetValidatingAdmissionPolicyBindingLabel(report kyvernov1alpha2.ReportInterface, binding admissionregistrationv1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||||
controllerutils.SetLabel(report, ValidatingAdmissionPolicyBindingLabel(binding), binding.GetResourceVersion())
|
controllerutils.SetLabel(report, ValidatingAdmissionPolicyBindingLabel(binding), binding.GetResourceVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ package report
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
|
"encoding/json"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
||||||
kyvernov1alpha2 "github.com/kyverno/kyverno/api/kyverno/v1alpha2"
|
kyvernov1alpha2 "github.com/kyverno/kyverno/api/kyverno/v1alpha2"
|
||||||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
|
"github.com/kyverno/kyverno/pkg/pss/utils"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
@ -87,14 +88,6 @@ func SeverityFromString(severity string) policyreportv1alpha2.PolicySeverity {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func addProperty(k, v string, result *policyreportv1alpha2.PolicyReportResult) {
|
|
||||||
if result.Properties == nil {
|
|
||||||
result.Properties = map[string]string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Properties[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToPolicyReportResult(policyType engineapi.PolicyType, policyName string, ruleResult engineapi.RuleResponse, annotations map[string]string, resource *corev1.ObjectReference) policyreportv1alpha2.PolicyReportResult {
|
func ToPolicyReportResult(policyType engineapi.PolicyType, policyName string, ruleResult engineapi.RuleResponse, annotations map[string]string, resource *corev1.ObjectReference) policyreportv1alpha2.PolicyReportResult {
|
||||||
result := policyreportv1alpha2.PolicyReportResult{
|
result := policyreportv1alpha2.PolicyReportResult{
|
||||||
Source: kyverno.ValueKyvernoApp,
|
Source: kyverno.ValueKyvernoApp,
|
||||||
|
@ -122,18 +115,7 @@ func ToPolicyReportResult(policyType engineapi.PolicyType, policyName string, ru
|
||||||
}
|
}
|
||||||
pss := ruleResult.PodSecurityChecks()
|
pss := ruleResult.PodSecurityChecks()
|
||||||
if pss != nil && len(pss.Checks) > 0 {
|
if pss != nil && len(pss.Checks) > 0 {
|
||||||
var controls []string
|
addPodSecurityProperties(pss, &result)
|
||||||
for _, check := range pss.Checks {
|
|
||||||
if !check.CheckResult.Allowed {
|
|
||||||
controls = append(controls, check.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(controls) > 0 {
|
|
||||||
sort.Strings(controls)
|
|
||||||
addProperty("standard", string(pss.Level), &result)
|
|
||||||
addProperty("version", pss.Version, &result)
|
|
||||||
addProperty("controls", strings.Join(controls, ","), &result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if policyType == engineapi.ValidatingAdmissionPolicyType {
|
if policyType == engineapi.ValidatingAdmissionPolicyType {
|
||||||
result.Source = "ValidatingAdmissionPolicy"
|
result.Source = "ValidatingAdmissionPolicy"
|
||||||
|
@ -145,6 +127,49 @@ func ToPolicyReportResult(policyType engineapi.PolicyType, policyName string, ru
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addProperty(k, v string, result *policyreportv1alpha2.PolicyReportResult) {
|
||||||
|
if result.Properties == nil {
|
||||||
|
result.Properties = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Properties[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
type Control struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Images []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPodSecurityProperties(pss *engineapi.PodSecurityChecks, result *policyreportv1alpha2.PolicyReportResult) {
|
||||||
|
if pss == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.Properties == nil {
|
||||||
|
result.Properties = map[string]string{}
|
||||||
|
}
|
||||||
|
var controls []Control
|
||||||
|
var controlIDs []string
|
||||||
|
for _, check := range pss.Checks {
|
||||||
|
if !check.CheckResult.Allowed {
|
||||||
|
controlName := utils.PSSControlIDToName(check.ID)
|
||||||
|
controlIDs = append(controlIDs, check.ID)
|
||||||
|
controls = append(controls, Control{
|
||||||
|
ID: check.ID,
|
||||||
|
Name: controlName,
|
||||||
|
Images: check.Images,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(controls) > 0 {
|
||||||
|
controlsJson, _ := json.Marshal(controls)
|
||||||
|
result.Properties["standard"] = string(pss.Level)
|
||||||
|
result.Properties["version"] = pss.Version
|
||||||
|
result.Properties["controls"] = strings.Join(controlIDs, ",")
|
||||||
|
result.Properties["controlsJSON"] = string(controlsJson)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func EngineResponseToReportResults(response engineapi.EngineResponse) []policyreportv1alpha2.PolicyReportResult {
|
func EngineResponseToReportResults(response engineapi.EngineResponse) []policyreportv1alpha2.PolicyReportResult {
|
||||||
pol := response.Policy()
|
pol := response.Policy()
|
||||||
policyName, _ := cache.MetaNamespaceKeyFunc(pol.AsKyvernoPolicy())
|
policyName, _ := cache.MetaNamespaceKeyFunc(pol.AsKyvernoPolicy())
|
||||||
|
|
|
@ -19,6 +19,7 @@ results:
|
||||||
policy: podsecurity-subrule-restricted
|
policy: podsecurity-subrule-restricted
|
||||||
properties:
|
properties:
|
||||||
controls: capabilities_restricted
|
controls: capabilities_restricted
|
||||||
|
controlsJSON: '[{"ID":"capabilities_restricted","Name":"Capabilities","Images":["docker.io/dummyimagename:latest"]}]'
|
||||||
standard: restricted
|
standard: restricted
|
||||||
version: latest
|
version: latest
|
||||||
result: fail
|
result: fail
|
||||||
|
|
Loading…
Add table
Reference in a new issue