diff --git a/authorize/evaluator/evaluator.go b/authorize/evaluator/evaluator.go index 0b1c313a3..454026f2b 100644 --- a/authorize/evaluator/evaluator.go +++ b/authorize/evaluator/evaluator.go @@ -22,17 +22,12 @@ import ( "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. type Request struct { - Policy *config.Policy - HTTP RequestHTTP - Session RequestSession + IsInternal bool + Policy *config.Policy + HTTP RequestHTTP + Session RequestSession } // RequestHTTP is the HTTP field in the request. @@ -125,8 +120,60 @@ func (e *Evaluator) Evaluate(ctx context.Context, req *Request) (*Result, error) ctx, span := trace.StartSpan(ctx, "authorize.Evaluator.Evaluate") 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 { - return notFoundOutput, nil + return &PolicyResponse{ + Deny: NewRuleResult(true, criteria.ReasonRouteNotFound), + }, nil } 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] if !ok { - return notFoundOutput, nil + return &PolicyResponse{ + Deny: NewRuleResult(true, criteria.ReasonRouteNotFound), + }, nil } 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) } - eg, ectx := errgroup.WithContext(ctx) - - var policyOutput *PolicyResponse - eg.Go(func() error { - var err error - policyOutput, err = policyEvaluator.Evaluate(ectx, &PolicyRequest{ - HTTP: req.HTTP, - Session: req.Session, - IsValidClientCertificate: isValidClientCertificate, - }) - return err + return policyEvaluator.Evaluate(ctx, &PolicyRequest{ + HTTP: req.HTTP, + Session: req.Session, + IsValidClientCertificate: isValidClientCertificate, }) +} - var headersOutput *HeadersResponse - eg.Go(func() error { - headersReq := NewHeadersRequestFromPolicy(req.Policy, req.HTTP.Hostname) - headersReq.Session = req.Session - var err error - headersOutput, err = e.headersEvaluators.Evaluate(ectx, headersReq) - return err - }) - - err = eg.Wait() +func (e *Evaluator) evaluateHeaders(ctx context.Context, req *Request) (*HeadersResponse, error) { + headersReq := NewHeadersRequestFromPolicy(req.Policy, req.HTTP.Hostname) + headersReq.Session = req.Session + res, err := e.headersEvaluators.Evaluate(ctx, headersReq) if err != nil { 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 } diff --git a/authorize/evaluator/headers_evaluator.go b/authorize/evaluator/headers_evaluator.go index 4b16a8455..f86a9a289 100644 --- a/authorize/evaluator/headers_evaluator.go +++ b/authorize/evaluator/headers_evaluator.go @@ -30,16 +30,18 @@ type HeadersRequest struct { // NewHeadersRequestFromPolicy creates a new HeadersRequest from a policy. func NewHeadersRequestFromPolicy(policy *config.Policy, hostname string) *HeadersRequest { input := new(HeadersRequest) - input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication - input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH || - policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_MAGLEV - input.Issuer = hostname - input.KubernetesServiceAccountToken = policy.KubernetesServiceAccountToken - for _, wu := range policy.To { - input.ToAudience = "https://" + wu.URL.Hostname() + if policy != nil { + input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication + input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH || + policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_MAGLEV + input.Issuer = hostname + input.KubernetesServiceAccountToken = policy.KubernetesServiceAccountToken + for _, wu := range policy.To { + input.ToAudience = "https://" + wu.URL.Hostname() + } + input.PassAccessToken = policy.GetSetAuthorizationHeader() == configpb.Route_ACCESS_TOKEN + input.PassIDToken = policy.GetSetAuthorizationHeader() == configpb.Route_ID_TOKEN } - input.PassAccessToken = policy.GetSetAuthorizationHeader() == configpb.Route_ACCESS_TOKEN - input.PassIDToken = policy.GetSetAuthorizationHeader() == configpb.Route_ID_TOKEN return input } diff --git a/authorize/evaluator/policy_evaluator_test.go b/authorize/evaluator/policy_evaluator_test.go index 386184c14..7893464bd 100644 --- a/authorize/evaluator/policy_evaluator_test.go +++ b/authorize/evaluator/policy_evaluator_test.go @@ -111,7 +111,7 @@ func TestPolicyEvaluator(t *testing.T) { }) require.NoError(t, err) 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), Traces: []contextutil.PolicyEvaluationTrace{{}}, }, output) @@ -172,7 +172,7 @@ func TestPolicyEvaluator(t *testing.T) { }) require.NoError(t, err) assert.Equal(t, &PolicyResponse{ - Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute), + Allow: NewRuleResult(false), Deny: NewRuleResult(true, criteria.ReasonAccept), Traces: []contextutil.PolicyEvaluationTrace{{}, {ID: "p1", Deny: true}}, }, output) @@ -203,7 +203,7 @@ func TestPolicyEvaluator(t *testing.T) { }) require.NoError(t, err) assert.Equal(t, &PolicyResponse{ - Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute), + Allow: NewRuleResult(false), Deny: NewRuleResult(true, criteria.ReasonAccept, criteria.ReasonInvalidClientCertificate), Traces: []contextutil.PolicyEvaluationTrace{{Deny: true}, {ID: "p1", Deny: true}}, }, output) @@ -289,7 +289,7 @@ func TestPolicyEvaluator(t *testing.T) { }) require.NoError(t, err) assert.Equal(t, &PolicyResponse{ - Allow: NewRuleResult(false, criteria.ReasonNonPomeriumRoute, criteria.ReasonUserUnauthenticated), + Allow: NewRuleResult(false, criteria.ReasonUserUnauthenticated), Deny: NewRuleResult(false, criteria.ReasonValidClientCertificateOrNoneRequired), Traces: []contextutil.PolicyEvaluationTrace{{Allow: false}}, }, output) diff --git a/authorize/grpc.go b/authorize/grpc.go index 2496ef84a..d18cc3654 100644 --- a/authorize/grpc.go +++ b/authorize/grpc.go @@ -11,6 +11,7 @@ import ( "github.com/pomerium/pomerium/authorize/evaluator" "github.com/pomerium/pomerium/config" + "github.com/pomerium/pomerium/config/envoyconfig" "github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/sessions" "github.com/pomerium/pomerium/internal/telemetry/requestid" @@ -93,6 +94,7 @@ func (a *Authorize) getEvaluatorRequestFromCheckRequest( ) (*evaluator.Request, error) { requestURL := getCheckRequestURL(in) req := &evaluator.Request{ + IsInternal: envoyconfig.ExtAuthzContextExtensionsIsInternal(in.GetAttributes().GetContextExtensions()), HTTP: evaluator.NewRequestHTTP( in.GetAttributes().GetRequest().GetHttp().GetMethod(), requestURL, @@ -106,15 +108,16 @@ func (a *Authorize) getEvaluatorRequestFromCheckRequest( ID: sessionState.ID, } } - req.Policy = a.getMatchingPolicy(requestURL) + req.Policy = a.getMatchingPolicy(envoyconfig.ExtAuthzContextExtensionsRouteID(in.Attributes.GetContextExtensions())) return req, nil } -func (a *Authorize) getMatchingPolicy(requestURL url.URL) *config.Policy { +func (a *Authorize) getMatchingPolicy(routeID uint64) *config.Policy { options := a.currentOptions.Load() for _, p := range options.GetAllPolicies() { - if p.Matches(requestURL) { + id, _ := p.RouteID() + if id == routeID { return &p } } @@ -159,6 +162,7 @@ func getCheckRequestURL(req *envoy_service_auth_v3.CheckRequest) url.URL { path := h.GetPath() if idx := strings.Index(path, "?"); idx != -1 { u.RawPath, u.RawQuery = path[:idx], path[idx+1:] + u.RawQuery = u.Query().Encode() } else { u.RawPath = path } diff --git a/config/envoyconfig/listeners.go b/config/envoyconfig/listeners.go index aa8e42138..b8c5005e9 100644 --- a/config/envoyconfig/listeners.go +++ b/config/envoyconfig/listeners.go @@ -13,11 +13,9 @@ import ( 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_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_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" - "github.com/golang/protobuf/ptypes/any" "github.com/golang/protobuf/ptypes/wrappers" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/wrapperspb" @@ -32,27 +30,16 @@ import ( const listenerBufferLimit uint32 = 32 * 1024 -var ( - disableExtAuthz *any.Any - tlsParams = &envoy_extensions_transport_sockets_tls_v3.TlsParameters{ - CipherSuites: []string{ - "ECDHE-ECDSA-AES256-GCM-SHA384", - "ECDHE-RSA-AES256-GCM-SHA384", - "ECDHE-ECDSA-AES128-GCM-SHA256", - "ECDHE-RSA-AES128-GCM-SHA256", - "ECDHE-ECDSA-CHACHA20-POLY1305", - "ECDHE-RSA-CHACHA20-POLY1305", - }, - 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, - }, - }) +var tlsParams = &envoy_extensions_transport_sockets_tls_v3.TlsParameters{ + CipherSuites: []string{ + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-RSA-CHACHA20-POLY1305", + }, + TlsMinimumProtocolVersion: envoy_extensions_transport_sockets_tls_v3.TlsParameters_TLSv1_2, } // BuildListeners builds envoy listeners from the given config. @@ -312,6 +299,7 @@ func (b *Builder) buildMainHTTPConnectionManagerFilter( SkipXffAppend: cfg.Options.SkipXffAppend, XffNumTrustedHops: cfg.Options.XffNumTrustedHops, LocalReplyConfig: b.buildLocalReplyConfig(cfg.Options, false), + NormalizePath: wrapperspb.Bool(true), } if fullyStatic { diff --git a/config/envoyconfig/per_filter_config.go b/config/envoyconfig/per_filter_config.go new file mode 100644 index 000000000..02fc65eaa --- /dev/null +++ b/config/envoyconfig/per_filter_config.go @@ -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 +} diff --git a/config/envoyconfig/route_configurations_test.go b/config/envoyconfig/route_configurations_test.go index e91f561b5..b0b2f475b 100644 --- a/config/envoyconfig/route_configurations_test.go +++ b/config/envoyconfig/route_configurations_test.go @@ -26,6 +26,7 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) { Policies: []config.Policy{ { From: "https://*.example.com", + To: mustParseWeightedURLs(t, "https://www.example.com"), }, }, }} @@ -40,15 +41,13 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) { "name": "catch-all", "domains": ["*"], "routes": [ - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium/jwt", true, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium/webauthn", true, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/ping", false, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/healthz", false, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium", false, false))+`, - `+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.pomerium/", false, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.well-known/pomerium", false, false))+`, - `+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.well-known/pomerium/", false, false))+`, - `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/robots.txt", false, false))+`, + `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/ping", false))+`, + `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/healthz", false))+`, + `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.pomerium", false))+`, + `+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.pomerium/", false))+`, + `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/.well-known/pomerium", false))+`, + `+protojson.Format(b.buildControlPlanePrefixRoute(cfg.Options, "/.well-known/pomerium/", false))+`, + `+protojson.Format(b.buildControlPlanePathRoute(cfg.Options, "/robots.txt", false))+`, { "name": "policy-0", "match": { @@ -79,7 +78,7 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) { ], "route": { "autoHostRewrite": true, - "cluster": "route-0", + "cluster": "route-5feb9fe8bd89aa97", "hashPolicy": [ { "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true }, { "connectionProperties": { "sourceIp": true }, "terminal": true } @@ -89,6 +88,17 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) { { "enabled": false, "upgradeType": "websocket" }, { "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": { "autoHostRewrite": true, - "cluster": "route-0", + "cluster": "route-5feb9fe8bd89aa97", "hashPolicy": [ { "header": { "headerName": "x-pomerium-routing-key" }, "terminal": true }, { "connectionProperties": { "sourceIp": true }, "terminal": true } @@ -131,6 +141,17 @@ func TestBuilder_buildMainRouteConfiguration(t *testing.T) { { "enabled": false, "upgradeType": "websocket" }, { "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" + } + } + } } } ] diff --git a/config/envoyconfig/routes.go b/config/envoyconfig/routes.go index 900d840f0..28a1c7013 100644 --- a/config/envoyconfig/routes.go +++ b/config/envoyconfig/routes.go @@ -45,7 +45,7 @@ func (b *Builder) buildGRPCRoutes() ([]*envoy_config_route_v3.Route, error) { }, Action: action, TypedPerFilterConfig: map[string]*any.Any{ - "envoy.filters.http.ext_authz": disableExtAuthz, + PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzDisabled(), }, }}, nil } @@ -65,20 +65,16 @@ func (b *Builder) buildPomeriumHTTPRoutes( } if !isFrontingAuthenticate { routes = append(routes, - // enable ext_authz - b.buildControlPlanePathRoute(options, "/.pomerium/jwt", true, requireStrictTransportSecurity), - b.buildControlPlanePathRoute(options, urlutil.WebAuthnURLPath, true, requireStrictTransportSecurity), - // disable ext_authz and passthrough to proxy handlers - b.buildControlPlanePathRoute(options, "/ping", false, requireStrictTransportSecurity), - b.buildControlPlanePathRoute(options, "/healthz", false, 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), + b.buildControlPlanePathRoute(options, "/ping", requireStrictTransportSecurity), + b.buildControlPlanePathRoute(options, "/healthz", requireStrictTransportSecurity), + b.buildControlPlanePathRoute(options, "/.pomerium", requireStrictTransportSecurity), + b.buildControlPlanePrefixRoute(options, "/.pomerium/", requireStrictTransportSecurity), + b.buildControlPlanePathRoute(options, "/.well-known/pomerium", requireStrictTransportSecurity), + b.buildControlPlanePrefixRoute(options, "/.well-known/pomerium/", requireStrictTransportSecurity), ) // per #837, only add robots.txt if there are no unauthenticated routes 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) { return []*envoy_config_route_v3.Route{ - b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, false, requireStrictTransportSecurity), - b.buildControlPlanePathRoute(options, "/", false, requireStrictTransportSecurity), + b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, requireStrictTransportSecurity), + b.buildControlPlanePathRoute(options, "/", requireStrictTransportSecurity), }, nil } } @@ -120,7 +116,6 @@ func (b *Builder) buildPomeriumAuthenticateHTTPRoutes( func (b *Builder) buildControlPlanePathRoute( options *config.Options, path string, - protected bool, requireStrictTransportSecurity bool, ) *envoy_config_route_v3.Route { r := &envoy_config_route_v3.Route{ @@ -136,11 +131,9 @@ func (b *Builder) buildControlPlanePathRoute( }, }, ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)), - } - if !protected { - r.TypedPerFilterConfig = map[string]*any.Any{ - "envoy.filters.http.ext_authz": disableExtAuthz, - } + TypedPerFilterConfig: map[string]*any.Any{ + PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(true, 0)), + }, } return r } @@ -148,7 +141,6 @@ func (b *Builder) buildControlPlanePathRoute( func (b *Builder) buildControlPlanePrefixRoute( options *config.Options, prefix string, - protected bool, requireStrictTransportSecurity bool, ) *envoy_config_route_v3.Route { r := &envoy_config_route_v3.Route{ @@ -164,11 +156,9 @@ func (b *Builder) buildControlPlanePrefixRoute( }, }, ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)), - } - if !protected { - r.TypedPerFilterConfig = map[string]*any.Any{ - "envoy.filters.http.ext_authz": disableExtAuthz, - } + TypedPerFilterConfig: map[string]*any.Any{ + PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(true, 0)), + }, } return r } @@ -288,6 +278,11 @@ func (b *Builder) buildRouteForPolicyAndMatch( return nil, err } + routeID, err := policy.RouteID() + if err != nil { + return nil, err + } + requireStrictTransportSecurity := cryptutil.HasCertificateForServerName(certs, fromURL.Hostname()) route := &envoy_config_route_v3.Route{ @@ -323,9 +318,12 @@ func (b *Builder) buildRouteForPolicyAndMatch( } if isFrontingAuthenticate { route.TypedPerFilterConfig = map[string]*any.Any{ - "envoy.filters.http.ext_authz": disableExtAuthz, + PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzDisabled(), } } else { + route.TypedPerFilterConfig = map[string]*any.Any{ + PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(false, routeID)), + } luaMetadata["remove_pomerium_cookie"] = &structpb.Value{ Kind: &structpb.Value_StringValue{ StringValue: cfg.Options.CookieName, @@ -344,8 +342,7 @@ func (b *Builder) buildRouteForPolicyAndMatch( } if policy.IsForKubernetes() { - policyID, _ := policy.RouteID() - for _, hdr := range b.reproxy.GetPolicyIDHeaders(policyID) { + for _, hdr := range b.reproxy.GetPolicyIDHeaders(routeID) { route.RequestHeadersToAdd = append(route.RequestHeadersToAdd, &envoy_config_core_v3.HeaderValueOption{ Header: &envoy_config_core_v3.HeaderValue{ diff --git a/config/envoyconfig/routes_test.go b/config/envoyconfig/routes_test.go index 6b8e4a457..28e68bce9 100644 --- a/config/envoyconfig/routes_test.go +++ b/config/envoyconfig/routes_test.go @@ -16,7 +16,6 @@ import ( "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/config/envoyconfig/filemgr" "github.com/pomerium/pomerium/internal/testutil" - "github.com/pomerium/pomerium/internal/urlutil" "github.com/pomerium/pomerium/pkg/cryptutil" ) @@ -56,43 +55,43 @@ func Test_buildGRPCRoutes(t *testing.T) { func Test_buildPomeriumHTTPRoutes(t *testing.T) { b := &Builder{filemgr: filemgr.NewManager()} - routeString := func(typ, name string, protected bool) string { + routeString := func(typ, name string) string { str := `{ - "name": "pomerium-` + typ + `-` + name + `", - "match": { - "` + typ + `": "` + name + `" + "name": "pomerium-` + typ + `-` + name + `", + "match": { + "` + typ + `": "` + name + `" + }, + "responseHeadersToAdd": [ + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "X-Frame-Options", + "value": "SAMEORIGIN" + } }, - "responseHeadersToAdd": [ - { - "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", - "header": { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - } - }, - { - "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", - "header": { - "key": "X-XSS-Protection", - "value": "1; mode=block" - } - } - ], - "route": { - "cluster": "pomerium-control-plane-http" - } - ` - if !protected { - str += `, - "typedPerFilterConfig": { - "envoy.filters.http.ext_authz": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute", - "disabled": true + { + "appendAction": "OVERWRITE_IF_EXISTS_OR_ADD", + "header": { + "key": "X-XSS-Protection", + "value": "1; mode=block" } } - ` - } - str += "}" + ], + "route": { + "cluster": "pomerium-control-plane-http" + }, + "typedPerFilterConfig": { + "envoy.filters.http.ext_authz": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute", + "checkSettings": { + "contextExtensions": { + "internal": "true", + "route_id": "0" + } + } + } + } + }` return str } t.Run("authenticate", func(t *testing.T) { @@ -105,17 +104,15 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) { require.NoError(t, err) testutil.AssertProtoJSONEqual(t, `[ - `+routeString("path", "/.pomerium/jwt", true)+`, - `+routeString("path", urlutil.WebAuthnURLPath, true)+`, - `+routeString("path", "/ping", false)+`, - `+routeString("path", "/healthz", false)+`, - `+routeString("path", "/.pomerium", false)+`, - `+routeString("prefix", "/.pomerium/", false)+`, - `+routeString("path", "/.well-known/pomerium", false)+`, - `+routeString("prefix", "/.well-known/pomerium/", false)+`, - `+routeString("path", "/robots.txt", false)+`, - `+routeString("path", "/oauth2/callback", false)+`, - `+routeString("path", "/", false)+` + `+routeString("path", "/ping")+`, + `+routeString("path", "/healthz")+`, + `+routeString("path", "/.pomerium")+`, + `+routeString("prefix", "/.pomerium/")+`, + `+routeString("path", "/.well-known/pomerium")+`, + `+routeString("prefix", "/.well-known/pomerium/")+`, + `+routeString("path", "/robots.txt")+`, + `+routeString("path", "/oauth2/callback")+`, + `+routeString("path", "/")+` ]`, routes) }) t.Run("proxy fronting authenticate", func(t *testing.T) { @@ -144,15 +141,13 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) { require.NoError(t, err) testutil.AssertProtoJSONEqual(t, `[ - `+routeString("path", "/.pomerium/jwt", true)+`, - `+routeString("path", urlutil.WebAuthnURLPath, true)+`, - `+routeString("path", "/ping", false)+`, - `+routeString("path", "/healthz", false)+`, - `+routeString("path", "/.pomerium", false)+`, - `+routeString("prefix", "/.pomerium/", false)+`, - `+routeString("path", "/.well-known/pomerium", false)+`, - `+routeString("prefix", "/.well-known/pomerium/", false)+`, - `+routeString("path", "/robots.txt", false)+` + `+routeString("path", "/ping")+`, + `+routeString("path", "/healthz")+`, + `+routeString("path", "/.pomerium")+`, + `+routeString("prefix", "/.pomerium/")+`, + `+routeString("path", "/.well-known/pomerium")+`, + `+routeString("prefix", "/.well-known/pomerium/")+`, + `+routeString("path", "/robots.txt")+` ]`, routes) }) @@ -172,14 +167,12 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) { require.NoError(t, err) testutil.AssertProtoJSONEqual(t, `[ - `+routeString("path", "/.pomerium/jwt", true)+`, - `+routeString("path", urlutil.WebAuthnURLPath, true)+`, - `+routeString("path", "/ping", false)+`, - `+routeString("path", "/healthz", false)+`, - `+routeString("path", "/.pomerium", false)+`, - `+routeString("prefix", "/.pomerium/", false)+`, - `+routeString("path", "/.well-known/pomerium", false)+`, - `+routeString("prefix", "/.well-known/pomerium/", false)+` + `+routeString("path", "/ping")+`, + `+routeString("path", "/healthz")+`, + `+routeString("path", "/.pomerium")+`, + `+routeString("prefix", "/.pomerium/")+`, + `+routeString("path", "/.well-known/pomerium")+`, + `+routeString("prefix", "/.well-known/pomerium/")+` ]`, routes) }) } @@ -187,7 +180,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) { func Test_buildControlPlanePathRoute(t *testing.T) { options := config.NewDefaultOptions() b := &Builder{filemgr: filemgr.NewManager()} - route := b.buildControlPlanePathRoute(options, "/hello/world", false, false) + route := b.buildControlPlanePathRoute(options, "/hello/world", false) testutil.AssertProtoJSONEqual(t, ` { "name": "pomerium-path-/hello/world", @@ -216,7 +209,12 @@ func Test_buildControlPlanePathRoute(t *testing.T) { "typedPerFilterConfig": { "envoy.filters.http.ext_authz": { "@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) { options := config.NewDefaultOptions() b := &Builder{filemgr: filemgr.NewManager()} - route := b.buildControlPlanePrefixRoute(options, "/hello/world/", false, false) + route := b.buildControlPlanePrefixRoute(options, "/hello/world/", false) testutil.AssertProtoJSONEqual(t, ` { "name": "pomerium-prefix-/hello/world/", @@ -255,7 +253,12 @@ func Test_buildControlPlanePrefixRoute(t *testing.T) { "typedPerFilterConfig": { "envoy.filters.http.ext_authz": { "@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{ { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Path: "/test", UpstreamTimeout: getDuration(tc.upstream), IdleTimeout: getDuration(tc.idle), @@ -356,14 +360,17 @@ func Test_buildPolicyRoutes(t *testing.T) { Policies: []config.Policy{ { From: "https://ignore.example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), PassIdentityHeaders: true, }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), PassIdentityHeaders: true, }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Path: "/some/path", AllowWebsockets: true, PreserveHostHeader: true, @@ -371,6 +378,7 @@ func Test_buildPolicyRoutes(t *testing.T) { }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Prefix: "/some/prefix/", SetRequestHeaders: map[string]string{"HEADER-KEY": "HEADER-VALUE"}, UpstreamTimeout: &oneMinute, @@ -378,11 +386,13 @@ func Test_buildPolicyRoutes(t *testing.T) { }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Regex: `^/[a]+$`, PassIdentityHeaders: true, }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Prefix: "/some/prefix/", RemoveRequestHeaders: []string{"HEADER-KEY"}, UpstreamTimeout: &oneMinute, @@ -390,6 +400,7 @@ func Test_buildPolicyRoutes(t *testing.T) { }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Path: "/some/path", AllowSPDY: true, PreserveHostHeader: true, @@ -397,6 +408,7 @@ func Test_buildPolicyRoutes(t *testing.T) { }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Path: "/some/path", AllowSPDY: true, AllowWebsockets: true, @@ -405,6 +417,7 @@ func Test_buildPolicyRoutes(t *testing.T) { }, { From: "https://example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), Path: "/websocket-timeout", AllowWebsockets: true, PreserveHostHeader: true, @@ -474,7 +487,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -534,7 +558,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -600,7 +635,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -661,7 +707,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -721,7 +778,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -780,7 +848,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -840,7 +919,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -900,7 +990,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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) @@ -915,6 +1016,7 @@ func Test_buildPolicyRoutes(t *testing.T) { Policies: []config.Policy{ { From: "https://authenticate.example.com", + To: mustParseWeightedURLs(t, "https://authenticate.internal"), PassIdentityHeaders: true, }, }, @@ -997,10 +1099,12 @@ func Test_buildPolicyRoutes(t *testing.T) { Policies: []config.Policy{ { From: "tcp+https://example.com:22", + To: mustParseWeightedURLs(t, "https://to.example.com"), PassIdentityHeaders: true, }, { From: "tcp+https://example.com:22", + To: mustParseWeightedURLs(t, "https://to.example.com"), PassIdentityHeaders: true, UpstreamTimeout: &ten, }, @@ -1069,7 +1173,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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", @@ -1130,7 +1245,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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) @@ -1149,6 +1275,7 @@ func Test_buildPolicyRoutes(t *testing.T) { Policies: []config.Policy{ { From: "https://from.example.com", + To: mustParseWeightedURLs(t, "https://to.example.com"), }, }, }}, nil, "from.example.com") @@ -1216,7 +1343,18 @@ func Test_buildPolicyRoutes(t *testing.T) { "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) @@ -1335,7 +1473,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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", @@ -1395,7 +1544,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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", @@ -1460,7 +1620,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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", @@ -1520,7 +1691,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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", @@ -1580,7 +1762,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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", @@ -1645,7 +1838,18 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "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) diff --git a/config/envoyconfig/testdata/main_http_connection_manager_filter.json b/config/envoyconfig/testdata/main_http_connection_manager_filter.json index 661b36b1d..097eb957d 100644 --- a/config/envoyconfig/testdata/main_http_connection_manager_filter.json +++ b/config/envoyconfig/testdata/main_http_connection_manager_filter.json @@ -120,6 +120,7 @@ ] }, "requestTimeout": "30s", + "normalizePath": true, "rds": { "configSource": { "ads": {}, diff --git a/config/policy_ppl.go b/config/policy_ppl.go index 200019092..e791e626e 100644 --- a/config/policy_ppl.go +++ b/config/policy_ppl.go @@ -13,10 +13,6 @@ func (p *Policy) ToPPL() *parser.Policy { ppl := &parser.Policy{} allowRule := parser.Rule{Action: parser.ActionAllow} - allowRule.Or = append(allowRule.Or, - parser.Criterion{ - Name: "pomerium_routes", - }) if p.AllowPublicUnauthenticatedAccess { allowRule.Or = append(allowRule.Or, parser.Criterion{ diff --git a/config/policy_ppl_test.go b/config/policy_ppl_test.go index 9c9d99549..38d876a89 100644 --- a/config/policy_ppl_test.go +++ b/config/policy_ppl_test.go @@ -57,24 +57,6 @@ default allow = [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"}] cors_preflight_0 = [true, {"cors-request"}] { @@ -380,7 +362,7 @@ else = [false, {"email-unauthorized"}] { else = [false, {"user-unauthenticated"}] 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]] v := merge_with_or(normalized) } diff --git a/pkg/policy/criteria/pomerium_routes.go b/pkg/policy/criteria/pomerium_routes.go deleted file mode 100644 index a1b6d6edd..000000000 --- a/pkg/policy/criteria/pomerium_routes.go +++ /dev/null @@ -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) -}