305 lines
7.6 KiB
Go
305 lines
7.6 KiB
Go
package config
|
|
|
|
import "encoding/json"
|
|
import "errors"
|
|
import "os"
|
|
import "path/filepath"
|
|
import "strings"
|
|
import "time"
|
|
import "strconv"
|
|
|
|
type Config struct {
|
|
HTTPAddrs []string `json:"http_addrs"`
|
|
HTTPSAddrs []string `json:"https_addrs"`
|
|
PublicBaseURL string `json:"public_base_url"`
|
|
DataDir string `json:"data_dir"`
|
|
FrontendDir string `json:"frontend_dir"`
|
|
DBDriver string `json:"db_driver"`
|
|
DBDSN string `json:"db_dsn"`
|
|
SessionTTL Duration `json:"session_ttl"`
|
|
AuthMode string `json:"auth_mode"`
|
|
LDAPURL string `json:"ldap_url"`
|
|
LDAPBindDN string `json:"ldap_bind_dn"`
|
|
LDAPBindPassword string `json:"ldap_bind_password"`
|
|
LDAPUserBaseDN string `json:"ldap_user_base_dn"`
|
|
LDAPUserFilter string `json:"ldap_user_filter"`
|
|
LDAPTLSInsecureSkipVerify bool `json:"ldap_tls_insecure_skip_verify"`
|
|
OIDCClientID string `json:"oidc_client_id"`
|
|
OIDCClientSecret string `json:"oidc_client_secret"`
|
|
OIDCAuthorizeURL string `json:"oidc_authorize_url"`
|
|
OIDCTokenURL string `json:"oidc_token_url"`
|
|
OIDCUserInfoURL string `json:"oidc_userinfo_url"`
|
|
OIDCRedirectURL string `json:"oidc_redirect_url"`
|
|
OIDCScopes string `json:"oidc_scopes"`
|
|
OIDCEnabled bool `json:"oidc_enabled"`
|
|
OIDCTLSInsecureSkipVerify bool `json:"oidc_tls_insecure_skip_verify"`
|
|
TLSServerCertSource string `json:"tls_server_cert_source"`
|
|
TLSCertFile string `json:"tls_cert_file"`
|
|
TLSKeyFile string `json:"tls_key_file"`
|
|
TLSPKIServerCertID string `json:"tls_pki_server_cert_id"`
|
|
TLSClientAuth string `json:"tls_client_auth"`
|
|
TLSClientCAFile string `json:"tls_client_ca_file"`
|
|
TLSPKIClientCAID string `json:"tls_pki_client_ca_id"`
|
|
TLSMinVersion string `json:"tls_min_version"`
|
|
GitHTTPPrefix string `json:"git_http_prefix"`
|
|
RPMHTTPPrefix string `json:"rpm_http_prefix"`
|
|
}
|
|
|
|
func Load(path string) (Config, error) {
|
|
var cfg Config
|
|
var data []byte
|
|
var err error
|
|
cfg = Config{
|
|
HTTPAddrs: []string{":1080"},
|
|
HTTPSAddrs: []string{},
|
|
DataDir: "./codit-data",
|
|
FrontendDir: filepath.Join("..", "frontend", "dist"),
|
|
DBDriver: "sqlite",
|
|
DBDSN: "file:./codit-data/codit.db?_pragma=foreign_keys(1)",
|
|
SessionTTL: Duration(24 * time.Hour),
|
|
AuthMode: "db",
|
|
LDAPUserFilter: "(uid={username})",
|
|
OIDCScopes: "openid profile email",
|
|
TLSServerCertSource: "files",
|
|
TLSClientAuth: "none",
|
|
TLSMinVersion: "1.2",
|
|
GitHTTPPrefix: "/git",
|
|
RPMHTTPPrefix: "/rpm",
|
|
}
|
|
if path != "" {
|
|
data, err = os.ReadFile(path)
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
err = json.Unmarshal(data, &cfg)
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
}
|
|
override(&cfg)
|
|
cfg.AuthMode = strings.ToLower(strings.TrimSpace(cfg.AuthMode))
|
|
cfg.TLSServerCertSource = strings.ToLower(strings.TrimSpace(cfg.TLSServerCertSource))
|
|
cfg.TLSClientAuth = strings.ToLower(strings.TrimSpace(cfg.TLSClientAuth))
|
|
cfg.HTTPAddrs = normalizeHTTPAddrs(cfg.HTTPAddrs)
|
|
cfg.HTTPSAddrs = normalizeHTTPAddrs(cfg.HTTPSAddrs)
|
|
if len(cfg.HTTPAddrs) == 0 && len(cfg.HTTPSAddrs) == 0 {
|
|
return cfg, errors.New("http_addrs or https_addrs is required")
|
|
}
|
|
if cfg.DBDSN == "" {
|
|
return cfg, errors.New("db dsn is required")
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func override(cfg *Config) {
|
|
var v string
|
|
v = os.Getenv("CODIT_HTTP_ADDRS")
|
|
if v != "" {
|
|
cfg.HTTPAddrs = splitCSV(v)
|
|
}
|
|
v = os.Getenv("CODIT_HTTPS_ADDRS")
|
|
if v != "" {
|
|
cfg.HTTPSAddrs = splitCSV(v)
|
|
}
|
|
v = os.Getenv("CODIT_PUBLIC_BASE_URL")
|
|
if v != "" {
|
|
cfg.PublicBaseURL = v
|
|
}
|
|
v = os.Getenv("CODIT_DATA_DIR")
|
|
if v != "" {
|
|
cfg.DataDir = v
|
|
}
|
|
v = os.Getenv("CODIT_FRONTEND_DIR")
|
|
if v != "" {
|
|
cfg.FrontendDir = v
|
|
}
|
|
v = os.Getenv("CODIT_DB_DRIVER")
|
|
if v != "" {
|
|
cfg.DBDriver = v
|
|
}
|
|
v = os.Getenv("CODIT_DB_DSN")
|
|
if v != "" {
|
|
cfg.DBDSN = v
|
|
}
|
|
v = os.Getenv("CODIT_AUTH_MODE")
|
|
if v != "" {
|
|
cfg.AuthMode = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_URL")
|
|
if v != "" {
|
|
cfg.LDAPURL = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_BIND_DN")
|
|
if v != "" {
|
|
cfg.LDAPBindDN = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_BIND_PASSWORD")
|
|
if v != "" {
|
|
cfg.LDAPBindPassword = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_USER_BASE_DN")
|
|
if v != "" {
|
|
cfg.LDAPUserBaseDN = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_USER_FILTER")
|
|
if v != "" {
|
|
cfg.LDAPUserFilter = v
|
|
}
|
|
v = os.Getenv("CODIT_LDAP_TLS_INSECURE_SKIP_VERIFY")
|
|
if v != "" {
|
|
cfg.LDAPTLSInsecureSkipVerify = parseEnvBool(v)
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_CLIENT_ID")
|
|
if v != "" {
|
|
cfg.OIDCClientID = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_CLIENT_SECRET")
|
|
if v != "" {
|
|
cfg.OIDCClientSecret = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_AUTHORIZE_URL")
|
|
if v != "" {
|
|
cfg.OIDCAuthorizeURL = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_TOKEN_URL")
|
|
if v != "" {
|
|
cfg.OIDCTokenURL = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_USERINFO_URL")
|
|
if v != "" {
|
|
cfg.OIDCUserInfoURL = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_REDIRECT_URL")
|
|
if v != "" {
|
|
cfg.OIDCRedirectURL = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_SCOPES")
|
|
if v != "" {
|
|
cfg.OIDCScopes = v
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_ENABLED")
|
|
if v != "" {
|
|
cfg.OIDCEnabled = parseEnvBool(v)
|
|
}
|
|
v = os.Getenv("CODIT_OIDC_TLS_INSECURE_SKIP_VERIFY")
|
|
if v != "" {
|
|
cfg.OIDCTLSInsecureSkipVerify = parseEnvBool(v)
|
|
}
|
|
v = os.Getenv("CODIT_TLS_SERVER_CERT_SOURCE")
|
|
if v != "" {
|
|
cfg.TLSServerCertSource = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_CERT_FILE")
|
|
if v != "" {
|
|
cfg.TLSCertFile = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_KEY_FILE")
|
|
if v != "" {
|
|
cfg.TLSKeyFile = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_PKI_SERVER_CERT_ID")
|
|
if v != "" {
|
|
cfg.TLSPKIServerCertID = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_CLIENT_AUTH")
|
|
if v != "" {
|
|
cfg.TLSClientAuth = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_CLIENT_CA_FILE")
|
|
if v != "" {
|
|
cfg.TLSClientCAFile = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_PKI_CLIENT_CA_ID")
|
|
if v != "" {
|
|
cfg.TLSPKIClientCAID = v
|
|
}
|
|
v = os.Getenv("CODIT_TLS_MIN_VERSION")
|
|
if v != "" {
|
|
cfg.TLSMinVersion = v
|
|
}
|
|
v = os.Getenv("CODIT_GIT_HTTP_PREFIX")
|
|
if v != "" {
|
|
cfg.GitHTTPPrefix = v
|
|
}
|
|
v = os.Getenv("CODIT_RPM_HTTP_PREFIX")
|
|
if v != "" {
|
|
cfg.RPMHTTPPrefix = v
|
|
}
|
|
}
|
|
|
|
type Duration time.Duration
|
|
|
|
func (d Duration) Duration() time.Duration {
|
|
return time.Duration(d)
|
|
}
|
|
|
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
|
var asString string
|
|
var asNumber int64
|
|
var err error
|
|
var parsed time.Duration
|
|
err = json.Unmarshal(b, &asString)
|
|
if err == nil {
|
|
parsed, err = time.ParseDuration(asString)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*d = Duration(parsed)
|
|
return nil
|
|
}
|
|
err = json.Unmarshal(b, &asNumber)
|
|
if err == nil {
|
|
*d = Duration(time.Duration(asNumber))
|
|
return nil
|
|
}
|
|
return errors.New("invalid duration format")
|
|
}
|
|
|
|
func parseEnvBool(v string) bool {
|
|
var lowered string
|
|
var parsed bool
|
|
var err error
|
|
lowered = strings.ToLower(strings.TrimSpace(v))
|
|
if lowered == "true" || lowered == "yes" || lowered == "y" || lowered == "on" {
|
|
return true
|
|
}
|
|
if lowered == "false" || lowered == "no" || lowered == "n" || lowered == "off" {
|
|
return false
|
|
}
|
|
parsed, err = strconv.ParseBool(lowered)
|
|
if err == nil {
|
|
return parsed
|
|
}
|
|
return false
|
|
}
|
|
|
|
func splitCSV(v string) []string {
|
|
var parts []string
|
|
var out []string
|
|
var i int
|
|
var p string
|
|
parts = strings.Split(v, ",")
|
|
for i = 0; i < len(parts); i++ {
|
|
p = strings.TrimSpace(parts[i])
|
|
if p == "" {
|
|
continue
|
|
}
|
|
out = append(out, p)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func normalizeHTTPAddrs(values []string) []string {
|
|
var out []string
|
|
var i int
|
|
var v string
|
|
for i = 0; i < len(values); i++ {
|
|
v = strings.TrimSpace(values[i])
|
|
if v == "" {
|
|
continue
|
|
}
|
|
out = append(out, v)
|
|
}
|
|
return out
|
|
}
|