3
This commit is contained in:
parent
5a6eed8c57
commit
5724939500
17 changed files with 576 additions and 356 deletions
|
|
@ -5,16 +5,16 @@ tmp_dir = "tmp"
|
||||||
[build]
|
[build]
|
||||||
args_bin = []
|
args_bin = []
|
||||||
bin = "./tmp/main"
|
bin = "./tmp/main"
|
||||||
cmd = "go build -o ./tmp/main ./cmd/server/."
|
cmd = "go build -buildvcs=false -o ./tmp/main ./cmd/server/"
|
||||||
delay = 1000
|
delay = 1000
|
||||||
exclude_dir = ["assets", "tmp", "vendor", "testdata","docker"]
|
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||||
exclude_file = []
|
exclude_file = []
|
||||||
exclude_regex = ["_test.go"]
|
exclude_regex = ["_test.go"]
|
||||||
exclude_unchanged = false
|
exclude_unchanged = false
|
||||||
follow_symlink = false
|
follow_symlink = false
|
||||||
full_bin = ""
|
full_bin = ""
|
||||||
include_dir = []
|
include_dir = []
|
||||||
include_ext = ["go", "tpl", "tmpl", "html","yml","yaml"]
|
include_ext = ["go", "tpl", "tmpl", "html","yml"]
|
||||||
include_file = []
|
include_file = []
|
||||||
kill_delay = "0s"
|
kill_delay = "0s"
|
||||||
log = "build-errors.log"
|
log = "build-errors.log"
|
||||||
|
|
|
||||||
52
.air.toml.bkup
Normal file
52
.air.toml.bkup
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
root = "."
|
||||||
|
testdata_dir = "testdata"
|
||||||
|
tmp_dir = "tmp"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
args_bin = []
|
||||||
|
bin = "./tmp/main"
|
||||||
|
cmd = "go build -o ./tmp/main ./cmd/server/."
|
||||||
|
delay = 1000
|
||||||
|
exclude_dir = ["assets", "tmp", "vendor", "testdata","docker"]
|
||||||
|
exclude_file = []
|
||||||
|
exclude_regex = ["_test.go"]
|
||||||
|
exclude_unchanged = false
|
||||||
|
follow_symlink = false
|
||||||
|
full_bin = ""
|
||||||
|
include_dir = []
|
||||||
|
include_ext = ["go", "tpl", "tmpl", "html","yml","yaml"]
|
||||||
|
include_file = []
|
||||||
|
kill_delay = "0s"
|
||||||
|
log = "build-errors.log"
|
||||||
|
poll = false
|
||||||
|
poll_interval = 0
|
||||||
|
post_cmd = []
|
||||||
|
pre_cmd = []
|
||||||
|
rerun = false
|
||||||
|
rerun_delay = 500
|
||||||
|
send_interrupt = false
|
||||||
|
stop_on_error = false
|
||||||
|
|
||||||
|
[color]
|
||||||
|
app = ""
|
||||||
|
build = "yellow"
|
||||||
|
main = "magenta"
|
||||||
|
runner = "green"
|
||||||
|
watcher = "cyan"
|
||||||
|
|
||||||
|
[log]
|
||||||
|
main_only = false
|
||||||
|
silent = false
|
||||||
|
time = false
|
||||||
|
|
||||||
|
[misc]
|
||||||
|
clean_on_exit = false
|
||||||
|
|
||||||
|
[proxy]
|
||||||
|
app_port = 0
|
||||||
|
enabled = false
|
||||||
|
proxy_port = 0
|
||||||
|
|
||||||
|
[screen]
|
||||||
|
clear_on_rebuild = false
|
||||||
|
keep_scroll = true
|
||||||
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Attach to Process",
|
||||||
|
"type": "go",
|
||||||
|
"request": "attach",
|
||||||
|
"mode": "local",
|
||||||
|
"processId": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -10,87 +10,85 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func CallbackHandler(w http.ResponseWriter, r *http.Request) {
|
func CallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
config.Wrapper(func(c *config.Config) {
|
configData := config.Get()
|
||||||
|
|
||||||
// ctx := context.Background()
|
// ctx := context.Background()
|
||||||
query := r.URL.Query()
|
query := r.URL.Query()
|
||||||
|
|
||||||
code := query.Get("code")
|
code := query.Get("code")
|
||||||
state := query.Get("state")
|
state := query.Get("state")
|
||||||
|
|
||||||
verifier := app.SessionManager.GetString(r.Context(), "code_verifier")
|
verifier := appData.SessionManager.GetString(r.Context(), "code_verifier")
|
||||||
if verifier == "" {
|
if verifier == "" {
|
||||||
http.Error(w, "Code verifier not found in session", http.StatusBadRequest)
|
http.Error(w, "Code verifier not found in session", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
expectedState := app.SessionManager.GetString(r.Context(), "state")
|
expectedState := appData.SessionManager.GetString(r.Context(), "state")
|
||||||
if state != expectedState {
|
if state != expectedState {
|
||||||
http.Error(w, "Invalid state parameter", http.StatusBadRequest)
|
http.Error(w, "Invalid state parameter", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// originalURL, err := decodeState(state)
|
originalURL, err := decodeState(state)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// dump.P(err.Error())
|
dump.P(err.Error())
|
||||||
// http.Error(w, "Invalid state", http.StatusBadRequest)
|
http.Error(w, "Invalid state", http.StatusBadRequest)
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
originalPath := app.SessionManager.GetString(r.Context(), "original_path")
|
dump.P("Original_Path: " + originalURL)
|
||||||
|
// originalPath := appData.SessionManager.GetString(r.Context(), "original_path")
|
||||||
|
|
||||||
authName := c.GetAuthNameByDomain(r.Host)
|
authName := configData.GetAuthNameByDomain(r.Host)
|
||||||
token, fullResponse, e := exchangeCode(code, verifier, c, authName)
|
token, fullResponse, e := exchangeCode(code, verifier, authName)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
dump.Println("exchangeCode: " + e.Error())
|
dump.Println("exchangeCode: " + e.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
app.SessionManager.Put(r.Context(), "access_token", token.AccessToken)
|
appData.SessionManager.Put(r.Context(), "access_token", token.AccessToken)
|
||||||
app.SessionManager.Put(r.Context(), "full_token", fullResponse)
|
appData.SessionManager.Put(r.Context(), "full_token", fullResponse)
|
||||||
|
|
||||||
// SetAuthHeader(w, token.AccessToken)
|
// SetAuthHeader(w, token.AccessToken)
|
||||||
http.Redirect(w, r, originalPath, http.StatusFound)
|
// http.Redirect(w, r, originalPath, http.StatusFound)
|
||||||
// http.Redirect(w, r, originalURL, http.StatusFound)
|
http.Redirect(w, r, originalURL, http.StatusFound)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
config.Wrapper(func(c *config.Config) {
|
configData := config.Get()
|
||||||
|
|
||||||
//TODO: only after returninig, delete the session!
|
//TODO: only after returninig, delete the session!
|
||||||
app.SessionManager.Remove(r.Context(), "access_token")
|
appData.SessionManager.Remove(r.Context(), "access_token")
|
||||||
app.SessionManager.Remove(r.Context(), "full_token")
|
appData.SessionManager.Remove(r.Context(), "full_token")
|
||||||
|
|
||||||
authName := c.DataMaps.DomainToAuth[r.Host]
|
authName := configData.DataMaps.DomainToAuth[r.Host]
|
||||||
a := c.Auth[authName]
|
a := configData.AuthMap[authName]
|
||||||
u := a.OpenID.EndPoints.Logout
|
u := a.OpenID.EndPoints.Logout
|
||||||
http.Redirect(w, r, u, http.StatusFound)
|
http.Redirect(w, r, u, http.StatusFound)
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
config.Wrapper(func(c *config.Config) {
|
configData := config.Get()
|
||||||
|
|
||||||
authName := c.DataMaps.DomainToAuth[r.Host]
|
authName := configData.DataMaps.DomainToAuth[r.Host]
|
||||||
|
|
||||||
// state := helper.RandStringByBits(64)
|
// state := helper.RandStringByBits(64)
|
||||||
nonce := helper.RandStringByBits(64)
|
nonce := helper.RandStringByBits(64)
|
||||||
authURL, _ := url.Parse(c.Auth[authName].OpenID.EndPoints.Auth)
|
authURL, _ := url.Parse(configData.AuthMap[authName].OpenID.EndPoints.Auth)
|
||||||
query := authURL.Query()
|
query := authURL.Query()
|
||||||
|
|
||||||
codeVerifier, _ := generateCodeVerifier()
|
codeVerifier, _ := generateCodeVerifier()
|
||||||
codeChallenge := generateCodeChallenge(codeVerifier)
|
codeChallenge := generateCodeChallenge(codeVerifier)
|
||||||
|
|
||||||
originalPath := app.SessionManager.GetString(r.Context(), "original_path")
|
originalPath := appData.SessionManager.GetString(r.Context(), "original_path")
|
||||||
state := generateState(url.QueryEscape(originalPath))
|
state := generateState(url.QueryEscape(originalPath))
|
||||||
query.Set("client_id", c.Auth[authName].OpenID.ClientID)
|
query.Set("client_id", configData.AuthMap[authName].OpenID.ClientID)
|
||||||
query.Set("response_type", "code")
|
query.Set("response_type", "code")
|
||||||
query.Set("scope", "openid")
|
query.Set("scope", "openid")
|
||||||
query.Set("redirect_uri", c.Auth[authName].OpenID.RedirectURI)
|
query.Set("redirect_uri", configData.AuthMap[authName].OpenID.RedirectURI)
|
||||||
query.Set("code_challenge", codeChallenge)
|
query.Set("code_challenge", codeChallenge)
|
||||||
query.Set("code_challenge_method", "S256")
|
query.Set("code_challenge_method", "S256")
|
||||||
query.Set("state", state)
|
query.Set("state", state)
|
||||||
query.Set("nonce", nonce)
|
query.Set("nonce", nonce)
|
||||||
authURL.RawQuery = query.Encode()
|
authURL.RawQuery = query.Encode()
|
||||||
app.SessionManager.Put(r.Context(), "state", state)
|
appData.SessionManager.Put(r.Context(), "state", state)
|
||||||
app.SessionManager.Put(r.Context(), "code_verifier", codeVerifier)
|
appData.SessionManager.Put(r.Context(), "code_verifier", codeVerifier)
|
||||||
http.Redirect(w, r, authURL.String(), http.StatusFound)
|
http.Redirect(w, r, authURL.String(), http.StatusFound)
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,39 +36,46 @@ type EntryPoint struct {
|
||||||
type ReverseProxies map[string]ReverseProxy
|
type ReverseProxies map[string]ReverseProxy
|
||||||
type ReverseProxy *httputil.ReverseProxy
|
type ReverseProxy *httputil.ReverseProxy
|
||||||
|
|
||||||
var app = logic.NewApp()
|
var (
|
||||||
|
appData *logic.App = logic.NewApp()
|
||||||
|
|
||||||
|
// configData *config.Config
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
helper.AppRunner(func() {
|
helper.AppRunner(func() {
|
||||||
config.Wrapper(func(c *config.Config) {
|
configData := config.Get()
|
||||||
|
//////////TESTING AREA//////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
groups := logic.NewGroups()
|
groups := logic.NewGroups()
|
||||||
mainRouter := router.New()
|
mainRouter := router.New()
|
||||||
groups.ForEach(func(k string, g *logic.Group) {
|
groups.ForEach(func(groupName string, g *logic.Group) {
|
||||||
groupSubRouter := mainRouter.Mux.NewRoute().Subrouter()
|
mainRouter.AddGroupRouter(groupName)
|
||||||
groupSubRouter.Use(Domain_Middleware)
|
mainRouter.GetGroupRouter(groupName).Mux.Use(Domain_Middleware)
|
||||||
for k := range g.ReverseProxies {
|
for k := range g.ReverseProxies {
|
||||||
rpConfig := c.ReverseProxies[k]
|
rpConfig := configData.ReverseProxies[k]
|
||||||
domain := rpConfig.Domain
|
domain := rpConfig.Domain
|
||||||
proxy := reverse_proxy.New(rpConfig.Host)
|
proxy := reverse_proxy.New(rpConfig.Host)
|
||||||
proxy.Name = domain
|
proxy.Name = domain
|
||||||
newRoute := groupSubRouter.NewRoute()
|
mainRouter.AddHostSubRouter(groupName, domain)
|
||||||
subRouter := newRoute.Host(domain).Subrouter()
|
|
||||||
if rpConfig.Auth != "" {
|
if rpConfig.Auth != "" {
|
||||||
if _, ok := c.Auth[rpConfig.Auth]; !ok {
|
if _, ok := configData.AuthMap[rpConfig.Auth]; !ok {
|
||||||
err := errors.New("Error: Auth " + rpConfig.Auth + " not exist!")
|
err := errors.New("Error: Auth " + rpConfig.Auth + " not exist!")
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
pths := c.Auth[rpConfig.Auth].Paths
|
pths := configData.AuthMap[rpConfig.Auth].Paths
|
||||||
authRoute := subRouter.NewRoute()
|
hostRouterMux := mainRouter.GetHostSubRouter(groupName, domain).Mux
|
||||||
subRouter.Use(Middleware_SetHeaders)
|
hostRouterMux.Use(Middleware_SetHeaders)
|
||||||
|
hostRouterMux.Use(authMiddleware)
|
||||||
|
|
||||||
|
authRoute := hostRouterMux.NewRoute()
|
||||||
authSubRouter := authRoute.PathPrefix(pths.Prefix).Subrouter()
|
authSubRouter := authRoute.PathPrefix(pths.Prefix).Subrouter()
|
||||||
authSubRouter.Path(pths.Login).Handler(http.HandlerFunc(LoginHandler))
|
authSubRouter.Path(pths.Login).Handler(http.HandlerFunc(LoginHandler))
|
||||||
authSubRouter.Path(pths.Logout).Handler(http.HandlerFunc(LogoutHandler))
|
authSubRouter.Path(pths.Logout).Handler(http.HandlerFunc(LogoutHandler))
|
||||||
authSubRouter.Path(pths.Callback).Handler(http.HandlerFunc(CallbackHandler))
|
authSubRouter.Path(pths.Callback).Handler(http.HandlerFunc(CallbackHandler))
|
||||||
subRouter.Use(authMiddleware)
|
|
||||||
}
|
}
|
||||||
subRouter.PathPrefix("/").Handler(proxy.Httputil)
|
mainRouter.GetHostSubRouter(groupName, domain).Mux.PathPrefix("/").Handler(proxy.Httputil)
|
||||||
|
|
||||||
// Filter out static file requests first
|
// Filter out static file requests first
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -79,11 +86,11 @@ func main() {
|
||||||
GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
// crt, key := "", ""
|
// crt, key := "", ""
|
||||||
|
|
||||||
crt, key := c.GetCertsPairByDomain(info.ServerName)
|
crt, key := configData.GetCertsPairByDomain(info.ServerName)
|
||||||
|
|
||||||
if crt == "" && key == "" {
|
if crt == "" && key == "" {
|
||||||
// crt = c.TLS.Certs["default"].Cert
|
// crt = configData.TLS.Certs["default"].Cert
|
||||||
// key = c.TLS.Certs["default"].Key
|
// key = configData.TLS.Certs["default"].Key
|
||||||
// panic("Error: TLS cert and key not found!")
|
// panic("Error: TLS cert and key not found!")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +103,7 @@ func main() {
|
||||||
}
|
}
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: ":" + g.Port,
|
Addr: ":" + g.Port,
|
||||||
Handler: app.SessionManager.LoadAndSave(groupSubRouter),
|
Handler: appData.SessionManager.LoadAndSave(mainRouter.GetGroupRouter(groupName).Mux),
|
||||||
TLSConfig: tlsConfig,
|
TLSConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -115,8 +122,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
helper.StartTestHTTPServer(3000)
|
helper.StartTestHTTPServer(3000, "app")
|
||||||
})
|
helper.StartTestHTTPServer(3001, "oded")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,18 +137,19 @@ func main() {
|
||||||
|
|
||||||
func authMiddleware(next http.Handler) http.Handler {
|
func authMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
configData := config.Get()
|
||||||
config.Wrapper(func(c *config.Config) {
|
|
||||||
currentPath := r.URL.Path
|
currentPath := r.URL.Path
|
||||||
authName := c.GetAuthNameByDomain(r.Host)
|
authName := configData.GetAuthNameByDomain(r.Host)
|
||||||
loginPath := c.Auth[authName].Paths.Prefix + c.Auth[authName].Paths.Login
|
loginPath := configData.AuthMap[authName].Paths.Prefix + configData.AuthMap[authName].Paths.Login
|
||||||
logoutPath := c.Auth[authName].Paths.Prefix + c.Auth[authName].Paths.Logout
|
logoutPath := configData.AuthMap[authName].Paths.Prefix + configData.AuthMap[authName].Paths.Logout
|
||||||
callbackPath := c.Auth[authName].Paths.Prefix + c.Auth[authName].Paths.Callback
|
callbackPath := configData.AuthMap[authName].Paths.Prefix + configData.AuthMap[authName].Paths.Callback
|
||||||
// TODO: mark auth reverse proxy in yaml
|
// TODO: mark auth reverse proxy in yaml
|
||||||
|
proxyName := configData.GetProxyNameByDomain(r.Host)
|
||||||
if r.Host == "keycloak.z.com" {
|
if configData.ReverseProxies[proxyName].IsAuthServer {
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch currentPath {
|
switch currentPath {
|
||||||
case loginPath:
|
case loginPath:
|
||||||
{
|
{
|
||||||
|
|
@ -163,14 +171,15 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
||||||
accessToken := app.SessionManager.GetString(r.Context(), "access_token")
|
accessToken := appData.SessionManager.GetString(r.Context(), "access_token")
|
||||||
if accessToken == "" {
|
if accessToken == "" {
|
||||||
authName := c.DataMaps.DomainToAuth[r.Host]
|
|
||||||
http.Redirect(w, r, c.Auth[authName].Paths.Prefix+c.Auth[authName].Paths.Login, http.StatusFound)
|
authName := configData.DataMaps.DomainToAuth[r.Host]
|
||||||
|
http.Redirect(w, r, configData.AuthMap[authName].Paths.Prefix+configData.AuthMap[authName].Paths.Login, http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// auth.SetAuthHeader(w, accessToken)
|
// auth.SetAuthHeader(w, accessToken)
|
||||||
a := c.Auth[authName]
|
a := configData.AuthMap[authName]
|
||||||
pths := a.Paths
|
pths := a.Paths
|
||||||
prefix := pths.Prefix
|
prefix := pths.Prefix
|
||||||
login := pths.Login
|
login := pths.Login
|
||||||
|
|
@ -182,7 +191,8 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||||
// return
|
// return
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenOk := IsAuthorizedJWT(accessToken, c, "default")
|
tokenOk := IsAuthorizedJWT(accessToken, authName)
|
||||||
|
|
||||||
if !tokenOk {
|
if !tokenOk {
|
||||||
http.Redirect(w, r, loginPath, http.StatusFound)
|
http.Redirect(w, r, loginPath, http.StatusFound)
|
||||||
return
|
return
|
||||||
|
|
@ -191,7 +201,6 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,8 +209,8 @@ func Domain_Middleware(next http.Handler) http.Handler {
|
||||||
// c := config.Get()
|
// c := config.Get()
|
||||||
|
|
||||||
// requestedPath := r.URL.Path
|
// requestedPath := r.URL.Path
|
||||||
// authName := c.GetAuthNameByDomain(r.Host)
|
// authName := configData.GetAuthNameByDomain(r.Host)
|
||||||
// auth := c.Auth[authName]
|
// auth := configData.AuthMap[authName]
|
||||||
// excludedPaths := []string{
|
// excludedPaths := []string{
|
||||||
// auth.Paths.Prefix + auth.Paths.Login,
|
// auth.Paths.Prefix + auth.Paths.Login,
|
||||||
// auth.Paths.Prefix + auth.Paths.Callback,
|
// auth.Paths.Prefix + auth.Paths.Callback,
|
||||||
|
|
@ -210,7 +219,7 @@ func Domain_Middleware(next http.Handler) http.Handler {
|
||||||
// contains := helper.IsSliceContains(excludedPaths, requestedPath)
|
// contains := helper.IsSliceContains(excludedPaths, requestedPath)
|
||||||
// contains := slices.Contains(excludedPaths, requestedPath)
|
// contains := slices.Contains(excludedPaths, requestedPath)
|
||||||
// if !contains {
|
// if !contains {
|
||||||
// app.SessionManager.Put(r.Context(), "original_path", requestedPath)
|
// appData.SessionManager.Put(r.Context(), "original_path", requestedPath)
|
||||||
// }
|
// }
|
||||||
// dump.P(requestedPath)
|
// dump.P(requestedPath)
|
||||||
|
|
||||||
|
|
@ -303,12 +312,22 @@ func decodeState(encodedState string) (string, error) {
|
||||||
}
|
}
|
||||||
return stateData["redirect_uri"], nil
|
return stateData["redirect_uri"], nil
|
||||||
}
|
}
|
||||||
func exchangeCode(code string, verifier string, c *config.Config, authName string) (*TokenResponse, string, error) {
|
|
||||||
|
func exchangeCode(code string, verifier string, authName string) (*TokenResponse, string, error) {
|
||||||
|
configData := config.Get()
|
||||||
|
clientID := configData.AuthMap[authName].OpenID.ClientID
|
||||||
|
clientSecert := configData.AuthMap[authName].OpenID.ClientSecert
|
||||||
|
redirectURI := configData.AuthMap[authName].OpenID.RedirectURI
|
||||||
|
// if strings.Contains(redirectURI,"<{{dynamic}}>") {
|
||||||
|
// configData.GenerateDynamicRedirectUri()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GenerateDynamicRedirectUri
|
||||||
data := url.Values{}
|
data := url.Values{}
|
||||||
data.Set("grant_type", "authorization_code")
|
data.Set("grant_type", "authorization_code")
|
||||||
data.Set("client_id", c.Auth[authName].OpenID.ClientID)
|
data.Set("client_id", clientID)
|
||||||
data.Set("client_secret", c.Auth[authName].OpenID.ClientSecert)
|
data.Set("client_secret", clientSecert)
|
||||||
data.Set("redirect_uri", c.Auth[authName].OpenID.RedirectURI)
|
data.Set("redirect_uri", redirectURI)
|
||||||
data.Set("code", code)
|
data.Set("code", code)
|
||||||
data.Set("scope", "openid zapp")
|
data.Set("scope", "openid zapp")
|
||||||
if verifier != "" {
|
if verifier != "" {
|
||||||
|
|
@ -318,7 +337,7 @@ func exchangeCode(code string, verifier string, c *config.Config, authName strin
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: DEVELOPMENT},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: DEVELOPMENT},
|
||||||
}
|
}
|
||||||
client := &http.Client{Transport: tr}
|
client := &http.Client{Transport: tr}
|
||||||
u := c.Auth[authName].OpenID.EndPoints.Token
|
u := configData.AuthMap[authName].OpenID.EndPoints.Token
|
||||||
r, _ := http.NewRequest(http.MethodPost, u, strings.NewReader(data.Encode()))
|
r, _ := http.NewRequest(http.MethodPost, u, strings.NewReader(data.Encode()))
|
||||||
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
resp, err := client.Do(r)
|
resp, err := client.Do(r)
|
||||||
|
|
@ -358,7 +377,9 @@ func generateCodeChallenge(verifier string) string {
|
||||||
return base64.RawURLEncoding.EncodeToString(hash[:])
|
return base64.RawURLEncoding.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsAuthorizedJWT(rawAccessToken string, c *config.Config, authName string) bool {
|
func IsAuthorizedJWT(rawAccessToken string, authName string) bool {
|
||||||
|
configData := config.Get()
|
||||||
|
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
}
|
}
|
||||||
|
|
@ -367,14 +388,14 @@ func IsAuthorizedJWT(rawAccessToken string, c *config.Config, authName string) b
|
||||||
Transport: tr,
|
Transport: tr,
|
||||||
}
|
}
|
||||||
ctx := oidc.ClientContext(context.Background(), client)
|
ctx := oidc.ClientContext(context.Background(), client)
|
||||||
provider, err := oidc.NewProvider(ctx, c.Auth[authName].OpenID.EndPoints.Issuer)
|
provider, err := oidc.NewProvider(ctx, configData.AuthMap[authName].OpenID.EndPoints.Issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dump.Println("authorisation failed while getting the provider: " + err.Error())
|
dump.Println("authorisation failed while getting the provider: " + err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
oidcConfig := &oidc.Config{
|
oidcConfig := &oidc.Config{
|
||||||
ClientID: c.Auth[authName].OpenID.ClientID,
|
ClientID: configData.AuthMap[authName].OpenID.ClientID,
|
||||||
}
|
}
|
||||||
verifier := provider.Verifier(oidcConfig)
|
verifier := provider.Verifier(oidcConfig)
|
||||||
idToken, err := verifier.Verify(ctx, rawAccessToken)
|
idToken, err := verifier.Verify(ctx, rawAccessToken)
|
||||||
|
|
@ -394,22 +415,22 @@ func IsAuthorizedJWT(rawAccessToken string, c *config.Config, authName string) b
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
|
||||||
func isStaticFileRequest(path string) bool {
|
// func isStaticFileRequest(path string) bool {
|
||||||
// Check for common static file prefixes
|
// // Check for common static file prefixes
|
||||||
if strings.HasPrefix(path, "/static/") || strings.HasPrefix(path, "/assets/") {
|
// if strings.HasPrefix(path, "/static/") || strings.HasPrefix(path, "/assets/") {
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Check for common static file extensions
|
// // Check for common static file extensions
|
||||||
staticExtensions := []string{
|
// staticExtensions := []string{
|
||||||
".css", ".js", ".jpg", ".jpeg", ".png", ".gif", ".svg", ".ico",
|
// ".css", ".js", ".jpg", ".jpeg", ".png", ".gif", ".svg", ".ico",
|
||||||
}
|
// }
|
||||||
|
|
||||||
for _, ext := range staticExtensions {
|
// for _, ext := range staticExtensions {
|
||||||
if strings.HasSuffix(path, ext) {
|
// if strings.HasSuffix(path, ext) {
|
||||||
return true
|
// return true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
44
config.yml
44
config.yml
|
|
@ -8,7 +8,6 @@ reverse_proxies:
|
||||||
enabled: true
|
enabled: true
|
||||||
certs: default
|
certs: default
|
||||||
auth_server: true
|
auth_server: true
|
||||||
|
|
||||||
app:
|
app:
|
||||||
domain: app.z.com
|
domain: app.z.com
|
||||||
host: http://127.0.0.1:3000
|
host: http://127.0.0.1:3000
|
||||||
|
|
@ -16,7 +15,16 @@ reverse_proxies:
|
||||||
tls:
|
tls:
|
||||||
enabled: true
|
enabled: true
|
||||||
certs: default
|
certs: default
|
||||||
auth: default
|
auth: app_auth
|
||||||
|
oded:
|
||||||
|
domain: oded.z.com
|
||||||
|
host: http://127.0.0.1:3001
|
||||||
|
entry_point: https
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
certs: default
|
||||||
|
auth: oded_auth
|
||||||
|
|
||||||
|
|
||||||
tls:
|
tls:
|
||||||
certs:
|
certs:
|
||||||
|
|
@ -32,7 +40,7 @@ entry_points:
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
default:
|
app_auth:
|
||||||
paths:
|
paths:
|
||||||
prefix: /auth
|
prefix: /auth
|
||||||
login: /login
|
login: /login
|
||||||
|
|
@ -43,19 +51,25 @@ auth:
|
||||||
realm: dev
|
realm: dev
|
||||||
client_id: dev_client
|
client_id: dev_client
|
||||||
client_secret: dWhSJgARBAuBAXN7sUTpqpIq2sKQdugs
|
client_secret: dWhSJgARBAuBAXN7sUTpqpIq2sKQdugs
|
||||||
redirect_uri: https://app.z.com/auth/callback
|
redirect_uri: <{{dynamic}}>/auth/callback
|
||||||
post_logout_redirect_uri: https://app.z.com/auth/logout
|
post_logout_redirect_uri: https://app.z.com/auth/logout
|
||||||
config_path: /realms/{{realm}}/.well-known/openid-configuration
|
config_path: /realms/<{{realm}}>/.well-known/openid-configuration
|
||||||
# config_fields:
|
oded_auth:
|
||||||
# - issuer
|
paths:
|
||||||
# - authorization_endpoint
|
prefix: /auth
|
||||||
# - token_endpoint
|
login: /login
|
||||||
# - introspection_endpoint
|
logout: /logout
|
||||||
# - userinfo_endpoint
|
callback: /callback
|
||||||
# - end_session_endpoint
|
open_id:
|
||||||
# - jwks_uri
|
host: http://127.0.0.1:8080
|
||||||
# issuer: http://127.0.0.1:8080/realms/dev
|
realm: dev
|
||||||
|
client_id: dev_client
|
||||||
|
client_secret: dWhSJgARBAuBAXN7sUTpqpIq2sKQdugs
|
||||||
|
# redirect_uri: https://oded.z.com/auth/callback
|
||||||
|
redirect_uri: <{{dynamic}}>/auth/callback
|
||||||
|
post_logout_redirect_uri: https://oded.z.com/auth/logout
|
||||||
|
# post_logout_redirect_uri: <{{dynamic}}>/auth/logout
|
||||||
|
config_path: /realms/<{{realm}}>/.well-known/openid-configuration
|
||||||
|
|
||||||
|
|
||||||
# scope: openid profile email
|
# scope: openid profile email
|
||||||
|
|
|
||||||
|
|
@ -15,20 +15,28 @@ const Viper_File_Name string = "config"
|
||||||
const Viper_File_Type string = "yaml"
|
const Viper_File_Type string = "yaml"
|
||||||
const Viper_File_Path string = "."
|
const Viper_File_Path string = "."
|
||||||
|
|
||||||
var c *Config
|
var (
|
||||||
|
configData *Config
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
helper.New().Screen.Clear()
|
h := helper.New()
|
||||||
c = createConfig()
|
h.Screen.Clear()
|
||||||
|
configData = createConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Wrapper(fn func(c *Config)) {
|
func Wrapper(fn func(c *Config)) {
|
||||||
fn(c)
|
fn(configData)
|
||||||
}
|
}
|
||||||
func Get() *Config {
|
func Get() *Config {
|
||||||
return c
|
|
||||||
|
return configData
|
||||||
|
}
|
||||||
|
func Get2() *Config {
|
||||||
|
return configData
|
||||||
}
|
}
|
||||||
func createConfig() *Config {
|
func createConfig() *Config {
|
||||||
|
|
||||||
c := &Config{}
|
c := &Config{}
|
||||||
c.initViper()
|
c.initViper()
|
||||||
c.setViperOptions(Viper_File_Name, Viper_File_Type, Viper_File_Path)
|
c.setViperOptions(Viper_File_Name, Viper_File_Type, Viper_File_Path)
|
||||||
|
|
@ -76,6 +84,19 @@ func (rp *ReverseProxies) ForEach(fn func(rpName string, rpConfig *ReverseProxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rp *ReverseProxies) ForEachReturn(fn func(rpName string, rpConfig *ReverseProxy) (res ForEachReturn)) *ForEachReturn {
|
||||||
|
res := ForEachReturn{}
|
||||||
|
for rpName, rpData := range *rp {
|
||||||
|
res = append(fn(rpName, &rpData), res)
|
||||||
|
}
|
||||||
|
return &res
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (rp AuthMap) ForEach(fn func(authName string, authConfig Auth)) {
|
||||||
|
// for authName, authConfig := range rp {
|
||||||
|
// fn(authName, authConfig)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
func (c *Config) fetchEndPointsByAuthName(authName string) map[string]any {
|
func (c *Config) fetchEndPointsByAuthName(authName string) map[string]any {
|
||||||
configURL := c.KeycloakWellknownURL(authName)
|
configURL := c.KeycloakWellknownURL(authName)
|
||||||
resp := helper.IsFetchOK[EndPoints](configURL, "", http.Get)
|
resp := helper.IsFetchOK[EndPoints](configURL, "", http.Get)
|
||||||
|
|
@ -89,10 +110,10 @@ func (c *Config) fetchEndPointsByAuthName(authName string) map[string]any {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) initOpenIDEndPoints() {
|
func (c *Config) initOpenIDEndPoints() {
|
||||||
for authName := range c.Auth {
|
for authName := range c.AuthMap {
|
||||||
data := c.fetchEndPointsByAuthName(authName)
|
data := c.fetchEndPointsByAuthName(authName)
|
||||||
|
|
||||||
c.Auth[authName].OpenID.EndPoints = &EndPoints{
|
c.AuthMap[authName].OpenID.EndPoints = &EndPoints{
|
||||||
Issuer: data["issuer"].(string),
|
Issuer: data["issuer"].(string),
|
||||||
Auth: data["authorization_endpoint"].(string),
|
Auth: data["authorization_endpoint"].(string),
|
||||||
Introspection: data["introspection_endpoint"].(string),
|
Introspection: data["introspection_endpoint"].(string),
|
||||||
|
|
@ -107,17 +128,35 @@ func (c *Config) initOpenIDEndPoints() {
|
||||||
}
|
}
|
||||||
func (c *Config) KeycloakWellknownURL(authName string) string {
|
func (c *Config) KeycloakWellknownURL(authName string) string {
|
||||||
|
|
||||||
if _, ok := c.Auth[authName]; !ok {
|
if _, ok := c.AuthMap[authName]; !ok {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
hostUrl := c.Auth[authName].OpenID.Host
|
hostUrl := c.AuthMap[authName].OpenID.Host
|
||||||
realm := c.Auth[authName].OpenID.Realm
|
realm := c.AuthMap[authName].OpenID.Realm
|
||||||
configPath := c.Auth[authName].OpenID.ConfigPath
|
configPath := c.AuthMap[authName].OpenID.ConfigPath
|
||||||
u := hostUrl
|
u := hostUrl
|
||||||
u += strings.ReplaceAll(configPath, "{{realm}}", realm)
|
u += strings.ReplaceAll(configPath, "<{{realm}}>", realm)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) GenerateDynamicRedirectUri(proxyName string, authName string) string {
|
||||||
|
if _, ok := c.AuthMap[authName]; !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
proto := "http"
|
||||||
|
|
||||||
|
domain := c.ReverseProxies[proxyName].Domain
|
||||||
|
tls := c.ReverseProxies[proxyName].TLS.Enabled
|
||||||
|
if tls {
|
||||||
|
proto = "https"
|
||||||
|
}
|
||||||
|
redirectURI := c.AuthMap[authName].OpenID.RedirectURI
|
||||||
|
u := redirectURI
|
||||||
|
u = strings.ReplaceAll(redirectURI, "<{{dynamic}}>", proto+"://"+domain)
|
||||||
|
|
||||||
|
return u
|
||||||
|
}
|
||||||
func (c *Config) initDomainToProxyNameMap() {
|
func (c *Config) initDomainToProxyNameMap() {
|
||||||
mp := make(map[string]string)
|
mp := make(map[string]string)
|
||||||
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
||||||
|
|
@ -126,17 +165,22 @@ func (c *Config) initDomainToProxyNameMap() {
|
||||||
c.DataMaps.DomainToProxy = mp
|
c.DataMaps.DomainToProxy = mp
|
||||||
}
|
}
|
||||||
func (c *Config) initDomainToProxyAuthName() {
|
func (c *Config) initDomainToProxyAuthName() {
|
||||||
|
|
||||||
authMap := map[string]int{}
|
authMap := map[string]int{}
|
||||||
for authName := range c.Auth {
|
for authName := range c.AuthMap {
|
||||||
authMap[authName] = 1
|
authMap[authName] = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
mp := make(map[string]string)
|
mp := make(map[string]string)
|
||||||
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
||||||
if v, ok := authMap[rpConfig.Auth]; ok && v == 1 {
|
if v, ok := authMap[rpConfig.Auth]; ok && v == 1 {
|
||||||
mp[rpConfig.Domain] = rpConfig.Auth
|
mp[rpConfig.Domain] = rpConfig.Auth
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
c.DataMaps.DomainToAuth = mp
|
c.DataMaps.DomainToAuth = mp
|
||||||
|
|
||||||
}
|
}
|
||||||
func (c *Config) initDomainToCertName() {
|
func (c *Config) initDomainToCertName() {
|
||||||
crtMap := map[string]int{}
|
crtMap := map[string]int{}
|
||||||
|
|
@ -155,6 +199,7 @@ func (c *Config) initDomainToCertName() {
|
||||||
func (c *Config) GetAuthNameByDomain(domain string) string {
|
func (c *Config) GetAuthNameByDomain(domain string) string {
|
||||||
return c.DataMaps.DomainToAuth[domain]
|
return c.DataMaps.DomainToAuth[domain]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetProxyNameByDomain(domain string) string {
|
func (c *Config) GetProxyNameByDomain(domain string) string {
|
||||||
return c.DataMaps.DomainToProxy[domain]
|
return c.DataMaps.DomainToProxy[domain]
|
||||||
}
|
}
|
||||||
|
|
@ -174,5 +219,25 @@ func (c *Config) GetCertsPairByDomain(domain string) (string, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return crt, key
|
return crt, key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetProxiesSliceByAuthName(authName string) []string {
|
||||||
|
slc := &[]string{}
|
||||||
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
||||||
|
isOK := true
|
||||||
|
if authName != rpConfig.Auth {
|
||||||
|
isOK = false
|
||||||
|
}
|
||||||
|
if _, ok := c.AuthMap[authName]; !ok {
|
||||||
|
isOK = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isOK {
|
||||||
|
helper.AppendToPointer(slc, rpName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return *slc
|
||||||
|
}
|
||||||
|
func (c *Config) GetAuthNameByProxyName(proxyName string) string {
|
||||||
|
return c.ReverseProxies[proxyName].Auth
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
import "github.com/spf13/viper"
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Viper *viper.Viper
|
|
||||||
DataMaps DataMaps
|
|
||||||
ReverseProxies ReverseProxies `mapstructure:"reverse_proxies"`
|
|
||||||
TLS TLS `mapstructure:"tls"`
|
|
||||||
EntryPoints EntryPoints `mapstructure:"entry_points"`
|
|
||||||
Auth map[string]*AuthInstance `mapstructure:"auth"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DataMaps struct {
|
|
||||||
DomainToProxy map[string]string
|
|
||||||
DomainToAuth map[string]string
|
|
||||||
DomainToCert map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// AUTH
|
|
||||||
// type Auth map[string]AuthInstance
|
|
||||||
|
|
||||||
type AuthInstance struct {
|
|
||||||
Paths Paths `mapstructure:"paths"`
|
|
||||||
OpenID OpenID `mapstructure:"open_id"`
|
|
||||||
}
|
|
||||||
type Paths struct {
|
|
||||||
Prefix string `mapstructure:"prefix"`
|
|
||||||
Login string `mapstructure:"login"`
|
|
||||||
Logout string `mapstructure:"logout"`
|
|
||||||
Callback string `mapstructure:"callback"`
|
|
||||||
}
|
|
||||||
type OpenID struct {
|
|
||||||
Host string `mapstructure:"host"`
|
|
||||||
Realm string `mapstructure:"realm"`
|
|
||||||
ClientID string `mapstructure:"client_id"`
|
|
||||||
ClientSecert string `mapstructure:"client_secret"`
|
|
||||||
RedirectURI string `mapstructure:"redirect_uri"`
|
|
||||||
PostLogoutRedirectURI string `mapstructure:"post_logout_redirect_uri"`
|
|
||||||
ConfigPath string `mapstructure:"config_path"`
|
|
||||||
EndPoints *EndPoints
|
|
||||||
}
|
|
||||||
|
|
||||||
type EndPoints struct {
|
|
||||||
Issuer string
|
|
||||||
Auth string
|
|
||||||
Introspection string
|
|
||||||
Token string
|
|
||||||
UserInfo string
|
|
||||||
Logout string
|
|
||||||
JwksUri string
|
|
||||||
}
|
|
||||||
|
|
||||||
// type OpenIdEndPoints struct {
|
|
||||||
// Issuer string
|
|
||||||
// Authorization string
|
|
||||||
// Token string
|
|
||||||
// Introspection string
|
|
||||||
// UserInfo string
|
|
||||||
// EndSession string
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ReverseProxies
|
|
||||||
|
|
||||||
type ReverseProxies map[string]ReverseProxy
|
|
||||||
|
|
||||||
type ReverseProxy struct {
|
|
||||||
Domain string `mapstructure:"domain"`
|
|
||||||
Host string `mapstructure:"host"`
|
|
||||||
EntryPoint string `mapstructure:"entry_point"`
|
|
||||||
TLS TLS_RP `mapstructure:"tls"`
|
|
||||||
Auth string `mapstructure:"auth"`
|
|
||||||
}
|
|
||||||
type TLS_RP struct {
|
|
||||||
Enabled bool `mapstructure:"enabled"`
|
|
||||||
Certs string `mapstructure:"certs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TLS
|
|
||||||
type TLS struct {
|
|
||||||
Certs map[string]Certs `mapstructure:"certs"`
|
|
||||||
}
|
|
||||||
type Certs struct {
|
|
||||||
Cert string `mapstructure:"cert"`
|
|
||||||
Key string `mapstructure:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EntryPoints
|
|
||||||
type EntryPoints map[string]EntryPoint
|
|
||||||
type EntryPoint struct {
|
|
||||||
Port string `mapstructure:"port"`
|
|
||||||
TLS bool `mapstructure:"tls"`
|
|
||||||
}
|
|
||||||
36
internal/config/types_auth_.go
Normal file
36
internal/config/types_auth_.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type AuthMap map[string]*Auth
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
Paths Paths `mapstructure:"paths"`
|
||||||
|
OpenID OpenID `mapstructure:"open_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Paths struct {
|
||||||
|
Prefix string `mapstructure:"prefix"`
|
||||||
|
Login string `mapstructure:"login"`
|
||||||
|
Logout string `mapstructure:"logout"`
|
||||||
|
Callback string `mapstructure:"callback"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenID struct {
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
Realm string `mapstructure:"realm"`
|
||||||
|
ClientID string `mapstructure:"client_id"`
|
||||||
|
ClientSecert string `mapstructure:"client_secret"`
|
||||||
|
RedirectURI string `mapstructure:"redirect_uri"`
|
||||||
|
PostLogoutRedirectURI string `mapstructure:"post_logout_redirect_uri"`
|
||||||
|
ConfigPath string `mapstructure:"config_path"`
|
||||||
|
EndPoints *EndPoints
|
||||||
|
}
|
||||||
|
|
||||||
|
type EndPoints struct {
|
||||||
|
Issuer string
|
||||||
|
Auth string
|
||||||
|
Introspection string
|
||||||
|
Token string
|
||||||
|
UserInfo string
|
||||||
|
Logout string
|
||||||
|
JwksUri string
|
||||||
|
}
|
||||||
20
internal/config/types_config.go
Normal file
20
internal/config/types_config.go
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import "github.com/spf13/viper"
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Viper *viper.Viper
|
||||||
|
DataMaps DataMaps
|
||||||
|
ReverseProxies ReverseProxies `mapstructure:"reverse_proxies"`
|
||||||
|
TLS TLS `mapstructure:"tls"`
|
||||||
|
EntryPoints EntryPoints `mapstructure:"entry_points"`
|
||||||
|
AuthMap AuthMap `mapstructure:"auth"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DataMaps struct {
|
||||||
|
DomainToProxy map[string]string
|
||||||
|
DomainToAuth map[string]string
|
||||||
|
DomainToCert map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ForEachReturn []any
|
||||||
8
internal/config/types_entry_points.go
Normal file
8
internal/config/types_entry_points.go
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type EntryPoints map[string]EntryPoint
|
||||||
|
|
||||||
|
type EntryPoint struct {
|
||||||
|
Port string `mapstructure:"port"`
|
||||||
|
TLS bool `mapstructure:"tls"`
|
||||||
|
}
|
||||||
12
internal/config/types_reverse_proxy.go
Normal file
12
internal/config/types_reverse_proxy.go
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type ReverseProxies map[string]ReverseProxy
|
||||||
|
|
||||||
|
type ReverseProxy struct {
|
||||||
|
Domain string `mapstructure:"domain"`
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
EntryPoint string `mapstructure:"entry_point"`
|
||||||
|
TLS TLS_RP `mapstructure:"tls"`
|
||||||
|
Auth string `mapstructure:"auth"`
|
||||||
|
IsAuthServer bool `mapstructure:"auth_server"`
|
||||||
|
}
|
||||||
15
internal/config/types_tls.go
Normal file
15
internal/config/types_tls.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type TLS struct {
|
||||||
|
Certs map[string]Certs `mapstructure:"certs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Certs struct {
|
||||||
|
Cert string `mapstructure:"cert"`
|
||||||
|
Key string `mapstructure:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TLS_RP struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Certs string `mapstructure:"certs"`
|
||||||
|
}
|
||||||
|
|
@ -1,24 +1,77 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import "github.com/gorilla/mux"
|
import (
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"zeevdiukman.com/zprox/pkg/helper"
|
||||||
|
)
|
||||||
|
|
||||||
func New() *MainRouter {
|
func New() *MainRouter {
|
||||||
r := &MainRouter{}
|
r := &MainRouter{}
|
||||||
r.SetMux()
|
r.setMux()
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MainRouter) SetMux() {
|
func (r *MainRouter) setMux() {
|
||||||
r.Mux = mux.NewRouter()
|
r.Mux = mux.NewRouter()
|
||||||
}
|
}
|
||||||
|
func (mainRouter *MainRouter) AddGroupRouter(groupName string) *GroupRouter {
|
||||||
|
s := mainRouter.Mux.NewRoute().Subrouter()
|
||||||
|
groupRouter := &GroupRouter{
|
||||||
|
Mux: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
newMap := make(GroupRouters)
|
||||||
|
helper.MapIter(mainRouter.GroupRouters, func(grName string, gr *GroupRouter) {
|
||||||
|
newMap[grName] = gr
|
||||||
|
})
|
||||||
|
newMap[groupName] = groupRouter
|
||||||
|
|
||||||
|
mainRouter.GroupRouters = newMap
|
||||||
|
return groupRouter
|
||||||
|
}
|
||||||
|
func (mainRouter *MainRouter) GetGroupRouter(groupName string) *GroupRouter {
|
||||||
|
return mainRouter.GroupRouters[groupName]
|
||||||
|
}
|
||||||
|
func (mainRouter *MainRouter) GetHostSubRouter(groupName string, domain string) *SubRouter {
|
||||||
|
return mainRouter.GroupRouters[groupName].SubRouters[domain]
|
||||||
|
}
|
||||||
|
func (mainRouter *MainRouter) AddHostSubRouter(groupName string, domain string) *SubRouter {
|
||||||
|
groupSubRouter := mainRouter.GroupRouters[groupName]
|
||||||
|
newRoute := groupSubRouter.Mux.NewRoute()
|
||||||
|
hostSubRouter := &SubRouter{
|
||||||
|
Mux: newRoute.Host(domain).Subrouter(),
|
||||||
|
}
|
||||||
|
newMap := make(SubRouters)
|
||||||
|
helper.MapIter(mainRouter.GroupRouters[groupName].SubRouters, func(grName string, gr *SubRouter) {
|
||||||
|
newMap[grName] = gr
|
||||||
|
})
|
||||||
|
newMap[domain] = hostSubRouter
|
||||||
|
mainRouter.GroupRouters[groupName].SubRouters = newMap
|
||||||
|
return hostSubRouter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mainRouter *MainRouter) AddGroupSubRouter(groupName string, subRouterName string) *SubRouter {
|
||||||
|
gsr := mainRouter.GetGroupRouter(groupName).Mux.NewRoute().Subrouter()
|
||||||
|
subRouter := &SubRouter{
|
||||||
|
Mux: gsr,
|
||||||
|
}
|
||||||
|
mainRouter.GroupRouters[groupName].SubRouters[subRouterName] = subRouter
|
||||||
|
return subRouter
|
||||||
|
}
|
||||||
|
|
||||||
type MainRouter struct {
|
type MainRouter struct {
|
||||||
Subrouters Subrouters
|
GroupRouters GroupRouters
|
||||||
Mux *mux.Router
|
Mux *mux.Router
|
||||||
}
|
}
|
||||||
type Subrouters map[string]SubRouter
|
|
||||||
type SubRouter struct {
|
type GroupRouters map[string]*GroupRouter
|
||||||
Name string
|
|
||||||
Group string
|
type GroupRouter struct {
|
||||||
*mux.Router
|
SubRouters SubRouters
|
||||||
|
Mux *mux.Router
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubRouters map[string]*SubRouter
|
||||||
|
type SubRouter struct {
|
||||||
|
Mux *mux.Router
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ func CapitalizeFirstLetter(input string) string {
|
||||||
|
|
||||||
return string(runes) // Convert rune slice back to string
|
return string(runes) // Convert rune slice back to string
|
||||||
}
|
}
|
||||||
func MapIter[K comparable, V comparable](m map[K]V, fn func(K, V)) {
|
func MapIter[K string, V any](m map[K]V, fn func(K, V)) {
|
||||||
for p, d := range m {
|
for p, d := range m {
|
||||||
fn(p, d)
|
fn(p, d)
|
||||||
}
|
}
|
||||||
|
|
@ -456,25 +456,25 @@ func AppRunner(runApp func()) {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
//do stuff after ending
|
//do stuff after ending
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
fmt.Println("BYE BYE!")
|
log.Println("AppRunner stopped")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartTestHTTPServer(port int) {
|
func StartTestHTTPServer(port int, name string) {
|
||||||
p := strconv.Itoa(port)
|
p := strconv.Itoa(port)
|
||||||
go func() {
|
go func() {
|
||||||
log.Println("Test server is running at http://" + GetIP() + ":" + p)
|
log.Println("Test server is running at http://" + GetIP() + ":" + p)
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintln(w, "/ OK")
|
fmt.Fprintln(w, r.Host+"/ OK")
|
||||||
})
|
})
|
||||||
r.Path("/test1").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
r.Path("/test1").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintln(w, "/test1 OK")
|
fmt.Fprintln(w, r.Host+"/test1 OK")
|
||||||
})
|
})
|
||||||
r.Path("/test2").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
r.Path("/test2").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintln(w, "/test2 OK")
|
fmt.Fprintln(w, r.Host+"/test2 OK")
|
||||||
})
|
})
|
||||||
err := http.ListenAndServe(":3000", r)
|
err := http.ListenAndServe(":"+p, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -510,3 +510,7 @@ func GetIP(prefix ...string) string {
|
||||||
}
|
}
|
||||||
return prfx
|
return prfx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AppendToPointer[T any](slc *[]T, val T) {
|
||||||
|
*slc = append(*slc, val)
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
BIN
tmp/main
BIN
tmp/main
Binary file not shown.
Loading…
Reference in a new issue