mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-31 18:07:17 +02:00
Merge pull request from GHSA-pvrc-wvj2-f59p
* authorize: use route id from envoy for policy evaluation * authorize: normalize URL query params * config: enable envoy normalize_path option * fix tests --------- Co-authored-by: Kenneth Jenkins <51246568+kenjenkins@users.noreply.github.com>
This commit is contained in:
parent
37c8dcc9db
commit
d315e68335
13 changed files with 503 additions and 289 deletions
|
@ -22,14 +22,9 @@ import (
|
||||||
"github.com/pomerium/pomerium/pkg/policy/criteria"
|
"github.com/pomerium/pomerium/pkg/policy/criteria"
|
||||||
)
|
)
|
||||||
|
|
||||||
// notFoundOutput is what's returned if a route isn't found for a policy.
|
|
||||||
var notFoundOutput = &Result{
|
|
||||||
Deny: NewRuleResult(true, criteria.ReasonRouteNotFound),
|
|
||||||
Headers: make(http.Header),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request contains the inputs needed for evaluation.
|
// Request contains the inputs needed for evaluation.
|
||||||
type Request struct {
|
type Request struct {
|
||||||
|
IsInternal bool
|
||||||
Policy *config.Policy
|
Policy *config.Policy
|
||||||
HTTP RequestHTTP
|
HTTP RequestHTTP
|
||||||
Session RequestSession
|
Session RequestSession
|
||||||
|
@ -125,8 +120,60 @@ func (e *Evaluator) Evaluate(ctx context.Context, req *Request) (*Result, error)
|
||||||
ctx, span := trace.StartSpan(ctx, "authorize.Evaluator.Evaluate")
|
ctx, span := trace.StartSpan(ctx, "authorize.Evaluator.Evaluate")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
|
var policyOutput *PolicyResponse
|
||||||
|
eg.Go(func() error {
|
||||||
|
var err error
|
||||||
|
if req.IsInternal {
|
||||||
|
policyOutput, err = e.evaluateInternal(ctx, req)
|
||||||
|
} else {
|
||||||
|
policyOutput, err = e.evaluatePolicy(ctx, req)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
var headersOutput *HeadersResponse
|
||||||
|
eg.Go(func() error {
|
||||||
|
var err error
|
||||||
|
headersOutput, err = e.evaluateHeaders(ctx, req)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
err := eg.Wait()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res := &Result{
|
||||||
|
Allow: policyOutput.Allow,
|
||||||
|
Deny: policyOutput.Deny,
|
||||||
|
Headers: headersOutput.Headers,
|
||||||
|
Traces: policyOutput.Traces,
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) evaluateInternal(_ context.Context, req *Request) (*PolicyResponse, error) {
|
||||||
|
// these endpoints require a logged-in user
|
||||||
|
if req.HTTP.Path == "/.pomerium/webauthn" || req.HTTP.Path == "/.pomerium/jwt" {
|
||||||
|
if req.Session.ID == "" {
|
||||||
|
return &PolicyResponse{
|
||||||
|
Allow: NewRuleResult(false, criteria.ReasonUserUnauthenticated),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &PolicyResponse{
|
||||||
|
Allow: NewRuleResult(true, criteria.ReasonPomeriumRoute),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Evaluator) evaluatePolicy(ctx context.Context, req *Request) (*PolicyResponse, error) {
|
||||||
if req.Policy == nil {
|
if req.Policy == nil {
|
||||||
return notFoundOutput, nil
|
return &PolicyResponse{
|
||||||
|
Deny: NewRuleResult(true, criteria.ReasonRouteNotFound),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := req.Policy.RouteID()
|
id, err := req.Policy.RouteID()
|
||||||
|
@ -136,7 +183,9 @@ func (e *Evaluator) Evaluate(ctx context.Context, req *Request) (*Result, error)
|
||||||
|
|
||||||
policyEvaluator, ok := e.policyEvaluators[id]
|
policyEvaluator, ok := e.policyEvaluators[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return notFoundOutput, nil
|
return &PolicyResponse{
|
||||||
|
Deny: NewRuleResult(true, criteria.ReasonRouteNotFound),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clientCA, err := e.getClientCA(req.Policy)
|
clientCA, err := e.getClientCA(req.Policy)
|
||||||
|
@ -149,41 +198,23 @@ func (e *Evaluator) Evaluate(ctx context.Context, req *Request) (*Result, error)
|
||||||
return nil, fmt.Errorf("authorize: error validating client certificate: %w", err)
|
return nil, fmt.Errorf("authorize: error validating client certificate: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
eg, ectx := errgroup.WithContext(ctx)
|
return policyEvaluator.Evaluate(ctx, &PolicyRequest{
|
||||||
|
|
||||||
var policyOutput *PolicyResponse
|
|
||||||
eg.Go(func() error {
|
|
||||||
var err error
|
|
||||||
policyOutput, err = policyEvaluator.Evaluate(ectx, &PolicyRequest{
|
|
||||||
HTTP: req.HTTP,
|
HTTP: req.HTTP,
|
||||||
Session: req.Session,
|
Session: req.Session,
|
||||||
IsValidClientCertificate: isValidClientCertificate,
|
IsValidClientCertificate: isValidClientCertificate,
|
||||||
})
|
})
|
||||||
return err
|
}
|
||||||
})
|
|
||||||
|
|
||||||
var headersOutput *HeadersResponse
|
func (e *Evaluator) evaluateHeaders(ctx context.Context, req *Request) (*HeadersResponse, error) {
|
||||||
eg.Go(func() error {
|
|
||||||
headersReq := NewHeadersRequestFromPolicy(req.Policy, req.HTTP.Hostname)
|
headersReq := NewHeadersRequestFromPolicy(req.Policy, req.HTTP.Hostname)
|
||||||
headersReq.Session = req.Session
|
headersReq.Session = req.Session
|
||||||
var err error
|
res, err := e.headersEvaluators.Evaluate(ctx, headersReq)
|
||||||
headersOutput, err = e.headersEvaluators.Evaluate(ectx, headersReq)
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
err = eg.Wait()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
carryOverJWTAssertion(headersOutput.Headers, req.HTTP.Headers)
|
carryOverJWTAssertion(res.Headers, req.HTTP.Headers)
|
||||||
|
|
||||||
res := &Result{
|
|
||||||
Allow: policyOutput.Allow,
|
|
||||||
Deny: policyOutput.Deny,
|
|
||||||
Headers: headersOutput.Headers,
|
|
||||||
Traces: policyOutput.Traces,
|
|
||||||
}
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ type HeadersRequest struct {
|
||||||
// NewHeadersRequestFromPolicy creates a new HeadersRequest from a policy.
|
// NewHeadersRequestFromPolicy creates a new HeadersRequest from a policy.
|
||||||
func NewHeadersRequestFromPolicy(policy *config.Policy, hostname string) *HeadersRequest {
|
func NewHeadersRequestFromPolicy(policy *config.Policy, hostname string) *HeadersRequest {
|
||||||
input := new(HeadersRequest)
|
input := new(HeadersRequest)
|
||||||
|
if policy != nil {
|
||||||
input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication
|
input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication
|
||||||
input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH ||
|
input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH ||
|
||||||
policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_MAGLEV
|
policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_MAGLEV
|
||||||
|
@ -40,6 +41,7 @@ func NewHeadersRequestFromPolicy(policy *config.Policy, hostname string) *Header
|
||||||
}
|
}
|
||||||
input.PassAccessToken = policy.GetSetAuthorizationHeader() == configpb.Route_ACCESS_TOKEN
|
input.PassAccessToken = policy.GetSetAuthorizationHeader() == configpb.Route_ACCESS_TOKEN
|
||||||
input.PassIDToken = policy.GetSetAuthorizationHeader() == configpb.Route_ID_TOKEN
|
input.PassIDToken = policy.GetSetAuthorizationHeader() == configpb.Route_ID_TOKEN
|
||||||
|
}
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ func TestPolicyEvaluator(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, &PolicyResponse{
|
assert.Equal(t, &PolicyResponse{
|
||||||
Allow: NewRuleResult(false, criteria.ReasonEmailUnauthorized, criteria.ReasonNonPomeriumRoute, criteria.ReasonUserUnauthorized),
|
Allow: NewRuleResult(false, criteria.ReasonEmailUnauthorized, criteria.ReasonUserUnauthorized),
|
||||||
Deny: NewRuleResult(false, criteria.ReasonValidClientCertificateOrNoneRequired),
|
Deny: NewRuleResult(false, criteria.ReasonValidClientCertificateOrNoneRequired),
|
||||||
Traces: []contextutil.PolicyEvaluationTrace{{}},
|
Traces: []contextutil.PolicyEvaluationTrace{{}},
|
||||||
}, output)
|
}, output)
|
||||||
|
@ -172,7 +172,7 @@ func TestPolicyEvaluator(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, &PolicyResponse{
|
assert.Equal(t, &PolicyResponse{
|
||||||
Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute),
|
Allow: NewRuleResult(false),
|
||||||
Deny: NewRuleResult(true, criteria.ReasonAccept),
|
Deny: NewRuleResult(true, criteria.ReasonAccept),
|
||||||
Traces: []contextutil.PolicyEvaluationTrace{{}, {ID: "p1", Deny: true}},
|
Traces: []contextutil.PolicyEvaluationTrace{{}, {ID: "p1", Deny: true}},
|
||||||
}, output)
|
}, output)
|
||||||
|
@ -203,7 +203,7 @@ func TestPolicyEvaluator(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, &PolicyResponse{
|
assert.Equal(t, &PolicyResponse{
|
||||||
Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute),
|
Allow: NewRuleResult(false),
|
||||||
Deny: NewRuleResult(true, criteria.ReasonAccept, criteria.ReasonInvalidClientCertificate),
|
Deny: NewRuleResult(true, criteria.ReasonAccept, criteria.ReasonInvalidClientCertificate),
|
||||||
Traces: []contextutil.PolicyEvaluationTrace{{Deny: true}, {ID: "p1", Deny: true}},
|
Traces: []contextutil.PolicyEvaluationTrace{{Deny: true}, {ID: "p1", Deny: true}},
|
||||||
}, output)
|
}, output)
|
||||||
|
@ -289,7 +289,7 @@ func TestPolicyEvaluator(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, &PolicyResponse{
|
assert.Equal(t, &PolicyResponse{
|
||||||
Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute, criteria.ReasonUserUnauthenticated),
|
Allow: NewRuleResult(false, criteria.ReasonUserUnauthenticated),
|
||||||
Deny: NewRuleResult(false, criteria.ReasonValidClientCertificateOrNoneRequired),
|
Deny: NewRuleResult(false, criteria.ReasonValidClientCertificateOrNoneRequired),
|
||||||
Traces: []contextutil.PolicyEvaluationTrace{{Allow: false}},
|
Traces: []contextutil.PolicyEvaluationTrace{{Allow: false}},
|
||||||
}, output)
|
}, output)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
|
"github.com/pomerium/pomerium/config/envoyconfig"
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/sessions"
|
"github.com/pomerium/pomerium/internal/sessions"
|
||||||
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
"github.com/pomerium/pomerium/internal/telemetry/requestid"
|
||||||
|
@ -93,6 +94,7 @@ func (a *Authorize) getEvaluatorRequestFromCheckRequest(
|
||||||
) (*evaluator.Request, error) {
|
) (*evaluator.Request, error) {
|
||||||
requestURL := getCheckRequestURL(in)
|
requestURL := getCheckRequestURL(in)
|
||||||
req := &evaluator.Request{
|
req := &evaluator.Request{
|
||||||
|
IsInternal: envoyconfig.ExtAuthzContextExtensionsIsInternal(in.GetAttributes().GetContextExtensions()),
|
||||||
HTTP: evaluator.NewRequestHTTP(
|
HTTP: evaluator.NewRequestHTTP(
|
||||||
in.GetAttributes().GetRequest().GetHttp().GetMethod(),
|
in.GetAttributes().GetRequest().GetHttp().GetMethod(),
|
||||||
requestURL,
|
requestURL,
|
||||||
|
@ -106,15 +108,16 @@ func (a *Authorize) getEvaluatorRequestFromCheckRequest(
|
||||||
ID: sessionState.ID,
|
ID: sessionState.ID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.Policy = a.getMatchingPolicy(requestURL)
|
req.Policy = a.getMatchingPolicy(envoyconfig.ExtAuthzContextExtensionsRouteID(in.Attributes.GetContextExtensions()))
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authorize) getMatchingPolicy(requestURL url.URL) *config.Policy {
|
func (a *Authorize) getMatchingPolicy(routeID uint64) *config.Policy {
|
||||||
options := a.currentOptions.Load()
|
options := a.currentOptions.Load()
|
||||||
|
|
||||||
for _, p := range options.GetAllPolicies() {
|
for _, p := range options.GetAllPolicies() {
|
||||||
if p.Matches(requestURL) {
|
id, _ := p.RouteID()
|
||||||
|
if id == routeID {
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,6 +162,7 @@ func getCheckRequestURL(req *envoy_service_auth_v3.CheckRequest) url.URL {
|
||||||
path := h.GetPath()
|
path := h.GetPath()
|
||||||
if idx := strings.Index(path, "?"); idx != -1 {
|
if idx := strings.Index(path, "?"); idx != -1 {
|
||||||
u.RawPath, u.RawQuery = path[:idx], path[idx+1:]
|
u.RawPath, u.RawQuery = path[:idx], path[idx+1:]
|
||||||
|
u.RawQuery = u.Query().Encode()
|
||||||
} else {
|
} else {
|
||||||
u.RawPath = path
|
u.RawPath = path
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,9 @@ import (
|
||||||
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
||||||
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
envoy_config_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
|
||||||
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||||
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
|
||||||
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
envoy_http_connection_manager "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
|
||||||
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
envoy_extensions_transport_sockets_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
|
||||||
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
|
||||||
"github.com/golang/protobuf/ptypes/any"
|
|
||||||
"github.com/golang/protobuf/ptypes/wrappers"
|
"github.com/golang/protobuf/ptypes/wrappers"
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"google.golang.org/protobuf/types/known/durationpb"
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
|
@ -32,9 +30,7 @@ import (
|
||||||
|
|
||||||
const listenerBufferLimit uint32 = 32 * 1024
|
const listenerBufferLimit uint32 = 32 * 1024
|
||||||
|
|
||||||
var (
|
var tlsParams = &envoy_extensions_transport_sockets_tls_v3.TlsParameters{
|
||||||
disableExtAuthz *any.Any
|
|
||||||
tlsParams = &envoy_extensions_transport_sockets_tls_v3.TlsParameters{
|
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
"ECDHE-ECDSA-AES256-GCM-SHA384",
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384",
|
"ECDHE-RSA-AES256-GCM-SHA384",
|
||||||
|
@ -45,15 +41,6 @@ var (
|
||||||
},
|
},
|
||||||
TlsMinimumProtocolVersion: envoy_extensions_transport_sockets_tls_v3.TlsParameters_TLSv1_2,
|
TlsMinimumProtocolVersion: envoy_extensions_transport_sockets_tls_v3.TlsParameters_TLSv1_2,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
disableExtAuthz = marshalAny(&envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute{
|
|
||||||
Override: &envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute_Disabled{
|
|
||||||
Disabled: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildListeners builds envoy listeners from the given config.
|
// BuildListeners builds envoy listeners from the given config.
|
||||||
func (b *Builder) BuildListeners(
|
func (b *Builder) BuildListeners(
|
||||||
|
@ -312,6 +299,7 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter(
|
||||||
SkipXffAppend: cfg.Options.SkipXffAppend,
|
SkipXffAppend: cfg.Options.SkipXffAppend,
|
||||||
XffNumTrustedHops: cfg.Options.XffNumTrustedHops,
|
XffNumTrustedHops: cfg.Options.XffNumTrustedHops,
|
||||||
LocalReplyConfig: b.buildLocalReplyConfig(cfg.Options, false),
|
LocalReplyConfig: b.buildLocalReplyConfig(cfg.Options, false),
|
||||||
|
NormalizePath: wrapperspb.Bool(true),
|
||||||
}
|
}
|
||||||
|
|
||||||
if fullyStatic {
|
if fullyStatic {
|
||||||
|
|
53
config/envoyconfig/per_filter_config.go
Normal file
53
config/envoyconfig/per_filter_config.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package envoyconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
envoy_extensions_filters_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
|
||||||
|
"github.com/golang/protobuf/ptypes/any"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PerFilterConfigExtAuthzName is the name of the ext authz filter to apply config to
|
||||||
|
const PerFilterConfigExtAuthzName = "envoy.filters.http.ext_authz"
|
||||||
|
|
||||||
|
// PerFilterConfigExtAuthzContextExtensions returns a per-filter config for ext authz that disables ext-authz.
|
||||||
|
func PerFilterConfigExtAuthzContextExtensions(authzContextExtensions map[string]string) *any.Any {
|
||||||
|
return marshalAny(&envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute{
|
||||||
|
Override: &envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute_CheckSettings{
|
||||||
|
CheckSettings: &envoy_extensions_filters_http_ext_authz_v3.CheckSettings{
|
||||||
|
ContextExtensions: authzContextExtensions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// PerFilterConfigExtAuthzDisabled returns a per-filter config for ext authz that disables ext-authz.
|
||||||
|
func PerFilterConfigExtAuthzDisabled() *any.Any {
|
||||||
|
return marshalAny(&envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute{
|
||||||
|
Override: &envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute_Disabled{
|
||||||
|
Disabled: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeExtAuthzContextExtensions makes the ext authz context extensions.
|
||||||
|
func MakeExtAuthzContextExtensions(internal bool, routeID uint64) map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"internal": strconv.FormatBool(internal),
|
||||||
|
"route_id": strconv.FormatUint(routeID, 10),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtAuthzContextExtensionsIsInternal returns true if the context extensions indicates the route is internal.
|
||||||
|
func ExtAuthzContextExtensionsIsInternal(extAuthzContextExtensions map[string]string) bool {
|
||||||
|
return extAuthzContextExtensions != nil && extAuthzContextExtensions["internal"] == "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtAuthzContextExtensionsRouteID returns the route id for the context extensions.
|
||||||
|
func ExtAuthzContextExtensionsRouteID(extAuthzContextExtensions map[string]string) uint64 {
|
||||||
|
if extAuthzContextExtensions == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
routeID, _ := strconv.ParseUint(extAuthzContextExtensions["route_id"], 10, 64)
|
||||||
|
return routeID
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "https://*.example.com",
|
From: "https://*.example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://www.example.com"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
@ -40,15 +41,13 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
"name": "catch-all",
|
"name": "catch-all",
|
||||||
"domains": ["*"],
|
"domains": ["*"],
|
||||||
"routes": [
|
"routes": [
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium/jwt", true, false))+`,
|
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/ping", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium/webauthn", true, false))+`,
|
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/healthz", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/ping", false, false))+`,
|
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/healthz", false, false))+`,
|
`+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.pomerium/", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium", false, false))+`,
|
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.well-known/pomerium", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.pomerium/", false, false))+`,
|
`+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.well-known/pomerium/", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.well-known/pomerium", false, false))+`,
|
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/robots.txt", false))+`,
|
||||||
`+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.well-known/pomerium/", false, false))+`,
|
|
||||||
`+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/robots.txt", false, false))+`,
|
|
||||||
{
|
{
|
||||||
"name": "policy-0",
|
"name": "policy-0",
|
||||||
"match": {
|
"match": {
|
||||||
|
@ -79,7 +78,7 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
],
|
],
|
||||||
"route": {
|
"route": {
|
||||||
"autoHostRewrite": true,
|
"autoHostRewrite": true,
|
||||||
"cluster": "route-0",
|
"cluster": "route-5feb9fe8bd89aa97",
|
||||||
"hashPolicy": [
|
"hashPolicy": [
|
||||||
{ "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true },
|
{ "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true },
|
||||||
{ "connectionProperties": { "sourceIp": true }, "terminal": true }
|
{ "connectionProperties": { "sourceIp": true }, "terminal": true }
|
||||||
|
@ -89,6 +88,17 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
{ "enabled": false, "upgradeType": "websocket" },
|
{ "enabled": false, "upgradeType": "websocket" },
|
||||||
{ "enabled": false, "upgradeType": "spdy/3.1" }
|
{ "enabled": false, "upgradeType": "spdy/3.1" }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "6911793875091303063"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -121,7 +131,7 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
],
|
],
|
||||||
"route": {
|
"route": {
|
||||||
"autoHostRewrite": true,
|
"autoHostRewrite": true,
|
||||||
"cluster": "route-0",
|
"cluster": "route-5feb9fe8bd89aa97",
|
||||||
"hashPolicy": [
|
"hashPolicy": [
|
||||||
{ "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true },
|
{ "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true },
|
||||||
{ "connectionProperties": { "sourceIp": true }, "terminal": true }
|
{ "connectionProperties": { "sourceIp": true }, "terminal": true }
|
||||||
|
@ -131,6 +141,17 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) {
|
||||||
{ "enabled": false, "upgradeType": "websocket" },
|
{ "enabled": false, "upgradeType": "websocket" },
|
||||||
{ "enabled": false, "upgradeType": "spdy/3.1" }
|
{ "enabled": false, "upgradeType": "spdy/3.1" }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "6911793875091303063"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -45,7 +45,7 @@ func (b *Builder) buildGRPCRoutes() ([]*envoy_config_route_v3.Route, error) {
|
||||||
},
|
},
|
||||||
Action: action,
|
Action: action,
|
||||||
TypedPerFilterConfig: map[string]*any.Any{
|
TypedPerFilterConfig: map[string]*any.Any{
|
||||||
"envoy.filters.http.ext_authz": disableExtAuthz,
|
PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzDisabled(),
|
||||||
},
|
},
|
||||||
}}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
@ -65,20 +65,16 @@ func (b *Builder) buildPomeriumHTTPRoutes(
|
||||||
}
|
}
|
||||||
if !isFrontingAuthenticate {
|
if !isFrontingAuthenticate {
|
||||||
routes = append(routes,
|
routes = append(routes,
|
||||||
// enable ext_authz
|
b.buildControlPlanePathRoute(options, "/ping", requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, "/.pomerium/jwt", true, requireStrictTransportSecurity),
|
b.buildControlPlanePathRoute(options, "/healthz", requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, urlutil.WebAuthnURLPath, true, requireStrictTransportSecurity),
|
b.buildControlPlanePathRoute(options, "/.pomerium", requireStrictTransportSecurity),
|
||||||
// disable ext_authz and passthrough to proxy handlers
|
b.buildControlPlanePrefixRoute(options, "/.pomerium/", requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, "/ping", false, requireStrictTransportSecurity),
|
b.buildControlPlanePathRoute(options, "/.well-known/pomerium", requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, "/healthz", false, requireStrictTransportSecurity),
|
b.buildControlPlanePrefixRoute(options, "/.well-known/pomerium/", requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, "/.pomerium", false, requireStrictTransportSecurity),
|
|
||||||
b.buildControlPlanePrefixRoute(options, "/.pomerium/", false, requireStrictTransportSecurity),
|
|
||||||
b.buildControlPlanePathRoute(options, "/.well-known/pomerium", false, requireStrictTransportSecurity),
|
|
||||||
b.buildControlPlanePrefixRoute(options, "/.well-known/pomerium/", false, requireStrictTransportSecurity),
|
|
||||||
)
|
)
|
||||||
// per #837, only add robots.txt if there are no unauthenticated routes
|
// per #837, only add robots.txt if there are no unauthenticated routes
|
||||||
if !hasPublicPolicyMatchingURL(options, url.URL{Scheme: "https", Host: host, Path: "/robots.txt"}) {
|
if !hasPublicPolicyMatchingURL(options, url.URL{Scheme: "https", Host: host, Path: "/robots.txt"}) {
|
||||||
routes = append(routes, b.buildControlPlanePathRoute(options, "/robots.txt", false, requireStrictTransportSecurity))
|
routes = append(routes, b.buildControlPlanePathRoute(options, "/robots.txt", requireStrictTransportSecurity))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +105,8 @@ func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(
|
||||||
}
|
}
|
||||||
if urlMatchesHost(u, host) {
|
if urlMatchesHost(u, host) {
|
||||||
return []*envoy_config_route_v3.Route{
|
return []*envoy_config_route_v3.Route{
|
||||||
b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, false, requireStrictTransportSecurity),
|
b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, requireStrictTransportSecurity),
|
||||||
b.buildControlPlanePathRoute(options, "/", false, requireStrictTransportSecurity),
|
b.buildControlPlanePathRoute(options, "/", requireStrictTransportSecurity),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +116,6 @@ func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(
|
||||||
func (b *Builder) buildControlPlanePathRoute(
|
func (b *Builder) buildControlPlanePathRoute(
|
||||||
options *config.Options,
|
options *config.Options,
|
||||||
path string,
|
path string,
|
||||||
protected bool,
|
|
||||||
requireStrictTransportSecurity bool,
|
requireStrictTransportSecurity bool,
|
||||||
) *envoy_config_route_v3.Route {
|
) *envoy_config_route_v3.Route {
|
||||||
r := &envoy_config_route_v3.Route{
|
r := &envoy_config_route_v3.Route{
|
||||||
|
@ -136,11 +131,9 @@ func (b *Builder) buildControlPlanePathRoute(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
||||||
}
|
TypedPerFilterConfig: map[string]*any.Any{
|
||||||
if !protected {
|
PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(true, 0)),
|
||||||
r.TypedPerFilterConfig = map[string]*any.Any{
|
},
|
||||||
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -148,7 +141,6 @@ func (b *Builder) buildControlPlanePathRoute(
|
||||||
func (b *Builder) buildControlPlanePrefixRoute(
|
func (b *Builder) buildControlPlanePrefixRoute(
|
||||||
options *config.Options,
|
options *config.Options,
|
||||||
prefix string,
|
prefix string,
|
||||||
protected bool,
|
|
||||||
requireStrictTransportSecurity bool,
|
requireStrictTransportSecurity bool,
|
||||||
) *envoy_config_route_v3.Route {
|
) *envoy_config_route_v3.Route {
|
||||||
r := &envoy_config_route_v3.Route{
|
r := &envoy_config_route_v3.Route{
|
||||||
|
@ -164,11 +156,9 @@ func (b *Builder) buildControlPlanePrefixRoute(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
||||||
}
|
TypedPerFilterConfig: map[string]*any.Any{
|
||||||
if !protected {
|
PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(true, 0)),
|
||||||
r.TypedPerFilterConfig = map[string]*any.Any{
|
},
|
||||||
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -288,6 +278,11 @@ func (b *Builder) buildRouteForPolicyAndMatch(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routeID, err := policy.RouteID()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, fromURL.Hostname())
|
requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, fromURL.Hostname())
|
||||||
|
|
||||||
route := &envoy_config_route_v3.Route{
|
route := &envoy_config_route_v3.Route{
|
||||||
|
@ -323,9 +318,12 @@ func (b *Builder) buildRouteForPolicyAndMatch(
|
||||||
}
|
}
|
||||||
if isFrontingAuthenticate {
|
if isFrontingAuthenticate {
|
||||||
route.TypedPerFilterConfig = map[string]*any.Any{
|
route.TypedPerFilterConfig = map[string]*any.Any{
|
||||||
"envoy.filters.http.ext_authz": disableExtAuthz,
|
PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzDisabled(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
route.TypedPerFilterConfig = map[string]*any.Any{
|
||||||
|
PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(false, routeID)),
|
||||||
|
}
|
||||||
luaMetadata["remove_pomerium_cookie"] = &structpb.Value{
|
luaMetadata["remove_pomerium_cookie"] = &structpb.Value{
|
||||||
Kind: &structpb.Value_StringValue{
|
Kind: &structpb.Value_StringValue{
|
||||||
StringValue: cfg.Options.CookieName,
|
StringValue: cfg.Options.CookieName,
|
||||||
|
@ -344,8 +342,7 @@ func (b *Builder) buildRouteForPolicyAndMatch(
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.IsForKubernetes() {
|
if policy.IsForKubernetes() {
|
||||||
policyID, _ := policy.RouteID()
|
for _, hdr := range b.reproxy.GetPolicyIDHeaders(routeID) {
|
||||||
for _, hdr := range b.reproxy.GetPolicyIDHeaders(policyID) {
|
|
||||||
route.RequestHeadersToAdd = append(route.RequestHeadersToAdd,
|
route.RequestHeadersToAdd = append(route.RequestHeadersToAdd,
|
||||||
&envoy_config_core_v3.HeaderValueOption{
|
&envoy_config_core_v3.HeaderValueOption{
|
||||||
Header: &envoy_config_core_v3.HeaderValue{
|
Header: &envoy_config_core_v3.HeaderValue{
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"github.com/pomerium/pomerium/config"
|
"github.com/pomerium/pomerium/config"
|
||||||
"github.com/pomerium/pomerium/config/envoyconfig/filemgr"
|
"github.com/pomerium/pomerium/config/envoyconfig/filemgr"
|
||||||
"github.com/pomerium/pomerium/internal/testutil"
|
"github.com/pomerium/pomerium/internal/testutil"
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
|
||||||
"github.com/pomerium/pomerium/pkg/cryptutil"
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ func Test_buildGRPCRoutes(t *testing.T) {
|
||||||
|
|
||||||
func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
b := &Builder{filemgr: filemgr.NewManager()}
|
b := &Builder{filemgr: filemgr.NewManager()}
|
||||||
routeString := func(typ, name string, protected bool) string {
|
routeString := func(typ, name string) string {
|
||||||
str := `{
|
str := `{
|
||||||
"name": "pomerium-` + typ + `-` + name + `",
|
"name": "pomerium-` + typ + `-` + name + `",
|
||||||
"match": {
|
"match": {
|
||||||
|
@ -80,19 +79,19 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
],
|
],
|
||||||
"route": {
|
"route": {
|
||||||
"cluster": "pomerium-control-plane-http"
|
"cluster": "pomerium-control-plane-http"
|
||||||
}
|
},
|
||||||
`
|
|
||||||
if !protected {
|
|
||||||
str += `,
|
|
||||||
"typedPerFilterConfig": {
|
"typedPerFilterConfig": {
|
||||||
"envoy.filters.http.ext_authz": {
|
"envoy.filters.http.ext_authz": {
|
||||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
"disabled": true
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "true",
|
||||||
|
"route_id": "0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
|
||||||
}
|
}
|
||||||
str += "}"
|
}
|
||||||
|
}`
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
t.Run("authenticate", func(t *testing.T) {
|
t.Run("authenticate", func(t *testing.T) {
|
||||||
|
@ -105,17 +104,15 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.AssertProtoJSONEqual(t, `[
|
testutil.AssertProtoJSONEqual(t, `[
|
||||||
`+routeString("path", "/.pomerium/jwt", true)+`,
|
`+routeString("path", "/ping")+`,
|
||||||
`+routeString("path", urlutil.WebAuthnURLPath, true)+`,
|
`+routeString("path", "/healthz")+`,
|
||||||
`+routeString("path", "/ping", false)+`,
|
`+routeString("path", "/.pomerium")+`,
|
||||||
`+routeString("path", "/healthz", false)+`,
|
`+routeString("prefix", "/.pomerium/")+`,
|
||||||
`+routeString("path", "/.pomerium", false)+`,
|
`+routeString("path", "/.well-known/pomerium")+`,
|
||||||
`+routeString("prefix", "/.pomerium/", false)+`,
|
`+routeString("prefix", "/.well-known/pomerium/")+`,
|
||||||
`+routeString("path", "/.well-known/pomerium", false)+`,
|
`+routeString("path", "/robots.txt")+`,
|
||||||
`+routeString("prefix", "/.well-known/pomerium/", false)+`,
|
`+routeString("path", "/oauth2/callback")+`,
|
||||||
`+routeString("path", "/robots.txt", false)+`,
|
`+routeString("path", "/")+`
|
||||||
`+routeString("path", "/oauth2/callback", false)+`,
|
|
||||||
`+routeString("path", "/", false)+`
|
|
||||||
]`, routes)
|
]`, routes)
|
||||||
})
|
})
|
||||||
t.Run("proxy fronting authenticate", func(t *testing.T) {
|
t.Run("proxy fronting authenticate", func(t *testing.T) {
|
||||||
|
@ -144,15 +141,13 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.AssertProtoJSONEqual(t, `[
|
testutil.AssertProtoJSONEqual(t, `[
|
||||||
`+routeString("path", "/.pomerium/jwt", true)+`,
|
`+routeString("path", "/ping")+`,
|
||||||
`+routeString("path", urlutil.WebAuthnURLPath, true)+`,
|
`+routeString("path", "/healthz")+`,
|
||||||
`+routeString("path", "/ping", false)+`,
|
`+routeString("path", "/.pomerium")+`,
|
||||||
`+routeString("path", "/healthz", false)+`,
|
`+routeString("prefix", "/.pomerium/")+`,
|
||||||
`+routeString("path", "/.pomerium", false)+`,
|
`+routeString("path", "/.well-known/pomerium")+`,
|
||||||
`+routeString("prefix", "/.pomerium/", false)+`,
|
`+routeString("prefix", "/.well-known/pomerium/")+`,
|
||||||
`+routeString("path", "/.well-known/pomerium", false)+`,
|
`+routeString("path", "/robots.txt")+`
|
||||||
`+routeString("prefix", "/.well-known/pomerium/", false)+`,
|
|
||||||
`+routeString("path", "/robots.txt", false)+`
|
|
||||||
]`, routes)
|
]`, routes)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -172,14 +167,12 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testutil.AssertProtoJSONEqual(t, `[
|
testutil.AssertProtoJSONEqual(t, `[
|
||||||
`+routeString("path", "/.pomerium/jwt", true)+`,
|
`+routeString("path", "/ping")+`,
|
||||||
`+routeString("path", urlutil.WebAuthnURLPath, true)+`,
|
`+routeString("path", "/healthz")+`,
|
||||||
`+routeString("path", "/ping", false)+`,
|
`+routeString("path", "/.pomerium")+`,
|
||||||
`+routeString("path", "/healthz", false)+`,
|
`+routeString("prefix", "/.pomerium/")+`,
|
||||||
`+routeString("path", "/.pomerium", false)+`,
|
`+routeString("path", "/.well-known/pomerium")+`,
|
||||||
`+routeString("prefix", "/.pomerium/", false)+`,
|
`+routeString("prefix", "/.well-known/pomerium/")+`
|
||||||
`+routeString("path", "/.well-known/pomerium", false)+`,
|
|
||||||
`+routeString("prefix", "/.well-known/pomerium/", false)+`
|
|
||||||
]`, routes)
|
]`, routes)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -187,7 +180,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
|
||||||
func Test_buildControlPlanePathRoute(t *testing.T) {
|
func Test_buildControlPlanePathRoute(t *testing.T) {
|
||||||
options := config.NewDefaultOptions()
|
options := config.NewDefaultOptions()
|
||||||
b := &Builder{filemgr: filemgr.NewManager()}
|
b := &Builder{filemgr: filemgr.NewManager()}
|
||||||
route := b.buildControlPlanePathRoute(options, "/hello/world", false, false)
|
route := b.buildControlPlanePathRoute(options, "/hello/world", false)
|
||||||
testutil.AssertProtoJSONEqual(t, `
|
testutil.AssertProtoJSONEqual(t, `
|
||||||
{
|
{
|
||||||
"name": "pomerium-path-/hello/world",
|
"name": "pomerium-path-/hello/world",
|
||||||
|
@ -216,7 +209,12 @@ func Test_buildControlPlanePathRoute(t *testing.T) {
|
||||||
"typedPerFilterConfig": {
|
"typedPerFilterConfig": {
|
||||||
"envoy.filters.http.ext_authz": {
|
"envoy.filters.http.ext_authz": {
|
||||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
"disabled": true
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "true",
|
||||||
|
"route_id": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +224,7 @@ func Test_buildControlPlanePathRoute(t *testing.T) {
|
||||||
func Test_buildControlPlanePrefixRoute(t *testing.T) {
|
func Test_buildControlPlanePrefixRoute(t *testing.T) {
|
||||||
options := config.NewDefaultOptions()
|
options := config.NewDefaultOptions()
|
||||||
b := &Builder{filemgr: filemgr.NewManager()}
|
b := &Builder{filemgr: filemgr.NewManager()}
|
||||||
route := b.buildControlPlanePrefixRoute(options, "/hello/world/", false, false)
|
route := b.buildControlPlanePrefixRoute(options, "/hello/world/", false)
|
||||||
testutil.AssertProtoJSONEqual(t, `
|
testutil.AssertProtoJSONEqual(t, `
|
||||||
{
|
{
|
||||||
"name": "pomerium-prefix-/hello/world/",
|
"name": "pomerium-prefix-/hello/world/",
|
||||||
|
@ -255,7 +253,12 @@ func Test_buildControlPlanePrefixRoute(t *testing.T) {
|
||||||
"typedPerFilterConfig": {
|
"typedPerFilterConfig": {
|
||||||
"envoy.filters.http.ext_authz": {
|
"envoy.filters.http.ext_authz": {
|
||||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
"disabled": true
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "true",
|
||||||
|
"route_id": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,6 +304,7 @@ func TestTimeouts(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Path: "/test",
|
Path: "/test",
|
||||||
UpstreamTimeout: getDuration(tc.upstream),
|
UpstreamTimeout: getDuration(tc.upstream),
|
||||||
IdleTimeout: getDuration(tc.idle),
|
IdleTimeout: getDuration(tc.idle),
|
||||||
|
@ -356,14 +360,17 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "https://ignore.example.com",
|
From: "https://ignore.example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Path: "/some/path",
|
Path: "/some/path",
|
||||||
AllowWebsockets: true,
|
AllowWebsockets: true,
|
||||||
PreserveHostHeader: true,
|
PreserveHostHeader: true,
|
||||||
|
@ -371,6 +378,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Prefix: "/some/prefix/",
|
Prefix: "/some/prefix/",
|
||||||
SetRequestHeaders: map[string]string{"HEADER-KEY": "HEADER-VALUE"},
|
SetRequestHeaders: map[string]string{"HEADER-KEY": "HEADER-VALUE"},
|
||||||
UpstreamTimeout: &oneMinute,
|
UpstreamTimeout: &oneMinute,
|
||||||
|
@ -378,11 +386,13 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Regex: `^/[a]+$`,
|
Regex: `^/[a]+$`,
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Prefix: "/some/prefix/",
|
Prefix: "/some/prefix/",
|
||||||
RemoveRequestHeaders: []string{"HEADER-KEY"},
|
RemoveRequestHeaders: []string{"HEADER-KEY"},
|
||||||
UpstreamTimeout: &oneMinute,
|
UpstreamTimeout: &oneMinute,
|
||||||
|
@ -390,6 +400,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Path: "/some/path",
|
Path: "/some/path",
|
||||||
AllowSPDY: true,
|
AllowSPDY: true,
|
||||||
PreserveHostHeader: true,
|
PreserveHostHeader: true,
|
||||||
|
@ -397,6 +408,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Path: "/some/path",
|
Path: "/some/path",
|
||||||
AllowSPDY: true,
|
AllowSPDY: true,
|
||||||
AllowWebsockets: true,
|
AllowWebsockets: true,
|
||||||
|
@ -405,6 +417,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "https://example.com",
|
From: "https://example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
Path: "/websocket-timeout",
|
Path: "/websocket-timeout",
|
||||||
AllowWebsockets: true,
|
AllowWebsockets: true,
|
||||||
PreserveHostHeader: true,
|
PreserveHostHeader: true,
|
||||||
|
@ -474,7 +487,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "11444765232398592404"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-2",
|
"name": "policy-2",
|
||||||
|
@ -534,7 +558,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2990091139764155677"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-3",
|
"name": "policy-3",
|
||||||
|
@ -600,7 +635,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2544588842279234006"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-4",
|
"name": "policy-4",
|
||||||
|
@ -661,7 +707,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "10244970664102670752"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-5",
|
"name": "policy-5",
|
||||||
|
@ -721,7 +778,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2544588842279234006"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-6",
|
"name": "policy-6",
|
||||||
|
@ -780,7 +848,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2990091139764155677"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-7",
|
"name": "policy-7",
|
||||||
|
@ -840,7 +919,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2990091139764155677"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-8",
|
"name": "policy-8",
|
||||||
|
@ -900,7 +990,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "1052418080698022187"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`, routes)
|
`, routes)
|
||||||
|
@ -915,6 +1016,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "https://authenticate.example.com",
|
From: "https://authenticate.example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://authenticate.internal"),
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -997,10 +1099,12 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "tcp+https://example.com:22",
|
From: "tcp+https://example.com:22",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
From: "tcp+https://example.com:22",
|
From: "tcp+https://example.com:22",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
PassIdentityHeaders: true,
|
PassIdentityHeaders: true,
|
||||||
UpstreamTimeout: &ten,
|
UpstreamTimeout: &ten,
|
||||||
},
|
},
|
||||||
|
@ -1069,7 +1173,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2226589900561460978"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-1",
|
"name": "policy-1",
|
||||||
|
@ -1130,7 +1245,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "2226589900561460978"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`, routes)
|
`, routes)
|
||||||
|
@ -1149,6 +1275,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
Policies: []config.Policy{
|
Policies: []config.Policy{
|
||||||
{
|
{
|
||||||
From: "https://from.example.com",
|
From: "https://from.example.com",
|
||||||
|
To: mustParseWeightedURLs(t, "https://to.example.com"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}, nil, "from.example.com")
|
}}, nil, "from.example.com")
|
||||||
|
@ -1216,7 +1343,18 @@ func Test_buildPolicyRoutes(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "15508081512033148378"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`, routes)
|
`, routes)
|
||||||
|
@ -1335,7 +1473,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-1",
|
"name": "policy-1",
|
||||||
|
@ -1395,7 +1544,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-2",
|
"name": "policy-2",
|
||||||
|
@ -1460,7 +1620,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-3",
|
"name": "policy-3",
|
||||||
|
@ -1520,7 +1691,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-4",
|
"name": "policy-4",
|
||||||
|
@ -1580,7 +1762,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "policy-5",
|
"name": "policy-5",
|
||||||
|
@ -1645,7 +1838,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
|
||||||
"value": "1; mode=block"
|
"value": "1; mode=block"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"typedPerFilterConfig": {
|
||||||
|
"envoy.filters.http.ext_authz": {
|
||||||
|
"@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute",
|
||||||
|
"checkSettings": {
|
||||||
|
"contextExtensions": {
|
||||||
|
"internal": "false",
|
||||||
|
"route_id": "285016060542193864"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
`, routes)
|
`, routes)
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"requestTimeout": "30s",
|
"requestTimeout": "30s",
|
||||||
|
"normalizePath": true,
|
||||||
"rds": {
|
"rds": {
|
||||||
"configSource": {
|
"configSource": {
|
||||||
"ads": {},
|
"ads": {},
|
||||||
|
|
|
@ -13,10 +13,6 @@ func (p *Policy) ToPPL() *parser.Policy {
|
||||||
ppl := &parser.Policy{}
|
ppl := &parser.Policy{}
|
||||||
|
|
||||||
allowRule := parser.Rule{Action: parser.ActionAllow}
|
allowRule := parser.Rule{Action: parser.ActionAllow}
|
||||||
allowRule.Or = append(allowRule.Or,
|
|
||||||
parser.Criterion{
|
|
||||||
Name: "pomerium_routes",
|
|
||||||
})
|
|
||||||
if p.AllowPublicUnauthenticatedAccess {
|
if p.AllowPublicUnauthenticatedAccess {
|
||||||
allowRule.Or = append(allowRule.Or,
|
allowRule.Or = append(allowRule.Or,
|
||||||
parser.Criterion{
|
parser.Criterion{
|
||||||
|
|
|
@ -57,24 +57,6 @@ default allow = [false, set()]
|
||||||
|
|
||||||
default deny = [false, set()]
|
default deny = [false, set()]
|
||||||
|
|
||||||
pomerium_routes_0 = [true, {"pomerium-route"}] {
|
|
||||||
session := get_session(input.session.id)
|
|
||||||
session.id != ""
|
|
||||||
contains(input.http.url, "/.pomerium/")
|
|
||||||
}
|
|
||||||
|
|
||||||
else = [true, {"pomerium-route"}] {
|
|
||||||
contains(input.http.url, "/.pomerium/")
|
|
||||||
not contains(input.http.url, "/.pomerium/jwt")
|
|
||||||
not contains(input.http.url, "/.pomerium/webauthn")
|
|
||||||
}
|
|
||||||
|
|
||||||
else = [false, {"user-unauthenticated"}] {
|
|
||||||
contains(input.http.url, "/.pomerium/")
|
|
||||||
}
|
|
||||||
|
|
||||||
else = [false, {"non-pomerium-route"}]
|
|
||||||
|
|
||||||
accept_0 = [true, {"accept"}]
|
accept_0 = [true, {"accept"}]
|
||||||
|
|
||||||
cors_preflight_0 = [true, {"cors-request"}] {
|
cors_preflight_0 = [true, {"cors-request"}] {
|
||||||
|
@ -380,7 +362,7 @@ else = [false, {"email-unauthorized"}] {
|
||||||
else = [false, {"user-unauthenticated"}]
|
else = [false, {"user-unauthenticated"}]
|
||||||
|
|
||||||
or_0 = v {
|
or_0 = v {
|
||||||
results := [pomerium_routes_0, accept_0, cors_preflight_0, authenticated_user_0, domain_0, domain_1, domain_2, domain_3, domain_4, claim_0, claim_1, claim_2, claim_3, user_0, email_0, user_1, email_1, user_2, email_2, user_3, email_3, user_4, email_4]
|
results := [accept_0, cors_preflight_0, authenticated_user_0, domain_0, domain_1, domain_2, domain_3, domain_4, claim_0, claim_1, claim_2, claim_3, user_0, email_0, user_1, email_1, user_2, email_2, user_3, email_3, user_4, email_4]
|
||||||
normalized := [normalize_criterion_result(x) | x := results[i]]
|
normalized := [normalize_criterion_result(x) | x := results[i]]
|
||||||
v := merge_with_or(normalized)
|
v := merge_with_or(normalized)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
package criteria
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/open-policy-agent/opa/ast"
|
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/urlutil"
|
|
||||||
"github.com/pomerium/pomerium/pkg/policy/generator"
|
|
||||||
"github.com/pomerium/pomerium/pkg/policy/parser"
|
|
||||||
"github.com/pomerium/pomerium/pkg/policy/rules"
|
|
||||||
)
|
|
||||||
|
|
||||||
type pomeriumRoutesCriterion struct {
|
|
||||||
g *Generator
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pomeriumRoutesCriterion) DataType() generator.CriterionDataType {
|
|
||||||
return generator.CriterionDataTypeUnused
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pomeriumRoutesCriterion) Name() string {
|
|
||||||
return "pomerium_routes"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c pomeriumRoutesCriterion) GenerateRule(_ string, _ parser.Value) (*ast.Rule, []*ast.Rule, error) {
|
|
||||||
r1 := c.g.NewRule(c.Name())
|
|
||||||
r1.Head.Value = NewCriterionTerm(true, ReasonPomeriumRoute)
|
|
||||||
r1.Body = ast.Body{
|
|
||||||
ast.MustParseExpr(`session := get_session(input.session.id)`),
|
|
||||||
ast.MustParseExpr(`session.id != ""`),
|
|
||||||
ast.MustParseExpr(`contains(input.http.url, "/.pomerium/")`),
|
|
||||||
}
|
|
||||||
|
|
||||||
r2 := c.g.NewRule(c.Name())
|
|
||||||
r2.Head.Value = NewCriterionTerm(true, ReasonPomeriumRoute)
|
|
||||||
r2.Body = ast.Body{
|
|
||||||
ast.MustParseExpr(`contains(input.http.url, "/.pomerium/")`),
|
|
||||||
ast.MustParseExpr(`not contains(input.http.url, "/.pomerium/jwt")`),
|
|
||||||
ast.MustParseExpr(`not contains(input.http.url, "` + urlutil.WebAuthnURLPath + `")`),
|
|
||||||
}
|
|
||||||
r1.Else = r2
|
|
||||||
|
|
||||||
r3 := c.g.NewRule(c.Name())
|
|
||||||
r3.Head.Value = NewCriterionTerm(false, ReasonUserUnauthenticated)
|
|
||||||
r3.Body = ast.Body{
|
|
||||||
ast.MustParseExpr(`contains(input.http.url, "/.pomerium/")`),
|
|
||||||
}
|
|
||||||
r2.Else = r3
|
|
||||||
|
|
||||||
r4 := c.g.NewRule(c.Name())
|
|
||||||
r4.Head.Value = NewCriterionTerm(false, ReasonNonPomeriumRoute)
|
|
||||||
r3.Else = r4
|
|
||||||
|
|
||||||
return r1, []*ast.Rule{
|
|
||||||
rules.GetSession(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PomeriumRoutes returns a Criterion on that allows access to pomerium routes.
|
|
||||||
func PomeriumRoutes(generator *Generator) Criterion {
|
|
||||||
return pomeriumRoutesCriterion{g: generator}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
Register(PomeriumRoutes)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue