1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00

add report logic in command apply

This commit is contained in:
Shuting Zhao 2020-10-15 17:29:07 -07:00
parent 99d27ec353
commit f798e9cf2d
8 changed files with 343 additions and 547 deletions

View file

@ -1,386 +0,0 @@
package jobs
import (
"fmt"
"strings"
"sync"
"time"
"github.com/cenkalti/backoff"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/constant"
dclient "github.com/kyverno/kyverno/pkg/dclient"
v1 "k8s.io/api/batch/v1"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/workqueue"
)
const workQueueName = "policy-violation-controller"
const workQueueRetryLimit = 3
//Job creates policy report
type Job struct {
dclient *dclient.Client
log logr.Logger
queue workqueue.RateLimitingInterface
dataStore *dataStore
configHandler config.Interface
mux sync.Mutex
}
// JobInfo defines Job Type
type JobInfo struct {
JobType string
JobData string
}
func (i JobInfo) toKey() string {
return fmt.Sprintf("kyverno-%v", i.JobType)
}
//NewDataStore returns an instance of data store
func newDataStore() *dataStore {
ds := dataStore{
data: make(map[string]JobInfo),
}
return &ds
}
type dataStore struct {
data map[string]JobInfo
mu sync.RWMutex
}
func (ds *dataStore) add(keyHash string, info JobInfo) {
ds.mu.Lock()
defer ds.mu.Unlock()
ds.data[keyHash] = info
}
func (ds *dataStore) lookup(keyHash string) JobInfo {
ds.mu.RLock()
defer ds.mu.RUnlock()
return ds.data[keyHash]
}
func (ds *dataStore) delete(keyHash string) {
ds.mu.Lock()
defer ds.mu.Unlock()
delete(ds.data, keyHash)
}
//JobsInterface provides API to create PVs
type JobsInterface interface {
Add(infos ...JobInfo)
}
// NewJobsJob returns a new instance of jobs generator
func NewJobsJob(dclient *dclient.Client,
configHandler config.Interface,
log logr.Logger) *Job {
gen := Job{
dclient: dclient,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), workQueueName),
dataStore: newDataStore(),
configHandler: configHandler,
log: log,
}
return &gen
}
func (j *Job) enqueue(info JobInfo) {
keyHash := info.toKey()
j.dataStore.add(keyHash, info)
j.queue.Add(keyHash)
j.log.V(4).Info("job added to the queue", "keyhash", keyHash)
}
//Add queues a job creation request
func (j *Job) Add(infos ...JobInfo) {
for _, info := range infos {
j.enqueue(info)
}
}
// Run starts the workers
func (j *Job) Run(workers int, stopCh <-chan struct{}) {
logger := j.log
defer utilruntime.HandleCrash()
logger.Info("start")
defer logger.Info("shutting down")
for i := 0; i < workers; i++ {
go wait.Until(j.runWorker, constant.PolicyViolationControllerResync, stopCh)
}
<-stopCh
}
func (j *Job) runWorker() {
for j.processNextWorkItem() {
}
}
func (j *Job) handleErr(err error, key interface{}) {
logger := j.log
if err == nil {
j.queue.Forget(key)
return
}
// retires requests if there is error
if j.queue.NumRequeues(key) < workQueueRetryLimit {
logger.Error(err, "failed to sync queued jobs", "key", key)
// Re-enqueue the key rate limited. Based on the rate limiter on the
// queue and the re-enqueue history, the key will be processed later again.
j.queue.AddRateLimited(key)
return
}
j.queue.Forget(key)
if keyHash, ok := key.(string); ok {
j.dataStore.delete(keyHash)
}
logger.Error(err, "dropping key out of the queue", "key", key)
}
func (j *Job) processNextWorkItem() bool {
logger := j.log
obj, shutdown := j.queue.Get()
if shutdown {
return false
}
defer j.queue.Done(obj)
var keyHash string
var ok bool
if keyHash, ok = obj.(string); !ok {
j.queue.Forget(obj)
logger.Info("incorrect type; expecting type 'string'", "obj", obj)
return true
}
// lookup data store
info := j.dataStore.lookup(keyHash)
err := j.syncHandler(info)
j.handleErr(err, keyHash)
return true
}
func (j *Job) syncHandler(info JobInfo) error {
defer func() {
j.mux.Unlock()
}()
j.mux.Lock()
var err error
var wg sync.WaitGroup
if info.JobType == constant.BackgroundPolicySync {
wg.Add(1)
go func() {
err = j.syncKyverno(&wg, constant.All, constant.BackgroundPolicySync, info.JobData)
}()
}
if info.JobType == constant.ConfigmapMode {
// shuting?
if info.JobData == "" {
return nil
}
scopes := strings.Split(info.JobData, ",")
if len(scopes) == 1 {
wg.Add(1)
go func() {
err = j.syncKyverno(&wg, constant.All, constant.ConfigmapMode, "")
}()
} else {
wg.Add(len(scopes))
for _, scope := range scopes {
go func(scope string) {
err = j.syncKyverno(&wg, scope, constant.ConfigmapMode, "")
}(scope)
}
}
}
wg.Wait()
return err
}
func (j *Job) syncKyverno(wg *sync.WaitGroup, scope, jobType, data string) error {
defer wg.Done()
go j.cleanupCompletedJobs()
mode := "cli"
args := []string{
"report",
"all",
fmt.Sprintf("--mode=%s", "configmap"),
}
if jobType == constant.BackgroundPolicySync || jobType == constant.BackgroundSync {
switch scope {
case constant.Namespace:
args = []string{
"report",
"namespace",
fmt.Sprintf("--mode=%s", mode),
}
case constant.Cluster:
args = []string{
"report",
"cluster",
fmt.Sprintf("--mode=%s", mode),
}
case constant.All:
args = []string{
"report",
"all",
fmt.Sprintf("--mode=%s", mode),
}
}
}
if jobType == constant.BackgroundPolicySync && data != "" {
args = append(args, fmt.Sprintf("-p=%s", data))
}
exbackoff := &backoff.ExponentialBackOff{
InitialInterval: backoff.DefaultInitialInterval,
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: time.Second,
MaxElapsedTime: 5 * time.Minute,
Clock: backoff.SystemClock,
}
exbackoff.Reset()
err := backoff.Retry(func() error {
resourceList, err := j.dclient.ListResource("", "Job", config.KubePolicyNamespace, &metav1.LabelSelector{
MatchLabels: map[string]string{
"scope": scope,
"type": jobType,
},
})
if err != nil {
return fmt.Errorf("failed to list jobs: %v", err)
}
if len(resourceList.Items) != 0 {
return fmt.Errorf("found %d Jobs", len(resourceList.Items))
}
return nil
}, exbackoff)
if err != nil {
return err
}
return j.CreateJob(args, jobType, scope)
}
// CreateJob will create Job template for background scan
func (j *Job) CreateJob(args []string, jobType, scope string) error {
ttl := new(int32)
*ttl = 60
job := &v1.Job{
ObjectMeta: metav1.ObjectMeta{
Namespace: config.KubePolicyNamespace,
Labels: map[string]string{
"scope": scope,
"type": jobType,
},
},
Spec: v1.JobSpec{
Template: apiv1.PodTemplateSpec{
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{
{
Name: strings.ToLower(fmt.Sprintf("%s-%s", jobType, scope)),
Image: config.KyvernoCliImage,
ImagePullPolicy: apiv1.PullAlways,
Args: args,
},
},
ServiceAccountName: "kyverno-service-account",
RestartPolicy: "OnFailure",
},
},
},
}
job.Spec.TTLSecondsAfterFinished = ttl
job.SetGenerateName("kyverno-policyreport-")
if _, err := j.dclient.CreateResource("", "Job", config.KubePolicyNamespace, job, false); err != nil {
return fmt.Errorf("failed to create job: %v", err)
}
return nil
}
func (j *Job) cleanupCompletedJobs() {
logger := j.log.WithName("cleanup jobs")
exbackoff := &backoff.ExponentialBackOff{
InitialInterval: backoff.DefaultInitialInterval,
RandomizationFactor: backoff.DefaultRandomizationFactor,
Multiplier: backoff.DefaultMultiplier,
MaxInterval: time.Second,
MaxElapsedTime: 2 * time.Minute,
Clock: backoff.SystemClock,
}
exbackoff.Reset()
err := backoff.Retry(func() error {
resourceList, err := j.dclient.ListResource("", "Job", config.KubePolicyNamespace, nil)
if err != nil {
return fmt.Errorf("failed to list jobs : %v", err)
}
if err != nil {
return fmt.Errorf("failed to list pods : %v", err)
}
for _, job := range resourceList.Items {
succeeded, ok, _ := unstructured.NestedInt64(job.Object, "status", "succeeded")
if ok && succeeded > 0 {
if errnew := j.dclient.DeleteResource("", "Job", job.GetNamespace(), job.GetName(), false); errnew != nil {
err = errnew
continue
}
podList, errNew := j.dclient.ListResource("", "Pod", config.KubePolicyNamespace, &metav1.LabelSelector{
MatchLabels: map[string]string{
"job-name": job.GetName(),
},
})
if errNew != nil {
err = errNew
continue
}
for _, pod := range podList.Items {
if errpod := j.dclient.DeleteResource("", "Pod", pod.GetNamespace(), pod.GetName(), false); errpod != nil {
logger.Error(errpod, "failed to delete pod", "name", pod.GetName())
err = errpod
}
}
}
}
return err
}, exbackoff)
if err != nil {
logger.Error(err, "failed to clean up completed jobs")
}
}

