mirror of https://github.com/portainer/portainer
separate internal configs with isInternal (#8690)
client-key: /Users/aliharris/.minikube/profiles/minikube/client.key Co-authored-by: testa113 <testa113>pull/8720/head
parent
945798a662
commit
22f4c5d650
|
@ -110,7 +110,7 @@ func (handler *Handler) getHelmClusterAccess(r *http.Request) (*options.Kubernet
|
|||
hostURL = r.Host
|
||||
}
|
||||
|
||||
kubeConfigInternal := handler.kubeClusterAccessService.GetData(hostURL, endpoint.ID)
|
||||
kubeConfigInternal := handler.kubeClusterAccessService.GetClusterDetails(hostURL, endpoint.ID, true)
|
||||
return &options.KubernetesClusterAccess{
|
||||
ClusterServerURL: kubeConfigInternal.ClusterServerURL,
|
||||
CertificateAuthorityFile: kubeConfigInternal.CertificateAuthorityFile,
|
||||
|
|
|
@ -51,7 +51,7 @@ func (handler *Handler) getKubernetesConfig(w http.ResponseWriter, r *http.Reque
|
|||
return httperror.BadRequest("empty endpoints list", errors.New("empty endpoints list"))
|
||||
}
|
||||
|
||||
config, handlerErr := handler.buildConfig(r, tokenData, bearerToken, endpoints)
|
||||
config, handlerErr := handler.buildConfig(r, tokenData, bearerToken, endpoints, false)
|
||||
if handlerErr != nil {
|
||||
return handlerErr
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ func (handler *Handler) filterUserKubeEndpoints(r *http.Request) ([]portainer.En
|
|||
return filteredEndpoints, nil
|
||||
}
|
||||
|
||||
func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenData, bearerToken string, endpoints []portainer.Endpoint) (*clientV1.Config, *httperror.HandlerError) {
|
||||
func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenData, bearerToken string, endpoints []portainer.Endpoint, isInternal bool) (*clientV1.Config, *httperror.HandlerError) {
|
||||
configClusters := make([]clientV1.NamedCluster, len(endpoints))
|
||||
configContexts := make([]clientV1.NamedContext, len(endpoints))
|
||||
var configAuthInfos []clientV1.NamedAuthInfo
|
||||
|
@ -125,7 +125,7 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
|
|||
instanceID := handler.KubernetesClientFactory.GetInstanceID()
|
||||
serviceAccountName := kcli.UserServiceAccountName(int(tokenData.ID), instanceID)
|
||||
|
||||
configClusters[idx] = handler.buildCluster(r, endpoint)
|
||||
configClusters[idx] = handler.buildCluster(r, endpoint, isInternal)
|
||||
configContexts[idx] = buildContext(serviceAccountName, endpoint)
|
||||
if !authInfosSet[serviceAccountName] {
|
||||
configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccountName, bearerToken))
|
||||
|
@ -143,8 +143,9 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (handler *Handler) buildCluster(r *http.Request, endpoint portainer.Endpoint) clientV1.NamedCluster {
|
||||
kubeConfigInternal := handler.kubeClusterAccessService.GetData(r.Host, endpoint.ID)
|
||||
// buildCluster builds a Kubernetes cluster configuration based on the endpoint and if it's used internally or externally.
|
||||
func (handler *Handler) buildCluster(r *http.Request, endpoint portainer.Endpoint, isInternal bool) clientV1.NamedCluster {
|
||||
kubeConfigInternal := handler.kubeClusterAccessService.GetClusterDetails(r.Host, endpoint.ID, isInternal)
|
||||
|
||||
return clientV1.NamedCluster{
|
||||
Name: buildClusterName(endpoint.Name),
|
||||
|
|
|
@ -171,6 +171,7 @@ func (handler *Handler) kubeClient(next http.Handler) http.Handler {
|
|||
tokenData,
|
||||
bearerToken,
|
||||
singleEndpointList,
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
httperror.WriteError(
|
||||
|
|
|
@ -4,9 +4,9 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"strconv"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
|
||||
|
@ -17,7 +17,7 @@ import (
|
|||
// KubeClusterAccessService represents a service that is responsible for centralizing kube cluster access data
|
||||
type KubeClusterAccessService interface {
|
||||
IsSecure() bool
|
||||
GetData(hostURL string, endpointId portainer.EndpointID) kubernetesClusterAccessData
|
||||
GetClusterDetails(hostURL string, endpointId portainer.EndpointID, isInternal bool) kubernetesClusterAccessData
|
||||
}
|
||||
|
||||
// KubernetesClusterAccess represents core details which can be used to generate KubeConfig file/data
|
||||
|
@ -89,21 +89,20 @@ func (service *kubeClusterAccessService) IsSecure() bool {
|
|||
return service.certificateAuthorityData != ""
|
||||
}
|
||||
|
||||
// GetData returns K8s cluster access details for the specified environment(endpoint).
|
||||
// GetClusterDetails returns K8s cluster access details for the specified environment(endpoint).
|
||||
// The struct can be used to:
|
||||
// - generate a kubeconfig file
|
||||
// - pass down params to binaries
|
||||
func (service *kubeClusterAccessService) GetData(hostURL string, endpointID portainer.EndpointID) kubernetesClusterAccessData {
|
||||
baseURL := service.baseURL
|
||||
|
||||
// When the api call is internal, the baseURL should not be used.
|
||||
// - isInternal is used to determine whether the kubeclient is accessed internally (for example using the kube client for backend calls) or externally (for example downloading the kubeconfig file)
|
||||
func (service *kubeClusterAccessService) GetClusterDetails(hostURL string, endpointID portainer.EndpointID, isInternal bool) kubernetesClusterAccessData {
|
||||
if hostURL == "localhost" {
|
||||
hostURL += service.httpsBindAddr
|
||||
baseURL = "/"
|
||||
}
|
||||
|
||||
if baseURL != "/" {
|
||||
baseURL = fmt.Sprintf("/%s/", strings.Trim(baseURL, "/"))
|
||||
baseURL := service.baseURL
|
||||
// When the kubeclient call is internal, the baseURL should not be used.
|
||||
if isInternal {
|
||||
baseURL = ""
|
||||
}
|
||||
|
||||
log.Debug().
|
||||
|
@ -112,9 +111,10 @@ func (service *kubeClusterAccessService) GetData(hostURL string, endpointID port
|
|||
Str("base_URL", baseURL).
|
||||
Msg("kubeconfig")
|
||||
|
||||
clusterURL := hostURL + baseURL
|
||||
|
||||
clusterServerURL := fmt.Sprintf("https://%sapi/endpoints/%d/kubernetes", clusterURL, endpointID)
|
||||
clusterServerURL, err := url.JoinPath("https://", hostURL, baseURL, "/api/endpoints/", strconv.Itoa(int(endpointID)), "/kubernetes")
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to create Kubeconfig cluster URL")
|
||||
}
|
||||
|
||||
return kubernetesClusterAccessData{
|
||||
ClusterServerURL: clusterServerURL,
|
||||
|
|
|
@ -91,21 +91,21 @@ func TestKubeClusterAccessService_IsSecure(t *testing.T) {
|
|||
func TestKubeClusterAccessService_GetKubeConfigInternal(t *testing.T) {
|
||||
is := assert.New(t)
|
||||
|
||||
t.Run("GetData contains host address", func(t *testing.T) {
|
||||
t.Run("GetClusterDetails contains host address", func(t *testing.T) {
|
||||
kcs := NewKubeClusterAccessService("/", "", "")
|
||||
clusterAccessDetails := kcs.GetData("mysite.com", 1)
|
||||
clusterAccessDetails := kcs.GetClusterDetails("mysite.com", 1, true)
|
||||
is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "https://mysite.com"), "should contain host address")
|
||||
})
|
||||
|
||||
t.Run("GetData contains environment proxy url", func(t *testing.T) {
|
||||
t.Run("GetClusterDetails contains environment proxy url", func(t *testing.T) {
|
||||
kcs := NewKubeClusterAccessService("/", "", "")
|
||||
clusterAccessDetails := kcs.GetData("mysite.com", 100)
|
||||
clusterAccessDetails := kcs.GetClusterDetails("mysite.com", 100, true)
|
||||
is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "api/endpoints/100/kubernetes"), "should contain environment proxy url")
|
||||
})
|
||||
|
||||
t.Run("GetData returns insecure cluster access config", func(t *testing.T) {
|
||||
t.Run("GetClusterDetails returns insecure cluster access config", func(t *testing.T) {
|
||||
kcs := NewKubeClusterAccessService("/", ":9443", "")
|
||||
clusterAccessDetails := kcs.GetData("mysite.com", 1)
|
||||
clusterAccessDetails := kcs.GetClusterDetails("mysite.com", 1, true)
|
||||
|
||||
wantClusterAccessDetails := kubernetesClusterAccessData{
|
||||
ClusterServerURL: "https://mysite.com/api/endpoints/1/kubernetes",
|
||||
|
@ -113,14 +113,14 @@ func TestKubeClusterAccessService_GetKubeConfigInternal(t *testing.T) {
|
|||
CertificateAuthorityData: "",
|
||||
}
|
||||
|
||||
is.Equal(clusterAccessDetails, wantClusterAccessDetails)
|
||||
is.Equal(wantClusterAccessDetails, clusterAccessDetails)
|
||||
})
|
||||
|
||||
t.Run("GetData returns secure cluster access config", func(t *testing.T) {
|
||||
t.Run("GetClusterDetails returns secure cluster access config", func(t *testing.T) {
|
||||
filePath := createTempFile("valid-cert.crt", certData, t)
|
||||
|
||||
kcs := NewKubeClusterAccessService("/", "", filePath)
|
||||
clusterAccessDetails := kcs.GetData("localhost", 1)
|
||||
clusterAccessDetails := kcs.GetClusterDetails("localhost", 1, true)
|
||||
|
||||
wantClusterAccessDetails := kubernetesClusterAccessData{
|
||||
ClusterServerURL: "https://localhost/api/endpoints/1/kubernetes",
|
||||
|
@ -128,6 +128,6 @@ func TestKubeClusterAccessService_GetKubeConfigInternal(t *testing.T) {
|
|||
CertificateAuthorityData: certDataString,
|
||||
}
|
||||
|
||||
is.Equal(clusterAccessDetails, wantClusterAccessDetails)
|
||||
is.Equal(wantClusterAccessDetails, clusterAccessDetails)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue