Implement locking in the transit backend.

This ensures that we can safely rotate and modify configuration
parameters with multiple requests in flight.

As a side effect we also get a cache, which should provide a nice
speedup since we don't need to decrypt/deserialize constantly, which
would happen even with the physical LRU.
This commit is contained in:
Jeff Mitchell
2016-01-27 16:24:11 -05:00
parent ba03981739
commit 46514e01fa
11 changed files with 403 additions and 217 deletions

View File

@@ -10,7 +10,7 @@ import (
"github.com/hashicorp/vault/logical/framework"
)
func pathDatakey() *framework.Path {
func (b *backend) pathDatakey() *framework.Path {
return &framework.Path{
Pattern: "datakey/" + framework.GenericNameRegex("plaintext") + "/" + framework.GenericNameRegex("name"),
Fields: map[string]*framework.FieldSchema{
@@ -39,7 +39,7 @@ and 512 bits are supported. Defaults to 256.`,
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: pathDatakeyWrite,
logical.UpdateOperation: b.pathDatakeyWrite,
},
HelpSynopsis: pathDatakeyHelpSyn,
@@ -47,7 +47,7 @@ and 512 bits are supported. Defaults to 256.`,
}
}
func pathDatakeyWrite(
func (b *backend) pathDatakeyWrite(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
name := d.Get("name").(string)
@@ -73,16 +73,24 @@ func pathDatakeyWrite(
}
// Get the policy
p, err := getPolicy(req, name)
lp, err := b.policies.getPolicy(req, name)
if err != nil {
return nil, err
}
// Error if invalid policy
if p == nil {
if lp == nil {
return logical.ErrorResponse("policy not found"), logical.ErrInvalidRequest
}
lp.lock.RLock()
defer lp.lock.RUnlock()
// Verify if wasn't deleted before we grabbed the lock
if lp.policy == nil {
return nil, fmt.Errorf("policy %s found in cache but no longer valid after lock", name)
}
newKey := make([]byte, 32)
bits := d.Get("bits").(int)
switch bits {
@@ -99,7 +107,7 @@ func pathDatakeyWrite(
return nil, err
}
ciphertext, err := p.Encrypt(context, base64.StdEncoding.EncodeToString(newKey))
ciphertext, err := lp.policy.Encrypt(context, base64.StdEncoding.EncodeToString(newKey))
if err != nil {
switch err.(type) {
case certutil.UserError: