pomerium/internal/config/options.go
Bobby DeSimone 3eff6cce13
internal/sessions: make user state domain scoped
internal/sessions: session state is domain scoped
internal/sessions: infer csrf cookie, route scoped
proxy & authenticate: use shared cookie name
proxy & authenticate: prevent resaving unchanged session
proxy & authenticate: redirect instead of error for no session on login
internal/config: merge cookies
proxy: remove favicon specific route
proxy: use mock server for tests
proxy: add tests for failures
2019-05-20 20:44:05 -07:00

224 lines
7.3 KiB
Go

package config
import (
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"time"
"github.com/pomerium/envconfig"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/policy"
)
// DisableHeaderKey is the key used to check whether to disable setting header
const DisableHeaderKey = "disable"
// Options are the global environmental flags used to set up pomerium's services.
// If a base64 encoded certificate and key are not provided as environmental variables,
// or if a file location is not provided, the server will attempt to find a matching keypair
// in the local directory as `./cert.pem` and `./privkey.pem` respectively.
type Options struct {
// Debug outputs human-readable logs to Stdout.
Debug bool `envconfig:"POMERIUM_DEBUG"`
// LogLevel sets the global override for log level. All Loggers will use at least this value.
// Possible options are "info","warn", and "error". Defaults to "debug".
LogLevel string `envconfig:"LOG_LEVEL"`
// SharedKey is the shared secret authorization key used to mutually authenticate
// requests between services.
SharedKey string `envconfig:"SHARED_SECRET"`
// Services is a list enabled service mode. If none are selected, "all" is used.
// Available options are : "all", "authenticate", "proxy".
Services string `envconfig:"SERVICES"`
// Addr specifies the host and port on which the server should serve
// HTTPS requests. If empty, ":https" is used.
Addr string `envconfig:"ADDRESS"`
// Cert and Key specifies the base64 encoded TLS certificates to use.
Cert string `envconfig:"CERTIFICATE"`
Key string `envconfig:"CERTIFICATE_KEY"`
// CertFile and KeyFile specifies the TLS certificates to use.
CertFile string `envconfig:"CERTIFICATE_FILE"`
KeyFile string `envconfig:"CERTIFICATE_KEY_FILE"`
// HttpRedirectAddr, if set, specifies the host and port to run the HTTP
// to HTTPS redirect server on. For example, ":http" would start a server
// on port 80. If empty, no redirect server is started.
HTTPRedirectAddr string `envconfig:"HTTP_REDIRECT_ADDR"`
// Timeout settings : https://github.com/pomerium/pomerium/issues/40
ReadTimeout time.Duration `envconfig:"TIMEOUT_READ"`
WriteTimeout time.Duration `envconfig:"TIMEOUT_WRITE"`
ReadHeaderTimeout time.Duration `envconfig:"TIMEOUT_READ_HEADER"`
IdleTimeout time.Duration `envconfig:"TIMEOUT_IDLE"`
// Policy is a base64 encoded yaml blob which enumerates
// per-route access control policies.
Policy string `envconfig:"POLICY"`
PolicyFile string `envconfig:"POLICY_FILE"`
// AuthenticateURL represents the externally accessible http endpoints
// used for authentication requests and callbacks
AuthenticateURL *url.URL `envconfig:"AUTHENTICATE_SERVICE_URL"`
// Session/Cookie management
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
CookieName string `envconfig:"COOKIE_NAME"`
CookieSecret string `envconfig:"COOKIE_SECRET"`
CookieDomain string `envconfig:"COOKIE_DOMAIN"`
CookieSecure bool `envconfig:"COOKIE_SECURE"`
CookieHTTPOnly bool `envconfig:"COOKIE_HTTP_ONLY"`
CookieExpire time.Duration `envconfig:"COOKIE_EXPIRE"`
CookieRefresh time.Duration `envconfig:"COOKIE_REFRESH"`
// Identity provider configuration variables as specified by RFC6749
// https://openid.net/specs/openid-connect-basic-1_0.html#RFC6749
ClientID string `envconfig:"IDP_CLIENT_ID"`
ClientSecret string `envconfig:"IDP_CLIENT_SECRET"`
Provider string `envconfig:"IDP_PROVIDER"`
ProviderURL string `envconfig:"IDP_PROVIDER_URL"`
Scopes []string `envconfig:"IDP_SCOPES"`
ServiceAccount string `envconfig:"IDP_SERVICE_ACCOUNT"`
Policies []policy.Policy `envconfig:"POLICY"`
// AuthenticateInternalAddr is used as an override when using a load balancer
// or ingress that does not natively support routing gRPC.
AuthenticateInternalAddr string `envconfig:"AUTHENTICATE_INTERNAL_URL"`
// AuthorizeURL is the routable destination of the authorize service's
// gRPC endpoint. NOTE: As above, many load balancers do not support
// externally routed gRPC so this may be an internal location.
AuthorizeURL *url.URL `envconfig:"AUTHORIZE_SERVICE_URL"`
// Settings to enable custom behind-the-ingress service communication
OverrideCertificateName string `envconfig:"OVERRIDE_CERTIFICATE_NAME"`
CA string `envconfig:"CERTIFICATE_AUTHORITY"`
CAFile string `envconfig:"CERTIFICATE_AUTHORITY_FILE"`
// SigningKey is a base64 encoded private key used to add a JWT-signature.
// https://www.pomerium.io/docs/signed-headers.html
SigningKey string `envconfig:"SIGNING_KEY"`
// Headers to set on all proxied requests. Add a 'disable' key map to turn off.
Headers map[string]string `envconfig:"HEADERS"`
// Sub-routes
Routes map[string]string `envconfig:"ROUTES"`
DefaultUpstreamTimeout time.Duration `envconfig:"DEFAULT_UPSTREAM_TIMEOUT"`
}
// NewOptions returns a new options struct with default vaules
func NewOptions() *Options {
o := &Options{
Debug: false,
LogLevel: "debug",
Services: "all",
CookieHTTPOnly: true,
CookieSecure: true,
CookieExpire: time.Duration(14) * time.Hour,
CookieRefresh: time.Duration(30) * time.Minute,
CookieName: "_pomerium",
DefaultUpstreamTimeout: time.Duration(30) * time.Second,
Headers: map[string]string{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
},
Addr: ":https",
CertFile: filepath.Join(findPwd(), "cert.pem"),
KeyFile: filepath.Join(findPwd(), "privkey.pem"),
ReadHeaderTimeout: 10 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 0, // support streaming by default
IdleTimeout: 5 * time.Minute,
AuthenticateURL: new(url.URL),
AuthorizeURL: new(url.URL),
}
return o
}
// OptionsFromEnvConfig builds the main binary's configuration
// options from provided environmental variables
func OptionsFromEnvConfig() (*Options, error) {
o := NewOptions()
if err := envconfig.Process("", o); err != nil {
return nil, err
}
if !IsValidService(o.Services) {
return nil, fmt.Errorf("%s is an invalid service type", o.Services)
}
if o.SharedKey == "" {
return nil, errors.New("shared-key cannot be empty")
}
if o.Debug {
log.SetDebugMode()
}
if o.LogLevel != "" {
log.SetLevel(o.LogLevel)
}
if _, disable := o.Headers[DisableHeaderKey]; disable {
o.Headers = make(map[string]string)
}
return o, nil
}
// findPwd returns best guess at current working directory
func findPwd() string {
p, err := os.Getwd()
if err != nil {
return "."
}
return p
}
// isValidService checks to see if a service is a valid service mode
func IsValidService(s string) bool {
switch s {
case
"all",
"proxy",
"authorize",
"authenticate":
return true
}
return false
}
func IsAuthenticate(s string) bool {
switch s {
case
"all",
"authenticate":
return true
}
return false
}
func IsAuthorize(s string) bool {
switch s {
case
"all",
"authorize":
return true
}
return false
}
func IsProxy(s string) bool {
switch s {
case
"all",
"proxy":
return true
}
return false
}