View file

@ -3,45 +3,28 @@ package apply
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"reflect"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/openapi"
"k8s.io/apimachinery/pkg/util/yaml"
"os"
"path/filepath"
"reflect"
"strings"
"time"
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/utils"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/kyverno/common"
"github.com/kyverno/kyverno/pkg/kyverno/sanitizedError"
"github.com/kyverno/kyverno/pkg/openapi"
policy2 "github.com/kyverno/kyverno/pkg/policy"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/kyverno/kyverno/pkg/engine"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/utils"
"github.com/spf13/cobra"
yamlv2 "gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes/scheme"
log "sigs.k8s.io/controller-runtime/pkg/log"
)
@ -187,13 +170,13 @@ func Command() *cobra.Command {
}
yamlBytes := []byte(resourceStr)
resources, err = getResource(yamlBytes)
resources, err = common.GetResource(yamlBytes)
if err != nil {
return sanitizedError.NewWithError("failed to extract the resources", err)
}
}
} else {
resources, err = getResources(policies, resourcePaths, dClient)
resources, err = common.GetResources(policies, resourcePaths, dClient)
if err != nil {
return sanitizedError.NewWithError("failed to load resources", err)
}
@ -277,135 +260,6 @@ func Command() *cobra.Command {
return cmd
}
func getResources(policies []*v1.ClusterPolicy, resourcePaths []string, dClient *client.Client) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
var err error
if dClient != nil {
var resourceTypesMap = make(map[string]bool)
var resourceTypes []string
for _, policy := range policies {
for _, rule := range policy.Spec.Rules {
for _, kind := range rule.MatchResources.Kinds {
resourceTypesMap[kind] = true
}
}
}
for kind := range resourceTypesMap {
resourceTypes = append(resourceTypes, kind)
}
resources, err = getResourcesOfTypeFromCluster(resourceTypes, dClient)
if err != nil {
return nil, err
}
}
for _, resourcePath := range resourcePaths {
resourceBytes, err := getFileBytes(resourcePath)
if err != nil {
return nil, err
}
getResources, err := getResource(resourceBytes)
if err != nil {
return nil, err
}
for _, resource := range getResources {
resources = append(resources, resource)
}
}
return resources, nil
}
func getResourcesOfTypeFromCluster(resourceTypes []string, dClient *client.Client) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
for _, kind := range resourceTypes {
resourceList, err := dClient.ListResource("", kind, "", nil)
if err != nil {
return nil, err
}
version := resourceList.GetAPIVersion()
for _, resource := range resourceList.Items {
resource.SetGroupVersionKind(schema.GroupVersionKind{
Group: "",
Version: version,
Kind: kind,
})
resources = append(resources, resource.DeepCopy())
}
}
return resources, nil
}
func getFileBytes(path string) ([]byte, error) {
file, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return file, err
}
func getResource(resourceBytes []byte) ([]*unstructured.Unstructured, error) {
resources := make([]*unstructured.Unstructured, 0)
var getErrString string
files, splitDocError := utils.SplitYAMLDocuments(resourceBytes)
if splitDocError != nil {
return nil, splitDocError
}
for _, resourceYaml := range files {
resource, err := convertResourceToUnstructured(resourceYaml)
if err != nil {
getErrString = getErrString + err.Error() + "\n"
}
resources = append(resources, resource)
}
if getErrString != "" {
return nil, errors.New(getErrString)
}
return resources, nil
}
func convertResourceToUnstructured(resourceYaml []byte) (*unstructured.Unstructured, error) {
decode := scheme.Codecs.UniversalDeserializer().Decode
resourceObject, metaData, err := decode(resourceYaml, nil, nil)
if err != nil {
return nil, err
}
resourceUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&resourceObject)
if err != nil {
return nil, err
}
resourceJSON, err := json.Marshal(resourceUnstructured)
if err != nil {
return nil, err
}
resource, err := engineutils.ConvertToUnstructured(resourceJSON)
if err != nil {
return nil, err
}
resource.SetGroupVersionKind(*metaData)
if resource.GetNamespace() == "" {
resource.SetNamespace("default")
}
return resource, nil
}
// applyPolicyOnResource - function to apply policy on resource
func applyPolicyOnResource(policy *v1.ClusterPolicy, resource *unstructured.Unstructured, mutateLogPath string, mutateLogPathIsDir bool, variables map[string]string, rc *resultCounts) error {
responseError := false

156
pkg/kyverno/apply/report.go Normal file
View file

@ -0,0 +1,156 @@
package apply
import (
"encoding/json"
"fmt"
"strings"
policyreportv1alpha1 "github.com/kyverno/kyverno/pkg/api/policyreport/v1alpha1"
"github.com/kyverno/kyverno/pkg/engine/response"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/policyreport"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
log "sigs.k8s.io/controller-runtime/pkg/log"
)
const clusterpolicyreport = "clusterpolicyreport"
// resps is the engine reponses generated for a single policy
func buildPolicyReports(resps []response.EngineResponse) (res []*unstructured.Unstructured) {
var raw []byte
var err error
resultsMap := buildPolicyResults(resps)
for scope, result := range resultsMap {
if scope == clusterpolicyreport {
report := &policyreportv1alpha1.ClusterPolicyReport{
Results: result,
Summary: calculateSummary(result),
}
report.SetName(scope)
if raw, err = json.Marshal(report); err != nil {
log.Log.Error(err, "failed to serilize policy report", "name", report.Name, "scope", scope)
}
} else {
report := &policyreportv1alpha1.PolicyReport{
Results: result,
Summary: calculateSummary(result),
}
ns := strings.ReplaceAll(scope, "policyreport-ns-", "")
report.SetName(scope)
report.SetNamespace(ns)
}
reportUnstructured, err := engineutils.ConvertToUnstructured(raw)
if err != nil {
log.Log.Error(err, "failed to convert policy report", "scope", scope)
continue
}
res = append(res, reportUnstructured)
}
return
}
// buildPolicyResults returns a string-PolicyReportResult map
// the key of the map is one of "clusterpolicyreport", "policyreport-ns-<namespace>"
func buildPolicyResults(resps []response.EngineResponse) map[string][]*policyreportv1alpha1.PolicyReportResult {
results := make(map[string][]*policyreportv1alpha1.PolicyReportResult)
infos := policyreport.GeneratePRsFromEngineResponse(resps, log.Log)
for _, info := range infos {
var appname string
ns := info.Resource.GetNamespace()
if ns != "" {
appname = fmt.Sprintf("policyreport-ns-%s", ns)
} else {
appname = fmt.Sprintf(clusterpolicyreport)
}
result := &policyreportv1alpha1.PolicyReportResult{
Policy: info.PolicyName,
Resources: []*corev1.ObjectReference{
{
Kind: info.Resource.GetKind(),
Namespace: info.Resource.GetNamespace(),
APIVersion: info.Resource.GetAPIVersion(),
Name: info.Resource.GetName(),
UID: info.Resource.GetUID(),
},
},
}
for _, rule := range info.Rules {
result.Rule = rule.Name
result.Message = rule.Message
result.Status = policyreportv1alpha1.PolicyStatus(rule.Check)
results[appname] = append(results[appname], result)
}
}
return mergeSucceededResults(results)
}
func mergeSucceededResults(results map[string][]*policyreportv1alpha1.PolicyReportResult) map[string][]*policyreportv1alpha1.PolicyReportResult {
resultsNew := make(map[string][]*policyreportv1alpha1.PolicyReportResult)
for scope, scopedResults := range results {
resourcesMap := make(map[string]*policyreportv1alpha1.PolicyReportResult)
for _, result := range scopedResults {
if result.Status != policyreportv1alpha1.PolicyStatus("Pass") {
resultsNew[scope] = append(resultsNew[scope], result)
continue
}
key := fmt.Sprintf("%s/%s", result.Policy, result.Rule)
if r, ok := resourcesMap[key]; !ok {
resourcesMap[key] = &policyreportv1alpha1.PolicyReportResult{}
resourcesMap[key] = result
} else {
r.Resources = append(r.Resources, result.Resources...)
resourcesMap[key] = r
}
}
for k, v := range resourcesMap {
names := strings.Split(k, "/")
if len(names) != 2 {
continue
}
r := &policyreportv1alpha1.PolicyReportResult{
Policy: names[0],
Rule: names[1],
Resources: v.Resources,
Status: policyreportv1alpha1.PolicyStatus("Pass"),
Scored: true,
}
resultsNew[scope] = append(resultsNew[scope], r)
}
}
return resultsNew
}
func calculateSummary(results []*policyreportv1alpha1.PolicyReportResult) (summary policyreportv1alpha1.PolicyReportSummary) {
for _, res := range results {
switch string(res.Status) {
case "Pass":
summary.Pass++
case "Fail":
summary.Fail++
case "Warn":
summary.Warn++
case "Error":
summary.Error++
case "Skip":
summary.Skip++
}
}
return
}

166
pkg/kyverno/common/fetch.go Normal file
View file

@ -0,0 +1,166 @@
package common
import (
"encoding/json"
"errors"
"io/ioutil"
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
client "github.com/kyverno/kyverno/pkg/dclient"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/utils"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GetResources gets matched resources by the given policies
// the resources are fetched from
// - local paths to resources, if given
// - the k8s cluster, if given
func GetResources(policies []*v1.ClusterPolicy, resourcePaths []string, dClient *client.Client) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
var err error
if dClient != nil {
var resourceTypesMap = make(map[string]bool)
var resourceTypes []string
for _, policy := range policies {
for _, rule := range policy.Spec.Rules {
for _, kind := range rule.MatchResources.Kinds {
resourceTypesMap[kind] = true
}
}
}
for kind := range resourceTypesMap {
resourceTypes = append(resourceTypes, kind)
}
resources, err = getResourcesOfTypeFromCluster(resourceTypes, dClient)
if err != nil {
return nil, err
}
}
for _, resourcePath := range resourcePaths {
resourceBytes, err := getFileBytes(resourcePath)
if err != nil {
return nil, err
}
getResources, err := GetResource(resourceBytes)
if err != nil {
return nil, err
}
for _, resource := range getResources {
resources = append(resources, resource)
}
}
return resources, nil
}
// GetResource converts raw bytes to unstructured object
func GetResource(resourceBytes []byte) ([]*unstructured.Unstructured, error) {
resources := make([]*unstructured.Unstructured, 0)
var getErrString string
files, splitDocError := utils.SplitYAMLDocuments(resourceBytes)
if splitDocError != nil {
return nil, splitDocError
}
for _, resourceYaml := range files {
resource, err := convertResourceToUnstructured(resourceYaml)
if err != nil {
getErrString = getErrString + err.Error() + "\n"
}
resources = append(resources, resource)
}
if getErrString != "" {
return nil, errors.New(getErrString)
}
return resources, nil
}
// shuting?
// // GetPoliciesFromCluster fetches the policies from the cluster
// func GetPoliciesFromCluster(pNames []string, dClient *client.Client) ([]*v1.ClusterPolicy, error) {
// resourceTyeps := []string{"ClusterPolicy", "Policy"}
// policies, err := getResourcesOfTypeFromCluster(resourceTyeps, dClient)
// if err != nil {
// return nil, err
// }
// // if its a namespace policy, fill in namespaces in match / exclude? when converting to cluster policy
// var cpols []*v1.ClusterPolicy
// for _, p := range policies {
// cpols = append(cpols, policy.ConvertPolicyToClusterPolicy(p))
// }
// }
func getResourcesOfTypeFromCluster(resourceTypes []string, dClient *client.Client) ([]*unstructured.Unstructured, error) {
var resources []*unstructured.Unstructured
for _, kind := range resourceTypes {
resourceList, err := dClient.ListResource("", kind, "", nil)
if err != nil {
return nil, err
}
version := resourceList.GetAPIVersion()
for _, resource := range resourceList.Items {
resource.SetGroupVersionKind(schema.GroupVersionKind{
Group: "",
Version: version,
Kind: kind,
})
resources = append(resources, resource.DeepCopy())
}
}
return resources, nil
}
func getFileBytes(path string) ([]byte, error) {
file, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return file, err
}
func convertResourceToUnstructured(resourceYaml []byte) (*unstructured.Unstructured, error) {
decode := scheme.Codecs.UniversalDeserializer().Decode
resourceObject, metaData, err := decode(resourceYaml, nil, nil)
if err != nil {
return nil, err
}
resourceUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&resourceObject)
if err != nil {
return nil, err
}
resourceJSON, err := json.Marshal(resourceUnstructured)
if err != nil {
return nil, err
}
resource, err := engineutils.ConvertToUnstructured(resourceJSON)
if err != nil {
return nil, err
}
resource.SetGroupVersionKind(*metaData)
if resource.GetNamespace() == "" {
resource.SetNamespace("default")
}
return resource, nil
}

