Files
KubePi/internal/api/v1/proxy/proxy.go
2021-06-30 11:19:43 +08:00

87 lines
2.7 KiB
Go

package proxy
import (
"encoding/pem"
"fmt"
"github.com/KubeOperator/ekko/internal/api/v1/session"
v1Cluster "github.com/KubeOperator/ekko/internal/model/v1/cluster"
"github.com/KubeOperator/ekko/internal/service/v1/cluster"
"github.com/KubeOperator/ekko/internal/service/v1/clusterbinding"
"github.com/KubeOperator/ekko/internal/service/v1/common"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
"k8s.io/client-go/rest"
"net/http/httputil"
"net/url"
)
type Handler struct {
clusterService cluster.Service
clusterBindingService clusterbinding.Service
}
func NewHandler() *Handler {
return &Handler{
clusterService: cluster.NewService(),
clusterBindingService: clusterbinding.NewService(),
}
}
func (h *Handler) KubernetesAPIProxy() iris.Handler {
return func(ctx *context.Context) {
// 查询当前集群
name := ctx.Params().GetString("name")
proxyPath := ctx.Params().GetString("p")
c, err := h.clusterService.Get(name, common.DBOptions{})
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Values().Set("message", fmt.Sprintf("get cluster failed: %s", err.Error()))
return
}
u := ctx.Values().Get("profile")
profile := u.(session.UserProfile)
binding, err := h.clusterBindingService.GetBindingByClusterNameAndSubject(name, v1Cluster.Subject{
Kind: "User",
Name: profile.Name,
}, common.DBOptions{})
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Values().Set("message", fmt.Sprintf("get cluster binding failed: %s", err.Error()))
return
}
kubeConf := &rest.Config{
Host: c.Spec.Connect.Forward.ApiServer,
TLSClientConfig: rest.TLSClientConfig{
Insecure: true,
CertData: binding.Certificate,
KeyData: pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: c.PrivateKey}),
},
}
apiUrl, err := url.Parse(c.Spec.Connect.Forward.ApiServer)
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Values().Set("message", fmt.Sprintf("parse cluster api server failed: %s", err.Error()))
return
}
ts, err := rest.TransportFor(kubeConf)
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.Values().Set("message", fmt.Sprintf("parse cluster api server failed: %s", err.Error()))
return
}
reverseProxy := httputil.NewSingleHostReverseProxy(apiUrl)
reverseProxy.Transport = ts
ctx.Request().URL.Path = proxyPath
if ctx.Method() == "PATCH" {
ctx.Request().Header.Set("Content-Type","application/merge-patch+json")
}
reverseProxy.ServeHTTP(ctx.ResponseWriter(), ctx.Request())
}
}
func Install(parent iris.Party) {
handler := NewHandler()
sp := parent.Party("/proxy")
sp.Any("/:name/k8s/{p:path}", handler.KubernetesAPIProxy())
}