mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 10:26:29 +02:00
Allow empty policies at startup
This commit is contained in:
parent
b8463e30c1
commit
989062db8e
9 changed files with 30 additions and 11 deletions
|
@ -10,6 +10,7 @@
|
|||
### CHANGED
|
||||
|
||||
- Proxy's sign out handler `{}/.pomerium/sign_out` now accepts an optional `redirect_uri` parameter which can be used to specify a custom redirect page, so long as it is under the same top-level domain. [GH-183]
|
||||
- Policy configuration can now be empty at startup [GH-190]
|
||||
|
||||
### FIXED
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package authorize // import "github.com/pomerium/pomerium/authorize"
|
|||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
|
@ -22,9 +21,6 @@ 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.Policies) == 0 {
|
||||
return errors.New("missing setting: no policies defined")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ func TestNew(t *testing.T) {
|
|||
{"bad shared secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", policies, true},
|
||||
{"really bad shared secret", "sup", policies, true},
|
||||
{"validation error, short secret", "AZA85podM73CjLCjViDNz1EUvvejKpWp7Hysr0knXA==", policies, true},
|
||||
{"empty options", "", []policy.Policy{}, true}, // special case
|
||||
{"missing policies", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", []policy.Policy{}, true}, // special case
|
||||
{"empty options", "", []policy.Policy{}, true}, // special case
|
||||
{"missing policies", "gXK6ggrlIW2HyKyUF9rUO4azrDgxhDPWqw9y+lJU7B8=", []policy.Policy{}, false}, // special case
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -56,6 +56,13 @@ type whitelist struct {
|
|||
// newIdentityWhitelistMap takes a slice of policies and creates a hashmap of identity
|
||||
// authorizations per-route for each allowed group, domain, and email.
|
||||
func newIdentityWhitelistMap(policies []policy.Policy, admins []string) *whitelist {
|
||||
|
||||
policyCount := len(policies)
|
||||
if policyCount == 0 {
|
||||
log.Warn().Msg("authorize: loaded configuration with no policies specified")
|
||||
}
|
||||
log.Info().Int("policy-count", policyCount).Msg("authorize: updated policies")
|
||||
|
||||
var wl whitelist
|
||||
wl.access = make(map[string]bool, len(policies)*3)
|
||||
for _, p := range policies {
|
||||
|
|
|
@ -50,6 +50,7 @@ func Test_IdentityWhitelistMap(t *testing.T) {
|
|||
{"valid user email", []policy.Policy{{From: "example.com", AllowedEmails: []string{"user@example.com"}}}, "example.com", &Identity{Email: "user@example.com"}, nil, true},
|
||||
{"invalid user email", []policy.Policy{{From: "example.com", AllowedEmails: []string{"user@example.com"}}}, "example.com", &Identity{Email: "user2@example.com"}, nil, false},
|
||||
{"empty everything", []policy.Policy{{From: "example.com"}}, "example.com", &Identity{Email: "user2@example.com"}, nil, false},
|
||||
{"empty policy", []policy.Policy{}, "example.com", &Identity{Email: "user@example.com"}, nil, false},
|
||||
// impersonation related
|
||||
{"admin not impersonating allowed", []policy.Policy{{From: "example.com", AllowedDomains: []string{"example.com"}}}, "example.com", &Identity{Email: "admin@example.com"}, []string{"admin@example.com"}, true},
|
||||
{"admin not impersonating denied", []policy.Policy{{From: "example.com", AllowedDomains: []string{"example.com"}}}, "example.com", &Identity{Email: "admin@admin-domain.com"}, []string{"admin@admin-domain.com"}, false},
|
||||
|
|
|
@ -194,7 +194,8 @@ Expose a prometheus format HTTP endpoint on the specified port. Disabled by def
|
|||
- Environmental Variable: `POLICY`
|
||||
- Config File Key: `policy`
|
||||
- Type: [base64 encoded] `string` or inline policy structure in config file
|
||||
- Required
|
||||
- Required
|
||||
- Required to forward traffic. Pomerium will safely start without a policy configured, but will be unable to authorize or proxy traffic until the configuration is updated to contain a policy.
|
||||
|
||||
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,
|
||||
|
||||
|
|
|
@ -242,6 +242,7 @@ func TestProxy_router(t *testing.T) {
|
|||
{"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},
|
||||
{"no policies", "https://notcorp.example.com/123", []policy.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},
|
||||
}
|
||||
|
@ -280,6 +281,7 @@ func TestProxy_Proxy(t *testing.T) {
|
|||
opts, optsWs := testOptionsTestServer(ts.URL), testOptionsTestServer(ts.URL)
|
||||
optsCORS := testOptionsWithCORS(ts.URL)
|
||||
optsPublic := testOptionsWithPublicAccess(ts.URL)
|
||||
optsNoPolicies := testOptionsWithEmptyPolicies(ts.URL)
|
||||
optsWs.AllowWebsockets = true
|
||||
|
||||
defaultHeaders, goodCORSHeaders, badCORSHeaders, headersWs := http.Header{}, http.Header{}, http.Header{}, http.Header{}
|
||||
|
@ -327,6 +329,7 @@ func TestProxy_Proxy(t *testing.T) {
|
|||
{"ws supported, ws connection", optsWs, http.MethodGet, headersWs, "https://httpbin.corp.example", &sessions.MockSessionStore{Session: goodSession}, clients.MockAuthenticate{ValidateResponse: true}, clients.MockAuthorize{AuthorizeResponse: true}, http.StatusOK},
|
||||
{"ws supported, http connection", optsWs, http.MethodGet, defaultHeaders, "https://httpbin.corp.example", &sessions.MockSessionStore{Session: goodSession}, clients.MockAuthenticate{ValidateResponse: true}, clients.MockAuthorize{AuthorizeResponse: true}, http.StatusOK},
|
||||
{"ws unsupported, ws connection", opts, http.MethodGet, headersWs, "https://httpbin.corp.example", &sessions.MockSessionStore{Session: goodSession}, clients.MockAuthenticate{ValidateResponse: true}, clients.MockAuthorize{AuthorizeResponse: true}, http.StatusBadRequest},
|
||||
{"No policies", optsNoPolicies, http.MethodGet, defaultHeaders, "https://httpbin.corp.example", &sessions.MockSessionStore{Session: goodSession}, clients.MockAuthenticate{ValidateResponse: true}, clients.MockAuthorize{AuthorizeResponse: true}, http.StatusNotFound},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
@ -44,9 +44,6 @@ func ValidateOptions(o config.Options) error {
|
|||
if len(decoded) != 32 {
|
||||
return fmt.Errorf("`SHARED_SECRET` want 32 but got %d bytes", len(decoded))
|
||||
}
|
||||
if len(o.Policies) == 0 {
|
||||
return errors.New("missing setting: no policies defined")
|
||||
}
|
||||
if o.AuthenticateURL.String() == "" {
|
||||
return errors.New("missing setting: authenticate-service-url")
|
||||
}
|
||||
|
@ -182,6 +179,13 @@ func New(opts config.Options) (*Proxy, error) {
|
|||
// UpdatePolicies updates the handlers based on the configured policies
|
||||
func (p *Proxy) UpdatePolicies(opts config.Options) error {
|
||||
routeConfigs := make(map[string]*routeConfig)
|
||||
|
||||
policyCount := len(opts.Policies)
|
||||
if policyCount == 0 {
|
||||
log.Warn().Msg("proxy: loaded configuration with no policies specified")
|
||||
}
|
||||
log.Info().Int("policy-count", policyCount).Msg("proxy: updated policies")
|
||||
|
||||
for _, route := range opts.Policies {
|
||||
proxy := NewReverseProxy(route.Destination)
|
||||
handler, err := NewReverseProxyHandler(opts, proxy, &route)
|
||||
|
|
|
@ -149,6 +149,12 @@ func testOptionsWithPublicAccessAndWhitelist(uri string) config.Options {
|
|||
return opts
|
||||
}
|
||||
|
||||
func testOptionsWithEmptyPolicies(uri string) config.Options {
|
||||
opts := testOptionsTestServer(uri)
|
||||
opts.Policies = []policy.Policy{}
|
||||
return opts
|
||||
}
|
||||
|
||||
func TestOptions_Validate(t *testing.T) {
|
||||
good := testOptions()
|
||||
badAuthURL := testOptions()
|
||||
|
@ -191,7 +197,7 @@ func TestOptions_Validate(t *testing.T) {
|
|||
{"short cookie secret", shortCookieLength, true},
|
||||
{"no shared secret", badSharedKey, true},
|
||||
{"invalid signing key", invalidSignKey, true},
|
||||
{"missing policy", missingPolicy, true},
|
||||
{"missing policy", missingPolicy, false},
|
||||
{"shared secret bad base64", sharedKeyBadBas64, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
|
Loading…
Add table
Reference in a new issue