Files
traefik-forward-auth/config.go
2019-01-30 16:52:47 +00:00

205 lines
5.2 KiB
Go

package main
import (
"fmt"
"net/url"
"strings"
"time"
"github.com/BurntSushi/toml"
"github.com/namsral/flag"
"github.com/thomseddon/traefik-forward-auth/provider"
)
type Config struct {
DefaultAction string
Path string
Lifetime time.Duration
Secret string
SecretBytes []byte
AuthHost string
LogLevel *string
LogFormat *string
TomlConfig *string // temp
CookieName string
CookieDomains []CookieDomain
CSRFCookieName string
CookieSecure bool
Domain []string
Whitelist []string
Providers provider.Providers
Rules map[string]Rules
}
type Rules struct {
Action string
Match []Match
}
type Match struct {
Host []string
PathPrefix []string
Header [][]string
}
func NewConfig() *Config {
c := &Config{}
c.parseFlags()
c.applyDefaults()
return c
}
// TODO: Fix
// At the moment any flag value will overwrite the toml config
// Need to put the flag default values in applyDefaults & empty the flag
// defaults so we can check if they're being passed and set accordingly
// Ideally we also need to remove the two calls to parseFlags
//
// We also need to check the default -config flag for toml suffix and
// parse that as needed
//
// Ideally we'd also support multiple config files
func NewParsedConfig() *Config {
c := &Config{}
// Temp
c.parseFlags()
// Parse toml
if *c.TomlConfig != "" {
if _, err := toml.DecodeFile(*c.TomlConfig, &c); err != nil {
panic(err)
return c
}
}
c.applyDefaults()
// Conversions
c.SecretBytes = []byte(c.Secret)
return c
}
func (c *Config) Checks() {
// Check for show stopper errors
if c.Providers.Google.ClientId == "" || c.Providers.Google.ClientSecret == "" || len(c.Secret) == 0 {
log.Fatal("client-id, client-secret and secret must all be set")
}
}
func (c *Config) applyDefaults() {
// Providers
// Google
if c.Providers.Google.Scope == "" {
c.Providers.Google.Scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
}
if c.Providers.Google.LoginURL == nil {
c.Providers.Google.LoginURL = &url.URL{
Scheme: "https",
Host: "accounts.google.com",
Path: "/o/oauth2/auth",
}
}
if c.Providers.Google.TokenURL == nil {
c.Providers.Google.TokenURL = &url.URL{
Scheme: "https",
Host: "www.googleapis.com",
Path: "/oauth2/v3/token",
}
}
if c.Providers.Google.UserURL == nil {
c.Providers.Google.UserURL = &url.URL{
Scheme: "https",
Host: "www.googleapis.com",
Path: "/oauth2/v2/userinfo",
}
}
}
func (c *Config) parseFlags() {
c.LogLevel = flag.String("log-level", "warn", "Log level: trace, debug, info, warn, error, fatal, panic")
c.LogFormat = flag.String("log-format", "text", "Log format: text, json, pretty")
c.TomlConfig = flag.String("toml-config", "", "TEMP")
// Legacy?
path := flag.String("url-path", "_oauth", "Callback URL")
lifetime := flag.Int("lifetime", 43200, "Session length in seconds")
secret := flag.String("secret", "", "*Secret used for signing (required)")
authHost := flag.String("auth-host", "", "Central auth login")
clientId := flag.String("client-id", "", "*Google Client ID (required)")
clientSecret := flag.String("client-secret", "", "*Google Client Secret (required)")
cookieName := flag.String("cookie-name", "_forward_auth", "Cookie Name")
cSRFCookieName := flag.String("csrf-cookie-name", "_forward_auth_csrf", "CSRF Cookie Name")
cookieDomainList := flag.String("cookie-domains", "", "Comma separated list of cookie domains") //todo
cookieSecret := flag.String("cookie-secret", "", "Deprecated")
cookieSecure := flag.Bool("cookie-secure", true, "Use secure cookies")
domainList := flag.String("domain", "", "Comma separated list of email domains to allow")
emailWhitelist := flag.String("whitelist", "", "Comma separated list of emails to allow")
prompt := flag.String("prompt", "", "Space separated list of OpenID prompt options")
flag.Parse()
// Add to config
c.Path = fmt.Sprintf("/%s", *path)
c.Lifetime = time.Second * time.Duration(*lifetime)
c.AuthHost = *authHost
c.Providers.Google.ClientId = *clientId
c.Providers.Google.ClientSecret = *clientSecret
c.Providers.Google.Prompt = *prompt
c.CookieName = *cookieName
c.CSRFCookieName = *cSRFCookieName
c.CookieSecure = *cookieSecure
// Backwards compatibility
if *secret == "" && *cookieSecret != "" {
*secret = *cookieSecret
}
c.Secret = *secret
// Parse lists
if *cookieDomainList != "" {
for _, d := range strings.Split(*cookieDomainList, ",") {
cookieDomain := NewCookieDomain(d)
c.CookieDomains = append(c.CookieDomains, *cookieDomain)
}
}
if *domainList != "" {
c.Domain = strings.Split(*domainList, ",")
}
if *emailWhitelist != "" {
c.Whitelist = strings.Split(*emailWhitelist, ",")
}
}
// Temp
func (c Config) Walk() {
for name, rule := range c.Rules {
fmt.Printf("Rule: %s\n", name)
for _, match := range rule.Match {
if len(match.Host) > 0 {
for _, val := range match.Host {
fmt.Printf(" - Host: %s\n", val)
}
}
if len(match.PathPrefix) > 0 {
for _, val := range match.PathPrefix {
fmt.Printf(" - PathPrefix: %s\n", val)
}
}
if len(match.Header) > 0 {
for _, val := range match.Header {
fmt.Printf(" - Header: %s: %s\n", val[0], val[1])
}
}
}
}
}