src/jetstream/plugins/kubernetes/dashboard/login.go
package dashboard
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
"github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
)
type loginResponse struct {
Token string `json:"token"`
}
type loginOKResponse struct {
JWEToken string `json:"jweToken"`
}
// KubeDashboardLogin will check and log into the Kubernetes Dashboard then redirect to the Dashboard UI
func KubeDashboardLogin(c echo.Context, p interfaces.PortalProxy) error {
log.Debug("kubeDashboardLogin request")
endpointGUID := c.Param("guid")
userGUID := c.Get("user_id").(string)
// Get the dashboard status
status, _ := KubeDashboardStatus(p, endpointGUID, userGUID, true)
if status.Service == nil {
return sendErrorPage(c, "Kubernetes Dashboard is not installed")
}
// Check that we have a token
if len(status.Token) == 0 {
return sendErrorPage(c, "Kubernetes Dashboard is not confiured - could not find Service Account Token")
}
// Now we need to log the user in
svc := status.Service
target := fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%s:/proxy/api/v1/csrftoken/login", svc.Namespace, svc.Scheme, svc.ServiceName)
response, err := p.DoProxySingleRequest(endpointGUID, userGUID, "GET", target, nil, nil)
if err != nil || response.StatusCode != 200 {
return sendErrorPage(c, "Unable to login to Kubernetes Dashboard")
}
// Get the csrf token
token := &loginResponse{}
if err := json.Unmarshal(response.Response, token); err != nil {
return sendErrorPage(c, "Failed to login to Kubernetes Dashboard - invalid login response")
}
// Login
login := loginResponse{
Token: status.Token,
}
body, err := json.Marshal(login)
if err != nil {
return sendErrorPage(c, "Failed to set auth token for Kubernetes Dashboard")
}
target = fmt.Sprintf("/api/v1/namespaces/%s/services/%s:%s:/proxy/api/v1/login", svc.Namespace, svc.Scheme, svc.ServiceName)
headers := make(http.Header)
headers.Set("X-CSRF-TOKEN", token.Token)
headers.Set("Content-Type", "application/json")
response, err = p.DoProxySingleRequest(endpointGUID, userGUID, "POST", target, headers, body)
if err != nil || response.StatusCode != 200 {
return sendErrorPage(c, "Failed to login to Kubernetes Dashboard")
}
// Get the csrf token
jweToken := &loginOKResponse{}
if err := json.Unmarshal(response.Response, jweToken); err != nil {
return sendErrorPage(c, "Failed to login to Kubernetes Dashboard - invalid login response")
}
session, err := p.GetSession(c)
if err != nil {
return sendErrorPage(c, "Failed to login to Kubernetes Dashboard - could not get Stratos Session")
}
// Need to cache the service information in the session to improve proxying performance
sessionValues := make(map[string]string)
sessionValues[kubeDashSessionEndpointID] = endpointGUID
sessionValues[kubeDashSessionNamespace] = svc.Namespace
sessionValues[kubeDashSessionScheme] = svc.Scheme
sessionValues[kubeDashSessionServiceName] = svc.ServiceName
sessionValues[kubeDashSessionToken] = url.QueryEscape(string(jweToken.JWEToken))
err = p.GetSessionDataStore().SetValues(session.ID, kubeDashSessionGroup, sessionValues, false)
if err != nil {
return sendErrorPage(c, "Failed to login to Kubernetes Dashboard - could not save Stratos Session data")
}
// Redirect to the kube dashboard proxy
redirectURL := fmt.Sprintf("/pp/v1/apps/kubedash/ui/%s/", endpointGUID)
return c.Redirect(http.StatusTemporaryRedirect, redirectURL)
}