authorize: preserve original context (#2247)

This commit is contained in:
wasaga 2021-06-01 11:10:35 -04:00 committed by GitHub
parent 96d6005639
commit 12c8bb2da4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 1 deletions

View file

@ -11,6 +11,7 @@ import (
"gopkg.in/square/go-jose.v2"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/urlutil"
"github.com/pomerium/pomerium/pkg/cryptutil"
@ -139,6 +140,8 @@ func (e *Evaluator) Evaluate(ctx context.Context, req *Request) (*Result, error)
return nil, err
}
carryOverJWTAssertion(headersOutput.Headers, req.HTTP.Headers)
res := &Result{
Allow: policyOutput.Allow,
Deny: policyOutput.Deny,
@ -227,3 +230,18 @@ func safeEval(ctx context.Context, q rego.PreparedEvalQuery, options ...rego.Eva
resultSet, err = q.Eval(ctx, options...)
return resultSet, err
}
// carryOverJWTAssertion copies assertion JWT from request to response
// note that src keys are expected to be http.CanonicalHeaderKey
func carryOverJWTAssertion(dst http.Header, src map[string]string) {
jwtForKey := http.CanonicalHeaderKey(httputil.HeaderPomeriumJWTAssertionFor)
jwtFor, ok := src[jwtForKey]
if ok && jwtFor != "" {
dst.Add(jwtForKey, jwtFor)
return
}
jwtFor, ok = src[http.CanonicalHeaderKey(httputil.HeaderPomeriumJWTAssertion)]
if ok && jwtFor != "" {
dst.Add(jwtForKey, jwtFor)
}
}

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math"
"net/http"
"net/url"
"testing"
@ -16,6 +17,7 @@ import (
"gopkg.in/square/go-jose.v2"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/pkg/cryptutil"
"github.com/pomerium/pomerium/pkg/grpc/databroker"
"github.com/pomerium/pomerium/pkg/grpc/directory"
@ -453,6 +455,46 @@ func TestEvaluator(t *testing.T) {
require.NoError(t, err)
assert.True(t, res.Allow)
})
t.Run("carry over assertion header", func(t *testing.T) {
tcs := []struct {
src map[string]string
jwtAssertionFor string
}{
{map[string]string{}, ""},
{map[string]string{
http.CanonicalHeaderKey(httputil.HeaderPomeriumJWTAssertion): "identity-a",
}, "identity-a"},
{map[string]string{
http.CanonicalHeaderKey(httputil.HeaderPomeriumJWTAssertionFor): "identity-a",
http.CanonicalHeaderKey(httputil.HeaderPomeriumJWTAssertion): "identity-b",
}, "identity-a"},
}
for _, tc := range tcs {
res, err := eval(t, options, []proto.Message{
&session.Session{
Id: "session1",
UserId: "user1",
},
&user.User{
Id: "user1",
},
}, &Request{
Policy: &policies[8],
Session: RequestSession{
ID: "session1",
},
HTTP: RequestHTTP{
Method: "GET",
URL: "https://from.example.com",
ClientCertificate: testValidCert,
Headers: tc.src,
},
})
if assert.NoError(t, err) {
assert.Equal(t, tc.jwtAssertionFor, res.Headers.Get(httputil.HeaderPomeriumJWTAssertionFor))
}
}
})
}
func mustParseURL(str string) *url.URL {

View file

@ -478,7 +478,7 @@ func mkRouteMatch(policy *config.Policy) *envoy_config_route_v3.RouteMatch {
func getRequestHeadersToRemove(options *config.Options, policy *config.Policy) []string {
requestHeadersToRemove := policy.RemoveRequestHeaders
if !policy.PassIdentityHeaders {
requestHeadersToRemove = append(requestHeadersToRemove, httputil.HeaderPomeriumJWTAssertion)
requestHeadersToRemove = append(requestHeadersToRemove, httputil.HeaderPomeriumJWTAssertion, httputil.HeaderPomeriumJWTAssertionFor)
for _, claim := range options.JWTClaimsHeaders {
requestHeadersToRemove = append(requestHeadersToRemove, httputil.PomeriumJWTHeaderName(claim))
}

View file

@ -19,6 +19,8 @@ const (
HeaderPomeriumResponse = "x-pomerium-intercepted-response"
// HeaderPomeriumJWTAssertion is the header key containing JWT signed user details.
HeaderPomeriumJWTAssertion = "x-pomerium-jwt-assertion"
// HeaderPomeriumJWTAssertionFor carries over original user identity from a chain of network calls.
HeaderPomeriumJWTAssertionFor = "x-pomerium-jwt-assertion-for"
// HeaderPomeriumReproxyPolicy is the header key containing the policy to reproxy a request to.
HeaderPomeriumReproxyPolicy = "x-pomerium-reproxy-policy"
// HeaderPomeriumReproxyPolicyHMAC is an HMAC of the HeaderPomeriumReproxyPolicy header.