Feature/remove request headers (#822)

* config: add RemoveRequestHeaders

Currently, we have "set_request_headers" config, which reflects envoy
route.Route.RequestHeadersToAdd. This commit add new config
"remove_request_headers", which reflects envoy RequestHeadersToRemove.

This is also a preparation for future PRs to implement disable user
identity in request headers feature.

* integration: add test for remove_request_headers
* docs: add documentation/changelog for remove_request_headers
This commit is contained in:
Cuong Manh Le 2020-06-03 21:46:51 +07:00 committed by GitHub
parent b80a419699
commit 4d5edb0d64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 5 deletions

View file

@ -80,6 +80,11 @@ type Policy struct {
// value of any existing value of a given header key.
SetRequestHeaders map[string]string `mapstructure:"set_request_headers" yaml:"set_request_headers,omitempty"`
// RemoveRequestHeaders removes a collection of headers from a downstream request.
// Note that this has lower priority than `SetRequestHeaders`, if you specify `X-Custom-Header` in both
// `SetRequestHeaders` and `RemoveRequestHeaders`, then the header won't be removed.
RemoveRequestHeaders []string `mapstructure:"remove_request_headers" yaml:"remove_request_headers,omitempty"`
// PreserveHostHeader disables host header rewriting.
//
// https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header

View file

@ -995,6 +995,24 @@ Set Request Headers allows you to set static values for given request headers. T
X-Your-favorite-authenticating-Proxy: "Pomerium"
```
### Remove Request Headers
- Config File Key: `removet_request_headers`
- Type: array of `strings`
- Optional
Remove Request Headers allows you to remove given request headers. This can be useful if you want to prevent privacy information from being passed to downstream applications. For example:
```yaml
- from: https://httpbin.corp.example.com
to: https://httpbin.org
allowed_users:
- bdd@pomerium.io
remove_request_headers:
- X-Email
- X-Username
```
### To
- `yaml`/`json` setting: `to`

View file

@ -1,5 +1,11 @@
# Changelog
## v0.10.0
### New
- config: add remove_request_headers @cuonglm [GH-702]
## v0.9.0
### New

View file

@ -119,6 +119,7 @@ local PomeriumPolicy = function() std.flattenArrays(
set_request_headers: {
'X-Custom-Request-Header': 'custom-request-header-value',
},
remove_request_headers: ['X-Custom-Request-Header-To-Remove'],
},
{
from: 'http://restricted-' + domain + '.localhost.pomerium.io',

View file

@ -147,6 +147,38 @@ func TestSetRequestHeaders(t *testing.T) {
}
func TestRemoveRequestHeaders(t *testing.T) {
ctx := mainCtx
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)
defer clearTimeout()
client := testcluster.NewHTTPClient()
req, err := http.NewRequestWithContext(ctx, "GET", "https://httpdetails.localhost.pomerium.io/", nil)
if err != nil {
t.Fatal(err)
}
req.Header.Add("X-Custom-Request-Header-To-Remove", "foo")
res, err := client.Do(req)
if !assert.NoError(t, err, "unexpected http error") {
return
}
defer res.Body.Close()
var result struct {
Headers map[string]string `json:"headers"`
}
err = json.NewDecoder(res.Body).Decode(&result)
if !assert.NoError(t, err) {
return
}
_, exist := result.Headers["X-Custom-Request-Header-To-Remove"]
assert.False(t, exist, "expected X-Custom-Request-Header-To-Remove not to be present.")
}
func TestWebsocket(t *testing.T) {
ctx := mainCtx
ctx, clearTimeout := context.WithTimeout(ctx, time.Second*30)

View file

@ -182,7 +182,8 @@ func buildPolicyRoutes(options *config.Options, domain string) []*envoy_config_r
Timeout: routeTimeout,
},
},
RequestHeadersToAdd: requestHeadersToAdd,
RequestHeadersToAdd: requestHeadersToAdd,
RequestHeadersToRemove: policy.RemoveRequestHeaders,
})
}
return routes

View file

@ -221,8 +221,15 @@ func Test_buildPolicyRoutes(t *testing.T) {
Source: &config.StringURL{URL: mustParseURL("https://example.com")},
Regex: `^/[a]+$`,
},
{
Source: &config.StringURL{URL: mustParseURL("https://example.com")},
Prefix: "/some/prefix/",
RemoveRequestHeaders: []string{"HEADER-KEY"},
UpstreamTimeout: time.Minute,
},
},
}, "example.com")
testutil.AssertProtoJSONEqual(t, `
[
{
@ -240,7 +247,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
},
"route": {
"autoHostRewrite": true,
"cluster": "policy-d00072a199d7b614",
"cluster": "policy-4e2763e591b22dc8",
"timeout": "3s",
"upgradeConfigs": [{
"enabled": false,
@ -263,7 +270,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
},
"route": {
"autoHostRewrite": false,
"cluster": "policy-907a31075a413547",
"cluster": "policy-e5d20435224ae9b",
"timeout": "0s",
"upgradeConfigs": [{
"enabled": true,
@ -286,7 +293,7 @@ func Test_buildPolicyRoutes(t *testing.T) {
},
"route": {
"autoHostRewrite": true,
"cluster": "policy-f05528f790686bc3",
"cluster": "policy-6e7239b3980df01f",
"timeout": "60s",
"upgradeConfigs": [{
"enabled": false,
@ -319,13 +326,37 @@ func Test_buildPolicyRoutes(t *testing.T) {
},
"route": {
"autoHostRewrite": true,
"cluster": "policy-e5d3a05ff1f97659",
"cluster": "policy-7bf4b11bf99ced85",
"timeout": "3s",
"upgradeConfigs": [{
"enabled": false,
"upgradeType": "websocket"
}]
}
},
{
"name": "policy-5",
"match": {
"prefix": "/some/prefix/"
},
"metadata": {
"filterMetadata": {
"envoy.filters.http.lua": {
"remove_pomerium_authorization": true,
"remove_pomerium_cookie": "pomerium"
}
}
},
"route": {
"autoHostRewrite": true,
"cluster": "policy-6b5e934ff586365d",
"timeout": "60s",
"upgradeConfigs": [{
"enabled": false,
"upgradeType": "websocket"
}]
},
"requestHeadersToRemove": ["HEADER-KEY"]
}
]
`, routes)