fix(kube): Use KubeClusterAccessService for Helm operations [EE-2500] (#6559)

pull/6665/head
Marcelo Rydel 2022-03-21 09:51:29 -03:00 committed by GitHub
parent cf7746082b
commit c486130a9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 105 additions and 103 deletions

View File

@ -599,7 +599,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
kubernetesTokenCacheManager := kubeproxy.NewTokenCacheManager() kubernetesTokenCacheManager := kubeproxy.NewTokenCacheManager()
kubeConfigService := kubernetes.NewKubeConfigCAService(*flags.AddrHTTPS, sslSettings.CertPath) kubeClusterAccessService := kubernetes.NewKubeClusterAccessService(*flags.BaseURL, *flags.AddrHTTPS, sslSettings.CertPath)
proxyManager := proxy.NewManager(dataStore, digitalSignatureService, reverseTunnelService, dockerClientFactory, kubernetesClientFactory, kubernetesTokenCacheManager) proxyManager := proxy.NewManager(dataStore, digitalSignatureService, reverseTunnelService, dockerClientFactory, kubernetesClientFactory, kubernetesTokenCacheManager)
@ -706,7 +706,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
OpenAMTService: openAMTService, OpenAMTService: openAMTService,
ProxyManager: proxyManager, ProxyManager: proxyManager,
KubernetesTokenCacheManager: kubernetesTokenCacheManager, KubernetesTokenCacheManager: kubernetesTokenCacheManager,
KubeConfigService: kubeConfigService, KubeClusterAccessService: kubeClusterAccessService,
SignatureService: digitalSignatureService, SignatureService: digitalSignatureService,
SnapshotService: snapshotService, SnapshotService: snapshotService,
SSLService: sslService, SSLService: sslService,
@ -716,7 +716,6 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
ShutdownCtx: shutdownCtx, ShutdownCtx: shutdownCtx,
ShutdownTrigger: shutdownTrigger, ShutdownTrigger: shutdownTrigger,
StackDeployer: stackDeployer, StackDeployer: stackDeployer,
BaseURL: *flags.BaseURL,
} }
} }

View File

@ -2,6 +2,7 @@ package helm
import ( import (
"net/http" "net/http"
"strings"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/portainer/libhelm" "github.com/portainer/libhelm"
@ -14,10 +15,6 @@ import (
"github.com/portainer/portainer/api/kubernetes" "github.com/portainer/portainer/api/kubernetes"
) )
const (
handlerActivityContext = "Kubernetes"
)
type requestBouncer interface { type requestBouncer interface {
AuthenticatedAccess(h http.Handler) http.Handler AuthenticatedAccess(h http.Handler) http.Handler
} }
@ -28,13 +25,13 @@ type Handler struct {
requestBouncer requestBouncer requestBouncer requestBouncer
dataStore dataservices.DataStore dataStore dataservices.DataStore
jwtService dataservices.JWTService jwtService dataservices.JWTService
kubeConfigService kubernetes.KubeConfigService kubeClusterAccessService kubernetes.KubeClusterAccessService
kubernetesDeployer portainer.KubernetesDeployer kubernetesDeployer portainer.KubernetesDeployer
helmPackageManager libhelm.HelmPackageManager helmPackageManager libhelm.HelmPackageManager
} }
// NewHandler creates a handler to manage endpoint group operations. // NewHandler creates a handler to manage endpoint group operations.
func NewHandler(bouncer requestBouncer, dataStore dataservices.DataStore, jwtService dataservices.JWTService, kubernetesDeployer portainer.KubernetesDeployer, helmPackageManager libhelm.HelmPackageManager, kubeConfigService kubernetes.KubeConfigService) *Handler { func NewHandler(bouncer requestBouncer, dataStore dataservices.DataStore, jwtService dataservices.JWTService, kubernetesDeployer portainer.KubernetesDeployer, helmPackageManager libhelm.HelmPackageManager, kubeClusterAccessService kubernetes.KubeClusterAccessService) *Handler {
h := &Handler{ h := &Handler{
Router: mux.NewRouter(), Router: mux.NewRouter(),
requestBouncer: bouncer, requestBouncer: bouncer,
@ -42,7 +39,7 @@ func NewHandler(bouncer requestBouncer, dataStore dataservices.DataStore, jwtSer
jwtService: jwtService, jwtService: jwtService,
kubernetesDeployer: kubernetesDeployer, kubernetesDeployer: kubernetesDeployer,
helmPackageManager: helmPackageManager, helmPackageManager: helmPackageManager,
kubeConfigService: kubeConfigService, kubeClusterAccessService: kubeClusterAccessService,
} }
h.Use(middlewares.WithEndpoint(dataStore.Endpoint(), "id")) h.Use(middlewares.WithEndpoint(dataStore.Endpoint(), "id"))
@ -104,10 +101,20 @@ func (handler *Handler) getHelmClusterAccess(r *http.Request) (*options.Kubernet
return nil, &httperror.HandlerError{http.StatusUnauthorized, "Unauthorized", err} return nil, &httperror.HandlerError{http.StatusUnauthorized, "Unauthorized", err}
} }
kubeConfigInternal := handler.kubeConfigService.GetKubeConfigInternal(endpoint.ID, bearerToken) sslSettings, err := handler.dataStore.SSLSettings().Settings()
if err != nil {
return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve settings from the database", err}
}
hostURL := "localhost"
if !sslSettings.SelfSigned {
hostURL = strings.Split(r.Host, ":")[0]
}
kubeConfigInternal := handler.kubeClusterAccessService.GetData(hostURL, endpoint.ID)
return &options.KubernetesClusterAccess{ return &options.KubernetesClusterAccess{
ClusterServerURL: kubeConfigInternal.ClusterServerURL, ClusterServerURL: kubeConfigInternal.ClusterServerURL,
CertificateAuthorityFile: kubeConfigInternal.CertificateAuthorityFile, CertificateAuthorityFile: kubeConfigInternal.CertificateAuthorityFile,
AuthToken: kubeConfigInternal.AuthToken, AuthToken: bearerToken,
}, nil }, nil
} }

