mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-10 15:47:36 +02:00
authorize: add support for .pomerium and unauthenticated routes (#639)
* authorize: add support for .pomerium and unauthenticated routes integration-tests: add test for forward auth dashboard urls * proxy: fix ctx error test to return a 200 when authorize allows it
This commit is contained in:
parent
e5c7c5b27e
commit
b1d3bbaf56
11 changed files with 158 additions and 69 deletions
|
@ -5,10 +5,15 @@ import data.shared_key
|
||||||
|
|
||||||
default allow = false
|
default allow = false
|
||||||
|
|
||||||
|
# allow public
|
||||||
|
allow {
|
||||||
|
route := first_allowed_route(input.url)
|
||||||
|
route_policies[route].AllowPublicUnauthenticatedAccess == true
|
||||||
|
}
|
||||||
|
|
||||||
# allow by email
|
# allow by email
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
token.payload.email = route_policies[route].allowed_users[_]
|
token.payload.email = route_policies[route].allowed_users[_]
|
||||||
token.valid
|
token.valid
|
||||||
count(deny)==0
|
count(deny)==0
|
||||||
|
@ -16,8 +21,7 @@ allow {
|
||||||
|
|
||||||
# allow group
|
# allow group
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
some group
|
some group
|
||||||
token.payload.groups[group] == route_policies[route].allowed_groups[_]
|
token.payload.groups[group] == route_policies[route].allowed_groups[_]
|
||||||
token.valid
|
token.valid
|
||||||
|
@ -26,8 +30,7 @@ allow {
|
||||||
|
|
||||||
# allow by impersonate email
|
# allow by impersonate email
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
token.payload.impersonate_email = route_policies[route].allowed_users[_]
|
token.payload.impersonate_email = route_policies[route].allowed_users[_]
|
||||||
token.valid
|
token.valid
|
||||||
count(deny)==0
|
count(deny)==0
|
||||||
|
@ -35,8 +38,7 @@ allow {
|
||||||
|
|
||||||
# allow by impersonate group
|
# allow by impersonate group
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
some group
|
some group
|
||||||
token.payload.impersonate_groups[group] == route_policies[route].allowed_groups[_]
|
token.payload.impersonate_groups[group] == route_policies[route].allowed_groups[_]
|
||||||
token.valid
|
token.valid
|
||||||
|
@ -45,8 +47,7 @@ allow {
|
||||||
|
|
||||||
# allow by domain
|
# allow by domain
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
some domain
|
some domain
|
||||||
email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain])
|
email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain])
|
||||||
token.valid
|
token.valid
|
||||||
|
@ -55,14 +56,24 @@ allow {
|
||||||
|
|
||||||
# allow by impersonate domain
|
# allow by impersonate domain
|
||||||
allow {
|
allow {
|
||||||
some route
|
route := first_allowed_route(input.url)
|
||||||
allowed_route(input.url, route_policies[route])
|
|
||||||
some domain
|
some domain
|
||||||
email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain])
|
email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain])
|
||||||
token.valid
|
token.valid
|
||||||
count(deny)==0
|
count(deny)==0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# allow pomerium urls
|
||||||
|
allow {
|
||||||
|
contains(input.url, "/.pomerium/")
|
||||||
|
not contains(input.url,"/.pomerium/admin")
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns the first matching route
|
||||||
|
first_allowed_route(input_url) = route {
|
||||||
|
route := [route | some route ; allowed_route(input.url, route_policies[route])][0]
|
||||||
|
}
|
||||||
|
|
||||||
allowed_route(input_url, policy){
|
allowed_route(input_url, policy){
|
||||||
input_url_obj := parse_url(input_url)
|
input_url_obj := parse_url(input_url)
|
||||||
allowed_route_source(input_url_obj, policy)
|
allowed_route_source(input_url_obj, policy)
|
||||||
|
|
|
@ -65,6 +65,51 @@ test_email_denied {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_public_allowed {
|
||||||
|
allow with data.route_policies as [{
|
||||||
|
"source": "example.com",
|
||||||
|
"AllowPublicUnauthenticatedAccess": true
|
||||||
|
}] with input as {
|
||||||
|
"url": "http://example.com",
|
||||||
|
"host": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_public_denied {
|
||||||
|
not allow with data.route_policies as [
|
||||||
|
{
|
||||||
|
"source": "example.com",
|
||||||
|
"prefix": "/by-user",
|
||||||
|
"allowed_users": ["bob@example.com"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "example.com",
|
||||||
|
"AllowPublicUnauthenticatedAccess": true
|
||||||
|
}
|
||||||
|
] with input as {
|
||||||
|
"url": "http://example.com/by-user",
|
||||||
|
"host": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_pomerium_allowed {
|
||||||
|
allow with data.route_policies as [{
|
||||||
|
"source": "example.com",
|
||||||
|
"allowed_users": ["bob@example.com"]
|
||||||
|
}] with input as {
|
||||||
|
"url": "http://example.com/.pomerium/",
|
||||||
|
"host": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_pomerium_denied {
|
||||||
|
not allow with data.route_policies as [{
|
||||||
|
"source": "example.com",
|
||||||
|
"allowed_users": ["bob@example.com"]
|
||||||
|
}] with input as {
|
||||||
|
"url": "http://example.com/.pomerium/admin",
|
||||||
|
"host": "example.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test_parse_url {
|
test_parse_url {
|
||||||
url := parse_url("http://example.com/some/path?qs")
|
url := parse_url("http://example.com/some/path?qs")
|
||||||
url.scheme == "http"
|
url.scheme == "http"
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||||
"github.com/pomerium/pomerium/internal/grpc/authorize"
|
"github.com/pomerium/pomerium/internal/grpc/authorize"
|
||||||
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry/trace"
|
"github.com/pomerium/pomerium/internal/telemetry/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +26,19 @@ func (a *Authorize) IsAuthorized(ctx context.Context, in *authorize.IsAuthorized
|
||||||
RemoteAddr: in.GetRequestRemoteAddr(),
|
RemoteAddr: in.GetRequestRemoteAddr(),
|
||||||
URL: getFullURL(in.GetRequestUrl(), in.GetRequestHost()),
|
URL: getFullURL(in.GetRequestUrl(), in.GetRequestHost()),
|
||||||
}
|
}
|
||||||
return a.pe.IsAuthorized(ctx, req)
|
reply, err := a.pe.IsAuthorized(ctx, req)
|
||||||
|
log.Info().
|
||||||
|
// request
|
||||||
|
Str("method", req.Method).
|
||||||
|
Str("url", req.URL).
|
||||||
|
// reply
|
||||||
|
Bool("allow", reply.Allow).
|
||||||
|
Strs("deny-reasons", reply.DenyReasons).
|
||||||
|
Str("user", reply.User).
|
||||||
|
Str("email", reply.Email).
|
||||||
|
Strs("groups", reply.Groups).
|
||||||
|
Msg("authorize.grpc.IsAuthorized")
|
||||||
|
return reply, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type protoHeader map[string]*authorize.IsAuthorizedRequest_Headers
|
type protoHeader map[string]*authorize.IsAuthorizedRequest_Headers
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -108,12 +108,11 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||||
|
@ -513,8 +512,6 @@ google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn
|
||||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
google.golang.org/api v0.14.0 h1:uMf5uLi4eQMRrMKhCplNik4U4H8Z6C1br3zOtAa/aDE=
|
google.golang.org/api v0.14.0 h1:uMf5uLi4eQMRrMKhCplNik4U4H8Z6C1br3zOtAa/aDE=
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40=
|
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
|
||||||
google.golang.org/api v0.22.0 h1:J1Pl9P2lnmYFSJvgs70DKELqHNh8CNWXPbud4njEE2s=
|
google.golang.org/api v0.22.0 h1:J1Pl9P2lnmYFSJvgs70DKELqHNh8CNWXPbud4njEE2s=
|
||||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
@ -549,6 +546,7 @@ google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLY
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
|
|
@ -16,8 +16,6 @@ func TestAuthorization(t *testing.T) {
|
||||||
defer clearTimeout()
|
defer clearTimeout()
|
||||||
|
|
||||||
t.Run("public", func(t *testing.T) {
|
t.Run("public", func(t *testing.T) {
|
||||||
t.Skip() // pomerium doesn't currently handle unauthenticated public routes
|
|
||||||
|
|
||||||
client := testcluster.NewHTTPClient()
|
client := testcluster.NewHTTPClient()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://httpdetails.localhost.pomerium.io", nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", "https://httpdetails.localhost.pomerium.io", nil)
|
||||||
|
@ -33,7 +31,6 @@ func TestAuthorization(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, res.StatusCode, "unexpected status code, headers=%v", res.Header)
|
assert.Equal(t, http.StatusOK, res.StatusCode, "unexpected status code, headers=%v", res.Header)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("domains", func(t *testing.T) {
|
t.Run("domains", func(t *testing.T) {
|
||||||
t.Run("allowed", func(t *testing.T) {
|
t.Run("allowed", func(t *testing.T) {
|
||||||
client := testcluster.NewHTTPClient()
|
client := testcluster.NewHTTPClient()
|
||||||
|
@ -78,7 +75,7 @@ func TestAuthorization(t *testing.T) {
|
||||||
client := testcluster.NewHTTPClient()
|
client := testcluster.NewHTTPClient()
|
||||||
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"), "joe@cats.test", []string{"user"})
|
res, err := flows.Authenticate(ctx, client, mustParseURL("https://httpdetails.localhost.pomerium.io/by-group"), "joe@cats.test", []string{"user"})
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
assertDeniedAccess(t, res, "expected Forbidden for user")
|
assertDeniedAccess(t, res, "expected Forbidden for user, but got %d", res.StatusCode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,6 +28,23 @@ func TestDashboard(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, res.StatusCode, "unexpected status code")
|
||||||
|
assert.Equal(t, "image/svg+xml", res.Header.Get("Content-Type"))
|
||||||
|
})
|
||||||
|
t.Run("forward auth image asset", func(t *testing.T) {
|
||||||
|
client := testcluster.NewHTTPClient()
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", "https://fa-httpdetails.localhost.pomerium.io/.pomerium/assets/img/pomerium.svg", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := client.Do(req)
|
||||||
|
if !assert.NoError(t, err, "unexpected http error") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, res.StatusCode, "unexpected status code")
|
assert.Equal(t, http.StatusOK, res.StatusCode, "unexpected status code")
|
||||||
assert.Equal(t, "image/svg+xml", res.Header.Get("Content-Type"))
|
assert.Equal(t, "image/svg+xml", res.Header.Get("Content-Type"))
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,30 +1,33 @@
|
||||||
local tls = import './tls.libsonnet';
|
local tls = import './tls.libsonnet';
|
||||||
|
|
||||||
local PomeriumPolicy = function() [
|
local PomeriumPolicy = function() std.flattenArrays([
|
||||||
|
[
|
||||||
{
|
{
|
||||||
from: 'http://httpdetails.localhost.pomerium.io',
|
from: 'http://' + domain + '.localhost.pomerium.io',
|
||||||
prefix: '/by-domain',
|
prefix: '/by-domain',
|
||||||
to: 'http://httpdetails.default.svc.cluster.local',
|
to: 'http://' + domain + '.default.svc.cluster.local',
|
||||||
allowed_domains: ['dogs.test'],
|
allowed_domains: ['dogs.test'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: 'http://httpdetails.localhost.pomerium.io',
|
from: 'http://' + domain + '.localhost.pomerium.io',
|
||||||
prefix: '/by-user',
|
prefix: '/by-user',
|
||||||
to: 'http://httpdetails.default.svc.cluster.local',
|
to: 'http://' + domain + '.default.svc.cluster.local',
|
||||||
allowed_users: ['bob@dogs.test'],
|
allowed_users: ['bob@dogs.test'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: 'http://httpdetails.localhost.pomerium.io',
|
from: 'http://' + domain + '.localhost.pomerium.io',
|
||||||
prefix: '/by-group',
|
prefix: '/by-group',
|
||||||
to: 'http://httpdetails.default.svc.cluster.local',
|
to: 'http://' + domain + '.default.svc.cluster.local',
|
||||||
allowed_groups: ['admin'],
|
allowed_groups: ['admin'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: 'http://httpdetails.localhost.pomerium.io',
|
from: 'http://' + domain + '.localhost.pomerium.io',
|
||||||
to: 'http://httpdetails.default.svc.cluster.local',
|
to: 'http://' + domain + '.default.svc.cluster.local',
|
||||||
allow_public_unauthenticated_access: true,
|
allow_public_unauthenticated_access: true,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
for domain in ['httpdetails', 'fa-httpdetails']
|
||||||
|
]);
|
||||||
|
|
||||||
local PomeriumPolicyHash = std.base64(std.md5(std.manifestJsonEx(PomeriumPolicy(), '')));
|
local PomeriumPolicyHash = std.base64(std.md5(std.manifestJsonEx(PomeriumPolicy(), '')));
|
||||||
|
|
||||||
|
@ -292,20 +295,27 @@ local PomeriumForwardAuthIngress = function() {
|
||||||
tls: [
|
tls: [
|
||||||
{
|
{
|
||||||
hosts: [
|
hosts: [
|
||||||
'fa-httpecho.localhost.pomerium.io',
|
'fa-httpdetails.localhost.pomerium.io',
|
||||||
],
|
],
|
||||||
secretName: 'pomerium-tls',
|
secretName: 'pomerium-tls',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
host: 'fa-httpecho.localhost.pomerium.io',
|
host: 'fa-httpdetails.localhost.pomerium.io',
|
||||||
http: {
|
http: {
|
||||||
paths: [
|
paths: [
|
||||||
|
{
|
||||||
|
path: '/.pomerium/',
|
||||||
|
backend: {
|
||||||
|
serviceName: 'proxy',
|
||||||
|
servicePort: 'https',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
backend: {
|
backend: {
|
||||||
serviceName: 'httpecho',
|
serviceName: 'httpdetails',
|
||||||
servicePort: 'http',
|
servicePort: 'http',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -117,6 +117,8 @@ func (p *Proxy) Verify(verifyOnly bool) http.Handler {
|
||||||
}
|
}
|
||||||
originalRequest := p.getOriginalRequest(r, uri)
|
originalRequest := p.getOriginalRequest(r, uri)
|
||||||
|
|
||||||
|
if err := p.authorize(w, originalRequest); err != nil {
|
||||||
|
// no session, so redirect
|
||||||
if _, err := sessions.FromContext(r.Context()); err != nil {
|
if _, err := sessions.FromContext(r.Context()); err != nil {
|
||||||
if verifyOnly {
|
if verifyOnly {
|
||||||
return httputil.NewError(http.StatusUnauthorized, err)
|
return httputil.NewError(http.StatusUnauthorized, err)
|
||||||
|
@ -131,7 +133,6 @@ func (p *Proxy) Verify(verifyOnly bool) http.Handler {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p.authorize(w, originalRequest); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,10 +103,7 @@ func (p *Proxy) AuthorizeSession(next http.Handler) http.Handler {
|
||||||
func (p *Proxy) authorize(w http.ResponseWriter, r *http.Request) error {
|
func (p *Proxy) authorize(w http.ResponseWriter, r *http.Request) error {
|
||||||
ctx, span := trace.StartSpan(r.Context(), "proxy.authorize")
|
ctx, span := trace.StartSpan(r.Context(), "proxy.authorize")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
jwt, err := sessions.FromContext(ctx)
|
jwt, _ := sessions.FromContext(ctx)
|
||||||
if err != nil {
|
|
||||||
return httputil.NewError(http.StatusInternalServerError, err)
|
|
||||||
}
|
|
||||||
authz, err := p.AuthorizeClient.Authorize(ctx, jwt, r)
|
authz, err := p.AuthorizeClient.Authorize(ctx, jwt, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return httputil.NewError(http.StatusInternalServerError, err)
|
return httputil.NewError(http.StatusInternalServerError, err)
|
||||||
|
|
|
@ -159,7 +159,7 @@ func TestProxy_AuthorizeSession(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{"user is authorized", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: true}}, nil, identity.MockProvider{}, http.StatusOK},
|
{"user is authorized", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: true}}, nil, identity.MockProvider{}, http.StatusOK},
|
||||||
{"user is not authorized", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: false}}, nil, identity.MockProvider{}, http.StatusForbidden},
|
{"user is not authorized", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: false}}, nil, identity.MockProvider{}, http.StatusForbidden},
|
||||||
{"ctx error", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: true}}, errors.New("hi"), identity.MockProvider{}, http.StatusInternalServerError},
|
{"ctx error", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{Allow: true}}, errors.New("hi"), identity.MockProvider{}, http.StatusOK},
|
||||||
{"authz client error", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeError: errors.New("err")}, nil, identity.MockProvider{}, http.StatusInternalServerError},
|
{"authz client error", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeError: errors.New("err")}, nil, identity.MockProvider{}, http.StatusInternalServerError},
|
||||||
{"expired, reauth failed", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{SessionExpired: true}}, nil, identity.MockProvider{}, http.StatusForbidden},
|
{"expired, reauth failed", 200, &mstore.Store{Session: &sessions.State{Email: "user@test.example", Expiry: jwt.NewNumericDate(time.Now().Add(10 * time.Second))}}, client.MockAuthorize{AuthorizeResponse: &authorize.IsAuthorizedReply{SessionExpired: true}}, nil, identity.MockProvider{}, http.StatusForbidden},
|
||||||
//todo(bdd): it's a bit tricky to test the refresh flow
|
//todo(bdd): it's a bit tricky to test the refresh flow
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue