From 12b4ee2fa95efdd8c9057e4fc8fa1e8abcff28b1 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Thu, 22 Aug 2024 13:54:32 +0200 Subject: [PATCH] virtual/apiexport: pass through request user with additional warrent for the target workspace Signed-off-by: Dr. Stefan Schimanski --- pkg/virtual/apiexport/builder/build.go | 32 ++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/pkg/virtual/apiexport/builder/build.go b/pkg/virtual/apiexport/builder/build.go index d5a74de82ac1..f1497280cc85 100644 --- a/pkg/virtual/apiexport/builder/build.go +++ b/pkg/virtual/apiexport/builder/build.go @@ -18,6 +18,7 @@ package builder import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -25,7 +26,6 @@ import ( kcpdynamic "github.com/kcp-dev/client-go/dynamic" kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" "github.com/kcp-dev/logicalcluster/v3" - "k8s.io/apimachinery/pkg/labels" "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -100,19 +100,41 @@ func BuildVirtualWorkspace( return nil, fmt.Errorf("error getting valid cluster from context: %w", err) } + user, found := genericapirequest.UserFrom(ctx) + if !found { + return nil, fmt.Errorf("error getting user from context") + } + // Wildcard requests cannot be impersonated against a concrete cluster. if cluster.Wildcard { return dynamicClient, nil } - impersonationConfig := rest.CopyConfig(cfg) - impersonationConfig.Impersonate = rest.ImpersonationConfig{ - UserName: "system:serviceaccount:default:rest", - Groups: []string{bootstrap.SystemKcpAdminGroup}, + // Add a warrant of a fake local service account giving full access + warrant := authorization.Warrant{ + User: "system:serviceaccount:default:rest", + Groups: []string{bootstrap.SystemKcpAdminGroup}, Extra: map[string][]string{ serviceaccount.ClusterNameKey: {cluster.Name.Path().String()}, }, } + bs, err := json.Marshal(warrant) + if err != nil { + return nil, fmt.Errorf("error marshaling warrant: %w", err) + } + + // Impersonate the request user and add the warrant as an extra + impersonationConfig := rest.CopyConfig(cfg) + impersonationConfig.Impersonate = rest.ImpersonationConfig{ + UserName: user.GetName(), + Groups: user.GetGroups(), + UID: user.GetUID(), + Extra: user.GetExtra(), + } + if impersonationConfig.Impersonate.Extra == nil { + impersonationConfig.Impersonate.Extra = map[string][]string{} + } + impersonationConfig.Impersonate.Extra[authorization.WarrantExtraKey] = append(impersonationConfig.Impersonate.Extra[authorization.WarrantExtraKey], string(bs)) impersonatedClient, err := kcpdynamic.NewForConfig(impersonationConfig) if err != nil { return nil, fmt.Errorf("error generating dynamic client: %w", err)