1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/engine/policycontext/policy_context.go
Jim Bugwadia b98c0775f2
Fix deferred loading (#7597)
* handle nested contexts

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add feature flag

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add kuttl tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix linter issues

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix CLI regclient

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix: token permissions on report vulns workflow (#7611)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix: token permissions (#7619)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix: update the flag descriptions of the reports-controller (#7617)

Signed-off-by: emmanuel-ferdman <emmanuelferdman@gmail.com>

* fix: panic if env var not defined (#7613)

* fix: panic if env var not defined

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* use toggles instead of a flag

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update toggle name

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update toggle name

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix roles

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix role

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* update manifests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* remove extra unlock

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix loader reset

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* propagate context

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* cm resolver

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* level management

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* address review comments

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add enableDeferredLoading to other controllers

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* re-enable ACR credhelper

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* improve tests

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* remove image registry client init

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* check for invalid reset/restore

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* recursive kuttl test

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* add pre/post queries

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* add check for a recursive match

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* new test suite

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* eval loaders at creation level

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* kuttl test

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* add an index for resolving deps in order

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* improve comment

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* extract remove method

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* merge main

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* flags

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* feature flag

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix flag

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* update unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* two rules kuttl test

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* update unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* revert

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* per rule checkpoint

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix mutate chained rules

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* per rule checpoint/restore

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* log error

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Signed-off-by: emmanuel-ferdman <emmanuelferdman@gmail.com>
Signed-off-by: ShutingZhao <shuting@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
2023-06-27 09:58:50 -07:00

272 lines
7.9 KiB
Go

package policycontext
import (
"fmt"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
"github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
admissionv1 "k8s.io/api/admission/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// PolicyContext contains the contexts for engine to process
type PolicyContext struct {
// policy is the policy to be processed
policy kyvernov1.PolicyInterface
// newResource is the resource to be processed
newResource unstructured.Unstructured
// oldResource is the prior resource for an update, or nil
oldResource unstructured.Unstructured
// element is set when the context is used for processing a foreach loop
element unstructured.Unstructured
// admissionInfo contains the admission request information
admissionInfo kyvernov1beta1.RequestInfo
// operation contains the admission operatipn
operation kyvernov1.AdmissionOperation
// requestResource is GVR of the admission request
requestResource metav1.GroupVersionResource
// gvk is GVK of the top level resource
gvk schema.GroupVersionKind
// subresource is the subresource being requested, if any (for example, "status" or "scale")
subresource string
// jsonContext is the variable context
jsonContext enginectx.Interface
// namespaceLabels stores the label of namespace to be processed by namespace selector
namespaceLabels map[string]string
// admissionOperation represents if the caller is from the webhook server
admissionOperation bool
}
// engineapi.PolicyContext interface
func (c *PolicyContext) Policy() kyvernov1.PolicyInterface {
return c.policy
}
func (c *PolicyContext) NewResource() unstructured.Unstructured {
return c.newResource
}
func (c *PolicyContext) OldResource() unstructured.Unstructured {
return c.oldResource
}
func (c *PolicyContext) RequestResource() metav1.GroupVersionResource {
return c.requestResource
}
func (c *PolicyContext) ResourceKind() (schema.GroupVersionKind, string) {
// if the top level GVK is empty, fallback to the GVK of the resource
if c.gvk.Empty() {
if c.newResource.Object != nil {
return c.newResource.GroupVersionKind(), ""
} else {
return c.oldResource.GroupVersionKind(), ""
}
}
return c.gvk, c.subresource
}
func (c *PolicyContext) AdmissionInfo() kyvernov1beta1.RequestInfo {
return c.admissionInfo
}
func (c *PolicyContext) Operation() kyvernov1.AdmissionOperation {
return c.operation
}
func (c *PolicyContext) NamespaceLabels() map[string]string {
return c.namespaceLabels
}
func (c *PolicyContext) AdmissionOperation() bool {
return c.admissionOperation
}
func (c *PolicyContext) Element() unstructured.Unstructured {
return c.element
}
func (c *PolicyContext) SetElement(element unstructured.Unstructured) {
c.element = element
}
func (c *PolicyContext) JSONContext() enginectx.Interface {
return c.jsonContext
}
func (c PolicyContext) Copy() engineapi.PolicyContext {
return c.copy()
}
// Mutators
func (c *PolicyContext) WithPolicy(policy kyvernov1.PolicyInterface) *PolicyContext {
copy := c.copy()
copy.policy = policy
return copy
}
func (c *PolicyContext) WithNamespaceLabels(namespaceLabels map[string]string) *PolicyContext {
copy := c.copy()
copy.namespaceLabels = namespaceLabels
return copy
}
func (c *PolicyContext) WithAdmissionInfo(admissionInfo kyvernov1beta1.RequestInfo) *PolicyContext {
copy := c.copy()
copy.admissionInfo = admissionInfo
return copy
}
func (c *PolicyContext) WithNewResource(resource unstructured.Unstructured) *PolicyContext {
copy := c.copy()
copy.newResource = resource
return copy
}
func (c *PolicyContext) WithOldResource(resource unstructured.Unstructured) *PolicyContext {
copy := c.copy()
copy.oldResource = resource
return copy
}
func (c *PolicyContext) WithResourceKind(gvk schema.GroupVersionKind, subresource string) *PolicyContext {
copy := c.copy()
copy.gvk = gvk
copy.subresource = subresource
return copy
}
func (c *PolicyContext) WithRequestResource(gvr metav1.GroupVersionResource) *PolicyContext {
copy := c.copy()
copy.requestResource = gvr
return copy
}
func (c *PolicyContext) WithResources(newResource unstructured.Unstructured, oldResource unstructured.Unstructured) *PolicyContext {
return c.WithNewResource(newResource).WithOldResource(oldResource)
}
func (c *PolicyContext) WithAdmissionOperation(admissionOperation bool) *PolicyContext {
copy := c.copy()
copy.admissionOperation = admissionOperation
return copy
}
func (c PolicyContext) copy() *PolicyContext {
return &c
}
// Constructors
func newPolicyContextWithJsonContext(operation kyvernov1.AdmissionOperation, jsonContext enginectx.Interface) *PolicyContext {
return &PolicyContext{
operation: operation,
jsonContext: jsonContext,
}
}
func NewPolicyContext(
jp jmespath.Interface,
resource unstructured.Unstructured,
operation kyvernov1.AdmissionOperation,
admissionInfo *kyvernov1beta1.RequestInfo,
configuration config.Configuration,
) (*PolicyContext, error) {
enginectx := enginectx.NewContext(jp)
if err := enginectx.AddResource(resource.Object); err != nil {
return nil, err
}
if err := enginectx.AddNamespace(resource.GetNamespace()); err != nil {
return nil, err
}
if err := enginectx.AddImageInfos(&resource, configuration); err != nil {
return nil, err
}
if admissionInfo != nil {
if err := enginectx.AddUserInfo(*admissionInfo); err != nil {
return nil, err
}
if err := enginectx.AddServiceAccount(admissionInfo.AdmissionUserInfo.Username); err != nil {
return nil, err
}
}
if err := enginectx.AddOperation(string(operation)); err != nil {
return nil, err
}
policyContext := newPolicyContextWithJsonContext(operation, enginectx)
if operation != kyvernov1.Delete {
policyContext = policyContext.WithNewResource(resource)
} else {
policyContext = policyContext.WithOldResource(resource)
}
if admissionInfo != nil {
policyContext = policyContext.WithAdmissionInfo(*admissionInfo)
}
return policyContext, nil
}
func NewPolicyContextFromAdmissionRequest(
jp jmespath.Interface,
request admissionv1.AdmissionRequest,
admissionInfo kyvernov1beta1.RequestInfo,
gvk schema.GroupVersionKind,
configuration config.Configuration,
) (*PolicyContext, error) {
engineCtx, err := newJsonContext(jp, request, &admissionInfo)
if err != nil {
return nil, fmt.Errorf("failed to create policy rule context: %w", err)
}
newResource, oldResource, err := admissionutils.ExtractResources(nil, request)
if err != nil {
return nil, fmt.Errorf("failed to parse resource: %w", err)
}
if err := engineCtx.AddImageInfos(&newResource, configuration); err != nil {
return nil, fmt.Errorf("failed to add image information to the policy rule context: %w", err)
}
policyContext := newPolicyContextWithJsonContext(kyvernov1.AdmissionOperation(request.Operation), engineCtx).
WithNewResource(newResource).
WithOldResource(oldResource).
WithAdmissionInfo(admissionInfo).
WithAdmissionOperation(true).
WithResourceKind(gvk, request.SubResource).
WithRequestResource(request.Resource)
return policyContext, nil
}
func newJsonContext(
jp jmespath.Interface,
request admissionv1.AdmissionRequest,
userRequestInfo *kyvernov1beta1.RequestInfo,
) (enginectx.Interface, error) {
engineCtx := enginectx.NewContext(jp)
if err := engineCtx.AddRequest(request); err != nil {
return nil, fmt.Errorf("failed to load incoming request in context: %w", err)
}
if err := engineCtx.AddUserInfo(*userRequestInfo); err != nil {
return nil, fmt.Errorf("failed to load userInfo in context: %w", err)
}
if err := engineCtx.AddServiceAccount(userRequestInfo.AdmissionUserInfo.Username); err != nil {
return nil, fmt.Errorf("failed to load service account in context: %w", err)
}
return engineCtx, nil
}