diff --git a/config/policy.go b/config/policy.go index b47c0d2cd..36c82a698 100644 --- a/config/policy.go +++ b/config/policy.go @@ -148,6 +148,16 @@ type Policy struct { SubPolicies []SubPolicy `mapstructure:"sub_policies" yaml:"sub_policies,omitempty" json:"sub_policies,omitempty"` EnvoyOpts *envoy_config_cluster_v3.Cluster `mapstructure:"_envoy_opts" yaml:"-" json:"-"` + + // RewriteResponseHeaders rewrites response headers. This can be used to change the Location header. + RewriteResponseHeaders []RewriteHeader `mapstructure:"rewrite_response_headers" yaml:"rewrite_response_headers,omitempty" json:"rewrite_response_headers,omitempty"` //nolint +} + +// RewriteHeader is a policy configuration option to rewrite an HTTP header. +type RewriteHeader struct { + Header string `mapstructure:"header" yaml:"header" json:"header"` + Prefix string `mapstructure:"prefix" yaml:"prefix,omitempty" json:"prefix,omitempty"` + Value string `mapstructure:"value" yaml:"value,omitempty" json:"value,omitempty"` } // A SubPolicy is a protobuf Policy within a protobuf Route. diff --git a/docs/reference/readme.md b/docs/reference/readme.md index 8d66f73a9..e0dcf1943 100644 --- a/docs/reference/readme.md +++ b/docs/reference/readme.md @@ -1294,6 +1294,30 @@ Remove Request Headers allows you to remove given request headers. This can be u ``` +### Rewrite Response Headers +- Config File Key: `rewrite_response_headers` +- Type: `object` +- Optional +- Example: `[{ "header": "Location", "prefix": "http://localhost:8000/two/", "value": "http://frontend/one/" }]` + +Rewrite Response Headers allows you to modify response headers before they are returned to the client. The `header` field will match the HTTP header name, and `prefix` will be replaced with `value`. For example, if the downstream server returns a header: + +```text +Location: http://localhost:8000/two/some/path/ +``` + +And the policy has this config: + +```yaml +rewrite_response_headers: + - header: Location + prefix: http://localhost:8000/two/ + value: http://frontend/one/ +``` + +The browser would be redirected to: `http://frontend/one/some/path/`. This is similar to nginx's [`proxy_redirect` option](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect), but can be used for any header. + + ### Redirect - `yaml`/`json` setting: 'redirect' - Type: object diff --git a/docs/reference/settings.yaml b/docs/reference/settings.yaml index 4f91e2be8..2d658ee8a 100644 --- a/docs/reference/settings.yaml +++ b/docs/reference/settings.yaml @@ -1427,6 +1427,30 @@ settings: - X-Email - X-Username ``` + - name: "Rewrite Response Headers" + keys: ["rewrite_response_headers"] + attributes: | + - Config File Key: `rewrite_response_headers` + - Type: `object` + - Optional + - Example: `[{ "header": "Location", "prefix": "http://localhost:8000/two/", "value": "http://frontend/one/" }]` + doc: | + Rewrite Response Headers allows you to modify response headers before they are returned to the client. The `header` field will match the HTTP header name, and `prefix` will be replaced with `value`. For example, if the downstream server returns a header: + + ```text + Location: http://localhost:8000/two/some/path/ + ``` + + And the policy has this config: + + ```yaml + rewrite_response_headers: + - header: Location + prefix: http://localhost:8000/two/ + value: http://frontend/one/ + ``` + + The browser would be redirected to: `http://frontend/one/some/path/`. This is similar to nginx's [`proxy_redirect` option](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect), but can be used for any header. - name: "Redirect" keys: ["redirect"] attributes: | diff --git a/go.mod b/go.mod index 423c5fcbe..dc87a3f2f 100644 --- a/go.mod +++ b/go.mod @@ -56,6 +56,7 @@ require ( github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 + github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da go.opencensus.io v0.23.0 go.uber.org/zap v1.16.0 golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 diff --git a/go.sum b/go.sum index 418448d04..84f032f09 100644 --- a/go.sum +++ b/go.sum @@ -618,6 +618,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5ukMK0AMWEhFaL/lrEOaephfuoiARg= +github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -780,6 +782,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/internal/controlplane/luascripts/rewrite-headers.lua b/internal/controlplane/luascripts/rewrite-headers.lua new file mode 100644 index 000000000..ec1867e01 --- /dev/null +++ b/internal/controlplane/luascripts/rewrite-headers.lua @@ -0,0 +1,28 @@ +function replace_prefix(str, prefix, value) + return str:gsub("^"..prefix, value) +end + +function envoy_on_request(request_handle) +end + +function envoy_on_response(response_handle) + local headers = response_handle:headers() + local metadata = response_handle:metadata() + + -- should be in the form: + -- [{ + -- "header":"Location", + -- "prefix":"http://localhost:8000/two/", + -- "value":"http://frontend/one/" + -- }] + local rewrite_response_headers = metadata:get("rewrite_response_headers") + if rewrite_response_headers then + for _, obj in pairs(rewrite_response_headers) do + local hdr = headers:get(obj.header) + if hdr ~= nil then + local newhdr = replace_prefix(hdr, obj.prefix, obj.value) + headers:replace(obj.header, newhdr) + end + end + end +end diff --git a/internal/controlplane/xds_listeners.go b/internal/controlplane/xds_listeners.go index df6ff4a79..94ba221be 100644 --- a/internal/controlplane/xds_listeners.go +++ b/internal/controlplane/xds_listeners.go @@ -373,6 +373,9 @@ func (srv *Server) buildMainHTTPConnectionManagerFilter( removeImpersonateHeadersLua := marshalAny(&envoy_extensions_filters_http_lua_v3.Lua{ InlineCode: luascripts.RemoveImpersonateHeaders, }) + rewriteHeadersLua := marshalAny(&envoy_extensions_filters_http_lua_v3.Lua{ + InlineCode: luascripts.RewriteHeaders, + }) filters := []*envoy_http_connection_manager.HttpFilter{ { @@ -399,6 +402,12 @@ func (srv *Server) buildMainHTTPConnectionManagerFilter( TypedConfig: cleanUpstreamLua, }, }, + { + Name: "envoy.filters.http.lua", + ConfigType: &envoy_http_connection_manager.HttpFilter_TypedConfig{ + TypedConfig: rewriteHeadersLua, + }, + }, } if tlsDomain != "" && tlsDomain != "*" { fixMisdirectedLua := marshalAny(&envoy_extensions_filters_http_lua_v3.Lua{ diff --git a/internal/controlplane/xds_listeners_test.go b/internal/controlplane/xds_listeners_test.go index 1f452c2e3..348c115bb 100644 --- a/internal/controlplane/xds_listeners_test.go +++ b/internal/controlplane/xds_listeners_test.go @@ -173,6 +173,13 @@ func Test_buildMainHTTPConnectionManagerFilter(t *testing.T) { "inlineCode": "function remove_pomerium_cookie(cookie_name, cookie)\n -- lua doesn't support optional capture groups\n -- so we replace twice to handle pomerium=xyz at the end of the string\n cookie = cookie:gsub(cookie_name .. \"=[^;]+; \", \"\")\n cookie = cookie:gsub(cookie_name .. \"=[^;]+\", \"\")\n return cookie\nend\n\nfunction has_prefix(str, prefix)\n return str ~= nil and str:sub(1, #prefix) == prefix\nend\n\nfunction envoy_on_request(request_handle)\n local headers = request_handle:headers()\n local metadata = request_handle:metadata()\n\n local remove_cookie_name = metadata:get(\"remove_pomerium_cookie\")\n if remove_cookie_name then\n local cookie = headers:get(\"cookie\")\n if cookie ~= nil then\n newcookie = remove_pomerium_cookie(remove_cookie_name, cookie)\n headers:replace(\"cookie\", newcookie)\n end\n end\n\n local remove_authorization = metadata:get(\"remove_pomerium_authorization\")\n if remove_authorization then\n local authorization = headers:get(\"authorization\")\n local authorization_prefix = \"Pomerium \"\n if has_prefix(authorization, authorization_prefix) then\n headers:remove(\"authorization\")\n end\n end\nend\n\nfunction envoy_on_response(response_handle)\n\nend\n" } }, + { + "name": "envoy.filters.http.lua", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", + "inlineCode": "function replace_prefix(str, prefix, value)\n return str:gsub(\"^\"..prefix, value)\nend\n\nfunction envoy_on_request(request_handle)\nend\n\nfunction envoy_on_response(response_handle)\n local headers = response_handle:headers()\n local metadata = response_handle:metadata()\n\n -- should be in the form:\n -- [{\n -- \"header\":\"Location\",\n -- \"prefix\":\"http://localhost:8000/two/\",\n -- \"value\":\"http://frontend/one/\"\n -- }]\n local rewrite_response_headers = metadata:get(\"rewrite_response_headers\")\n if rewrite_response_headers then\n for _, obj in pairs(rewrite_response_headers) do\n local hdr = headers:get(obj.header)\n if hdr ~= nil then\n local newhdr = replace_prefix(hdr, obj.prefix, obj.value)\n headers:replace(obj.header, newhdr)\n end\n end\n end\nend\n" + } + }, { "name": "envoy.filters.http.router" } diff --git a/internal/controlplane/xds_lua.go b/internal/controlplane/xds_lua.go index 542cc04b4..6f66d2eb1 100644 --- a/internal/controlplane/xds_lua.go +++ b/internal/controlplane/xds_lua.go @@ -12,6 +12,7 @@ var luascripts struct { ExtAuthzSetCookie string CleanUpstream string RemoveImpersonateHeaders string + RewriteHeaders string FixMisdirected string } @@ -20,6 +21,7 @@ func init() { "luascripts/clean-upstream.lua": &luascripts.CleanUpstream, "luascripts/ext-authz-set-cookie.lua": &luascripts.ExtAuthzSetCookie, "luascripts/remove-impersonate-headers.lua": &luascripts.RemoveImpersonateHeaders, + "luascripts/rewrite-headers.lua": &luascripts.RewriteHeaders, "luascripts/fix-misdirected.lua": &luascripts.FixMisdirected, } diff --git a/internal/controlplane/xds_lua_test.go b/internal/controlplane/xds_lua_test.go new file mode 100644 index 000000000..6eb9199ee --- /dev/null +++ b/internal/controlplane/xds_lua_test.go @@ -0,0 +1,166 @@ +package controlplane + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + lua "github.com/yuin/gopher-lua" +) + +func TestLuaRewriteHeaders(t *testing.T) { + L := lua.NewState() + defer L.Close() + + bs, err := luaFS.ReadFile("luascripts/rewrite-headers.lua") + require.NoError(t, err) + + err = L.DoString(string(bs)) + require.NoError(t, err) + + headers := map[string]string{ + "Location": "https://localhost:8080/two/some/uri/", + } + metadata := map[string]interface{}{ + "rewrite_response_headers": []interface{}{ + map[string]interface{}{ + "header": "Location", + "prefix": "https://localhost:8080/two/", + "value": "https://frontend/one/", + }, + map[string]interface{}{ + "header": "SomeOtherHeader", + "prefix": "x", + "value": "y", + }, + }, + } + handle := newLuaResponseHandle(L, headers, metadata) + + err = L.CallByParam(lua.P{ + Fn: L.GetGlobal("envoy_on_response"), + NRet: 0, + Protect: true, + }, handle) + require.NoError(t, err) + + assert.Equal(t, "https://frontend/one/some/uri/", headers["Location"]) +} + +func newLuaResponseHandle(L *lua.LState, headers map[string]string, metadata map[string]interface{}) lua.LValue { + typ := L.NewTable() + L.SetFuncs(typ, map[string]lua.LGFunction{ + "headers": func(L *lua.LState) int { + L.Push(newLuaHeaders(L, headers)) + return 1 + }, + "metadata": func(L *lua.LState) int { + L.Push(newLuaMetadata(L, metadata)) + return 1 + }, + }) + L.SetField(typ, "__index", typ) + + tbl := L.NewTable() + L.SetMetatable(tbl, typ) + return tbl +} + +func newLuaHeaders(L *lua.LState, headers map[string]string) lua.LValue { + typ := L.NewTable() + L.SetFuncs(typ, map[string]lua.LGFunction{ + "get": func(L *lua.LState) int { + _ = L.CheckTable(1) + key := L.CheckString(2) + + str, ok := headers[key] + if !ok { + L.Push(lua.LNil) + return 0 + } + + L.Push(lua.LString(str)) + return 1 + }, + "replace": func(L *lua.LState) int { + _ = L.CheckTable(1) + key := L.CheckString(2) + value := L.CheckString(3) + + headers[key] = value + + return 0 + }, + }) + L.SetField(typ, "__index", typ) + + tbl := L.NewTable() + L.SetMetatable(tbl, typ) + return tbl +} + +func newLuaMetadata(L *lua.LState, metadata map[string]interface{}) lua.LValue { + typ := L.NewTable() + L.SetFuncs(typ, map[string]lua.LGFunction{ + "get": func(L *lua.LState) int { + _ = L.CheckTable(1) + key := L.CheckString(2) + + obj, ok := metadata[key] + if !ok { + L.Push(lua.LNil) + return 0 + } + + L.Push(toLua(L, obj)) + return 1 + }, + }) + L.SetField(typ, "__index", typ) + + tbl := L.NewTable() + L.SetMetatable(tbl, typ) + return tbl +} + +func toLua(L *lua.LState, obj interface{}) lua.LValue { + // send the object through JSON to remove custom types + var normalized interface{} + bs, err := json.Marshal(obj) + if err != nil { + panic(err) + } + err = json.Unmarshal(bs, &normalized) + if err != nil { + panic(err) + } + + if normalized == nil { + return lua.LNil + } + + switch t := normalized.(type) { + case []interface{}: + tbl := L.NewTable() + for _, v := range t { + tbl.Append(toLua(L, v)) + } + return tbl + case map[string]interface{}: + tbl := L.NewTable() + for k, v := range t { + L.SetField(tbl, k, toLua(L, v)) + } + return tbl + case bool: + return lua.LBool(t) + case float64: + return lua.LNumber(t) + case string: + return lua.LString(t) + default: + panic(fmt.Sprintf("%T not supported for toLua", obj)) + } +} diff --git a/internal/controlplane/xds_routes.go b/internal/controlplane/xds_routes.go index 54072fb2d..3f4270ad7 100644 --- a/internal/controlplane/xds_routes.go +++ b/internal/controlplane/xds_routes.go @@ -1,6 +1,7 @@ package controlplane import ( + "encoding/json" "fmt" "net/url" "sort" @@ -290,6 +291,10 @@ func (srv *Server) buildPolicyRoutes(options *config.Options, domain string) ([] 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, domain) if err != nil { @@ -300,27 +305,25 @@ func (srv *Server) buildPolicyRoutes(options *config.Options, domain string) ([] "envoy.filters.http.ext_authz": disableExtAuthz, } } else { - envoyRoute.Metadata.FilterMetadata = map[string]*structpb.Struct{ - "envoy.filters.http.lua": { - Fields: map[string]*structpb.Value{ - "remove_pomerium_cookie": { - Kind: &structpb.Value_StringValue{ - StringValue: options.CookieName, - }, - }, - "remove_pomerium_authorization": { - Kind: &structpb.Value_BoolValue{ - BoolValue: true, - }, - }, - "remove_impersonate_headers": { - Kind: &structpb.Value_BoolValue{ - BoolValue: policy.KubernetesServiceAccountTokenFile != "" || policy.KubernetesServiceAccountToken != "", - }, - }, - }, + 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.KubernetesServiceAccountTokenFile != "" || policy.KubernetesServiceAccountToken != "", + }, + } + } + + envoyRoute.Metadata.FilterMetadata = map[string]*structpb.Struct{ + "envoy.filters.http.lua": {Fields: luaMetadata}, } routes = append(routes, envoyRoute) @@ -559,3 +562,18 @@ func isProxyFrontingAuthenticate(options *config.Options, domain string) (bool, 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 +} diff --git a/internal/controlplane/xds_routes_test.go b/internal/controlplane/xds_routes_test.go index f8d98c204..3a644cdf1 100644 --- a/internal/controlplane/xds_routes_test.go +++ b/internal/controlplane/xds_routes_test.go @@ -295,7 +295,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -319,7 +320,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -344,7 +346,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -378,7 +381,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -402,7 +406,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -427,7 +432,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -451,7 +457,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -476,7 +483,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -517,6 +525,11 @@ func Test_buildPolicyRoutes(t *testing.T) { "prefix": "/" }, "metadata": { + "filterMetadata": { + "envoy.filters.http.lua": { + "rewrite_response_headers": [] + } + } }, "route": { "autoHostRewrite": true, @@ -568,7 +581,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -594,7 +608,8 @@ func Test_buildPolicyRoutes(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -678,7 +693,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -703,7 +719,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -728,7 +745,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -759,7 +777,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -784,7 +803,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } }, @@ -809,7 +829,8 @@ func Test_buildPolicyRoutesRewrite(t *testing.T) { "envoy.filters.http.lua": { "remove_impersonate_headers": false, "remove_pomerium_authorization": true, - "remove_pomerium_cookie": "pomerium" + "remove_pomerium_cookie": "pomerium", + "rewrite_response_headers": [] } } },