mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 18:06:34 +02:00
* remove source, remove deadcode, fix linting issues * use github action for lint * fix missing envoy
574 lines
18 KiB
Go
574 lines
18 KiB
Go
package envoyconfig
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"sort"
|
|
|
|
envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
|
|
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
|
envoy_type_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/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/structpb"
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
|
|
"github.com/pomerium/pomerium/config"
|
|
"github.com/pomerium/pomerium/internal/httputil"
|
|
"github.com/pomerium/pomerium/internal/urlutil"
|
|
)
|
|
|
|
const (
|
|
httpCluster = "pomerium-control-plane-http"
|
|
)
|
|
|
|
func (b *Builder) buildGRPCRoutes() ([]*envoy_config_route_v3.Route, error) {
|
|
action := &envoy_config_route_v3.Route_Route{
|
|
Route: &envoy_config_route_v3.RouteAction{
|
|
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
|
Cluster: "pomerium-control-plane-grpc",
|
|
},
|
|
},
|
|
}
|
|
return []*envoy_config_route_v3.Route{{
|
|
Name: "pomerium-grpc",
|
|
Match: &envoy_config_route_v3.RouteMatch{
|
|
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{
|
|
Prefix: "/",
|
|
},
|
|
Grpc: &envoy_config_route_v3.RouteMatch_GrpcRouteMatchOptions{},
|
|
},
|
|
Action: action,
|
|
TypedPerFilterConfig: map[string]*any.Any{
|
|
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
},
|
|
}}, nil
|
|
}
|
|
|
|
func (b *Builder) buildPomeriumHTTPRoutes(
|
|
options *config.Options,
|
|
host string,
|
|
requireStrictTransportSecurity bool,
|
|
) ([]*envoy_config_route_v3.Route, error) {
|
|
var routes []*envoy_config_route_v3.Route
|
|
|
|
// if this is the pomerium proxy in front of the the authenticate service, don't add
|
|
// these routes since they will be handled by authenticate
|
|
isFrontingAuthenticate, err := isProxyFrontingAuthenticate(options, host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
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),
|
|
)
|
|
// 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))
|
|
}
|
|
}
|
|
|
|
authRoutes, err := b.buildPomeriumAuthenticateHTTPRoutes(options, host, requireStrictTransportSecurity)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
routes = append(routes, authRoutes...)
|
|
return routes, nil
|
|
}
|
|
|
|
func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(
|
|
options *config.Options,
|
|
host string,
|
|
requireStrictTransportSecurity bool,
|
|
) ([]*envoy_config_route_v3.Route, error) {
|
|
if !config.IsAuthenticate(options.Services) {
|
|
return nil, nil
|
|
}
|
|
|
|
for _, fn := range []func() (*url.URL, error){
|
|
options.GetAuthenticateURL,
|
|
options.GetInternalAuthenticateURL,
|
|
} {
|
|
u, err := fn()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if urlMatchesHost(u, host) {
|
|
return []*envoy_config_route_v3.Route{
|
|
b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, false, requireStrictTransportSecurity),
|
|
b.buildControlPlanePathRoute(options, "/", false, requireStrictTransportSecurity),
|
|
}, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (b *Builder) buildControlPlanePathRoute(
|
|
options *config.Options,
|
|
path string,
|
|
protected bool,
|
|
requireStrictTransportSecurity bool,
|
|
) *envoy_config_route_v3.Route {
|
|
r := &envoy_config_route_v3.Route{
|
|
Name: "pomerium-path-" + path,
|
|
Match: &envoy_config_route_v3.RouteMatch{
|
|
PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{Path: path},
|
|
},
|
|
Action: &envoy_config_route_v3.Route_Route{
|
|
Route: &envoy_config_route_v3.RouteAction{
|
|
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
|
Cluster: httpCluster,
|
|
},
|
|
},
|
|
},
|
|
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
|
}
|
|
if !protected {
|
|
r.TypedPerFilterConfig = map[string]*any.Any{
|
|
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (b *Builder) buildControlPlanePrefixRoute(
|
|
options *config.Options,
|
|
prefix string,
|
|
protected bool,
|
|
requireStrictTransportSecurity bool,
|
|
) *envoy_config_route_v3.Route {
|
|
r := &envoy_config_route_v3.Route{
|
|
Name: "pomerium-prefix-" + prefix,
|
|
Match: &envoy_config_route_v3.RouteMatch{
|
|
PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{Prefix: prefix},
|
|
},
|
|
Action: &envoy_config_route_v3.Route_Route{
|
|
Route: &envoy_config_route_v3.RouteAction{
|
|
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
|
Cluster: httpCluster,
|
|
},
|
|
},
|
|
},
|
|
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
|
|
}
|
|
if !protected {
|
|
r.TypedPerFilterConfig = map[string]*any.Any{
|
|
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
// getClusterID returns a cluster ID
|
|
var getClusterID = func(policy *config.Policy) string {
|
|
prefix := getClusterStatsName(policy)
|
|
if prefix == "" {
|
|
prefix = "route"
|
|
}
|
|
|
|
id, _ := policy.RouteID()
|
|
return fmt.Sprintf("%s-%x", prefix, id)
|
|
}
|
|
|
|
// getClusterStatsName returns human readable name that would be used by envoy to emit statistics, available as envoy_cluster_name label
|
|
func getClusterStatsName(policy *config.Policy) string {
|
|
if policy.EnvoyOpts != nil && policy.EnvoyOpts.Name != "" {
|
|
return policy.EnvoyOpts.Name
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (b *Builder) buildPolicyRoutes(
|
|
options *config.Options,
|
|
host string,
|
|
requireStrictTransportSecurity bool,
|
|
) ([]*envoy_config_route_v3.Route, error) {
|
|
var routes []*envoy_config_route_v3.Route
|
|
|
|
for i, p := range options.GetAllPolicies() {
|
|
policy := p
|
|
fromURL, err := urlutil.ParseAndValidateURL(policy.From)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !urlMatchesHost(fromURL, host) {
|
|
continue
|
|
}
|
|
|
|
match := mkRouteMatch(&policy)
|
|
envoyRoute := &envoy_config_route_v3.Route{
|
|
Name: fmt.Sprintf("policy-%d", i),
|
|
Match: match,
|
|
Metadata: &envoy_config_core_v3.Metadata{},
|
|
RequestHeadersToAdd: toEnvoyHeaders(policy.SetRequestHeaders),
|
|
RequestHeadersToRemove: getRequestHeadersToRemove(options, &policy),
|
|
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeadersForPolicy(&policy, requireStrictTransportSecurity)),
|
|
}
|
|
if policy.Redirect != nil {
|
|
action, err := b.buildPolicyRouteRedirectAction(policy.Redirect)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
envoyRoute.Action = &envoy_config_route_v3.Route_Redirect{Redirect: action}
|
|
} else {
|
|
action, err := b.buildPolicyRouteRouteAction(options, &policy)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
envoyRoute.Action = &envoy_config_route_v3.Route_Route{Route: action}
|
|
}
|
|
|
|
luaMetadata := map[string]*structpb.Value{
|
|
"rewrite_response_headers": getRewriteHeadersMetadata(policy.RewriteResponseHeaders),
|
|
}
|
|
|
|
// disable authentication entirely when the proxy is fronting authenticate
|
|
isFrontingAuthenticate, err := isProxyFrontingAuthenticate(options, host)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if isFrontingAuthenticate {
|
|
envoyRoute.TypedPerFilterConfig = map[string]*any.Any{
|
|
"envoy.filters.http.ext_authz": disableExtAuthz,
|
|
}
|
|
} else {
|
|
luaMetadata["remove_pomerium_cookie"] = &structpb.Value{
|
|
Kind: &structpb.Value_StringValue{
|
|
StringValue: options.CookieName,
|
|
},
|
|
}
|
|
luaMetadata["remove_pomerium_authorization"] = &structpb.Value{
|
|
Kind: &structpb.Value_BoolValue{
|
|
BoolValue: true,
|
|
},
|
|
}
|
|
luaMetadata["remove_impersonate_headers"] = &structpb.Value{
|
|
Kind: &structpb.Value_BoolValue{
|
|
BoolValue: policy.IsForKubernetes(),
|
|
},
|
|
}
|
|
}
|
|
|
|
if policy.IsForKubernetes() {
|
|
policyID, _ := policy.RouteID()
|
|
for _, hdr := range b.reproxy.GetPolicyIDHeaders(policyID) {
|
|
envoyRoute.RequestHeadersToAdd = append(envoyRoute.RequestHeadersToAdd,
|
|
&envoy_config_core_v3.HeaderValueOption{
|
|
Header: &envoy_config_core_v3.HeaderValue{
|
|
Key: hdr[0],
|
|
Value: hdr[1],
|
|
},
|
|
AppendAction: envoy_config_core_v3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
|
})
|
|
}
|
|
}
|
|
|
|
envoyRoute.Metadata.FilterMetadata = map[string]*structpb.Struct{
|
|
"envoy.filters.http.lua": {Fields: luaMetadata},
|
|
}
|
|
|
|
routes = append(routes, envoyRoute)
|
|
}
|
|
return routes, nil
|
|
}
|
|
|
|
func (b *Builder) buildPolicyRouteRedirectAction(r *config.PolicyRedirect) (*envoy_config_route_v3.RedirectAction, error) {
|
|
action := &envoy_config_route_v3.RedirectAction{}
|
|
switch {
|
|
case r.HTTPSRedirect != nil:
|
|
action.SchemeRewriteSpecifier = &envoy_config_route_v3.RedirectAction_HttpsRedirect{
|
|
HttpsRedirect: *r.HTTPSRedirect,
|
|
}
|
|
case r.SchemeRedirect != nil:
|
|
action.SchemeRewriteSpecifier = &envoy_config_route_v3.RedirectAction_SchemeRedirect{
|
|
SchemeRedirect: *r.SchemeRedirect,
|
|
}
|
|
}
|
|
if r.HostRedirect != nil {
|
|
action.HostRedirect = *r.HostRedirect
|
|
}
|
|
if r.PortRedirect != nil {
|
|
action.PortRedirect = *r.PortRedirect
|
|
}
|
|
switch {
|
|
case r.PathRedirect != nil:
|
|
action.PathRewriteSpecifier = &envoy_config_route_v3.RedirectAction_PathRedirect{
|
|
PathRedirect: *r.PathRedirect,
|
|
}
|
|
case r.PrefixRewrite != nil:
|
|
action.PathRewriteSpecifier = &envoy_config_route_v3.RedirectAction_PrefixRewrite{
|
|
PrefixRewrite: *r.PrefixRewrite,
|
|
}
|
|
}
|
|
if r.ResponseCode != nil {
|
|
action.ResponseCode = envoy_config_route_v3.RedirectAction_RedirectResponseCode(*r.ResponseCode)
|
|
}
|
|
if r.StripQuery != nil {
|
|
action.StripQuery = *r.StripQuery
|
|
}
|
|
return action, nil
|
|
}
|
|
|
|
func (b *Builder) buildPolicyRouteRouteAction(options *config.Options, policy *config.Policy) (*envoy_config_route_v3.RouteAction, error) {
|
|
clusterName := getClusterID(policy)
|
|
// kubernetes requests are sent to the http control plane to be reproxied
|
|
if policy.IsForKubernetes() {
|
|
clusterName = httpCluster
|
|
}
|
|
routeTimeout := getRouteTimeout(options, policy)
|
|
idleTimeout := getRouteIdleTimeout(policy)
|
|
prefixRewrite, regexRewrite := getRewriteOptions(policy)
|
|
upgradeConfigs := []*envoy_config_route_v3.RouteAction_UpgradeConfig{
|
|
{
|
|
UpgradeType: "websocket",
|
|
Enabled: &wrappers.BoolValue{Value: policy.AllowWebsockets},
|
|
},
|
|
{
|
|
UpgradeType: "spdy/3.1",
|
|
Enabled: &wrappers.BoolValue{Value: policy.AllowSPDY},
|
|
},
|
|
}
|
|
|
|
if policy.IsTCP() {
|
|
upgradeConfigs = append(upgradeConfigs, &envoy_config_route_v3.RouteAction_UpgradeConfig{
|
|
UpgradeType: "CONNECT",
|
|
Enabled: &wrappers.BoolValue{Value: true},
|
|
ConnectConfig: &envoy_config_route_v3.RouteAction_UpgradeConfig_ConnectConfig{},
|
|
})
|
|
}
|
|
action := &envoy_config_route_v3.RouteAction{
|
|
ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{
|
|
Cluster: clusterName,
|
|
},
|
|
UpgradeConfigs: upgradeConfigs,
|
|
HostRewriteSpecifier: &envoy_config_route_v3.RouteAction_AutoHostRewrite{
|
|
AutoHostRewrite: &wrappers.BoolValue{Value: !policy.PreserveHostHeader},
|
|
},
|
|
Timeout: routeTimeout,
|
|
IdleTimeout: idleTimeout,
|
|
PrefixRewrite: prefixRewrite,
|
|
RegexRewrite: regexRewrite,
|
|
HashPolicy: []*envoy_config_route_v3.RouteAction_HashPolicy{
|
|
// hash by the routing key, which is added by authorize.
|
|
{
|
|
PolicySpecifier: &envoy_config_route_v3.RouteAction_HashPolicy_Header_{
|
|
Header: &envoy_config_route_v3.RouteAction_HashPolicy_Header{
|
|
HeaderName: httputil.HeaderPomeriumRoutingKey,
|
|
},
|
|
},
|
|
Terminal: true,
|
|
},
|
|
// if the routing key is missing, hash by the ip.
|
|
{
|
|
PolicySpecifier: &envoy_config_route_v3.RouteAction_HashPolicy_ConnectionProperties_{
|
|
ConnectionProperties: &envoy_config_route_v3.RouteAction_HashPolicy_ConnectionProperties{
|
|
SourceIp: true,
|
|
},
|
|
},
|
|
Terminal: true,
|
|
},
|
|
},
|
|
}
|
|
setHostRewriteOptions(policy, action)
|
|
|
|
return action, nil
|
|
}
|
|
|
|
func mkEnvoyHeader(k, v string) *envoy_config_core_v3.HeaderValueOption {
|
|
return &envoy_config_core_v3.HeaderValueOption{
|
|
Header: &envoy_config_core_v3.HeaderValue{
|
|
Key: k,
|
|
Value: v,
|
|
},
|
|
AppendAction: envoy_config_core_v3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD,
|
|
}
|
|
}
|
|
|
|
func toEnvoyHeaders(headers map[string]string) []*envoy_config_core_v3.HeaderValueOption {
|
|
var ks []string
|
|
for k := range headers {
|
|
ks = append(ks, k)
|
|
}
|
|
sort.Strings(ks)
|
|
|
|
envoyHeaders := make([]*envoy_config_core_v3.HeaderValueOption, 0, len(headers))
|
|
for _, k := range ks {
|
|
envoyHeaders = append(envoyHeaders, mkEnvoyHeader(k, headers[k]))
|
|
}
|
|
return envoyHeaders
|
|
}
|
|
|
|
func mkRouteMatch(policy *config.Policy) *envoy_config_route_v3.RouteMatch {
|
|
match := &envoy_config_route_v3.RouteMatch{}
|
|
switch {
|
|
case policy.IsTCP():
|
|
match.PathSpecifier = &envoy_config_route_v3.RouteMatch_ConnectMatcher_{
|
|
ConnectMatcher: &envoy_config_route_v3.RouteMatch_ConnectMatcher{},
|
|
}
|
|
case policy.Regex != "":
|
|
match.PathSpecifier = &envoy_config_route_v3.RouteMatch_SafeRegex{
|
|
SafeRegex: &envoy_type_matcher_v3.RegexMatcher{
|
|
EngineType: &envoy_type_matcher_v3.RegexMatcher_GoogleRe2{
|
|
GoogleRe2: &envoy_type_matcher_v3.RegexMatcher_GoogleRE2{},
|
|
},
|
|
Regex: policy.Regex,
|
|
},
|
|
}
|
|
case policy.Path != "":
|
|
match.PathSpecifier = &envoy_config_route_v3.RouteMatch_Path{Path: policy.Path}
|
|
case policy.Prefix != "":
|
|
match.PathSpecifier = &envoy_config_route_v3.RouteMatch_Prefix{Prefix: policy.Prefix}
|
|
default:
|
|
match.PathSpecifier = &envoy_config_route_v3.RouteMatch_Prefix{Prefix: "/"}
|
|
}
|
|
return match
|
|
}
|
|
|
|
func getRequestHeadersToRemove(options *config.Options, policy *config.Policy) []string {
|
|
requestHeadersToRemove := policy.RemoveRequestHeaders
|
|
if !policy.PassIdentityHeaders {
|
|
requestHeadersToRemove = append(requestHeadersToRemove,
|
|
httputil.HeaderPomeriumJWTAssertion,
|
|
httputil.HeaderPomeriumJWTAssertionFor)
|
|
for headerName := range options.JWTClaimsHeaders {
|
|
requestHeadersToRemove = append(requestHeadersToRemove, headerName)
|
|
}
|
|
}
|
|
// remove these headers to prevent a user from re-proxying requests through the control plane
|
|
requestHeadersToRemove = append(requestHeadersToRemove,
|
|
httputil.HeaderPomeriumReproxyPolicy,
|
|
httputil.HeaderPomeriumReproxyPolicyHMAC,
|
|
)
|
|
return requestHeadersToRemove
|
|
}
|
|
|
|
func getRouteTimeout(options *config.Options, policy *config.Policy) *durationpb.Duration {
|
|
var routeTimeout *durationpb.Duration
|
|
if policy.UpstreamTimeout != nil {
|
|
routeTimeout = durationpb.New(*policy.UpstreamTimeout)
|
|
} else if shouldDisableStreamIdleTimeout(policy) {
|
|
// a non-zero value would conflict with idleTimeout and/or websocket / tcp calls
|
|
routeTimeout = durationpb.New(0)
|
|
} else {
|
|
routeTimeout = durationpb.New(options.DefaultUpstreamTimeout)
|
|
}
|
|
return routeTimeout
|
|
}
|
|
|
|
func getRouteIdleTimeout(policy *config.Policy) *durationpb.Duration {
|
|
var idleTimeout *durationpb.Duration
|
|
if policy.IdleTimeout != nil {
|
|
idleTimeout = durationpb.New(*policy.IdleTimeout)
|
|
} else if shouldDisableStreamIdleTimeout(policy) {
|
|
idleTimeout = durationpb.New(0)
|
|
}
|
|
return idleTimeout
|
|
}
|
|
|
|
func shouldDisableStreamIdleTimeout(policy *config.Policy) bool {
|
|
return policy.AllowWebsockets ||
|
|
policy.IsTCP() ||
|
|
policy.IsForKubernetes() // disable for kubernetes so that tailing logs works (#2182)
|
|
}
|
|
|
|
func getRewriteOptions(policy *config.Policy) (prefixRewrite string, regexRewrite *envoy_type_matcher_v3.RegexMatchAndSubstitute) {
|
|
if policy.PrefixRewrite != "" {
|
|
prefixRewrite = policy.PrefixRewrite
|
|
} else if policy.RegexRewritePattern != "" {
|
|
regexRewrite = &envoy_type_matcher_v3.RegexMatchAndSubstitute{
|
|
Pattern: &envoy_type_matcher_v3.RegexMatcher{
|
|
EngineType: &envoy_type_matcher_v3.RegexMatcher_GoogleRe2{
|
|
GoogleRe2: &envoy_type_matcher_v3.RegexMatcher_GoogleRE2{},
|
|
},
|
|
Regex: policy.RegexRewritePattern,
|
|
},
|
|
Substitution: policy.RegexRewriteSubstitution,
|
|
}
|
|
} else if len(policy.To) > 0 && policy.To[0].URL.Path != "" {
|
|
prefixRewrite = policy.To[0].URL.Path
|
|
}
|
|
|
|
return prefixRewrite, regexRewrite
|
|
}
|
|
|
|
func setHostRewriteOptions(policy *config.Policy, action *envoy_config_route_v3.RouteAction) {
|
|
switch {
|
|
case policy.HostRewrite != "":
|
|
action.HostRewriteSpecifier = &envoy_config_route_v3.RouteAction_HostRewriteLiteral{
|
|
HostRewriteLiteral: policy.HostRewrite,
|
|
}
|
|
case policy.HostRewriteHeader != "":
|
|
action.HostRewriteSpecifier = &envoy_config_route_v3.RouteAction_HostRewriteHeader{
|
|
HostRewriteHeader: policy.HostRewriteHeader,
|
|
}
|
|
case policy.HostPathRegexRewritePattern != "":
|
|
action.HostRewriteSpecifier = &envoy_config_route_v3.RouteAction_HostRewritePathRegex{
|
|
HostRewritePathRegex: &envoy_type_matcher_v3.RegexMatchAndSubstitute{
|
|
Pattern: &envoy_type_matcher_v3.RegexMatcher{
|
|
EngineType: &envoy_type_matcher_v3.RegexMatcher_GoogleRe2{
|
|
GoogleRe2: &envoy_type_matcher_v3.RegexMatcher_GoogleRE2{},
|
|
},
|
|
Regex: policy.HostPathRegexRewritePattern,
|
|
},
|
|
Substitution: policy.HostPathRegexRewriteSubstitution,
|
|
},
|
|
}
|
|
case policy.PreserveHostHeader:
|
|
action.HostRewriteSpecifier = &envoy_config_route_v3.RouteAction_AutoHostRewrite{
|
|
AutoHostRewrite: wrapperspb.Bool(false),
|
|
}
|
|
default:
|
|
action.HostRewriteSpecifier = &envoy_config_route_v3.RouteAction_AutoHostRewrite{
|
|
AutoHostRewrite: wrapperspb.Bool(true),
|
|
}
|
|
}
|
|
}
|
|
|
|
func hasPublicPolicyMatchingURL(options *config.Options, requestURL url.URL) bool {
|
|
for _, policy := range options.GetAllPolicies() {
|
|
if policy.AllowPublicUnauthenticatedAccess && policy.Matches(requestURL) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isProxyFrontingAuthenticate(options *config.Options, host string) (bool, error) {
|
|
authenticateURL, err := options.GetAuthenticateURL()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if !config.IsAuthenticate(options.Services) && urlMatchesHost(authenticateURL, host) {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func getRewriteHeadersMetadata(headers []config.RewriteHeader) *structpb.Value {
|
|
if len(headers) == 0 {
|
|
return &structpb.Value{
|
|
Kind: &structpb.Value_ListValue{
|
|
ListValue: new(structpb.ListValue),
|
|
},
|
|
}
|
|
}
|
|
var obj interface{}
|
|
bs, _ := json.Marshal(headers)
|
|
_ = json.Unmarshal(bs, &obj)
|
|
v, _ := structpb.NewValue(obj)
|
|
return v
|
|
}
|