From 2c60762cfcfa1e7f65cb3f03f046a840c5765e9e Mon Sep 17 00:00:00 2001 From: hongming Date: Thu, 10 Jun 2021 15:16:12 +0800 Subject: [PATCH] Fix container terminal security risk Signed-off-by: hongming --- pkg/apiserver/apiserver.go | 2 +- pkg/kapis/terminal/v1alpha2/handler.go | 31 ++++++++++++++++++++++++- pkg/kapis/terminal/v1alpha2/register.go | 6 +++-- tools/cmd/doc-gen/main.go | 2 +- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index b459294a4..3f8e88ad4 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -229,7 +229,7 @@ func (s *APIServer) installKubeSphereAPIs() { s.KubernetesClient.Master())) urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.InformerFactory, s.KubernetesClient.Kubernetes(), s.KubernetesClient.KubeSphere(), s.EventsClient, s.LoggingClient, s.AuditingClient, amOperator, rbacAuthorizer, s.MonitoringClient, s.RuntimeCache, s.Config.MeteringOptions)) - urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config())) + urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), rbacAuthorizer, s.KubernetesClient.Config())) urlruntime.Must(clusterkapisv1alpha1.AddToContainer(s.container, s.InformerFactory.KubernetesSharedInformerFactory(), s.InformerFactory.KubeSphereSharedInformerFactory(), diff --git a/pkg/kapis/terminal/v1alpha2/handler.go b/pkg/kapis/terminal/v1alpha2/handler.go index ac500b242..996c77c49 100644 --- a/pkg/kapis/terminal/v1alpha2/handler.go +++ b/pkg/kapis/terminal/v1alpha2/handler.go @@ -17,8 +17,13 @@ limitations under the License. package v1alpha2 import ( + "errors" "net/http" + "kubesphere.io/kubesphere/pkg/api" + "kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer" + requestctx "kubesphere.io/kubesphere/pkg/apiserver/request" + "github.com/emicklei/go-restful" "github.com/gorilla/websocket" "k8s.io/client-go/kubernetes" @@ -37,9 +42,10 @@ var upgrader = websocket.Upgrader{ type terminalHandler struct { terminaler terminal.Interface + authorizer authorizer.Authorizer } -func newTerminalHandler(client kubernetes.Interface, config *rest.Config) *terminalHandler { +func newTerminalHandler(client kubernetes.Interface, authorizer authorizer.Authorizer, config *rest.Config) *terminalHandler { return &terminalHandler{ terminaler: terminal.NewTerminaler(client, config), } @@ -51,6 +57,29 @@ func (t *terminalHandler) handleTerminalSession(request *restful.Request, respon containerName := request.QueryParameter("container") shell := request.QueryParameter("shell") + user, _ := requestctx.UserFrom(request.Request.Context()) + + createPodsExec := authorizer.AttributesRecord{ + User: user, + Verb: "create", + Resource: "pods", + Subresource: "exec", + Namespace: namespace, + ResourceRequest: true, + ResourceScope: requestctx.NamespaceScope, + } + + decision, reason, err := t.authorizer.Authorize(createPodsExec) + if err != nil { + api.HandleInternalError(response, request, err) + return + } + + if decision != authorizer.DecisionAllow { + api.HandleForbidden(response, request, errors.New(reason)) + return + } + conn, err := upgrader.Upgrade(response.ResponseWriter, request.Request, nil) if err != nil { klog.Warning(err) diff --git a/pkg/kapis/terminal/v1alpha2/register.go b/pkg/kapis/terminal/v1alpha2/register.go index 00138812b..402006340 100644 --- a/pkg/kapis/terminal/v1alpha2/register.go +++ b/pkg/kapis/terminal/v1alpha2/register.go @@ -23,6 +23,8 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer" + "kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/models" @@ -34,11 +36,11 @@ const ( var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} -func AddToContainer(c *restful.Container, client kubernetes.Interface, config *rest.Config) error { +func AddToContainer(c *restful.Container, client kubernetes.Interface, authorizer authorizer.Authorizer, config *rest.Config) error { webservice := runtime.NewWebService(GroupVersion) - handler := newTerminalHandler(client, config) + handler := newTerminalHandler(client, authorizer, config) webservice.Route(webservice.GET("/namespaces/{namespace}/pods/{pod}/exec"). To(handler.handleTerminalSession). diff --git a/tools/cmd/doc-gen/main.go b/tools/cmd/doc-gen/main.go index 40c7ae70b..731f46779 100644 --- a/tools/cmd/doc-gen/main.go +++ b/tools/cmd/doc-gen/main.go @@ -132,7 +132,7 @@ func generateSwaggerJson() []byte { urlruntime.Must(resourcesv1alpha2.AddToContainer(container, clientsets.Kubernetes(), informerFactory, "")) urlruntime.Must(resourcesv1alpha3.AddToContainer(container, informerFactory, nil)) urlruntime.Must(tenantv1alpha2.AddToContainer(container, informerFactory, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)) - urlruntime.Must(terminalv1alpha2.AddToContainer(container, clientsets.Kubernetes(), nil)) + urlruntime.Must(terminalv1alpha2.AddToContainer(container, clientsets.Kubernetes(), nil, nil)) urlruntime.Must(metricsv1alpha2.AddToContainer(container)) urlruntime.Must(networkv1alpha2.AddToContainer(container, "")) alertingOptions := &alerting.Options{}