refactor (kms): add GetWrapperer for RewrapFn parameter (#2701)

* refactor (kms): add GetWrapperer for RewrapFn parameter

* tests (kms): add MockWrapper and MockGetWrapperer

Make it a bit easier to write unhappy path tests which depend on
a Wrapper or GetWrapperer
This commit is contained in:
Jim authored and GitHub committed 2022-12-13 05:38:14 -05:00
1 parent 173e1587d0
commit 38b12394fd
12 files changed
+126 -29

No files matched your search

+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
kms.RegisterTableRewrapFn(defaultAuthMethodTableName, authMethodRewrapFn)
}
func authMethodRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func authMethodRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "oidc.authMethodRewrapFn"
if dataKeyVersionId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing data key version id")
+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
kms.RegisterTableRewrapFn("auth_password_argon2_cred", argon2ConfigRewrapFn)
}
func argon2ConfigRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func argon2ConfigRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "password.argon2ConfigRewrapFn"
if dataKeyVersionId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing data key version id")
+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
kms.RegisterTableRewrapFn(defaultAuthTokenTableName, authTokenRewrapFn)
}
func authTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func authTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "authtoken.authTokenRewrapFn"
if dataKeyVersionId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing data key version id")
+4 -4
View File
@@ -15,7 +15,7 @@ func init() {
kms.RegisterTableRewrapFn("credential_static_json_credential", credStaticJsonRewrapFn)
}
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) string {
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) string {
if dataKeyVersionId == "" {
return "missing data key version id"
}
@@ -34,7 +34,7 @@ func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId
return ""
}
func credStaticUsernamePasswordRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func credStaticUsernamePasswordRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "static.credStaticUsernamePasswordRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -79,7 +79,7 @@ func credStaticUsernamePasswordRewrapFn(ctx context.Context, dataKeyVersionId, s
return nil
}
func credStaticSshPrivKeyRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func credStaticSshPrivKeyRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "static.credStaticSshPrivKeyRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -125,7 +125,7 @@ func credStaticSshPrivKeyRewrapFn(ctx context.Context, dataKeyVersionId, scopeId
return nil
}
func credStaticJsonRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func credStaticJsonRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "static.credStaticJsonRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
+3 -3
View File
@@ -14,7 +14,7 @@ func init() {
kms.RegisterTableRewrapFn("credential_vault_token", credVaultTokenRewrapFn)
}
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) string {
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) string {
if dataKeyVersionId == "" {
return "missing data key version id"
}
@@ -33,7 +33,7 @@ func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId
return ""
}
func credVaultClientCertificateRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func credVaultClientCertificateRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "vault.credVaultClientCertificateRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -62,7 +62,7 @@ func credVaultClientCertificateRewrapFn(ctx context.Context, dataKeyVersionId, s
return nil
}
func credVaultTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func credVaultTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "vault.credVaultTokenRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
+1 -1
View File
@@ -13,7 +13,7 @@ func init() {
kms.RegisterTableRewrapFn("host_plugin_catalog_secret", hostCatalogSecretRewrapFn)
}
func hostCatalogSecretRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func hostCatalogSecretRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "plugin.hostCatalogSecretRewrapFn"
if dataKeyVersionId == "" {
return errors.New(ctx, errors.InvalidParameter, op, "missing data key version id")
+8 -8
View File
@@ -439,7 +439,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
t.Run("does-nothing-when-no-run-available", func(t *testing.T) {
callbackCalled := false
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
callbackCalled = true
return nil
}
@@ -476,7 +476,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
require.NoError(t, err)
})
callbackCalled := false
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
callbackCalled = true
return nil
}
@@ -501,7 +501,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
})
callbackCalled := make(chan struct{})
returnFromCallback := make(chan struct{})
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
close(callbackCalled)
assert.Equal(t, "global", scopeId)
// Block here until we want it to return
@@ -568,7 +568,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
require.NoError(t, err)
})
rewrappedKeyVersion := ""
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
rewrappedKeyVersion = dataKeyVersionId
return nil
}
@@ -600,7 +600,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
require.NoError(t, err)
})
rewrappedKeyVersion := ""
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
rewrappedKeyVersion = dataKeyVersionId
return nil
}
@@ -624,7 +624,7 @@ func TestMonitorTableRewrappingRuns(t *testing.T) {
require.NoError(t, err)
})
callbackCalled := make(chan struct{})
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
tableNameToRewrapFn["auth_token"] = func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
close(callbackCalled)
// Block here until we want it to return
<-ctx.Done()
@@ -909,7 +909,7 @@ func TestDestroyKeyVersion(t *testing.T) {
}
func Test_RegisterTableRewrapFn(t *testing.T) {
rewrapFn := func(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
rewrapFn := func(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
return nil
}
RegisterTableRewrapFn("a_table", rewrapFn)
@@ -923,7 +923,7 @@ func Test_RegisterTableRewrapFn(t *testing.T) {
func Test_ListTablesSupportingRewrap(t *testing.T) {
assert.Empty(t, ListTablesSupportingRewrap())
rewrapFn := func(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error {
rewrapFn := func(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error {
return nil
}
RegisterTableRewrapFn("a_table", rewrapFn)
+9 -1
View File
@@ -5,10 +5,18 @@ import (
"fmt"
"github.com/hashicorp/boundary/internal/db"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
"golang.org/x/exp/maps"
)
type RewrapFn func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms *Kms) error
// GetWrapperer defines (and constrains) the kms features required by the
// RewrapFn
type GetWrapperer interface {
// GetWrapper returns a wrapper for the given scope and purpose.
GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose, opt ...Option) (wrapping.Wrapper, error)
}
type RewrapFn func(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kms GetWrapperer) error
var tableNameToRewrapFn = map[string]RewrapFn{}
+89
View File
@@ -39,3 +39,92 @@ func TestKmsDeleteAllKeys(t testing.TB, conn *db.DB) {
type dataKey struct{}
func (*dataKey) TableName() string { return "kms_data_key" }
// MockGetWrapperer provides a mock for returning a set of mock values for a
// GetWrapperer
type MockGetWrapperer struct {
// Kms is the underlying kms which is used to provide the mock's default
// behavior
Kms *Kms
// GetErr is a mock value to return for the GetWrapper(...) operation
GetErr error
// ReturnWrapper is a mock value to return for the GetWrapper(...) operation
ReturnWrapper wrapping.Wrapper
}
// GetWrapper returns a wrapper for a given scope and purpose. Supports mock
// values: ReturnWrapper, GetErr
func (m *MockGetWrapperer) GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose, opt ...Option) (wrapping.Wrapper, error) {
switch {
case m.ReturnWrapper != nil:
return m.ReturnWrapper, nil
case m.GetErr != nil:
return nil, m.GetErr
default:
return m.Kms.GetWrapper(ctx, scopeId, purpose, opt...)
}
}
// MockWrapper provides a mock for returning a set of mock values for a Wrapper
type MockWrapper struct {
// Wrapper is the underlying wrapping.Wrapper which is used to provide the
// mock's default behavior
Wrapper wrapping.Wrapper
// EncryptErr is a mock value to return for the Encrypt(...) operation
EncryptErr error
// DecryptErr is a mock value to return for the Decrypt(...) operation
DecryptErr error
// KeyIdErr is a mock value to return for the KeyId(...) operation
KeyIdErr error
// KeyIdReturned is a mock value to return for the KeyId(...) operation
KeyIdReturned string
}
// Type of the wrapper. No mock values supported
func (w *MockWrapper) Type(ctx context.Context) (wrapping.WrapperType, error) {
return w.Wrapper.Type(ctx)
}
// KeyId is the id of the key currently used for encryption operations. Mock
// values supported: KeyIdErr, KeyIdReturned
func (w *MockWrapper) KeyId(ctx context.Context) (string, error) { // nolint
switch {
case w.KeyIdErr != nil:
return "", w.KeyIdErr
case w.KeyIdReturned != "":
return w.KeyIdReturned, nil
default:
return w.Wrapper.KeyId(ctx)
}
}
// SetConfig applies the given options to a wrapper and returns
// configuration information. No mock values supported.
func (w *MockWrapper) SetConfig(ctx context.Context, options ...wrapping.Option) (*wrapping.WrapperConfig, error) {
return w.Wrapper.SetConfig(ctx, options...)
}
// / Encrypt encrypts the given byte slice and stores the resulting information
// in the returned blob info. Mock values supported: EncryptErr
func (w *MockWrapper) Encrypt(ctx context.Context, plaintext []byte, options ...wrapping.Option) (*wrapping.BlobInfo, error) {
if w.EncryptErr != nil {
return nil, w.EncryptErr
}
return w.Wrapper.Encrypt(ctx, plaintext, options...)
}
// Decrypt decrypts the given byte slice and stores the resulting information in
// the returned byte slice. Mock values supported: DecryptErr
func (w *MockWrapper) Decrypt(ctx context.Context, ciphertext *wrapping.BlobInfo, options ...wrapping.Option) ([]byte, error) {
if w.DecryptErr != nil {
return nil, w.DecryptErr
}
return w.Wrapper.Decrypt(ctx, ciphertext, options...)
}
+4 -4
View File
@@ -15,7 +15,7 @@ func init() {
kms.RegisterTableRewrapFn("worker_auth_server_led_activation_token", workerAuthServerLedActivationTokenRewrapFn)
}
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) string {
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) string {
if dataKeyVersionId == "" {
return "missing data key version id"
}
@@ -34,7 +34,7 @@ func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId
return ""
}
func workerAuthCertRewrapFn(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func workerAuthCertRewrapFn(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "server.workerAuthCertRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -63,7 +63,7 @@ func workerAuthCertRewrapFn(ctx context.Context, dataKeyVersionId string, scopeI
return nil
}
func workerAuthRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func workerAuthRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "server.workerAuthRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -108,7 +108,7 @@ func workerAuthRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, r
return nil
}
func workerAuthServerLedActivationTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func workerAuthServerLedActivationTokenRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "server.workerAuthServerLedActivationTokenRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
+2 -2
View File
@@ -686,9 +686,9 @@ func fetchConnections(ctx context.Context, r db.Reader, sessionId string, opt ..
// the session uses a legacy private key or not. It also updates the encrypted session
// in the database (if necessary). Eventually we should be able to remove this function
// and use the session key unconditionally.
func decryptAndMaybeUpdateSession(ctx context.Context, kmsRepo *kms.Kms, session *Session, writer db.Writer) error {
func decryptAndMaybeUpdateSession(ctx context.Context, kmsRepo kms.GetWrapperer, session *Session, writer db.Writer) error {
const op = "session.decryptAndMaybeUpdateSession"
if kmsRepo == nil {
if util.IsNil(kmsRepo) {
return errors.New(ctx, errors.InvalidParameter, op, "missing kms repo")
}
if session == nil {
+3 -3
View File
@@ -14,7 +14,7 @@ func init() {
kms.RegisterTableRewrapFn("session_credential", sessionCredentialRewrapFn)
}
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) string {
func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) string {
if dataKeyVersionId == "" {
return "missing data key version id"
}
@@ -33,7 +33,7 @@ func rewrapParameterChecks(ctx context.Context, dataKeyVersionId string, scopeId
return ""
}
func sessionCredentialRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func sessionCredentialRewrapFn(ctx context.Context, dataKeyVersionId, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "session.sessionCredentialRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)
@@ -84,7 +84,7 @@ func sessionCredentialRewrapFn(ctx context.Context, dataKeyVersionId, scopeId st
return nil
}
func sessionRewrapFn(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo *kms.Kms) error {
func sessionRewrapFn(ctx context.Context, dataKeyVersionId string, scopeId string, reader db.Reader, writer db.Writer, kmsRepo kms.GetWrapperer) error {
const op = "session.sessionRewrapFn"
if errStr := rewrapParameterChecks(ctx, dataKeyVersionId, scopeId, reader, writer, kmsRepo); errStr != "" {
return errors.New(ctx, errors.InvalidParameter, op, errStr)