config: do not add route headers to global map (#4630)

config: do not add route headers to global map (#4629)

Currently the GetSetResponseHeadersForPolicy() method may add entries to 
the global SetResponseHeaders map, which can lead to one route's headers
being applied to other routes.

Instead, make a copy of the SetResponseHeaders map before adding any 
route-specific response header entries.

Add additional unit tests for GetSetResponseHeaders() and 
GetSetResponseHeadersForPolicy().

Co-authored-by: Kenneth Jenkins <51246568+kenjenkins@users.noreply.github.com>
This commit is contained in:
backport-actions-token[bot] 2023-10-18 14:19:48 -07:00 committed by GitHub
parent 9f56ab2b00
commit c32005d0fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 3 deletions

View file

@ -1121,9 +1121,12 @@ func (o *Options) GetSetResponseHeaders() map[string]string {
// GetSetResponseHeadersForPolicy gets the SetResponseHeaders for a policy.
func (o *Options) GetSetResponseHeadersForPolicy(policy *Policy) map[string]string {
hdrs := o.SetResponseHeaders
if hdrs == nil {
hdrs = make(map[string]string)
hdrs := make(map[string]string)
for k, v := range o.SetResponseHeaders {
hdrs[k] = v
}
if o.SetResponseHeaders == nil {
for k, v := range defaultSetResponseHeaders {
hdrs[k] = v
}

View file

@ -978,6 +978,18 @@ func TestOptions_GetSetResponseHeaders(t *testing.T) {
options.SetResponseHeaders = map[string]string{DisableHeaderKey: "1", "x-other": "xyz"}
assert.Equal(t, map[string]string{}, options.GetSetResponseHeaders())
})
t.Run("empty", func(t *testing.T) {
options := NewDefaultOptions()
options.SetResponseHeaders = map[string]string{}
assert.Equal(t, map[string]string{}, options.GetSetResponseHeaders())
})
t.Run("no partial defaults", func(t *testing.T) {
options := NewDefaultOptions()
options.Cert = "CERT"
options.SetResponseHeaders = map[string]string{"X-Frame-Options": "DENY"}
assert.Equal(t, map[string]string{"X-Frame-Options": "DENY"},
options.GetSetResponseHeaders())
})
}
func TestOptions_GetSetResponseHeadersForPolicy(t *testing.T) {
@ -989,6 +1001,50 @@ func TestOptions_GetSetResponseHeadersForPolicy(t *testing.T) {
}
assert.Equal(t, map[string]string{"x": "y"}, options.GetSetResponseHeadersForPolicy(policy))
})
t.Run("global defaults plus policy", func(t *testing.T) {
options := NewDefaultOptions()
options.Cert = "CERT"
policy := &Policy{
SetResponseHeaders: map[string]string{"Route": "xyz"},
}
assert.Equal(t, map[string]string{
"Route": "xyz",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
"X-Frame-Options": "SAMEORIGIN",
"X-XSS-Protection": "1; mode=block",
}, options.GetSetResponseHeadersForPolicy(policy))
})
t.Run("global defaults partial override", func(t *testing.T) {
options := NewDefaultOptions()
options.Cert = "CERT"
policy := &Policy{
SetResponseHeaders: map[string]string{"X-Frame-Options": "DENY"},
}
assert.Equal(t, map[string]string{
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
}, options.GetSetResponseHeadersForPolicy(policy))
})
t.Run("multiple policies", func(t *testing.T) {
options := NewDefaultOptions()
options.SetResponseHeaders = map[string]string{"global": "foo"}
p1 := &Policy{
SetResponseHeaders: map[string]string{"route-1": "bar"},
}
p2 := &Policy{
SetResponseHeaders: map[string]string{"route-2": "baz"},
}
assert.Equal(t, map[string]string{
"global": "foo",
"route-1": "bar",
}, options.GetSetResponseHeadersForPolicy(p1))
assert.Equal(t, map[string]string{
"global": "foo",
"route-2": "baz",
}, options.GetSetResponseHeadersForPolicy(p2))
assert.Equal(t, map[string]string{"global": "foo"}, options.GetSetResponseHeaders())
})
}
func TestOptions_GetSharedKey(t *testing.T) {