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) {
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{
|
||||||
|
|
23
vault/ui.go
23
vault/ui.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue