243 lines
5.8 KiB
Go
243 lines
5.8 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/spf13/viper"
|
|
"zeevdiukman.com/zprox/pkg/helper"
|
|
)
|
|
|
|
const Viper_File_Name string = "config"
|
|
const Viper_File_Type string = "yaml"
|
|
const Viper_File_Path string = "."
|
|
|
|
var (
|
|
configData *Config
|
|
)
|
|
|
|
func init() {
|
|
h := helper.New()
|
|
h.Screen.Clear()
|
|
configData = createConfig()
|
|
}
|
|
|
|
func Wrapper(fn func(c *Config)) {
|
|
fn(configData)
|
|
}
|
|
func Get() *Config {
|
|
|
|
return configData
|
|
}
|
|
func Get2() *Config {
|
|
return configData
|
|
}
|
|
func createConfig() *Config {
|
|
|
|
c := &Config{}
|
|
c.initViper()
|
|
c.setViperOptions(Viper_File_Name, Viper_File_Type, Viper_File_Path)
|
|
c.viperReadYaml()
|
|
c.viperUnmarshalYaml()
|
|
c.initDomainToProxyNameMap()
|
|
c.initDomainToProxyAuthName()
|
|
c.initDomainToCertName()
|
|
c.initOpenIDEndPoints()
|
|
return c
|
|
}
|
|
|
|
func (c *Config) initViper() {
|
|
c.Viper = viper.New()
|
|
}
|
|
|
|
func (c *Config) setViperOptions(fileName string, fileExtention string, filePath string) {
|
|
c.Viper.SetConfigName(fileName)
|
|
c.Viper.SetConfigType(fileExtention)
|
|
c.Viper.AddConfigPath(filePath)
|
|
}
|
|
|
|
func (c *Config) viperReadYaml() {
|
|
err := c.Viper.ReadInConfig()
|
|
if err != nil {
|
|
log.Fatalf("Error reading config file, %s", err)
|
|
}
|
|
}
|
|
func (c *Config) viperUnmarshalYaml() {
|
|
err := c.Viper.Unmarshal(&c)
|
|
if err != nil {
|
|
log.Fatalf("Unable to decode into struct, %v", err)
|
|
}
|
|
}
|
|
|
|
func (eps *EntryPoints) ForEach(fn func(epName string, epConfig *EntryPoint)) {
|
|
for epName, epConfig := range *eps {
|
|
fn(epName, &epConfig)
|
|
}
|
|
}
|
|
|
|
func (rp *ReverseProxies) ForEach(fn func(rpName string, rpConfig *ReverseProxy)) {
|
|
for rpName, rpData := range *rp {
|
|
fn(rpName, &rpData)
|
|
}
|
|
}
|
|
|
|
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 {
|
|
configURL := c.KeycloakWellknownURL(authName)
|
|
resp := helper.IsFetchOK[EndPoints](configURL, "", http.Get)
|
|
respByes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
}
|
|
data := map[string]any{}
|
|
json.Unmarshal(respByes, &data)
|
|
return data
|
|
}
|
|
|
|
func (c *Config) initOpenIDEndPoints() {
|
|
for authName := range c.AuthMap {
|
|
data := c.fetchEndPointsByAuthName(authName)
|
|
|
|
c.AuthMap[authName].OpenID.EndPoints = &EndPoints{
|
|
Issuer: data["issuer"].(string),
|
|
Auth: data["authorization_endpoint"].(string),
|
|
Introspection: data["introspection_endpoint"].(string),
|
|
Token: data["token_endpoint"].(string),
|
|
UserInfo: data["userinfo_endpoint"].(string),
|
|
Logout: data["end_session_endpoint"].(string),
|
|
JwksUri: data["jwks_uri"].(string),
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
func (c *Config) KeycloakWellknownURL(authName string) string {
|
|
|
|
if _, ok := c.AuthMap[authName]; !ok {
|
|
return ""
|
|
}
|
|
hostUrl := c.AuthMap[authName].OpenID.Host
|
|
realm := c.AuthMap[authName].OpenID.Realm
|
|
configPath := c.AuthMap[authName].OpenID.ConfigPath
|
|
u := hostUrl
|
|
u += strings.ReplaceAll(configPath, "<{{realm}}>", realm)
|
|
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() {
|
|
mp := make(map[string]string)
|
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
|
mp[rpConfig.Domain] = rpName
|
|
})
|
|
c.DataMaps.DomainToProxy = mp
|
|
}
|
|
func (c *Config) initDomainToProxyAuthName() {
|
|
|
|
authMap := map[string]int{}
|
|
for authName := range c.AuthMap {
|
|
authMap[authName] = 1
|
|
}
|
|
|
|
mp := make(map[string]string)
|
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
|
if v, ok := authMap[rpConfig.Auth]; ok && v == 1 {
|
|
mp[rpConfig.Domain] = rpConfig.Auth
|
|
|
|
}
|
|
|
|
})
|
|
c.DataMaps.DomainToAuth = mp
|
|
|
|
}
|
|
func (c *Config) initDomainToCertName() {
|
|
crtMap := map[string]int{}
|
|
for crtName := range c.TLS.Certs {
|
|
crtMap[crtName] = 1
|
|
}
|
|
mp := make(map[string]string)
|
|
c.ReverseProxies.ForEach(func(rpName string, rpConfig *ReverseProxy) {
|
|
if v, ok := crtMap[rpConfig.TLS.Certs]; ok && v == 1 {
|
|
mp[rpConfig.Domain] = rpConfig.TLS.Certs
|
|
}
|
|
mp[rpConfig.Domain] = rpConfig.TLS.Certs
|
|
})
|
|
c.DataMaps.DomainToCert = mp
|
|
}
|
|
func (c *Config) GetAuthNameByDomain(domain string) string {
|
|
return c.DataMaps.DomainToAuth[domain]
|
|
}
|
|
|
|
func (c *Config) GetProxyNameByDomain(domain string) string {
|
|
return c.DataMaps.DomainToProxy[domain]
|
|
}
|
|
func (c *Config) GetCertNameByDomain(domain string) string {
|
|
return c.DataMaps.DomainToCert[domain]
|
|
}
|
|
func (c *Config) GetCertsPairByDomain(domain string) (string, string) {
|
|
var crt string
|
|
var key string
|
|
certName := c.DataMaps.DomainToCert[domain]
|
|
crt = c.TLS.Certs[certName].Cert
|
|
key = c.TLS.Certs[certName].Key
|
|
if !(certName != "" && crt == "" && key != "") {
|
|
certName = "default"
|
|
crt = c.TLS.Certs[certName].Cert
|
|
key = c.TLS.Certs[certName].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
|
|
}
|