diff --git a/compose.yaml b/compose.yaml index 47ed675..b6de464 100644 --- a/compose.yaml +++ b/compose.yaml @@ -39,7 +39,7 @@ services: volumes: - 'presences-config:/etc/presences/' restart: 'unless-stopped' - command: ['presences', '--config', '/etc/presences/config.yaml', 'server'] + command: ['presences', '--config', '/etc/presences/config.yaml'] adminer: depends_on: diff --git a/config.go b/config.go index c3228ed..4ce0ba5 100644 --- a/config.go +++ b/config.go @@ -33,13 +33,12 @@ type Config struct { Key string } - // Credentials holds username-password pairs for basic authentication - // not part of minimum viable product - //Credentials map[string]string - UI struct { - Username string - Password string + //Username 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 diff --git a/flag.go b/flag.go index 8a01a21..014b0c6 100644 --- a/flag.go +++ b/flag.go @@ -6,37 +6,106 @@ import ( ) const ( - configPort = "Port" - defaultPort = 8080 - flagPort = "port" + flagPortConfig = "Port" + flagPortDefault = 8080 + flagPort = "port" - configTLSCert = "TLS.Cert" - defaultTLSCert = "" - flagTLSCert = "tls-cert" + flagTLSCertConfig = "TLS.Cert" + flagTLSCertDefault = "" + flagTLSCert = "tls-cert" - configTLSKey = "TLS.Key" - defaultTLSKey = "" - flagTLSKey = "tls-key" + flagTLSKeyConfig = "TLS.Key" + flagTLSKeyDefault = "" + 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 func BindFlags(set *pflag.FlagSet) error { // Credentials -> seulement par config - set.Int(flagPort, defaultPort, "User interface port") - if err := viper.BindPFlag(configPort, set.Lookup(flagPort)); err != nil { + set.Int(flagPort, flagPortDefault, "User interface port") + if err := viper.BindPFlag(flagPortConfig, set.Lookup(flagPort)); err != nil { return err } - set.String(flagTLSKey, defaultTLSKey, "User interface TLS private key (or path to file)") - if err := viper.BindPFlag(configTLSKey, set.Lookup(flagTLSKey)); err != nil { + set.String(flagTLSKey, flagTLSKeyDefault, "User interface TLS private key (or path to file)") + if err := viper.BindPFlag(flagTLSKeyConfig, set.Lookup(flagTLSKey)); err != nil { return err } - set.String(flagTLSCert, defaultTLSCert, "User interface TLS certificate (or path to file)") - if err := viper.BindPFlag(configTLSCert, set.Lookup(flagTLSCert)); err != nil { + set.String(flagTLSCert, flagTLSCertDefault, "User interface TLS certificate (or path to file)") + if err := viper.BindPFlag(flagTLSCertConfig, set.Lookup(flagTLSCert)); err != nil { 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 } diff --git a/server.go b/server.go index 59d809d..fdd02a3 100644 --- a/server.go +++ b/server.go @@ -41,19 +41,19 @@ func RunUIServer(ctx context.Context, cfg Config, bottinClient *bottin.APIClient e.Pre(middleware.AddTrailingSlash()) - // basic auth - if cfg.UI.Username == "" || cfg.UI.Password == "" { - return fmt.Errorf("UI username and password cannot be empty, please set UI.Password and UI.Username (PRESENCES_UI_PASSWORD and PRESENCES_UI_USERNAME") + if len(cfg.UI.Credentials) == 0 { + 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.") } e.Pre(middleware.BasicAuth( func(username, password string, c echo.Context) (bool, error) { - userOK := subtle.ConstantTimeCompare([]byte(username), []byte(cfg.UI.Username)) == 1 - passOK := subtle.ConstantTimeCompare([]byte(password), []byte(cfg.UI.Password)) == 1 - if userOK && passOK { - return true, nil + rightPassword, userExists := cfg.UI.Credentials[username] + if !userExists { + return false, nil } - return false, nil + + passwordOK := subtle.ConstantTimeCompare([]byte(password), []byte(rightPassword)) == 1 + return passwordOK, nil }), )