Transit UX improvements: show key policy, configs on write (#20652)

* Respond with cache size on config write

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Respond with key policy on write

This includes creating a key, but also trimming or rotating an
existing key.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add changelog entry

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Correctly handle locking around policy formatting

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Validate that responses are non-empty

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

---------

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
Alexander Scheel 2023-05-18 14:36:10 -04:00 committed by GitHub
parent f219d7a77c
commit f9fdac0345
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 35 deletions

View File

@ -1071,9 +1071,7 @@ func testConvergentEncryptionCommon(t *testing.T, ver int, keyType keysutil.KeyT
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp != nil { require.NotNil(t, resp, "expected populated request")
t.Fatal("expected nil response")
}
p, err := keysutil.LoadPolicy(context.Background(), storage, path.Join("policy", "testkey")) p, err := keysutil.LoadPolicy(context.Background(), storage, path.Join("policy", "testkey"))
if err != nil { if err != nil {
@ -1559,9 +1557,7 @@ func TestBadInput(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp != nil { require.NotNil(t, resp, "expected populated request")
t.Fatal("expected nil response")
}
req.Path = "decrypt/test" req.Path = "decrypt/test"
req.Data = map[string]interface{}{ req.Data = map[string]interface{}{
@ -1650,9 +1646,7 @@ func TestTransit_AutoRotateKeys(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp != nil { require.NotNil(t, resp, "expected populated request")
t.Fatal("expected nil response")
}
// Write a key with an auto rotate value one day in the future // Write a key with an auto rotate value one day in the future
req = &logical.Request{ req = &logical.Request{
@ -1667,9 +1661,7 @@ func TestTransit_AutoRotateKeys(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp != nil { require.NotNil(t, resp, "expected populated request")
t.Fatal("expected nil response")
}
// Run the rotation check and ensure none of the keys have rotated // Run the rotation check and ensure none of the keys have rotated
b.checkAutoRotateAfter = time.Now() b.checkAutoRotateAfter = time.Now()

View File

@ -84,7 +84,11 @@ func (b *backend) pathCacheConfigWrite(ctx context.Context, req *logical.Request
return nil, err return nil, err
} }
return nil, nil return &logical.Response{
Data: map[string]interface{}{
"size": cacheSize,
},
}, nil
} }
type configCache struct { type configCache struct {

View File

@ -257,12 +257,14 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
p.Unlock() p.Unlock()
} }
resp := &logical.Response{} resp, err := b.formatKeyPolicy(p, nil)
if err != nil {
return nil, err
}
if !upserted { if !upserted {
resp.AddWarning(fmt.Sprintf("key %s already existed", name)) resp.AddWarning(fmt.Sprintf("key %s already existed", name))
} }
return resp, nil
return nil, nil
} }
// Built-in helper type for returning asymmetric keys // Built-in helper type for returning asymmetric keys
@ -290,6 +292,19 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
} }
defer p.Unlock() defer p.Unlock()
contextRaw := d.Get("context").(string)
var context []byte
if len(contextRaw) != 0 {
context, err = base64.StdEncoding.DecodeString(contextRaw)
if err != nil {
return logical.ErrorResponse("failed to base64-decode context"), logical.ErrInvalidRequest
}
}
return b.formatKeyPolicy(p, context)
}
func (b *backend) formatKeyPolicy(p *keysutil.Policy, context []byte) (*logical.Response, error) {
// Return the response // Return the response
resp := &logical.Response{ resp := &logical.Response{
Data: map[string]interface{}{ Data: map[string]interface{}{
@ -346,15 +361,6 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
} }
} }
contextRaw := d.Get("context").(string)
var context []byte
if len(contextRaw) != 0 {
context, err = base64.StdEncoding.DecodeString(contextRaw)
if err != nil {
return logical.ErrorResponse("failed to base64-decode context"), logical.ErrInvalidRequest
}
}
switch p.Type { switch p.Type {
case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305: case keysutil.KeyType_AES128_GCM96, keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
retKeys := map[string]int64{} retKeys := map[string]int64{}

View File

@ -97,6 +97,8 @@ func (b *backend) pathKeysConfigWrite(ctx context.Context, req *logical.Request,
} }
defer p.Unlock() defer p.Unlock()
var warning string
originalMinDecryptionVersion := p.MinDecryptionVersion originalMinDecryptionVersion := p.MinDecryptionVersion
originalMinEncryptionVersion := p.MinEncryptionVersion originalMinEncryptionVersion := p.MinEncryptionVersion
originalDeletionAllowed := p.DeletionAllowed originalDeletionAllowed := p.DeletionAllowed
@ -113,8 +115,6 @@ func (b *backend) pathKeysConfigWrite(ctx context.Context, req *logical.Request,
} }
}() }()
resp = &logical.Response{}
persistNeeded := false persistNeeded := false
minDecryptionVersionRaw, ok := d.GetOk("min_decryption_version") minDecryptionVersionRaw, ok := d.GetOk("min_decryption_version")
@ -127,7 +127,7 @@ func (b *backend) pathKeysConfigWrite(ctx context.Context, req *logical.Request,
if minDecryptionVersion == 0 { if minDecryptionVersion == 0 {
minDecryptionVersion = 1 minDecryptionVersion = 1
resp.AddWarning("since Vault 0.3, transit key numbering starts at 1; forcing minimum to 1") warning = "since Vault 0.3, transit key numbering starts at 1; forcing minimum to 1"
} }
if minDecryptionVersion != p.MinDecryptionVersion { if minDecryptionVersion != p.MinDecryptionVersion {
@ -221,7 +221,14 @@ func (b *backend) pathKeysConfigWrite(ctx context.Context, req *logical.Request,
} }
if !persistNeeded { if !persistNeeded {
return nil, nil resp, err := b.formatKeyPolicy(p, nil)
if err != nil {
return nil, err
}
if warning != "" {
resp.AddWarning(warning)
}
return resp, nil
} }
switch { switch {
@ -231,11 +238,18 @@ func (b *backend) pathKeysConfigWrite(ctx context.Context, req *logical.Request,
return logical.ErrorResponse("min decryption version should not be less then min available version"), nil return logical.ErrorResponse("min decryption version should not be less then min available version"), nil
} }
if len(resp.Warnings) == 0 { if err := p.Persist(ctx, req.Storage); err != nil {
return nil, p.Persist(ctx, req.Storage) return nil, err
} }
return resp, p.Persist(ctx, req.Storage) resp, err = b.formatKeyPolicy(p, nil)
if err != nil {
return nil, err
}
if warning != "" {
resp.AddWarning(warning)
}
return resp, nil
} }
const pathKeysConfigHelpSyn = `Configure a named encryption key` const pathKeysConfigHelpSyn = `Configure a named encryption key`

View File

@ -64,6 +64,7 @@ func (b *backend) pathRotateWrite(ctx context.Context, req *logical.Request, d *
if !b.System().CachingDisabled() { if !b.System().CachingDisabled() {
p.Lock(true) p.Lock(true)
} }
defer p.Unlock()
if p.Type == keysutil.KeyType_MANAGED_KEY { if p.Type == keysutil.KeyType_MANAGED_KEY {
var keyId string var keyId string
@ -78,8 +79,11 @@ func (b *backend) pathRotateWrite(ctx context.Context, req *logical.Request, d *
err = p.Rotate(ctx, req.Storage, b.GetRandomReader()) err = p.Rotate(ctx, req.Storage, b.GetRandomReader())
} }
p.Unlock() if err != nil {
return nil, err return nil, err
}
return b.formatKeyPolicy(p, nil)
} }
const pathRotateHelpSyn = `Rotate named encryption key` const pathRotateHelpSyn = `Rotate named encryption key`

View File

@ -100,7 +100,7 @@ func (b *backend) pathTrimUpdate() framework.OperationFunc {
return nil, err return nil, err
} }
return nil, nil return b.formatKeyPolicy(p, nil)
} }
} }

3
changelog/20652.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
secrets/transit: Respond to writes with updated key policy, cache configuration.
```