View File

@ -36,8 +36,8 @@ func Test_helmDelete(t *testing.T) {
kubernetesDeployer := exectest.NewKubernetesDeployer() kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("") helmPackageManager := test.NewMockHelmBinaryPackageManager("")
kubeConfigService := kubernetes.NewKubeConfigCAService("", "") kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeConfigService) h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)
is.NotNil(h, "Handler should not fail") is.NotNil(h, "Handler should not fail")

View File

@ -39,8 +39,8 @@ func Test_helmInstall(t *testing.T) {
kubernetesDeployer := exectest.NewKubernetesDeployer() kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("") helmPackageManager := test.NewMockHelmBinaryPackageManager("")
kubeConfigService := kubernetes.NewKubeConfigCAService("", "") kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeConfigService) h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)
is.NotNil(h, "Handler should not fail") is.NotNil(h, "Handler should not fail")

View File

@ -38,8 +38,8 @@ func Test_helmList(t *testing.T) {
kubernetesDeployer := exectest.NewKubernetesDeployer() kubernetesDeployer := exectest.NewKubernetesDeployer()
helmPackageManager := test.NewMockHelmBinaryPackageManager("") helmPackageManager := test.NewMockHelmBinaryPackageManager("")
kubeConfigService := kubernetes.NewKubeConfigCAService("", "") kubeClusterAccessService := kubernetes.NewKubeClusterAccessService("", "", "")
h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeConfigService) h := NewHandler(helper.NewTestRequestBouncer(), store, jwtService, kubernetesDeployer, helmPackageManager, kubeClusterAccessService)
// Install a single chart. We expect to get these values back // Install a single chart. We expect to get these values back
options := options.InstallOptions{Name: "nginx-1", Chart: "nginx", Namespace: "default"} options := options.InstallOptions{Name: "nginx-1", Chart: "nginx", Namespace: "default"}

View File

