go-zprox/internal/config/config.go
Zeev Diukman fbaf9393ea first
2025-03-02 16:14:03 +00:00

178 lines
4.4 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 c *Config
func init() {
helper.New().Screen.Clear()
c = createConfig()
}
func Wrapper(fn func(c *Config)) {
fn(c)
}
func Get() *Config {
return c
}
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 (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.Auth {
data := c.fetchEndPointsByAuthName(authName)
c.Auth[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.Auth[authName]; !ok {
return ""
}
hostUrl := c.Auth[authName].OpenID.Host
realm := c.Auth[authName].OpenID.Realm
configPath := c.Auth[authName].OpenID.ConfigPath
u := hostUrl
u += strings.ReplaceAll(configPath, "{{realm}}", realm)
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.Auth {
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
}