Files
access-manager-api/app/main.go
T
2026-10-26 18:26:03 +00:00

138 lines
4.3 KiB
Go

package app
import (
"crypto/rand"
"flag"
"fmt"
"log"
"net/http"
"strconv"
"time"
common "access-manager-api/app/common"
"access-manager-api/app/pve"
paas "proxmoxaas-common-lib"
"github.com/gorilla/sessions"
)
type UserSession struct {
PVE common.Backend
Realm struct {
Name string
Handler common.Backend
}
DB common.Backend
}
var Version = "1.0.0"
var Config common.Config
var RootSession *UserSession
var UserSessions map[string]*UserSession
var Realms map[string]common.Realm
var Store *sessions.CookieStore
func Run() {
configPath := flag.String("config", "config.json", "path to config.json file")
flag.Parse()
// load config values
Config = common.GetConfig(*configPath)
// already exits if failed
log.Printf("[INFO] Read in config from %s\n", *configPath)
// setup http router
router := http.NewServeMux()
// setup api auth cookies
SetupAPISessionStore(&Config)
// setup root api token
client, code, err := pve.NewClientFromAPIToken(Config.PVE, Config.PVE.Token)
if err != nil {
log.Fatalf("error initializing pve root client: %d %s", code, err)
}
RootSession = &UserSession{
PVE: client,
}
// get realms from proxmox
Realms = make(map[string]common.Realm)
Realms = RootSession.PVE.(pve.ProxmoxClient).GetRealms()
// make global session map
UserSessions = make(map[string]*UserSession)
router.HandleFunc("GET /version", func(w http.ResponseWriter, r *http.Request) {
paas.HTTPWriteJson(w, http.StatusOK, map[string]any{"version": Version})
})
router.HandleFunc("POST /ticket", POST_Ticket)
router.HandleFunc("DELETE /ticket", DELETE_Ticket)
router.HandleFunc("GET /pools/{poolid}", GET_Pool)
router.HandleFunc("POST /pools/{poolid}", POST_Pool)
router.HandleFunc("DELETE /pools/{poolid}", DELETE_Pool)
router.HandleFunc("GET /groups/{groupname}", GET_Group)
router.HandleFunc("POST /groups/{groupname}", POST_Group)
router.HandleFunc("DELETE /groups/{groupname}", DELETE_Group)
router.HandleFunc("POST /pools/{poolid}/groups/{groupname}", POST_Pool_Group)
router.HandleFunc("DELETE /pools/{poolid}/groups/{groupname}", DELETE_Pool_Group)
router.HandleFunc("GET /users/{username}", GET_User)
router.HandleFunc("POST /users/{username}", POST_User)
router.HandleFunc("DELETE /users/{username}", DELETE_User)
router.HandleFunc("POST /groups/{groupname}/users/{username}", POST_Group_User)
router.HandleFunc("DELETE /groups/{groupname}/users/{username}", DELETE_Group_User)
server := LoggingMiddleware(router)
log.Printf("[INFO] starting API listening on 0.0.0.0:%d", Config.ListenPort)
log.Fatalf("[ERR ] Error starting router: %s", http.ListenAndServe("0.0.0.0:"+strconv.Itoa(Config.ListenPort), server))
}
func SetupAPISessionStore(config *common.Config) {
authKey := make([]byte, 32)
encrKey := make([]byte, 32)
n, _ := rand.Read(authKey) // rand Read never returns an error, always crashes on error
log.Printf("Generated cookie session authentication key of length %d\n", n)
n, _ = rand.Read(encrKey) // rand Read never returns an error, always crashes on error
log.Printf("Generated cookie session encryption key of length %d\n", n)
Store = sessions.NewCookieStore(authKey, encrKey)
Store.Options = &sessions.Options{
Path: config.SessionCookie.Path,
HttpOnly: config.SessionCookie.HttpOnly,
Secure: config.SessionCookie.Secure,
MaxAge: config.SessionCookie.MaxAge,
}
log.Printf("Started cookie store (Name: %s Params: %+v)\n", config.SessionCookieName, config.SessionCookie)
}
// get the cookie session from the request, returns a new session if the cookie is missing or invalid
func GetCookieSession(r *http.Request) *sessions.Session {
session, err := Store.Get(r, Config.SessionCookieName)
if err != nil {
log.Printf("Error getting session cookie: %s\n", err.Error())
}
return session
}
func GetUserSessionFromRequest(r *http.Request) (*UserSession, int, error) {
session := GetCookieSession(r)
SessionUUID := session.Values["SessionUUID"]
if SessionUUID == nil {
return nil, http.StatusUnauthorized, fmt.Errorf("no auth session found")
}
uuid := SessionUUID.(string)
usersession := UserSessions[uuid]
return usersession, http.StatusOK, nil
}
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
})
}