Refactor progress
- move directory structure - string based rule definition - use traefik rule parsing - drop toml config - new flag library - implement go dep
This commit is contained in:
146
internal/config.go
Normal file
146
internal/config.go
Normal file
@ -0,0 +1,146 @@
|
||||
package tfa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
"github.com/thomseddon/traefik-forward-auth/internal/provider"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
LogLevel string `long:"log-level" default:"warn" description:"Log level: trace, debug, info, warn, error, fatal, panic"`
|
||||
LogFormat string `long:"log-format" default:"text" description:"Log format: text, json, pretty"`
|
||||
|
||||
AuthHost string `long:"auth-host" description:"Host for central auth login"`
|
||||
ConfigFile string `long:"config-file" description:"Config File"`
|
||||
CookieDomains CookieDomains `long:"cookie-domains" description:"Comma separated list of cookie domains"`
|
||||
CookieInsecure bool `long:"cookie-insecure" description:"Use secure cookies"`
|
||||
CookieName string `long:"cookie-name" default:"_forward_auth" description:"Cookie Name"`
|
||||
CSRFCookieName string `long:"csrf-cookie-name" default:"_forward_auth_csrf" description:"CSRF Cookie Name"`
|
||||
DefaultAction string `long:"default-action" default:"allow" description:"Default Action"`
|
||||
Domains CommaSeparatedList `long:"domains" description:"Comma separated list of email domains to allow"`
|
||||
LifetimeString int `long:"lifetime" default:"43200" description:"Lifetime in seconds"`
|
||||
Path string `long:"path" default:"_oauth" description:"Callback URL Path"`
|
||||
SecretString string `long:"secret" description:"*Secret used for signing (required)"`
|
||||
Whitelist CommaSeparatedList `long:"whitelist" description:"Comma separated list of email addresses to allow"`
|
||||
|
||||
Providers provider.Providers
|
||||
Rules []Rule `long:"rule"`
|
||||
|
||||
Secret []byte
|
||||
Lifetime time.Duration
|
||||
|
||||
Prompt string `long:"prompt" description:"DEPRECATED - Use providers.google.prompt"`
|
||||
// TODO: Need to mimick the default behaviour of bool flags
|
||||
CookieSecure string `long:"cookie-secure" default:"true" description:"DEPRECATED - Use \"cookie-insecure\""`
|
||||
|
||||
flags []string
|
||||
usingToml bool
|
||||
}
|
||||
|
||||
type CommaSeparatedList []string
|
||||
|
||||
func (c *CommaSeparatedList) UnmarshalFlag(value string) error {
|
||||
*c = strings.Split(value, ",")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommaSeparatedList) MarshalFlag() (string, error) {
|
||||
return strings.Join(*c, ","), nil
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
Action string
|
||||
Rule string
|
||||
}
|
||||
|
||||
func (r *Rule) UnmarshalFlag(value string) error {
|
||||
// Format is "action:rule"
|
||||
parts := strings.SplitN(value, ":", 2)
|
||||
|
||||
if len(parts) != 2 {
|
||||
return errors.New("Invalid rule format, should be \"action:rule\"")
|
||||
}
|
||||
|
||||
if parts[0] != "auth" && parts[0] != "allow" {
|
||||
return errors.New("Invalid rule action, must be \"auth\" or \"allow\"")
|
||||
}
|
||||
|
||||
// Parse rule
|
||||
*r = Rule{
|
||||
Action: parts[0],
|
||||
Rule: parts[1],
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Rule) MarshalFlag() (string, error) {
|
||||
// TODO: format correctly
|
||||
return fmt.Sprintf("%+v", *r), nil
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
// TODO:
|
||||
// - parse ini
|
||||
// - parse env vars
|
||||
// - parse env var file
|
||||
// - support multiple config files
|
||||
// - maintain backwards compat
|
||||
|
||||
func NewGlobalConfig() Config {
|
||||
return NewGlobalConfigWithArgs(os.Args[1:])
|
||||
}
|
||||
|
||||
func NewGlobalConfigWithArgs(args []string) Config {
|
||||
config = Config{}
|
||||
|
||||
config.parseFlags(args)
|
||||
|
||||
// Struct defaults
|
||||
config.Providers.Google.Build()
|
||||
|
||||
// Transformations
|
||||
config.Path = fmt.Sprintf("/%s", config.Path)
|
||||
config.Secret = []byte(config.SecretString)
|
||||
config.Lifetime = time.Second * time.Duration(config.LifetimeString)
|
||||
|
||||
// TODO: Backwards compatability
|
||||
// "secret" used to be "cookie-secret"
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
func (c *Config) parseFlags(args []string) {
|
||||
if _, err := flags.ParseArgs(c, args); err != nil {
|
||||
flagsErr, ok := err.(*flags.Error)
|
||||
if ok && flagsErr.Type == flags.ErrHelp {
|
||||
os.Exit(0)
|
||||
} else {
|
||||
fmt.Printf("%+v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) Checks() {
|
||||
// Check for show stopper errors
|
||||
if len(c.Secret) == 0 {
|
||||
log.Fatal("\"secret\" option must be set.")
|
||||
}
|
||||
|
||||
if c.Providers.Google.ClientId == "" || c.Providers.Google.ClientSecret == "" {
|
||||
log.Fatal("google.providers.client-id, google.providers.client-secret must be set")
|
||||
}
|
||||
}
|
||||
|
||||
func (c Config) Serialise() string {
|
||||
jsonConf, _ := json.Marshal(c)
|
||||
return string(jsonConf)
|
||||
}
|
Reference in New Issue
Block a user