mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
refactor: resolve roles/cluster roles/top level GVK earlier in the admission chain (#6775)
* refactor: remove more admission request pointers Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * more Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * refactor: resolve roles/cluster roles earlier in the admission chain 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> * enrich Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * enrich 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
9bca7b36b1
commit
4634760e9e
14 changed files with 120 additions and 89 deletions
|
@ -70,7 +70,7 @@ func NewServer(
|
|||
"POST",
|
||||
config.CleanupValidatingWebhookServicePath,
|
||||
handlers.FromAdmissionFunc("VALIDATE", validationHandler).
|
||||
WithDump(debugModeOpts.DumpPayload, nil, nil).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithSubResourceFilter().
|
||||
WithMetrics(policyLogger, metricsConfig.Config(), metrics.WebhookValidating).
|
||||
WithAdmission(policyLogger.WithName("validate")).
|
||||
|
|
|
@ -544,6 +544,7 @@ func main() {
|
|||
runtime,
|
||||
kubeInformer.Rbac().V1().RoleBindings().Lister(),
|
||||
kubeInformer.Rbac().V1().ClusterRoleBindings().Lister(),
|
||||
dClient.Discovery(),
|
||||
)
|
||||
// start informers and wait for cache sync
|
||||
// we need to call start again because we potentially registered new informers
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
|
@ -190,9 +189,9 @@ func NewPolicyContext(operation kyvernov1.AdmissionOperation) *PolicyContext {
|
|||
}
|
||||
|
||||
func NewPolicyContextFromAdmissionRequest(
|
||||
client dclient.IDiscovery,
|
||||
request admissionv1.AdmissionRequest,
|
||||
admissionInfo kyvernov1beta1.RequestInfo,
|
||||
gvk schema.GroupVersionKind,
|
||||
configuration config.Configuration,
|
||||
) (*PolicyContext, error) {
|
||||
ctx, err := newVariablesContext(request, &admissionInfo)
|
||||
|
@ -206,10 +205,6 @@ func NewPolicyContextFromAdmissionRequest(
|
|||
if err := ctx.AddImageInfos(&newResource, configuration); err != nil {
|
||||
return nil, fmt.Errorf("failed to add image information to the policy rule context: %w", err)
|
||||
}
|
||||
gvk, err := client.GetGVKFromGVR(schema.GroupVersionResource(request.Resource))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyContext := NewPolicyContextWithJsonContext(kyvernov1.AdmissionOperation(request.Operation), ctx).
|
||||
WithNewResource(newResource).
|
||||
WithOldResource(oldResource).
|
||||
|
|
|
@ -39,21 +39,16 @@ func (inner AdmissionHandler) withAdmission(logger logr.Logger) HttpHandler {
|
|||
return
|
||||
}
|
||||
logger := logger.WithValues(
|
||||
"kind", admissionReview.Request.Kind.Kind,
|
||||
"gvk", admissionReview.Request.Kind,
|
||||
"gvr", admissionReview.Request.Resource,
|
||||
"namespace", admissionReview.Request.Namespace,
|
||||
"name", admissionReview.Request.Name,
|
||||
"operation", admissionReview.Request.Operation,
|
||||
"uid", admissionReview.Request.UID,
|
||||
"user", admissionReview.Request.UserInfo,
|
||||
)
|
||||
admissionReview.Response = &admissionv1.AdmissionResponse{
|
||||
Allowed: true,
|
||||
UID: admissionReview.Request.UID,
|
||||
}
|
||||
admissionRequest := AdmissionRequest{
|
||||
AdmissionRequest: *admissionReview.Request,
|
||||
// TODO: roles/clusterroles
|
||||
}
|
||||
admissionResponse := inner(request.Context(), logger, admissionRequest, startTime)
|
||||
admissionReview.Response = &admissionResponse
|
||||
|
|
|
@ -6,47 +6,37 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
|
||||
)
|
||||
|
||||
func (inner AdmissionHandler) WithDump(
|
||||
enabled bool,
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
) AdmissionHandler {
|
||||
if !enabled {
|
||||
return inner
|
||||
}
|
||||
return inner.withDump(rbLister, crbLister).WithTrace("DUMP")
|
||||
return inner.withDump().WithTrace("DUMP")
|
||||
}
|
||||
|
||||
func (inner AdmissionHandler) withDump(
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
) AdmissionHandler {
|
||||
func (inner AdmissionHandler) withDump() AdmissionHandler {
|
||||
return func(ctx context.Context, logger logr.Logger, request AdmissionRequest, startTime time.Time) AdmissionResponse {
|
||||
response := inner(ctx, logger, request, startTime)
|
||||
dumpPayload(logger, rbLister, crbLister, request.AdmissionRequest, response)
|
||||
dumpPayload(logger, request, response)
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
func dumpPayload(
|
||||
logger logr.Logger,
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
request admissionv1.AdmissionRequest,
|
||||
request AdmissionRequest,
|
||||
response AdmissionResponse,
|
||||
) {
|
||||
reqPayload, err := newAdmissionRequestPayload(request, rbLister, crbLister)
|
||||
reqPayload, err := newAdmissionRequestPayload(request)
|
||||
if err != nil {
|
||||
logger.Error(err, "Failed to extract resources")
|
||||
} else {
|
||||
|
@ -77,11 +67,9 @@ type admissionRequestPayload struct {
|
|||
}
|
||||
|
||||
func newAdmissionRequestPayload(
|
||||
request admissionv1.AdmissionRequest,
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
request AdmissionRequest,
|
||||
) (*admissionRequestPayload, error) {
|
||||
newResource, oldResource, err := admissionutils.ExtractResources(nil, request)
|
||||
newResource, oldResource, err := admissionutils.ExtractResources(nil, request.AdmissionRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -92,15 +80,6 @@ func newAdmissionRequestPayload(
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
var roles, clusterRoles []string
|
||||
if rbLister != nil && crbLister != nil {
|
||||
if r, cr, err := userinfo.GetRoleRef(rbLister, crbLister, request.UserInfo); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
roles = r
|
||||
clusterRoles = cr
|
||||
}
|
||||
}
|
||||
return redactPayload(&admissionRequestPayload{
|
||||
UID: request.UID,
|
||||
Kind: request.Kind,
|
||||
|
@ -113,8 +92,8 @@ func newAdmissionRequestPayload(
|
|||
Namespace: request.Namespace,
|
||||
Operation: string(request.Operation),
|
||||
UserInfo: request.UserInfo,
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
Roles: request.Roles,
|
||||
ClusterRoles: request.ClusterRoles,
|
||||
Object: newResource,
|
||||
OldObject: oldResource,
|
||||
DryRun: request.DryRun,
|
||||
|
|
|
@ -141,7 +141,7 @@ func Test_RedactPayload(t *testing.T) {
|
|||
var req admissionv1.AdmissionRequest
|
||||
err := json.Unmarshal(c.requestPayload, &req)
|
||||
assert.NilError(t, err)
|
||||
payload, err := newAdmissionRequestPayload(req, nil, nil)
|
||||
payload, err := newAdmissionRequestPayload(AdmissionRequest{AdmissionRequest: req})
|
||||
assert.NilError(t, err)
|
||||
if payload.Object.Object != nil {
|
||||
data, err := datautils.ToMap(payload.Object.Object["data"])
|
||||
|
|
61
pkg/webhooks/handlers/enrich.go
Normal file
61
pkg/webhooks/handlers/enrich.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
|
||||
)
|
||||
|
||||
func (inner AdmissionHandler) WithRoles(
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
) AdmissionHandler {
|
||||
return inner.withRoles(rbLister, crbLister).WithTrace("ROLES")
|
||||
}
|
||||
|
||||
func (inner AdmissionHandler) WithTopLevelGVK(
|
||||
client dclient.IDiscovery,
|
||||
) AdmissionHandler {
|
||||
return inner.withTopLevelGVK(client).WithTrace("GVK")
|
||||
}
|
||||
|
||||
func (inner AdmissionHandler) withRoles(
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
) AdmissionHandler {
|
||||
return func(ctx context.Context, logger logr.Logger, request AdmissionRequest, startTime time.Time) AdmissionResponse {
|
||||
roles, clusterRoles, err := userinfo.GetRoleRef(rbLister, crbLister, request.UserInfo)
|
||||
if err != nil {
|
||||
return admissionutils.Response(request.UID, err)
|
||||
}
|
||||
request.Roles = roles
|
||||
request.ClusterRoles = clusterRoles
|
||||
logger = logger.WithValues(
|
||||
"roles", roles,
|
||||
"clusterroles", clusterRoles,
|
||||
)
|
||||
return inner(ctx, logger, request, startTime)
|
||||
}
|
||||
}
|
||||
|
||||
func (inner AdmissionHandler) withTopLevelGVK(
|
||||
client dclient.IDiscovery,
|
||||
) AdmissionHandler {
|
||||
return func(ctx context.Context, logger logr.Logger, request AdmissionRequest, startTime time.Time) AdmissionResponse {
|
||||
gvk, err := client.GetGVKFromGVR(schema.GroupVersionResource(request.Resource))
|
||||
if err != nil {
|
||||
return admissionutils.Response(request.UID, err)
|
||||
}
|
||||
request.GroupVersionKind = gvk
|
||||
logger = logger.WithValues(
|
||||
"resource.gvk", gvk,
|
||||
)
|
||||
return inner(ctx, logger, request, startTime)
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@ import (
|
|||
|
||||
const namespaceControllerUsername = "system:serviceaccount:kube-system:namespace-controller"
|
||||
|
||||
var kyvernoUsername = fmt.Sprintf("system:serviceaccount:%s:%s", config.KyvernoNamespace(), config.KyvernoServiceAccountName())
|
||||
|
||||
func (inner AdmissionHandler) WithProtection(enabled bool) AdmissionHandler {
|
||||
if !enabled {
|
||||
return inner
|
||||
|
@ -37,7 +39,7 @@ func (inner AdmissionHandler) withProtection() AdmissionHandler {
|
|||
for _, resource := range []unstructured.Unstructured{newResource, oldResource} {
|
||||
resLabels := resource.GetLabels()
|
||||
if resLabels[kyvernov1.LabelAppManagedBy] == kyvernov1.ValueKyvernoApp {
|
||||
if request.UserInfo.Username != fmt.Sprintf("system:serviceaccount:%s:%s", config.KyvernoNamespace(), config.KyvernoServiceAccountName()) {
|
||||
if request.UserInfo.Username != kyvernoUsername {
|
||||
logger.Info("Access to the resource not authorized, this is a kyverno managed resource and should be altered only by kyverno")
|
||||
return admissionutils.Response(request.UID, errors.New("A kyverno managed resource can only be modified by kyverno"))
|
||||
}
|
||||
|
|
|
@ -7,11 +7,21 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type AdmissionRequest struct {
|
||||
// AdmissionRequest is the original admission request.
|
||||
admissionv1.AdmissionRequest
|
||||
|
||||
// Roles is a list of possible role send the request.
|
||||
Roles []string
|
||||
|
||||
// ClusterRoles is a list of possible clusterRoles send the request.
|
||||
ClusterRoles []string
|
||||
|
||||
// GroupVersionKind is the top level GVK.
|
||||
GroupVersionKind schema.GroupVersionKind
|
||||
}
|
||||
|
||||
type AdmissionResponse = admissionv1.AdmissionResponse
|
||||
|
|
|
@ -36,8 +36,6 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
|||
|
||||
dclient := dclient.NewEmptyFakeClient()
|
||||
configuration := config.NewDefaultConfiguration()
|
||||
rbLister := informers.Rbac().V1().RoleBindings().Lister()
|
||||
crbLister := informers.Rbac().V1().ClusterRoleBindings().Lister()
|
||||
urLister := kyvernoInformers.Kyverno().V1beta1().UpdateRequests().Lister().UpdateRequests(config.KyvernoNamespace())
|
||||
peLister := kyvernoInformers.Kyverno().V2alpha1().PolicyExceptions().Lister()
|
||||
rclient := registryclient.NewOrDie()
|
||||
|
@ -53,7 +51,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
|||
urGenerator: updaterequest.NewFake(),
|
||||
eventGen: event.NewFake(),
|
||||
openApiManager: openapi.NewFake(),
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, dclient, rbLister, crbLister),
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration),
|
||||
engine: engine.NewEngine(
|
||||
configuration,
|
||||
dclient,
|
||||
|
|
|
@ -96,7 +96,7 @@ func NewHandlers(
|
|||
urGenerator: urGenerator,
|
||||
eventGen: eventGen,
|
||||
openApiManager: openApiManager,
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration, client, rbLister, crbLister),
|
||||
pcBuilder: webhookutils.NewPolicyContextBuilder(configuration),
|
||||
admissionReports: admissionReports,
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func (h *resourceHandlers) Validate(ctx context.Context, logger logr.Logger, req
|
|||
|
||||
logger.V(4).Info("processing policies for validate admission request", "validate", len(policies), "mutate", len(mutatePolicies), "generate", len(generatePolicies))
|
||||
|
||||
policyContext, err := h.pcBuilder.Build(request.AdmissionRequest)
|
||||
policyContext, err := h.pcBuilder.Build(request.AdmissionRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind)
|
||||
if err != nil {
|
||||
return errorResponse(logger, request.UID, err, "failed create policy context")
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ func (h *resourceHandlers) Validate(ctx context.Context, logger logr.Logger, req
|
|||
policyContext = policyContext.WithNamespaceLabels(namespaceLabels)
|
||||
vh := validation.NewValidationHandler(logger, h.kyvernoClient, h.engine, h.pCache, h.pcBuilder, h.eventGen, h.admissionReports, h.metricsConfig, h.configuration)
|
||||
|
||||
ok, msg, warnings := vh.HandleValidation(ctx, request.AdmissionRequest, policies, policyContext, startTime)
|
||||
ok, msg, warnings := vh.HandleValidation(ctx, request, policies, policyContext, startTime)
|
||||
if !ok {
|
||||
logger.Info("admission request denied")
|
||||
return admissionutils.Response(request.UID, errors.New(msg), warnings...)
|
||||
|
@ -155,7 +155,7 @@ func (h *resourceHandlers) Mutate(ctx context.Context, logger logr.Logger, reque
|
|||
return admissionutils.ResponseSuccess(request.UID)
|
||||
}
|
||||
logger.V(4).Info("processing policies for mutate admission request", "mutatePolicies", len(mutatePolicies), "verifyImagesPolicies", len(verifyImagesPolicies))
|
||||
policyContext, err := h.pcBuilder.Build(request.AdmissionRequest)
|
||||
policyContext, err := h.pcBuilder.Build(request.AdmissionRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to build policy context")
|
||||
return admissionutils.Response(request.UID, err)
|
||||
|
@ -168,7 +168,7 @@ func (h *resourceHandlers) Mutate(ctx context.Context, logger logr.Logger, reque
|
|||
}
|
||||
newRequest := patchRequest(mutatePatches, request.AdmissionRequest, logger)
|
||||
// rebuild context to process images updated via mutate policies
|
||||
policyContext, err = h.pcBuilder.Build(newRequest)
|
||||
policyContext, err = h.pcBuilder.Build(newRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to build policy context")
|
||||
return admissionutils.Response(request.UID, err)
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/tracing"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
||||
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
|
@ -29,7 +30,7 @@ type ValidationHandler interface {
|
|||
// HandleValidation handles validating webhook admission request
|
||||
// If there are no errors in validating rule we apply generation rules
|
||||
// patchedResource is the (resource + patches) after applying mutation rules
|
||||
HandleValidation(context.Context, admissionv1.AdmissionRequest, []kyvernov1.PolicyInterface, *engine.PolicyContext, time.Time) (bool, string, []string)
|
||||
HandleValidation(context.Context, handlers.AdmissionRequest, []kyvernov1.PolicyInterface, *engine.PolicyContext, time.Time) (bool, string, []string)
|
||||
}
|
||||
|
||||
func NewValidationHandler(
|
||||
|
@ -70,12 +71,12 @@ type validationHandler struct {
|
|||
|
||||
func (v *validationHandler) HandleValidation(
|
||||
ctx context.Context,
|
||||
request admissionv1.AdmissionRequest,
|
||||
request handlers.AdmissionRequest,
|
||||
policies []kyvernov1.PolicyInterface,
|
||||
policyContext *engine.PolicyContext,
|
||||
admissionRequestTimestamp time.Time,
|
||||
) (bool, string, []string) {
|
||||
resourceName := admissionutils.GetResourceName(request)
|
||||
resourceName := admissionutils.GetResourceName(request.AdmissionRequest)
|
||||
logger := v.log.WithValues("action", "validate", "resource", resourceName, "operation", request.Operation, "gvk", request.Kind)
|
||||
|
||||
var deletionTimeStamp *metav1.Time
|
||||
|
@ -145,12 +146,12 @@ func (v *validationHandler) HandleValidation(
|
|||
func (v *validationHandler) buildAuditResponses(
|
||||
ctx context.Context,
|
||||
resource unstructured.Unstructured,
|
||||
request admissionv1.AdmissionRequest,
|
||||
request handlers.AdmissionRequest,
|
||||
namespaceLabels map[string]string,
|
||||
) ([]engineapi.EngineResponse, error) {
|
||||
gvr := schema.GroupVersionResource(request.Resource)
|
||||
policies := v.pCache.GetPolicies(policycache.ValidateAudit, gvr, request.SubResource, request.Namespace)
|
||||
policyContext, err := v.pcBuilder.Build(request)
|
||||
policyContext, err := v.pcBuilder.Build(request.AdmissionRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -175,12 +176,12 @@ func (v *validationHandler) buildAuditResponses(
|
|||
func (v *validationHandler) handleAudit(
|
||||
ctx context.Context,
|
||||
resource unstructured.Unstructured,
|
||||
request admissionv1.AdmissionRequest,
|
||||
request handlers.AdmissionRequest,
|
||||
namespaceLabels map[string]string,
|
||||
engineResponses ...engineapi.EngineResponse,
|
||||
) {
|
||||
createReport := v.admissionReports
|
||||
if admissionutils.IsDryRun(request) {
|
||||
if admissionutils.IsDryRun(request.AdmissionRequest) {
|
||||
createReport = false
|
||||
}
|
||||
// we don't need reports for deletions
|
||||
|
@ -208,7 +209,7 @@ func (v *validationHandler) handleAudit(
|
|||
v.eventGen.Add(events...)
|
||||
if createReport {
|
||||
responses = append(responses, engineResponses...)
|
||||
report := reportutils.BuildAdmissionReport(resource, request, responses...)
|
||||
report := reportutils.BuildAdmissionReport(resource, request.AdmissionRequest, responses...)
|
||||
if len(report.GetResults()) > 0 {
|
||||
_, err = reportutils.CreateReport(ctx, report, v.kyvernoClient)
|
||||
if err != nil {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
|
@ -81,6 +82,7 @@ func NewServer(
|
|||
runtime runtimeutils.Runtime,
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
discovery dclient.IDiscovery,
|
||||
) Server {
|
||||
mux := httprouter.New()
|
||||
resourceLogger := logger.WithName("resource")
|
||||
|
@ -96,7 +98,9 @@ func NewServer(
|
|||
return handler.
|
||||
WithFilter(configuration).
|
||||
WithProtection(toggle.ProtectManagedResources.Enabled()).
|
||||
WithDump(debugModeOpts.DumpPayload, rbLister, crbLister).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithTopLevelGVK(discovery).
|
||||
WithRoles(rbLister, crbLister).
|
||||
WithOperationFilter(admissionv1.Create, admissionv1.Update, admissionv1.Connect).
|
||||
WithMetrics(resourceLogger, metricsConfig.Config(), metrics.WebhookMutating).
|
||||
WithAdmission(resourceLogger.WithName("mutate"))
|
||||
|
@ -111,7 +115,9 @@ func NewServer(
|
|||
return handler.
|
||||
WithFilter(configuration).
|
||||
WithProtection(toggle.ProtectManagedResources.Enabled()).
|
||||
WithDump(debugModeOpts.DumpPayload, rbLister, crbLister).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithTopLevelGVK(discovery).
|
||||
WithRoles(rbLister, crbLister).
|
||||
WithMetrics(resourceLogger, metricsConfig.Config(), metrics.WebhookValidating).
|
||||
WithAdmission(resourceLogger.WithName("validate"))
|
||||
},
|
||||
|
@ -120,7 +126,7 @@ func NewServer(
|
|||
"POST",
|
||||
config.PolicyMutatingWebhookServicePath,
|
||||
handlers.FromAdmissionFunc("MUTATE", policyHandlers.Mutate).
|
||||
WithDump(debugModeOpts.DumpPayload, rbLister, crbLister).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithMetrics(policyLogger, metricsConfig.Config(), metrics.WebhookMutating).
|
||||
WithAdmission(policyLogger.WithName("mutate")).
|
||||
ToHandlerFunc(),
|
||||
|
@ -129,7 +135,7 @@ func NewServer(
|
|||
"POST",
|
||||
config.PolicyValidatingWebhookServicePath,
|
||||
handlers.FromAdmissionFunc("VALIDATE", policyHandlers.Validate).
|
||||
WithDump(debugModeOpts.DumpPayload, rbLister, crbLister).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithSubResourceFilter().
|
||||
WithMetrics(policyLogger, metricsConfig.Config(), metrics.WebhookValidating).
|
||||
WithAdmission(policyLogger.WithName("validate")).
|
||||
|
@ -139,7 +145,7 @@ func NewServer(
|
|||
"POST",
|
||||
config.ExceptionValidatingWebhookServicePath,
|
||||
handlers.FromAdmissionFunc("VALIDATE", exceptionHandlers.Validate).
|
||||
WithDump(debugModeOpts.DumpPayload, rbLister, crbLister).
|
||||
WithDump(debugModeOpts.DumpPayload).
|
||||
WithSubResourceFilter().
|
||||
WithMetrics(exceptionLogger, metricsConfig.Config(), metrics.WebhookValidating).
|
||||
WithAdmission(exceptionLogger.WithName("validate")).
|
||||
|
|
|
@ -1,51 +1,34 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/userinfo"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
rbacv1listers "k8s.io/client-go/listers/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
type PolicyContextBuilder interface {
|
||||
Build(admissionv1.AdmissionRequest) (*engine.PolicyContext, error)
|
||||
Build(admissionv1.AdmissionRequest, []string, []string, schema.GroupVersionKind) (*engine.PolicyContext, error)
|
||||
}
|
||||
|
||||
type policyContextBuilder struct {
|
||||
configuration config.Configuration
|
||||
client dclient.Interface
|
||||
rbLister rbacv1listers.RoleBindingLister
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister
|
||||
}
|
||||
|
||||
func NewPolicyContextBuilder(
|
||||
configuration config.Configuration,
|
||||
client dclient.Interface,
|
||||
rbLister rbacv1listers.RoleBindingLister,
|
||||
crbLister rbacv1listers.ClusterRoleBindingLister,
|
||||
) PolicyContextBuilder {
|
||||
return &policyContextBuilder{
|
||||
configuration: configuration,
|
||||
client: client,
|
||||
rbLister: rbLister,
|
||||
crbLister: crbLister,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *policyContextBuilder) Build(request admissionv1.AdmissionRequest) (*engine.PolicyContext, error) {
|
||||
func (b *policyContextBuilder) Build(request admissionv1.AdmissionRequest, roles, clusterRoles []string, gvk schema.GroupVersionKind) (*engine.PolicyContext, error) {
|
||||
userRequestInfo := kyvernov1beta1.RequestInfo{
|
||||
AdmissionUserInfo: *request.UserInfo.DeepCopy(),
|
||||
Roles: roles,
|
||||
ClusterRoles: clusterRoles,
|
||||
}
|
||||
if roles, clusterRoles, err := userinfo.GetRoleRef(b.rbLister, b.crbLister, request.UserInfo); err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch RBAC information for request: %w", err)
|
||||
} else {
|
||||
userRequestInfo.Roles = roles
|
||||
userRequestInfo.ClusterRoles = clusterRoles
|
||||
}
|
||||
return engine.NewPolicyContextFromAdmissionRequest(b.client.Discovery(), request, userRequestInfo, b.configuration)
|
||||
return engine.NewPolicyContextFromAdmissionRequest(request, userRequestInfo, gvk, b.configuration)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue