diff --git a/main.go b/main.go index df47b688..994bbde1 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ import ( "context" "os" - "github.com/rancher/webhook/pkg/admission" + "github.com/rancher/webhook/pkg/server" "github.com/rancher/wrangler/pkg/kubeconfig" "github.com/rancher/wrangler/pkg/ratelimit" "github.com/rancher/wrangler/pkg/signals" @@ -28,7 +28,7 @@ func run() error { cfg.RateLimiter = ratelimit.None ctx := signals.SetupSignalHandler(context.Background()) - if err := admission.ListenAndServe(ctx, cfg); err != nil { + if err := server.ListenAndServe(ctx, cfg); err != nil { return err } diff --git a/pkg/admission/validation.go b/pkg/admission/validation.go deleted file mode 100644 index 01a85299..00000000 --- a/pkg/admission/validation.go +++ /dev/null @@ -1,71 +0,0 @@ -package admission - -import ( - "context" - "net/http" - - "github.com/rancher/rancher/pkg/apis/management.cattle.io" - v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" - "github.com/rancher/webhook/pkg/auth" - "github.com/rancher/webhook/pkg/authentication" - "github.com/rancher/webhook/pkg/cluster" - mgmtcontrollers "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io" - k8srbacv1 "github.com/rancher/webhook/pkg/generated/controllers/rbac.authorization.k8s.io" - "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac" - "github.com/rancher/wrangler/pkg/start" - "github.com/rancher/wrangler/pkg/webhook" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" -) - -func Validation(ctx context.Context, cfg *rest.Config) (http.Handler, error) { - grb, err := mgmtcontrollers.NewFactoryFromConfig(cfg) - if err != nil { - return nil, err - } - - r, err := rbac.NewFactoryFromConfig(cfg) - if err != nil { - return nil, err - } - - k8srbac, err := k8srbacv1.NewFactoryFromConfig(cfg) - if err != nil { - return nil, err - } - - rbacRestGetter := authentication.RBACRestGetter{ - Roles: r.Rbac().V1().Role().Cache(), - RoleBindings: r.Rbac().V1().RoleBinding().Cache(), - ClusterRoles: r.Rbac().V1().ClusterRole().Cache(), - ClusterRoleBindings: r.Rbac().V1().ClusterRoleBinding().Cache(), - } - - ruleResolver := rbacregistryvalidation.NewDefaultRuleResolver(rbacRestGetter, rbacRestGetter, rbacRestGetter, rbacRestGetter) - - escalationChecker := auth.NewEscalationChecker(ruleResolver, grb.Management().V3().RoleTemplate().Cache(), k8srbac.Rbac().V1().ClusterRole().Cache()) - - globalRoleBindings := auth.NewGRBValidator(grb.Management().V3().GlobalRole().Cache(), escalationChecker) - prtbs := auth.NewPRTBValidator(grb.Management().V3().RoleTemplate().Cache(), escalationChecker) - crtbs := auth.NewCRTBValidator(grb.Management().V3().RoleTemplate().Cache(), escalationChecker) - roleTemplates := auth.NewRoleTemplateValidator(escalationChecker) - - k8s, err := kubernetes.NewForConfig(cfg) - if err != nil { - return nil, err - } - - clusters := cluster.NewClusterValidator(k8s.AuthorizationV1().SubjectAccessReviews()) - - router := webhook.NewRouter() - router.Kind("Cluster").Group(management.GroupName).Type(&v3.Cluster{}).Handle(clusters) - router.Kind("RoleTemplate").Group(management.GroupName).Type(&v3.RoleTemplate{}).Handle(roleTemplates) - router.Kind("GlobalRoleBinding").Group(management.GroupName).Type(&v3.GlobalRoleBinding{}).Handle(globalRoleBindings) - router.Kind("ClusterRoleTemplateBinding").Group(management.GroupName).Type(&v3.ClusterRoleTemplateBinding{}).Handle(crtbs) - router.Kind("ProjectRoleTemplateBinding").Group(management.GroupName).Type(&v3.ProjectRoleTemplateBinding{}).Handle(prtbs) - - starters := []start.Starter{r, grb, k8srbac} - start.All(ctx, 5, starters...) - return router, nil -} diff --git a/pkg/auth/escalation.go b/pkg/auth/escalation.go index e688358d..8f30f9f1 100644 --- a/pkg/auth/escalation.go +++ b/pkg/auth/escalation.go @@ -6,8 +6,9 @@ import ( rancherv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" v3 "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io/v3" - k8srbacv1 "github.com/rancher/webhook/pkg/generated/controllers/rbac.authorization.k8s.io/v1" + k8srbacv1 "github.com/rancher/wrangler/pkg/generated/controllers/rbac/v1" "github.com/rancher/wrangler/pkg/webhook" + authenticationv1 "k8s.io/api/authentication/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apiserver/pkg/authentication/user" @@ -30,14 +31,14 @@ type EscalationChecker struct { ruleSolver validation.AuthorizationRuleResolver } -// confirmNoEscalation checks that the user attempting to create a binding/role has all the permissions they are attempting +// ConfirmNoEscalation checks that the user attempting to create a binding/role has all the permissions they are attempting // to grant -func (ec *EscalationChecker) confirmNoEscalation(response *webhook.Response, request *webhook.Request, rules []rbacv1.PolicyRule, namespace string) error { +func (ec *EscalationChecker) ConfirmNoEscalation(response *webhook.Response, request *webhook.Request, rules []rbacv1.PolicyRule, namespace string) error { userInfo := &user.DefaultInfo{ Name: request.UserInfo.Username, UID: request.UserInfo.UID, Groups: request.UserInfo.Groups, - Extra: toExtraString(request.UserInfo.Extra), + Extra: ToExtraString(request.UserInfo.Extra), } globaleCtx := k8srequest.WithNamespace(k8srequest.WithUser(context.Background(), userInfo), namespace) @@ -55,8 +56,8 @@ func (ec *EscalationChecker) confirmNoEscalation(response *webhook.Response, req return nil } -// rulesFromTemplate gets all rules from the template and all referenced templates -func (ec *EscalationChecker) rulesFromTemplate(rt *rancherv3.RoleTemplate) ([]rbacv1.PolicyRule, error) { +// RulesFromTemplate gets all rules from the template and all referenced templates +func (ec *EscalationChecker) RulesFromTemplate(rt *rancherv3.RoleTemplate) ([]rbacv1.PolicyRule, error) { var rules []rbacv1.PolicyRule var err error templatesSeen := make(map[string]bool) @@ -99,3 +100,11 @@ func (ec *EscalationChecker) gatherRules(rt *rancherv3.RoleTemplate, rules []rba } return rules, nil } + +func ToExtraString(extra map[string]authenticationv1.ExtraValue) map[string][]string { + result := make(map[string][]string) + for k, v := range extra { + result[k] = v + } + return result +} diff --git a/pkg/authentication/rolegetter.go b/pkg/auth/rolegetter.go similarity index 89% rename from pkg/authentication/rolegetter.go rename to pkg/auth/rolegetter.go index edfbbfc4..147e87e6 100644 --- a/pkg/authentication/rolegetter.go +++ b/pkg/auth/rolegetter.go @@ -1,7 +1,7 @@ -package authentication +package auth import ( - wranglerv1 "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1" + wranglerv1 "github.com/rancher/wrangler/pkg/generated/controllers/rbac/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/labels" ) diff --git a/pkg/clients/clients.go b/pkg/clients/clients.go new file mode 100644 index 00000000..17401498 --- /dev/null +++ b/pkg/clients/clients.go @@ -0,0 +1,52 @@ +package clients + +import ( + v1 "github.com/rancher/rancher/pkg/apis/catalog.cattle.io/v1" + "github.com/rancher/webhook/pkg/auth" + "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io" + managementv3 "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io/v3" + "github.com/rancher/wrangler/pkg/clients" + "github.com/rancher/wrangler/pkg/schemes" + "k8s.io/client-go/rest" + rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" +) + +type Clients struct { + clients.Clients + + Management managementv3.Interface + EscalationChecker *auth.EscalationChecker +} + +func New(rest *rest.Config) (*Clients, error) { + clients, err := clients.NewFromConfig(rest, nil) + if err != nil { + return nil, err + } + + if err := schemes.Register(v1.AddToScheme); err != nil { + return nil, err + } + + mgmt, err := management.NewFactoryFromConfigWithOptions(rest, clients.FactoryOptions) + if err != nil { + return nil, err + } + + rbacRestGetter := auth.RBACRestGetter{ + Roles: clients.RBAC.Role().Cache(), + RoleBindings: clients.RBAC.RoleBinding().Cache(), + ClusterRoles: clients.RBAC.ClusterRole().Cache(), + ClusterRoleBindings: clients.RBAC.ClusterRoleBinding().Cache(), + } + + ruleResolver := rbacregistryvalidation.NewDefaultRuleResolver(rbacRestGetter, rbacRestGetter, rbacRestGetter, rbacRestGetter) + escalationChecker := auth.NewEscalationChecker(ruleResolver, + mgmt.Management().V3().RoleTemplate().Cache(), clients.RBAC.ClusterRole().Cache()) + + return &Clients{ + Clients: *clients, + Management: mgmt.Management().V3(), + EscalationChecker: escalationChecker, + }, nil +} diff --git a/pkg/codegen/main.go b/pkg/codegen/main.go index f3f7c938..b5d5d86b 100644 --- a/pkg/codegen/main.go +++ b/pkg/codegen/main.go @@ -6,7 +6,6 @@ import ( v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" controllergen "github.com/rancher/wrangler/pkg/controller-gen" "github.com/rancher/wrangler/pkg/controller-gen/args" - v1 "k8s.io/api/rbac/v1" ) func main() { @@ -17,15 +16,11 @@ func main() { Groups: map[string]args.Group{ "management.cattle.io": { Types: []interface{}{ + v3.Cluster{}, v3.GlobalRole{}, v3.RoleTemplate{}, }, }, - "rbac.authorization.k8s.io": { - Types: []interface{}{ - v1.ClusterRole{}, - }, - }, }, }) } diff --git a/pkg/cluster/cluster.go b/pkg/resources/cluster/cluster.go similarity index 96% rename from pkg/cluster/cluster.go rename to pkg/resources/cluster/cluster.go index 1e4be72f..bf6853fd 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/resources/cluster/cluster.go @@ -12,7 +12,7 @@ import ( authorizationv1 "k8s.io/client-go/kubernetes/typed/authorization/v1" ) -func NewClusterValidator(sar authorizationv1.SubjectAccessReviewInterface) webhook.Handler { +func NewValidator(sar authorizationv1.SubjectAccessReviewInterface) webhook.Handler { return &clusterValidator{ sar: sar, } diff --git a/pkg/auth/clusterrtb.go b/pkg/resources/clusterroletemplatebinding/clusterrtb.go similarity index 82% rename from pkg/auth/clusterrtb.go rename to pkg/resources/clusterroletemplatebinding/clusterrtb.go index 4870fa2a..379e84d5 100644 --- a/pkg/auth/clusterrtb.go +++ b/pkg/resources/clusterroletemplatebinding/clusterrtb.go @@ -1,9 +1,10 @@ -package auth +package clusterroletemplatebinding import ( "time" rancherv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" + "github.com/rancher/webhook/pkg/auth" v3 "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io/v3" "github.com/rancher/wrangler/pkg/webhook" admissionv1 "k8s.io/api/admission/v1" @@ -12,7 +13,7 @@ import ( "k8s.io/utils/trace" ) -func NewCRTBValidator(rt v3.RoleTemplateCache, escalationChecker *EscalationChecker) webhook.Handler { +func NewValidator(rt v3.RoleTemplateCache, escalationChecker *auth.EscalationChecker) webhook.Handler { return &clusterRoleTemplateBindingValidator{ escalationChecker: escalationChecker, roleTemplates: rt, @@ -20,7 +21,7 @@ func NewCRTBValidator(rt v3.RoleTemplateCache, escalationChecker *EscalationChec } type clusterRoleTemplateBindingValidator struct { - escalationChecker *EscalationChecker + escalationChecker *auth.EscalationChecker roleTemplates v3.RoleTemplateCache } @@ -47,12 +48,12 @@ func (c *clusterRoleTemplateBindingValidator) Admit(response *webhook.Response, return err } - rules, err := c.escalationChecker.rulesFromTemplate(rt) + rules, err := c.escalationChecker.RulesFromTemplate(rt) if err != nil { return err } - return c.escalationChecker.confirmNoEscalation(response, request, rules, "local") + return c.escalationChecker.ConfirmNoEscalation(response, request, rules, "local") } func crtbObject(request *webhook.Request) (*rancherv3.ClusterRoleTemplateBinding, error) { diff --git a/pkg/auth/globarolebinding.go b/pkg/resources/globalrolebinding/globarolebinding.go similarity index 74% rename from pkg/auth/globarolebinding.go rename to pkg/resources/globalrolebinding/globarolebinding.go index f8e9896f..e47a86fd 100644 --- a/pkg/auth/globarolebinding.go +++ b/pkg/resources/globalrolebinding/globarolebinding.go @@ -1,18 +1,18 @@ -package auth +package globalrolebinding import ( "time" rancherv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" + "github.com/rancher/webhook/pkg/auth" v3 "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io/v3" "github.com/rancher/wrangler/pkg/webhook" admissionv1 "k8s.io/api/admission/v1" - authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/trace" ) -func NewGRBValidator(grClient v3.GlobalRoleCache, escalationChecker *EscalationChecker) webhook.Handler { +func NewValidator(grClient v3.GlobalRoleCache, escalationChecker *auth.EscalationChecker) webhook.Handler { return &globalRoleBindingValidator{ escalationChecker: escalationChecker, globalRoles: grClient, @@ -20,7 +20,7 @@ func NewGRBValidator(grClient v3.GlobalRoleCache, escalationChecker *EscalationC } type globalRoleBindingValidator struct { - escalationChecker *EscalationChecker + escalationChecker *auth.EscalationChecker globalRoles v3.GlobalRoleCache } @@ -39,7 +39,7 @@ func (grbv *globalRoleBindingValidator) Admit(response *webhook.Response, reques return err } - return grbv.escalationChecker.confirmNoEscalation(response, request, globalRole.Rules, "") + return grbv.escalationChecker.ConfirmNoEscalation(response, request, globalRole.Rules, "") } func grbObject(request *webhook.Request) (*rancherv3.GlobalRoleBinding, error) { @@ -52,11 +52,3 @@ func grbObject(request *webhook.Request) (*rancherv3.GlobalRoleBinding, error) { } return grb.(*rancherv3.GlobalRoleBinding), err } - -func toExtraString(extra map[string]authenticationv1.ExtraValue) map[string][]string { - result := make(map[string][]string) - for k, v := range extra { - result[k] = v - } - return result -} diff --git a/pkg/auth/projectrtb.go b/pkg/resources/projectroletemplatebinding/projectrtb.go similarity index 83% rename from pkg/auth/projectrtb.go rename to pkg/resources/projectroletemplatebinding/projectrtb.go index 812935df..71484ecd 100644 --- a/pkg/auth/projectrtb.go +++ b/pkg/resources/projectroletemplatebinding/projectrtb.go @@ -1,10 +1,11 @@ -package auth +package projectroletemplatebinding import ( "strings" "time" rancherv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" + "github.com/rancher/webhook/pkg/auth" v3 "github.com/rancher/webhook/pkg/generated/controllers/management.cattle.io/v3" "github.com/rancher/wrangler/pkg/webhook" admissionv1 "k8s.io/api/admission/v1" @@ -13,7 +14,7 @@ import ( "k8s.io/utils/trace" ) -func NewPRTBValidator(rt v3.RoleTemplateCache, escalationChecker *EscalationChecker) webhook.Handler { +func NewValidator(rt v3.RoleTemplateCache, escalationChecker *auth.EscalationChecker) webhook.Handler { return &projectRoleTemplateBindingValidator{ escalationChecker: escalationChecker, roleTemplates: rt, @@ -21,7 +22,7 @@ func NewPRTBValidator(rt v3.RoleTemplateCache, escalationChecker *EscalationChec } type projectRoleTemplateBindingValidator struct { - escalationChecker *EscalationChecker + escalationChecker *auth.EscalationChecker roleTemplates v3.RoleTemplateCache } @@ -50,12 +51,12 @@ func (p *projectRoleTemplateBindingValidator) Admit(response *webhook.Response, return err } - rules, err := p.escalationChecker.rulesFromTemplate(rt) + rules, err := p.escalationChecker.RulesFromTemplate(rt) if err != nil { return err } - return p.escalationChecker.confirmNoEscalation(response, request, rules, projectNS) + return p.escalationChecker.ConfirmNoEscalation(response, request, rules, projectNS) } func prtbObject(request *webhook.Request) (*rancherv3.ProjectRoleTemplateBinding, error) { diff --git a/pkg/auth/roletemplate.go b/pkg/resources/roletemplate/roletemplate.go similarity index 77% rename from pkg/auth/roletemplate.go rename to pkg/resources/roletemplate/roletemplate.go index 56694681..70f45180 100644 --- a/pkg/auth/roletemplate.go +++ b/pkg/resources/roletemplate/roletemplate.go @@ -1,23 +1,24 @@ -package auth +package roletemplate import ( "time" rancherv3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" + "github.com/rancher/webhook/pkg/auth" "github.com/rancher/wrangler/pkg/webhook" admissionv1 "k8s.io/api/admission/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/trace" ) -func NewRoleTemplateValidator(escalationChecker *EscalationChecker) webhook.Handler { +func NewValidator(escalationChecker *auth.EscalationChecker) webhook.Handler { return &roleTemplateValidator{ escalationChecker: escalationChecker, } } type roleTemplateValidator struct { - escalationChecker *EscalationChecker + escalationChecker *auth.EscalationChecker } func (r *roleTemplateValidator) Admit(response *webhook.Response, request *webhook.Request) error { @@ -29,12 +30,12 @@ func (r *roleTemplateValidator) Admit(response *webhook.Response, request *webho return err } - rules, err := r.escalationChecker.rulesFromTemplate(rt) + rules, err := r.escalationChecker.RulesFromTemplate(rt) if err != nil { return err } - return r.escalationChecker.confirmNoEscalation(response, request, rules, "") + return r.escalationChecker.ConfirmNoEscalation(response, request, rules, "") } func roleTemplateObject(request *webhook.Request) (*rancherv3.RoleTemplate, error) { diff --git a/pkg/admission/server.go b/pkg/server/server.go similarity index 66% rename from pkg/admission/server.go rename to pkg/server/server.go index 2ec20970..a6f51982 100644 --- a/pkg/admission/server.go +++ b/pkg/server/server.go @@ -1,15 +1,14 @@ -package admission +package server import ( "context" "net/http" "time" + "github.com/gorilla/mux" "github.com/rancher/dynamiclistener" "github.com/rancher/dynamiclistener/server" - "github.com/rancher/wrangler/pkg/apply" - "github.com/rancher/wrangler/pkg/generated/controllers/core" - "github.com/rancher/wrangler/pkg/schemes" + "github.com/rancher/webhook/pkg/clients" "github.com/sirupsen/logrus" v1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" @@ -18,47 +17,42 @@ import ( ) var ( - namespace = "cattle-system" - tlsName = "rancher-webhook.cattle-system.svc" - certName = "cattle-webhook-tls" - caName = "cattle-webhook-ca" - port = int32(443) - path = "/v1/webhook/validation" - clusterScope = v1.ClusterScope - namespaceScope = v1.NamespacedScope - failPolicyFail = v1.Fail - failPolicyIgnore = v1.Ignore - sideEffect = v1.SideEffectClassNone + namespace = "cattle-system" + tlsName = "rancher-webhook.cattle-system.svc" + certName = "cattle-webhook-tls" + caName = "cattle-webhook-ca" + port = int32(443) + validationPath = "/v1/webhook/validation" + mutationPath = "/v1/webhook/mutation" + clusterScope = v1.ClusterScope + namespaceScope = v1.NamespacedScope + failPolicyFail = v1.Fail + failPolicyIgnore = v1.Ignore + sideEffectClassNone = v1.SideEffectClassNone ) func ListenAndServe(ctx context.Context, cfg *rest.Config) error { - if err := schemes.Register(v1.AddToScheme); err != nil { - return err - } - - handler, err := Validation(ctx, cfg) + clients, err := clients.New(cfg) if err != nil { return err } - return listenAndServe(ctx, cfg, handler) -} - -func listenAndServe(ctx context.Context, cfg *rest.Config, handler http.Handler) (rErr error) { - apply, err := apply.NewForConfig(cfg) + validation, err := Validation(clients) if err != nil { return err } - apply = apply.WithDynamicLookup() + router := mux.NewRouter() + router.Handle(validationPath, validation) - coreControllers, err := core.NewFactoryFromConfigWithNamespace(cfg, namespace) - if err != nil { - return err - } + return listenAndServe(ctx, clients, router) +} + +func listenAndServe(ctx context.Context, clients *clients.Clients, handler http.Handler) (rErr error) { + apply := clients.Apply.WithDynamicLookup() - coreControllers.Core().V1().Secret().OnChange(ctx, "secrets", func(key string, secret *corev1.Secret) (*corev1.Secret, error) { - if secret == nil || secret.Name != caName || len(secret.Data[corev1.TLSCertKey]) == 0 { + clients.Core.Secret().OnChange(ctx, "secrets", func(key string, secret *corev1.Secret) (*corev1.Secret, error) { + if secret == nil || secret.Name != caName || secret.Namespace != namespace || len(secret.Data[corev1.TLSCertKey]) == 0 { return nil, nil } @@ -77,7 +71,7 @@ func listenAndServe(ctx context.Context, cfg *rest.Config, handler http.Handler) Service: &v1.ServiceReference{ Namespace: namespace, Name: "rancher-webhook", - Path: &path, + Path: &validationPath, Port: &port, }, CABundle: secret.Data[corev1.TLSCertKey], @@ -97,7 +91,7 @@ func listenAndServe(ctx context.Context, cfg *rest.Config, handler http.Handler) }, }, FailurePolicy: &failPolicyIgnore, - SideEffects: &sideEffect, + SideEffects: &sideEffectClassNone, AdmissionReviewVersions: []string{"v1", "v1beta1"}, }, { @@ -106,7 +100,7 @@ func listenAndServe(ctx context.Context, cfg *rest.Config, handler http.Handler) Service: &v1.ServiceReference{ Namespace: namespace, Name: "rancher-webhook", - Path: &path, + Path: &validationPath, Port: &port, }, CABundle: secret.Data[corev1.TLSCertKey], @@ -163,42 +157,23 @@ func listenAndServe(ctx context.Context, cfg *rest.Config, handler http.Handler) }, }, FailurePolicy: &failPolicyFail, - SideEffects: &sideEffect, + SideEffects: &sideEffectClassNone, AdmissionReviewVersions: []string{"v1", "v1beta1"}, }, }, }) }) - defer func() { - if rErr != nil { - return - } - rErr = coreControllers.Start(ctx, 1) - }() - return server.ListenAndServe(ctx, 9443, 0, handler, &server.ListenOpts{ - Secrets: coreControllers.Core().V1().Secret(), + Secrets: clients.Core.Secret(), CertNamespace: namespace, CertName: certName, CAName: caName, TLSListenerConfig: dynamiclistener.Config{ SANs: []string{ - "rancher-webhook", + tlsName, }, - CloseConnOnCertChange: false, - FilterCN: only(tlsName), + FilterCN: dynamiclistener.OnlyAllow(tlsName), }, }) } - -func only(str string) func(...string) []string { - return func(s2 ...string) []string { - for _, s := range s2 { - if s == str { - return []string{s} - } - } - return nil - } -} diff --git a/pkg/server/validation.go b/pkg/server/validation.go new file mode 100644 index 00000000..98f636fa --- /dev/null +++ b/pkg/server/validation.go @@ -0,0 +1,32 @@ +package server + +import ( + "net/http" + + "github.com/rancher/rancher/pkg/apis/management.cattle.io" + v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3" + "github.com/rancher/webhook/pkg/clients" + "github.com/rancher/webhook/pkg/resources/cluster" + "github.com/rancher/webhook/pkg/resources/clusterroletemplatebinding" + "github.com/rancher/webhook/pkg/resources/globalrolebinding" + "github.com/rancher/webhook/pkg/resources/projectroletemplatebinding" + "github.com/rancher/webhook/pkg/resources/roletemplate" + "github.com/rancher/wrangler/pkg/webhook" +) + +func Validation(clients *clients.Clients) (http.Handler, error) { + globalRoleBindings := globalrolebinding.NewValidator(clients.Management.GlobalRole().Cache(), clients.EscalationChecker) + prtbs := projectroletemplatebinding.NewValidator(clients.Management.RoleTemplate().Cache(), clients.EscalationChecker) + crtbs := clusterroletemplatebinding.NewValidator(clients.Management.RoleTemplate().Cache(), clients.EscalationChecker) + roleTemplates := roletemplate.NewValidator(clients.EscalationChecker) + clusters := cluster.NewValidator(clients.K8s.AuthorizationV1().SubjectAccessReviews()) + + router := webhook.NewRouter() + router.Kind("Cluster").Group(management.GroupName).Type(&v3.Cluster{}).Handle(clusters) + router.Kind("RoleTemplate").Group(management.GroupName).Type(&v3.RoleTemplate{}).Handle(roleTemplates) + router.Kind("GlobalRoleBinding").Group(management.GroupName).Type(&v3.GlobalRoleBinding{}).Handle(globalRoleBindings) + router.Kind("ClusterRoleTemplateBinding").Group(management.GroupName).Type(&v3.ClusterRoleTemplateBinding{}).Handle(crtbs) + router.Kind("ProjectRoleTemplateBinding").Group(management.GroupName).Type(&v3.ProjectRoleTemplateBinding{}).Handle(prtbs) + + return router, nil +}