diff --git a/api/http/handler/kubernetes/kubernetes_config.go b/api/http/handler/kubernetes/kubernetes_config.go index 88094d23b..e9211cc63 100644 --- a/api/http/handler/kubernetes/kubernetes_config.go +++ b/api/http/handler/kubernetes/kubernetes_config.go @@ -6,8 +6,6 @@ import ( "net/http" "strings" - clientV1 "k8s.io/client-go/tools/clientcmd/api/v1" - httperror "github.com/portainer/libhttp/error" "github.com/portainer/libhttp/request" "github.com/portainer/libhttp/response" @@ -15,6 +13,7 @@ import ( "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/internal/endpointutils" kcli "github.com/portainer/portainer/api/kubernetes/cli" + clientV1 "k8s.io/client-go/tools/clientcmd/api/v1" ) // @id GetKubernetesConfig @@ -124,21 +123,14 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD authInfosSet := make(map[string]bool) for idx, endpoint := range endpoints { - cli, err := handler.kubernetesClientFactory.GetKubeClient(&endpoint) - if err != nil { - return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to create Kubernetes client", err} - } - - serviceAccount, err := cli.GetServiceAccount(tokenData) - if err != nil { - return nil, &httperror.HandlerError{http.StatusInternalServerError, fmt.Sprintf("unable to find serviceaccount associated with user; username=%s", tokenData.Username), err} - } + instanceID := handler.kubernetesClientFactory.GetInstanceID() + serviceAccountName := kcli.UserServiceAccountName(int(tokenData.ID), instanceID) configClusters[idx] = buildCluster(r, handler.BaseURL, endpoint) - configContexts[idx] = buildContext(serviceAccount.Name, endpoint) - if !authInfosSet[serviceAccount.Name] { - configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccount.Name, bearerToken)) - authInfosSet[serviceAccount.Name] = true + configContexts[idx] = buildContext(serviceAccountName, endpoint) + if !authInfosSet[serviceAccountName] { + configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccountName, bearerToken)) + authInfosSet[serviceAccountName] = true } } diff --git a/api/kubernetes/cli/client.go b/api/kubernetes/cli/client.go index c8b2cb4b3..435152066 100644 --- a/api/kubernetes/cli/client.go +++ b/api/kubernetes/cli/client.go @@ -44,6 +44,10 @@ func NewClientFactory(signatureService portainer.DigitalSignatureService, revers } } +func (factory *ClientFactory) GetInstanceID() (instanceID string) { + return factory.instanceID +} + // Remove the cached kube client so a new one can be created func (factory *ClientFactory) RemoveKubeClient(endpointID portainer.EndpointID) { factory.endpointClients.Remove(strconv.Itoa(int(endpointID))) diff --git a/api/kubernetes/cli/naming.go b/api/kubernetes/cli/naming.go index 5bff9b076..f42289a28 100644 --- a/api/kubernetes/cli/naming.go +++ b/api/kubernetes/cli/naming.go @@ -17,7 +17,7 @@ const ( portainerShellPodPrefix = "portainer-pod-kubectl-shell" ) -func userServiceAccountName(userID int, instanceID string) string { +func UserServiceAccountName(userID int, instanceID string) string { return fmt.Sprintf("%s-%s-%d", portainerUserServiceAccountPrefix, instanceID, userID) } diff --git a/api/kubernetes/cli/service_account.go b/api/kubernetes/cli/service_account.go index 53b72ba36..f9c421ec6 100644 --- a/api/kubernetes/cli/service_account.go +++ b/api/kubernetes/cli/service_account.go @@ -16,7 +16,7 @@ func (kcl *KubeClient) GetServiceAccount(tokenData *portainer.TokenData) (*v1.Se if tokenData.Role == portainer.AdministratorRole { portainerServiceAccountName = portainerClusterAdminServiceAccountName } else { - portainerServiceAccountName = userServiceAccountName(int(tokenData.ID), kcl.instanceID) + portainerServiceAccountName = UserServiceAccountName(int(tokenData.ID), kcl.instanceID) } // verify name exists as service account resource within portainer namespace @@ -30,7 +30,7 @@ func (kcl *KubeClient) GetServiceAccount(tokenData *portainer.TokenData) (*v1.Se // GetServiceAccountBearerToken returns the ServiceAccountToken associated to the specified user. func (kcl *KubeClient) GetServiceAccountBearerToken(userID int) (string, error) { - serviceAccountName := userServiceAccountName(userID, kcl.instanceID) + serviceAccountName := UserServiceAccountName(userID, kcl.instanceID) return kcl.getServiceAccountToken(serviceAccountName) } @@ -39,7 +39,7 @@ func (kcl *KubeClient) GetServiceAccountBearerToken(userID int) (string, error) // cluster before creating a ServiceAccount and a ServiceAccountToken for the specified Portainer user. //It will also create required default RoleBinding and ClusterRoleBinding rules. func (kcl *KubeClient) SetupUserServiceAccount(userID int, teamIDs []int, restrictDefaultNamespace bool) error { - serviceAccountName := userServiceAccountName(userID, kcl.instanceID) + serviceAccountName := UserServiceAccountName(userID, kcl.instanceID) err := kcl.ensureRequiredResourcesExist() if err != nil { diff --git a/api/kubernetes/cli/service_account_test.go b/api/kubernetes/cli/service_account_test.go index 5392de38f..6387d6902 100644 --- a/api/kubernetes/cli/service_account_test.go +++ b/api/kubernetes/cli/service_account_test.go @@ -67,7 +67,7 @@ func Test_GetServiceAccount(t *testing.T) { ID: 1, Role: portainer.StandardUserRole, } - serviceAccountName := userServiceAccountName(int(tokenData.ID), k.instanceID) + serviceAccountName := UserServiceAccountName(int(tokenData.ID), k.instanceID) serviceAccount := &v1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Name: serviceAccountName, diff --git a/app/portainer/components/endpoint-list/endpointList.html b/app/portainer/components/endpoint-list/endpointList.html index 92c9752ea..33c9453a8 100644 --- a/app/portainer/components/endpoint-list/endpointList.html +++ b/app/portainer/components/endpoint-list/endpointList.html @@ -5,11 +5,11 @@