View file

@ -19,8 +19,8 @@ import (
"github.com/kyverno/kyverno/pkg/constant"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/jobs"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/policyreport/jobs"
"github.com/kyverno/kyverno/pkg/policyviolation"
"github.com/kyverno/kyverno/pkg/resourcecache"
"github.com/kyverno/kyverno/pkg/webhookconfig"

View file

@ -15,7 +15,7 @@ import (
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/constant"
dclient "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/jobs"
"github.com/kyverno/kyverno/pkg/policyreport/jobs"
"github.com/kyverno/kyverno/pkg/policystatus"
v1 "k8s.io/api/core/v1"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

View file

@ -2,9 +2,11 @@ package policyviolation
import (
"fmt"
"os"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/engine/response"
)
@ -16,10 +18,14 @@ func GeneratePVsFromEngineResponse(ers []response.EngineResponse, log logr.Logge
log.V(4).Info("resource does no have a name assigned yet, not creating a policy violation", "resource", er.PolicyResponse.Resource)
continue
}
// skip when response succeed
if er.IsSuccessful() {
continue
if os.Getenv("POLICY-TYPE") != common.PolicyReport {
if er.IsSuccessful() {
continue
}
}
// build policy violation info
pvInfos = append(pvInfos, buildPVInfo(er))
}

View file

@ -18,8 +18,8 @@ import (
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/constant"
dclient "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/jobs"
"github.com/kyverno/kyverno/pkg/policyreport"
"github.com/kyverno/kyverno/pkg/policyreport/jobs"
"github.com/kyverno/kyverno/pkg/policystatus"
unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"