vault/builtin/logical/transit/path_datakey_test.go
Vault Automation caf642b7d2
Backport Vault 42177 Add Backend Field into ce/main (#12152)
* Vault 42177 Add Backend Field (#12092)

* add a new struct for the total number of successful requests for transit and transform

* implement tracking for encrypt path

* implement tracking in encrypt path

* add tracking in rewrap

* add tracking to datakey path

* add tracking to  hmac path

* add tracking to sign  path

* add tracking to verify path

* unit tests for verify path

* add tracking to cmac path

* reset the global counter in each unit test

* add tracking to hmac verify

* add methods to retrieve and flush transit count

* modify the methods that store and update data protection call counts

* update the methods

* add a helper method to combine replicated and local data call counts

* add tracking to the endpoint

* fix some formatting errors

* add unit tests to path encrypt for tracking

* add unit tests to decrypt path

* fix linter error

* add unit tests to test update and store methods for data protection calls

* stub fix: do not create separate files

* fix the tracking by coordinating replicated and local data, add unit tests

* update all reference to the new data struct

* revert to previous design with just one global counter for all calls for each cluster

* complete external test

* no need to check if current count is greater than 0, remove it

* feedback: remove unnacassary comments about atomic addition, standardize comments

* leave jira id on todo comment, remove unused method

* rename mathods by removing HWM and max in names, update jira id in todo comment, update response field key name

* feedback: remove explicit counter in cmac tests, instead put in the expected number

* feedback: remove explicit tracking in the rest of the tests

* feedback: separate transit testing into its own external test

* Update vault/consumption_billing_util_test.go

Co-authored-by: divyaac <divya.chandrasekaran@hashicorp.com>

* update comment after test name change

* fix comments

* fix comments in test

* another comment fix

* feedback: remove incorrect comment

* fix a CE test

* fix the update method: instead of storing max, increment by the current count value

* update the unit test, remove local prefix as argument to the methods since we store only to non-replicated paths

* update the external test

* Adds a field to backend to track billing data

removed file

* Changed implementation to use a map instead

* Some more comments

* Add more implementation

* Edited grpc server backend

* Refactored a bit

* Fix one more test

* Modified map:

* Revert "Modified map:"

This reverts commit 1730fe1f358b210e6abae43fbdca09e585aaaaa8.

* Removed some other things

* Edited consumption billing files a bit

* Testing function

* Fix transit stuff and make sure tests pass

* Changes

* More changes

* More changes

* Edited external test

* Edited some more tests

* Edited and fixed tests

* One more fix

* Fix some more tests

* Moved some testing structures around and added error checking

* Fixed some nits

* Update builtin/logical/transit/path_sign_verify.go

Co-authored-by: Nick Cabatoff <ncabatoff@hashicorp.com>

* Edited some errors

* Fixed error logs

* Edited one more thing

* Decorate the error

* Update vault/consumption_billing.go

Co-authored-by: Nick Cabatoff <ncabatoff@hashicorp.com>

---------

Co-authored-by: Amir Aslamov <amir.aslamov@hashicorp.com>
Co-authored-by: Nick Cabatoff <ncabatoff@hashicorp.com>

* Edited stub function

---------

Co-authored-by: divyaac <divya.chandrasekaran@hashicorp.com>
Co-authored-by: Amir Aslamov <amir.aslamov@hashicorp.com>
Co-authored-by: Nick Cabatoff <ncabatoff@hashicorp.com>
Co-authored-by: divyaac <divyaac@berkeley.edu>
2026-02-03 22:48:12 +00:00

129 lines
4 KiB
Go

// Copyright IBM Corp. 2016, 2025
// SPDX-License-Identifier: BUSL-1.1
package transit
import (
"context"
"testing"
"github.com/hashicorp/vault/sdk/logical"
"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/require"
)
// TestDataKeyWithPaddingScheme validates that we properly leverage padding scheme
// args for the returned keys
func TestDataKeyWithPaddingScheme(t *testing.T) {
b, s := createBackendWithStorage(t)
keyName := "test"
createKeyReq := &logical.Request{
Operation: logical.UpdateOperation,
Path: "keys/" + keyName,
Storage: s,
Data: map[string]interface{}{
"type": "rsa-2048",
},
}
resp, err := b.HandleRequest(context.Background(), createKeyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("failed key creation: err: %v resp: %#v", err, resp)
}
tests := []struct {
Name string
PaddingScheme string
DecryptPaddingScheme string
ShouldFailToDecrypt bool
}{
{"no-padding-scheme", "", "", false},
{"oaep", "oaep", "oaep", false},
{"pkcs1v15", "pkcs1v15", "pkcs1v15", false},
{"mixed-should-fail", "pkcs1v15", "oaep", true},
{"mixed-based-on-default-should-fail", "", "pkcs1v15", true},
}
for _, tc := range tests {
t.Run(tc.Name, func(t *testing.T) {
dataKeyReq := &logical.Request{
Operation: logical.UpdateOperation,
Path: "datakey/wrapped/" + keyName,
Storage: s,
Data: map[string]interface{}{},
}
if len(tc.PaddingScheme) > 0 {
dataKeyReq.Data["padding_scheme"] = tc.PaddingScheme
}
resp, err = b.HandleRequest(context.Background(), dataKeyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("failed data key api: err: %v resp: %#v", err, resp)
}
require.NotNil(t, resp, "Got nil nil response")
var d struct {
Ciphertext string `mapstructure:"ciphertext"`
}
err = mapstructure.Decode(resp.Data, &d)
require.NoError(t, err, "failed decoding datakey api response")
require.NotEmpty(t, d.Ciphertext, "ciphertext should not be empty")
// Attempt to decrypt with data key with the same padding scheme
decryptReq := &logical.Request{
Operation: logical.UpdateOperation,
Path: "decrypt/" + keyName,
Storage: s,
Data: map[string]interface{}{
"ciphertext": d.Ciphertext,
},
}
if len(tc.DecryptPaddingScheme) > 0 {
decryptReq.Data["padding_scheme"] = tc.DecryptPaddingScheme
}
resp, err = b.HandleRequest(context.Background(), decryptReq)
if tc.ShouldFailToDecrypt {
require.Error(t, err, "Should have failed decryption as padding schemes are mixed")
} else {
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("failed to decrypt data key: err: %v resp: %#v", err, resp)
}
}
})
}
// We expect 8 successful requests ((3 valid cases x 2 operations) + (2 invalid cases x 1 operation))
require.Equal(t, uint64(8), b.billingDataCounts.Transit.Load())
}
// TestDataKeyWithPaddingSchemeInvalidKeyType validates we fail when we specify a
// padding_scheme value on an invalid key type (non-RSA)
func TestDataKeyWithPaddingSchemeInvalidKeyType(t *testing.T) {
b, s := createBackendWithStorage(t)
keyName := "test"
createKeyReq := &logical.Request{
Operation: logical.UpdateOperation,
Path: "keys/" + keyName,
Storage: s,
Data: map[string]interface{}{},
}
resp, err := b.HandleRequest(context.Background(), createKeyReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("failed key creation: err: %v resp: %#v", err, resp)
}
dataKeyReq := &logical.Request{
Operation: logical.UpdateOperation,
Path: "datakey/wrapped/" + keyName,
Storage: s,
Data: map[string]interface{}{
"padding_scheme": "oaep",
},
}
resp, err = b.HandleRequest(context.Background(), dataKeyReq)
require.ErrorContains(t, err, "invalid request")
require.NotNil(t, resp, "response should not be nil")
require.Contains(t, resp.Error().Error(), "padding_scheme argument invalid: unsupported key")
// We expect 0 successful requests
require.Equal(t, uint64(0), b.billingDataCounts.Transit.Load())
}