From 7027f458dd95b2c4005f4565cc68e5d534a773cc Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 09:12:12 -0600 Subject: [PATCH 01/25] config: add prefix, path and regex options proxy: support prefix, path and regex options --- config/policy.go | 5 ++++ proxy/proxy.go | 47 +++++++++++++++++++++++++++++++++++-- proxy/proxy_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/config/policy.go b/config/policy.go index 833a5b362..d72912959 100644 --- a/config/policy.go +++ b/config/policy.go @@ -24,6 +24,11 @@ type Policy struct { Source *HostnameURL `yaml:",omitempty" json:"source,omitempty"` Destination *url.URL `yaml:",omitempty" json:"destination,omitempty"` + // Additional route matching options + Prefix string `mapstructure:"prefix" yaml:"prefix,omitempty" json:"prefix,omitempty"` + Path string `mapstructure:"path" yaml:"path,omitempty" json:"path,omitempty"` + Regex string `mapstructure:"regex" yaml:"regex,omitempty" json:"regex,omitempty"` + // Allow unauthenticated HTTP OPTIONS requests as per the CORS spec // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests CORSAllowPreflight bool `mapstructure:"cors_allow_preflight" yaml:"cors_allow_preflight,omitempty"` diff --git a/proxy/proxy.go b/proxy/proxy.go index 311f32f14..38f3f70c4 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -14,6 +14,8 @@ import ( "net/http" stdhttputil "net/http/httputil" "net/url" + "regexp" + "strings" "time" "github.com/gorilla/mux" @@ -230,8 +232,8 @@ func (p *Proxy) reverseProxyHandler(r *mux.Router, policy config.Policy) *mux.Ro // 4. Override any custom transport settings (e.g. TLS settings, etc) proxy.Transport = p.roundTripperFromPolicy(&policy) - // 5. Create a sub-router for a given route's hostname (`httpbin.corp.example.com`) - rp := r.Host(policy.Source.Host).Subrouter() + // 5. Create a sub-router with a matcher derived from the policy (host, path, etc...) + rp := r.MatcherFunc(routeMatcherFuncFromPolicy(policy)).Subrouter() rp.PathPrefix("/").Handler(proxy) // Optional: If websockets are enabled, do not set a handler request timeout @@ -323,3 +325,44 @@ func (p *Proxy) roundTripperFromPolicy(policy *config.Policy) http.RoundTripper func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { p.Handler.ServeHTTP(w, r) } + + +// routeMatcherFuncFromPolicy returns a mux matcher function which compares an http request with a policy. +// +// Routes can be filtered by the `source`, `prefix`, `path` and `regex` fields in the policy config. +func routeMatcherFuncFromPolicy(policy config.Policy) mux.MatcherFunc { + // match by source + sourceMatches := func(r *http.Request) bool { + return r.Host == policy.Source.Host && + strings.HasPrefix(r.URL.Path, policy.Source.Path) + } + + // match by prefix + prefixMatches := func(r *http.Request) bool { + return policy.Prefix == "" || + strings.HasPrefix(r.URL.Path, policy.Prefix) + } + + // match by path + pathMatches := func(r *http.Request) bool { + return policy.Path == "" || + r.URL.Path == policy.Path + } + + // match by path regex + var regexMatches func(*http.Request) bool + if policy.Regex == "" { + regexMatches = func(r *http.Request) bool { return true } + } else if re, err := regexp.Compile(policy.Regex); err == nil { + regexMatches = func(r *http.Request) bool { + return re.MatchString(r.URL.Path) + } + } else { + log.Error().Err(err).Str("regex", policy.Regex).Msg("proxy: invalid regex in policy, ignoring route") + regexMatches = func(r *http.Request) bool { return false } + } + + return func(r *http.Request, rm *mux.RouteMatch) bool { + return sourceMatches(r) && prefixMatches(r) && pathMatches(r) && regexMatches(r) + } +} \ No newline at end of file diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 47298a2c5..6f2a06609 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -276,3 +276,59 @@ func TestNewReverseProxy(t *testing.T) { t.Errorf("got body %q; expected %q", g, e) } } + +func TestRouteMatcherFuncFromPolicy(t *testing.T) { + tests := []struct { + source, prefix, path, regex string + incomingURL string + expect bool + msg string + }{ + // host in source + {"https://www.example.com", "", "", "", + "https://www.example.com", true, + "should match when host is the same as source host"}, + {"https://www.example.com", "", "", "", + "https://www.google.com", false, + "should not match when host is different from source host"}, + + // path prefix in source + {"https://www.example.com/admin", "", "", "", + "https://www.example.com/admin/someaction", true, + "should match when path begins with source path"}, + {"https://www.example.com/admin", "", "", "", + "https://www.example.com/notadmin", false, + "should not match when path does not begin with source path"}, + + // path prefix + {"https://www.example.com", "/admin", "", "", + "https://www.example.com/admin/someaction", true, + "should match when path begins with prefix"}, + {"https://www.example.com", "/admin", "", "", + "https://www.example.com/notadmin", false, + "should not match when path does not begin with prefix"}, + } + + for _, tt := range tests { + srcURL, err := url.Parse(tt.source) + if err != nil { + panic(err) + } + src := &config.HostnameURL{URL: srcURL} + matcher := routeMatcherFuncFromPolicy(config.Policy{ + Source: src, + Prefix: tt.prefix, + Path: tt.path, + Regex: tt.regex, + }) + req, err := http.NewRequest("GET", tt.incomingURL, nil) + if err != nil { + panic(err) + } + actual := matcher(req, nil) + if actual != tt.expect { + t.Errorf("%s (source=%s prefix=%s path=%s regex=%s incoming-url=%s)", + tt.msg, tt.source, tt.prefix, tt.path, tt.regex, tt.incomingURL) + } + } +} From d6591e4109826efc437bbfb597cd44aca39807a9 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 09:24:51 -0600 Subject: [PATCH 02/25] proxy: add additional tests for route matcher function --- proxy/proxy_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 6f2a06609..1a3099303 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -307,6 +307,28 @@ func TestRouteMatcherFuncFromPolicy(t *testing.T) { {"https://www.example.com", "/admin", "", "", "https://www.example.com/notadmin", false, "should not match when path does not begin with prefix"}, + + // path + {"https://www.example.com", "", "/admin", "", + "https://www.example.com/admin", true, + "should match when path is the same as the policy path"}, + {"https://www.example.com", "", "/admin", "", + "https://www.example.com/admin/someaction", false, + "should not match when path merely begins with the policy path"}, + {"https://www.example.com", "", "/admin", "", + "https://www.example.com/notadmin", false, + "should not match when path is different from the policy path"}, + + // path regex + {"https://www.example.com", "", "", "^/admin/[a-z]+$", + "https://www.example.com/admin/someaction", true, + "should match when path matches policy path regex"}, + {"https://www.example.com", "", "", "^/admin/[a-z]+$", + "https://www.example.com/notadmin", false, + "should not match when path does not match policy path regex"}, + {"https://www.example.com", "", "", "invalid[", + "https://www.example.com/invalid", false, + "should not match on invalid policy path regex"}, } for _, tt := range tests { From 5ecfa343614f2cf45ab714c50a68cc60fecb8a4e Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 09:35:56 -0600 Subject: [PATCH 03/25] config: gofmt --- config/policy.go | 4 ++-- proxy/proxy.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/config/policy.go b/config/policy.go index d72912959..7c611276f 100644 --- a/config/policy.go +++ b/config/policy.go @@ -26,8 +26,8 @@ type Policy struct { // Additional route matching options Prefix string `mapstructure:"prefix" yaml:"prefix,omitempty" json:"prefix,omitempty"` - Path string `mapstructure:"path" yaml:"path,omitempty" json:"path,omitempty"` - Regex string `mapstructure:"regex" yaml:"regex,omitempty" json:"regex,omitempty"` + Path string `mapstructure:"path" yaml:"path,omitempty" json:"path,omitempty"` + Regex string `mapstructure:"regex" yaml:"regex,omitempty" json:"regex,omitempty"` // Allow unauthenticated HTTP OPTIONS requests as per the CORS spec // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests diff --git a/proxy/proxy.go b/proxy/proxy.go index 38f3f70c4..d3e23a3b6 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -326,7 +326,6 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { p.Handler.ServeHTTP(w, r) } - // routeMatcherFuncFromPolicy returns a mux matcher function which compares an http request with a policy. // // Routes can be filtered by the `source`, `prefix`, `path` and `regex` fields in the policy config. @@ -365,4 +364,4 @@ func routeMatcherFuncFromPolicy(policy config.Policy) mux.MatcherFunc { return func(r *http.Request, rm *mux.RouteMatch) bool { return sourceMatches(r) && prefixMatches(r) && pathMatches(r) && regexMatches(r) } -} \ No newline at end of file +} From 428dee99c4a483e0ecb97c284d02f6344121c535 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 12:15:37 -0600 Subject: [PATCH 04/25] authorize: update opa rego to support additional policy properties --- authorize/evaluator/opa/policy/authz.rego | 76 +++++++++++++++--- .../evaluator/opa/policy/authz_test.rego | 78 +++++++++++++++++++ 2 files changed, 143 insertions(+), 11 deletions(-) create mode 100644 authorize/evaluator/opa/policy/authz_test.rego diff --git a/authorize/evaluator/opa/policy/authz.rego b/authorize/evaluator/opa/policy/authz.rego index 490a68bab..3790b2509 100644 --- a/authorize/evaluator/opa/policy/authz.rego +++ b/authorize/evaluator/opa/policy/authz.rego @@ -8,7 +8,7 @@ default allow = false # allow by email allow { some route - input.host = route_policies[route].source + allowed_route(input.url, route_policies[route]) token.payload.email = route_policies[route].allowed_users[_] token.valid count(deny)==0 @@ -17,7 +17,7 @@ allow { # allow group allow { some route - input.host = route_policies[route].source + allowed_route(input.url, route_policies[route]) token.payload.groups[_] = route_policies[route].allowed_groups[_] token.valid count(deny)==0 @@ -26,7 +26,7 @@ allow { # allow by impersonate email allow { some route - input.host = route_policies[route].source + allowed_route(input.url, route_policies[route]) token.payload.impersonate_email = route_policies[route].allowed_users[_] token.valid count(deny)==0 @@ -35,7 +35,7 @@ allow { # allow by impersonate group allow { some route - input.host = route_policies[route].source + allowed_route(input.url, route_policies[route]) token.payload.impersonate_groups[_] = route_policies[route].allowed_groups[_] token.valid count(deny)==0 @@ -44,9 +44,8 @@ allow { # allow by domain allow { some route - input.host = route_policies[route].source - some domain - email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain]) + allowed_route(input.url, route_policies[route]) + allowed_user_domain(token.payload.email) token.valid count(deny)==0 } @@ -54,14 +53,69 @@ allow { # allow by impersonate domain allow { some route - input.host = route_policies[route].source - some domain - email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain]) + allowed_route(input.url, route_policies[route]) + allowed_user_domain(token.payload.impersonate_email) token.valid count(deny)==0 } -email_in_domain(email, domain) { +allowed_route(input_url, policy){ + input_url_obj := parse_url(input_url) + allowed_route_source(input_url_obj, policy) + allowed_route_prefix(input_url_obj, policy) + allowed_route_path(input_url_obj, policy) + allowed_route_regex(input_url_obj, policy) +} + +allowed_route_source(input_url_obj, policy) { + object.get(policy, "source", "") == "" +} +allowed_route_source(input_url_obj, policy) { + object.get(policy, "source", "") != "" + source_url_obj := parse_url(policy.source) + input_url_obj.host == source_url_obj.host + startswith(input_url_obj.path, source_url_obj.path) +} + +allowed_route_prefix(input_url_obj, policy) { + object.get(policy, "prefix", "") == "" +} +allowed_route_prefix(input_url_obj, policy) { + object.get(policy, "prefix", "") != "" + startswith(input_url_obj.path, policy.prefix) +} + +allowed_route_path(input_url_obj, policy) { + object.get(policy, "path", "") == "" +} +allowed_route_path(input_url_obj, policy) { + object.get(policy, "path", "") != "" + policy.path == input_url_obj.path +} + +allowed_route_regex(input_url_obj, policy) { + object.get(policy, "regex", "") == "" +} +allowed_route_regex(input_url_obj, policy) { + object.get(policy, "regex", "") != "" + re_match(policy.regex, input_url_obj.path) +} + +parse_url(str) = { "scheme": scheme, "host": host, "path": path } { + [_, scheme, host, rawpath] = regex.find_all_string_submatch_n( + `(?:(http[s]?)://)?([^/]+)([^?#]*)`, + str, 1)[0] + path = normalize_url_path(rawpath) +} + +normalize_url_path(str) = "/" { + str == "" +} +normalize_url_path(str) = str { + str != "" +} + +allowed_user_domain(email){ x := split(email, "@") count(x) == 2 x[1] == domain diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego new file mode 100644 index 000000000..6e2c439c0 --- /dev/null +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -0,0 +1,78 @@ +package pomerium.authz + +jwt_header := { +"typ": "JWT", +"alg": "HS256" +} +signing_key := { +"kty": "oct", +"k": "OkFmqMK9U0dmPhMCW0VYy6D_raJKwEJsMdxqdnukThzko3D_XrsihwYE0pxrUSpm0JTrW2QpIz4rT1vdEvZw67WP4xrqjiwyd7PgpPTD5xvQBM7TIKiSW0X2R0pfq_OItszPQRtb7VirrSbGJiLNS-NJMMrYVKWWtUbVSTXEjL7VcFqML5PiSe7XDmyCZjpgEpfE5Q82zIeXM2sLrz6HW2A9IwGk7mWS0c57R_2JGyFO2tCA4zEIYhWvLE62Os2tZ6YrrwdB8n35jlPpgUE6poEvIU20lPLaocozXYMqAku-KJnloJlAzKg2Xa_0iSiSgSAumx44B3n7DQjg3jPhRg" +} +shared_key := base64url.decode(signing_key.k) + +test_email_allowed { +user := io.jwt.encode_sign(jwt_header, { + "aud": ["example.com"], + "email": "joe@example.com" +}, signing_key) + +allow with data.route_policies as [{ + "source": "example.com", + "allowed_users": ["joe@example.com"] +}] with data.signing_key as signing_key with data.shared_key as shared_key with input as { + "url": "http://example.com", + "host": "example.com", + "user": user +} +} + +test_email_denied { +user := io.jwt.encode_sign(jwt_header, { + "aud": ["example.com"], + "email": "joe@example.com" +}, signing_key) + +not allow with data.route_policies as [{ + "source": "example.com", + "allowed_users": ["bob@example.com"] +}] with data.signing_key as signing_key with data.shared_key as shared_key with input as { + "url": "http://example.com", + "host": "example.com", + "user": user +} +} + +test_parse_url { + url := parse_url("http://example.com/some/path?qs") + url.scheme == "http" + url.host == "example.com" + url.path == "/some/path" +} + +test_allowed_route_source { + allowed_route("http://example.com", {"source": "example.com"}) + allowed_route("http://example.com", {"source": "http://example.com"}) + allowed_route("http://example.com", {"source": "https://example.com"}) + not allowed_route("http://example.org", {"source": "example.com"}) + allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path"}) + allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path?qs"}) + not allowed_route("http://example.com/some/other/path", {"source": "https://example.com/some/path"}) +} + +test_allowed_route_prefix { + allowed_route("http://example.com", {"prefix": "/"}) + allowed_route("http://example.com/admin/somepath", {"prefix": "/admin"}) + not allowed_route("http://example.com", {"prefix": "/admin"}) +} + +test_allowed_route_path { + allowed_route("http://example.com", {"path": "/"}) + not allowed_route("http://example.com/admin/somepath", {"path": "/admin"}) + not allowed_route("http://example.com", {"path": "/admin"}) +} + +test_allowed_route_regex { + allowed_route("http://example.com", {"regex": ".*"}) + allowed_route("http://example.com/admin/somepath", {"regex": "/admin/.*"}) + not allowed_route("http://example.com", {"regex": "[xyz]"}) +} From 903a2d401f3c1ead17b28c5775f93856ce12736b Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 12:19:51 -0600 Subject: [PATCH 05/25] authorize: fix indentation --- .../evaluator/opa/policy/authz_test.rego | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index 6e2c439c0..448241541 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -1,45 +1,45 @@ package pomerium.authz jwt_header := { -"typ": "JWT", -"alg": "HS256" + "typ": "JWT", + "alg": "HS256" } signing_key := { -"kty": "oct", -"k": "OkFmqMK9U0dmPhMCW0VYy6D_raJKwEJsMdxqdnukThzko3D_XrsihwYE0pxrUSpm0JTrW2QpIz4rT1vdEvZw67WP4xrqjiwyd7PgpPTD5xvQBM7TIKiSW0X2R0pfq_OItszPQRtb7VirrSbGJiLNS-NJMMrYVKWWtUbVSTXEjL7VcFqML5PiSe7XDmyCZjpgEpfE5Q82zIeXM2sLrz6HW2A9IwGk7mWS0c57R_2JGyFO2tCA4zEIYhWvLE62Os2tZ6YrrwdB8n35jlPpgUE6poEvIU20lPLaocozXYMqAku-KJnloJlAzKg2Xa_0iSiSgSAumx44B3n7DQjg3jPhRg" + "kty": "oct", + "k": "OkFmqMK9U0dmPhMCW0VYy6D_raJKwEJsMdxqdnukThzko3D_XrsihwYE0pxrUSpm0JTrW2QpIz4rT1vdEvZw67WP4xrqjiwyd7PgpPTD5xvQBM7TIKiSW0X2R0pfq_OItszPQRtb7VirrSbGJiLNS-NJMMrYVKWWtUbVSTXEjL7VcFqML5PiSe7XDmyCZjpgEpfE5Q82zIeXM2sLrz6HW2A9IwGk7mWS0c57R_2JGyFO2tCA4zEIYhWvLE62Os2tZ6YrrwdB8n35jlPpgUE6poEvIU20lPLaocozXYMqAku-KJnloJlAzKg2Xa_0iSiSgSAumx44B3n7DQjg3jPhRg" } shared_key := base64url.decode(signing_key.k) test_email_allowed { -user := io.jwt.encode_sign(jwt_header, { - "aud": ["example.com"], - "email": "joe@example.com" -}, signing_key) + user := io.jwt.encode_sign(jwt_header, { + "aud": ["example.com"], + "email": "joe@example.com" + }, signing_key) -allow with data.route_policies as [{ - "source": "example.com", - "allowed_users": ["joe@example.com"] -}] with data.signing_key as signing_key with data.shared_key as shared_key with input as { - "url": "http://example.com", - "host": "example.com", - "user": user -} + allow with data.route_policies as [{ + "source": "example.com", + "allowed_users": ["joe@example.com"] + }] with data.signing_key as signing_key with data.shared_key as shared_key with input as { + "url": "http://example.com", + "host": "example.com", + "user": user + } } test_email_denied { -user := io.jwt.encode_sign(jwt_header, { - "aud": ["example.com"], - "email": "joe@example.com" -}, signing_key) + user := io.jwt.encode_sign(jwt_header, { + "aud": ["example.com"], + "email": "joe@example.com" + }, signing_key) -not allow with data.route_policies as [{ - "source": "example.com", - "allowed_users": ["bob@example.com"] -}] with data.signing_key as signing_key with data.shared_key as shared_key with input as { - "url": "http://example.com", - "host": "example.com", - "user": user -} + not allow with data.route_policies as [{ + "source": "example.com", + "allowed_users": ["bob@example.com"] + }] with data.signing_key as signing_key with data.shared_key as shared_key with input as { + "url": "http://example.com", + "host": "example.com", + "user": user + } } test_parse_url { From e8c8e7c688534aa24933e600e5f27ed313c5024f Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 12:32:48 -0600 Subject: [PATCH 06/25] config: use full string url instead of just the hostname for the policy options --- authorize/evaluator/opa/opa_test.go | 2 ++ config/options_test.go | 2 +- config/policy.go | 15 +++++++-------- config/policy_test.go | 4 ++-- proxy/proxy_test.go | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/authorize/evaluator/opa/opa_test.go b/authorize/evaluator/opa/opa_test.go index 7bf7566a0..5667dcb23 100644 --- a/authorize/evaluator/opa/opa_test.go +++ b/authorize/evaluator/opa/opa_test.go @@ -91,9 +91,11 @@ func Test_Eval(t *testing.T) { } req := struct { Host string `json:"host,omitempty"` + URL string `json:"url,omitempty"` User string `json:"user,omitempty"` }{ Host: tt.route, + URL: "https://" + tt.route, User: rawJWT, } got, err := pe.IsAuthorized(context.TODO(), req) diff --git a/config/options_test.go b/config/options_test.go index e5f264a72..56c67139d 100644 --- a/config/options_test.go +++ b/config/options_test.go @@ -152,7 +152,7 @@ func Test_parsePolicyFile(t *testing.T) { want []Policy wantErr bool }{ - {"simple json", []byte(fmt.Sprintf(`{"policy":[{"from": "%s","to":"%s"}]}`, source, dest)), []Policy{{From: source, To: dest, Source: &HostnameURL{sourceURL}, Destination: destURL}}, false}, + {"simple json", []byte(fmt.Sprintf(`{"policy":[{"from": "%s","to":"%s"}]}`, source, dest)), []Policy{{From: source, To: dest, Source: &StringURL{sourceURL}, Destination: destURL}}, false}, {"bad from", []byte(`{"policy":[{"from": "%","to":"httpbin.org"}]}`), nil, true}, {"bad to", []byte(`{"policy":[{"from": "pomerium.io","to":"%"}]}`), nil, true}, } diff --git a/config/policy.go b/config/policy.go index 7c611276f..7537f067a 100644 --- a/config/policy.go +++ b/config/policy.go @@ -21,8 +21,8 @@ type Policy struct { AllowedGroups []string `mapstructure:"allowed_groups" yaml:"allowed_groups,omitempty" json:"allowed_groups,omitempty"` AllowedDomains []string `mapstructure:"allowed_domains" yaml:"allowed_domains,omitempty" json:"allowed_domains,omitempty"` - Source *HostnameURL `yaml:",omitempty" json:"source,omitempty"` - Destination *url.URL `yaml:",omitempty" json:"destination,omitempty"` + Source *StringURL `yaml:",omitempty" json:"source,omitempty"` + Destination *url.URL `yaml:",omitempty" json:"destination,omitempty"` // Additional route matching options Prefix string `mapstructure:"prefix" yaml:"prefix,omitempty" json:"prefix,omitempty"` @@ -90,7 +90,7 @@ func (p *Policy) Validate() error { if err != nil { return fmt.Errorf("config: policy bad source url %w", err) } - p.Source = &HostnameURL{source} + p.Source = &StringURL{source} p.Destination, err = urlutil.ParseAndValidateURL(p.To) if err != nil { @@ -140,13 +140,12 @@ func (p *Policy) String() string { return fmt.Sprintf("%s → %s", p.Source.String(), p.Destination.String()) } -// HostnameURL wraps url but marshals only the host representation of that -// url struct. -type HostnameURL struct { +// StringURL stores a URL as a string in json. +type StringURL struct { *url.URL } // MarshalJSON returns the URLs host as json. -func (j *HostnameURL) MarshalJSON() ([]byte, error) { - return json.Marshal(j.Host) +func (u *StringURL) MarshalJSON() ([]byte, error) { + return json.Marshal(u.String()) } diff --git a/config/policy_test.go b/config/policy_test.go index b64c6b9b1..a35cf612b 100644 --- a/config/policy_test.go +++ b/config/policy_test.go @@ -57,8 +57,8 @@ func TestPolicy_String(t *testing.T) { want string wantFrom string }{ - {"good", "https://pomerium.io", "https://localhost", "https://pomerium.io → https://localhost", `"pomerium.io"`}, - {"failed to validate", "https://pomerium.io", "localhost", "https://pomerium.io → localhost", `"pomerium.io"`}, + {"good", "https://pomerium.io", "https://localhost", "https://pomerium.io → https://localhost", `"https://pomerium.io"`}, + {"failed to validate", "https://pomerium.io", "localhost", "https://pomerium.io → localhost", `"https://pomerium.io"`}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 1a3099303..97a16cf24 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -336,7 +336,7 @@ func TestRouteMatcherFuncFromPolicy(t *testing.T) { if err != nil { panic(err) } - src := &config.HostnameURL{URL: srcURL} + src := &config.StringURL{URL: srcURL} matcher := routeMatcherFuncFromPolicy(config.Policy{ Source: src, Prefix: tt.prefix, From cd6d68682242f8151aeb364265bdbbf01612e7a9 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 12:38:30 -0600 Subject: [PATCH 07/25] authorize: regenerate statik file --- authorize/evaluator/opa/policy/statik.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/authorize/evaluator/opa/policy/statik.go b/authorize/evaluator/opa/policy/statik.go index acf920f56..82bc044ff 100644 --- a/authorize/evaluator/opa/policy/statik.go +++ b/authorize/evaluator/opa/policy/statik.go @@ -6,11 +6,9 @@ import ( "github.com/rakyll/statik/fs" ) - const Rego = "rego" // static asset namespace func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00o\xa5\x94P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01s \x9e^\xbcV\xd1n\xac6\x10}\xb6\xbfb\xe4(\x12\xa8\x944\x91Z\xa9\xa8H}\xe9\x17\xf4\x11!\xe4\xe0\xd9]'`#l\xb2\xbb]\xed\xbfW\xb6a!$U\xd2{\xb3\xf7e\x17\xcf0g\xce\x99\x19\xdbt\xbc~\xe6[\x84N\xb7\xd8\xcb\xa1M\xf9`w\xffP*\xdbN\xf7\x16\x04\xb7<\xed\xf5`\xb1\xeat#k\x89\xe6\x95\xcb\xecx\x8f\xa2z\xc6#\xa5\x027|h,\xf0\xa6\xd1{\xc8a\xc3\x1b\x83\x94\xde\x8c\x86\xc7#`\xcbeC\xc3\xf2D\x89\xd1-\x82\x07\xa7D\xaan\xb0\xe9N\x1b\x0b9\xbcNX\xf8e\x99\x1a=\xf45Rb\xf53\xaa\xb4\xe3\xc7Fs\x91z\xcc\xff\x8c\xf1\xb9PT\x83\xc1\xde\x14U9E\xbf\xf0F\nJj=(\x1b T\xc78\xcf\x7f\xa1\xe7\x99\xed\xb6\xd7C\xf7\xc5T=\xa6c\xf1!\xdd\xcb\x9b\x9f\xe6\xfbx\x04\xd9v\xd8\x1b\xad\xb8\xc5\xabTz\x81_]\xa9\xea+\x15\xd7h\xc2R\xc5\x95\x1b\"t\xcb\xa5\xfan\xfe>l\xc4\"\xbe\xf0\x95TU0D\xefl\x86\xe4\x03-!\xd2\x14\xe1\xbf\x8c\xff\x8f\xa4ew~\xbc\xbc7\x13\xf8\xe5R\xd7\xf9\xc7,a\x15;\x95\x07\xc8r0]#\xed\xe4d\x7f\xb2x\xc2:\xc4\x90\xe7\xf0@\xc9\xa1\xb8/\xdd\xe3(\xec<\x1f\x8fx\xe8d\x8fb> '\xc3\x89\x12\xa5\xf7\x95\xc1Z+a\xb2\xdc\xca\x16SgQ&\x8a\xef\xee\xf1wJ\x8a\x1dr\x81}\x02cE\x12\xa8J\xc7G\xea\xf4ioS\x81\xb5\x16\x18\x85\xe2\xbb\xcd\x17Sr\x19\x8dC\x07\x7f\xc0\"A\xe0\xa4\x8e\x05\xf35\x01i.\xd4\"Z\xd1\x8bZ}\xd4\x13i|\x01\xe8c\x1a\x1fW\xdbg\xd2\x87^\xd0yy-^\xa6\xc2\xed\xf6)\x8d?\x07;\xe8\x1b\x04p\xbb\xa5\xa9\x1ej<\xab\xe9\xb1=sqv\x17\xf4\x84\xaa\x9f\x06\x1eti,\x1an\xcb\xed\xb0\xd6\x9dOrF\xdfP\xb4\xd3\xee0V\xc7\x90\xc3-0Sn\xb1A\x96\x81\xff\x91\x00\xa3=\xc02\xa0\x7fC>3p\xc9\xbbs\xf4\x16Ert\xf6N\x9a\xefh\xdc5A\xe2\x90\xae\x85\xac\n^\xd7\x85\xb1Z\xc8Ma\xba\x95cZ\xc8(\x0cf\xb3/\xd1U\x16m\xadm\x17fy\x15g\xf3y|\x15->\xcf\x97\xef\xe3h\xf1\xf9\xea\xed\xf2\x97\xf8KB~\xc6\xea\x04>\xc6\x8b\x0f\xd44}\xf9@*\xdd\xf0Z|\xf3\xdb\xcf\xad\x90~\xfaA\xe5\x19\x8f^.\x9b3\xdf\x89\xac\x1eU\xe7\xb2?\xf9\x0d\xfeo\x8e\xfe\xa7z\x8e[\x91o8\xe4\xbd\xa7\x83\xc8\xb4\xb5\xb0\xde\x98\x00\xfb\x8b\xc5\xc7\xe6\xb3\x8f\xf3O\xe4\xb5\xf8\xb8$\x12\x8f\xdf\x1a<\xb8\xbf6\xb8\xa9O\xb7k\xdc\xb7Bc5\xbe_\x0f&b!\xd5\xae0X*Y\x99,\xb7\xa2\xc1\x94,\xd2D\xf1\xfc#\xfeAe\xdc\"\xafP'\xd0\xb7\xcf\x04\x8a%1\x17*\xbd\xde\xd9\xb4\xc2RU\xc7\xcelP\xc7\xae\x06\xfd\xfd`\xdf\xc2\x9f0\x9a\xa2gG\x8du\xc1\\\xcb\x05a\x8e\x14#\xdc\xb71[\x12\xad\xde4\xf67\xad\x16\xd2\xae\xa3>n\xcb\x0d\xacx\x05\xbc\xab\x04\xca\x12!\xe2]\x15g\xf0\xce\x80T\x16\x84\x84w\xef\xbf\xb2d\xe1\x99\xb9\x058\xd0\xe2]\xb5\x8c\xdd4?\"\x8e\xd0\xb1\xc6\x06\xa5-\x84,jal4BNN\x13\xc6\x93\xab\x0f!\x90^^5\xf7\xafv\x91\xa2\x96\x04'\xcb\xd7\x06b\xc0\x90(\xb2\x06{b\x8f\xbff\x98\x19c\xf0\x8a\xff^\x8dI\x88\xd3%*I\x15U}B\x9e{\xcf\xb9\xe7\xdcs!\xc0\xf2\x81\x03e\x82CHQ\x1c\x96@\xcc\xddT\x92\xbc\x84\x9b.\x046\xa4r\xf3\\\xfe)\x15\x14\xbe!JSV\xba\xc6X)J\x05\x05\x04\x8e\xf8\xfc\xae\xab\xb5\xba\"m%\x86\x9c\x08E\x8e\xe9\xc3\xcd3\xc2\xe7\x1b\xd1\x82-\x9e!|\xf1q\xe3_\x85\xcbA\xef\xdb\xa4b\x87CwpiT\xa6\xf3M\xbdmR\xd0\xed%Z\x97\x0d\xec\xf5\xd2\x8eb\x7f\xec\xa6>>k\x9b3\xca\x90\x9b\xcc\xb5\nY\xd3\x89N\xc2JwL\x0duD:i\x95\x8e\x7f_\xd9\xda\xea.\xa97\x8cauM\x97\x1eJ6vc\xe8\x90\xe1\xb8][\xafF\x17\x83\xc6\xb8\xd3C\xbaQ\x99\xa9\xb7\x15\xf2\xb84o:\x9c\xa5\xc3\xd1-_4\xa6\x88R}q\xddE\xfd\x1f\xfa\x97\x1f\xdd\xc1\x80\xce\xa7=\xc3\xe0\x93\xc5T\x1f\xcf4\xaf\xdf\x98ZW\xcbA\xbf6D:l\xcc\xda\xe1\xe6\xf2\xce#\x8eF\x1e\xb5\xda\xe8\xab\x9av\xe0l\xa0\xb2>M\xeb\xdf\x0d\xb5\xf5\xad\x93\\\xfb\x8d\xd0\xd0+V\xadqk\xaa\xdd\xeb\xcd\xd5\x8d\xca/[\xd5T\xeb\xcc]c\xd5\xd7\xea\xea\x0dS\xf9]}Nib_|\x8d\xcej^0$\xceD\xab\x13\xac\xad:\x13\xb5\x12\x0c\xfb\x00[8\x9d\xcd\x07\xcb\x96\x1f\x7f\xe9u\xa3\x00w\x83V\xdas\xd4\x190+HG\xba\xa3\xb7\xe2p]\xad^\x9cE\x8d\xf6\xc8s\xce\xbc\xa1{\xebd\x01\xb8\x80B\xfby\xff\x0b\xc0`\xbd\x1a\xd3\xa0dC\x0b\xdb\xf0$\x97O\xc9?\x95$\x0e\x197a\x08P`\x82 \xc0 \xb4Ef1\xdb\x05\x8ep\xc9Kx F\x02k\n\xec\xc9\xcbE\x14EgA\x01\xb1\xad4\xe5{\x05\xaeAH\x02X\xb2p\xa8<\x14E%\xa3\x15i{\x18\xfe\x99/K\x85mQ\xce)9\x95\xa4B6]N\x10we\x1bpP\xa28\xe6\xd0$8@\x16\x82L\x06L\xbe\xcf\xc61\x1cS\x0b\n\xd6r3\xc0\x0eQ\x94I\xd9\xab\xce\x91d\xd5\xe3\x97\xf0&\xfc\x0dw\xe2\xbfu\xbc7\xa1o\xef\xec(=\x07\xdd=\xd3|\xc8\xdb/\xe0\xc3\xce(t\xe0;b\xcb\xda\x05o\xe9\xb7\x8f\xc7\xb6'y*>q\x1donOp\xbf\xde\xa4\x0f;s\x7f\x05\x00\x00\xff\xffPK\x07\x08\x14<\x81\xd1L\x03\x00\x00\xa9\n\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0d\x91\x90P\xe3\xe3,\x014\x04\x00\x00\"\x10\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\x1a\x9f\x98^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00q\x92\x90P\x14<\x81\xd1L\x03\x00\x00\xa9\n\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81u\x04\x00\x00authz_test.regoUT\x05\x00\x01\xb6\xa1\x98^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\x07\x08\x00\x00\x00\x00" + fs.RegisterWithNamespace("rego", data) +} From 5ad0e0ebdc8e80ba374642ef7b8f1282f3b8641d Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 14:53:39 -0600 Subject: [PATCH 08/25] authorize: build full URL from gRPC request --- authorize/grpc.go | 17 ++++++++++++++++- authorize/grpc_test.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/authorize/grpc.go b/authorize/grpc.go index c56320bb0..d42aaaf5b 100644 --- a/authorize/grpc.go +++ b/authorize/grpc.go @@ -4,6 +4,7 @@ package authorize import ( "context" + "net/url" "github.com/pomerium/pomerium/authorize/evaluator" "github.com/pomerium/pomerium/internal/grpc/authorize" @@ -22,7 +23,7 @@ func (a *Authorize) IsAuthorized(ctx context.Context, in *authorize.IsAuthorized Method: in.GetRequestMethod(), RequestURI: in.GetRequestRequestUri(), RemoteAddr: in.GetRequestRemoteAddr(), - URL: in.GetRequestUrl(), + URL: getFullURL(in.GetRequestUrl(), in.GetRequestHost()), } return a.pe.IsAuthorized(ctx, req) } @@ -38,3 +39,17 @@ func cloneHeaders(in protoHeader) map[string][]string { } return out } + +func getFullURL(rawurl, host string) string { + u, err := url.Parse(rawurl) + if err != nil { + u = &url.URL{Path: rawurl} + } + if u.Host == "" { + u.Host = host + } + if u.Scheme == "" { + u.Scheme = "http" + } + return u.String() +} diff --git a/authorize/grpc_test.go b/authorize/grpc_test.go index 33245d15c..c4a765957 100644 --- a/authorize/grpc_test.go +++ b/authorize/grpc_test.go @@ -47,3 +47,19 @@ func TestAuthorize_IsAuthorized(t *testing.T) { }) } } + +func Test_getFullURL(t *testing.T) { + tests := []struct { + rawurl, host, expect string + }{ + {"https://www.example.com/admin", "", "https://www.example.com/admin"}, + {"https://www.example.com/admin", "example.com", "https://www.example.com/admin"}, + {"/admin", "example.com", "http://example.com/admin"}, + } + for _, tt := range tests { + actual := getFullURL(tt.rawurl, tt.host) + if actual != tt.expect { + t.Errorf("expected getFullURL(%s, %s) to be %s, but got %s", tt.rawurl, tt.host, tt.expect, actual) + } + } +} From 85a1a6d01306605f882249693501faa5cb2a6e73 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 16:00:00 -0600 Subject: [PATCH 09/25] authorize,proxy: remove support for paths within the from parameter --- authorize/evaluator/opa/policy/authz.rego | 1 - authorize/evaluator/opa/policy/authz_test.rego | 3 --- authorize/evaluator/opa/policy/statik.go | 2 +- proxy/proxy.go | 7 +++++-- proxy/proxy_test.go | 8 -------- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/authorize/evaluator/opa/policy/authz.rego b/authorize/evaluator/opa/policy/authz.rego index 3790b2509..8ca118526 100644 --- a/authorize/evaluator/opa/policy/authz.rego +++ b/authorize/evaluator/opa/policy/authz.rego @@ -74,7 +74,6 @@ allowed_route_source(input_url_obj, policy) { object.get(policy, "source", "") != "" source_url_obj := parse_url(policy.source) input_url_obj.host == source_url_obj.host - startswith(input_url_obj.path, source_url_obj.path) } allowed_route_prefix(input_url_obj, policy) { diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index 448241541..2d292c5ee 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -54,9 +54,6 @@ test_allowed_route_source { allowed_route("http://example.com", {"source": "http://example.com"}) allowed_route("http://example.com", {"source": "https://example.com"}) not allowed_route("http://example.org", {"source": "example.com"}) - allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path"}) - allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path?qs"}) - not allowed_route("http://example.com/some/other/path", {"source": "https://example.com/some/path"}) } test_allowed_route_prefix { diff --git a/authorize/evaluator/opa/policy/statik.go b/authorize/evaluator/opa/policy/statik.go index 82bc044ff..66e68afcf 100644 --- a/authorize/evaluator/opa/policy/statik.go +++ b/authorize/evaluator/opa/policy/statik.go @@ -9,6 +9,6 @@ import ( const Rego = "rego" // static asset namespace func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x0d\x91\x90P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\x1a\x9f\x98^\xc4WQo\xdb6\x10~\xb6\x00\xfd\x87+\x8b\x02\xd2\xaa\xc9m\x81\x0d\x980!{\xd9/\xd8\xa3\xe1\xaa\xb4t\xb6\x99H\xa4@R\xb5\xdd \xff}8R\xb2\x15\xc5N\xd26\xd9^\x12\xebx\xf7\xf1\xfb\xeeH\x1e\xd9\xf2\xf2\x86o\x10Z\xd5\xa0\x16]\x93\xf2\xcen\xbf\x85A\x18\x88\xa6U\xdaB\xc5-O\xb5\xea,\x16\xad\xaaE)\xd0\xdc\x1f3[\xae\xb1*n\xf0@Q\x15\xaeyW[\xe0u\xadv\x90\xc3\x9a\xd7\x06i\xe0moZ\x1d\x00\x1b.\xea0\xf0\xdf\xb7a03\xaaAps\x84\xc1\xcc\x99\xb1*\xdcw$d\xdb\xd9\xb4\xd3u\x02\xf7I,\xdc\xe72\x0e\x83\x99U7(\xd3\x96\x1fj\xc5\xab\xd4\xa1C~\xde=\x1d\xd0;\x83\xda,\x8a\xe51\xfc+\xafE\x15\x06\xb3Ru\xd2F\x15\xcaC\x9c\xe7\x1f\xc2\xe0nL~\xa3U\xd7\xbe\x1as\x87N\xa4\x9ed\x7f\xf4\xfc>\xfa\xab\x03\x88\xa6Em\x94\xe4\x16_\xb9\x0e\xa3\x99\x8a\xd7\xac\xc9D\xd4\xeb\x96h,\xea\xbf(W\xa5\x1a.\xe4\x0b\xca\x19\xe7\xba\xf0\xe8\xd1\x99\xfd\x13\x7f7\xd3q\x0d\xfe\x07\xd6\x0fV\xdb3\x15\x9c\xe1R8.\x8e\xc5!&\xf2Gk\xa1V\xd7\x90\xe5\xd0rm\x90\x0c\xa7\x80x\xaa\xab0\xaa\xd3\xe5\x08\x92\x82\x8f\xb0\x0f\xbc[\x8dk\xb1\x7f\xb67\xb7\xdb\xe7\xfaj\xdc\xe0e\xe0\x87Ix\x9c\xb8\xab\xa6Z]ci\xd3\x0d\xda\xc8\x9b\x13`>\x8a%\xc0X\x0cy\x0e\x8c9\xf0\x17\x87~\xe3\xa1g\xdex\xbe*>2\xf5.\xf1\xb4\x82\xe9V\x19K\x14\xefC83\x01[\xae\xad\xd9\x89i\x86SJz2\x0d\"\xe3\xf94>Z\xd1\x8bZ}\xd4\x13i|\x01\xe8c\x1a\x1fW\xdbg\xd2\x87^\xd0yy-^\xa6\xc2\xed\xf6)\x8d?\x07;\xe8\x1b\x04p\xbb\xa5\xa9\x1ej<\xab\xe9\xb1=sqv\x17\xf4\x84\xaa\x9f\x06\x1eti,\x1an\xcb\xed\xb0\xd6\x9dOrF\xdfP\xb4\xd3\xee0V\xc7\x90\xc3-0Sn\xb1A\x96\x81\xff\x91\x00\xa3=\xc02\xa0\x7fC>3p\xc9\xbbs\xf4\x16Ert\xf6N\x9a\xefh\xdc5A\xe2\x90\xae\x85\xac\n^\xd7\x85\xb1Z\xc8Ma\xba\x95cZ\xc8(\x0cf\xb3/\xd1U\x16m\xadm\x17fy\x15g\xf3y|\x15->\xcf\x97\xef\xe3h\xf1\xf9\xea\xed\xf2\x97\xf8KB~\xc6\xea\x04>\xc6\x8b\x0f\xd44}\xf9@*\xdd\xf0Z|\xf3\xdb\xcf\xad\x90~\xfaA\xe5\x19\x8f^.\x9b3\xdf\x89\xac\x1eU\xe7\xb2?\xf9\x0d\xfeo\x8e\xfe\xa7z\x8e[\x91o8\xe4\xbd\xa7\x83\xc8\xb4\xb5\xb0\xde\x98\x00\xfb\x8b\xc5\xc7\xe6\xb3\x8f\xf3O\xe4\xb5\xf8\xb8$\x12\x8f\xdf\x1a<\xb8\xbf6\xb8\xa9O\xb7k\xdc\xb7Bc5\xbe_\x0f&b!\xd5\xae0X*Y\x99,\xb7\xa2\xc1\x94,\xd2D\xf1\xfc#\xfeAe\xdc\"\xafP'\xd0\xb7\xcf\x04\x8a%1\x17*\xbd\xde\xd9\xb4\xc2RU\xc7\xcelP\xc7\xae\x06\xfd\xfd`\xdf\xc2\x9f0\x9a\xa2gG\x8du\xc1\\\xcb\x05a\x8e\x14#\xdc\xb71[\x12\xad\xde4\xf67\xad\x16\xd2\xae\xa3>n\xcb\x0d\xacx\x05\xbc\xab\x04\xca\x12!\xe2]\x15g\xf0\xce\x80T\x16\x84\x84w\xef\xbf\xb2d\xe1\x99\xb9\x058\xd0\xe2]\xb5\x8c\xdd4?\"\x8e\xd0\xb1\xc6\x06\xa5-\x84,jal4BNN\x13\xc6\x93\xab\x0f!\x90^^5\xf7\xafv\x91\xa2\x96\x04'\xcb\xd7\x06b\xc0\x90(\xb2\x06{b\x8f\xbff\x98\x19c\xf0\x8a\xff^\x8dI\x88\xd3%*I\x15U}B\x9e{\xcf\xb9\xe7\xdcs!\xc0\xf2\x81\x03e\x82CHQ\x1c\x96@\xcc\xddT\x92\xbc\x84\x9b.\x046\xa4r\xf3\\\xfe)\x15\x14\xbe!JSV\xba\xc6X)J\x05\x05\x04\x8e\xf8\xfc\xae\xab\xb5\xba\"m%\x86\x9c\x08E\x8e\xe9\xc3\xcd3\xc2\xe7\x1b\xd1\x82-\x9e!|\xf1q\xe3_\x85\xcbA\xef\xdb\xa4b\x87CwpiT\xa6\xf3M\xbdmR\xd0\xed%Z\x97\x0d\xec\xf5\xd2\x8eb\x7f\xec\xa6>>k\x9b3\xca\x90\x9b\xcc\xb5\nY\xd3\x89N\xc2JwL\x0duD:i\x95\x8e\x7f_\xd9\xda\xea.\xa97\x8cauM\x97\x1eJ6vc\xe8\x90\xe1\xb8][\xafF\x17\x83\xc6\xb8\xd3C\xbaQ\x99\xa9\xb7\x15\xf2\xb84o:\x9c\xa5\xc3\xd1-_4\xa6\x88R}q\xddE\xfd\x1f\xfa\x97\x1f\xdd\xc1\x80\xce\xa7=\xc3\xe0\x93\xc5T\x1f\xcf4\xaf\xdf\x98ZW\xcbA\xbf6D:l\xcc\xda\xe1\xe6\xf2\xce#\x8eF\x1e\xb5\xda\xe8\xab\x9av\xe0l\xa0\xb2>M\xeb\xdf\x0d\xb5\xf5\xad\x93\\\xfb\x8d\xd0\xd0+V\xadqk\xaa\xdd\xeb\xcd\xd5\x8d\xca/[\xd5T\xeb\xcc]c\xd5\xd7\xea\xea\x0dS\xf9]}Nib_|\x8d\xcej^0$\xceD\xab\x13\xac\xad:\x13\xb5\x12\x0c\xfb\x00[8\x9d\xcd\x07\xcb\x96\x1f\x7f\xe9u\xa3\x00w\x83V\xdas\xd4\x190+HG\xba\xa3\xb7\xe2p]\xad^\x9cE\x8d\xf6\xc8s\xce\xbc\xa1{\xebd\x01\xb8\x80B\xfby\xff\x0b\xc0`\xbd\x1a\xd3\xa0dC\x0b\xdb\xf0$\x97O\xc9?\x95$\x0e\x197a\x08P`\x82 \xc0 \xb4Ef1\xdb\x05\x8ep\xc9Kx F\x02k\n\xec\xc9\xcbE\x14EgA\x01\xb1\xad4\xe5{\x05\xaeAH\x02X\xb2p\xa8<\x14E%\xa3\x15i{\x18\xfe\x99/K\x85mQ\xce)9\x95\xa4B6]N\x10we\x1bpP\xa28\xe6\xd0$8@\x16\x82L\x06L\xbe\xcf\xc61\x1cS\x0b\n\xd6r3\xc0\x0eQ\x94I\xd9\xab\xce\x91d\xd5\xe3\x97\xf0&\xfc\x0dw\xe2\xbfu\xbc7\xa1o\xef\xec(=\x07\xdd=\xd3|\xc8\xdb/\xe0\xc3\xce(t\xe0;b\xcb\xda\x05o\xe9\xb7\x8f\xc7\xb6'y*>q\x1donOp\xbf\xde\xa4\x0f;s\x7f\x05\x00\x00\xff\xffPK\x07\x08\x14<\x81\xd1L\x03\x00\x00\xa9\n\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0d\x91\x90P\xe3\xe3,\x014\x04\x00\x00\"\x10\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\x1a\x9f\x98^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00q\x92\x90P\x14<\x81\xd1L\x03\x00\x00\xa9\n\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb6\x81u\x04\x00\x00authz_test.regoUT\x05\x00\x01\xb6\xa1\x98^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\x07\x08\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00.\xaf\x90P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\xc8\xd4\x98^\xbcWQo\xdb6\x10~\x16\x7f\xc5\x95E\x01q\xd5\xe4\xa6\xc0\x06L\x98\x90\xbd\xec\x17\xec\xd1pUZ:\xdbL$R \xa9\xd8\xae\xe1\xff>\x90\x94lEq\xdcti\xf6b[\xc7\xe3w\xdf\xddw\xe6Q-/\xef\xf9\x1a\xa1U\x0dj\xd15)\xef\xec\xe6\x1b!\xa2i\x95\xb6Pq\xcbS\xad:\x8bE\xabjQ\n4\x8f\x96\xcc\x86k\xac\x8a{\xdc\x13R\xe1\x8aw\xb5\x05^\xd7j\x0b9\xacxm\x90\x90\xf7\xbda\xb9\x07l\xb8\xa8Ix<\x90\xc8\xa8\x06\xc1\x83\x93\xc8\x1b\xb1*\xfcc,d\xdb\xd9\xb4\xd3u\x02\x8f\x83\xcf\xfd\xe3\x82\x91\xc8\xaa{\x94i\xcb\xf7\xb5\xe2U\xea\x91!\xbf\xec\x9d\x0e\xe0\x9dAm\xe6\xc5b\xd8\xfd\xc0kQ\x91\xa8T\x9d\xb4q\x85r\xcf\xf2\xfc\x139\x9e9\xaf\xb5\xea\xda7!\xec\x91\x1d\x97\xef\x92>y\xbe\x98\xf5r\x0f\xa2iQ\x1b%\xb9\xc57\xac\xfa(J\xf1F\nLry;A\xc6\xb9\xbc\xb18\x95j\xb8\x90?)\x8bqe\x8b\x80\x1c_\xf8o\xb0\x1f!8\xae\xf8\xffL\xf6IK}\x9f\xf8\x05\x16\x85g\xe1\xe3\xef\xd9\x81D'c\xa1\x96w\x90\xe5\xd0rm\xd0\x19\xce\xfel\x92OaT\xa7\xcb\x11\xa0\xdb{\x02\x9d:\xb7\x1aWb\xf7Rgn7/t\xd5\xb8\xc6ga\xa7\xc9_\xa7\xec\xd4S\xcb;,m\xbaF\x1b\x07k\x024l\xa2 P\xca \xcf\x81Rr\xfc\xe9\xb8\xef\x18\x90\xca\x82\x90\xf0\xe1\xe3\x03M\xe6\x81\x91o\xb0\x81\x0f\xef\xaa\x05s!\xfeCN\x0e\x1bklP\xdaB\xc8\xa2\x16\xc6\xc6#\xdc\xe4\x1c\x8e\x8d/\x1bn\xb7K\x93W\xcd\xf8\x921E\xf2\xef\x1a\xde\xc7$\xf0\xe3\xb7\x9b\xa8T\xd2:\xe1Gw\x14\x9a\x0e\xaf<3\x0fL=/\xf2\x1e\xdc.\x90J\xfe\xea\xcd\x9e\xa1\x81\x95V\x0d\xf0\xb2D#\xe4:\xb0\x0d\xadfz\xc1\x86D\\\x1d\x02\xde\xe2p\xb9*/\xc8\xe5\xc5t\x83\xe49\x1ch\x0f\xe1O\x92^3\xea\x8bA3\xf0\xdf\xe1l\xf1?\x13\x98\xe8\xfbT\xdc\xe2\x01\xb5X\xed\xddqr\x969q\x10QD\x0d\x96\x1a\xdd\x11v~\xfbK\xfc\x02\xef\\\xb8Qg\x91(:\x92\xc8Su\x00Y\xfe8_g#>\xe9\xe9Jxg \xb7\xeb\xe9Z\xb0\x12#\xd6\x12\xab\xe2nk\xb3\xbc\xe7\x8e\xd2sw+\xf1\x81\xf2zM3\xa0\x7f\xff\xf3\xf9\xb7\xdf\xe9qR\xeb\xa4\x7f\x7f\x15k\xe9N\xd0{\xdc3B\xc8T+\xf7\x91x\x05\xdd\xd0\x00p\xcf\xe1\xb5\xc0\xd9\xc8\x91\xfc\x1b\x00\x00\xff\xffPK\x07\x08\xee;\x12\x1e\x1b\x04\x00\x00?\x0f\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x005\xaf\x90P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x01\xd7\xd4\x98^\xd4\x92\xdbo\xe28\x14\xc6\x9f\xc9_\x11\xe5\xa9]u\x80M\xb9\xcc U\xbb\xb4\xa4\x1dnSh\x80@\xab*2\x89\x9b\x98\\ll\x87@F\xfc\xef+\x9b\x96\xd2\x99t\xc5TZ\xad\xe6)\x8a\xcf9\xdf\xf9>\xffL\x80\x13\x00\x0f\xaa\x04G\x90\xa2$*\x82\x84\xfb\x99\xa2,Rn\xfb\x10\xb8\x90\xaa\x8d\x0b\xf5\xbbR\xd0\xf8\x86h\x0dU\xebX#\xedL)h \xf4\xc4\xefWS\xaf\xd64e\xab0\xe4\xc5(\xf6\xec\x00n^&\x02\xbe\x11-\xd8\xe1r\"\x10?\xb7\xc1u\xb4\xecw\xbf\x8c\xcbn4\xf0\xfbWVy2\xdb\xd4Z6\x05\x9dnjtX\xdf]/\xdd8 F~\x16\xe0\xf3\x96=\xa5\x0c\xf9\xe9\xcc(\x935\x1d\x9b$*wF\xd4\xd2\x87\xa4\x9dU\xe8\xe8\xcf\x95k\xac\xee\xd3Z\xdd\x1aT\xd6t\xb9@\xe9\xc6\xad\x0f<2\x18\xb5\xaa\xeb\xd5\xf0\xb2_\x1f\xb5\xbb\xc8\xb4\xcaS\xfd\xaeL\x9e\x96\xf6m\x9b\xb3l0\xbc\xe3\xf3\xfa\x04Qj\xceo:\xa8\xf7\xcd\xfc\xf4\xad\xd3\xef\xd3\xd9\xa4kY|<\x9f\x98\xa3\xa9\xb1\xe8\xd5'\xce\xf5\xb2\xdf\xab\x0e\x90 \xeb\xd3V\xb4\xb9\xba_\x10\xcf OFu\xf8Y\xcf\xdap\xda\xd7Y\x8ff\xb5\xaf\x96\xde\xfc\xd2No\x82zd\x99e\xa7Z\xbf\xb3\xf5\xce\xcd\xe6\xfaV\xe7W\xcdJf\xb4g\xbe\xb5\xea\x195\xfd\x96\xe9\xfc\xbe6\xa34u/?\xc7\xe7\xd5E8 \xde\xd8\xa8\x11l\xac\xdac\xbd\x1c\x0ez\x00;8\x9b\xce\xfa\xcbf\x90|\xeav\xe2\x10w\xc2f\xd6\xf5\xf4)\xb0\xcb\xc8D\xa6g6\x93h]\xa9\\\x9e\xc7\xf5\xd6p\xe1\x9d/\x06\xfe\x9d'\x01\xf8\x80B\xf7\xe5\xfe\xe7\x80\xc1Z%\xa1a\xd1\x85\x0ev\xe1\xc9\x01\x9fbp\xaa(\x1c2n\xc3\x08\xa0\xd0\x06a\x88S\xe8\nf \xdb\x01G\xb8\xb8Hy\x11\xc6b\xd6\x16\xb3'\xaf/\xe2Lt\x164\x90\xb8ZC}\xd0\xe0\x1aD$\x84E\x07G\xda\xe3\x99\xa8HYA{\x81\xe1\xdf\x87e\xa5\xb0=S\x0f\x9c\x9c*JAnWS\xc4}\xd5\x05\x1c\x14)N8\xb4 \x0e\x91\x83 S\x01S\x1f\xe4:\x86\x13\xea@\xa1z\xa8(\xf7=\x07\xb0\x85{&=\xfd\xb8\xf8Q)l\x1f\x0f\x96\x1c\xbeV\xc0\x0e-\x1d6\xbd\xde\xa8\xe8y\xfd\x93-(& \x17\x05\xe9.\xa12\xb0\xcf9i\x94J?9\xf41\xe3\xb9\xd6\x85e\xad\xa1\x8a\x8fR\xd8*\xdb7`\\\x18\xa3\xff\x8dK\x8c\xb9\xfa\x9f\xb0\x99\xe3\xf9o\xcd\x86\x00\xca\xa0\x9d\xd0P\x82\xa1\xa1\xe0\xb2?;\xc9YSb8\x82%\x02\xb8\xff\xd7\x92i\xa7r\xa8\xc8\x1c\x1fFP\xbd\xb8\xd8\x19\xd3v\xa7\xc2\x8b<{KG\x94\xc4\xbc,\xbd\xcai{O/\xb7\xbc\x03\xb4\xc3!\xec\xbd9\xcf\xf3\xa6\x9d\xa9\xdf\xdf\xc1\xb7=\xfd\xf5\xf9\x9c\x86\x8f\xca\xb0\x1c\x9d\xfd\x9b|W\x0bS\xef\xdf#\xe5\xdf\x18\xa1\xf0 \xad\x8f\xbf\xb1]\xbf\x90/\x1d\x17\xb0\x04\xdc\x08\xc5\x12\x9d$\xf7\x83\x88\xac\x1e\x191\xc7\xc3~\xfc\x9dt\xe2\xe9\x1c\x9fM\xf8\xdb';\xcaOn\xba\x17\x99\x0fe\xfbi8?\x19\x85\x1e\xfc\x05l\xb2]\xe8\x16\xff\xf88\xb6\xbd\xc8s\xf1Y\xeb\xf8p{\x81\x87\xf5&{\xdc\x85\xfb'\x00\x00\xff\xffPK\x07\x08\x08\xcb\x89\x8b7\x03\x00\x00\x88 \x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00.\xaf\x90P\xee;\x12\x1e\x1b\x04\x00\x00?\x0f\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\xc8\xd4\x98^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x005\xaf\x90P\x08\xcb\x89\x8b7\x03\x00\x00\x88 \x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\\\x04\x00\x00authz_test.regoUT\x05\x00\x01\xd7\xd4\x98^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xd9\x07\x00\x00\x00\x00" fs.RegisterWithNamespace("rego", data) } diff --git a/proxy/proxy.go b/proxy/proxy.go index d3e23a3b6..a600eeffd 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -330,10 +330,13 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // // Routes can be filtered by the `source`, `prefix`, `path` and `regex` fields in the policy config. func routeMatcherFuncFromPolicy(policy config.Policy) mux.MatcherFunc { + if !(policy.Source.Path == "" || policy.Source.Path == "/") { + log.Warn().Str("source", policy.Source.String()).Msg("proxy: dropping path from %v, should be set using path key") + } + // match by source sourceMatches := func(r *http.Request) bool { - return r.Host == policy.Source.Host && - strings.HasPrefix(r.URL.Path, policy.Source.Path) + return r.Host == policy.Source.Host } // match by prefix diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 97a16cf24..d86f962b4 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -292,14 +292,6 @@ func TestRouteMatcherFuncFromPolicy(t *testing.T) { "https://www.google.com", false, "should not match when host is different from source host"}, - // path prefix in source - {"https://www.example.com/admin", "", "", "", - "https://www.example.com/admin/someaction", true, - "should match when path begins with source path"}, - {"https://www.example.com/admin", "", "", "", - "https://www.example.com/notadmin", false, - "should not match when path does not begin with source path"}, - // path prefix {"https://www.example.com", "/admin", "", "", "https://www.example.com/admin/someaction", true, From c8c307be6994d5704558017c48fed03f3328dc2f Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 16:07:29 -0600 Subject: [PATCH 10/25] proxy: update warning message --- proxy/proxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/proxy.go b/proxy/proxy.go index a600eeffd..27d5ae617 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -331,7 +331,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Routes can be filtered by the `source`, `prefix`, `path` and `regex` fields in the policy config. func routeMatcherFuncFromPolicy(policy config.Policy) mux.MatcherFunc { if !(policy.Source.Path == "" || policy.Source.Path == "/") { - log.Warn().Str("source", policy.Source.String()).Msg("proxy: dropping path from %v, should be set using path key") + log.Warn().Str("from", policy.From).Msgf("proxy: dropping path from %s, should be set using path key", policy.Source.String()) } // match by source From e1d2501a94e99f095e7a2c2afd7355267b3cef93 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Thu, 16 Apr 2020 16:39:03 -0600 Subject: [PATCH 11/25] proxy: move warning message to config validation --- config/policy.go | 7 +++++++ config/policy_test.go | 1 + proxy/proxy.go | 4 ---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/config/policy.go b/config/policy.go index 7537f067a..8705ae55b 100644 --- a/config/policy.go +++ b/config/policy.go @@ -90,6 +90,13 @@ func (p *Policy) Validate() error { if err != nil { return fmt.Errorf("config: policy bad source url %w", err) } + + // Make sure there's no path set on the from url + if !(source.Path == "" || source.Path == "/") { + return fmt.Errorf("config: policy source url (%s) contains a path, but it should be set using the path field instead", + source.String()) + } + p.Source = &StringURL{source} p.Destination, err = urlutil.ParseAndValidateURL(p.To) diff --git a/config/policy_test.go b/config/policy_test.go index a35cf612b..fbe532744 100644 --- a/config/policy_test.go +++ b/config/policy_test.go @@ -20,6 +20,7 @@ func Test_PolicyValidate(t *testing.T) { {"empty from host", Policy{From: "https://", To: "https://httpbin.corp.example"}, true}, {"empty from scheme", Policy{From: "httpbin.corp.example", To: "https://httpbin.corp.example"}, true}, {"empty to scheme", Policy{From: "https://httpbin.corp.example", To: "//httpbin.corp.example"}, true}, + {"path in from", Policy{From: "https://httpbin.corp.example/some/path", To: "https://httpbin.corp.example"}, true}, {"cors policy", Policy{From: "https://httpbin.corp.example", To: "https://httpbin.corp.notatld", CORSAllowPreflight: true}, false}, {"public policy", Policy{From: "https://httpbin.corp.example", To: "https://httpbin.corp.notatld", AllowPublicUnauthenticatedAccess: true}, false}, {"public and whitelist", Policy{From: "https://httpbin.corp.example", To: "https://httpbin.corp.notatld", AllowPublicUnauthenticatedAccess: true, AllowedUsers: []string{"test@domain.example"}}, true}, diff --git a/proxy/proxy.go b/proxy/proxy.go index 27d5ae617..43339000a 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -330,10 +330,6 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // // Routes can be filtered by the `source`, `prefix`, `path` and `regex` fields in the policy config. func routeMatcherFuncFromPolicy(policy config.Policy) mux.MatcherFunc { - if !(policy.Source.Path == "" || policy.Source.Path == "/") { - log.Warn().Str("from", policy.From).Msgf("proxy: dropping path from %s, should be set using path key", policy.Source.String()) - } - // match by source sourceMatches := func(r *http.Request) bool { return r.Host == policy.Source.Host From 19053c8f064d05225731aea253c774c179d3f744 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 07:57:26 -0600 Subject: [PATCH 12/25] proxy: add additional tests for trailing slash --- authorize/evaluator/opa/policy/authz_test.rego | 2 ++ proxy/proxy_test.go | 3 +++ 2 files changed, 5 insertions(+) diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index 2d292c5ee..d75e0f756 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -53,6 +53,7 @@ test_allowed_route_source { allowed_route("http://example.com", {"source": "example.com"}) allowed_route("http://example.com", {"source": "http://example.com"}) allowed_route("http://example.com", {"source": "https://example.com"}) + allowed_route("http://example.com/", {"source": "https://example.com"}) not allowed_route("http://example.org", {"source": "example.com"}) } @@ -64,6 +65,7 @@ test_allowed_route_prefix { test_allowed_route_path { allowed_route("http://example.com", {"path": "/"}) + allowed_route("http://example.com/", {"path": "/"}) not allowed_route("http://example.com/admin/somepath", {"path": "/admin"}) not allowed_route("http://example.com", {"path": "/admin"}) } diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index d86f962b4..b14aeca15 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -288,6 +288,9 @@ func TestRouteMatcherFuncFromPolicy(t *testing.T) { {"https://www.example.com", "", "", "", "https://www.example.com", true, "should match when host is the same as source host"}, + {"https://www.example.com/", "", "", "", + "https://www.example.com", true, + "should match when host is the same as source host with trailing slash"}, {"https://www.example.com", "", "", "", "https://www.google.com", false, "should not match when host is different from source host"}, From a1424a54d0fb71ab39de804590b2cc6df816ebc6 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 07:59:24 -0600 Subject: [PATCH 13/25] authorize: more tests --- authorize/evaluator/opa/policy/authz_test.rego | 2 ++ 1 file changed, 2 insertions(+) diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index d75e0f756..8db234eaf 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -54,6 +54,8 @@ test_allowed_route_source { allowed_route("http://example.com", {"source": "http://example.com"}) allowed_route("http://example.com", {"source": "https://example.com"}) allowed_route("http://example.com/", {"source": "https://example.com"}) + allowed_route("http://example.com", {"source": "https://example.com/"}) + allowed_route("http://example.com/", {"source": "https://example.com/"}) not allowed_route("http://example.org", {"source": "example.com"}) } From 90af23432c773363ecf5d9ebda8683e6b254521f Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 08:11:56 -0600 Subject: [PATCH 14/25] authorize: run opa test in ci --- .github/workflows/test.yaml | 5 +++++ Makefile | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 21d6e9247..5fad595bf 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,6 +31,11 @@ jobs: uses: actions/setup-go@v1 with: go-version: ${{ matrix.go-version }} + - name: Install OPA + run: | + cd /usr/local/bin + sudo curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64 + sudo chmod +x ./opa - name: Checkout code uses: actions/checkout@v2 - name: Test diff --git a/Makefile b/Makefile index d78fbcb53..424280b7c 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ CTIMEVAR=-X $(PKG)/internal/version.GitCommit=$(GITCOMMIT) \ -X $(PKG)/internal/version.ProjectURL=$(PKG) GO_LDFLAGS=-ldflags "-s -w $(CTIMEVAR)" GOOSARCHES = linux/amd64 darwin/amd64 windows/amd64 -GOLANGCI_VERSION = v1.21.0 - +GOLANGCI_VERSION = v1.21.0 + .PHONY: all all: clean build-deps test lint spellcheck build ## Runs a clean, build, fmt, lint, test, and vet. @@ -68,6 +68,7 @@ lint: ## Verifies `golint` passes. test: ## Runs the go tests. @echo "==> $@" @go test -tags "$(BUILDTAGS)" $(shell go list ./... | grep -v vendor) + @opa test ./authorize/evaluator/opa/policy .PHONY: spellcheck spellcheck: # Spellcheck docs From 6cda829ed8bbf9941d2050a5e196d83dc31752ae Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 08:17:35 -0600 Subject: [PATCH 15/25] ci: download the proper opa binary --- .github/workflows/test.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5fad595bf..48e8dd4a9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -33,8 +33,9 @@ jobs: go-version: ${{ matrix.go-version }} - name: Install OPA run: | + OS=$(uname | tr '[:upper:]' '[:lower:]') cd /usr/local/bin - sudo curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64 + sudo curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_${OS}_amd64 sudo chmod +x ./opa - name: Checkout code uses: actions/checkout@v2 From 7aa97dee68bec251edbfef07cf1da48a8af40f75 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 08:23:50 -0600 Subject: [PATCH 16/25] ci: install opa from source --- .github/workflows/test.yaml | 6 ------ Makefile | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 48e8dd4a9..21d6e9247 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,12 +31,6 @@ jobs: uses: actions/setup-go@v1 with: go-version: ${{ matrix.go-version }} - - name: Install OPA - run: | - OS=$(uname | tr '[:upper:]' '[:lower:]') - cd /usr/local/bin - sudo curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_${OS}_amd64 - sudo chmod +x ./opa - name: Checkout code uses: actions/checkout@v2 - name: Test diff --git a/Makefile b/Makefile index 424280b7c..fc68e2502 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ build-deps: ## Install build dependencies @echo "==> $@" @cd /tmp; GO111MODULE=on go get -u github.com/client9/misspell/cmd/misspell @cd /tmp; GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_VERSION} + @cd /tmp; GO111MODULE=on go get -u github.com/open-policy-agent/opa .PHONY: docs docs: ## Start the vuepress docs development server From f979bae194cd2893c925f919c181a104b0b0a528 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 08:32:32 -0600 Subject: [PATCH 17/25] ci: specify version number for build dependencies, call build-deps before test --- .github/workflows/test.yaml | 2 ++ Makefile | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 21d6e9247..c580a0b36 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -33,6 +33,8 @@ jobs: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@v2 + - name: Build dependencies + run: make build-deps - name: Test run: make test diff --git a/Makefile b/Makefile index fc68e2502..c48c1e81e 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,9 @@ CTIMEVAR=-X $(PKG)/internal/version.GitCommit=$(GITCOMMIT) \ -X $(PKG)/internal/version.ProjectURL=$(PKG) GO_LDFLAGS=-ldflags "-s -w $(CTIMEVAR)" GOOSARCHES = linux/amd64 darwin/amd64 windows/amd64 +MISSPELL_VERSION = v0.3.4 GOLANGCI_VERSION = v1.21.0 +OPA_VERSION = v0.19.1 .PHONY: all all: clean build-deps test lint spellcheck build ## Runs a clean, build, fmt, lint, test, and vet. @@ -36,9 +38,9 @@ all: clean build-deps test lint spellcheck build ## Runs a clean, build, fmt, li .PHONY: build-deps build-deps: ## Install build dependencies @echo "==> $@" - @cd /tmp; GO111MODULE=on go get -u github.com/client9/misspell/cmd/misspell + @cd /tmp; GO111MODULE=on go get github.com/client9/misspell/cmd/misspell@${MISSPELL_VERSION} @cd /tmp; GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_VERSION} - @cd /tmp; GO111MODULE=on go get -u github.com/open-policy-agent/opa + @cd /tmp; GO111MODULE=on go get github.com/open-policy-agent/opa@${OPA_VERSION} .PHONY: docs docs: ## Start the vuepress docs development server From 6baf25dae8adfade18682f3e259f8a36d54d5c31 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 08:37:45 -0600 Subject: [PATCH 18/25] ci: add go bin dir to path for test --- .github/workflows/test.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c580a0b36..24672648b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -36,7 +36,9 @@ jobs: - name: Build dependencies run: make build-deps - name: Test - run: make test + run: | + export PATH=$PATH:$(go env GOPATH)/bin + make test cover: strategy: From 9e66471c07a073113809a8922a588172c36fe3f1 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 09:10:07 -0600 Subject: [PATCH 19/25] docs: add additional path filtering configuration documentation --- docs/configuration/readme.md | 44 +++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/configuration/readme.md b/docs/configuration/readme.md index e7e24cf7c..e2b29110d 100644 --- a/docs/configuration/readme.md +++ b/docs/configuration/readme.md @@ -753,12 +753,27 @@ Policy contains route specific settings, and access control details. If you are <<< @/docs/configuration/examples/config/policy.example.yaml +Policy routes are checked in the order they appear in the policy, so more specific routes should appear before less specific routes. For example: + +```yaml +policies: + - from: http://from.example.com + to: http://to.example.com + prefix: /admin + allowed_groups: ["superuser"] + - from: http://from.example.com + to: http://to.example.com + allow_public_unauthenticated_access: true +``` + +In this example an incoming request with a path prefix of `/admin` would be handled by the first route (which is restricted to superusers). All other requests for `from.example.com` would be handled by the second route (which is open to the public). + A list of policy configuration variables follows. ### From - `yaml`/`json` setting: `from` -- Type: `URL` (must contain a scheme and hostname) +- Type: `URL` (must contain a scheme and hostname, must not contain a path) - Required - Example: `https://httpbin.corp.example.com` @@ -773,6 +788,33 @@ A list of policy configuration variables follows. `To` is the destination of a proxied request. It can be an internal resource, or an external resource. +### Prefix + +- `yaml`/`json` setting: `prefix` +- Type: `string` +- Optional +- Example: `/admin` + +If set, the route will only match incoming requests with a path that begins with the specified prefix. + +### Path + +- `yaml`/`json` setting: `path` +- Type: `string` +- Optional +- Example: `/admin/some/exact/path` + +If set, the route will only match incoming requests with a path that is an exact match for the specified path. + +### Regex + +- `yaml`/`json` setting: `regex` +- Type: `string` (containing a regular expression) +- Optional +- Example: `^/(admin|superuser)/.*$` + +If set, the route will only match incoming requests with a path that matches the specified regular expression. The supported syntax is the same as the Go [regexp package](https://golang.org/pkg/regexp/) which is based on [re2](https://github.com/google/re2/wiki/Syntax). + ### Allowed Users - `yaml`/`json` setting: `allowed_users` From 5be8265e62daaef2ecf81db3a913491ec30efcf2 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 09:48:53 -0600 Subject: [PATCH 20/25] proxy: add test to confirm prefix routing behaves as expected --- proxy/proxy_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index b14aeca15..fe1c35488 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -1,6 +1,7 @@ package proxy import ( + "io" "io/ioutil" "net" "net/http" @@ -349,3 +350,65 @@ func TestRouteMatcherFuncFromPolicy(t *testing.T) { } } } + +func TestPolicyPrefixRouting(t *testing.T) { + adminServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "admin: "+r.URL.Path) + })) + defer adminServer.Close() + + publicServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "public: "+r.URL.Path) + })) + defer publicServer.Close() + + opts := testOptions(t) + opts.Policies = []config.Policy{ + { + From: "https://from.example.com", + To: "http://" + adminServer.Listener.Addr().String(), + Prefix: "/admin", + AllowPublicUnauthenticatedAccess: true, + }, + { + From: "https://from.example.com", + To: "http://" + publicServer.Listener.Addr().String(), + AllowPublicUnauthenticatedAccess: true, + }, + } + + p, err := New(opts) + if err != nil { + t.Fatalf("error creating proxy: %v", err) + } + + t.Run("admin", func(t *testing.T) { + req, err := http.NewRequest("GET", "https://from.example.com/admin/path", nil) + if err != nil { + t.Fatalf("error creating http request: %v", err) + } + + rr := httptest.NewRecorder() + p.ServeHTTP(rr, req) + rr.Flush() + + if rr.Body.String() != "admin: /admin/path" { + t.Errorf("expected admin request to go to the admin backend") + } + }) + + t.Run("non-admin", func(t *testing.T) { + req, err := http.NewRequest("GET", "https://from.example.com/nonadmin/path", nil) + if err != nil { + t.Fatalf("error creating http request: %v", err) + } + + rr := httptest.NewRecorder() + p.ServeHTTP(rr, req) + rr.Flush() + + if rr.Body.String() != "public: /nonadmin/path" { + t.Errorf("expected non-admin request to go to the public backend") + } + }) +} \ No newline at end of file From 2130a58dfb23b172b7668db75af47d0627d88580 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 09:54:34 -0600 Subject: [PATCH 21/25] proxy: fmt code --- proxy/proxy_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index fe1c35488..b4b770f6c 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -365,14 +365,14 @@ func TestPolicyPrefixRouting(t *testing.T) { opts := testOptions(t) opts.Policies = []config.Policy{ { - From: "https://from.example.com", - To: "http://" + adminServer.Listener.Addr().String(), - Prefix: "/admin", + From: "https://from.example.com", + To: "http://" + adminServer.Listener.Addr().String(), + Prefix: "/admin", AllowPublicUnauthenticatedAccess: true, }, { - From: "https://from.example.com", - To: "http://" + publicServer.Listener.Addr().String(), + From: "https://from.example.com", + To: "http://" + publicServer.Listener.Addr().String(), AllowPublicUnauthenticatedAccess: true, }, } @@ -411,4 +411,4 @@ func TestPolicyPrefixRouting(t *testing.T) { t.Errorf("expected non-admin request to go to the public backend") } }) -} \ No newline at end of file +} From 170f7f07d3dafc0c2e037ec0d92f7120b57b700d Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 17 Apr 2020 10:05:15 -0600 Subject: [PATCH 22/25] docs: add upgrading documentation for potentially breaking configuration changes --- docs/docs/upgrading.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/docs/upgrading.md b/docs/docs/upgrading.md index 17270c678..a838d9f24 100644 --- a/docs/docs/upgrading.md +++ b/docs/docs/upgrading.md @@ -5,6 +5,45 @@ description: >- for Pomerium. Please read it carefully. --- +# Since 0.8.0 + +## Breaking + +### Using paths in from URLs + +Although it's unlikely anyone ever used it, prior to 0.8.0 the policy configuration allowed you to specify a `from` field with a path component: + +```yaml +policy: + - from: "https://example.com/some/path" +``` +The proxy and authorization server would simply ignore the path and route/authorize based on the host name. + +With the introduction of `prefix`, `path` and `regex` fields to the policy route configuration, we decided not to support using a path in the `from` url, since the behavior was somewhat ambiguous and better handled by the explicit fields. + +To avoid future confusion, the application will now declare any configuration which contains a `from` field with a path as invalid, with this error message: + +``` +config: policy source url (%s) contains a path, but it should be set using the path field instead +``` + +If you see this error you can fix it by simply removing the path from the `from` field and moving it to a `prefix` field. + +In other words, this configuration: + +```yaml +policy: + - from: "http://example.com/some/path" +``` + +Should be written like this: + +```yaml +policy: + - from: "http://example.com" + prefix: "/some/path" +``` + # Since 0.6.0 ## Breaking From ea1c6efc24953dea5eee0cb6bdc8927332198423 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Mon, 20 Apr 2020 13:42:03 -0600 Subject: [PATCH 23/25] authorize: fix domain check bug, rewrite url for forward auth, add dev script --- authorize/evaluator/opa/policy/authz.rego | 20 ++++++--- .../evaluator/opa/policy/authz_test.rego | 23 ++++++++++ authorize/evaluator/opa/policy/statik.go | 2 +- proxy/forward_auth.go | 13 ++++-- scripts/build-dev-docker.bash | 42 +++++++++++++++++++ 5 files changed, 90 insertions(+), 10 deletions(-) create mode 100755 scripts/build-dev-docker.bash diff --git a/authorize/evaluator/opa/policy/authz.rego b/authorize/evaluator/opa/policy/authz.rego index 8ca118526..c5786f750 100644 --- a/authorize/evaluator/opa/policy/authz.rego +++ b/authorize/evaluator/opa/policy/authz.rego @@ -12,15 +12,18 @@ allow { token.payload.email = route_policies[route].allowed_users[_] token.valid count(deny)==0 + trace(sprintf("allow by email (route=%v email=%v)", [route, token.payload.email])) } # allow group allow { some route allowed_route(input.url, route_policies[route]) - token.payload.groups[_] = route_policies[route].allowed_groups[_] + some group + token.payload.groups[group] == route_policies[route].allowed_groups[_] token.valid count(deny)==0 + trace(sprintf("allow by group (route=%v group=%v)", [route, group])) } # allow by impersonate email @@ -30,33 +33,40 @@ allow { token.payload.impersonate_email = route_policies[route].allowed_users[_] token.valid count(deny)==0 + trace(sprintf("allow by impersonate email (route=%v email=%v)", [route, token.payload.impersonate_email])) } # allow by impersonate group allow { some route allowed_route(input.url, route_policies[route]) - token.payload.impersonate_groups[_] = route_policies[route].allowed_groups[_] + some group + token.payload.impersonate_groups[group] == route_policies[route].allowed_groups[_] token.valid count(deny)==0 + trace(sprintf("allow by impersonate group (route=%v group=%v)", [route, group])) } # allow by domain allow { some route allowed_route(input.url, route_policies[route]) - allowed_user_domain(token.payload.email) + some domain + email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain]) token.valid count(deny)==0 + trace(sprintf("allow by domain (route=%v email=%v domain=%v)", [route, token.payload.email, domain])) } # allow by impersonate domain allow { some route allowed_route(input.url, route_policies[route]) - allowed_user_domain(token.payload.impersonate_email) + some domain + email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain]) token.valid count(deny)==0 + trace(sprintf("allow by impersonate domain (route=%v email=%v domain=%v)", [route, token.payload.impersonate_email, domain])) } allowed_route(input_url, policy){ @@ -114,7 +124,7 @@ normalize_url_path(str) = str { str != "" } -allowed_user_domain(email){ +email_in_domain(email, domain) { x := split(email, "@") count(x) == 2 x[1] == domain diff --git a/authorize/evaluator/opa/policy/authz_test.rego b/authorize/evaluator/opa/policy/authz_test.rego index 8db234eaf..285cbc131 100644 --- a/authorize/evaluator/opa/policy/authz_test.rego +++ b/authorize/evaluator/opa/policy/authz_test.rego @@ -26,6 +26,29 @@ test_email_allowed { } } +test_example { + user := io.jwt.encode_sign(jwt_header, { + "aud": ["example.com"], + "email": "joe@example.com" + }, signing_key) + not allow with data.route_policies as [ + { + "source": "http://example.com", + "path": "/a", + "allowed_domains": ["example.com"] + }, + { + "source": "http://example.com", + "path": "/b", + "allowed_users": ["noone@pomerium.com"] + }, + ] with data.signing_key as signing_key with data.shared_key as shared_key with input as { + "url": "http://example.com/b", + "host": "example.com", + "user": user + } +} + test_email_denied { user := io.jwt.encode_sign(jwt_header, { "aud": ["example.com"], diff --git a/authorize/evaluator/opa/policy/statik.go b/authorize/evaluator/opa/policy/statik.go index 66e68afcf..3ac101116 100644 --- a/authorize/evaluator/opa/policy/statik.go +++ b/authorize/evaluator/opa/policy/statik.go @@ -9,6 +9,6 @@ import ( const Rego = "rego" // static asset namespace func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00.\xaf\x90P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\xc8\xd4\x98^\xbcWQo\xdb6\x10~\x16\x7f\xc5\x95E\x01q\xd5\xe4\xa6\xc0\x06L\x98\x90\xbd\xec\x17\xec\xd1pUZ:\xdbL$R \xa9\xd8\xae\xe1\xff>\x90\x94lEq\xdcti\xf6b[\xc7\xe3w\xdf\xddw\xe6Q-/\xef\xf9\x1a\xa1U\x0dj\xd15)\xef\xec\xe6\x1b!\xa2i\x95\xb6Pq\xcbS\xad:\x8bE\xabjQ\n4\x8f\x96\xcc\x86k\xac\x8a{\xdc\x13R\xe1\x8aw\xb5\x05^\xd7j\x0b9\xacxm\x90\x90\xf7\xbda\xb9\x07l\xb8\xa8Ix<\x90\xc8\xa8\x06\xc1\x83\x93\xc8\x1b\xb1*\xfcc,d\xdb\xd9\xb4\xd3u\x02\x8f\x83\xcf\xfd\xe3\x82\x91\xc8\xaa{\x94i\xcb\xf7\xb5\xe2U\xea\x91!\xbf\xec\x9d\x0e\xe0\x9dAm\xe6\xc5b\xd8\xfd\xc0kQ\x91\xa8T\x9d\xb4q\x85r\xcf\xf2\xfc\x139\x9e9\xaf\xb5\xea\xda7!\xec\x91\x1d\x97\xef\x92>y\xbe\x98\xf5r\x0f\xa2iQ\x1b%\xb9\xc57\xac\xfa(J\xf1F\nLry;A\xc6\xb9\xbc\xb18\x95j\xb8\x90?)\x8bqe\x8b\x80\x1c_\xf8o\xb0\x1f!8\xae\xf8\xffL\xf6IK}\x9f\xf8\x05\x16\x85g\xe1\xe3\xef\xd9\x81D'c\xa1\x96w\x90\xe5\xd0rm\xd0\x19\xce\xfel\x92OaT\xa7\xcb\x11\xa0\xdb{\x02\x9d:\xb7\x1aWb\xf7Rgn7/t\xd5\xb8\xc6ga\xa7\xc9_\xa7\xec\xd4S\xcb;,m\xbaF\x1b\x07k\x024l\xa2 P\xca \xcf\x81Rr\xfc\xe9\xb8\xef\x18\x90\xca\x82\x90\xf0\xe1\xe3\x03M\xe6\x81\x91o\xb0\x81\x0f\xef\xaa\x05s!\xfeCN\x0e\x1bklP\xdaB\xc8\xa2\x16\xc6\xc6#\xdc\xe4\x1c\x8e\x8d/\x1bn\xb7K\x93W\xcd\xf8\x921E\xf2\xef\x1a\xde\xc7$\xf0\xe3\xb7\x9b\xa8T\xd2:\xe1Gw\x14\x9a\x0e\xaf<3\x0fL=/\xf2\x1e\xdc.\x90J\xfe\xea\xcd\x9e\xa1\x81\x95V\x0d\xf0\xb2D#\xe4:\xb0\x0d\xadfz\xc1\x86D\\\x1d\x02\xde\xe2p\xb9*/\xc8\xe5\xc5t\x83\xe49\x1ch\x0f\xe1O\x92^3\xea\x8bA3\xf0\xdf\xe1l\xf1?\x13\x98\xe8\xfbT\xdc\xe2\x01\xb5X\xed\xddqr\x969q\x10QD\x0d\x96\x1a\xdd\x11v~\xfbK\xfc\x02\xef\\\xb8Qg\x91(:\x92\xc8Su\x00Y\xfe8_g#>\xe9\xe9Jxg \xb7\xeb\xe9Z\xb0\x12#\xd6\x12\xab\xe2nk\xb3\xbc\xe7\x8e\xd2sw+\xf1\x81\xf2zM3\xa0\x7f\xff\xf3\xf9\xb7\xdf\xe9qR\xeb\xa4\x7f\x7f\x15k\xe9N\xd0{\xdc3B\xc8T+\xf7\x91x\x05\xdd\xd0\x00p\xcf\xe1\xb5\xc0\xd9\xc8\x91\xfc\x1b\x00\x00\xff\xffPK\x07\x08\xee;\x12\x1e\x1b\x04\x00\x00?\x0f\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x005\xaf\x90P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x01\xd7\xd4\x98^\xd4\x92\xdbo\xe28\x14\xc6\x9f\xc9_\x11\xe5\xa9]u\x80M\xb9\xcc U\xbb\xb4\xa4\x1dnSh\x80@\xab*2\x89\x9b\x98\\ll\x87@F\xfc\xef+\x9b\x96\xd2\x99t\xc5TZ\xad\xe6)\x8a\xcf9\xdf\xf9>\xffL\x80\x13\x00\x0f\xaa\x04G\x90\xa2$*\x82\x84\xfb\x99\xa2,Rn\xfb\x10\xb8\x90\xaa\x8d\x0b\xf5\xbbR\xd0\xf8\x86h\x0dU\xebX#\xedL)h \xf4\xc4\xefWS\xaf\xd64e\xab0\xe4\xc5(\xf6\xec\x00n^&\x02\xbe\x11-\xd8\xe1r\"\x10?\xb7\xc1u\xb4\xecw\xbf\x8c\xcbn4\xf0\xfbWVy2\xdb\xd4Z6\x05\x9dnjtX\xdf]/\xdd8 F~\x16\xe0\xf3\x96=\xa5\x0c\xf9\xe9\xcc(\x935\x1d\x9b$*wF\xd4\xd2\x87\xa4\x9dU\xe8\xe8\xcf\x95k\xac\xee\xd3Z\xdd\x1aT\xd6t\xb9@\xe9\xc6\xad\x0f<2\x18\xb5\xaa\xeb\xd5\xf0\xb2_\x1f\xb5\xbb\xc8\xb4\xcaS\xfd\xaeL\x9e\x96\xf6m\x9b\xb3l0\xbc\xe3\xf3\xfa\x04Qj\xceo:\xa8\xf7\xcd\xfc\xf4\xad\xd3\xef\xd3\xd9\xa4kY|<\x9f\x98\xa3\xa9\xb1\xe8\xd5'\xce\xf5\xb2\xdf\xab\x0e\x90 \xeb\xd3V\xb4\xb9\xba_\x10\xcf OFu\xf8Y\xcf\xdap\xda\xd7Y\x8ff\xb5\xaf\x96\xde\xfc\xd2No\x82zd\x99e\xa7Z\xbf\xb3\xf5\xce\xcd\xe6\xfaV\xe7W\xcdJf\xb4g\xbe\xb5\xea\x195\xfd\x96\xe9\xfc\xbe6\xa34u/?\xc7\xe7\xd5E8 \xde\xd8\xa8\x11l\xac\xdac\xbd\x1c\x0ez\x00;8\x9b\xce\xfa\xcbf\x90|\xeav\xe2\x10w\xc2f\xd6\xf5\xf4)\xb0\xcb\xc8D\xa6g6\x93h]\xa9\\\x9e\xc7\xf5\xd6p\xe1\x9d/\x06\xfe\x9d'\x01\xf8\x80B\xf7\xe5\xfe\xe7\x80\xc1Z%\xa1a\xd1\x85\x0ev\xe1\xc9\x01\x9fbp\xaa(\x1c2n\xc3\x08\xa0\xd0\x06a\x88S\xe8\nf \xdb\x01G\xb8\xb8Hy\x11\xc6b\xd6\x16\xb3'\xaf/\xe2Lt\x164\x90\xb8ZC}\xd0\xe0\x1aD$\x84E\x07G\xda\xe3\x99\xa8HYA{\x81\xe1\xdf\x87e\xa5\xb0=S\x0f\x9c\x9c*JAnWS\xc4}\xd5\x05\x1c\x14)N8\xb4 \x0e\x91\x83 S\x01S\x1f\xe4:\x86\x13\xea@\xa1z\xa8(\xf7=\x07\xb0\x85{&=\xfd\xb8\xf8Q)l\x1f\x0f\x96\x1c\xbeV\xc0\x0e-\x1d6\xbd\xde\xa8\xe8y\xfd\x93-(& \x17\x05\xe9.\xa12\xb0\xcf9i\x94J?9\xf41\xe3\xb9\xd6\x85e\xad\xa1\x8a\x8fR\xd8*\xdb7`\\\x18\xa3\xff\x8dK\x8c\xb9\xfa\x9f\xb0\x99\xe3\xf9o\xcd\x86\x00\xca\xa0\x9d\xd0P\x82\xa1\xa1\xe0\xb2?;\xc9YSb8\x82%\x02\xb8\xff\xd7\x92i\xa7r\xa8\xc8\x1c\x1fFP\xbd\xb8\xd8\x19\xd3v\xa7\xc2\x8b<{KG\x94\xc4\xbc,\xbd\xcai{O/\xb7\xbc\x03\xb4\xc3!\xec\xbd9\xcf\xf3\xa6\x9d\xa9\xdf\xdf\xc1\xb7=\xfd\xf5\xf9\x9c\x86\x8f\xca\xb0\x1c\x9d\xfd\x9b|W\x0bS\xef\xdf#\xe5\xdf\x18\xa1\xf0 \xad\x8f\xbf\xb1]\xbf\x90/\x1d\x17\xb0\x04\xdc\x08\xc5\x12\x9d$\xf7\x83\x88\xac\x1e\x191\xc7\xc3~\xfc\x9dt\xe2\xe9\x1c\x9fM\xf8\xdb';\xcaOn\xba\x17\x99\x0fe\xfbi8?\x19\x85\x1e\xfc\x05l\xb2]\xe8\x16\xff\xf88\xb6\xbd\xc8s\xf1Y\xeb\xf8p{\x81\x87\xf5&{\xdc\x85\xfb'\x00\x00\xff\xffPK\x07\x08\x08\xcb\x89\x8b7\x03\x00\x00\x88 \x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00.\xaf\x90P\xee;\x12\x1e\x1b\x04\x00\x00?\x0f\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\xc8\xd4\x98^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x005\xaf\x90P\x08\xcb\x89\x8b7\x03\x00\x00\x88 \x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\\\x04\x00\x00authz_test.regoUT\x05\x00\x01\xd7\xd4\x98^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xd9\x07\x00\x00\x00\x00" + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x86\x9c\x94P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\xac\xf9\x9d^\xc4X\xdbn\xdc6\x10}\x16\xbfb\xc2\xc0\x80\xd4\xa8r\x12\xa0\x05*Tp_\xfa\x05}\x14\x14\x85\x96fwiK\xa4@R\xf6n\x16\xfb\xef\x05Ii/Zy\xe38\xae\xfbbY\xc3\x99\xc33gF\xbcl\xc7\xaa{\xb6D\xe8d\x8b\x8a\xf7m\xc2z\xb3\xfaF\x08o;\xa9\x0c\xd4\xcc\xb0D\xc9\xde`\xd9\xc9\x86W\x1c\xf5\xc9\x90^1\x85uy\x8f\x1bBj\\\xb0\xbe1\xc0\x9aF>B\x06\x0b\xd6h$\xe4\xfd`\xb8\xdd\x00\xb6\x8c7\xc4\xbfnI\xa0e\x8b\xe0\xc0I\xe0\x8cX\x97\xee5\xe4\xa2\xebM\xd2\xab&\x86\xd3\xc9s\xf7ZD$0\xf2\x1eE\xd2\xb1M#Y\x9d8d\xc8\xe6\xbd\x93\x11\xbc\xd7\xa8t^\x16c\xf4\x03kxM\x82J\xf6\xc2\x845\x8aM\x94e\x1fI`\x14\xab0\xd4\x9d\xe2\xc2,BzJ\x1fB\x07\x9a]=\xf8\xf7\xec\xea!\xa21\xf8\xa9b\x98\xa1UD\x11\xd9\x1dtX*\xd9w\xaf$\x82\x0b\xf6\x80\x13A\x9cQ\xe7\xeeQ@\xf6=e\x06\xf7\x17K\xe3\xe2\x8f\xa4q\xef\x13i<\x97S1n7\xc0\xdb\x0e\x95\x96\x82\x19\xfc\x0f\x1b\xe4h\x96\xf2M\x9a\xe5,\xad\x1fj\x9c3\xba\x97u{\x9b\x9e:&\xf5\xc6\xfdu\x96\xec\xcbz\xad\x96-\xe3\xe25\x85\x1a\x10\x03W\xa4\x92\x8b\xd2\x1b\xc2\x99u\xe0 \xa4\xbdF>R\xe7\xfeyh\xe1\x1f\x94\xca\x87\xcft\xdb0\xf2\xfd\x05+\x86\x91\xc2\xa5\x9e\xfb\xbf\xb4<\xfb4\xdeH\xd7\xf3\xdc_\xa8\xf1L\x02'z\xcf\x88W:\xf1\\\x82\x9bhK\x82\xbd\xb1\x94\xb7w\x90f\xd01\xa5\xd1\x1a\x0e\xfe\xd1\xa4\x0c\xa5\x96\xbd\xaa\x8e\x00m\xec\x1et\xea\xdc)\\\xf0\xf5s\x9d\x99Y=\xd3U\xe1\x12\x9f\x84\x9d&\x7f\x99\xb2m:y{\x87\x95I\x96hBo\x8d\x81\xfa \x1a\x03\xa5\x91]\x99(%\xbbW\xc7}\xe7p\x03o\x9b\xaf\x84\x0fL\xbcK4)Z\xb2\x92\xdaXv\xa7\x08\xce|\xae\xc3\xc5j<\xc5\xd7\x07]\xd4\xe1\xe7qG\x1d\x0cSF?\xf2i\x1f$\xb65F\xc4\xc4G\xce\xd4\xf9B\x03=\xc9\x82\x99\xd5\xe5\xdc~\ns\xc8k$\xce\xcc\xcaNs\x9e\xdby.\x97:\xfc\xa9\x89]\xcc\xc5l~\x16u\xc8Ga\xd92S\xad\xc6\xe6t.\xf1L^\xaeH\x87^\xd6FE\x90\xc1\x16\xa8\xaeV\xd8\"M\xc1\xff\x13\x03\xb5-KS\xb0\x8fQ\xc3\x14\x9cb;\xcb,/\xe3\xbd\xaf\xf7Q\xec\xd1\x0e\x17\xf6\x08f\xe7O\x16\\\xd4%k\x9aR\x1b\xc5\xc5\xb2\xd4\xfd\xadcY\x8a\x90\x04\xc1\xd7\xf0&\x0dW\xc6t\xb9.n\xa2\xf4\xfa:\xba \xf3/\xd7\xc5\x87(\xcc\xbf\xdc\xbc/~\x89\xbe\xc6$\x08\xb4Q1|\x8a\xf2\x8f\x05 |\xbd@H\xd5\xb2\x86\x7f\xf3\x9f\x97k\x88an\x97\xde\xcc\xf0\x90'\xbd\xa6nK3j_\x8e\xa7\x9d\xad\xd7\xe0\xfcnp&\xd3-\xecd\x9dw\x05[\xdb\xc5Bw\x0d7\xe3 \xfd\x8bF\xe3v\xb4v}\xf0\x99\x04\xeb\xfc\x93;^\x0d{\xe3\xeep\xcd\xc2u\xc7\x15\xd6\x87\x8b\xd6h\xd8\x92@\xc8\xc7Rc%E\xad\xd3\xcc\xf0\x16\x13k\x11:\x8c\xae?\xe1\x1f$\xc8W\xc8jT1\x0c{R\x0cea\xf9p\x99\xdc=\x9a\xa4\xc6J\xd6\xfb}[\xa3\x8a\xac\xa4\xc3 a\xdd\xc1\x9fp4\x81\xe7$69u\xdb\x1cp\xbd\xa7\x16\xe2\xba\x8bh\xb1%\xc1`\xd9\xfb\xee\xb7W\x1f\xb3b\x1anY\x0d\xac\xaf9\x8a\n!d}\x1d\xa5p\xa5AH\x03\\\xc0\xd5\x87\x07\x1a\xe7\x9e\x91\xeb\xa2\x91\x0f\xeb\xeb\"\xb2S\xbc '\x8b\x8d\x0d\xb6(\x8c\xadU\xc3\xb5 \x8fp\xe3\xc3t'\x07!\x1bm\xd3du{|\x00\x9a\"\xb9\x0b\xb2\xf3\xd1\xb3\xc7\xac\xef\x1dD*)\x8c=\xb8\x1c\x9d\x9fh2\xde\xd3\xaf\x1d0u\xbc\xc8{\xb0Q \xa4\xf8\xd5\x99\x1dC\x0d\x0b%[`U\x85\x9a\x8b\xa5g\xeb\x8fJz(\xd8\x98\x88\xd5\xc1\xe3\x15\xdbyU\x9e\x91\xcb\xb3\xe9\xfa\x92g\xb0\xa5\x03\x84[.\x86\x9aQ'\x06M\xc1=\xfd\x02\xe2\xfe\x8daR\xdf\xf3\xe2\x96\x0f\xa8\xf8bc\xd7\x8cC\x99c\x0b\x11\x04Tc\xa5\xd0\xaeS\x87\x9f,b7\xc0z;\xddQg\x91 \xd8\x91\xc0Q\xb5\x00iv\x9a\xaf\xb5\xf9\xef{:\xe2o\xaf\xfe\xaa3\x1d\xf3V\xa2\xf9R`]\xde=\x9a4\x1b\xb8\xa3p\xdc\xedH\xb8\xa5\xacY\xd2\x14\xe8\xdf\xff|\xfe\xedw\xba\x9bh\x1d\x0f?\xba\xf0\xa5\xb0\xcb\xe4=n\"B\xc8\xb4V\xf6O\xec*h\x17\x1a\x00\xfb\x9e\x97v\xb5\xb56\xb2#\xff\x06\x00\x00\xff\xffPK\x07\x08\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8c\x98\x94P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x018\xf2\x9d^\xd4U[O\xe3:\x17}N~E\x94'\xf8T\xd2~\xa1\x97\x19$t\x86Kaz\x1b\n)\xb4\x05\xa1\xc8ML\xe26\x89]\xdb\xa1\x97Q\xff\xfb\x91\x9d^2L\x18\x02::\xe8\xe7\xe4\xa8X\xfc\x8d\xa1\x8f\x19\xcf\xa4.(\xebG\x9a\xf8Q\x95\x95\xba\xda\x18\x93\xe4}\x8a%J\x84\xb9\x96\xc3\x15UQD\xd3\xb43k\xf9\xe2\x07:>6\x02\xec\x80@h7\xb6\xef\x0b\xc2R\xf8\xce4\x17\x87\x00El\xcd;\x04)\xcb\x94U\xe1\xf5&O\xe0 W\x1f\x02\xb8/\xca\x8a\xc9\xa4\xd8g\xb5G\xe4E\xe7\xdd\xb6F\x18G\xf0\xdb\xb66\xdd\xfe_\\\xda7\x15m$l\xb7\xf9\xcd\x8a?\xef\xb8||\\\x18\xa1O{{rn\xfa\xfb\xdf\x9f\x11\x1e\xfd\xa7\xdf\x1f\x02(\x83vL\x03i\x0c\x0d\x84/\xdb\xbb\xbd\x8c6E\x86CX\x14\xcb\xfe\xd7\x94\xe9\xfb\xb2\xc8`\x8e\x0fC\xa8\x1d\x1f'\xc4\xf4\xe4Vp\x91w\xbf\xba#B\xa2^\x86vp\xfa\x96\xd3f\xca\x89A\x89\x1d\x82\xde/\xf7Y\xdc\xf4\x82\xf6\xf3\x15\xfbV\xfb\xef\xaf\xcfH\xf8(\x0c\xfb\x08N\xf1\x9f\x02z\x1b\xa7\x98\x0f(\x07\xa3\x04i\xfb\xbd\xbd\x8a\x86\xa9\xf7g\xbb\xb2\xb7\x81P\xf8\x84\xe6\xf9\xb7!\xc9\x97\xefrN\x89\xc0\x0dQ$\xd7Rn\xe5\x0b\x10\x19\xcd)1\x83\xc3\xb6\xfc\x15u\xe2\xb3\xc8\xafm\xf3\x8f\x93SYFQ.\x11\x99#\xd9\xc0|h \xbf\x15g\x8f\x83B\x0f\xbe\xc3k\x99.p\x8d\xff\xe5\x9cH\x86\xb0-\xc8:\xb8\xc6\xca/n\x0b\xf00_,\x1f\x13q\x7f\x07\x00\x00\xff\xffPK\x07\x08\x1e\xcc\xe9\xae\xb4\x03\x00\x00}\x0d\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x86\x9c\x94P\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\xac\xf9\x9d^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8c\x98\x94P\x1e\xcc\xe9\xae\xb4\x03\x00\x00}\x0d\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc3\x04\x00\x00authz_test.regoUT\x05\x00\x018\xf2\x9d^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xbd\x08\x00\x00\x00\x00" fs.RegisterWithNamespace("rego", data) } diff --git a/proxy/forward_auth.go b/proxy/forward_auth.go index 6c362bb9f..133948154 100644 --- a/proxy/forward_auth.go +++ b/proxy/forward_auth.go @@ -115,6 +115,7 @@ func (p *Proxy) Verify(verifyOnly bool) http.Handler { if err != nil { return httputil.NewError(http.StatusBadRequest, err) } + originalRequest := p.getOriginalRequest(r, uri) if _, err := sessions.FromContext(r.Context()); err != nil { if verifyOnly { @@ -130,10 +131,7 @@ func (p *Proxy) Verify(verifyOnly bool) http.Handler { return nil } - r.Host = uri.Host - r.URL = uri - r.RequestURI = uri.String() - if err := p.authorize(w, r); err != nil { + if err := p.authorize(w, originalRequest); err != nil { return err } @@ -143,3 +141,10 @@ func (p *Proxy) Verify(verifyOnly bool) http.Handler { return nil }) } + +func (p *Proxy) getOriginalRequest(r *http.Request, originalURL *url.URL) *http.Request { + originalRequest := r.Clone(r.Context()) + originalRequest.Host = originalURL.Host + originalRequest.URL = originalURL + return originalRequest +} diff --git a/scripts/build-dev-docker.bash b/scripts/build-dev-docker.bash new file mode 100755 index 000000000..39f146f33 --- /dev/null +++ b/scripts/build-dev-docker.bash @@ -0,0 +1,42 @@ +#!/bin/bash +set -euxo pipefail + +_dir=/tmp/pomerium-dev-docker +mkdir -p "$_dir" + +# build linux binary +env GOOS=linux \ + GOARCH=amd64 \ + CGO_ENABLED=0 \ + GO111MODULE=on \ + go build \ + -ldflags "-s -w" \ + -o "$_dir/pomerium" \ + ./cmd/pomerium + +# build docker image +( + + +cd $_dir +cat <config.yaml + +EOF +cat <Dockerfile +FROM gcr.io/distroless/base:debug +WORKDIR /pomerium +COPY pomerium /bin/pomerium +COPY config.yaml /pomerium/config.yaml +ENTRYPOINT [ "/bin/pomerium" ] +CMD ["-config","/pomerium/config.yaml"] +EOF +docker build --tag=pomerium/pomerium:dev . + +# build for minikube +if command -v minikube >/dev/null 2>&1 ; then + eval "$(minikube docker-env --shell=bash)" + docker build --tag=pomerium/pomerium:dev . +fi + + +) From bc8048ff6bb7641f24763ecead0bfa70df556186 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Mon, 20 Apr 2020 18:25:49 -0600 Subject: [PATCH 24/25] authorize: regenerate statik --- authorize/evaluator/opa/policy/statik.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/authorize/evaluator/opa/policy/statik.go b/authorize/evaluator/opa/policy/statik.go index 3ac101116..ad90c3361 100644 --- a/authorize/evaluator/opa/policy/statik.go +++ b/authorize/evaluator/opa/policy/statik.go @@ -6,9 +6,11 @@ import ( "github.com/rakyll/statik/fs" ) + const Rego = "rego" // static asset namespace func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x86\x9c\x94P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01\xac\xf9\x9d^\xc4X\xdbn\xdc6\x10}\x16\xbfb\xc2\xc0\x80\xd4\xa8r\x12\xa0\x05*Tp_\xfa\x05}\x14\x14\x85\x96fwiK\xa4@R\xf6n\x16\xfb\xef\x05Ii/Zy\xe38\xae\xfbbY\xc3\x99\xc33gF\xbcl\xc7\xaa{\xb6D\xe8d\x8b\x8a\xf7m\xc2z\xb3\xfaF\x08o;\xa9\x0c\xd4\xcc\xb0D\xc9\xde`\xd9\xc9\x86W\x1c\xf5\xc9\x90^1\x85uy\x8f\x1bBj\\\xb0\xbe1\xc0\x9aF>B\x06\x0b\xd6h$\xe4\xfd`\xb8\xdd\x00\xb6\x8c7\xc4\xbfnI\xa0e\x8b\xe0\xc0I\xe0\x8cX\x97\xee5\xe4\xa2\xebM\xd2\xab&\x86\xd3\xc9s\xf7ZD$0\xf2\x1eE\xd2\xb1M#Y\x9d8d\xc8\xe6\xbd\x93\x11\xbc\xd7\xa8t^\x16c\xf4\x03kxM\x82J\xf6\xc2\x845\x8aM\x94e\x1fI`\x14\xab0\xd4\x9d\xe2\xc2,BzJ\x1fB\x07\x9a]=\xf8\xf7\xec\xea!\xa21\xf8\xa9b\x98\xa1UD\x11\xd9\x1dtX*\xd9w\xaf$\x82\x0b\xf6\x80\x13A\x9cQ\xe7\xeeQ@\xf6=e\x06\xf7\x17K\xe3\xe2\x8f\xa4q\xef\x13i<\x97S1n7\xc0\xdb\x0e\x95\x96\x82\x19\xfc\x0f\x1b\xe4h\x96\xf2M\x9a\xe5,\xad\x1fj\x9c3\xba\x97u{\x9b\x9e:&\xf5\xc6\xfdu\x96\xec\xcbz\xad\x96-\xe3\xe25\x85\x1a\x10\x03W\xa4\x92\x8b\xd2\x1b\xc2\x99u\xe0 \xa4\xbdF>R\xe7\xfeyh\xe1\x1f\x94\xca\x87\xcft\xdb0\xf2\xfd\x05+\x86\x91\xc2\xa5\x9e\xfb\xbf\xb4<\xfb4\xdeH\xd7\xf3\xdc_\xa8\xf1L\x02'z\xcf\x88W:\xf1\\\x82\x9bhK\x82\xbd\xb1\x94\xb7w\x90f\xd01\xa5\xd1\x1a\x0e\xfe\xd1\xa4\x0c\xa5\x96\xbd\xaa\x8e\x00m\xec\x1et\xea\xdc)\\\xf0\xf5s\x9d\x99Y=\xd3U\xe1\x12\x9f\x84\x9d&\x7f\x99\xb2m:y{\x87\x95I\x96hBo\x8d\x81\xfa \x1a\x03\xa5\x91]\x99(%\xbbW\xc7}\xe7p\x03o\x9b\xaf\x84\x0fL\xbcK4)Z\xb2\x92\xdaXv\xa7\x08\xce|\xae\xc3\xc5j<\xc5\xd7\x07]\xd4\xe1\xe7qG\x1d\x0cSF?\xf2i\x1f$\xb65F\xc4\xc4G\xce\xd4\xf9B\x03=\xc9\x82\x99\xd5\xe5\xdc~\ns\xc8k$\xce\xcc\xcaNs\x9e\xdby.\x97:\xfc\xa9\x89]\xcc\xc5l~\x16u\xc8Ga\xd92S\xad\xc6\xe6t.\xf1L^\xaeH\x87^\xd6FE\x90\xc1\x16\xa8\xaeV\xd8\"M\xc1\xff\x13\x03\xb5-KS\xb0\x8fQ\xc3\x14\x9cb;\xcb,/\xe3\xbd\xaf\xf7Q\xec\xd1\x0e\x17\xf6\x08f\xe7O\x16\\\xd4%k\x9aR\x1b\xc5\xc5\xb2\xd4\xfd\xadcY\x8a\x90\x04\xc1\xd7\xf0&\x0dW\xc6t\xb9.n\xa2\xf4\xfa:\xba \xf3/\xd7\xc5\x87(\xcc\xbf\xdc\xbc/~\x89\xbe\xc6$\x08\xb4Q1|\x8a\xf2\x8f\x05 |\xbd@H\xd5\xb2\x86\x7f\xf3\x9f\x97k\x88an\x97\xde\xcc\xf0\x90'\xbd\xa6nK3j_\x8e\xa7\x9d\xad\xd7\xe0\xfcnp&\xd3-\xecd\x9dw\x05[\xdb\xc5Bw\x0d7\xe3 \xfd\x8bF\xe3v\xb4v}\xf0\x99\x04\xeb\xfc\x93;^\x0d{\xe3\xeep\xcd\xc2u\xc7\x15\xd6\x87\x8b\xd6h\xd8\x92@\xc8\xc7Rc%E\xad\xd3\xcc\xf0\x16\x13k\x11:\x8c\xae?\xe1\x1f$\xc8W\xc8jT1\x0c{R\x0cea\xf9p\x99\xdc=\x9a\xa4\xc6J\xd6\xfb}[\xa3\x8a\xac\xa4\xc3 a\xdd\xc1\x9fp4\x81\xe7$69u\xdb\x1cp\xbd\xa7\x16\xe2\xba\x8bh\xb1%\xc1`\xd9\xfb\xee\xb7W\x1f\xb3b\x1anY\x0d\xac\xaf9\x8a\n!d}\x1d\xa5p\xa5AH\x03\\\xc0\xd5\x87\x07\x1a\xe7\x9e\x91\xeb\xa2\x91\x0f\xeb\xeb\"\xb2S\xbc '\x8b\x8d\x0d\xb6(\x8c\xadU\xc3\xb5 \x8fp\xe3\xc3t'\x07!\x1bm\xd3du{|\x00\x9a\"\xb9\x0b\xb2\xf3\xd1\xb3\xc7\xac\xef\x1dD*)\x8c=\xb8\x1c\x9d\x9fh2\xde\xd3\xaf\x1d0u\xbc\xc8{\xb0Q \xa4\xf8\xd5\x99\x1dC\x0d\x0b%[`U\x85\x9a\x8b\xa5g\xeb\x8fJz(\xd8\x98\x88\xd5\xc1\xe3\x15\xdbyU\x9e\x91\xcb\xb3\xe9\xfa\x92g\xb0\xa5\x03\x84[.\x86\x9aQ'\x06M\xc1=\xfd\x02\xe2\xfe\x8daR\xdf\xf3\xe2\x96\x0f\xa8\xf8bc\xd7\x8cC\x99c\x0b\x11\x04Tc\xa5\xd0\xaeS\x87\x9f,b7\xc0z;\xddQg\x91 \xd8\x91\xc0Q\xb5\x00iv\x9a\xaf\xb5\xf9\xef{:\xe2o\xaf\xfe\xaa3\x1d\xf3V\xa2\xf9R`]\xde=\x9a4\x1b\xb8\xa3p\xdc\xedH\xb8\xa5\xacY\xd2\x14\xe8\xdf\xff|\xfe\xedw\xba\x9bh\x1d\x0f?\xba\xf0\xa5\xb0\xcb\xe4=n\"B\xc8\xb4V\xf6O\xec*h\x17\x1a\x00\xfb\x9e\x97v\xb5\xb56\xb2#\xff\x06\x00\x00\xff\xffPK\x07\x08\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8c\x98\x94P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x018\xf2\x9d^\xd4U[O\xe3:\x17}N~E\x94'\xf8T\xd2~\xa1\x97\x19$t\x86Kaz\x1b\n)\xb4\x05\xa1\xc8ML\xe26\x89]\xdb\xa1\x97Q\xff\xfb\x91\x9d^2L\x18\x02::\xe8\xe7\xe4\xa8X\xfc\x8d\xa1\x8f\x19\xcf\xa4.(\xebG\x9a\xf8Q\x95\x95\xba\xda\x18\x93\xe4}\x8a%J\x84\xb9\x96\xc3\x15UQD\xd3\xb43k\xf9\xe2\x07:>6\x02\xec\x80@h7\xb6\xef\x0b\xc2R\xf8\xce4\x17\x87\x00El\xcd;\x04)\xcb\x94U\xe1\xf5&O\xe0 W\x1f\x02\xb8/\xca\x8a\xc9\xa4\xd8g\xb5G\xe4E\xe7\xdd\xb6F\x18G\xf0\xdb\xb66\xdd\xfe_\\\xda7\x15m$l\xb7\xf9\xcd\x8a?\xef\xb8||\\\x18\xa1O{{rn\xfa\xfb\xdf\x9f\x11\x1e\xfd\xa7\xdf\x1f\x02(\x83vL\x03i\x0c\x0d\x84/\xdb\xbb\xbd\x8c6E\x86CX\x14\xcb\xfe\xd7\x94\xe9\xfb\xb2\xc8`\x8e\x0fC\xa8\x1d\x1f'\xc4\xf4\xe4Vp\x91w\xbf\xba#B\xa2^\x86vp\xfa\x96\xd3f\xca\x89A\x89\x1d\x82\xde/\xf7Y\xdc\xf4\x82\xf6\xf3\x15\xfbV\xfb\xef\xaf\xcfH\xf8(\x0c\xfb\x08N\xf1\x9f\x02z\x1b\xa7\x98\x0f(\x07\xa3\x04i\xfb\xbd\xbd\x8a\x86\xa9\xf7g\xbb\xb2\xb7\x81P\xf8\x84\xe6\xf9\xb7!\xc9\x97\xefrN\x89\xc0\x0dQ$\xd7Rn\xe5\x0b\x10\x19\xcd)1\x83\xc3\xb6\xfc\x15u\xe2\xb3\xc8\xafm\xf3\x8f\x93SYFQ.\x11\x99#\xd9\xc0|h \xbf\x15g\x8f\x83B\x0f\xbe\xc3k\x99.p\x8d\xff\xe5\x9cH\x86\xb0-\xc8:\xb8\xc6\xca/n\x0b\xf00_,\x1f\x13q\x7f\x07\x00\x00\xff\xffPK\x07\x08\x1e\xcc\xe9\xae\xb4\x03\x00\x00}\x0d\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x86\x9c\x94P\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01\xac\xf9\x9d^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8c\x98\x94P\x1e\xcc\xe9\xae\xb4\x03\x00\x00}\x0d\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc3\x04\x00\x00authz_test.regoUT\x05\x00\x018\xf2\x9d^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\xbd\x08\x00\x00\x00\x00" - fs.RegisterWithNamespace("rego", data) -} + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x12\x03\x95P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00authz.regoUT\x05\x00\x01D=\x9e^\xc4X\xdbn\xdc6\x10}\x16\xbfb\xc2\xc0\x80\xd4\xa8r\x12\xa0\x05*Tp_\xfa\x05}\x14\x14\x85\x96fwiK\xa4@R\xf6n\x16\xfb\xef\x05Ii/Zy\xe38\xae\xfbbY\xc3\x99\xc33gF\xbcl\xc7\xaa{\xb6D\xe8d\x8b\x8a\xf7m\xc2z\xb3\xfaF\x08o;\xa9\x0c\xd4\xcc\xb0D\xc9\xde`\xd9\xc9\x86W\x1c\xf5\xc9\x90^1\x85uy\x8f\x1bBj\\\xb0\xbe1\xc0\x9aF>B\x06\x0b\xd6h$\xe4\xfd`\xb8\xdd\x00\xb6\x8c7\xc4\xbfnI\xa0e\x8b\xe0\xc0I\xe0\x8cX\x97\xee5\xe4\xa2\xebM\xd2\xab&\x86\xd3\xc9s\xf7ZD$0\xf2\x1eE\xd2\xb1M#Y\x9d8d\xc8\xe6\xbd\x93\x11\xbc\xd7\xa8t^\x16c\xf4\x03kxM\x82J\xf6\xc2\x845\x8aM\x94e\x1fI`\x14\xab0\xd4\x9d\xe2\xc2,BzJ\x1fB\x07\x9a]=\xf8\xf7\xec\xea!\xa21\xf8\xa9b\x98\xa1UD\x11\xd9\x1dtX*\xd9w\xaf$\x82\x0b\xf6\x80\x13A\x9cQ\xe7\xeeQ@\xf6=e\x06\xf7\x17K\xe3\xe2\x8f\xa4q\xef\x13i<\x97S1n7\xc0\xdb\x0e\x95\x96\x82\x19\xfc\x0f\x1b\xe4h\x96\xf2M\x9a\xe5,\xad\x1fj\x9c3\xba\x97u{\x9b\x9e:&\xf5\xc6\xfdu\x96\xec\xcbz\xad\x96-\xe3\xe25\x85\x1a\x10\x03W\xa4\x92\x8b\xd2\x1b\xc2\x99u\xe0 \xa4\xbdF>R\xe7\xfeyh\xe1\x1f\x94\xca\x87\xcft\xdb0\xf2\xfd\x05+\x86\x91\xc2\xa5\x9e\xfb\xbf\xb4<\xfb4\xdeH\xd7\xf3\xdc_\xa8\xf1L\x02'z\xcf\x88W:\xf1\\\x82\x9bhK\x82\xbd\xb1\x94\xb7w\x90f\xd01\xa5\xd1\x1a\x0e\xfe\xd1\xa4\x0c\xa5\x96\xbd\xaa\x8e\x00m\xec\x1et\xea\xdc)\\\xf0\xf5s\x9d\x99Y=\xd3U\xe1\x12\x9f\x84\x9d&\x7f\x99\xb2m:y{\x87\x95I\x96hBo\x8d\x81\xfa \x1a\x03\xa5\x91]\x99(%\xbbW\xc7}\xe7p\x03o\x9b\xaf\x84\x0fL\xbcK4)Z\xb2\x92\xdaXv\xa7\x08\xce|\xae\xc3\xc5j<\xc5\xd7\x07]\xd4\xe1\xe7qG\x1d\x0cSF?\xf2i\x1f$\xb65F\xc4\xc4G\xce\xd4\xf9B\x03=\xc9\x82\x99\xd5\xe5\xdc~\ns\xc8k$\xce\xcc\xcaNs\x9e\xdby.\x97:\xfc\xa9\x89]\xcc\xc5l~\x16u\xc8Ga\xd92S\xad\xc6\xe6t.\xf1L^\xaeH\x87^\xd6FE\x90\xc1\x16\xa8\xaeV\xd8\"M\xc1\xff\x13\x03\xb5-KS\xb0\x8fQ\xc3\x14\x9cb;\xcb,/\xe3\xbd\xaf\xf7Q\xec\xd1\x0e\x17\xf6\x08f\xe7O\x16\\\xd4%k\x9aR\x1b\xc5\xc5\xb2\xd4\xfd\xadcY\x8a\x90\x04\xc1\xd7\xf0&\x0dW\xc6t\xb9.n\xa2\xf4\xfa:\xba \xf3/\xd7\xc5\x87(\xcc\xbf\xdc\xbc/~\x89\xbe\xc6$\x08\xb4Q1|\x8a\xf2\x8f\x05 |\xbd@H\xd5\xb2\x86\x7f\xf3\x9f\x97k\x88an\x97\xde\xcc\xf0\x90'\xbd\xa6nK3j_\x8e\xa7\x9d\xad\xd7\xe0\xfcnp&\xd3-\xecd\x9dw\x05[\xdb\xc5Bw\x0d7\xe3 \xfd\x8bF\xe3v\xb4v}\xf0\x99\x04\xeb\xfc\x93;^\x0d{\xe3\xeep\xcd\xc2u\xc7\x15\xd6\x87\x8b\xd6h\xd8\x92@\xc8\xc7Rc%E\xad\xd3\xcc\xf0\x16\x13k\x11:\x8c\xae?\xe1\x1f$\xc8W\xc8jT1\x0c{R\x0cea\xf9p\x99\xdc=\x9a\xa4\xc6J\xd6\xfb}[\xa3\x8a\xac\xa4\xc3 a\xdd\xc1\x9fp4\x81\xe7$69u\xdb\x1cp\xbd\xa7\x16\xe2\xba\x8bh\xb1%\xc1`\xd9\xfb\xee\xb7W\x1f\xb3b\x1anY\x0d\xac\xaf9\x8a\n!d}\x1d\xa5p\xa5AH\x03\\\xc0\xd5\x87\x07\x1a\xe7\x9e\x91\xeb\xa2\x91\x0f\xeb\xeb\"\xb2S\xbc '\x8b\x8d\x0d\xb6(\x8c\xadU\xc3\xb5 \x8fp\xe3\xc3t'\x07!\x1bm\xd3du{|\x00\x9a\"\xb9\x0b\xb2\xf3\xd1\xb3\xc7\xac\xef\x1dD*)\x8c=\xb8\x1c\x9d\x9fh2\xde\xd3\xaf\x1d0u\xbc\xc8{\xb0Q \xa4\xf8\xd5\x99\x1dC\x0d\x0b%[`U\x85\x9a\x8b\xa5g\xeb\x8fJz(\xd8\x98\x88\xd5\xc1\xe3\x15\xdbyU\x9e\x91\xcb\xb3\xe9\xfa\x92g\xb0\xa5\x03\x84[.\x86\x9aQ'\x06M\xc1=\xfd\x02\xe2\xfe\x8daR\xdf\xf3\xe2\x96\x0f\xa8\xf8bc\xd7\x8cC\x99c\x0b\x11\x04Tc\xa5\xd0\xaeS\x87\x9f,b7\xc0z;\xddQg\x91 \xd8\x91\xc0Q\xb5\x00iv\x9a\xaf\xb5\xf9\xef{:\xe2o\xaf\xfe\xaa3\x1d\xf3V\xa2\xf9R`]\xde=\x9a4\x1b\xb8\xa3p\xdc\xedH\xb8\xa5\xacY\xd2\x14\xe8\xdf\xff|\xfe\xedw\xba\x9bh\x1d\x0f?\xba\xf0\xa5\xb0\xcb\xe4=n\"B\xc8\xb4V\xf6O\xec*h\x17\x1a\x00\xfb\x9e\x97v\xb5\xb56\xb2#\xff\x06\x00\x00\xff\xffPK\x07\x08\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x12\x03\x95P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00authz_test.regoUT\x05\x00\x01D=\x9e^\xd4UkO\xe38\x14\xfd\x9c\xfc\x8a(\x9f`\xd5i\xbb\xa1\x8f\x19$\xb4\xc3#0}\x0d\x85\x14\xd2\x82P\xe4&&q\xf3pj;\xa4\xcd\xa8\xff}e\x97\xb6\x19\x08\xbb\x01\xad\x84\xf6Se\xdf{\xcf=\xf7\x9e\xe3&\x06\xb6\x0f\\\xa8\xc48\x84\x04%a\x15$\xcc\xcbdy\x962\xcb\x83\xc0\x81D9\x1f\xf4\x9bCd\xc0\xf6\xf8,\\\x9e\xde\xcdbW\x8f\x1f\xf5\xe6\xd5W-\xeb\xc0\xf1@\xa3}\x92\xb5~\x98\xda\xf1\xb7Nz\xe1\xb7C\xd3\xa8\xdb\xcd\xf6\xb5\xa5u/\x96\xe7\x97\x1a;=ndzg\xe2\x99O}\xbd\xa5]R\x8d\xdd\xb5&\x84\xa4\xce\xc9\xd7\xe8\xa09\x0b\x86\xb1{\xa3\xb7b\xac?un\xb4z0\xec\x03l\xe3l<\x19\xcc\x8f\xfd\xe4K\xaf\x1b\x05\xb8\x1b\x1cg=W\x1b\x03\xab\x8e\x0cd\xb8\xc6q\x12.\x1a\x8d\x93\x83\xa8}v5s\x0ffC\xef\xda\x15\x02x\x80@g\xb3\xff)\xa0\xb0\xd5HHPu\xa0\x8d\x1d\xb8\x97\xd3\xa7\xea\xef\xcb2\x83\x94Y0\x04(\xb0@\x10\xe0\x14:\\\xb3\x84\xae\x05G\xb8:KY\x15F\xbc\xd6\xe2\xb5{;GTx\xa6\xa4\x82\xc4Q\x0f\x95{\x15.@\x18\x07\xb0j\xe3P}\xa8\xf0\x88\x80\xe5j\xcf0\xfc\x9e\x0f\xcb\xd2\xaa\xa2\xe4\x98\xec\xcb\xb2$\xba+)b\x9e\xe2\x00\x06\xaa\x04'\x0cZ1\x0e\x90\x8d U\x00U\xeeE;\x8a\x13bC\x8e\x9aG\x14\xfd\x9e\x07\xb08{*8\xbdl\xfc K\xab\x87\\\x93\xbc[\x01\xcdS\xca'\xed6\xcasv'\x91\x82\xa28a< \xd8%D\x0c\xec1\x16\x1f\xd6j\xaf\x18z\x98\xb2B\xea\x9c\xb2z\xa8\xf0\x1fYZ\xc9\xab\x8d0\xeb\xbcO\x91D\x8a0SJ\xa8\"K\x12o\x9aW\xe6\x8d\xf1%5\x06\xcc\xe3 5\xf0|\xb1\x91\xcc\xc1!@\x11}\xcdZ\x96\xa4U\xe5C-\xa6/Z\xec\\\x11a\x1c\xc1\xef\xdb\xbf\xba|\x9f\xcf1\xc73\xd7\xf7\xdbC\xbc[\x07F\xe8\xd3\x9emI\x93\xbc\xff\xe9N\xf1\xf4\x7f\xfdtc@(\xb4\x12\x12\x08aH\xc0u\xd9\xde\xed\x15\x99\x80\xe2\x10\xd6\xb8}\xff\x9aSu_\x14U\xa9\xed\xc1\x10*GGkb\xea\xfa\x96s\x11w\xbf\xab\xc3C\xbc^\x84vp\xea\x96\xd3f\xcbk\x81\xd6rpz\xbf\xdd\x17qS+\xca\xaf7\xe4[\xed\xbf\xbf\xbe \xe1\xa30\xf4#8\xb5\xff\n\xe8\xdfqj\xe5\x80J0Z#m\xdf\xdb\x9bh\x98\xb8\xff,W\xb1\x1bb\x02\x1f\xd1\xa2\xbc\x1b\xd6\xf9\xe2\x9f\xb6\xe4\x88\xc0 Q$l)\\\xf9\x02DDK\x8eX\xc0a[\xfe\xc6t\xfcY\x94\x9fm\xf3\x0d)9YAQ\xa9!\nW\xb2\xfdD~d!\xaf\x8a\x8b\xd7A\xa0\x0b\xdf\xa1\xb5H\xe7\xb8\xd5?Jn\xa4`\xb0-\xc8s\xf0\x19\xab\xfcp[\x80\xfb\xc52{X\x0f\xf7w\x00\x00\x00\xff\xffPK\x07\x08\xf7ol\x88\x94\x03\x00\x00\xb8\x0c\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x12\x03\x95P\xab\xe0F\x9a\x82\x04\x00\x00\xf4\x11\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00authz.regoUT\x05\x00\x01D=\x9e^PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x12\x03\x95P\xf7ol\x88\x94\x03\x00\x00\xb8\x0c\x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xc3\x04\x00\x00authz_test.regoUT\x05\x00\x01D=\x9e^PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x87\x00\x00\x00\x9d\x08\x00\x00\x00\x00" + fs.RegisterWithNamespace("rego", data) + } + \ No newline at end of file From a05bbd9ba7fdedaa4d81f3f4c2e68faa3927c72c Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Tue, 21 Apr 2020 07:19:02 -0600 Subject: [PATCH 25/25] authorize: remove trace statements from rego file --- authorize/evaluator/opa/policy/authz.rego | 6 ------ 1 file changed, 6 deletions(-) diff --git a/authorize/evaluator/opa/policy/authz.rego b/authorize/evaluator/opa/policy/authz.rego index c5786f750..707bfe2ef 100644 --- a/authorize/evaluator/opa/policy/authz.rego +++ b/authorize/evaluator/opa/policy/authz.rego @@ -12,7 +12,6 @@ allow { token.payload.email = route_policies[route].allowed_users[_] token.valid count(deny)==0 - trace(sprintf("allow by email (route=%v email=%v)", [route, token.payload.email])) } # allow group @@ -23,7 +22,6 @@ allow { token.payload.groups[group] == route_policies[route].allowed_groups[_] token.valid count(deny)==0 - trace(sprintf("allow by group (route=%v group=%v)", [route, group])) } # allow by impersonate email @@ -33,7 +31,6 @@ allow { token.payload.impersonate_email = route_policies[route].allowed_users[_] token.valid count(deny)==0 - trace(sprintf("allow by impersonate email (route=%v email=%v)", [route, token.payload.impersonate_email])) } # allow by impersonate group @@ -44,7 +41,6 @@ allow { token.payload.impersonate_groups[group] == route_policies[route].allowed_groups[_] token.valid count(deny)==0 - trace(sprintf("allow by impersonate group (route=%v group=%v)", [route, group])) } # allow by domain @@ -55,7 +51,6 @@ allow { email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain]) token.valid count(deny)==0 - trace(sprintf("allow by domain (route=%v email=%v domain=%v)", [route, token.payload.email, domain])) } # allow by impersonate domain @@ -66,7 +61,6 @@ allow { email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain]) token.valid count(deny)==0 - trace(sprintf("allow by impersonate domain (route=%v email=%v domain=%v)", [route, token.payload.impersonate_email, domain])) } allowed_route(input_url, policy){