WIP: major/v2 #1

Draft
vlbeaudoin wants to merge 5 commits from major/v2 into main
4 changed files with 98 additions and 30 deletions
Showing only changes of commit 940c6d8a25 - Show all commits

View file

@ -39,7 +39,7 @@ services:
volumes: volumes:
- 'presences-config:/etc/presences/' - 'presences-config:/etc/presences/'
restart: 'unless-stopped' restart: 'unless-stopped'
command: ['presences', '--config', '/etc/presences/config.yaml', 'server'] command: ['presences', '--config', '/etc/presences/config.yaml']
adminer: adminer:
depends_on: depends_on:

View file

@ -33,13 +33,12 @@ type Config struct {
Key string Key string
} }
// Credentials holds username-password pairs for basic authentication
// not part of minimum viable product
//Credentials map[string]string
UI struct { UI struct {
Username string //Username string
Password string //Password string
// Credentials holds username-password pairs for basic authentication
Credentials map[string]string
} }
// Port holds the port on which to expose the user interface // Port holds the port on which to expose the user interface

99
flag.go
View file

@ -6,37 +6,106 @@ import (
) )
const ( const (
configPort = "Port" flagPortConfig = "Port"
defaultPort = 8080 flagPortDefault = 8080
flagPort = "port" flagPort = "port"
configTLSCert = "TLS.Cert" flagTLSCertConfig = "TLS.Cert"
defaultTLSCert = "" flagTLSCertDefault = ""
flagTLSCert = "tls-cert" flagTLSCert = "tls-cert"
configTLSKey = "TLS.Key" flagTLSKeyConfig = "TLS.Key"
defaultTLSKey = "" flagTLSKeyDefault = ""
flagTLSKey = "tls-key" flagTLSKey = "tls-key"
flagDBDatabaseConfig = "DB.Database"
flagDBDatabaseDefault = "presences"
flagDBDatabase = "db-database"
flagDBHostConfig = "DB.Host"
flagDBHostDefault = "presences-db"
flagDBHost = "db-host"
flagDBPasswordConfig = "DB.Password"
flagDBPasswordDefault = "presences"
flagDBPassword = "db-password"
flagDBPortConfig = "DB.Port"
flagDBPortDefault = 5432
flagDBPort = "db-port"
flagDBSSLModeConfig = "DB.SSLMode"
flagDBSSLModeDefault = "prefer"
flagDBSSLMode = "db-sslmode"
flagDBUsernameConfig = "DB.Username"
flagDBUsernameDefault = "presences"
flagDBUsername = "db-username"
/*
flagUICredentialsConfig = "UI.Credentials"
//flagUICredentialsDefault = make(map[string]string)
flagUICredentials = "ui-credentials"
*/
//TODO check if any necessary flags are missing
) )
// BindClientFlags declares client-related flags and config options in the specified *pflag.FlagSet // BindClientFlags declares client-related flags and config options in the specified *pflag.FlagSet
func BindFlags(set *pflag.FlagSet) error { func BindFlags(set *pflag.FlagSet) error {
// Credentials -> seulement par config // Credentials -> seulement par config
set.Int(flagPort, defaultPort, "User interface port") set.Int(flagPort, flagPortDefault, "User interface port")
if err := viper.BindPFlag(configPort, set.Lookup(flagPort)); err != nil { if err := viper.BindPFlag(flagPortConfig, set.Lookup(flagPort)); err != nil {
return err return err
} }
set.String(flagTLSKey, defaultTLSKey, "User interface TLS private key (or path to file)") set.String(flagTLSKey, flagTLSKeyDefault, "User interface TLS private key (or path to file)")
if err := viper.BindPFlag(configTLSKey, set.Lookup(flagTLSKey)); err != nil { if err := viper.BindPFlag(flagTLSKeyConfig, set.Lookup(flagTLSKey)); err != nil {
return err return err
} }
set.String(flagTLSCert, defaultTLSCert, "User interface TLS certificate (or path to file)") set.String(flagTLSCert, flagTLSCertDefault, "User interface TLS certificate (or path to file)")
if err := viper.BindPFlag(configTLSCert, set.Lookup(flagTLSCert)); err != nil { if err := viper.BindPFlag(flagTLSCertConfig, set.Lookup(flagTLSCert)); err != nil {
return err return err
} }
set.String(flagDBDatabase, flagDBDatabaseDefault, "PostgreSQL database")
if err := viper.BindPFlag(flagDBDatabaseConfig, set.Lookup(flagDBDatabase)); err != nil {
return err
}
set.String(flagDBHost, flagDBHostDefault, "PostgreSQL host")
if err := viper.BindPFlag(flagDBHostConfig, set.Lookup(flagDBHost)); err != nil {
return err
}
set.String(flagDBPassword, flagDBPasswordDefault, "PostgreSQL password")
if err := viper.BindPFlag(flagDBPasswordConfig, set.Lookup(flagDBPassword)); err != nil {
return err
}
set.Int(flagDBPort, flagDBPortDefault, "PostgreSQL port")
if err := viper.BindPFlag(flagDBPortConfig, set.Lookup(flagDBPort)); err != nil {
return err
}
set.String(flagDBSSLMode, flagDBSSLModeDefault, "PostgreSQL ssl mode")
if err := viper.BindPFlag(flagDBSSLModeConfig, set.Lookup(flagDBSSLMode)); err != nil {
return err
}
set.String(flagDBUsername, flagDBUsernameDefault, "PostgreSQL username")
if err := viper.BindPFlag(flagDBUsernameConfig, set.Lookup(flagDBUsername)); err != nil {
return err
}
/*
set.StringToString(flagUICredentials, nil, "Sets of credentials for the UI console")
if err := viper.BindPFlag(flagUICredentialsConfig, set.Lookup(flagUICredentials)); err != nil {
return err
}
*/
return nil return nil
} }

View file

@ -41,19 +41,19 @@ func RunUIServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient
e.Pre(middleware.AddTrailingSlash()) e.Pre(middleware.AddTrailingSlash())
// basic auth if len(cfg.UI.Credentials) == 0 {
if cfg.UI.Username == "" || cfg.UI.Password == "" { return fmt.Errorf("UI.Credentials config file option of type map[string]string must contain at least one username-password key-value pair. Note that there is no flag or ENV counterpart, this must be done through a config file.")
return fmt.Errorf("UI username and password cannot be empty, please set UI.Password and UI.Username (PRESENCES_UI_PASSWORD and PRESENCES_UI_USERNAME")
} }
e.Pre(middleware.BasicAuth( e.Pre(middleware.BasicAuth(
func(username, password string, c echo.Context) (bool, error) { func(username, password string, c echo.Context) (bool, error) {
userOK := subtle.ConstantTimeCompare([]byte(username), []byte(cfg.UI.Username)) == 1 rightPassword, userExists := cfg.UI.Credentials[username]
passOK := subtle.ConstantTimeCompare([]byte(password), []byte(cfg.UI.Password)) == 1 if !userExists {
if userOK && passOK { return false, nil
return true, nil
} }
return false, nil
passwordOK := subtle.ConstantTimeCompare([]byte(password), []byte(rightPassword)) == 1
return passwordOK, nil
}), }),
) )