fix: invoke auth via Fission router JWT login
This commit is contained in:
+81
-8
@@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"fission-console/ui"
|
||||
@@ -32,11 +33,21 @@ var (
|
||||
timeTrigGVR = schema.GroupVersionResource{Group: "fission.io", Version: "v1", Resource: "timetriggers"}
|
||||
)
|
||||
|
||||
const defaultSATokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
||||
|
||||
type server struct {
|
||||
dyn dynamic.Interface
|
||||
ns string
|
||||
routerURL string
|
||||
http *http.Client
|
||||
dyn dynamic.Interface
|
||||
ns string
|
||||
routerURL string
|
||||
http *http.Client
|
||||
saTokenPath string
|
||||
|
||||
authUser string
|
||||
authPass string
|
||||
|
||||
tokenMu sync.Mutex
|
||||
cachedJWT string
|
||||
tokenExpAt time.Time
|
||||
}
|
||||
|
||||
type createFunctionRequest struct {
|
||||
@@ -68,11 +79,18 @@ func main() {
|
||||
log.Fatalf("create dynamic client: %v", err)
|
||||
}
|
||||
|
||||
authUser := envDefault("FISSION_AUTH_USERNAME", "")
|
||||
authPass := envDefault("FISSION_AUTH_PASSWORD", "")
|
||||
saTokenPath := envDefault("SA_TOKEN_PATH", defaultSATokenPath)
|
||||
|
||||
s := &server{
|
||||
dyn: dyn,
|
||||
ns: namespace,
|
||||
routerURL: routerURL,
|
||||
http: &http.Client{Timeout: 30 * time.Second},
|
||||
dyn: dyn,
|
||||
ns: namespace,
|
||||
routerURL: routerURL,
|
||||
http: &http.Client{Timeout: 30 * time.Second},
|
||||
saTokenPath: saTokenPath,
|
||||
authUser: authUser,
|
||||
authPass: authPass,
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
@@ -474,6 +492,9 @@ func (s *server) handleInvokeFunction(w http.ResponseWriter, r *http.Request, na
|
||||
if invokeMethod == http.MethodPost {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
if token := s.getRouterToken(); token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
|
||||
resp, err := s.http.Do(req)
|
||||
if err != nil {
|
||||
@@ -491,6 +512,58 @@ func (s *server) handleInvokeFunction(w http.ResponseWriter, r *http.Request, na
|
||||
})
|
||||
}
|
||||
|
||||
func (s *server) readSAToken() string {
|
||||
if s.saTokenPath == "" {
|
||||
return ""
|
||||
}
|
||||
data, err := os.ReadFile(s.saTokenPath)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(string(data))
|
||||
}
|
||||
|
||||
func (s *server) getRouterToken() string {
|
||||
if s.authUser == "" || s.authPass == "" {
|
||||
return s.readSAToken()
|
||||
}
|
||||
|
||||
s.tokenMu.Lock()
|
||||
defer s.tokenMu.Unlock()
|
||||
|
||||
if s.cachedJWT != "" && time.Now().Before(s.tokenExpAt) {
|
||||
return s.cachedJWT
|
||||
}
|
||||
|
||||
loginURL := s.routerURL + "/auth/login"
|
||||
body, _ := json.Marshal(map[string]string{"username": s.authUser, "password": s.authPass})
|
||||
resp, err := s.http.Post(loginURL, "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
log.Printf("router login failed: %v", err)
|
||||
return s.readSAToken()
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
|
||||
respBody, _ := io.ReadAll(resp.Body)
|
||||
log.Printf("router login %d: %s", resp.StatusCode, string(respBody))
|
||||
return s.readSAToken()
|
||||
}
|
||||
|
||||
var result struct {
|
||||
AccessToken string `json:"accesstoken"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil || result.AccessToken == "" {
|
||||
log.Printf("router login decode error: %v", err)
|
||||
return s.readSAToken()
|
||||
}
|
||||
|
||||
s.cachedJWT = result.AccessToken
|
||||
s.tokenExpAt = time.Now().Add(100 * time.Second)
|
||||
log.Printf("router JWT obtained, expires in 100s")
|
||||
return s.cachedJWT
|
||||
}
|
||||
|
||||
func (s *server) handleDeleteFunction(w http.ResponseWriter, r *http.Request, name string) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 20*time.Second)
|
||||
defer cancel()
|
||||
|
||||
Reference in New Issue
Block a user