mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 02:16:28 +02:00
Switch options parsing to viper
This commit is contained in:
parent
702cc30b77
commit
febf9464a4
18 changed files with 798 additions and 326 deletions
|
@ -20,25 +20,10 @@ func ValidateOptions(o *config.Options) error {
|
|||
if len(decoded) != 32 {
|
||||
return fmt.Errorf("authorize: `SHARED_SECRET` want 32 but got %d bytes", len(decoded))
|
||||
}
|
||||
if o.Policy == "" && o.PolicyFile == "" {
|
||||
return errors.New("authorize: either `POLICY` or `POLICY_FILE` must be non-nil")
|
||||
}
|
||||
if o.Policy != "" {
|
||||
confBytes, err := base64.StdEncoding.DecodeString(o.Policy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("authorize: `POLICY` is invalid base64 %v", err)
|
||||
}
|
||||
_, err = policy.FromConfig(confBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("authorize: `POLICY` %v", err)
|
||||
}
|
||||
}
|
||||
if o.PolicyFile != "" {
|
||||
_, err = policy.FromConfigFile(o.PolicyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("authorize: `POLICY_FILE` %v", err)
|
||||
}
|
||||
if len(o.Policies) == 0 {
|
||||
return errors.New("missing setting: no policies defined")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -61,17 +46,10 @@ func New(opts *config.Options) (*Authorize, error) {
|
|||
}
|
||||
// errors handled by validate
|
||||
sharedKey, _ := base64.StdEncoding.DecodeString(opts.SharedKey)
|
||||
var policies []policy.Policy
|
||||
if opts.Policy != "" {
|
||||
confBytes, _ := base64.StdEncoding.DecodeString(opts.Policy)
|
||||
policies, _ = policy.FromConfig(confBytes)
|
||||
} else {
|
||||
policies, _ = policy.FromConfigFile(opts.PolicyFile)
|
||||
}
|
||||
|
||||
return &Authorize{
|
||||
SharedKey: string(sharedKey),
|
||||
identityAccess: NewIdentityWhitelist(policies),
|
||||
identityAccess: NewIdentityWhitelist(opts.Policies),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,52 +1,36 @@
|
|||
package authorize
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/config"
|
||||
"github.com/pomerium/pomerium/internal/policy"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
t.Parallel()
|
||||
content := []byte(`[{"from": "pomerium.io","to":"httpbin.org"}]`)
|
||||
tmpfile, err := ioutil.TempFile("", "example")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove(tmpfile.Name()) // clean up
|
||||
|
||||
if _, err := tmpfile.Write(content); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := tmpfile.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
goodPolicy := policy.Policy{From: "pomerium.io", To: "httpbin.org"}
|
||||
goodPolicy.Validate()
|
||||
policies := []policy.Policy{
|
||||
goodPolicy,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
SharedKey string
|
||||
Policy string
|
||||
PolicyFile string
|
||||
wantErr bool
|
||||
name string
|
||||
SharedKey string
|
||||
Policies []policy.Policy
|
||||
wantErr bool
|
||||
}{
|
||||
{"good", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "WwogIHsKICAgICJyb3V0ZXMiOiAiaHR0cDovL3BvbWVyaXVtLmlvIgogIH0KXQ==", "", false},
|
||||
{"bad shared secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", "WwogIHsKICAgICJyb3V0ZXMiOiAiaHR0cDovL3BvbWVyaXVtLmlvIgogIH0KXQ==", "", true},
|
||||
{"really bad shared secret", "sup", "WwogIHsKICAgICJyb3V0ZXMiOiAiaHR0cDovL3BvbWVyaXVtLmlvIgogIH0KXQ==", "", true},
|
||||
{"bad base64 policy", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "WwogIHsKICAgICJyb3V0ZXMiOiAiaHR0cDovL3BvbWVyaXVtLmlvIgogIH0KXQ^=", "", true},
|
||||
{"bad json", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "e30=", "", true},
|
||||
{"no policies", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "", "", true},
|
||||
{"good policy file", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "", "./testdata/basic.json", true},
|
||||
{"bad policy file, directory", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "", "./testdata/", true},
|
||||
{"good policy", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "WwogIHsKICAgICJyb3V0ZXMiOiAiaHR0cDovL3BvbWVyaXVtLmlvIgogIH0KXQ==", "", false},
|
||||
{"good file", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", "", tmpfile.Name(), false},
|
||||
{"validation error, short secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", "", "", true},
|
||||
{"nil options", "", "", "", true}, // special case
|
||||
{"good", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", policies, false},
|
||||
{"bad shared secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", policies, true},
|
||||
{"really bad shared secret", "sup", policies, true},
|
||||
{"validation error, short secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", policies, true},
|
||||
{"nil options", "", []policy.Policy{}, true}, // special case
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := &config.Options{SharedKey: tt.SharedKey, Policy: tt.Policy, PolicyFile: tt.PolicyFile}
|
||||
o := &config.Options{SharedKey: tt.SharedKey, Policies: tt.Policies}
|
||||
if tt.name == "nil options" {
|
||||
o = nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
)
|
||||
|
||||
var versionFlag = flag.Bool("version", false, "prints the version")
|
||||
var configFile = flag.String("config", "", "Specify configuration file location")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
@ -31,7 +32,7 @@ func main() {
|
|||
fmt.Println(version.FullVersion())
|
||||
os.Exit(0)
|
||||
}
|
||||
opt, err := config.OptionsFromEnvConfig()
|
||||
opt, err := parseOptions(*configFile)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("cmd/pomerium: options")
|
||||
}
|
||||
|
@ -169,8 +170,8 @@ func wrapMiddleware(o *config.Options, mux *http.ServeMux) http.Handler {
|
|||
return c.Then(mux)
|
||||
}
|
||||
|
||||
func parseOptions() (*config.Options, error) {
|
||||
o, err := config.OptionsFromEnvConfig()
|
||||
func parseOptions(configFile string) (*config.Options, error) {
|
||||
o, err := config.OptionsFromViper(configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/policy"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/config"
|
||||
"github.com/pomerium/pomerium/internal/middleware"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -110,7 +112,6 @@ func Test_newAuthorizeService(t *testing.T) {
|
|||
}{
|
||||
{"wrong service", "proxy", "", "", false},
|
||||
{"bad option parsing", "authorize", "SharedKey", "false", true},
|
||||
{"bad env", "authorize", "Policy", "error!", true},
|
||||
{"good", "authorize", "SharedKey", "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM=", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -118,7 +119,11 @@ func Test_newAuthorizeService(t *testing.T) {
|
|||
testOpts := config.NewOptions()
|
||||
testOpts.Services = tt.s
|
||||
testOpts.CookieSecret = "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="
|
||||
testOpts.Policy = "LSBmcm9tOiBodHRwYmluLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vaHR0cGJpbgogIGFsbG93ZWRfZG9tYWluczoKICAgIC0gcG9tZXJpdW0uaW8KICBjb3JzX2FsbG93X3ByZWZsaWdodDogdHJ1ZQogIHRpbWVvdXQ6IDMwcwotIGZyb206IGV4dGVybmFsLWh0dHBiaW4uY29ycC5iZXlvbmRwZXJpbWV0ZXIuY29tCiAgdG86IGh0dHBiaW4ub3JnCiAgYWxsb3dlZF9kb21haW5zOgogICAgLSBnbWFpbC5jb20KLSBmcm9tOiB3ZWlyZGx5c3NsLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vbmV2ZXJzc2wuY29tCiAgYWxsb3dlZF91c2VyczoKICAgIC0gYmRkQHBvbWVyaXVtLmlvCiAgYWxsb3dlZF9ncm91cHM6CiAgICAtIGFkbWlucwogICAgLSBkZXZlbG9wZXJzCi0gZnJvbTogaGVsbG8uY29ycC5iZXlvbmRwZXJpbWV0ZXIuY29tCiAgdG86IGh0dHA6Ly9oZWxsbzo4MDgwCiAgYWxsb3dlZF9ncm91cHM6CiAgICAtIGFkbWlucw=="
|
||||
testPolicy := policy.Policy{From: "pomerium.io", To: "httpbin.org"}
|
||||
testPolicy.Validate()
|
||||
testOpts.Policies = []policy.Policy{
|
||||
testPolicy,
|
||||
}
|
||||
|
||||
if tt.Field != "" {
|
||||
testOptsField := reflect.ValueOf(testOpts).Elem().FieldByName(tt.Field)
|
||||
|
@ -146,16 +151,19 @@ func Test_newProxyeService(t *testing.T) {
|
|||
}{
|
||||
{"wrong service", "authenticate", "", "", false},
|
||||
{"bad option parsing", "proxy", "SharedKey", "false", true},
|
||||
{"bad env", "proxy", "Policy", "error!", true},
|
||||
{"good", "proxy", "SharedKey", "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM=", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
testOpts := config.NewOptions()
|
||||
testPolicy := policy.Policy{From: "pomerium.io", To: "httpbin.org"}
|
||||
testPolicy.Validate()
|
||||
testOpts.Policies = []policy.Policy{
|
||||
testPolicy,
|
||||
}
|
||||
testOpts.AuthenticateURL, _ = url.Parse("https://authenticate.example.com")
|
||||
testOpts.AuthorizeURL, _ = url.Parse("https://authorize.example.com")
|
||||
testOpts.Policy = "LSBmcm9tOiBodHRwYmluLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vaHR0cGJpbgogIGFsbG93ZWRfZG9tYWluczoKICAgIC0gcG9tZXJpdW0uaW8KICBjb3JzX2FsbG93X3ByZWZsaWdodDogdHJ1ZQogIHRpbWVvdXQ6IDMwcwotIGZyb206IGV4dGVybmFsLWh0dHBiaW4uY29ycC5iZXlvbmRwZXJpbWV0ZXIuY29tCiAgdG86IGh0dHBiaW4ub3JnCiAgYWxsb3dlZF9kb21haW5zOgogICAgLSBnbWFpbC5jb20KLSBmcm9tOiB3ZWlyZGx5c3NsLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vbmV2ZXJzc2wuY29tCiAgYWxsb3dlZF91c2VyczoKICAgIC0gYmRkQHBvbWVyaXVtLmlvCiAgYWxsb3dlZF9ncm91cHM6CiAgICAtIGFkbWlucwogICAgLSBkZXZlbG9wZXJzCi0gZnJvbTogaGVsbG8uY29ycC5iZXlvbmRwZXJpbWV0ZXIuY29tCiAgdG86IGh0dHA6Ly9oZWxsbzo4MDgwCiAgYWxsb3dlZF9ncm91cHM6CiAgICAtIGFkbWlucw=="
|
||||
testOpts.CookieSecret = "YixWi1MYh77NMECGGIJQevoonYtVF+ZPRkQZrrmeRqM="
|
||||
testOpts.Services = tt.s
|
||||
|
||||
|
@ -219,7 +227,7 @@ func Test_parseOptions(t *testing.T) {
|
|||
os.Setenv(tt.envKey, tt.envValue)
|
||||
defer os.Unsetenv(tt.envKey)
|
||||
|
||||
got, err := parseOptions()
|
||||
got, err := parseOptions("")
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parseOptions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
|
|
25
config-policy-only.yaml
Normal file
25
config-policy-only.yaml
Normal file
|
@ -0,0 +1,25 @@
|
|||
### Other keys configuration removed for clarity ###
|
||||
|
||||
# Proxied routes and per-route policies are defined in a policy block
|
||||
policy: # Omit the 'policy' key if you are encoding it into an environment variable
|
||||
- from: httpbin.corp.beyondperimeter.com
|
||||
to: http://httpbin
|
||||
allowed_domains:
|
||||
- pomerium.io
|
||||
cors_allow_preflight: true
|
||||
timeout: 30s
|
||||
- from: external-httpbin.corp.beyondperimeter.com
|
||||
to: httpbin.org
|
||||
allowed_domains:
|
||||
- gmail.com
|
||||
- from: weirdlyssl.corp.beyondperimeter.com
|
||||
to: http://neverssl.com
|
||||
allowed_users:
|
||||
- bdd@pomerium.io
|
||||
allowed_groups:
|
||||
- admins
|
||||
- developers
|
||||
- from: hello.corp.beyondperimeter.com
|
||||
to: http://hello:8080
|
||||
allowed_groups:
|
||||
- admins
|
89
config.example.yaml
Normal file
89
config.example.yaml
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Main configuration flags
|
||||
address: ":8443" # optional, default is 443
|
||||
pomerium_debug: true # optional, default is false
|
||||
service: "all" # optional, default is all
|
||||
# log_level: "info" # optional, default is debug
|
||||
|
||||
authenticate_service_url: https://authenticate.corp.pomerium.io:8443
|
||||
authorize_service_url: https://authorize.corp.pomerium.io:8443
|
||||
|
||||
# Certificates can be loaded as files or base64 encoded bytes. If neither is set, a
|
||||
# pomerium will attempt to locate a pair in the root directory
|
||||
certificate_file: "./cert.pem" # optional, defaults to `./cert.pem`
|
||||
certificate_key_file: "./privkey.pem" # optional, defaults to `./certprivkey.pem`
|
||||
certificate_authority_file: "./cert.pem"
|
||||
# certificate: |
|
||||
# "xxxxxx" # base64 encoded cert, eg. `base64 -i cert.pem`
|
||||
# certificate_key: |
|
||||
# "xxxx" # base64 encoded key, eg. `base64 -i privkey.pem`
|
||||
|
||||
# Generate 256 bit random keys e.g. `head -c32 /dev/urandom | base64`
|
||||
shared_secret: hsJIQsx9KKx4qVlggg/T3AuLTmVu0uHhwTQgMPlVs7U=
|
||||
cookie_secret: WwMtDXWaRDMBQCylle8OJ+w4kLIDIGd8W3cB4/zFFtg=
|
||||
# If set, a JWT based signature is appended to each request header `x-pomerium-jwt-assertion`
|
||||
# signing_key: "Replace with base64'd private key from ./scripts/self-signed-sign-key.sh"
|
||||
|
||||
# Identity Provider Settings
|
||||
|
||||
# Azure
|
||||
# idp_provider: "azure"
|
||||
# idp_provider_url: "https://login.microsoftonline.com/REPLACEME/v2.0"
|
||||
# idp_client_id: "REPLACEME
|
||||
# idp_client_secret: "REPLACEME"
|
||||
|
||||
# Gitlab
|
||||
# idp_provider: "gitlab"
|
||||
# idp_provider_url: "https://gitlab.onprem.example.com" # optional, defaults to `https://gitlab.com`
|
||||
# idp_client_id: "REPLACEME
|
||||
# idp_client_secret: "REPLACEME"
|
||||
|
||||
## GOOGLE
|
||||
# idp_provider: "google"
|
||||
# idp_provider_url: "https://accounts.google.com" # optional for google
|
||||
# idp_client_id: "REPLACEME
|
||||
# idp_client_secret: "REPLACEME
|
||||
|
||||
# IF GSUITE and you want to get user groups you will need to set a service account
|
||||
# see identity provider docs for gooogle for more info :
|
||||
# idp_service_account: $(echo '{"impersonate_user": "bdd@pomerium.io"}' | base64)
|
||||
|
||||
# OKTA
|
||||
# idp_provider: "okta"
|
||||
# idp_client_id: "REPLACEME"
|
||||
# idp_client_secret: "replaceme"
|
||||
# idp_provider_url: "https://REPLACEME.oktapreview.com/oauth2/default"
|
||||
|
||||
# OneLogin
|
||||
# idp_provider: "onelogin"
|
||||
# idp_client_id: "REPLACEME"
|
||||
# idp_client_secret: "REPLACEME"
|
||||
# idp_provider_url: "https://openid-connect.onelogin.com/oidc" #optional, defaults to `https://openid-connect.onelogin.com/oidc`
|
||||
|
||||
# scope: "openid email" # generally, you want the default OIDC scopes
|
||||
|
||||
# Proxied routes and per-route policies are defined in a policy block
|
||||
policy:
|
||||
- from: httpbin.corp.beyondperimeter.com
|
||||
to: http://httpbin
|
||||
allowed_domains:
|
||||
- pomerium.io
|
||||
cors_allow_preflight: true
|
||||
timeout: 30s
|
||||
- from: external-httpbin.corp.beyondperimeter.com
|
||||
to: httpbin.org
|
||||
allowed_domains:
|
||||
- gmail.com
|
||||
- from: weirdlyssl.corp.beyondperimeter.com
|
||||
to: http://neverssl.com
|
||||
allowed_users:
|
||||
- bdd@pomerium.io
|
||||
allowed_groups:
|
||||
- admins
|
||||
- developers
|
||||
- from: hello.corp.beyondperimeter.com
|
||||
to: http://hello:8080
|
||||
allowed_groups:
|
||||
- admins
|
||||
- from: external-search.corp.beyondperimeter.com
|
||||
to: google.com
|
||||
allow_public_unauthenticated_access: true
|
|
@ -2,14 +2,19 @@
|
|||
sidebar: auto
|
||||
---
|
||||
|
||||
# Configuration Variables
|
||||
# Configuration
|
||||
|
||||
Pomerium uses [environmental variables] to set configuration settings. If you are coming from a kubernetes or docker background this should feel familiar. If not, check out the following primers.
|
||||
Pomerium can use a combination of a YAML/JSON/TOML configuration file and [environmental variables] to set configuration settings.
|
||||
|
||||
If you are coming from a kubernetes or docker background this should feel familiar. If not, check out the following primers.
|
||||
|
||||
- [Store config in the environment](https://12factor.net/config)
|
||||
- [Kubernetes: Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
|
||||
- [Kubernetes: Config Maps](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/)
|
||||
- [Docker: Environment variables](https://docs.docker.com/compose/environment-variables/)
|
||||
|
||||
In general, any setting specified by environment variable can also be present in the optional config file as the same name but lower cased. Environment variables take precedence.
|
||||
|
||||
## Global settings
|
||||
|
||||
These are configuration variables shared by all services, in all service modes.
|
||||
|
@ -17,6 +22,7 @@ These are configuration variables shared by all services, in all service modes.
|
|||
### Service Mode
|
||||
|
||||
- Environmental Variable: `SERVICES`
|
||||
- Config File Key: `services`
|
||||
- Type: `string`
|
||||
- Default: `all`
|
||||
- Options: `all` `authenticate` `authorize` or `proxy`
|
||||
|
@ -26,6 +32,7 @@ Service mode sets the pomerium service(s) to run. If testing, you may want to se
|
|||
### Address
|
||||
|
||||
- Environmental Variable: `ADDRESS`
|
||||
- Config File Key: `address`
|
||||
- Type: `string`
|
||||
- Example: `:https`, `:443`, `:8443`
|
||||
- Default: `:https`
|
||||
|
@ -36,6 +43,7 @@ Address specifies the host and port to serve HTTPS and gRPC requests from. If em
|
|||
### Shared Secret
|
||||
|
||||
- Environmental Variable: `SHARED_SECRET`
|
||||
- Config File Key: `shared_secret`
|
||||
- Type: [base64 encoded] `string`
|
||||
- Required
|
||||
|
||||
|
@ -48,6 +56,7 @@ head -c32 /dev/urandom | base64
|
|||
### Debug
|
||||
|
||||
- Environmental Variable: `POMERIUM_DEBUG`
|
||||
- Config File Key: `pomerium_debug`
|
||||
- Type: `bool`
|
||||
- Default: `false`
|
||||
|
||||
|
@ -74,6 +83,7 @@ If `false`
|
|||
### Log Level
|
||||
|
||||
- Environmental Variable: `LOG_LEVEL`
|
||||
- Config File Key: `log_level`
|
||||
- Type: `string`
|
||||
- Options: `debug` `info` `warn` `error`
|
||||
- Default: `debug`
|
||||
|
@ -83,6 +93,7 @@ Log level sets the global logging level for pomerium. Only logs of the desired l
|
|||
### Certificate
|
||||
|
||||
- Environmental Variable: either `CERTIFICATE` or `CERTIFICATE_FILE`
|
||||
- Config File Key: `certificate` or `certificate_file`
|
||||
- Type: [base64 encoded] `string` or relative file location
|
||||
- Required
|
||||
|
||||
|
@ -91,6 +102,7 @@ Certificate is the x509 _public-key_ used to establish secure HTTP and gRPC conn
|
|||
### Certificate Key
|
||||
|
||||
- Environmental Variable: either `CERTIFICATE_KEY` or `CERTIFICATE_KEY_FILE`
|
||||
- Config File Key: `certificate_key` or `certificate_key_file`
|
||||
- Type: [base64 encoded] `string`
|
||||
- Required
|
||||
|
||||
|
@ -99,6 +111,7 @@ Certificate key is the x509 _private-key_ used to establish secure HTTP and gRPC
|
|||
### Global Timeouts
|
||||
|
||||
- Environmental Variables: `TIMEOUT_READ` `TIMEOUT_WRITE` `TIMEOUT_READ_HEADER` `TIMEOUT_IDLE`
|
||||
- Config File Key: `timeout_read` `timeout_write` `timeout_read_header` `timeout_idle`
|
||||
- Type: [Go Duration](https://golang.org/pkg/time/#Duration.String) `string`
|
||||
- Example: `TIMEOUT_READ=30s`
|
||||
- Defaults: `TIMEOUT_READ_HEADER=10s` `TIMEOUT_READ=30s` `TIMEOUT_WRITE=0` `TIMEOUT_IDLE=5m`
|
||||
|
@ -112,6 +125,7 @@ Timeouts set the global server timeouts. For route-specific timeouts, see [polic
|
|||
### HTTP Redirect Address
|
||||
|
||||
- Environmental Variable: `HTTP_REDIRECT_ADDR`
|
||||
- Config File Key: `http_redirect_addr`
|
||||
- Type: `string`
|
||||
- Example: `:80`, `:http`, `:8080`
|
||||
- Optional
|
||||
|
@ -120,14 +134,14 @@ If set, the HTTP Redirect Address specifies the host and port to redirect http t
|
|||
|
||||
### Policy
|
||||
|
||||
- Environmental Variable: either `POLICY` or `POLICY_FILE`
|
||||
- Type: [base64 encoded] `string` or relative file location
|
||||
- Filetype: `json` or `yaml`
|
||||
- Environmental Variable: `POLICY`
|
||||
- Config File Key: `policy`
|
||||
- Type: [base64 encoded] `string` or inline policy structure in config file
|
||||
- Required
|
||||
|
||||
Policy contains route specific settings, and access control details. For example,
|
||||
Policy contains route specific settings, and access control details. If you are configuring via POLICY environment variable, just the contents of the policy needs to be passed. If you are configuring via file, the policy should be present under the policy key. For example,
|
||||
|
||||
<<< @/policy.example.yaml
|
||||
<<< @/config-policy-only.yaml
|
||||
|
||||
A list of policy configuration variables follows.
|
||||
|
||||
|
@ -211,6 +225,7 @@ Policy timeout establishes the per-route timeout value. Cannot exceed global tim
|
|||
### Authenticate Service URL
|
||||
|
||||
- Environmental Variable: `AUTHENTICATE_SERVICE_URL`
|
||||
- Config File Key: `authenticate_service_url`
|
||||
- Type: `URL`
|
||||
- Required
|
||||
- Example: `https://authenticate.corp.example.com`
|
||||
|
@ -220,6 +235,7 @@ Authenticate Service URL is the externally accessible URL for the authenticate s
|
|||
### Identity Provider Name
|
||||
|
||||
- Environmental Variable: `IDP_PROVIDER`
|
||||
- Config File Key: `idp_provider`
|
||||
- Type: `string`
|
||||
- Required
|
||||
- Options: `azure` `google` `okta` `gitlab` `onelogin` or `oidc`
|
||||
|
@ -231,6 +247,7 @@ See [identity provider] for details.
|
|||
### Identity Provider Client ID
|
||||
|
||||
- Environmental Variable: `IDP_CLIENT_ID`
|
||||
- Config File Key: `idp_client_id`
|
||||
- Type: `string`
|
||||
- Required
|
||||
|
||||
|
@ -239,6 +256,7 @@ Client ID is the OAuth 2.0 Client Identifier retrieved from your identity provid
|
|||
### Identity Provider Client Secret
|
||||
|
||||
- Environmental Variable: `IDP_CLIENT_SECRET`
|
||||
- Config File Key: `idp_client_secret`
|
||||
- Type: `string`
|
||||
- Required
|
||||
|
||||
|
@ -247,6 +265,7 @@ Client Secret is the OAuth 2.0 Secret Identifier retrieved from your identity pr
|
|||
### Identity Provider URL
|
||||
|
||||
- Environmental Variable: `IDP_PROVIDER_URL`
|
||||
- Config File Key: `idp_provider_url`
|
||||
- Type: `string`
|
||||
- Required, depending on provider
|
||||
|
||||
|
@ -255,6 +274,7 @@ Provider URL is the base path to an identity provider's [OpenID connect discover
|
|||
### Identity Provider Scopes
|
||||
|
||||
- Environmental Variable: `IDP_SCOPES`
|
||||
- Config File Key: `idp_scopes`
|
||||
- Type: `[]string` comma separated list of oauth scopes.
|
||||
- Default: `oidc`,`profile`, `email`, `offline_access` (typically)
|
||||
- Optional for built-in identity providers.
|
||||
|
@ -264,6 +284,7 @@ Identity provider scopes correspond to access privilege scopes as defined in Sec
|
|||
### Identity Provider Service Account
|
||||
|
||||
- Environmental Variable: `IDP_SERVICE_ACCOUNT`
|
||||
- Config File Key: `idp_service_account`
|
||||
- Type: `string`
|
||||
- Required, depending on provider
|
||||
|
||||
|
@ -274,6 +295,7 @@ Identity Provider Service Account is field used to configure any additional user
|
|||
### Signing Key
|
||||
|
||||
- Environmental Variable: `SIGNING_KEY`
|
||||
- Config File Key: `signing_key`
|
||||
- Type: [base64 encoded] `string`
|
||||
- Optional
|
||||
|
||||
|
@ -282,6 +304,7 @@ Signing key is the base64 encoded key used to sign outbound requests. For more i
|
|||
### Authenticate Service URL
|
||||
|
||||
- Environmental Variable: `AUTHENTICATE_SERVICE_URL`
|
||||
- Config File Key: `authenticate_service_url`
|
||||
- Type: `URL`
|
||||
- Required
|
||||
- Example: `https://authenticate.corp.example.com`
|
||||
|
@ -291,6 +314,7 @@ Authenticate Service URL is the externally accessible URL for the authenticate s
|
|||
### Authenticate Internal Service URL
|
||||
|
||||
- Environmental Variable: `AUTHENTICATE_INTERNAL_URL`
|
||||
- Config File Key: `authenticate_internal_url`
|
||||
- Type: `string`
|
||||
- Optional
|
||||
- Example: `pomerium-authenticate-service.pomerium.svc.cluster.local`
|
||||
|
@ -300,6 +324,7 @@ Authenticate Internal Service URL is the internally routed dns name of the authe
|
|||
### Authorize Service URL
|
||||
|
||||
- Environmental Variable: `AUTHORIZE_SERVICE_URL`
|
||||
- Config File Key: `authorize_service_url`
|
||||
- Type: `URL`
|
||||
- Required
|
||||
- Example: `https://access.corp.example.com` or `pomerium-authorize-service.pomerium.svc.cluster.local`
|
||||
|
@ -311,6 +336,7 @@ If your load balancer does not support gRPC pass-through you'll need to set this
|
|||
### Override Certificate Name
|
||||
|
||||
- Environmental Variable: `OVERRIDE_CERTIFICATE_NAME`
|
||||
- Config File Key: `override_certificate_name`
|
||||
- Type: `int`
|
||||
- Optional (but typically required if Authenticate Internal Service Address is set)
|
||||
- Example: `*.corp.example.com` if wild card or `authenticate.corp.example.com`/`authorize.corp.example.com`
|
||||
|
@ -320,6 +346,7 @@ When Authenticate Internal Service Address is set, secure service communication
|
|||
### Certificate Authority
|
||||
|
||||
- Environmental Variable: `CERTIFICATE_AUTHORITY` or `CERTIFICATE_AUTHORITY_FILE`
|
||||
- Config File Key: `certificate_authority` or `certificate_authority_file`
|
||||
- Type: [base64 encoded] `string` or relative file location
|
||||
- Optional
|
||||
|
||||
|
@ -328,6 +355,7 @@ Certificate Authority is set when behind-the-ingress service communication uses
|
|||
### Headers
|
||||
|
||||
- Environmental Variable: `HEADERS`
|
||||
- Config File Key: `headers`
|
||||
- Type: map of `strings` key value pairs
|
||||
- Example: `X-Content-Type-Options:nosniff,X-Frame-Options:SAMEORIGIN`
|
||||
- To disable: `disable:true`
|
||||
|
|
|
@ -61,6 +61,6 @@ export IDP_CLIENT_SECRET="REPLACEME"
|
|||
# export SCOPE="openid email" # generally, you want the default OIDC scopes
|
||||
|
||||
# Proxied routes and per-route policies are defined in a policy provided either
|
||||
# directly as a base64 encoded yaml/json file, or as a path pointing to a
|
||||
# policy file (`POLICY_FILE`)
|
||||
export POLICY_FILE="./policy.example.yml"
|
||||
# directly as a base64 encoded yaml/json file, or as the policy key in the configuration
|
||||
# file
|
||||
export POLICY="$(base64 ./policy.yaml)"
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,13 +3,13 @@ module github.com/pomerium/pomerium
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/golang/mock v1.2.0
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/pomerium/envconfig v1.5.0
|
||||
github.com/pomerium/go-oidc v2.0.0+incompatible
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
|
||||
github.com/rs/zerolog v1.12.0
|
||||
github.com/spf13/viper v1.3.2
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25
|
||||
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7
|
||||
|
|
105
go.sum
105
go.sum
|
@ -2,16 +2,40 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
|
@ -19,11 +43,35 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pomerium/envconfig v1.5.0 h1:OeYS/p6AUxKFqCZHM5BG7pUb0m3MkaC1ZhRLPTHbk8g=
|
||||
|
@ -33,26 +81,69 @@ github.com/pomerium/go-oidc v2.0.0+incompatible/go.mod h1:DRsGVw6MOgxbfq4Y57jKOE
|
|||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rs/zerolog v1.12.0 h1:aqZ1XRadoS8IBknR5IDFvGzbHly1X9ApIqOroooQF/c=
|
||||
github.com/rs/zerolog v1.12.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7 h1:Qe/u+eY379X4He4GBMFZYu3pmh1ML5yT1aL1ndNM1zQ=
|
||||
golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
||||
|
@ -62,16 +153,23 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0 h1:K6z2u68e86TPdSdefXdzvXgR1zEMa+459vBSfWYAZkI=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
|
@ -86,14 +184,21 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk
|
|||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099 h1:XJP7lxbSxWLOMNdBE4B/STaqVy6L73o0knwj2vIlxnw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/envconfig"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/policy"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// DisableHeaderKey is the key used to check whether to disable setting header
|
||||
|
@ -22,97 +26,99 @@ const DisableHeaderKey = "disable"
|
|||
// 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"`
|
||||
Debug bool `mapstructure:"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"`
|
||||
LogLevel string `mapstructure:"log_level"`
|
||||
|
||||
// SharedKey is the shared secret authorization key used to mutually authenticate
|
||||
// requests between services.
|
||||
SharedKey string `envconfig:"SHARED_SECRET"`
|
||||
SharedKey string `mapstructure:"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"`
|
||||
Services string `mapstructure:"services"`
|
||||
|
||||
// Addr specifies the host and port on which the server should serve
|
||||
// HTTPS requests. If empty, ":https" is used.
|
||||
Addr string `envconfig:"ADDRESS"`
|
||||
Addr string `mapstructure:"address"`
|
||||
|
||||
// Cert and Key specifies the base64 encoded TLS certificates to use.
|
||||
Cert string `envconfig:"CERTIFICATE"`
|
||||
Key string `envconfig:"CERTIFICATE_KEY"`
|
||||
Cert string `mapstructure:"certificate"`
|
||||
Key string `mapstructure:"certificate_key"`
|
||||
|
||||
// CertFile and KeyFile specifies the TLS certificates to use.
|
||||
CertFile string `envconfig:"CERTIFICATE_FILE"`
|
||||
KeyFile string `envconfig:"CERTIFICATE_KEY_FILE"`
|
||||
CertFile string `mapstructure:"certificate_file"`
|
||||
KeyFile string `mapstructure:"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"`
|
||||
HTTPRedirectAddr string `mapstructure:"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"`
|
||||
ReadTimeout time.Duration `mapstructure:"timeout_read"`
|
||||
WriteTimeout time.Duration `mapstructure:"timeout_write"`
|
||||
ReadHeaderTimeout time.Duration `mapstructure:"timeout_read_header"`
|
||||
IdleTimeout time.Duration `mapstructure:"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"`
|
||||
PolicyEnv string
|
||||
PolicyFile string `mapstructure:"policy_file"`
|
||||
|
||||
// AuthenticateURL represents the externally accessible http endpoints
|
||||
// used for authentication requests and callbacks
|
||||
AuthenticateURL *url.URL `envconfig:"AUTHENTICATE_SERVICE_URL"`
|
||||
AuthenticateURLString string `mapstructure:"authenticate_service_url"`
|
||||
AuthenticateURL *url.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"`
|
||||
CookieName string `mapstructure:"cookie_name"`
|
||||
CookieSecret string `mapstructure:"cookie_secret"`
|
||||
CookieDomain string `mapstructure:"cookie_domain"`
|
||||
CookieSecure bool `mapstructure:"cookie_secure"`
|
||||
CookieHTTPOnly bool `mapstructure:"cookie_http_only"`
|
||||
CookieExpire time.Duration `mapstructure:"cookie_expire"`
|
||||
CookieRefresh time.Duration `mapstructure:"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"`
|
||||
ClientID string `mapstructure:"idp_client_id"`
|
||||
ClientSecret string `mapstructure:"idp_client_secret"`
|
||||
Provider string `mapstructure:"idp_provider"`
|
||||
ProviderURL string `mapstructure:"idp_provider_url"`
|
||||
Scopes []string `mapstructure:"idp_scopes"`
|
||||
ServiceAccount string `mapstructure:"idp_service_account"`
|
||||
|
||||
Policies []policy.Policy `envconfig:"POLICY"`
|
||||
Policies []policy.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"`
|
||||
AuthenticateInternalAddr string `mapstructure:"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"`
|
||||
AuthorizeURLString string `mapstructure:"authorize_service_url"`
|
||||
AuthorizeURL *url.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"`
|
||||
OverrideCertificateName string `mapstructure:"override_certificate_name"`
|
||||
CA string `mapstructure:"certificate_authority"`
|
||||
CAFile string `mapstructure:"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"`
|
||||
SigningKey string `mapstructure:"signing_key"`
|
||||
|
||||
// Headers to set on all proxied requests. Add a 'disable' key map to turn off.
|
||||
Headers map[string]string `envconfig:"HEADERS"`
|
||||
Headers map[string]string `mapstructure:"headers"`
|
||||
|
||||
// Sub-routes
|
||||
Routes map[string]string `envconfig:"ROUTES"`
|
||||
DefaultUpstreamTimeout time.Duration `envconfig:"DEFAULT_UPSTREAM_TIMEOUT"`
|
||||
Routes map[string]string `mapstructure:"routes"`
|
||||
DefaultUpstreamTimeout time.Duration `mapstructure:"default_upstream_timeout"`
|
||||
}
|
||||
|
||||
// NewOptions returns a new options struct with default vaules
|
||||
|
@ -146,19 +152,39 @@ func NewOptions() *Options {
|
|||
return o
|
||||
}
|
||||
|
||||
// OptionsFromEnvConfig builds the main binary's configuration
|
||||
// options from provided environmental variables
|
||||
func OptionsFromEnvConfig() (*Options, error) {
|
||||
// OptionsFromViper builds the main binary's configuration
|
||||
// options by parsing environmental variables and config file
|
||||
func OptionsFromViper(configFile string) (*Options, error) {
|
||||
o := NewOptions()
|
||||
if err := envconfig.Process("", o); err != nil {
|
||||
return nil, err
|
||||
|
||||
// Load up config
|
||||
o.bindEnvs()
|
||||
if configFile != "" {
|
||||
log.Info().Msgf("Loading config from '%s'", configFile)
|
||||
viper.SetConfigFile(configFile)
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read config: %s", err)
|
||||
}
|
||||
}
|
||||
if !IsValidService(o.Services) {
|
||||
return nil, fmt.Errorf("%s is an invalid service type", o.Services)
|
||||
|
||||
err := viper.Unmarshal(o)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to load options from config: %s", err)
|
||||
}
|
||||
if o.SharedKey == "" {
|
||||
return nil, errors.New("shared-key cannot be empty")
|
||||
|
||||
// Turn URL strings into url structs
|
||||
err = o.parseURLs()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse URLs: %s", err)
|
||||
}
|
||||
|
||||
// Load and initialize policy
|
||||
err = o.parsePolicy()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse Policy: %s", err)
|
||||
}
|
||||
|
||||
if o.Debug {
|
||||
log.SetDebugMode()
|
||||
}
|
||||
|
@ -168,9 +194,99 @@ func OptionsFromEnvConfig() (*Options, error) {
|
|||
if _, disable := o.Headers[DisableHeaderKey]; disable {
|
||||
o.Headers = make(map[string]string)
|
||||
}
|
||||
|
||||
err = o.validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// validate ensures the Options fields are properly formed and present
|
||||
func (o *Options) validate() error {
|
||||
|
||||
if !IsValidService(o.Services) {
|
||||
return fmt.Errorf("%s is an invalid service type", o.Services)
|
||||
}
|
||||
|
||||
if o.SharedKey == "" {
|
||||
return errors.New("shared-key cannot be empty")
|
||||
}
|
||||
|
||||
if len(o.Routes) != 0 {
|
||||
return errors.New("routes setting is deprecated, use policy instead")
|
||||
}
|
||||
|
||||
if o.PolicyFile != "" {
|
||||
return errors.New("Setting POLICY_FILE is deprecated, use policy env var or config file instead")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parsePolicy initializes policy
|
||||
func (o *Options) parsePolicy() error {
|
||||
var policies []policy.Policy
|
||||
// Parse from base64 env var
|
||||
if o.PolicyEnv != "" {
|
||||
policyBytes, err := base64.StdEncoding.DecodeString(o.PolicyEnv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not decode POLICY env var: %s", err)
|
||||
}
|
||||
if err := yaml.Unmarshal(policyBytes, &policies); err != nil {
|
||||
return fmt.Errorf("Could not parse POLICY env var: %s", err)
|
||||
}
|
||||
// Parse from file
|
||||
} else {
|
||||
err := viper.UnmarshalKey("policy", &policies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Finish initializing policies
|
||||
for i := range policies {
|
||||
err := (&policies[i]).Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
o.Policies = policies
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseURLs parses URL strings into actual URL pointers
|
||||
func (o *Options) parseURLs() error {
|
||||
AuthenticateURL, err := url.Parse(o.AuthenticateURLString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
AuthorizeURL, err := url.Parse(o.AuthorizeURLString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.AuthenticateURL = AuthenticateURL
|
||||
o.AuthorizeURL = AuthorizeURL
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindEnvs makes sure viper binds to each env var based on the mapstructure tag
|
||||
func (o *Options) bindEnvs() {
|
||||
tagName := `mapstructure`
|
||||
t := reflect.TypeOf(*o)
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
envName := field.Tag.Get(tagName)
|
||||
viper.BindEnv(envName)
|
||||
}
|
||||
|
||||
// Statically bind fields
|
||||
viper.BindEnv("PolicyEnv", "POLICY")
|
||||
}
|
||||
|
||||
// findPwd returns best guess at current working directory
|
||||
func findPwd() string {
|
||||
p, err := os.Getwd()
|
||||
|
@ -180,7 +296,7 @@ func findPwd() string {
|
|||
return p
|
||||
}
|
||||
|
||||
// isValidService checks to see if a service is a valid service mode
|
||||
// IsValidService checks to see if a service is a valid service mode
|
||||
func IsValidService(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
|
@ -193,6 +309,7 @@ func IsValidService(s string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// IsAuthenticate checks to see if we should be running the authenticate service
|
||||
func IsAuthenticate(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
|
@ -203,6 +320,7 @@ func IsAuthenticate(s string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// IsAuthorize checks to see if we should be running the authorize service
|
||||
func IsAuthorize(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
|
@ -213,6 +331,7 @@ func IsAuthorize(s string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// IsProxy checks to see if we should be running the proxy service
|
||||
func IsProxy(s string) bool {
|
||||
switch s {
|
||||
case
|
||||
|
|
|
@ -1,46 +1,54 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/policy"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func Test_optionsFromEnvConfig(t *testing.T) {
|
||||
good := NewOptions()
|
||||
good.SharedKey = "test"
|
||||
func Test_validate(t *testing.T) {
|
||||
|
||||
testOptions := func() *Options {
|
||||
o := NewOptions()
|
||||
o.SharedKey = "test"
|
||||
o.Services = "all"
|
||||
return o
|
||||
}
|
||||
good := testOptions()
|
||||
badServices := testOptions()
|
||||
badServices.Services = "blue"
|
||||
badSecret := testOptions()
|
||||
badSecret.SharedKey = ""
|
||||
badRoutes := testOptions()
|
||||
badRoutes.Routes = map[string]string{"foo": "bar"}
|
||||
badPolicyFile := testOptions()
|
||||
badPolicyFile.PolicyFile = "file"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
want *Options
|
||||
envKey string
|
||||
envValue string
|
||||
testOpts *Options
|
||||
wantErr bool
|
||||
}{
|
||||
{"good default with no env settings", good, "", "", false},
|
||||
{"invalid service type", nil, "SERVICES", "invalid", true},
|
||||
{"good service", good, "SERVICES", "all", false},
|
||||
{"bad debug boolean", nil, "POMERIUM_DEBUG", "yes", true},
|
||||
{"missing shared secret", nil, "SHARED_SECRET", "", true},
|
||||
{"good default with no env settings", good, false},
|
||||
{"invalid service type", badServices, true},
|
||||
{"missing shared secret", badSecret, true},
|
||||
{"routes present", badRoutes, true},
|
||||
{"policy file specified", badPolicyFile, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
os.Clearenv()
|
||||
if tt.envKey != "" {
|
||||
os.Setenv(tt.envKey, tt.envValue)
|
||||
}
|
||||
if tt.envKey != "SHARED_SECRET" {
|
||||
os.Setenv("SHARED_SECRET", "test")
|
||||
}
|
||||
got, err := OptionsFromEnvConfig()
|
||||
os.Unsetenv(tt.envKey)
|
||||
|
||||
err := tt.testOpts.validate()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("optionsFromEnvConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("optionsFromEnvConfig() = got %#v,\n want %#v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -89,3 +97,220 @@ func Test_isAuthenticate(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_isAuthorize(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
service string
|
||||
want bool
|
||||
}{
|
||||
{"proxy", "proxy", false},
|
||||
{"all", "all", true},
|
||||
{"authorize", "authorize", true},
|
||||
{"authorize bad case", "AuThorize", false},
|
||||
{"authenticate implemented", "authenticate", false},
|
||||
{"jiberish", "xd23", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := IsAuthorize(tt.service); got != tt.want {
|
||||
t.Errorf("isAuthenticate() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
func Test_bindEnvs(t *testing.T) {
|
||||
o := &Options{}
|
||||
os.Clearenv()
|
||||
defer os.Unsetenv("POMERIUM_DEBUG")
|
||||
defer os.Unsetenv("POLICY")
|
||||
os.Setenv("POMERIUM_DEBUG", "true")
|
||||
os.Setenv("POLICY", "mypolicy")
|
||||
o.bindEnvs()
|
||||
err := viper.Unmarshal(o)
|
||||
if err != nil {
|
||||
t.Errorf("Could not unmarshal %#v: %s", o, err)
|
||||
}
|
||||
if !o.Debug {
|
||||
t.Errorf("Failed to load POMERIUM_DEBUG from environment")
|
||||
}
|
||||
if o.Services != "" {
|
||||
t.Errorf("Somehow got SERVICES from environment without configuring it")
|
||||
}
|
||||
if o.PolicyEnv != "mypolicy" {
|
||||
t.Errorf("Failed to bind policy env var to PolicyEnv")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseURLs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
authorizeURL string
|
||||
authenticateURL string
|
||||
wantErr bool
|
||||
}{
|
||||
{"good", "https://authz.mydomain.tld", "https://authn.mydomain.tld", false},
|
||||
{"bad authorize", "notaurl", "https://authn.mydomain.tld", true},
|
||||
{"bad authenticate", "https://authz.mydomain.tld", "notaurl", true},
|
||||
{"only authn", "", "https://authn.mydomain.tld", false},
|
||||
{"only authz", "https://authz.mydomain.tld", "", false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
o := &Options{
|
||||
AuthenticateURLString: test.authenticateURL,
|
||||
AuthorizeURLString: test.authorizeURL,
|
||||
}
|
||||
err := o.parseURLs()
|
||||
if !test.wantErr && err != nil {
|
||||
t.Errorf("Failed to parse URLs %v: %s", test, err)
|
||||
}
|
||||
if o.AuthenticateURL.String() != test.authenticateURL {
|
||||
t.Errorf("Failed to update AuthenticateURL: %v", test)
|
||||
}
|
||||
if o.AuthorizeURL.String() != test.authorizeURL {
|
||||
t.Errorf("Failed to update AuthorizeURL: %v", test)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_OptionsFromViper(t *testing.T) {
|
||||
testPolicy := policy.Policy{
|
||||
To: "https://httpbin.org",
|
||||
From: "https://pomerium.io",
|
||||
}
|
||||
testPolicy.Validate()
|
||||
testPolicies := []policy.Policy{
|
||||
testPolicy,
|
||||
}
|
||||
|
||||
goodConfigBytes := []byte(`{"shared_secret":"Setec Astronomy","service":"all","policy":[{"from":"https://pomerium.io","to":"https://httpbin.org"}]}`)
|
||||
goodOptions := NewOptions()
|
||||
goodOptions.SharedKey = "Setec Astronomy"
|
||||
goodOptions.Services = "all"
|
||||
goodOptions.Policies = testPolicies
|
||||
goodOptions.CookieName = "oatmeal"
|
||||
|
||||
badConfigBytes := []byte("badjson!")
|
||||
badUnmarshalConfigBytes := []byte(`"debug": "blue"`)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
configBytes []byte
|
||||
want *Options
|
||||
wantErr bool
|
||||
}{
|
||||
{"good", goodConfigBytes, goodOptions, false},
|
||||
{"bad json", badConfigBytes, nil, true},
|
||||
{"bad unmarshal", badUnmarshalConfigBytes, nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
viper.Reset()
|
||||
os.Clearenv()
|
||||
os.Setenv("COOKIE_NAME", "oatmeal")
|
||||
defer os.Unsetenv("COOKIE_NAME")
|
||||
tempFile, _ := ioutil.TempFile("", "*.json")
|
||||
defer tempFile.Close()
|
||||
defer os.Remove(tempFile.Name())
|
||||
tempFile.Write(tt.configBytes)
|
||||
got, err := OptionsFromViper(tempFile.Name())
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("OptionsFromViper() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("OptionsFromViper() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// Test for missing config file
|
||||
o, err := OptionsFromViper("filedoesnotexist")
|
||||
if o != nil || err == nil {
|
||||
t.Errorf("OptionsFromViper(): Did when loading missing file")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parsePolicyEnv(t *testing.T) {
|
||||
t.Parallel()
|
||||
source := "https://pomerium.io"
|
||||
sourceURL, _ := url.ParseRequestURI(source)
|
||||
dest := "https://httpbin.org"
|
||||
destURL, _ := url.ParseRequestURI(dest)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
policyBytes []byte
|
||||
want []policy.Policy
|
||||
wantErr bool
|
||||
}{
|
||||
{"simple json", []byte(fmt.Sprintf(`[{"from": "%s","to":"%s"}]`, source, dest)), []policy.Policy{{From: source, To: dest, Source: sourceURL, Destination: destURL}}, false},
|
||||
{"bad from", []byte(`[{"from": "%","to":"httpbin.org"}]`), nil, true},
|
||||
{"bad to", []byte(`[{"from": "pomerium.io","to":"%"}]`), nil, true},
|
||||
{"simple error", []byte(`{}`), nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := new(Options)
|
||||
|
||||
o.PolicyEnv = base64.StdEncoding.EncodeToString(tt.policyBytes)
|
||||
err := o.parsePolicy()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parasePolicy() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(o.Policies, tt.want) {
|
||||
t.Errorf("parasePolicy() = \n%v, want \n%v", o, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Catch bad base64
|
||||
o := new(Options)
|
||||
o.PolicyEnv = "foo"
|
||||
err := o.parsePolicy()
|
||||
if err == nil {
|
||||
t.Errorf("parasePolicy() did not catch bad base64 %v", o)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parsePolicyFile(t *testing.T) {
|
||||
source := "https://pomerium.io"
|
||||
sourceURL, _ := url.ParseRequestURI(source)
|
||||
dest := "https://httpbin.org"
|
||||
destURL, _ := url.ParseRequestURI(dest)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
policyBytes []byte
|
||||
want []policy.Policy
|
||||
wantErr bool
|
||||
}{
|
||||
{"simple json", []byte(fmt.Sprintf(`{"policy":[{"from": "%s","to":"%s"}]}`, source, dest)), []policy.Policy{{From: source, To: dest, Source: sourceURL, Destination: destURL}}, false},
|
||||
{"bad from", []byte(`{"policy":[{"from": "%","to":"httpbin.org"}]}`), nil, true},
|
||||
{"bad to", []byte(`{"policy":[{"from": "pomerium.io","to":"%"}]}`), nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := new(Options)
|
||||
|
||||
tempFile, _ := ioutil.TempFile("", "*.json")
|
||||
defer tempFile.Close()
|
||||
defer os.Remove(tempFile.Name())
|
||||
tempFile.Write(tt.policyBytes)
|
||||
o = new(Options)
|
||||
viper.SetConfigFile(tempFile.Name())
|
||||
err := viper.ReadInConfig()
|
||||
err = o.parsePolicy()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parasePolicy() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(o.Policies, tt.want) {
|
||||
t.Errorf("parasePolicy() = \n%v, want \n%v", o, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,42 +3,39 @@ package policy // import "github.com/pomerium/pomerium/internal/policy"
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/fileutil"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Policy contains authorization policy information.
|
||||
// todo(bdd) : add upstream timeout and configuration settings
|
||||
type Policy struct {
|
||||
//
|
||||
From string `yaml:"from"`
|
||||
To string `yaml:"to"`
|
||||
From string `mapstructure:"from" yaml:"from"`
|
||||
To string `mapstructure:"to" yaml:"to"`
|
||||
// Identity related policy
|
||||
AllowedEmails []string `yaml:"allowed_users"`
|
||||
AllowedGroups []string `yaml:"allowed_groups"`
|
||||
AllowedDomains []string `yaml:"allowed_domains"`
|
||||
AllowedEmails []string `mapstructure:"allowed_users" yaml:"allowed_users"`
|
||||
AllowedGroups []string `mapstructure:"allowed_groups" yaml:"allowed_groups"`
|
||||
AllowedDomains []string `mapstructure:"allowed_domains" yaml:"allowed_domains"`
|
||||
|
||||
Source *url.URL
|
||||
Destination *url.URL
|
||||
|
||||
// Allow unauthenticated HTTP OPTIONS requests as per the CORS spec
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests
|
||||
CORSAllowPreflight bool `yaml:"cors_allow_preflight"`
|
||||
CORSAllowPreflight bool `mapstructure:"cors_allow_preflight" yaml:"cors_allow_preflight"`
|
||||
|
||||
// Allow any public request to access this route. **Bypasses authentication**
|
||||
AllowPublicUnauthenticatedAccess bool `yaml:"allow_public_unauthenticated_access"`
|
||||
AllowPublicUnauthenticatedAccess bool `mapstructure:"allow_public_unauthenticated_access" yaml:"allow_public_unauthenticated_access"`
|
||||
|
||||
// UpstreamTimeout is the route specific timeout. Must be less than the global
|
||||
// timeout. If unset, route will fallback to the proxy's DefaultUpstreamTimeout.
|
||||
UpstreamTimeout time.Duration `yaml:"timeout"`
|
||||
UpstreamTimeout time.Duration `mapstructure:"timeout" yaml:"timeout"`
|
||||
}
|
||||
|
||||
func (p *Policy) validate() (err error) {
|
||||
// Validate parses the source and destination URLs in the Policy
|
||||
func (p *Policy) Validate() (err error) {
|
||||
p.Source, err = urlParse(p.From)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -57,37 +54,7 @@ func (p *Policy) validate() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// FromConfig parses configuration file as bytes and returns authorization
|
||||
// policies. Supports yaml, json.
|
||||
func FromConfig(confBytes []byte) ([]Policy, error) {
|
||||
var f []Policy
|
||||
if err := yaml.Unmarshal(confBytes, &f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// build source and destination urls
|
||||
for i := range f {
|
||||
if err := (&f[i]).validate(); err != nil {
|
||||
return nil, fmt.Errorf("route at index %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// FromConfigFile parses configuration file from a path and returns
|
||||
// authorization policies. Supports yaml, json.
|
||||
func FromConfigFile(f string) ([]Policy, error) {
|
||||
exists, err := fileutil.IsReadableFile(f)
|
||||
if err != nil || !exists {
|
||||
return nil, fmt.Errorf("policy file %v: %v exists? %v", f, err, exists)
|
||||
}
|
||||
confBytes, err := ioutil.ReadFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FromConfig(confBytes)
|
||||
}
|
||||
|
||||
// urlParse wraps url.Parse to add a scheme if none-exists.
|
||||
// URLParse wraps url.Parse to add a scheme if none-exists.
|
||||
// https://github.com/golang/go/issues/12585
|
||||
func urlParse(uri string) (*url.URL, error) {
|
||||
if !strings.Contains(uri, "://") {
|
||||
|
|
|
@ -6,36 +6,6 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestFromConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
source, _ := urlParse("pomerium.io")
|
||||
dest, _ := urlParse("httpbin.org")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
yamlBytes []byte
|
||||
want []Policy
|
||||
wantErr bool
|
||||
}{
|
||||
{"simple json", []byte(`[{"from": "pomerium.io","to":"httpbin.org"}]`), []Policy{{From: "pomerium.io", To: "httpbin.org", Source: source, Destination: dest}}, false},
|
||||
{"bad from", []byte(`[{"from": "%","to":"httpbin.org"}]`), nil, true},
|
||||
{"bad to", []byte(`[{"from": "pomerium.io","to":"%"}]`), nil, true},
|
||||
{"simple error", []byte(`{}`), nil, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := FromConfig(tt.yamlBytes)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("FromConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("FromConfig() = \n%v, want \n%v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_urlParse(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
|
@ -62,30 +32,34 @@ func Test_urlParse(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFromConfigFile(t *testing.T) {
|
||||
func Test_Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
source, _ := urlParse("pomerium.io")
|
||||
dest, _ := urlParse("httpbin.org")
|
||||
basePolicy := Policy{From: "httpbin.corp.example", To: "httpbin.corp.notatld"}
|
||||
|
||||
corsPolicy := basePolicy
|
||||
corsPolicy.CORSAllowPreflight = true
|
||||
|
||||
publicPolicy := basePolicy
|
||||
publicPolicy.AllowPublicUnauthenticatedAccess = true
|
||||
|
||||
publicAndWhitelistPolicy := publicPolicy
|
||||
publicAndWhitelistPolicy.AllowedEmails = []string{"test@gmail.com"}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
f string
|
||||
want []Policy
|
||||
policy Policy
|
||||
wantErr bool
|
||||
}{
|
||||
{"simple json", "./testdata/basic.json", []Policy{{From: "pomerium.io", To: "httpbin.org", Source: source, Destination: dest}}, false},
|
||||
{"simple yaml", "./testdata/basic.yaml", []Policy{{From: "pomerium.io", To: "httpbin.org", Source: source, Destination: dest}}, false},
|
||||
{"failed dir", "./testdata/", nil, true},
|
||||
{"good", basePolicy, false},
|
||||
{"cors policy", corsPolicy, false},
|
||||
{"public policy", publicPolicy, false},
|
||||
{"public and whitelist", publicAndWhitelistPolicy, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := FromConfigFile(tt.f)
|
||||
err := tt.policy.Validate()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("FromConfigFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("FromConfigFile() = %v, want %v", got, tt.want)
|
||||
t.Errorf("Validate() error = %v, want %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,7 +18,4 @@
|
|||
- from: hello.corp.beyondperimeter.com
|
||||
to: http://hello:8080
|
||||
allowed_groups:
|
||||
- admins
|
||||
- from: external-search.corp.beyondperimeter.com
|
||||
to: google.com
|
||||
allow_public_unauthenticated_access: true
|
||||
- admins
|
|
@ -1,7 +1,6 @@
|
|||
package proxy
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -13,6 +12,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/config"
|
||||
"github.com/pomerium/pomerium/internal/policy"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/proxy/clients"
|
||||
)
|
||||
|
@ -292,26 +292,27 @@ func Test_extendDeadline(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestProxy_router(t *testing.T) {
|
||||
configBlob := `[{"from":"corp.example.com","to":"example.com"}]` //valid yaml
|
||||
policy := base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
testPolicy := policy.Policy{From: "corp.example.com", To: "example.com"}
|
||||
testPolicy.Validate()
|
||||
policies := []policy.Policy{testPolicy}
|
||||
tests := []struct {
|
||||
name string
|
||||
host string
|
||||
mux string
|
||||
mux []policy.Policy
|
||||
route http.Handler
|
||||
wantOk bool
|
||||
}{
|
||||
{"good corp", "https://corp.example.com", policy, nil, true},
|
||||
{"good with slash", "https://corp.example.com/", policy, nil, true},
|
||||
{"good with path", "https://corp.example.com/123", policy, nil, true},
|
||||
{"good corp", "https://corp.example.com", policies, nil, true},
|
||||
{"good with slash", "https://corp.example.com/", policies, nil, true},
|
||||
{"good with path", "https://corp.example.com/123", policies, nil, true},
|
||||
// {"multiple", "https://corp.example.com/", map[string]string{"corp.unrelated.com": "unrelated.com", "corp.example.com": "example.com"}, nil, true},
|
||||
{"bad corp", "https://notcorp.example.com/123", policy, nil, false},
|
||||
{"bad sub-sub", "https://notcorp.corp.example.com/123", policy, nil, false},
|
||||
{"bad corp", "https://notcorp.example.com/123", policies, nil, false},
|
||||
{"bad sub-sub", "https://notcorp.corp.example.com/123", policies, nil, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
opts := testOptions()
|
||||
opts.Policy = tt.mux
|
||||
opts.Policies = tt.mux
|
||||
p, err := New(opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -403,6 +404,7 @@ func TestProxy_Proxy(t *testing.T) {
|
|||
t.Errorf("\n%+v", opts)
|
||||
t.Errorf("\n%+v", ts.URL)
|
||||
|
||||
t.Errorf("handler returned wrong status code: got %v want %v \n body %s", status, tt.wantStatus, w.Body.String())
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -42,29 +42,9 @@ func ValidateOptions(o *config.Options) error {
|
|||
if len(decoded) != 32 {
|
||||
return fmt.Errorf("authorize: `SHARED_SECRET` want 32 but got %d bytes", len(decoded))
|
||||
}
|
||||
if len(o.Routes) != 0 {
|
||||
return errors.New("routes setting is deprecated, use policy instead")
|
||||
if len(o.Policies) == 0 {
|
||||
return errors.New("missing setting: no policies defined")
|
||||
}
|
||||
if o.Policy == "" && o.PolicyFile == "" {
|
||||
return errors.New("proxy: either `POLICY` or `POLICY_FILE` must be non-nil")
|
||||
}
|
||||
if o.Policy != "" {
|
||||
confBytes, err := base64.StdEncoding.DecodeString(o.Policy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("proxy: `POLICY` is invalid base64 %v", err)
|
||||
}
|
||||
_, err = policy.FromConfig(confBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("proxy: `POLICY` %v", err)
|
||||
}
|
||||
}
|
||||
if o.PolicyFile != "" {
|
||||
_, err = policy.FromConfigFile(o.PolicyFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("proxy: `POLICY_FILE` %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if o.AuthenticateURL == nil {
|
||||
return errors.New("missing setting: authenticate-service-url")
|
||||
}
|
||||
|
@ -164,14 +144,8 @@ func New(opts *config.Options) (*Proxy, error) {
|
|||
redirectURL: &url.URL{Path: "/.pomerium/callback"},
|
||||
templates: templates.New(),
|
||||
}
|
||||
var policies []policy.Policy
|
||||
if opts.Policy != "" {
|
||||
confBytes, _ := base64.StdEncoding.DecodeString(opts.Policy)
|
||||
policies, _ = policy.FromConfig(confBytes)
|
||||
} else {
|
||||
policies, _ = policy.FromConfigFile(opts.PolicyFile)
|
||||
}
|
||||
for _, route := range policies {
|
||||
|
||||
for _, route := range opts.Policies {
|
||||
proxy := NewReverseProxy(route.Destination)
|
||||
handler, err := NewReverseProxyHandler(opts, proxy, &route)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package proxy // import "github.com/pomerium/pomerium/proxy"
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -58,11 +56,10 @@ func TestNewReverseProxyHandler(t *testing.T) {
|
|||
proxyHandler := NewReverseProxy(proxyURL)
|
||||
opts := config.NewOptions()
|
||||
opts.SigningKey = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU0zbXBaSVdYQ1g5eUVneFU2czU3Q2J0YlVOREJTQ0VBdFFGNWZVV0hwY1FvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFaFBRditMQUNQVk5tQlRLMHhTVHpicEVQa1JyazFlVXQxQk9hMzJTRWZVUHpOaTRJV2VaLwpLS0lUdDJxMUlxcFYyS01TYlZEeXI5aWp2L1hoOThpeUV3PT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
||||
route, err := policy.FromConfig([]byte(`[{"from":"corp.example.com","to":"example.com","timeout":"1s"}]`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
handle, err := NewReverseProxyHandler(opts, proxyHandler, &route[0])
|
||||
testPolicy := policy.Policy{From: "corp.example.com", To: "example.com", UpstreamTimeout: 1 * time.Second}
|
||||
testPolicy.Validate()
|
||||
|
||||
handle, err := NewReverseProxyHandler(opts, proxyHandler, &testPolicy)
|
||||
if err != nil {
|
||||
t.Errorf("got %q", err)
|
||||
}
|
||||
|
@ -83,11 +80,11 @@ func TestNewReverseProxyHandler(t *testing.T) {
|
|||
func testOptions() *config.Options {
|
||||
authenticateService, _ := url.Parse("https://authenticate.corp.beyondperimeter.com")
|
||||
authorizeService, _ := url.Parse("https://authorize.corp.beyondperimeter.com")
|
||||
configBlob := `[{"from":"corp.example.notatld","to":"example.notatld"}]`
|
||||
policy := base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
|
||||
opts := config.NewOptions()
|
||||
opts.Policy = policy
|
||||
testPolicy := policy.Policy{From: "corp.example.notatld", To: "example.notatld"}
|
||||
testPolicy.Validate()
|
||||
opts.Policies = []policy.Policy{testPolicy}
|
||||
opts.AuthenticateURL = authenticateService
|
||||
opts.AuthorizeURL = authorizeService
|
||||
opts.SharedKey = "80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ="
|
||||
|
@ -100,11 +97,13 @@ func testOptionsTestServer(uri string) *config.Options {
|
|||
authenticateService, _ := url.Parse("https://authenticate.corp.beyondperimeter.com")
|
||||
authorizeService, _ := url.Parse("https://authorize.corp.beyondperimeter.com")
|
||||
// RFC 2606
|
||||
configBlob := fmt.Sprintf(`[{"from":"httpbin.corp.example","to":"%s"}]`, uri)
|
||||
policy := base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
|
||||
testPolicy := policy.Policy{
|
||||
From: "httpbin.corp.example",
|
||||
To: uri,
|
||||
}
|
||||
testPolicy.Validate()
|
||||
opts := config.NewOptions()
|
||||
opts.Policy = policy
|
||||
opts.Policies = []policy.Policy{testPolicy}
|
||||
opts.AuthenticateURL = authenticateService
|
||||
opts.AuthorizeURL = authorizeService
|
||||
opts.SharedKey = "80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ="
|
||||
|
@ -114,33 +113,44 @@ func testOptionsTestServer(uri string) *config.Options {
|
|||
}
|
||||
|
||||
func testOptionsWithCORS(uri string) *config.Options {
|
||||
configBlob := fmt.Sprintf(`[{"from":"httpbin.corp.example","to":"%s","cors_allow_preflight":true}]`, uri)
|
||||
testPolicy := policy.Policy{
|
||||
From: "httpbin.corp.example",
|
||||
To: uri,
|
||||
CORSAllowPreflight: true,
|
||||
}
|
||||
testPolicy.Validate()
|
||||
opts := testOptionsTestServer(uri)
|
||||
opts.Policy = base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
opts.Policies = []policy.Policy{testPolicy}
|
||||
return opts
|
||||
}
|
||||
|
||||
|
||||
func testOptionsWithPublicAccess(uri string) *config.Options {
|
||||
configBlob := fmt.Sprintf(`[{"from":"httpbin.corp.example","to":"%s","allow_public_unauthenticated_access":true}]`, uri)
|
||||
testPolicy := policy.Policy{
|
||||
From: "httpbin.corp.example",
|
||||
To: uri,
|
||||
AllowPublicUnauthenticatedAccess: true,
|
||||
}
|
||||
testPolicy.Validate()
|
||||
opts := testOptions()
|
||||
opts.Policy = base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
opts.Policies = []policy.Policy{testPolicy}
|
||||
return opts
|
||||
}
|
||||
|
||||
func testOptionsWithPublicAccessAndWhitelist(uri string) *config.Options {
|
||||
configBlob := fmt.Sprintf(`[{"from":"httpbin.corp.example","to":"%s","allow_public_unauthenticated_access":true,"allowed_users":["test@gmail.com"]}]`, uri)
|
||||
testPolicy := policy.Policy{
|
||||
From: "httpbin.corp.example",
|
||||
To: uri,
|
||||
AllowPublicUnauthenticatedAccess: true,
|
||||
AllowedEmails: []string{"test@gmail.com"},
|
||||
}
|
||||
testPolicy.Validate()
|
||||
opts := testOptions()
|
||||
opts.Policy = base64.URLEncoding.EncodeToString([]byte(configBlob))
|
||||
opts.Policies = []policy.Policy{testPolicy}
|
||||
return opts
|
||||
}
|
||||
|
||||
func TestOptions_Validate(t *testing.T) {
|
||||
good := testOptions()
|
||||
badFromRoute := testOptions()
|
||||
badFromRoute.Routes = map[string]string{"example.com": "^"}
|
||||
badToRoute := testOptions()
|
||||
badToRoute.Routes = map[string]string{"^": "example.com"}
|
||||
badAuthURL := testOptions()
|
||||
badAuthURL.AuthenticateURL = nil
|
||||
authurl, _ := url.Parse("http://authenticate.corp.beyondperimeter.com")
|
||||
|
@ -160,15 +170,8 @@ func TestOptions_Validate(t *testing.T) {
|
|||
invalidSignKey.SigningKey = "OromP1gurwGWjQPYb1nNgSxtbVB5NnLzX6z5WOKr0Yw^"
|
||||
badSharedKey := testOptions()
|
||||
badSharedKey.SharedKey = ""
|
||||
policyBadBase64 := testOptions()
|
||||
policyBadBase64.Policy = "^"
|
||||
badPolicyToURL := testOptions()
|
||||
badPolicyToURL.Policy = "LSBmcm9tOiBodHRwYmluLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vaHR0cGJpbl4KICBhbGxvd2VkX2RvbWFpbnM6CiAgICAtIHBvbWVyaXVtLmlv"
|
||||
badPolicyFromURL := testOptions()
|
||||
badPolicyFromURL.Policy = "LSBmcm9tOiBodHRwYmluLmNvcnAuYmV5b25kcGVyaW1ldGVyLmNvbQogIHRvOiBodHRwOi8vaHR0cGJpbl4KICBhbGxvd2VkX2RvbWFpbnM6CiAgICAtIHBvbWVyaXVtLmlv"
|
||||
corsPolicy := testOptionsWithCORS("example.notatld")
|
||||
publicPolicy := testOptionsWithPublicAccess("example.notatld")
|
||||
publicWithWhitelistPolicy := testOptionsWithPublicAccessAndWhitelist("example.notatld")
|
||||
missingPolicy := testOptions()
|
||||
missingPolicy.Policies = []policy.Policy{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -177,8 +180,6 @@ func TestOptions_Validate(t *testing.T) {
|
|||
}{
|
||||
{"good - minimum options", good, false},
|
||||
{"nil options", &config.Options{}, true},
|
||||
{"from route", badFromRoute, true},
|
||||
{"to route", badToRoute, true},
|
||||
{"authenticate service url", badAuthURL, true},
|
||||
{"authenticate service url not https", authenticateBadScheme, true},
|
||||
{"authorize service url not https", authorizeBadSCheme, true},
|
||||
|
@ -188,12 +189,7 @@ func TestOptions_Validate(t *testing.T) {
|
|||
{"short cookie secret", shortCookieLength, true},
|
||||
{"no shared secret", badSharedKey, true},
|
||||
{"invalid signing key", invalidSignKey, true},
|
||||
{"policy invalid base64", policyBadBase64, true},
|
||||
{"policy bad to url", badPolicyFromURL, true},
|
||||
{"policy bad from url", badPolicyFromURL, true},
|
||||
{"CORS policy good", corsPolicy, false},
|
||||
{"policy public good", publicPolicy, false},
|
||||
{"policy public and whitelist bad", publicWithWhitelistPolicy, true},
|
||||
{"missing policy", missingPolicy, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
Loading…
Add table
Reference in a new issue