config: fix set_response_headers (#4026)

* config: fix set_response_headers

* fix disabling to support route headers when global headers are disabled
This commit is contained in:
Caleb Doxsey 2023-04-20 17:07:23 -06:00 committed by GitHub
parent b7d846464c
commit 681cf6fa27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 422 additions and 38 deletions

View file

@ -21,17 +21,12 @@ func (b *Builder) buildVirtualHost(
} }
// these routes match /.pomerium/... and similar paths // these routes match /.pomerium/... and similar paths
rs, err := b.buildPomeriumHTTPRoutes(options, host) rs, err := b.buildPomeriumHTTPRoutes(options, host, requireStrictTransportSecurity)
if err != nil { if err != nil {
return nil, err return nil, err
} }
vh.Routes = append(vh.Routes, rs...) vh.Routes = append(vh.Routes, rs...)
// if we're the proxy or authenticate service, add our global headers
if config.IsProxy(options.Services) || config.IsAuthenticate(options.Services) {
vh.ResponseHeadersToAdd = toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity))
}
return vh, nil return vh, nil
} }

View file

@ -78,7 +78,7 @@ func (b *Builder) buildMainRouteConfiguration(
// if we're the proxy, add all the policy routes // if we're the proxy, add all the policy routes
if config.IsProxy(cfg.Options.Services) { if config.IsProxy(cfg.Options.Services) {
rs, err := b.buildPolicyRoutes(cfg.Options, host) rs, err := b.buildPolicyRoutes(cfg.Options, host, requireStrictTransportSecurity)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -47,7 +47,11 @@ func (b *Builder) buildGRPCRoutes() ([]*envoy_config_route_v3.Route, error) {
}}, nil }}, nil
} }
func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, host string) ([]*envoy_config_route_v3.Route, error) { func (b *Builder) buildPomeriumHTTPRoutes(
options *config.Options,
host string,
requireStrictTransportSecurity bool,
) ([]*envoy_config_route_v3.Route, error) {
var routes []*envoy_config_route_v3.Route var routes []*envoy_config_route_v3.Route
// if this is the pomerium proxy in front of the the authenticate service, don't add // if this is the pomerium proxy in front of the the authenticate service, don't add
@ -59,23 +63,23 @@ func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, host string)
if !isFrontingAuthenticate { if !isFrontingAuthenticate {
routes = append(routes, routes = append(routes,
// enable ext_authz // enable ext_authz
b.buildControlPlanePathRoute("/.pomerium/jwt", true), b.buildControlPlanePathRoute(options, "/.pomerium/jwt", true, requireStrictTransportSecurity),
b.buildControlPlanePathRoute(urlutil.WebAuthnURLPath, true), b.buildControlPlanePathRoute(options, urlutil.WebAuthnURLPath, true, requireStrictTransportSecurity),
// disable ext_authz and passthrough to proxy handlers // disable ext_authz and passthrough to proxy handlers
b.buildControlPlanePathRoute("/ping", false), b.buildControlPlanePathRoute(options, "/ping", false, requireStrictTransportSecurity),
b.buildControlPlanePathRoute("/healthz", false), b.buildControlPlanePathRoute(options, "/healthz", false, requireStrictTransportSecurity),
b.buildControlPlanePathRoute("/.pomerium", false), b.buildControlPlanePathRoute(options, "/.pomerium", false, requireStrictTransportSecurity),
b.buildControlPlanePrefixRoute("/.pomerium/", false), b.buildControlPlanePrefixRoute(options, "/.pomerium/", false, requireStrictTransportSecurity),
b.buildControlPlanePathRoute("/.well-known/pomerium", false), b.buildControlPlanePathRoute(options, "/.well-known/pomerium", false, requireStrictTransportSecurity),
b.buildControlPlanePrefixRoute("/.well-known/pomerium/", false), 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("/robots.txt", false)) routes = append(routes, b.buildControlPlanePathRoute(options, "/robots.txt", false, requireStrictTransportSecurity))
} }
} }
authRoutes, err := b.buildPomeriumAuthenticateHTTPRoutes(options, host) authRoutes, err := b.buildPomeriumAuthenticateHTTPRoutes(options, host, requireStrictTransportSecurity)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -83,7 +87,11 @@ func (b *Builder) buildPomeriumHTTPRoutes(options *config.Options, host string)
return routes, nil return routes, nil
} }
func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(options *config.Options, host string) ([]*envoy_config_route_v3.Route, error) { func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(
options *config.Options,
host string,
requireStrictTransportSecurity bool,
) ([]*envoy_config_route_v3.Route, error) {
if !config.IsAuthenticate(options.Services) { if !config.IsAuthenticate(options.Services) {
return nil, nil return nil, nil
} }
@ -98,15 +106,20 @@ func (b *Builder) buildPomeriumAuthenticateHTTPRoutes(options *config.Options, h
} }
if urlMatchesHost(u, host) { if urlMatchesHost(u, host) {
return []*envoy_config_route_v3.Route{ return []*envoy_config_route_v3.Route{
b.buildControlPlanePathRoute(options.AuthenticateCallbackPath, false), b.buildControlPlanePathRoute(options, options.AuthenticateCallbackPath, false, requireStrictTransportSecurity),
b.buildControlPlanePathRoute("/", false), b.buildControlPlanePathRoute(options, "/", false, requireStrictTransportSecurity),
}, nil }, nil
} }
} }
return nil, nil return nil, nil
} }
func (b *Builder) buildControlPlanePathRoute(path string, protected bool) *envoy_config_route_v3.Route { func (b *Builder) buildControlPlanePathRoute(
options *config.Options,
path string,
protected bool,
requireStrictTransportSecurity bool,
) *envoy_config_route_v3.Route {
r := &envoy_config_route_v3.Route{ r := &envoy_config_route_v3.Route{
Name: "pomerium-path-" + path, Name: "pomerium-path-" + path,
Match: &envoy_config_route_v3.RouteMatch{ Match: &envoy_config_route_v3.RouteMatch{
@ -119,6 +132,7 @@ func (b *Builder) buildControlPlanePathRoute(path string, protected bool) *envoy
}, },
}, },
}, },
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
} }
if !protected { if !protected {
r.TypedPerFilterConfig = map[string]*any.Any{ r.TypedPerFilterConfig = map[string]*any.Any{
@ -128,7 +142,12 @@ func (b *Builder) buildControlPlanePathRoute(path string, protected bool) *envoy
return r return r
} }
func (b *Builder) buildControlPlanePrefixRoute(prefix string, protected bool) *envoy_config_route_v3.Route { func (b *Builder) buildControlPlanePrefixRoute(
options *config.Options,
prefix string,
protected bool,
requireStrictTransportSecurity bool,
) *envoy_config_route_v3.Route {
r := &envoy_config_route_v3.Route{ r := &envoy_config_route_v3.Route{
Name: "pomerium-prefix-" + prefix, Name: "pomerium-prefix-" + prefix,
Match: &envoy_config_route_v3.RouteMatch{ Match: &envoy_config_route_v3.RouteMatch{
@ -141,6 +160,7 @@ func (b *Builder) buildControlPlanePrefixRoute(prefix string, protected bool) *e
}, },
}, },
}, },
ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeaders(requireStrictTransportSecurity)),
} }
if !protected { if !protected {
r.TypedPerFilterConfig = map[string]*any.Any{ r.TypedPerFilterConfig = map[string]*any.Any{
@ -169,7 +189,11 @@ func getClusterStatsName(policy *config.Policy) string {
return "" return ""
} }
func (b *Builder) buildPolicyRoutes(options *config.Options, host string) ([]*envoy_config_route_v3.Route, error) { func (b *Builder) buildPolicyRoutes(
options *config.Options,
host string,
requireStrictTransportSecurity bool,
) ([]*envoy_config_route_v3.Route, error) {
var routes []*envoy_config_route_v3.Route var routes []*envoy_config_route_v3.Route
for i, p := range options.GetAllPolicies() { for i, p := range options.GetAllPolicies() {
@ -185,7 +209,7 @@ func (b *Builder) buildPolicyRoutes(options *config.Options, host string) ([]*en
Metadata: &envoy_config_core_v3.Metadata{}, Metadata: &envoy_config_core_v3.Metadata{},
RequestHeadersToAdd: toEnvoyHeaders(policy.SetRequestHeaders), RequestHeadersToAdd: toEnvoyHeaders(policy.SetRequestHeaders),
RequestHeadersToRemove: getRequestHeadersToRemove(options, &policy), RequestHeadersToRemove: getRequestHeadersToRemove(options, &policy),
ResponseHeadersToAdd: toEnvoyHeaders(policy.SetResponseHeaders), ResponseHeadersToAdd: toEnvoyHeaders(options.GetSetResponseHeadersForPolicy(&policy, requireStrictTransportSecurity)),
} }
if policy.Redirect != nil { if policy.Redirect != nil {
action, err := b.buildPolicyRouteRedirectAction(policy.Redirect) action, err := b.buildPolicyRouteRedirectAction(policy.Redirect)

View file

@ -61,6 +61,22 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
"match": { "match": {
"` + typ + `": "` + name + `" "` + typ + `": "` + name + `"
}, },
"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": { "route": {
"cluster": "pomerium-control-plane-http" "cluster": "pomerium-control-plane-http"
} }
@ -84,7 +100,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
AuthenticateURLString: "https://authenticate.example.com", AuthenticateURLString: "https://authenticate.example.com",
AuthenticateCallbackPath: "/oauth2/callback", AuthenticateCallbackPath: "/oauth2/callback",
} }
routes, err := b.buildPomeriumHTTPRoutes(options, "authenticate.example.com") routes, err := b.buildPomeriumHTTPRoutes(options, "authenticate.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `[ testutil.AssertProtoJSONEqual(t, `[
@ -107,7 +123,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
AuthenticateURLString: "https://authenticate.example.com", AuthenticateURLString: "https://authenticate.example.com",
AuthenticateCallbackPath: "/oauth2/callback", AuthenticateCallbackPath: "/oauth2/callback",
} }
routes, err := b.buildPomeriumHTTPRoutes(options, "authenticate.example.com") routes, err := b.buildPomeriumHTTPRoutes(options, "authenticate.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, "null", routes) testutil.AssertProtoJSONEqual(t, "null", routes)
}) })
@ -123,7 +139,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
}}, }},
} }
_ = options.Policies[0].Validate() _ = options.Policies[0].Validate()
routes, err := b.buildPomeriumHTTPRoutes(options, "from.example.com") routes, err := b.buildPomeriumHTTPRoutes(options, "from.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `[ testutil.AssertProtoJSONEqual(t, `[
@ -151,7 +167,7 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
}}, }},
} }
_ = options.Policies[0].Validate() _ = options.Policies[0].Validate()
routes, err := b.buildPomeriumHTTPRoutes(options, "from.example.com") routes, err := b.buildPomeriumHTTPRoutes(options, "from.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, `[ testutil.AssertProtoJSONEqual(t, `[
@ -168,14 +184,31 @@ func Test_buildPomeriumHTTPRoutes(t *testing.T) {
} }
func Test_buildControlPlanePathRoute(t *testing.T) { func Test_buildControlPlanePathRoute(t *testing.T) {
options := config.NewDefaultOptions()
b := &Builder{filemgr: filemgr.NewManager()} b := &Builder{filemgr: filemgr.NewManager()}
route := b.buildControlPlanePathRoute("/hello/world", false) route := b.buildControlPlanePathRoute(options, "/hello/world", false, false)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
{ {
"name": "pomerium-path-/hello/world", "name": "pomerium-path-/hello/world",
"match": { "match": {
"path": "/hello/world" "path": "/hello/world"
}, },
"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": { "route": {
"cluster": "pomerium-control-plane-http" "cluster": "pomerium-control-plane-http"
}, },
@ -190,14 +223,31 @@ func Test_buildControlPlanePathRoute(t *testing.T) {
} }
func Test_buildControlPlanePrefixRoute(t *testing.T) { func Test_buildControlPlanePrefixRoute(t *testing.T) {
options := config.NewDefaultOptions()
b := &Builder{filemgr: filemgr.NewManager()} b := &Builder{filemgr: filemgr.NewManager()}
route := b.buildControlPlanePrefixRoute("/hello/world/", false) route := b.buildControlPlanePrefixRoute(options, "/hello/world/", false, false)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
{ {
"name": "pomerium-prefix-/hello/world/", "name": "pomerium-prefix-/hello/world/",
"match": { "match": {
"prefix": "/hello/world/" "prefix": "/hello/world/"
}, },
"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": { "route": {
"cluster": "pomerium-control-plane-http" "cluster": "pomerium-control-plane-http"
}, },
@ -255,7 +305,7 @@ func TestTimeouts(t *testing.T) {
AllowWebsockets: tc.allowWebsockets, AllowWebsockets: tc.allowWebsockets,
}, },
}, },
}, "example.com") }, "example.com", false)
if !assert.NoError(t, err, "%v", tc) || !assert.Len(t, routes, 1, tc) || !assert.NotNil(t, routes[0].GetRoute(), "%v", tc) { if !assert.NoError(t, err, "%v", tc) || !assert.Len(t, routes, 1, tc) || !assert.NotNil(t, routes[0].GetRoute(), "%v", tc) {
continue continue
} }
@ -359,7 +409,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
UpstreamTimeout: &ten, UpstreamTimeout: &ten,
}, },
}, },
}, "example.com") }, "example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -405,6 +455,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -449,6 +515,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -499,6 +581,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -545,6 +643,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -589,6 +703,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"HEADER-KEY", "HEADER-KEY",
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -632,6 +762,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -676,6 +822,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -720,6 +882,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
} }
] ]
@ -737,7 +915,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
PassIdentityHeaders: true, PassIdentityHeaders: true,
}, },
}, },
}, "authenticate.example.com") }, "authenticate.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -781,6 +959,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
], ],
"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"
}
}
],
"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",
@ -807,7 +1001,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
UpstreamTimeout: &ten, UpstreamTimeout: &ten,
}, },
}, },
}, "example.com:22") }, "example.com:22", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -855,6 +1049,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -900,6 +1110,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
} }
] ]
@ -920,7 +1146,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
Source: &config.StringURL{URL: mustParseURL(t, "https://from.example.com")}, Source: &config.StringURL{URL: mustParseURL(t, "https://from.example.com")},
}, },
}, },
}, "from.example.com") }, "from.example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -969,6 +1195,22 @@ func Test_buildPolicyRoutes(t *testing.T) {
"x-email", "x-email",
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
} }
] ]
@ -1024,7 +1266,7 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
HostPathRegexRewriteSubstitution: "\\1", HostPathRegexRewriteSubstitution: "\\1",
}, },
}, },
}, "example.com") }, "example.com", false)
require.NoError(t, err) require.NoError(t, err)
testutil.AssertProtoJSONEqual(t, ` testutil.AssertProtoJSONEqual(t, `
@ -1071,6 +1313,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -1115,6 +1373,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -1165,6 +1439,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -1209,6 +1499,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -1253,6 +1559,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
}, },
{ {
@ -1303,6 +1625,22 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) {
"requestHeadersToRemove": [ "requestHeadersToRemove": [
"x-pomerium-reproxy-policy", "x-pomerium-reproxy-policy",
"x-pomerium-reproxy-policy-hmac" "x-pomerium-reproxy-policy-hmac"
],
"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"
}
}
] ]
} }
] ]

