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:
parent
fc9fa540af
commit
191aa65bc3
|
@ -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
|
||||
```
|
|
@ -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) {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
if value == "" {
|
||||
if len(values) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Return multiple values if specified
|
||||
if multivalue {
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"values": values,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"value": value,
|
||||
"value": values[0],
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
@ -2477,7 +2487,7 @@ func (b *SystemBackend) handleConfigUIHeadersUpdate(ctx context.Context, req *lo
|
|||
for _, v := range values {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@ func (b *SystemBackend) configPaths() []*framework.Path {
|
|||
Type: framework.TypeStringSlice,
|
||||
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{
|
||||
|
|
23
vault/ui.go
23
vault/ui.go
|
@ -92,25 +92,25 @@ func (c *UIConfig) HeaderKeys(ctx context.Context) ([]string, error) {
|
|||
return keys, nil
|
||||
}
|
||||
|
||||
// GetHeader retrieves the configured value for the given header
|
||||
func (c *UIConfig) GetHeader(ctx context.Context, header string) (string, error) {
|
||||
// GetHeader retrieves the configured values for the given header
|
||||
func (c *UIConfig) GetHeader(ctx context.Context, header string) ([]string, error) {
|
||||
c.l.RLock()
|
||||
defer c.l.RUnlock()
|
||||
|
||||
config, err := c.get(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
if config == nil {
|
||||
return "", nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
value := config.Headers.Get(header)
|
||||
value := config.Headers.Values(header)
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// SetHeader sets the value for the given header
|
||||
func (c *UIConfig) SetHeader(ctx context.Context, header, value string) error {
|
||||
// SetHeader sets the values for the given header
|
||||
func (c *UIConfig) SetHeader(ctx context.Context, header string, values []string) error {
|
||||
c.l.Lock()
|
||||
defer c.l.Unlock()
|
||||
|
||||
|
@ -123,7 +123,14 @@ func (c *UIConfig) SetHeader(ctx context.Context, header, value string) error {
|
|||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -51,10 +51,10 @@ func TestConfig_Headers(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if head != "" {
|
||||
if len(head) != 0 {
|
||||
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 {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -62,22 +62,28 @@ func TestConfig_Headers(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if head == "" {
|
||||
t.Fatal("header not found when it should be")
|
||||
if len(head) != 2 {
|
||||
t.Fatalf("header not found or incorrect number of values: %#v", head)
|
||||
}
|
||||
if head != "123" {
|
||||
t.Fatalf("expected: %s, got: %s", "123", head)
|
||||
if head[0] != "123" {
|
||||
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")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if head == "" {
|
||||
t.Fatal("header not found when it should be")
|
||||
if len(head) != 2 {
|
||||
t.Fatalf("header not found or incorrect number of values: %#v", head)
|
||||
}
|
||||
if head != "123" {
|
||||
t.Fatalf("expected: %s, got: %s", "123", head)
|
||||
if head[0] != "123" {
|
||||
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())
|
||||
|
@ -88,7 +94,7 @@ func TestConfig_Headers(t *testing.T) {
|
|||
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 {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
@ -112,7 +118,7 @@ func TestConfig_Headers(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if head != "" {
|
||||
if len(head) != 0 {
|
||||
t.Fatal("header returned found, should not be found")
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
err = config.SetHeader(context.Background(), "Content-security-Policy", "test")
|
||||
err = config.SetHeader(context.Background(), "Content-security-Policy", []string{"test"})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ This endpoint returns the given UI header configuration.
|
|||
|
||||
- `name` `(string: <required>)` – The name of the custom header.
|
||||
|
||||
- `multivalue` `(bool: <optional>)` - Returns multiple values if true.
|
||||
|
||||
### Sample Request
|
||||
|
||||
```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
|
||||
|
||||
This endpoint allows configuring the values to be returned for the UI header.
|
||||
|
|
Loading…
Reference in New Issue