From 8de557ea100836c3acb07a9eef52909993331089 Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Mon, 16 Aug 2021 10:21:43 +0200 Subject: [PATCH 1/5] feat: workspace auth Signed-off-by: Michal Vala --- .../devworkspace/solver/che_routing.go | 45 +++++++++++++++++-- .../devworkspace/solver/traefik_config.go | 18 +++++++- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/controllers/devworkspace/solver/che_routing.go b/controllers/devworkspace/solver/che_routing.go index 6364874c8f..7659ad2357 100644 --- a/controllers/devworkspace/solver/che_routing.go +++ b/controllers/devworkspace/solver/che_routing.go @@ -370,7 +370,7 @@ func addToTraefikConfig(namespace string, workspaceID string, machineName string rtrs[name] = traefikConfigRouter{ Rule: fmt.Sprintf("PathPrefix(`%s`)", prefix), Service: name, - Middlewares: []string{name}, + Middlewares: []string{name + "-header", name + "-prefix", name + "-auth"}, Priority: 100, } @@ -384,11 +384,50 @@ func addToTraefikConfig(namespace string, workspaceID string, machineName string }, } - mdls[name] = traefikConfigMiddleware{ - StripPrefix: traefikConfigStripPrefix{ + mdls[name+"-prefix"] = traefikConfigMiddleware{ + StripPrefix: &traefikConfigStripPrefix{ Prefixes: []string{prefix}, }, } + + mdls[name+"-auth"] = traefikConfigMiddleware{ + ForwardAuth: &traefikConfigForwardAuth{ + Address: "http://127.0.0.1:8089/" + namespace, + }, + } + + mdls[name+"-header"] = traefikConfigMiddleware{ + Plugin: &traefikPlugin{ + HeaderRewrite: traefikPluginHeaderRewrite{ + From: "X-Forwarded-Access-Token", + To: "Authorization", + Prefix: "Bearer ", + }, + }, + } + + // WE NEED THIS CLUSTERROLE/BINDING FOR USER TO HAVE AN ACCESS TO HIS NAMESPACE WORKSPACES + // --- + //apiVersion: rbac.authorization.k8s.io/v1 + //kind: ClusterRole + //metadata: + // name: user5-che-ws + //rules: + //- nonResourceURLs: ["/user5-che"] + // verbs: ["get"] + //--- + //apiVersion: rbac.authorization.k8s.io/v1 + //kind: ClusterRoleBinding + //metadata: + // name: user5-che-ws + //roleRef: + // apiGroup: rbac.authorization.k8s.io + // kind: ClusterRole + // name: user5-che-ws + //subjects: + //- kind: User + // name: user5 + } } } diff --git a/controllers/devworkspace/solver/traefik_config.go b/controllers/devworkspace/solver/traefik_config.go index 3e0394888c..099e8cab51 100644 --- a/controllers/devworkspace/solver/traefik_config.go +++ b/controllers/devworkspace/solver/traefik_config.go @@ -23,7 +23,9 @@ type traefikConfigService struct { } type traefikConfigMiddleware struct { - StripPrefix traefikConfigStripPrefix `json:"stripPrefix"` + StripPrefix *traefikConfigStripPrefix `json:"stripPrefix,omitempty"` + ForwardAuth *traefikConfigForwardAuth `json:"forwardAuth,omitempty"` + Plugin *traefikPlugin `json:"plugin,omitempty"` } type traefikConfigLoadbalancer struct { @@ -37,3 +39,17 @@ type traefikConfigLoadbalancerServer struct { type traefikConfigStripPrefix struct { Prefixes []string `json:"prefixes"` } + +type traefikConfigForwardAuth struct { + Address string `json:"address"` +} + +type traefikPlugin struct { + HeaderRewrite traefikPluginHeaderRewrite `json:"header-rewrite"` +} + +type traefikPluginHeaderRewrite struct { + From string `json:"from"` + To string `json:"to"` + Prefix string `json:"prefix"` +} From c577a876039e25504936d4a3ffb7579f9603975d Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Tue, 17 Aug 2021 16:33:14 +0200 Subject: [PATCH 2/5] feat: authorize workspace endpoints Signed-off-by: Michal Vala --- .../devworkspace/solver/che_routing.go | 25 +--------- pkg/deploy/gateway/gateway.go | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/controllers/devworkspace/solver/che_routing.go b/controllers/devworkspace/solver/che_routing.go index 7659ad2357..611dc78a9d 100644 --- a/controllers/devworkspace/solver/che_routing.go +++ b/controllers/devworkspace/solver/che_routing.go @@ -392,7 +392,7 @@ func addToTraefikConfig(namespace string, workspaceID string, machineName string mdls[name+"-auth"] = traefikConfigMiddleware{ ForwardAuth: &traefikConfigForwardAuth{ - Address: "http://127.0.0.1:8089/" + namespace, + Address: "http://127.0.0.1:8089?namespace=" + namespace, }, } @@ -405,29 +405,6 @@ func addToTraefikConfig(namespace string, workspaceID string, machineName string }, }, } - - // WE NEED THIS CLUSTERROLE/BINDING FOR USER TO HAVE AN ACCESS TO HIS NAMESPACE WORKSPACES - // --- - //apiVersion: rbac.authorization.k8s.io/v1 - //kind: ClusterRole - //metadata: - // name: user5-che-ws - //rules: - //- nonResourceURLs: ["/user5-che"] - // verbs: ["get"] - //--- - //apiVersion: rbac.authorization.k8s.io/v1 - //kind: ClusterRoleBinding - //metadata: - // name: user5-che-ws - //roleRef: - // apiGroup: rbac.authorization.k8s.io - // kind: ClusterRole - // name: user5-che-ws - //subjects: - //- kind: User - // name: user5 - } } } diff --git a/pkg/deploy/gateway/gateway.go b/pkg/deploy/gateway/gateway.go index 9f567530ef..634bf46a8f 100644 --- a/pkg/deploy/gateway/gateway.go +++ b/pkg/deploy/gateway/gateway.go @@ -101,6 +101,11 @@ func syncAll(deployContext *deploy.DeployContext) error { } else { return err } + + kubeRbacProxyConfig := getGatewayKubeRbacProxyConfigSpec(instance) + if _, err := deploy.Sync(deployContext, &kubeRbacProxyConfig, configMapDiffOpts); err != nil { + return err + } } traefikConfig := getGatewayTraefikConfigSpec(instance) @@ -424,6 +429,31 @@ skip_provider_button = true`, instance.Spec.Server.CheHost, instance.Spec.Auth.O } } +func getGatewayKubeRbacProxyConfigSpec(instance *orgv1.CheCluster) corev1.ConfigMap { + return corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "ConfigMap", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "che-gateway-config-kube-rbac-proxy", + Namespace: instance.Namespace, + Labels: deploy.GetLabels(instance, GatewayServiceName), + }, + Data: map[string]string{ + "authorization-config.yaml": ` +authorization: + rewrites: + byQueryParameter: + name: "namespace" + resourceAttributes: + apiVersion: v1 + resource: services + namespace: "{{ .Value }}"`, + }, + } +} + func generateRandomCookieSecret() []byte { return []byte(base64.StdEncoding.EncodeToString([]byte(util.GeneratePasswd(16)))) } @@ -620,6 +650,14 @@ func getContainersSpec(instance *orgv1.CheCluster) []corev1.Container { "--insecure-listen-address=127.0.0.1:8089", "--upstream=http://127.0.0.1:8090/ping", "--logtostderr=true", + "--config-file=/etc/kube-rbac-proxy/authorization-config.yaml", + "--v=10", + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "kube-rbac-proxy-config", + MountPath: "/etc/kube-rbac-proxy", + }, }, }) } @@ -690,6 +728,17 @@ func getVolumesSpec(instance *orgv1.CheCluster) []corev1.Volume { }, }, }) + + volumes = append(volumes, corev1.Volume{ + Name: "kube-rbac-proxy-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "che-gateway-config-kube-rbac-proxy", + }, + }, + }, + }) } return volumes From 3baad52bbd5f3dfcf312558f1c767d0614265e52 Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Tue, 17 Aug 2021 16:38:40 +0200 Subject: [PATCH 3/5] omitempty treafik plugin object Signed-off-by: Michal Vala --- controllers/devworkspace/solver/che_routing.go | 2 +- controllers/devworkspace/solver/traefik_config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/devworkspace/solver/che_routing.go b/controllers/devworkspace/solver/che_routing.go index 611dc78a9d..d76f66f076 100644 --- a/controllers/devworkspace/solver/che_routing.go +++ b/controllers/devworkspace/solver/che_routing.go @@ -398,7 +398,7 @@ func addToTraefikConfig(namespace string, workspaceID string, machineName string mdls[name+"-header"] = traefikConfigMiddleware{ Plugin: &traefikPlugin{ - HeaderRewrite: traefikPluginHeaderRewrite{ + HeaderRewrite: &traefikPluginHeaderRewrite{ From: "X-Forwarded-Access-Token", To: "Authorization", Prefix: "Bearer ", diff --git a/controllers/devworkspace/solver/traefik_config.go b/controllers/devworkspace/solver/traefik_config.go index 099e8cab51..fd9cc0447f 100644 --- a/controllers/devworkspace/solver/traefik_config.go +++ b/controllers/devworkspace/solver/traefik_config.go @@ -45,7 +45,7 @@ type traefikConfigForwardAuth struct { } type traefikPlugin struct { - HeaderRewrite traefikPluginHeaderRewrite `json:"header-rewrite"` + HeaderRewrite *traefikPluginHeaderRewrite `json:"header-rewrite,omitempty"` } type traefikPluginHeaderRewrite struct { From 90db77782bbc8719d251e502b73f86fe23bf8004 Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Tue, 17 Aug 2021 16:39:29 +0200 Subject: [PATCH 4/5] kube-rbac-proxy default logging Signed-off-by: Michal Vala --- pkg/deploy/gateway/gateway.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/deploy/gateway/gateway.go b/pkg/deploy/gateway/gateway.go index 634bf46a8f..c15d2759ea 100644 --- a/pkg/deploy/gateway/gateway.go +++ b/pkg/deploy/gateway/gateway.go @@ -651,7 +651,6 @@ func getContainersSpec(instance *orgv1.CheCluster) []corev1.Container { "--upstream=http://127.0.0.1:8090/ping", "--logtostderr=true", "--config-file=/etc/kube-rbac-proxy/authorization-config.yaml", - "--v=10", }, VolumeMounts: []corev1.VolumeMount{ { From 083a8d73a42a9c56546b9563f8f8d45c91e72d0b Mon Sep 17 00:00:00 2001 From: Michal Vala Date: Wed, 18 Aug 2021 15:03:07 +0200 Subject: [PATCH 5/5] tests Signed-off-by: Michal Vala --- .../devworkspace/solver/che_routing_test.go | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/controllers/devworkspace/solver/che_routing_test.go b/controllers/devworkspace/solver/che_routing_test.go index 82486abef5..2c89a0937c 100644 --- a/controllers/devworkspace/solver/che_routing_test.go +++ b/controllers/devworkspace/solver/che_routing_test.go @@ -260,9 +260,35 @@ func TestCreateRelocatedObjects(t *testing.T) { t.Fatalf("Expected exactly one traefik router but got %d", len(workspaceConfig.HTTP.Routers)) } - if _, ok := workspaceConfig.HTTP.Routers["wsid-m1-9999"]; !ok { + wsid := "wsid-m1-9999" + if _, ok := workspaceConfig.HTTP.Routers[wsid]; !ok { t.Fatal("traefik config doesn't contain expected workspace configuration") } + + if len(workspaceConfig.HTTP.Routers[wsid].Middlewares) != 3 { + t.Fatalf("Expected 3 middlewares in router but got '%d'", len(workspaceConfig.HTTP.Routers[wsid].Middlewares)) + } + + if len(workspaceConfig.HTTP.Middlewares) != 3 { + t.Fatalf("Expected 3 middlewares set but got '%d'", len(workspaceConfig.HTTP.Middlewares)) + } + + mwares := []string{wsid + "-auth", wsid + "-prefix", wsid + "-header"} + for _, mware := range mwares { + if _, ok := workspaceConfig.HTTP.Middlewares[mware]; !ok { + t.Fatalf("traefik config doesn't set middleware '%s'", mware) + } + found := false + for _, r := range workspaceConfig.HTTP.Routers[wsid].Middlewares { + if r == mware { + found = true + } + } + if !found { + t.Fatalf("traefik config route doesn't set middleware '%s'", mware) + } + } + }) }