mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 19:47:54 +00:00
Use capabilities to determine upsert-ability in transit.
This commit is contained in:
@@ -39,6 +39,19 @@ func TestBackend_basic(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestBackend_upsert(t *testing.T) {
|
||||
decryptData := make(map[string]interface{})
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
Factory: Factory,
|
||||
Steps: []logicaltest.TestStep{
|
||||
testAccStepReadPolicy(t, "test", true, false),
|
||||
testAccStepEncryptUpsert(t, "test", testPlaintext, decryptData),
|
||||
testAccStepReadPolicy(t, "test", false, false),
|
||||
testAccStepDecrypt(t, "test", testPlaintext, decryptData),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestBackend_datakey(t *testing.T) {
|
||||
dataKeyInfo := make(map[string]interface{})
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
@@ -268,6 +281,30 @@ func testAccStepEncrypt(
|
||||
}
|
||||
}
|
||||
|
||||
func testAccStepEncryptUpsert(
|
||||
t *testing.T, name, plaintext string, decryptData map[string]interface{}) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.CreateOperation,
|
||||
Path: "encrypt/" + name,
|
||||
Data: map[string]interface{}{
|
||||
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
|
||||
},
|
||||
Check: func(resp *logical.Response) error {
|
||||
var d struct {
|
||||
Ciphertext string `mapstructure:"ciphertext"`
|
||||
}
|
||||
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
||||
return err
|
||||
}
|
||||
if d.Ciphertext == "" {
|
||||
return fmt.Errorf("missing ciphertext")
|
||||
}
|
||||
decryptData["ciphertext"] = d.Ciphertext
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testAccStepEncryptContext(
|
||||
t *testing.T, name, plaintext, context string, decryptData map[string]interface{}) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
|
||||
@@ -30,14 +30,28 @@ func (b *backend) pathEncrypt() *framework.Path {
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.CreateOperation: b.pathEncryptWrite,
|
||||
logical.UpdateOperation: b.pathEncryptWrite,
|
||||
},
|
||||
|
||||
ExistenceCheck: b.pathEncryptExistenceCheck,
|
||||
|
||||
HelpSynopsis: pathEncryptHelpSyn,
|
||||
HelpDescription: pathEncryptHelpDesc,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *backend) pathEncryptExistenceCheck(
|
||||
req *logical.Request, d *framework.FieldData) (bool, error) {
|
||||
name := d.Get("name").(string)
|
||||
lp, err := b.policies.getPolicy(req, name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return lp != nil, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathEncryptWrite(
|
||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
name := d.Get("name").(string)
|
||||
@@ -65,7 +79,19 @@ func (b *backend) pathEncryptWrite(
|
||||
|
||||
// Error if invalid policy
|
||||
if lp == nil {
|
||||
return logical.ErrorResponse("policy not found"), logical.ErrInvalidRequest
|
||||
if req.Operation != logical.CreateOperation {
|
||||
return logical.ErrorResponse("policy not found"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
isDerived := len(context) != 0
|
||||
|
||||
lp, err = b.policies.generatePolicy(req.Storage, name, isDerived)
|
||||
// If the error is that the policy has been created in the interim we
|
||||
// will get the policy back, so only consider it an error if err is not
|
||||
// nil and we do not get a policy back
|
||||
if err != nil && lp != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
lp.RLock()
|
||||
|
||||
@@ -48,14 +48,15 @@ endpoint. Since the `default` policy contains `auth/token/renew-self` this
|
||||
makes it much more likely that the request will succeed rather than somewhat
|
||||
confusingly failing due to a lack of permissions on `auth/token/renew`.
|
||||
|
||||
## Transit No Longer Upserts Keys By Default
|
||||
## Transit Upsertion Behavior Uses Capabilities
|
||||
|
||||
Previously, attempting to encrypt with a key that did not exist would create a
|
||||
key with default values. This was convenient but ultimately allowed a client to
|
||||
potentially escape an ACL policy restriction, albeit without any dangerous
|
||||
access. However, this is now disabled by default. If you want to enable this
|
||||
behavior, you can use the `allow_upsert` parameter to the new `transit/config`
|
||||
endpoint to turn it back on.
|
||||
access. Now that Vault supports more granular capabilities in policies,
|
||||
upsertion behavior is controlled by whether the client has the `create`
|
||||
capability for the request (upsertion is allowed) or only the `update`
|
||||
capability (upsertion is denied).
|
||||
|
||||
## etcd Physical Backend Uses `sync`
|
||||
|
||||
|
||||
@@ -305,7 +305,13 @@ only encrypt or decrypt using the named keys they need access to.
|
||||
<dl class="api">
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Encrypts the provided plaintext using the named key.
|
||||
Encrypts the provided plaintext using the named key. This path supports the
|
||||
`create` and `update` policy capabilities as follows: if the user has the
|
||||
`create` capability for this endpoint in their policies, and the key does
|
||||
not exist, it will be upserted with default values (whether the key
|
||||
requires derivation depends on whether the context parameter is empty or
|
||||
not). If the user only has `update` capability and the key does not exist,
|
||||
an error will be returned.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
|
||||
Reference in New Issue
Block a user