Fix UI custom header values (#10511)

* Fix UI custom header values

* Fix changelog entry

* Introduce param for multi values

* Fix multivalue

* multivalue should be bool

* Sort imports

* Fix conflict

* Remove changelog entry

* Revert entry delete
This commit is contained in:
Michel Vocks 2020-12-15 15:58:03 +01:00 committed by GitHub
parent fc9fa540af
commit 191aa65bc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 25 deletions

3
changelog/10490.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
api/sys/config/ui: Fixes issue where multiple UI custom header values are ignored and only the first given value is used
```

View File

@ -2432,18 +2432,28 @@ func (b *SystemBackend) handleDisableAudit(ctx context.Context, req *logical.Req
func (b *SystemBackend) handleConfigUIHeadersRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { func (b *SystemBackend) handleConfigUIHeadersRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
header := data.Get("header").(string) header := data.Get("header").(string)
multivalue := data.Get("multivalue").(bool)
value, err := b.Core.uiConfig.GetHeader(ctx, header) values, err := b.Core.uiConfig.GetHeader(ctx, header)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if value == "" { if len(values) == 0 {
return nil, nil return nil, nil
} }
// Return multiple values if specified
if multivalue {
return &logical.Response{
Data: map[string]interface{}{
"values": values,
},
}, nil
}
return &logical.Response{ return &logical.Response{
Data: map[string]interface{}{ Data: map[string]interface{}{
"value": value, "value": values[0],
}, },
}, nil }, nil
} }
@ -2477,7 +2487,7 @@ func (b *SystemBackend) handleConfigUIHeadersUpdate(ctx context.Context, req *lo
for _, v := range values { for _, v := range values {
value.Add(header, v) value.Add(header, v)
} }
err := b.Core.uiConfig.SetHeader(ctx, header, value.Get(header)) err := b.Core.uiConfig.SetHeader(ctx, header, value.Values(header))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -71,6 +71,10 @@ func (b *SystemBackend) configPaths() []*framework.Path {
Type: framework.TypeStringSlice, Type: framework.TypeStringSlice,
Description: "The values to set the header.", Description: "The values to set the header.",
}, },
"multivalue": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Returns multiple values if true",
},
}, },
Operations: map[logical.Operation]framework.OperationHandler{ Operations: map[logical.Operation]framework.OperationHandler{

View File

@ -92,25 +92,25 @@ func (c *UIConfig) HeaderKeys(ctx context.Context) ([]string, error) {
return keys, nil return keys, nil
} }
// GetHeader retrieves the configured value for the given header // GetHeader retrieves the configured values for the given header
func (c *UIConfig) GetHeader(ctx context.Context, header string) (string, error) { func (c *UIConfig) GetHeader(ctx context.Context, header string) ([]string, error) {
c.l.RLock() c.l.RLock()
defer c.l.RUnlock() defer c.l.RUnlock()
config, err := c.get(ctx) config, err := c.get(ctx)
if err != nil { if err != nil {
return "", err return nil, err
} }
if config == nil { if config == nil {
return "", nil return nil, nil
} }
value := config.Headers.Get(header) value := config.Headers.Values(header)
return value, nil return value, nil
} }
// SetHeader sets the value for the given header // SetHeader sets the values for the given header
func (c *UIConfig) SetHeader(ctx context.Context, header, value string) error { func (c *UIConfig) SetHeader(ctx context.Context, header string, values []string) error {
c.l.Lock() c.l.Lock()
defer c.l.Unlock() defer c.l.Unlock()
@ -123,7 +123,14 @@ func (c *UIConfig) SetHeader(ctx context.Context, header, value string) error {
Headers: http.Header{}, Headers: http.Header{},
} }
} }
config.Headers.Set(header, value)
// Clear custom header values before setting new
config.Headers.Del(header)
// Set new values
for _, value := range values {
config.Headers.Add(header, value)
}
return c.save(ctx, config) return c.save(ctx, config)
} }

View File

@ -51,10 +51,10 @@ func TestConfig_Headers(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if head != "" { if len(head) != 0 {
t.Fatal("header returned found, should not be found") t.Fatal("header returned found, should not be found")
} }
err = config.SetHeader(context.Background(), "Test-Header", "123") err = config.SetHeader(context.Background(), "Test-Header", []string{"123", "456"})
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
@ -62,22 +62,28 @@ func TestConfig_Headers(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if head == "" { if len(head) != 2 {
t.Fatal("header not found when it should be") t.Fatalf("header not found or incorrect number of values: %#v", head)
} }
if head != "123" { if head[0] != "123" {
t.Fatalf("expected: %s, got: %s", "123", head) t.Fatalf("expected: %s, got: %s", "123", head[0])
}
if head[1] != "456" {
t.Fatalf("expected: %s, got: %s", "456", head[1])
} }
head, err = config.GetHeader(context.Background(), "tEST-hEADER") head, err = config.GetHeader(context.Background(), "tEST-hEADER")
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if head == "" { if len(head) != 2 {
t.Fatal("header not found when it should be") t.Fatalf("header not found or incorrect number of values: %#v", head)
} }
if head != "123" { if head[0] != "123" {
t.Fatalf("expected: %s, got: %s", "123", head) t.Fatalf("expected: %s, got: %s", "123", head[0])
}
if head[1] != "456" {
t.Fatalf("expected: %s, got: %s", "456", head[1])
} }
keys, err := config.HeaderKeys(context.Background()) keys, err := config.HeaderKeys(context.Background())
@ -88,7 +94,7 @@ func TestConfig_Headers(t *testing.T) {
t.Fatalf("expected 1 key, got %d", len(keys)) t.Fatalf("expected 1 key, got %d", len(keys))
} }
err = config.SetHeader(context.Background(), "Test-Header-2", "321") err = config.SetHeader(context.Background(), "Test-Header-2", []string{"321"})
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
@ -112,7 +118,7 @@ func TestConfig_Headers(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }
if head != "" { if len(head) != 0 {
t.Fatal("header returned found, should not be found") t.Fatal("header returned found, should not be found")
} }
keys, err = config.HeaderKeys(context.Background()) keys, err = config.HeaderKeys(context.Background())
@ -151,7 +157,7 @@ func TestConfig_DefaultHeaders(t *testing.T) {
t.Fatalf("header does not match: expected %s, got %s", defaultCSP, head) t.Fatalf("header does not match: expected %s, got %s", defaultCSP, head)
} }
err = config.SetHeader(context.Background(), "Content-security-Policy", "test") err = config.SetHeader(context.Background(), "Content-security-Policy", []string{"test"})
if err != nil { if err != nil {
t.Fatalf("err: %v", err) t.Fatalf("err: %v", err)
} }

View File

@ -24,6 +24,8 @@ This endpoint returns the given UI header configuration.
- `name` `(string: <required>)`  The name of the custom header. - `name` `(string: <required>)`  The name of the custom header.
- `multivalue` `(bool: <optional>)` - Returns multiple values if true.
### Sample Request ### Sample Request
```shell-session ```shell-session
@ -40,6 +42,22 @@ $ curl \
} }
``` ```
### Sample Request (Multi value)
```shell-session
$ curl \
--header "X-Vault-Token: ..." \
http://127.0.0.1:8200/v1/sys/config/ui/headers/X-Custom-Header?multivalue=true
```
### Sample Response
```json
{
"values": ["custom-value-1", "custom-value-2"]
}
```
## Configure UI Headers ## Configure UI Headers
This endpoint allows configuring the values to be returned for the UI header. This endpoint allows configuring the values to be returned for the UI header.