polycule-connect/polyculeconnect/config/config.go

227 lines
6 KiB
Go
Raw Normal View History

2023-10-12 18:36:34 +00:00
package config
import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
2023-10-14 16:06:02 +00:00
"github.com/dexidp/dex/connector/oidc"
"github.com/kelseyhightower/envconfig"
2023-10-12 18:36:34 +00:00
"github.com/sirupsen/logrus"
)
const (
envConfigPrefix = "POLYCULECONNECT"
DefaultConfigPath = "/etc/polyculeconnect.json"
)
2023-10-12 18:36:34 +00:00
type ListeningMode string
2023-10-12 18:36:34 +00:00
const (
ModeUnix ListeningMode = "unix"
ModeNet ListeningMode = "net"
2023-10-12 18:36:34 +00:00
)
type BackendConfigType string
const (
Memory BackendConfigType = "memory"
SQLite BackendConfigType = "sqlite"
)
const (
defaultLogLevel = logrus.InfoLevel
defaultServerMode = ModeNet
defaultServerHost = "0.0.0.0"
defaultServerPort = 5000
defaultServerSocket = ""
defaultServerStaticDir = "./"
defaultIssuer = "locahost"
defaultStorageType = Memory
defaultStorageFile = "./polyculeconnect.db"
defaultStorageHost = "127.0.0.1"
defaultStoragePort = 5432
defaultStorageDB = "polyculeconnect"
defaultStorageUser = "polyculeconnect"
defaultStoragePassword = "polyculeconnect"
defaultStorageSSLMode = "disable"
defaultStorageSSLCaFile = ""
)
// Deprecated: remove when we finally drop the JSON config
2023-10-14 16:06:02 +00:00
type BackendConfig struct {
Config *oidc.Config `json:"config"`
Name string `json:"name"`
ID string `json:"ID"`
Type BackendConfigType `json:"type"`
Local bool `json:"local"`
2023-10-14 16:06:02 +00:00
}
type SSLStorageConfig struct {
Mode string `json:"mode" envconfig:"STORAGE_SSL_MODE"`
CaFile string `json:"ca_file" envconfig:"STORAGE_SSL_CA_FILE"`
2023-10-14 16:06:02 +00:00
}
type StorageConfig struct {
File string `envconfig:"STORAGE_PATH"`
Host string `envconfig:"STORAGE_HOST"`
Port int `envconfig:"STORAGE_PORT"`
Database string `envconfig:"STORAGE_DATABASE"`
User string `envconfig:"STORAGE_USER"`
Password string `envconfig:"STORAGE_PASSWORD"`
SSL SSLStorageConfig
}
type logConfig struct {
Level string `json:"level"`
}
type serverConfig struct {
Mode string `json:"mode"`
Host string `json:"host"`
Port int `json:"port"`
Sock string `json:"sock"`
}
type jsonStorageConfig struct {
Type string `json:"type"`
File string `json:"path"`
Host string `json:"host" `
Port int `json:"port"`
Database string `json:"database" `
User string `json:"user" `
Password string `json:"password" `
SSL SSLStorageConfig `json:"ssl"`
}
2023-10-12 18:36:34 +00:00
type jsonConf struct {
LogConfig logConfig `json:"log"`
ServerConfig serverConfig `json:"server"`
StorageConfig jsonStorageConfig `json:"storage"`
}
func (c *jsonConf) initValues(ac *AppConfig) {
c.LogConfig = logConfig{Level: ac.LogLevel.String()}
c.ServerConfig = serverConfig{
Mode: string(ac.ServerMode),
Host: ac.Host,
Port: ac.Port,
Sock: ac.SockPath,
}
c.StorageConfig = jsonStorageConfig{
Type: ac.StorageType,
File: ac.StorageConfig.File,
Host: ac.StorageConfig.Host,
Port: ac.StorageConfig.Port,
Database: ac.StorageConfig.Database,
User: ac.StorageConfig.User,
Password: ac.StorageConfig.Password,
SSL: ac.StorageConfig.SSL,
}
2023-10-12 18:36:34 +00:00
}
type AppConfig struct {
LogLevel logrus.Level `envconfig:"LOG_LEVEL"`
ServerMode ListeningMode `envconfig:"SERVER_MODE"`
Host string `envconfig:"SERVER_HOST"`
Port int `envconfig:"SERVER_PORT"`
SockPath string `envconfig:"SERVER_SOCK"`
StorageType string `envconfig:"STORAGE_TYPE"`
StorageConfig *StorageConfig
Issuer string
StaticDir string
}
func defaultConfig() AppConfig {
return AppConfig{
LogLevel: defaultLogLevel,
ServerMode: defaultServerMode,
Host: defaultServerHost,
Port: defaultServerPort,
SockPath: defaultServerSocket,
StorageType: string(defaultStorageType),
StorageConfig: &StorageConfig{
File: defaultStorageFile,
Host: defaultStorageHost,
Port: defaultServerPort,
Database: defaultStorageDB,
User: defaultStorageUser,
Password: defaultStoragePassword,
SSL: SSLStorageConfig{
Mode: defaultStorageSSLMode,
CaFile: defaultStorageSSLCaFile,
},
},
Issuer: defaultIssuer,
StaticDir: defaultServerStaticDir,
}
2023-10-12 18:36:34 +00:00
}
func parseLevel(lvlStr string) logrus.Level {
for _, lvl := range logrus.AllLevels {
if lvl.String() == lvlStr {
return lvl
}
}
return logrus.InfoLevel
}
func (ac *AppConfig) UnmarshalJSON(data []byte) error {
var jsonConf jsonConf
jsonConf.initValues(ac)
2023-10-12 18:36:34 +00:00
if err := json.Unmarshal(data, &jsonConf); err != nil {
return fmt.Errorf("failed to read JSON: %w", err)
}
ac.LogLevel = parseLevel(jsonConf.LogConfig.Level)
ac.ServerMode = ListeningMode(jsonConf.ServerConfig.Mode)
ac.Host = jsonConf.ServerConfig.Host
ac.Port = jsonConf.ServerConfig.Port
ac.SockPath = jsonConf.ServerConfig.Sock
ac.StorageType = jsonConf.StorageConfig.Type
ac.StorageConfig.File = jsonConf.StorageConfig.File
ac.StorageConfig.Host = jsonConf.StorageConfig.Host
ac.StorageConfig.Port = jsonConf.StorageConfig.Port
ac.StorageConfig.Database = jsonConf.StorageConfig.Database
ac.StorageConfig.User = jsonConf.StorageConfig.User
ac.StorageConfig.Password = jsonConf.StorageConfig.Password
ac.StorageConfig.SSL = jsonConf.StorageConfig.SSL
return nil
2023-10-12 18:36:34 +00:00
}
func (ac *AppConfig) RedirectURI() string {
return ac.Issuer + "/callback"
}
2023-10-12 18:36:34 +00:00
func New(filepath string) (*AppConfig, error) {
conf := defaultConfig()
2023-10-12 18:36:34 +00:00
content, err := os.ReadFile(filepath)
if err != nil {
if !errors.Is(err, fs.ErrNotExist) {
return nil, fmt.Errorf("failed to read config file %q: %w", filepath, err)
}
} else {
if err := json.Unmarshal(content, &conf); err != nil {
return nil, fmt.Errorf("failed to parse config file: %w", err)
2023-10-12 18:36:34 +00:00
}
}
if err := envconfig.Process(envConfigPrefix, &conf); err != nil {
return nil, err
}
if err := envconfig.Process(envConfigPrefix, conf.StorageConfig); err != nil {
return nil, err
}
if err := envconfig.Process(envConfigPrefix, &conf.StorageConfig.SSL); err != nil {
return nil, err
}
2023-10-12 18:36:34 +00:00
return &conf, nil
}