@ -2,6 +2,7 @@ package kubernetes
import ( import (
"errors" "errors"
"github.com/portainer/portainer/api/kubernetes"
"net/http" "net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -17,21 +18,22 @@ import (
// Handler is the HTTP handler which will natively deal with to external environments(endpoints). // Handler is the HTTP handler which will natively deal with to external environments(endpoints).
type Handler struct { type Handler struct {
*mux.Router *mux.Router
dataStore dataservices.DataStore
kubernetesClientFactory *cli.ClientFactory
authorizationService *authorization.Service authorizationService *authorization.Service
JwtService dataservices.JWTService dataStore dataservices.DataStore
BaseURL string jwtService dataservices.JWTService
kubernetesClientFactory *cli.ClientFactory
kubeClusterAccessService kubernetes.KubeClusterAccessService
} }
// NewHandler creates a handler to process pre-proxied requests to external APIs. // NewHandler creates a handler to process pre-proxied requests to external APIs.
func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore dataservices.DataStore, kubernetesClientFactory *cli.ClientFactory, baseURL string) *Handler { func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore dataservices.DataStore, jwtService dataservices.JWTService, kubeClusterAccessService kubernetes.KubeClusterAccessService, kubernetesClientFactory *cli.ClientFactory) *Handler {
h := &Handler{ h := &Handler{
Router: mux.NewRouter(), Router: mux.NewRouter(),
dataStore: dataStore,
kubernetesClientFactory: kubernetesClientFactory,
authorizationService: authorizationService, authorizationService: authorizationService,
BaseURL: baseURL, dataStore: dataStore,
jwtService: jwtService,
kubeClusterAccessService: kubeClusterAccessService,
kubernetesClientFactory: kubernetesClientFactory,
} }
kubeRouter := h.PathPrefix("/kubernetes").Subrouter() kubeRouter := h.PathPrefix("/kubernetes").Subrouter()

View File

@ -39,7 +39,7 @@ func (handler *Handler) getKubernetesConfig(w http.ResponseWriter, r *http.Reque
if err != nil { if err != nil {
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err} return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err}
} }
bearerToken, err := handler.JwtService.GenerateTokenForKubeconfig(tokenData) bearerToken, err := handler.jwtService.GenerateTokenForKubeconfig(tokenData)
if err != nil { if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to generate JWT token", err} return &httperror.HandlerError{http.StatusInternalServerError, "Unable to generate JWT token", err}
} }
@ -126,7 +126,7 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
instanceID := handler.kubernetesClientFactory.GetInstanceID() instanceID := handler.kubernetesClientFactory.GetInstanceID()
serviceAccountName := kcli.UserServiceAccountName(int(tokenData.ID), instanceID) serviceAccountName := kcli.UserServiceAccountName(int(tokenData.ID), instanceID)
configClusters[idx] = buildCluster(r, handler.BaseURL, endpoint) configClusters[idx] = handler.buildCluster(r, endpoint)
configContexts[idx] = buildContext(serviceAccountName, endpoint) configContexts[idx] = buildContext(serviceAccountName, endpoint)
if !authInfosSet[serviceAccountName] { if !authInfosSet[serviceAccountName] {
configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccountName, bearerToken)) configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccountName, bearerToken))
@ -144,15 +144,13 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
}, nil }, nil
} }
func buildCluster(r *http.Request, baseURL string, endpoint portainer.Endpoint) clientV1.NamedCluster { func (handler *Handler) buildCluster(r *http.Request, endpoint portainer.Endpoint) clientV1.NamedCluster {
if baseURL != "/" { hostURL := strings.Split(r.Host, ":")[0]
baseURL = fmt.Sprintf("/%s/", strings.Trim(baseURL, "/")) kubeConfigInternal := handler.kubeClusterAccessService.GetData(hostURL, endpoint.ID)
}
proxyURL := fmt.Sprintf("https://%s%sapi/endpoints/%d/kubernetes", r.Host, baseURL, endpoint.ID)
return clientV1.NamedCluster{ return clientV1.NamedCluster{
Name: buildClusterName(endpoint.Name), Name: buildClusterName(endpoint.Name),
Cluster: clientV1.Cluster{ Cluster: clientV1.Cluster{
Server: proxyURL, Server: kubeConfigInternal.ClusterServerURL,
InsecureSkipTLSVerify: true, InsecureSkipTLSVerify: true,
}, },
} }

View File

@ -87,7 +87,7 @@ type Server struct {
SwarmStackManager portainer.SwarmStackManager SwarmStackManager portainer.SwarmStackManager
ProxyManager *proxy.Manager ProxyManager *proxy.Manager
KubernetesTokenCacheManager *kubernetes.TokenCacheManager KubernetesTokenCacheManager *kubernetes.TokenCacheManager
KubeConfigService k8s.KubeConfigService KubeClusterAccessService k8s.KubeClusterAccessService
Handler *handler.Handler Handler *handler.Handler
SSLService *ssl.Service SSLService *ssl.Service
DockerClientFactory *docker.ClientFactory DockerClientFactory *docker.ClientFactory
@ -98,7 +98,6 @@ type Server struct {
ShutdownCtx context.Context ShutdownCtx context.Context
ShutdownTrigger context.CancelFunc ShutdownTrigger context.CancelFunc
StackDeployer stackdeployer.StackDeployer StackDeployer stackdeployer.StackDeployer
BaseURL string
} }
// Start starts the HTTP server // Start starts the HTTP server
@ -175,12 +174,11 @@ func (server *Server) Start() error {
endpointProxyHandler.ProxyManager = server.ProxyManager endpointProxyHandler.ProxyManager = server.ProxyManager
endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService
var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.KubernetesClientFactory, server.BaseURL) var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.JWTService, server.KubeClusterAccessService, server.KubernetesClientFactory)
kubernetesHandler.JwtService = server.JWTService
var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public")) var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public"))
var endpointHelmHandler = helm.NewHandler(requestBouncer, server.DataStore, server.JWTService, server.KubernetesDeployer, server.HelmPackageManager, server.KubeConfigService) var endpointHelmHandler = helm.NewHandler(requestBouncer, server.DataStore, server.JWTService, server.KubernetesDeployer, server.HelmPackageManager, server.KubeClusterAccessService)
var helmTemplatesHandler = helm.NewTemplateHandler(requestBouncer, server.HelmPackageManager) var helmTemplatesHandler = helm.NewTemplateHandler(requestBouncer, server.HelmPackageManager)