View file

@ -1009,6 +1009,11 @@ func (o *Options) GetGoogleCloudServerlessAuthenticationServiceAccount() string
// GetSetResponseHeaders gets the SetResponseHeaders. // GetSetResponseHeaders gets the SetResponseHeaders.
func (o *Options) GetSetResponseHeaders(requireStrictTransportSecurity bool) map[string]string { func (o *Options) GetSetResponseHeaders(requireStrictTransportSecurity bool) map[string]string {
return o.GetSetResponseHeadersForPolicy(nil, requireStrictTransportSecurity)
}
// GetSetResponseHeadersForPolicy gets the SetResponseHeaders for a policy.
func (o *Options) GetSetResponseHeadersForPolicy(policy *Policy, requireStrictTransportSecurity bool) map[string]string {
hdrs := o.SetResponseHeaders hdrs := o.SetResponseHeaders
if hdrs == nil { if hdrs == nil {
hdrs = make(map[string]string) hdrs = make(map[string]string)
@ -1016,12 +1021,23 @@ func (o *Options) GetSetResponseHeaders(requireStrictTransportSecurity bool) map
hdrs[k] = v hdrs[k] = v
} }
} }
if _, ok := o.SetResponseHeaders[DisableHeaderKey]; ok { if _, ok := hdrs[DisableHeaderKey]; ok {
hdrs = make(map[string]string) hdrs = make(map[string]string)
} }
if policy != nil && policy.SetResponseHeaders != nil {
for k, v := range policy.SetResponseHeaders {
hdrs[k] = v
}
}
if _, ok := hdrs[DisableHeaderKey]; ok {
hdrs = make(map[string]string)
}
if !requireStrictTransportSecurity { if !requireStrictTransportSecurity {
delete(hdrs, "Strict-Transport-Security") delete(hdrs, "Strict-Transport-Security")
} }
return hdrs return hdrs
} }

View file

@ -766,6 +766,17 @@ func TestOptions_GetSetResponseHeaders(t *testing.T) {
}) })
} }
func TestOptions_GetSetResponseHeadersForPolicy(t *testing.T) {
t.Run("disable but set in policy", func(t *testing.T) {
options := NewDefaultOptions()
options.SetResponseHeaders = map[string]string{DisableHeaderKey: "1"}
policy := &Policy{
SetResponseHeaders: map[string]string{"x": "y"},
}
assert.Equal(t, map[string]string{"x": "y"}, options.GetSetResponseHeadersForPolicy(policy, true))
})
}
func TestOptions_GetSharedKey(t *testing.T) { func TestOptions_GetSharedKey(t *testing.T) {
t.Run("default", func(t *testing.T) { t.Run("default", func(t *testing.T) {
o := NewDefaultOptions() o := NewDefaultOptions()