mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
feat: implement background scan (#12101)
* feat: implement background scan Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * scanner Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor request Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> --------- Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
208314b04a
commit
02fceb64f7
15 changed files with 351 additions and 136 deletions
|
@ -36,6 +36,7 @@ import (
|
||||||
gitutils "github.com/kyverno/kyverno/pkg/utils/git"
|
gitutils "github.com/kyverno/kyverno/pkg/utils/git"
|
||||||
policyvalidation "github.com/kyverno/kyverno/pkg/validation/policy"
|
policyvalidation "github.com/kyverno/kyverno/pkg/validation/policy"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
@ -339,10 +340,21 @@ func (c *ApplyCommandConfig) applyValidatingPolicies(
|
||||||
}
|
}
|
||||||
responses := make([]engineapi.EngineResponse, 0)
|
responses := make([]engineapi.EngineResponse, 0)
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
request := engine.EngineRequest{
|
request := engine.Request(
|
||||||
Context: contextProvider,
|
contextProvider,
|
||||||
Resource: resource,
|
resource.GroupVersionKind(),
|
||||||
}
|
// TODO
|
||||||
|
schema.GroupVersionResource{},
|
||||||
|
// TODO
|
||||||
|
"",
|
||||||
|
resource.GetName(),
|
||||||
|
resource.GetNamespace(),
|
||||||
|
admissionv1.Create,
|
||||||
|
resource,
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
response, err := eng.Handle(ctx, request)
|
response, err := eng.Handle(ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.ContinueOnFail {
|
if c.ContinueOnFail {
|
||||||
|
|
|
@ -254,7 +254,7 @@ func getKindsFromValidatingAdmissionPolicy(policy admissionregistrationv1.Valida
|
||||||
resourceTypesMap := make(map[schema.GroupVersionKind]bool)
|
resourceTypesMap := make(map[schema.GroupVersionKind]bool)
|
||||||
subresourceMap := make(map[schema.GroupVersionKind]v1alpha1.Subresource)
|
subresourceMap := make(map[schema.GroupVersionKind]v1alpha1.Subresource)
|
||||||
|
|
||||||
kinds := admissionpolicy.GetKinds(policy)
|
kinds := admissionpolicy.GetKinds(policy.Spec.MatchConstraints)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
addGVKToResourceTypesMap(kind, resourceTypesMap, subresourceMap, client)
|
addGVKToResourceTypesMap(kind, resourceTypesMap, subresourceMap, client)
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ func createReportControllers(
|
||||||
client,
|
client,
|
||||||
kyvernoV1.Policies(),
|
kyvernoV1.Policies(),
|
||||||
kyvernoV1.ClusterPolicies(),
|
kyvernoV1.ClusterPolicies(),
|
||||||
|
kyvernoV2alpha1.ValidatingPolicies(),
|
||||||
vapInformer,
|
vapInformer,
|
||||||
)
|
)
|
||||||
warmups = append(warmups, func(ctx context.Context) error {
|
warmups = append(warmups, func(ctx context.Context) error {
|
||||||
|
@ -101,8 +102,8 @@ func createReportControllers(
|
||||||
metadataFactory,
|
metadataFactory,
|
||||||
kyvernoV1.Policies(),
|
kyvernoV1.Policies(),
|
||||||
kyvernoV1.ClusterPolicies(),
|
kyvernoV1.ClusterPolicies(),
|
||||||
vapInformer,
|
|
||||||
kyvernoV2alpha1.ValidatingPolicies(),
|
kyvernoV2alpha1.ValidatingPolicies(),
|
||||||
|
vapInformer,
|
||||||
),
|
),
|
||||||
aggregationWorkers,
|
aggregationWorkers,
|
||||||
))
|
))
|
||||||
|
@ -115,6 +116,7 @@ func createReportControllers(
|
||||||
metadataFactory,
|
metadataFactory,
|
||||||
kyvernoV1.Policies(),
|
kyvernoV1.Policies(),
|
||||||
kyvernoV1.ClusterPolicies(),
|
kyvernoV1.ClusterPolicies(),
|
||||||
|
kyvernoV2alpha1.ValidatingPolicies(),
|
||||||
kyvernoV2.PolicyExceptions(),
|
kyvernoV2.PolicyExceptions(),
|
||||||
vapInformer,
|
vapInformer,
|
||||||
vapBindingInformer,
|
vapBindingInformer,
|
||||||
|
@ -131,8 +133,8 @@ func createReportControllers(
|
||||||
ctrls = append(ctrls, internal.NewController(
|
ctrls = append(ctrls, internal.NewController(
|
||||||
backgroundscancontroller.ControllerName,
|
backgroundscancontroller.ControllerName,
|
||||||
backgroundScanController,
|
backgroundScanController,
|
||||||
backgroundScanWorkers),
|
backgroundScanWorkers,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ctrls, func(ctx context.Context) error {
|
return ctrls, func(ctx context.Context) error {
|
||||||
|
|
|
@ -27,10 +27,8 @@ import (
|
||||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetKinds(policy admissionregistrationv1.ValidatingAdmissionPolicy) []string {
|
func GetKinds(matchResources *admissionregistrationv1.MatchResources) []string {
|
||||||
var kindList []string
|
var kindList []string
|
||||||
|
|
||||||
matchResources := policy.Spec.MatchConstraints
|
|
||||||
for _, rule := range matchResources.ResourceRules {
|
for _, rule := range matchResources.ResourceRules {
|
||||||
group := rule.APIGroups[0]
|
group := rule.APIGroups[0]
|
||||||
version := rule.APIVersions[0]
|
version := rule.APIVersions[0]
|
||||||
|
|
|
@ -128,7 +128,7 @@ spec:
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
_, policy, _, _, _ := yamlutils.GetPolicy(tt.policy)
|
_, policy, _, _, _ := yamlutils.GetPolicy(tt.policy)
|
||||||
kinds := GetKinds(policy[0])
|
kinds := GetKinds(policy[0].Spec.MatchConstraints)
|
||||||
if !reflect.DeepEqual(kinds, tt.wantKinds) {
|
if !reflect.DeepEqual(kinds, tt.wantKinds) {
|
||||||
t.Errorf("Expected %v, got %v", tt.wantKinds, kinds)
|
t.Errorf("Expected %v, got %v", tt.wantKinds, kinds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,62 @@ import (
|
||||||
admissionv1 "k8s.io/api/admission/v1"
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/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"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/admission"
|
"k8s.io/apiserver/pkg/admission"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EngineRequest struct {
|
type EngineRequest struct {
|
||||||
Request *admissionv1.AdmissionRequest
|
request admissionv1.AdmissionRequest
|
||||||
Resource *unstructured.Unstructured
|
context contextlib.ContextInterface
|
||||||
Context contextlib.ContextInterface
|
}
|
||||||
|
|
||||||
|
func RequestFromAdmission(context contextlib.ContextInterface, request admissionv1.AdmissionRequest) EngineRequest {
|
||||||
|
return EngineRequest{
|
||||||
|
request: request,
|
||||||
|
context: context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Request(
|
||||||
|
context contextlib.ContextInterface,
|
||||||
|
gvk schema.GroupVersionKind,
|
||||||
|
gvr schema.GroupVersionResource,
|
||||||
|
subResource string,
|
||||||
|
name string,
|
||||||
|
namespace string,
|
||||||
|
operation admissionv1.Operation,
|
||||||
|
// userInfo authenticationv1.UserInfo,
|
||||||
|
object runtime.Object,
|
||||||
|
oldObject runtime.Object,
|
||||||
|
dryRun bool,
|
||||||
|
options runtime.Object,
|
||||||
|
) EngineRequest {
|
||||||
|
request := admissionv1.AdmissionRequest{
|
||||||
|
Kind: metav1.GroupVersionKind(gvk),
|
||||||
|
Resource: metav1.GroupVersionResource(gvr),
|
||||||
|
SubResource: subResource,
|
||||||
|
RequestKind: ptr.To(metav1.GroupVersionKind(gvk)),
|
||||||
|
RequestResource: ptr.To(metav1.GroupVersionResource(gvr)),
|
||||||
|
RequestSubResource: subResource,
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
Operation: operation,
|
||||||
|
// UserInfo: userInfo,
|
||||||
|
Object: runtime.RawExtension{Object: object},
|
||||||
|
OldObject: runtime.RawExtension{Object: oldObject},
|
||||||
|
DryRun: &dryRun,
|
||||||
|
Options: runtime.RawExtension{Object: options},
|
||||||
|
}
|
||||||
|
return RequestFromAdmission(context, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EngineRequest) AdmissionRequest() admissionv1.AdmissionRequest {
|
||||||
|
return r.request
|
||||||
}
|
}
|
||||||
|
|
||||||
type EngineResponse struct {
|
type EngineResponse struct {
|
||||||
|
@ -59,62 +104,49 @@ func NewEngine(provider Provider, nsResolver NamespaceResolver, matcher matching
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) Handle(ctx context.Context, request EngineRequest) (EngineResponse, error) {
|
func (e *engine) Handle(ctx context.Context, request EngineRequest) (EngineResponse, error) {
|
||||||
response := EngineResponse{
|
var response EngineResponse
|
||||||
Resource: request.Resource,
|
// fetch compiled policies
|
||||||
}
|
|
||||||
policies, err := e.provider.CompiledPolicies(ctx)
|
policies, err := e.provider.CompiledPolicies(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
// load objects
|
||||||
|
object, oldObject, err := admissionutils.ExtractResources(nil, request.request)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
response.Resource = &object
|
||||||
|
if response.Resource.Object == nil {
|
||||||
|
response.Resource = &oldObject
|
||||||
|
}
|
||||||
|
// default dry run
|
||||||
|
dryRun := false
|
||||||
|
if request.request.DryRun != nil {
|
||||||
|
dryRun = *request.request.DryRun
|
||||||
|
}
|
||||||
|
// create admission attributes
|
||||||
|
attr := admission.NewAttributesRecord(
|
||||||
|
&object,
|
||||||
|
&oldObject,
|
||||||
|
schema.GroupVersionKind(request.request.Kind),
|
||||||
|
request.request.Namespace,
|
||||||
|
request.request.Name,
|
||||||
|
schema.GroupVersionResource(request.request.Resource),
|
||||||
|
request.request.SubResource,
|
||||||
|
admission.Operation(request.request.Operation),
|
||||||
|
nil,
|
||||||
|
dryRun,
|
||||||
|
// TODO
|
||||||
|
nil,
|
||||||
|
)
|
||||||
// resolve namespace
|
// resolve namespace
|
||||||
var namespace runtime.Object
|
var namespace runtime.Object
|
||||||
var attr admission.Attributes
|
if ns := request.request.Namespace; ns != "" {
|
||||||
if request.Request != nil {
|
namespace = e.nsResolver(ns)
|
||||||
object, oldObject, err := admissionutils.ExtractResources(nil, *request.Request)
|
|
||||||
if err != nil {
|
|
||||||
return response, err
|
|
||||||
}
|
|
||||||
dryRun := false
|
|
||||||
if request.Request.DryRun != nil {
|
|
||||||
dryRun = *request.Request.DryRun
|
|
||||||
}
|
|
||||||
attr = admission.NewAttributesRecord(
|
|
||||||
&object,
|
|
||||||
&oldObject,
|
|
||||||
schema.GroupVersionKind(request.Request.Kind),
|
|
||||||
request.Request.Namespace,
|
|
||||||
request.Request.Name,
|
|
||||||
schema.GroupVersionResource(request.Request.Resource),
|
|
||||||
request.Request.SubResource,
|
|
||||||
admission.Operation(request.Request.Operation),
|
|
||||||
nil,
|
|
||||||
dryRun,
|
|
||||||
// TODO
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
if ns := request.Request.Namespace; ns != "" {
|
|
||||||
namespace = e.nsResolver(ns)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
attr = admission.NewAttributesRecord(
|
|
||||||
request.Resource,
|
|
||||||
nil,
|
|
||||||
request.Resource.GroupVersionKind(),
|
|
||||||
request.Resource.GetNamespace(),
|
|
||||||
request.Resource.GetName(),
|
|
||||||
schema.GroupVersionResource{},
|
|
||||||
"",
|
|
||||||
admission.Create,
|
|
||||||
nil,
|
|
||||||
false,
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
if ns := request.Resource.GetNamespace(); ns != "" {
|
|
||||||
namespace = e.nsResolver(ns)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// evaluate policies
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
response.Policies = append(response.Policies, e.handlePolicy(ctx, policy, attr, request.Request, namespace, request.Context))
|
response.Policies = append(response.Policies, e.handlePolicy(ctx, policy, attr, &request.request, namespace, request.context))
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ type controller struct {
|
||||||
// listers
|
// listers
|
||||||
polLister kyvernov1listers.PolicyLister
|
polLister kyvernov1listers.PolicyLister
|
||||||
cpolLister kyvernov1listers.ClusterPolicyLister
|
cpolLister kyvernov1listers.ClusterPolicyLister
|
||||||
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
|
||||||
vpolLister kyvernov2alpha1listers.ValidatingPolicyLister
|
vpolLister kyvernov2alpha1listers.ValidatingPolicyLister
|
||||||
|
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
||||||
ephrLister cache.GenericLister
|
ephrLister cache.GenericLister
|
||||||
cephrLister cache.GenericLister
|
cephrLister cache.GenericLister
|
||||||
|
|
||||||
|
@ -73,8 +73,8 @@ func NewController(
|
||||||
metadataFactory metadatainformers.SharedInformerFactory,
|
metadataFactory metadatainformers.SharedInformerFactory,
|
||||||
polInformer kyvernov1informers.PolicyInformer,
|
polInformer kyvernov1informers.PolicyInformer,
|
||||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||||
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
|
||||||
vpolInformer kyvernov2alpha1informers.ValidatingPolicyInformer,
|
vpolInformer kyvernov2alpha1informers.ValidatingPolicyInformer,
|
||||||
|
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
||||||
) controllers.Controller {
|
) controllers.Controller {
|
||||||
ephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("ephemeralreports"))
|
ephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("ephemeralreports"))
|
||||||
cephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("clusterephemeralreports"))
|
cephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("clusterephemeralreports"))
|
||||||
|
@ -133,10 +133,10 @@ func NewController(
|
||||||
); err != nil {
|
); err != nil {
|
||||||
logger.Error(err, "failed to register event handlers")
|
logger.Error(err, "failed to register event handlers")
|
||||||
}
|
}
|
||||||
if vapInformer != nil {
|
if vpolInformer != nil {
|
||||||
c.vapLister = vapInformer.Lister()
|
c.vpolLister = vpolInformer.Lister()
|
||||||
if _, err := controllerutils.AddEventHandlersT(
|
if _, err := controllerutils.AddEventHandlersT(
|
||||||
vapInformer.Informer(),
|
vpolInformer.Informer(),
|
||||||
func(_ metav1.Object) { enqueueAll() },
|
func(_ metav1.Object) { enqueueAll() },
|
||||||
func(_, _ metav1.Object) { enqueueAll() },
|
func(_, _ metav1.Object) { enqueueAll() },
|
||||||
func(_ metav1.Object) { enqueueAll() },
|
func(_ metav1.Object) { enqueueAll() },
|
||||||
|
@ -144,10 +144,10 @@ func NewController(
|
||||||
logger.Error(err, "failed to register event handlers")
|
logger.Error(err, "failed to register event handlers")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if vpolInformer != nil {
|
if vapInformer != nil {
|
||||||
c.vpolLister = vpolInformer.Lister()
|
c.vapLister = vapInformer.Lister()
|
||||||
if _, err := controllerutils.AddEventHandlersT(
|
if _, err := controllerutils.AddEventHandlersT(
|
||||||
vpolInformer.Informer(),
|
vapInformer.Informer(),
|
||||||
func(_ metav1.Object) { enqueueAll() },
|
func(_ metav1.Object) { enqueueAll() },
|
||||||
func(_, _ metav1.Object) { enqueueAll() },
|
func(_, _ metav1.Object) { enqueueAll() },
|
||||||
func(_ metav1.Object) { enqueueAll() },
|
func(_ metav1.Object) { enqueueAll() },
|
||||||
|
|
|
@ -8,14 +8,17 @@ import (
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
||||||
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
|
||||||
reportsv1 "github.com/kyverno/kyverno/api/reports/v1"
|
reportsv1 "github.com/kyverno/kyverno/api/reports/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/breaker"
|
"github.com/kyverno/kyverno/pkg/breaker"
|
||||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||||
kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||||
kyvernov2informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2"
|
kyvernov2informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2"
|
||||||
|
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
|
||||||
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||||
kyvernov2listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2"
|
kyvernov2listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2"
|
||||||
|
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/controllers"
|
"github.com/kyverno/kyverno/pkg/controllers"
|
||||||
|
@ -60,6 +63,7 @@ type controller struct {
|
||||||
// listers
|
// listers
|
||||||
polLister kyvernov1listers.PolicyLister
|
polLister kyvernov1listers.PolicyLister
|
||||||
cpolLister kyvernov1listers.ClusterPolicyLister
|
cpolLister kyvernov1listers.ClusterPolicyLister
|
||||||
|
vpolLister kyvernov2alpha1listers.ValidatingPolicyLister
|
||||||
polexLister kyvernov2listers.PolicyExceptionLister
|
polexLister kyvernov2listers.PolicyExceptionLister
|
||||||
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
||||||
vapBindingLister admissionregistrationv1listers.ValidatingAdmissionPolicyBindingLister
|
vapBindingLister admissionregistrationv1listers.ValidatingAdmissionPolicyBindingLister
|
||||||
|
@ -68,7 +72,7 @@ type controller struct {
|
||||||
nsLister corev1listers.NamespaceLister
|
nsLister corev1listers.NamespaceLister
|
||||||
|
|
||||||
// queue
|
// queue
|
||||||
queue workqueue.TypedRateLimitingInterface[any]
|
queue workqueue.TypedRateLimitingInterface[string]
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
metadataCache resource.MetadataCache
|
metadataCache resource.MetadataCache
|
||||||
|
@ -90,6 +94,7 @@ func NewController(
|
||||||
metadataFactory metadatainformers.SharedInformerFactory,
|
metadataFactory metadatainformers.SharedInformerFactory,
|
||||||
polInformer kyvernov1informers.PolicyInformer,
|
polInformer kyvernov1informers.PolicyInformer,
|
||||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||||
|
vpolInformer kyvernov2alpha1informers.ValidatingPolicyInformer,
|
||||||
polexInformer kyvernov2informers.PolicyExceptionInformer,
|
polexInformer kyvernov2informers.PolicyExceptionInformer,
|
||||||
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
||||||
vapBindingInformer admissionregistrationv1informers.ValidatingAdmissionPolicyBindingInformer,
|
vapBindingInformer admissionregistrationv1informers.ValidatingAdmissionPolicyBindingInformer,
|
||||||
|
@ -106,8 +111,8 @@ func NewController(
|
||||||
ephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("ephemeralreports"))
|
ephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("ephemeralreports"))
|
||||||
cephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("clusterephemeralreports"))
|
cephrInformer := metadataFactory.ForResource(reportsv1.SchemeGroupVersion.WithResource("clusterephemeralreports"))
|
||||||
queue := workqueue.NewTypedRateLimitingQueueWithConfig(
|
queue := workqueue.NewTypedRateLimitingQueueWithConfig(
|
||||||
workqueue.DefaultTypedControllerRateLimiter[any](),
|
workqueue.DefaultTypedControllerRateLimiter[string](),
|
||||||
workqueue.TypedRateLimitingQueueConfig[any]{Name: ControllerName},
|
workqueue.TypedRateLimitingQueueConfig[string]{Name: ControllerName},
|
||||||
)
|
)
|
||||||
c := controller{
|
c := controller{
|
||||||
client: client,
|
client: client,
|
||||||
|
@ -129,6 +134,12 @@ func NewController(
|
||||||
reportsConfig: reportsConfig,
|
reportsConfig: reportsConfig,
|
||||||
breaker: breaker,
|
breaker: breaker,
|
||||||
}
|
}
|
||||||
|
if vpolInformer != nil {
|
||||||
|
c.vpolLister = vpolInformer.Lister()
|
||||||
|
if _, err := controllerutils.AddEventHandlersT(vpolInformer.Informer(), c.addVP, c.updateVP, c.deleteVP); err != nil {
|
||||||
|
logger.Error(err, "failed to register event handlers")
|
||||||
|
}
|
||||||
|
}
|
||||||
if vapInformer != nil {
|
if vapInformer != nil {
|
||||||
c.vapLister = vapInformer.Lister()
|
c.vapLister = vapInformer.Lister()
|
||||||
if _, err := controllerutils.AddEventHandlersT(vapInformer.Informer(), c.addVAP, c.updateVAP, c.deleteVAP); err != nil {
|
if _, err := controllerutils.AddEventHandlersT(vapInformer.Informer(), c.addVAP, c.updateVAP, c.deleteVAP); err != nil {
|
||||||
|
@ -197,6 +208,20 @@ func (c *controller) deleteException(obj *kyvernov2.PolicyException) {
|
||||||
c.enqueueResources()
|
c.enqueueResources()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *controller) addVP(obj *kyvernov2alpha1.ValidatingPolicy) {
|
||||||
|
c.enqueueResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) updateVP(old, obj *kyvernov2alpha1.ValidatingPolicy) {
|
||||||
|
if old.GetResourceVersion() != obj.GetResourceVersion() {
|
||||||
|
c.enqueueResources()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) deleteVP(obj *kyvernov2alpha1.ValidatingPolicy) {
|
||||||
|
c.enqueueResources()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controller) addVAP(obj *admissionregistrationv1.ValidatingAdmissionPolicy) {
|
func (c *controller) addVAP(obj *admissionregistrationv1.ValidatingAdmissionPolicy) {
|
||||||
c.enqueueResources()
|
c.enqueueResources()
|
||||||
}
|
}
|
||||||
|
@ -313,6 +338,7 @@ func (c *controller) reconcileReport(
|
||||||
full bool,
|
full bool,
|
||||||
uid types.UID,
|
uid types.UID,
|
||||||
gvk schema.GroupVersionKind,
|
gvk schema.GroupVersionKind,
|
||||||
|
gvr schema.GroupVersionResource,
|
||||||
resource resource.Resource,
|
resource resource.Resource,
|
||||||
exceptions []kyvernov2.PolicyException,
|
exceptions []kyvernov2.PolicyException,
|
||||||
bindings []admissionregistrationv1.ValidatingAdmissionPolicyBinding,
|
bindings []admissionregistrationv1.ValidatingAdmissionPolicyBinding,
|
||||||
|
@ -362,29 +388,21 @@ func (c *controller) reconcileReport(
|
||||||
policyNameToLabel := map[string]string{}
|
policyNameToLabel := map[string]string{}
|
||||||
for _, policy := range policies {
|
for _, policy := range policies {
|
||||||
var key string
|
var key string
|
||||||
var err error
|
|
||||||
if policy.AsKyvernoPolicy() != nil {
|
if policy.AsKyvernoPolicy() != nil {
|
||||||
key, err = cache.MetaNamespaceKeyFunc(policy.AsKyvernoPolicy())
|
key = cache.MetaObjectToName(policy.AsKyvernoPolicy()).String()
|
||||||
} else if policy.AsValidatingAdmissionPolicy() != nil {
|
} else if policy.AsValidatingAdmissionPolicy() != nil {
|
||||||
key, err = cache.MetaNamespaceKeyFunc(policy.AsValidatingAdmissionPolicy())
|
key = cache.MetaObjectToName(policy.AsValidatingAdmissionPolicy()).String()
|
||||||
}
|
} else if policy.AsValidatingPolicy() != nil {
|
||||||
if err != nil {
|
key = cache.MetaObjectToName(policy.AsValidatingPolicy()).String()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
policyNameToLabel[key] = reportutils.PolicyLabel(policy)
|
policyNameToLabel[key] = reportutils.PolicyLabel(policy)
|
||||||
}
|
}
|
||||||
for i, exception := range exceptions {
|
for i, exception := range exceptions {
|
||||||
key, err := cache.MetaNamespaceKeyFunc(&exceptions[i])
|
key := cache.MetaObjectToName(&exceptions[i]).String()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
policyNameToLabel[key] = reportutils.PolicyExceptionLabel(exception)
|
policyNameToLabel[key] = reportutils.PolicyExceptionLabel(exception)
|
||||||
}
|
}
|
||||||
for _, binding := range bindings {
|
for _, binding := range bindings {
|
||||||
key, err := cache.MetaNamespaceKeyFunc(binding)
|
key := cache.MetaObjectToName(&binding).String()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
policyNameToLabel[key] = reportutils.ValidatingAdmissionPolicyBindingLabel(binding)
|
policyNameToLabel[key] = reportutils.ValidatingAdmissionPolicyBindingLabel(binding)
|
||||||
}
|
}
|
||||||
for _, result := range observed.GetResults() {
|
for _, result := range observed.GetResults() {
|
||||||
|
@ -401,7 +419,6 @@ func (c *controller) reconcileReport(
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label := policyNameToLabel[result.Policy]
|
label := policyNameToLabel[result.Policy]
|
||||||
vapBindingLabel := policyNameToLabel[result.Properties["binding"]]
|
vapBindingLabel := policyNameToLabel[result.Properties["binding"]]
|
||||||
if (label != "" && expected[label] == actual[label]) ||
|
if (label != "" && expected[label] == actual[label]) ||
|
||||||
|
@ -430,7 +447,7 @@ func (c *controller) reconcileReport(
|
||||||
}
|
}
|
||||||
if full || reevaluate || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() {
|
if full || reevaluate || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() {
|
||||||
scanner := utils.NewScanner(logger, c.engine, c.config, c.jp, c.client, c.reportsConfig)
|
scanner := utils.NewScanner(logger, c.engine, c.config, c.jp, c.client, c.reportsConfig)
|
||||||
for _, result := range scanner.ScanResource(ctx, *target, ns, bindings, policy) {
|
for _, result := range scanner.ScanResource(ctx, *target, gvr, "", ns, bindings, policy) {
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return result.Error
|
return result.Error
|
||||||
} else if result.EngineResponse != nil {
|
} else if result.EngineResponse != nil {
|
||||||
|
@ -499,7 +516,7 @@ func (c *controller) storeReport(ctx context.Context, observed, desired reportsv
|
||||||
func (c *controller) reconcile(ctx context.Context, log logr.Logger, key, namespace, name string) error {
|
func (c *controller) reconcile(ctx context.Context, log logr.Logger, key, namespace, name string) error {
|
||||||
// try to find resource from the cache
|
// try to find resource from the cache
|
||||||
uid := types.UID(name)
|
uid := types.UID(name)
|
||||||
resource, gvk, exists := c.metadataCache.GetResourceHash(uid)
|
resource, gvk, gvr, exists := c.metadataCache.GetResourceHash(uid)
|
||||||
// if the resource is not present it means we shouldn't have a report for it
|
// if the resource is not present it means we shouldn't have a report for it
|
||||||
// we can delete the report, we will recreate one if the resource comes back
|
// we can delete the report, we will recreate one if the resource comes back
|
||||||
if !exists {
|
if !exists {
|
||||||
|
@ -535,6 +552,16 @@ func (c *controller) reconcile(ctx context.Context, log logr.Logger, key, namesp
|
||||||
for _, pol := range kyvernoPolicies {
|
for _, pol := range kyvernoPolicies {
|
||||||
policies = append(policies, engineapi.NewKyvernoPolicy(pol))
|
policies = append(policies, engineapi.NewKyvernoPolicy(pol))
|
||||||
}
|
}
|
||||||
|
if c.vpolLister != nil {
|
||||||
|
// load validating policies
|
||||||
|
vpols, err := utils.FetchValidatingPolicies(c.vpolLister)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, vpol := range vpols {
|
||||||
|
policies = append(policies, engineapi.NewValidatingPolicy(&vpol))
|
||||||
|
}
|
||||||
|
}
|
||||||
if c.vapLister != nil {
|
if c.vapLister != nil {
|
||||||
// load validating admission policies
|
// load validating admission policies
|
||||||
vapPolicies, err := utils.FetchValidatingAdmissionPolicies(c.vapLister)
|
vapPolicies, err := utils.FetchValidatingAdmissionPolicies(c.vapLister)
|
||||||
|
@ -566,7 +593,7 @@ func (c *controller) reconcile(ctx context.Context, log logr.Logger, key, namesp
|
||||||
c.queue.AddAfter(key, c.forceDelay)
|
c.queue.AddAfter(key, c.forceDelay)
|
||||||
}()
|
}()
|
||||||
if needsReconcile {
|
if needsReconcile {
|
||||||
return c.reconcileReport(ctx, namespace, name, full, uid, gvk, resource, exceptions, vapBindings, policies...)
|
return c.reconcileReport(ctx, namespace, name, full, uid, gvk, gvr, resource, exceptions, vapBindings, policies...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -10,7 +10,9 @@ import (
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"github.com/kyverno/kyverno/pkg/admissionpolicy"
|
"github.com/kyverno/kyverno/pkg/admissionpolicy"
|
||||||
kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
||||||
|
kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1"
|
||||||
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||||
|
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/controllers"
|
"github.com/kyverno/kyverno/pkg/controllers"
|
||||||
"github.com/kyverno/kyverno/pkg/controllers/report/utils"
|
"github.com/kyverno/kyverno/pkg/controllers/report/utils"
|
||||||
|
@ -55,7 +57,7 @@ const (
|
||||||
type EventHandler func(EventType, types.UID, schema.GroupVersionKind, Resource)
|
type EventHandler func(EventType, types.UID, schema.GroupVersionKind, Resource)
|
||||||
|
|
||||||
type MetadataCache interface {
|
type MetadataCache interface {
|
||||||
GetResourceHash(uid types.UID) (Resource, schema.GroupVersionKind, bool)
|
GetResourceHash(uid types.UID) (Resource, schema.GroupVersionKind, schema.GroupVersionResource, bool)
|
||||||
GetAllResourceKeys() []string
|
GetAllResourceKeys() []string
|
||||||
AddEventHandler(EventHandler)
|
AddEventHandler(EventHandler)
|
||||||
Warmup(ctx context.Context) error
|
Warmup(ctx context.Context) error
|
||||||
|
@ -79,6 +81,7 @@ type controller struct {
|
||||||
// listers
|
// listers
|
||||||
polLister kyvernov1listers.PolicyLister
|
polLister kyvernov1listers.PolicyLister
|
||||||
cpolLister kyvernov1listers.ClusterPolicyLister
|
cpolLister kyvernov1listers.ClusterPolicyLister
|
||||||
|
vpolLister kyvernov2alpha1listers.ValidatingPolicyLister
|
||||||
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
vapLister admissionregistrationv1listers.ValidatingAdmissionPolicyLister
|
||||||
|
|
||||||
// queue
|
// queue
|
||||||
|
@ -93,6 +96,7 @@ func NewController(
|
||||||
client dclient.Interface,
|
client dclient.Interface,
|
||||||
polInformer kyvernov1informers.PolicyInformer,
|
polInformer kyvernov1informers.PolicyInformer,
|
||||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||||
|
vpolInformer kyvernov2alpha1informers.ValidatingPolicyInformer,
|
||||||
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
vapInformer admissionregistrationv1informers.ValidatingAdmissionPolicyInformer,
|
||||||
) Controller {
|
) Controller {
|
||||||
c := controller{
|
c := controller{
|
||||||
|
@ -105,6 +109,12 @@ func NewController(
|
||||||
),
|
),
|
||||||
dynamicWatchers: map[schema.GroupVersionResource]*watcher{},
|
dynamicWatchers: map[schema.GroupVersionResource]*watcher{},
|
||||||
}
|
}
|
||||||
|
if vpolInformer != nil {
|
||||||
|
c.vpolLister = vpolInformer.Lister()
|
||||||
|
if _, _, err := controllerutils.AddDefaultEventHandlers(logger, vpolInformer.Informer(), c.queue); err != nil {
|
||||||
|
logger.Error(err, "failed to register event handlers")
|
||||||
|
}
|
||||||
|
}
|
||||||
if vapInformer != nil {
|
if vapInformer != nil {
|
||||||
c.vapLister = vapInformer.Lister()
|
c.vapLister = vapInformer.Lister()
|
||||||
if _, _, err := controllerutils.AddDefaultEventHandlers(logger, vapInformer.Informer(), c.queue); err != nil {
|
if _, _, err := controllerutils.AddDefaultEventHandlers(logger, vapInformer.Informer(), c.queue); err != nil {
|
||||||
|
@ -129,15 +139,15 @@ func (c *controller) Run(ctx context.Context, workers int) {
|
||||||
c.stopDynamicWatchers()
|
c.stopDynamicWatchers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) GetResourceHash(uid types.UID) (Resource, schema.GroupVersionKind, bool) {
|
func (c *controller) GetResourceHash(uid types.UID) (Resource, schema.GroupVersionKind, schema.GroupVersionResource, bool) {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
for _, watcher := range c.dynamicWatchers {
|
for gvr, watcher := range c.dynamicWatchers {
|
||||||
if resource, exists := watcher.hashes[uid]; exists {
|
if resource, exists := watcher.hashes[uid]; exists {
|
||||||
return resource, watcher.gvk, true
|
return resource, watcher.gvk, gvr, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Resource{}, schema.GroupVersionKind{}, false
|
return Resource{}, schema.GroupVersionKind{}, schema.GroupVersionResource{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) GetAllResourceKeys() []string {
|
func (c *controller) GetAllResourceKeys() []string {
|
||||||
|
@ -249,7 +259,21 @@ func (c *controller) updateDynamicWatchers(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
// fetch kinds from validating admission policies
|
// fetch kinds from validating admission policies
|
||||||
for _, policy := range vapPolicies {
|
for _, policy := range vapPolicies {
|
||||||
kinds := admissionpolicy.GetKinds(policy)
|
kinds := admissionpolicy.GetKinds(policy.Spec.MatchConstraints)
|
||||||
|
for _, kind := range kinds {
|
||||||
|
group, version, kind, subresource := kubeutils.ParseKindSelector(kind)
|
||||||
|
c.addGVKToGVRMapping(group, version, kind, subresource, gvkToGvr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.vpolLister != nil {
|
||||||
|
vpols, err := utils.FetchValidatingPolicies(c.vpolLister)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// fetch kinds from validating admission policies
|
||||||
|
for _, policy := range vpols {
|
||||||
|
kinds := admissionpolicy.GetKinds(policy.Spec.MatchConstraints)
|
||||||
for _, kind := range kinds {
|
for _, kind := range kinds {
|
||||||
group, version, kind, subresource := kubeutils.ParseKindSelector(kind)
|
group, version, kind, subresource := kubeutils.ParseKindSelector(kind)
|
||||||
c.addGVKToGVRMapping(group, version, kind, subresource, gvkToGvr)
|
c.addGVKToGVRMapping(group, version, kind, subresource, gvkToGvr)
|
||||||
|
|
|
@ -7,6 +7,9 @@ import (
|
||||||
"github.com/kyverno/kyverno/api/kyverno"
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/admissionpolicy"
|
"github.com/kyverno/kyverno/pkg/admissionpolicy"
|
||||||
|
celengine "github.com/kyverno/kyverno/pkg/cel/engine"
|
||||||
|
"github.com/kyverno/kyverno/pkg/cel/matching"
|
||||||
|
celpolicy "github.com/kyverno/kyverno/pkg/cel/policy"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/engine"
|
"github.com/kyverno/kyverno/pkg/engine"
|
||||||
|
@ -14,9 +17,11 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
||||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
type scanner struct {
|
type scanner struct {
|
||||||
|
@ -34,7 +39,15 @@ type ScanResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Scanner interface {
|
type Scanner interface {
|
||||||
ScanResource(context.Context, unstructured.Unstructured, *corev1.Namespace, []admissionregistrationv1.ValidatingAdmissionPolicyBinding, ...engineapi.GenericPolicy) map[*engineapi.GenericPolicy]ScanResult
|
ScanResource(
|
||||||
|
context.Context,
|
||||||
|
unstructured.Unstructured,
|
||||||
|
schema.GroupVersionResource,
|
||||||
|
string,
|
||||||
|
*corev1.Namespace,
|
||||||
|
[]admissionregistrationv1.ValidatingAdmissionPolicyBinding,
|
||||||
|
...engineapi.GenericPolicy,
|
||||||
|
) map[*engineapi.GenericPolicy]ScanResult
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScanner(
|
func NewScanner(
|
||||||
|
@ -55,18 +68,38 @@ func NewScanner(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstructured, ns *corev1.Namespace, bindings []admissionregistrationv1.ValidatingAdmissionPolicyBinding, policies ...engineapi.GenericPolicy) map[*engineapi.GenericPolicy]ScanResult {
|
func (s *scanner) ScanResource(
|
||||||
results := map[*engineapi.GenericPolicy]ScanResult{}
|
ctx context.Context,
|
||||||
for i, policy := range policies {
|
resource unstructured.Unstructured,
|
||||||
var errors []error
|
gvr schema.GroupVersionResource,
|
||||||
logger := s.logger.WithValues("kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName())
|
subResource string,
|
||||||
var response *engineapi.EngineResponse
|
ns *corev1.Namespace,
|
||||||
|
bindings []admissionregistrationv1.ValidatingAdmissionPolicyBinding,
|
||||||
|
policies ...engineapi.GenericPolicy,
|
||||||
|
) map[*engineapi.GenericPolicy]ScanResult {
|
||||||
|
var kpols, vpols, vaps []engineapi.GenericPolicy
|
||||||
|
// split policies per nature
|
||||||
|
for _, policy := range policies {
|
||||||
if pol := policy.AsKyvernoPolicy(); pol != nil {
|
if pol := policy.AsKyvernoPolicy(); pol != nil {
|
||||||
|
kpols = append(kpols, policy)
|
||||||
|
} else if pol := policy.AsValidatingPolicy(); pol != nil {
|
||||||
|
vpols = append(vpols, policy)
|
||||||
|
} else if pol := policy.AsValidatingAdmissionPolicy(); pol != nil {
|
||||||
|
vaps = append(vaps, policy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger := s.logger.WithValues("kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName())
|
||||||
|
results := map[*engineapi.GenericPolicy]ScanResult{}
|
||||||
|
// evaluate kyverno policies
|
||||||
|
var nsLabels map[string]string
|
||||||
|
if ns != nil {
|
||||||
|
nsLabels = ns.Labels
|
||||||
|
}
|
||||||
|
for i, policy := range kpols {
|
||||||
|
if pol := policy.AsKyvernoPolicy(); pol != nil {
|
||||||
|
var errors []error
|
||||||
|
var response *engineapi.EngineResponse
|
||||||
var err error
|
var err error
|
||||||
var nsLabels map[string]string
|
|
||||||
if ns != nil {
|
|
||||||
nsLabels = ns.Labels
|
|
||||||
}
|
|
||||||
if s.reportingConfig.ValidateReportsEnabled() {
|
if s.reportingConfig.ValidateReportsEnabled() {
|
||||||
response, err = s.validateResource(ctx, resource, nsLabels, pol)
|
response, err = s.validateResource(ctx, resource, nsLabels, pol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,7 +119,6 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
|
||||||
}
|
}
|
||||||
response.PolicyResponse.Rules = ruleResponses
|
response.PolicyResponse.Rules = ruleResponses
|
||||||
}
|
}
|
||||||
|
|
||||||
ivResponse, err := s.validateImages(ctx, resource, nsLabels, pol)
|
ivResponse, err := s.validateImages(ctx, resource, nsLabels, pol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to scan images")
|
logger.Error(err, "failed to scan images")
|
||||||
|
@ -98,7 +130,66 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
|
||||||
response.PolicyResponse.Rules = append(response.PolicyResponse.Rules, ivResponse.PolicyResponse.Rules...)
|
response.PolicyResponse.Rules = append(response.PolicyResponse.Rules, ivResponse.PolicyResponse.Rules...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if pol := policy.AsValidatingAdmissionPolicy(); pol != nil {
|
results[&kpols[i]] = ScanResult{response, multierr.Combine(errors...)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// evaluate validating policies
|
||||||
|
for i, policy := range vpols {
|
||||||
|
if pol := policy.AsValidatingPolicy(); pol != nil {
|
||||||
|
// create compiler
|
||||||
|
compiler := celpolicy.NewCompiler()
|
||||||
|
// create provider
|
||||||
|
provider, err := celengine.NewProvider(compiler, *pol)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to create policy provider")
|
||||||
|
results[&vpols[i]] = ScanResult{nil, err}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// create engine
|
||||||
|
engine := celengine.NewEngine(
|
||||||
|
provider,
|
||||||
|
func(name string) *corev1.Namespace { return ns },
|
||||||
|
matching.NewMatcher(),
|
||||||
|
)
|
||||||
|
// create context provider
|
||||||
|
context, err := celpolicy.NewContextProvider(
|
||||||
|
s.client.GetKubeClient(),
|
||||||
|
nil,
|
||||||
|
// TODO
|
||||||
|
// []imagedataloader.Option{imagedataloader.WithLocalCredentials(c.RegistryAccess)},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "failed to create cel context provider")
|
||||||
|
results[&vpols[i]] = ScanResult{nil, err}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
request := celengine.Request(
|
||||||
|
context,
|
||||||
|
resource.GroupVersionKind(),
|
||||||
|
gvr,
|
||||||
|
subResource,
|
||||||
|
resource.GetName(),
|
||||||
|
resource.GetNamespace(),
|
||||||
|
admissionv1.Create,
|
||||||
|
&resource,
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
engineResponse, err := engine.Handle(ctx, request)
|
||||||
|
response := engineapi.EngineResponse{
|
||||||
|
Resource: resource,
|
||||||
|
PolicyResponse: engineapi.PolicyResponse{
|
||||||
|
// TODO: policies at index 0
|
||||||
|
Rules: engineResponse.Policies[0].Rules,
|
||||||
|
},
|
||||||
|
}.WithPolicy(vpols[i])
|
||||||
|
results[&vpols[i]] = ScanResult{&response, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// evaluate validating admission policies
|
||||||
|
for i, policy := range vaps {
|
||||||
|
if pol := policy.AsValidatingAdmissionPolicy(); pol != nil {
|
||||||
policyData := admissionpolicy.NewPolicyData(*pol)
|
policyData := admissionpolicy.NewPolicyData(*pol)
|
||||||
for _, binding := range bindings {
|
for _, binding := range bindings {
|
||||||
if binding.Spec.PolicyName == pol.Name {
|
if binding.Spec.PolicyName == pol.Name {
|
||||||
|
@ -106,12 +197,8 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res, err := admissionpolicy.Validate(policyData, resource, map[string]map[string]string{}, s.client)
|
res, err := admissionpolicy.Validate(policyData, resource, map[string]map[string]string{}, s.client)
|
||||||
if err != nil {
|
results[&vaps[i]] = ScanResult{&res, err}
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
|
||||||
response = &res
|
|
||||||
}
|
}
|
||||||
results[&policies[i]] = ScanResult{response, multierr.Combine(errors...)}
|
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,12 @@ import (
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
|
||||||
|
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
|
||||||
reportsv1 "github.com/kyverno/kyverno/api/reports/v1"
|
reportsv1 "github.com/kyverno/kyverno/api/reports/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/autogen"
|
"github.com/kyverno/kyverno/pkg/autogen"
|
||||||
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1"
|
||||||
kyvernov2listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2"
|
kyvernov2listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2"
|
||||||
|
kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1"
|
||||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||||
policyvalidation "github.com/kyverno/kyverno/pkg/validation/policy"
|
policyvalidation "github.com/kyverno/kyverno/pkg/validation/policy"
|
||||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||||
|
@ -148,3 +150,15 @@ func FetchValidatingAdmissionPolicyBindings(vapBindingLister admissionregistrati
|
||||||
}
|
}
|
||||||
return bindings, nil
|
return bindings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FetchValidatingPolicies(vpolLister kyvernov2alpha1listers.ValidatingPolicyLister) ([]kyvernov2alpha1.ValidatingPolicy, error) {
|
||||||
|
var policies []kyvernov2alpha1.ValidatingPolicy
|
||||||
|
if pols, err := vpolLister.List(labels.Everything()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
for _, pol := range pols {
|
||||||
|
policies = append(policies, *pol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return policies, nil
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||||
admissionv1 "k8s.io/api/admission/v1"
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +35,12 @@ func ExtractResources(newRaw []byte, request admissionv1.AdmissionRequest) (unst
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emptyResource, emptyResource, fmt.Errorf("failed to convert new raw to unstructured: %v", err)
|
return emptyResource, emptyResource, fmt.Errorf("failed to convert new raw to unstructured: %v", err)
|
||||||
}
|
}
|
||||||
|
} else if request.Object.Object != nil {
|
||||||
|
ret, err := runtime.DefaultUnstructuredConverter.ToUnstructured(request.Object.Object)
|
||||||
|
if err != nil {
|
||||||
|
return emptyResource, emptyResource, fmt.Errorf("failed to convert new raw to unstructured: %v", err)
|
||||||
|
}
|
||||||
|
newResource = unstructured.Unstructured{Object: ret}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old Resource
|
// Old Resource
|
||||||
|
@ -43,6 +50,12 @@ func ExtractResources(newRaw []byte, request admissionv1.AdmissionRequest) (unst
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return emptyResource, emptyResource, fmt.Errorf("failed to convert old raw to unstructured: %v", err)
|
return emptyResource, emptyResource, fmt.Errorf("failed to convert old raw to unstructured: %v", err)
|
||||||
}
|
}
|
||||||
|
} else if request.OldObject.Object != nil {
|
||||||
|
ret, err := runtime.DefaultUnstructuredConverter.ToUnstructured(request.OldObject.Object)
|
||||||
|
if err != nil {
|
||||||
|
return emptyResource, emptyResource, fmt.Errorf("failed to convert old raw to unstructured: %v", err)
|
||||||
|
}
|
||||||
|
oldResource = unstructured.Unstructured{Object: ret}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newResource, oldResource, err
|
return newResource, oldResource, err
|
||||||
|
|
|
@ -54,7 +54,7 @@ func newControllerMetrics(logger logr.Logger, controllerName string) *controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(ctx context.Context, logger logr.Logger, controllerName string, period time.Duration, queue workqueue.TypedRateLimitingInterface[any], n, maxRetries int, r reconcileFunc, routines ...func(context.Context, logr.Logger)) {
|
func Run[T comparable](ctx context.Context, logger logr.Logger, controllerName string, period time.Duration, queue workqueue.TypedRateLimitingInterface[T], n, maxRetries int, r reconcileFunc, routines ...func(context.Context, logr.Logger)) {
|
||||||
logger.Info("starting ...")
|
logger.Info("starting ...")
|
||||||
defer logger.Info("stopped")
|
defer logger.Info("stopped")
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -88,12 +88,12 @@ func Run(ctx context.Context, logger logr.Logger, controllerName string, period
|
||||||
logger.Info("waiting for workers to terminate ...")
|
logger.Info("waiting for workers to terminate ...")
|
||||||
}
|
}
|
||||||
|
|
||||||
func worker(ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[any], maxRetries int, r reconcileFunc) {
|
func worker[T comparable](ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[T], maxRetries int, r reconcileFunc) {
|
||||||
for processNextWorkItem(ctx, logger, metric, queue, maxRetries, r) {
|
for processNextWorkItem(ctx, logger, metric, queue, maxRetries, r) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processNextWorkItem(ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[any], maxRetries int, r reconcileFunc) bool {
|
func processNextWorkItem[T comparable](ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[T], maxRetries int, r reconcileFunc) bool {
|
||||||
if obj, quit := queue.Get(); !quit {
|
if obj, quit := queue.Get(); !quit {
|
||||||
defer queue.Done(obj)
|
defer queue.Done(obj)
|
||||||
handleErr(ctx, logger, metric, queue, maxRetries, reconcile(ctx, logger, obj, r), obj)
|
handleErr(ctx, logger, metric, queue, maxRetries, reconcile(ctx, logger, obj, r), obj)
|
||||||
|
@ -102,7 +102,7 @@ func processNextWorkItem(ctx context.Context, logger logr.Logger, metric *contro
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleErr(ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[any], maxRetries int, err error, obj interface{}) {
|
func handleErr[T comparable](ctx context.Context, logger logr.Logger, metric *controllerMetrics, queue workqueue.TypedRateLimitingInterface[T], maxRetries int, err error, obj T) {
|
||||||
if metric.reconcileTotal != nil {
|
if metric.reconcileTotal != nil {
|
||||||
metric.reconcileTotal.Add(ctx, 1, sdkmetric.WithAttributes(attribute.String("controller_name", metric.controllerName)))
|
metric.reconcileTotal.Add(ctx, 1, sdkmetric.WithAttributes(attribute.String("controller_name", metric.controllerName)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,10 @@ const (
|
||||||
// policy labels
|
// policy labels
|
||||||
LabelDomainClusterPolicy = "cpol.kyverno.io"
|
LabelDomainClusterPolicy = "cpol.kyverno.io"
|
||||||
LabelDomainPolicy = "pol.kyverno.io"
|
LabelDomainPolicy = "pol.kyverno.io"
|
||||||
|
LabelDomainValidatingPolicy = "vpol.kyverno.io"
|
||||||
LabelPrefixClusterPolicy = LabelDomainClusterPolicy + "/"
|
LabelPrefixClusterPolicy = LabelDomainClusterPolicy + "/"
|
||||||
LabelPrefixPolicy = LabelDomainPolicy + "/"
|
LabelPrefixPolicy = LabelDomainPolicy + "/"
|
||||||
|
LabelPrefixValidatingPolicy = LabelDomainValidatingPolicy + "/"
|
||||||
LabelPrefixPolicyException = "polex.kyverno.io/"
|
LabelPrefixPolicyException = "polex.kyverno.io/"
|
||||||
LabelPrefixValidatingAdmissionPolicy = "validatingadmissionpolicy.apiserver.io/"
|
LabelPrefixValidatingAdmissionPolicy = "validatingadmissionpolicy.apiserver.io/"
|
||||||
LabelPrefixValidatingAdmissionPolicyBinding = "validatingadmissionpolicybinding.apiserver.io/"
|
LabelPrefixValidatingAdmissionPolicyBinding = "validatingadmissionpolicybinding.apiserver.io/"
|
||||||
|
@ -47,6 +49,7 @@ const (
|
||||||
func IsPolicyLabel(label string) bool {
|
func IsPolicyLabel(label string) bool {
|
||||||
return strings.HasPrefix(label, LabelPrefixPolicy) ||
|
return strings.HasPrefix(label, LabelPrefixPolicy) ||
|
||||||
strings.HasPrefix(label, LabelPrefixClusterPolicy) ||
|
strings.HasPrefix(label, LabelPrefixClusterPolicy) ||
|
||||||
|
strings.HasPrefix(label, LabelPrefixValidatingPolicy) ||
|
||||||
strings.HasPrefix(label, LabelPrefixPolicyException) ||
|
strings.HasPrefix(label, LabelPrefixPolicyException) ||
|
||||||
strings.HasPrefix(label, LabelPrefixValidatingAdmissionPolicy) ||
|
strings.HasPrefix(label, LabelPrefixValidatingAdmissionPolicy) ||
|
||||||
strings.HasPrefix(label, LabelPrefixValidatingAdmissionPolicyBinding)
|
strings.HasPrefix(label, LabelPrefixValidatingAdmissionPolicyBinding)
|
||||||
|
@ -65,12 +68,16 @@ func PolicyNameFromLabel(namespace, label string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PolicyLabelPrefix(policy engineapi.GenericPolicy) string {
|
func PolicyLabelPrefix(policy engineapi.GenericPolicy) string {
|
||||||
if policy.IsNamespaced() {
|
|
||||||
return LabelPrefixPolicy
|
|
||||||
}
|
|
||||||
if policy.AsKyvernoPolicy() != nil {
|
if policy.AsKyvernoPolicy() != nil {
|
||||||
|
if policy.IsNamespaced() {
|
||||||
|
return LabelPrefixPolicy
|
||||||
|
}
|
||||||
return LabelPrefixClusterPolicy
|
return LabelPrefixClusterPolicy
|
||||||
}
|
}
|
||||||
|
if policy.AsValidatingPolicy() != nil {
|
||||||
|
return LabelPrefixValidatingPolicy
|
||||||
|
}
|
||||||
|
// TODO: detect potential type not detected
|
||||||
return LabelPrefixValidatingAdmissionPolicy
|
return LabelPrefixValidatingAdmissionPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,26 +40,24 @@ func New(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) Validate(ctx context.Context, logger logr.Logger, request handlers.AdmissionRequest, failurePolicy string, startTime time.Time) handlers.AdmissionResponse {
|
func (h *handler) Validate(ctx context.Context, logger logr.Logger, admissionRequest handlers.AdmissionRequest, failurePolicy string, startTime time.Time) handlers.AdmissionResponse {
|
||||||
response, err := h.engine.Handle(ctx, celengine.EngineRequest{
|
request := celengine.RequestFromAdmission(h.context, admissionRequest.AdmissionRequest)
|
||||||
Request: &request.AdmissionRequest,
|
response, err := h.engine.Handle(ctx, request)
|
||||||
Context: h.context,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admissionutils.Response(request.UID, err)
|
return admissionutils.Response(admissionRequest.UID, err)
|
||||||
}
|
}
|
||||||
var group wait.Group
|
var group wait.Group
|
||||||
defer group.Wait()
|
defer group.Wait()
|
||||||
group.Start(func() {
|
group.Start(func() {
|
||||||
err := h.admissionReport(ctx, response, request)
|
err := h.admissionReport(ctx, request, response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "failed to create report")
|
logger.Error(err, "failed to create report")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return h.admissionResponse(response, request)
|
return h.admissionResponse(request, response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) admissionResponse(response celengine.EngineResponse, request handlers.AdmissionRequest) handlers.AdmissionResponse {
|
func (h *handler) admissionResponse(request celengine.EngineRequest, response celengine.EngineResponse) handlers.AdmissionResponse {
|
||||||
var errs []error
|
var errs []error
|
||||||
var warnings []string
|
var warnings []string
|
||||||
for _, policy := range response.Policies {
|
for _, policy := range response.Policies {
|
||||||
|
@ -84,11 +82,12 @@ func (h *handler) admissionResponse(response celengine.EngineResponse, request h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return admissionutils.Response(request.UID, multierr.Combine(errs...), warnings...)
|
return admissionutils.Response(request.AdmissionRequest().UID, multierr.Combine(errs...), warnings...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) admissionReport(ctx context.Context, response celengine.EngineResponse, request handlers.AdmissionRequest) error {
|
func (h *handler) admissionReport(ctx context.Context, request celengine.EngineRequest, response celengine.EngineResponse) error {
|
||||||
object, oldObject, err := admissionutils.ExtractResources(nil, request.AdmissionRequest)
|
admissionRequest := request.AdmissionRequest()
|
||||||
|
object, oldObject, err := admissionutils.ExtractResources(nil, admissionRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -106,7 +105,7 @@ func (h *handler) admissionReport(ctx context.Context, response celengine.Engine
|
||||||
engineResponse = engineResponse.WithPolicy(engineapi.NewValidatingPolicy(&r.Policy))
|
engineResponse = engineResponse.WithPolicy(engineapi.NewValidatingPolicy(&r.Policy))
|
||||||
responses = append(responses, engineResponse)
|
responses = append(responses, engineResponse)
|
||||||
}
|
}
|
||||||
report := reportutils.BuildAdmissionReport(object, request.AdmissionRequest, responses...)
|
report := reportutils.BuildAdmissionReport(object, admissionRequest, responses...)
|
||||||
if len(report.GetResults()) > 0 {
|
if len(report.GetResults()) > 0 {
|
||||||
err := h.reportsBreaker.Do(ctx, func(ctx context.Context) error {
|
err := h.reportsBreaker.Do(ctx, func(ctx context.Context) error {
|
||||||
_, err := reportutils.CreateReport(ctx, report, h.kyvernoClient)
|
_, err := reportutils.CreateReport(ctx, report, h.kyvernoClient)
|
||||||
|
|
Loading…
Add table
Reference in a new issue