mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 17:52:32 +00:00
Fix for KV_V2 Custom Metadata Bug (#17395)
This commit is contained in:
@@ -319,13 +319,66 @@ func TestExtractCustomMetadata(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: map[string]interface{}{"org": "eng"},
|
expected: map[string]interface{}{"org": "eng"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "a read response with no custom metadata from a pre-1.9 Vault server",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"metadata": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a write response with no custom metadata from a pre-1.9 Vault server",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a read response with no custom metadata from a post-1.9 Vault server",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"custom_metadata": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a write response with no custom metadata from a post-1.9 Vault server",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"custom_metadata": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a read response where custom metadata was deleted",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"custom_metadata": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a write response where custom metadata was deleted",
|
||||||
|
inputAPIResp: &Secret{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"custom_metadata": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: map[string]interface{}{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
cm, err := extractCustomMetadata(tc.inputAPIResp)
|
cm := extractCustomMetadata(tc.inputAPIResp)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(cm, tc.expected) {
|
if !reflect.DeepEqual(cm, tc.expected) {
|
||||||
t.Fatalf("%s: got\n%#v\nexpected\n%#v\n", tc.name, cm, tc.expected)
|
t.Fatalf("%s: got\n%#v\nexpected\n%#v\n", tc.name, cm, tc.expected)
|
||||||
|
|||||||
44
api/kv_v2.go
44
api/kv_v2.go
@@ -125,11 +125,7 @@ func (kv *KVv2) Get(ctx context.Context, secretPath string) (*KVSecret, error) {
|
|||||||
return nil, fmt.Errorf("error parsing secret at %s: %w", pathToRead, err)
|
return nil, fmt.Errorf("error parsing secret at %s: %w", pathToRead, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := extractCustomMetadata(secret)
|
kvSecret.CustomMetadata = extractCustomMetadata(secret)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading custom metadata for secret at %s: %w", pathToRead, err)
|
|
||||||
}
|
|
||||||
kvSecret.CustomMetadata = cm
|
|
||||||
|
|
||||||
return kvSecret, nil
|
return kvSecret, nil
|
||||||
}
|
}
|
||||||
@@ -159,11 +155,7 @@ func (kv *KVv2) GetVersion(ctx context.Context, secretPath string, version int)
|
|||||||
return nil, fmt.Errorf("error parsing secret at %s: %w", pathToRead, err)
|
return nil, fmt.Errorf("error parsing secret at %s: %w", pathToRead, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := extractCustomMetadata(secret)
|
kvSecret.CustomMetadata = extractCustomMetadata(secret)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading custom metadata for secret at %s: %w", pathToRead, err)
|
|
||||||
}
|
|
||||||
kvSecret.CustomMetadata = cm
|
|
||||||
|
|
||||||
return kvSecret, nil
|
return kvSecret, nil
|
||||||
}
|
}
|
||||||
@@ -260,11 +252,7 @@ func (kv *KVv2) Put(ctx context.Context, secretPath string, data map[string]inte
|
|||||||
Raw: secret,
|
Raw: secret,
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := extractCustomMetadata(secret)
|
kvSecret.CustomMetadata = extractCustomMetadata(secret)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading custom metadata for secret at %s: %w", pathToWriteTo, err)
|
|
||||||
}
|
|
||||||
kvSecret.CustomMetadata = cm
|
|
||||||
|
|
||||||
return kvSecret, nil
|
return kvSecret, nil
|
||||||
}
|
}
|
||||||
@@ -497,30 +485,24 @@ func (kv *KVv2) Rollback(ctx context.Context, secretPath string, toVersion int)
|
|||||||
return kvs, nil
|
return kvs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractCustomMetadata(secret *Secret) (map[string]interface{}, error) {
|
func extractCustomMetadata(secret *Secret) map[string]interface{} {
|
||||||
// Logical Writes return the metadata directly, Reads return it nested inside the "metadata" key
|
// Logical Writes return the metadata directly, Reads return it nested inside the "metadata" key
|
||||||
customMetadataInterface, ok := secret.Data["custom_metadata"]
|
customMetadataInterface, ok := secret.Data["custom_metadata"]
|
||||||
if !ok {
|
if !ok {
|
||||||
metadataInterface, ok := secret.Data["metadata"]
|
metadataInterface := secret.Data["metadata"]
|
||||||
if !ok { // if that's not found, bail since it should have had one or the other
|
|
||||||
return nil, fmt.Errorf("secret is missing expected fields")
|
|
||||||
}
|
|
||||||
metadataMap, ok := metadataInterface.(map[string]interface{})
|
metadataMap, ok := metadataInterface.(map[string]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected type for 'metadata' element: %T (%#v)", metadataInterface, metadataInterface)
|
return nil
|
||||||
}
|
|
||||||
customMetadataInterface, ok = metadataMap["custom_metadata"]
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("metadata missing expected field \"custom_metadata\": %v", metadataMap)
|
|
||||||
}
|
}
|
||||||
|
customMetadataInterface = metadataMap["custom_metadata"]
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, ok := customMetadataInterface.(map[string]interface{})
|
cm, ok := customMetadataInterface.(map[string]interface{})
|
||||||
if !ok && customMetadataInterface != nil {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unexpected type for 'metadata' element: %T (%#v)", customMetadataInterface, customMetadataInterface)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return cm, nil
|
return cm
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractDataAndVersionMetadata(secret *Secret) (*KVSecret, error) {
|
func extractDataAndVersionMetadata(secret *Secret) (*KVSecret, error) {
|
||||||
@@ -724,11 +706,7 @@ func mergePatch(ctx context.Context, client *Client, mountPath string, secretPat
|
|||||||
Raw: secret,
|
Raw: secret,
|
||||||
}
|
}
|
||||||
|
|
||||||
cm, err := extractCustomMetadata(secret)
|
kvSecret.CustomMetadata = extractCustomMetadata(secret)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error reading custom metadata for secret %s: %w", secretPath, err)
|
|
||||||
}
|
|
||||||
kvSecret.CustomMetadata = cm
|
|
||||||
|
|
||||||
return kvSecret, nil
|
return kvSecret, nil
|
||||||
}
|
}
|
||||||
|
|||||||
3
changelog/17395.txt
Normal file
3
changelog/17395.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:bug:
|
||||||
|
api: Fix to account for older versions of Vault with no `custom_metadata` support
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user