View File

@ -7,26 +7,27 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"strings"
"github.com/pkg/errors" "github.com/pkg/errors"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
) )
// KubeConfigService represents a service that is responsible for handling kubeconfig operations // KubeClusterAccessService represents a service that is responsible for centralizing kube cluster access data
type KubeConfigService interface { type KubeClusterAccessService interface {
IsSecure() bool IsSecure() bool
GetKubeConfigInternal(endpointId portainer.EndpointID, authToken string) kubernetesClusterAccess GetData(hostURL string, endpointId portainer.EndpointID) kubernetesClusterAccessData
} }
// KubernetesClusterAccess represents core details which can be used to generate KubeConfig file/data // KubernetesClusterAccess represents core details which can be used to generate KubeConfig file/data
type kubernetesClusterAccess struct { type kubernetesClusterAccessData struct {
ClusterServerURL string `example:"https://mycompany.k8s.com"` ClusterServerURL string `example:"https://mycompany.k8s.com"`
CertificateAuthorityFile string `example:"/data/tls/localhost.crt"` CertificateAuthorityFile string `example:"/data/tls/localhost.crt"`
CertificateAuthorityData string `example:"MIIC5TCCAc2gAwIBAgIJAJ+...+xuhOaFXwQ=="` CertificateAuthorityData string `example:"MIIC5TCCAc2gAwIBAgIJAJ+...+xuhOaFXwQ=="`
AuthToken string `example:"ey..."`
} }
type kubeConfigCAService struct { type kubeClusterAccessService struct {
baseURL string
httpsBindAddr string httpsBindAddr string
certificateAuthorityFile string certificateAuthorityFile string
certificateAuthorityData string certificateAuthorityData string
@ -39,14 +40,15 @@ var (
errTLSCertValidation = errors.New("failed to parse tls certificate") errTLSCertValidation = errors.New("failed to parse tls certificate")
) )
// NewKubeConfigCAService encapsulates generation of core KubeConfig data // NewKubeClusterAccessService creates a new instance of a KubeClusterAccessService
func NewKubeConfigCAService(httpsBindAddr string, tlsCertPath string) KubeConfigService { func NewKubeClusterAccessService(baseURL, httpsBindAddr, tlsCertPath string) KubeClusterAccessService {
certificateAuthorityData, err := getCertificateAuthorityData(tlsCertPath) certificateAuthorityData, err := getCertificateAuthorityData(tlsCertPath)
if err != nil { if err != nil {
log.Printf("[DEBUG] [internal,kubeconfig] [message: %s, generated KubeConfig will be insecure]", err.Error()) log.Printf("[DEBUG] [internal,kubeconfig] [message: %s, generated KubeConfig will be insecure]", err.Error())
} }
return &kubeConfigCAService{ return &kubeClusterAccessService{
baseURL: baseURL,
httpsBindAddr: httpsBindAddr, httpsBindAddr: httpsBindAddr,
certificateAuthorityFile: tlsCertPath, certificateAuthorityFile: tlsCertPath,
certificateAuthorityData: certificateAuthorityData, certificateAuthorityData: certificateAuthorityData,
@ -82,23 +84,27 @@ func getCertificateAuthorityData(tlsCertPath string) (string, error) {
// this is based on the fact that we can successfully extract `certificateAuthorityData` from // this is based on the fact that we can successfully extract `certificateAuthorityData` from
// certificate file at `tlsCertPath`. If we can successfully extract `certificateAuthorityData`, // certificate file at `tlsCertPath`. If we can successfully extract `certificateAuthorityData`,
// then this will be used as `certificate-authority-data` attribute in a generated KubeConfig. // then this will be used as `certificate-authority-data` attribute in a generated KubeConfig.
func (kccas *kubeConfigCAService) IsSecure() bool { func (service *kubeClusterAccessService) IsSecure() bool {
return kccas.certificateAuthorityData != "" return service.certificateAuthorityData != ""
} }
// GetKubeConfigInternal returns K8s cluster access details for the specified environment(endpoint). // GetData returns K8s cluster access details for the specified environment(endpoint).
// On startup, portainer generates a certificate against localhost at specified `httpsBindAddr` port, hence
// the kubeconfig generated should only be utilised by internal portainer binaries as the `ClusterServerURL`
// points to the internally accessible `https` based `localhost` address.
// The struct can be used to: // The struct can be used to:
// - generate a kubeconfig file // - generate a kubeconfig file
// - pass down params to binaries // - pass down params to binaries
func (kccas *kubeConfigCAService) GetKubeConfigInternal(endpointId portainer.EndpointID, authToken string) kubernetesClusterAccess { func (service *kubeClusterAccessService) GetData(hostURL string, endpointID portainer.EndpointID) kubernetesClusterAccessData {
clusterServerUrl := fmt.Sprintf("https://localhost%s/api/endpoints/%s/kubernetes", kccas.httpsBindAddr, fmt.Sprint(endpointId)) baseURL := service.baseURL
return kubernetesClusterAccess{ if baseURL != "/" {
ClusterServerURL: clusterServerUrl, baseURL = fmt.Sprintf("/%s/", strings.Trim(baseURL, "/"))
CertificateAuthorityFile: kccas.certificateAuthorityFile, }
CertificateAuthorityData: kccas.certificateAuthorityData,
AuthToken: authToken, clusterURL := hostURL + service.httpsBindAddr + baseURL
clusterServerURL := fmt.Sprintf("https://%sapi/endpoints/%d/kubernetes", clusterURL, endpointID)
return kubernetesClusterAccessData{
ClusterServerURL: clusterServerURL,
CertificateAuthorityFile: service.certificateAuthorityFile,
CertificateAuthorityData: service.certificateAuthorityData,
} }
} }

View File

@ -78,11 +78,11 @@ func Test_getCertificateAuthorityData(t *testing.T) {
}) })
} }
func TestKubeConfigService_IsSecure(t *testing.T) { func TestKubeClusterAccessService_IsSecure(t *testing.T) {
is := assert.New(t) is := assert.New(t)
t.Run("IsSecure should be false", func(t *testing.T) { t.Run("IsSecure should be false", func(t *testing.T) {
kcs := NewKubeConfigCAService("", "") kcs := NewKubeClusterAccessService("", "", "")
is.False(kcs.IsSecure(), "should be false if TLS cert not provided") is.False(kcs.IsSecure(), "should be false if TLS cert not provided")
}) })
@ -90,39 +90,32 @@ func TestKubeConfigService_IsSecure(t *testing.T) {
filePath, teardown := createTempFile("valid-cert.crt", certData) filePath, teardown := createTempFile("valid-cert.crt", certData)
defer teardown() defer teardown()
kcs := NewKubeConfigCAService("", filePath) kcs := NewKubeClusterAccessService("", "", filePath)
is.True(kcs.IsSecure(), "should be true if valid TLS cert (path and content) provided") is.True(kcs.IsSecure(), "should be true if valid TLS cert (path and content) provided")
}) })
} }
func TestKubeConfigService_GetKubeConfigInternal(t *testing.T) { func TestKubeClusterAccessService_GetKubeConfigInternal(t *testing.T) {
is := assert.New(t) is := assert.New(t)
t.Run("GetKubeConfigInternal returns localhost address", func(t *testing.T) { t.Run("GetData contains host address", func(t *testing.T) {
kcs := NewKubeConfigCAService("", "") kcs := NewKubeClusterAccessService("/", "", "")
clusterAccessDetails := kcs.GetKubeConfigInternal(1, "some-token") clusterAccessDetails := kcs.GetData("mysite.com", 1)
is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "https://localhost"), "should contain localhost address") is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "https://mysite.com"), "should contain host address")
}) })
t.Run("GetKubeConfigInternal contains https bind address port", func(t *testing.T) { t.Run("GetData contains environment proxy url", func(t *testing.T) {
kcs := NewKubeConfigCAService(":1010", "") kcs := NewKubeClusterAccessService("/", "", "")
clusterAccessDetails := kcs.GetKubeConfigInternal(1, "some-token") clusterAccessDetails := kcs.GetData("mysite.com", 100)
is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, ":1010"), "should contain bind address port")
})
t.Run("GetKubeConfigInternal contains environment proxy url", func(t *testing.T) {
kcs := NewKubeConfigCAService("", "")
clusterAccessDetails := kcs.GetKubeConfigInternal(100, "some-token")
is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "api/endpoints/100/kubernetes"), "should contain environment proxy url") is.True(strings.Contains(clusterAccessDetails.ClusterServerURL, "api/endpoints/100/kubernetes"), "should contain environment proxy url")
}) })
t.Run("GetKubeConfigInternal returns insecure cluster access config", func(t *testing.T) { t.Run("GetData returns insecure cluster access config", func(t *testing.T) {
kcs := NewKubeConfigCAService("", "") kcs := NewKubeClusterAccessService("/", ":9443", "")
clusterAccessDetails := kcs.GetKubeConfigInternal(1, "some-token") clusterAccessDetails := kcs.GetData("mysite.com", 1)
wantClusterAccessDetails := kubernetesClusterAccess{ wantClusterAccessDetails := kubernetesClusterAccessData{
ClusterServerURL: "https://localhost/api/endpoints/1/kubernetes", ClusterServerURL: "https://mysite.com:9443/api/endpoints/1/kubernetes",
AuthToken: "some-token",
CertificateAuthorityFile: "", CertificateAuthorityFile: "",
CertificateAuthorityData: "", CertificateAuthorityData: "",
} }
@ -130,16 +123,15 @@ func TestKubeConfigService_GetKubeConfigInternal(t *testing.T) {
is.Equal(clusterAccessDetails, wantClusterAccessDetails) is.Equal(clusterAccessDetails, wantClusterAccessDetails)
}) })
t.Run("GetKubeConfigInternal returns secure cluster access config", func(t *testing.T) { t.Run("GetData returns secure cluster access config", func(t *testing.T) {
filePath, teardown := createTempFile("valid-cert.crt", certData) filePath, teardown := createTempFile("valid-cert.crt", certData)
defer teardown() defer teardown()
kcs := NewKubeConfigCAService("", filePath) kcs := NewKubeClusterAccessService("/", "", filePath)
clusterAccessDetails := kcs.GetKubeConfigInternal(1, "some-token") clusterAccessDetails := kcs.GetData("localhost", 1)
wantClusterAccessDetails := kubernetesClusterAccess{ wantClusterAccessDetails := kubernetesClusterAccessData{
ClusterServerURL: "https://localhost/api/endpoints/1/kubernetes", ClusterServerURL: "https://localhost/api/endpoints/1/kubernetes",
AuthToken: "some-token",
CertificateAuthorityFile: filePath, CertificateAuthorityFile: filePath,
CertificateAuthorityData: certDataString, CertificateAuthorityData: certDataString,
} }