From 8151b30ce98911beddf8cc6fb23f14b8de17c98f Mon Sep 17 00:00:00 2001 From: Louis Ruch Date: Tue, 12 Jan 2021 08:50:19 -0800 Subject: [PATCH] ICU-743/Domain errors internal/kms refactor (#848) * Domain errors internal/kms refactor * Update changelog * Update internal/host error op * Incorrect error returned in read_writer --- CHANGELOG.md | 5 ++ internal/db/read_writer.go | 4 +- internal/db/read_writer_test.go | 42 ++++------ internal/errors/code.go | 4 + internal/errors/code_test.go | 15 ++++ internal/errors/error.go | 6 +- internal/errors/info.go | 12 +++ internal/errors/kind.go | 2 + internal/host/static/repository_host.go | 20 +++-- .../host/static/repository_host_catalog.go | 20 +++-- internal/host/static/repository_host_set.go | 20 +++-- .../host/static/repository_host_set_member.go | 12 +-- internal/iam/group_member_test.go | 4 +- internal/iam/group_test.go | 4 +- internal/iam/principal_role_test.go | 8 +- internal/iam/repository.go | 6 +- internal/iam/repository_group_test.go | 8 +- .../iam/repository_principal_role_test.go | 4 +- internal/iam/repository_role_grant_test.go | 4 +- internal/iam/repository_role_test.go | 4 +- internal/iam/repository_user_test.go | 16 +--- internal/iam/role_test.go | 4 +- internal/kms/database_key.go | 13 ++-- internal/kms/database_key_test.go | 6 +- internal/kms/database_key_version.go | 27 ++++--- internal/kms/database_key_version_test.go | 10 +-- internal/kms/ids.go | 33 +++++--- internal/kms/kms.go | 63 ++++++++------- internal/kms/oplog_key.go | 13 ++-- internal/kms/oplog_key_test.go | 6 +- internal/kms/oplog_key_version.go | 27 ++++--- internal/kms/oplog_key_version_test.go | 10 +-- internal/kms/repository.go | 44 ++++++----- internal/kms/repository_database_key.go | 60 +++++++------- internal/kms/repository_database_key_test.go | 8 +- .../kms/repository_database_key_version.go | 78 ++++++++++--------- .../repository_database_key_version_test.go | 18 ++--- internal/kms/repository_oplog_key.go | 60 +++++++------- internal/kms/repository_oplog_key_test.go | 20 ++--- internal/kms/repository_oplog_key_version.go | 78 ++++++++++--------- .../kms/repository_oplog_key_version_test.go | 18 ++--- internal/kms/repository_root_key.go | 58 ++++++++------ internal/kms/repository_root_key_test.go | 14 ++-- internal/kms/repository_root_key_version.go | 74 ++++++++++-------- .../kms/repository_root_key_version_test.go | 18 ++--- internal/kms/repository_session_key.go | 60 +++++++------- internal/kms/repository_session_key_test.go | 21 +++-- .../kms/repository_session_key_version.go | 78 ++++++++++--------- .../repository_session_key_version_test.go | 18 ++--- internal/kms/repository_test.go | 18 ++--- internal/kms/repository_token_key.go | 60 +++++++------- internal/kms/repository_token_key_test.go | 20 ++--- internal/kms/repository_token_key_version.go | 78 ++++++++++--------- .../kms/repository_token_key_version_test.go | 18 ++--- internal/kms/root_key.go | 15 ++-- internal/kms/root_key_test.go | 6 +- internal/kms/root_key_version.go | 25 +++--- internal/kms/root_key_version_test.go | 8 +- internal/kms/session_key.go | 13 ++-- internal/kms/session_key_test.go | 6 +- internal/kms/session_key_version.go | 25 +++--- internal/kms/session_key_version_test.go | 10 +-- internal/kms/token_key.go | 13 ++-- internal/kms/token_key_test.go | 6 +- internal/kms/token_key_version.go | 27 ++++--- internal/kms/token_key_version_test.go | 10 +-- internal/session/repository_test.go | 4 +- internal/target/repository_tcp_target_test.go | 8 +- 68 files changed, 802 insertions(+), 725 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 232edfbfc..dbb67fa49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ## Next +### New and Improved + +* controller: Improved error handling in kms repo + ([PR](https://github.com/hashicorp/boundary/pull/848)) + ### Bug Fixes * cli: When `output-curl-string` is used with `update` or `add-/remove-/set-` diff --git a/internal/db/read_writer.go b/internal/db/read_writer.go index 52d72174d..c268626cb 100644 --- a/internal/db/read_writer.go +++ b/internal/db/read_writer.go @@ -563,13 +563,13 @@ func (rw *Db) Delete(ctx context.Context, i interface{}, opt ...Option) (int, er if rowsDeleted > 0 && (withOplog || opts.newOplogMsg != nil) { if withOplog { if err := rw.addOplog(ctx, DeleteOp, opts, ticket, i); err != nil { - return rowsDeleted, errors.Wrap(db.Error, op, errors.WithMsg("add oplog failed")) + return rowsDeleted, errors.Wrap(err, op, errors.WithMsg("add oplog failed")) } } if opts.newOplogMsg != nil { msg, err := rw.newOplogMessage(ctx, DeleteOp, i) if err != nil { - return rowsDeleted, errors.Wrap(db.Error, op, errors.WithMsg("returning oplog failed")) + return rowsDeleted, errors.Wrap(err, op, errors.WithMsg("returning oplog failed")) } *opts.newOplogMsg = *msg } diff --git a/internal/db/read_writer_test.go b/internal/db/read_writer_test.go index 0ad6f7268..863a9cd33 100644 --- a/internal/db/read_writer_test.go +++ b/internal/db/read_writer_test.go @@ -1329,9 +1329,7 @@ func TestDb_Delete(t *testing.T) { assert.Equal(tt.want, got) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "received unexpected error: %v", err) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "received unexpected error: %v", err) err := TestVerifyOplog(t, rw, tt.args.i.GetPublicId(), WithOperation(oplog.OpType_OP_TYPE_DELETE), WithCreateNotBefore(5*time.Second)) assert.Error(err) return @@ -1660,9 +1658,7 @@ func TestDb_CreateItems(t *testing.T) { err := rw.CreateItems(context.Background(), tt.args.createItems, tt.args.opt...) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) return } require.NoError(err) @@ -1857,9 +1853,7 @@ func TestDb_DeleteItems(t *testing.T) { rowsDeleted, err := rw.DeleteItems(context.Background(), tt.args.deleteItems, tt.args.opt...) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) return } require.NoError(err) @@ -2108,9 +2102,7 @@ func TestDb_GetTicket(t *testing.T) { got, err := rw.GetTicket(tt.aggregateType) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error type: %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error type: %s", err.Error()) return } require.NoError(err) @@ -2252,9 +2244,7 @@ func TestDb_WriteOplogEntryWith(t *testing.T) { err := rw.WriteOplogEntryWith(context.Background(), tt.args.wrapper, tt.args.ticket, tt.args.metadata, tt.args.msgs, tt.args.opt...) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) if tt.wantErrContains != "" { assert.Contains(err.Error(), tt.wantErrContains) } @@ -2283,7 +2273,7 @@ func TestClear_InputTypes(t *testing.T) { name string args args want interface{} - err error + err errors.Code }{ { name: "nil", @@ -2292,7 +2282,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "string", @@ -2301,7 +2291,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "pointer-to-nil-struct", @@ -2310,7 +2300,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "pointer-to-string", @@ -2319,7 +2309,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "not-pointer", @@ -2330,7 +2320,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "map", @@ -2342,7 +2332,7 @@ func TestClear_InputTypes(t *testing.T) { f: []string{"field"}, d: 1, }, - err: errors.ErrInvalidParameter, + err: errors.InvalidParameter, }, { name: "pointer-to-struct", @@ -2364,8 +2354,8 @@ func TestClear_InputTypes(t *testing.T) { assert, require := assert.New(t), require.New(t) input := tt.args.v err := Clear(input, tt.args.f, tt.args.d) - if tt.err != nil { - assert.Error(err) + if tt.err != 0 { + assert.True(errors.Match(errors.T(tt.err), err)) return } require.NoError(err) @@ -2844,9 +2834,7 @@ func TestDb_oplogMsgsForItems(t *testing.T) { got, err := rw.oplogMsgsForItems(context.Background(), tt.args.opType, tt.args.opts, tt.args.items) if tt.wantErr { require.Error(err) - if tt.wantIsErr != 0 { - assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) return } require.NoError(err) diff --git a/internal/errors/code.go b/internal/errors/code.go index 70f7ec51a..f482af9ef 100644 --- a/internal/errors/code.go +++ b/internal/errors/code.go @@ -26,6 +26,7 @@ const ( InvalidPublicId Code = 102 // InvalidPublicId represents an invalid public Id for an operation InvalidFieldMask Code = 103 // InvalidFieldMask represents an invalid field mast for an operation EmptyFieldMask Code = 104 // EmptyFieldMask represents an empty field mask for an operation + KeyNotFound Code = 105 // KeyNotFound represents that a key/version was not found in the KMS // PasswordTooShort results from attempting to set a password which is to short. PasswordTooShort Code = 200 @@ -42,6 +43,9 @@ const ( // new passwords are equal. PasswordsEqual Code = 203 + Encrypt Code = 300 // Encrypt represents an error occurred during the underlying encryption process + Decrypt Code = 301 // Decrypt represents an error occurred during the underlying decryption process + // DB errors are reserved Codes from 1000-1999 CheckConstraint Code = 1000 // CheckConstraint represents a check constraint error NotNull Code = 1001 // NotNull represents a value must not be null error diff --git a/internal/errors/code_test.go b/internal/errors/code_test.go index db3ab32a9..9545b3cef 100644 --- a/internal/errors/code_test.go +++ b/internal/errors/code_test.go @@ -52,6 +52,11 @@ func TestCode_Both_String_Info(t *testing.T) { c: EmptyFieldMask, want: EmptyFieldMask, }, + { + name: "KeyNotFound", + c: KeyNotFound, + want: KeyNotFound, + }, { name: "PasswordTooShort", c: PasswordTooShort, @@ -72,6 +77,16 @@ func TestCode_Both_String_Info(t *testing.T) { c: PasswordsEqual, want: PasswordsEqual, }, + { + name: "Encrypt", + c: Encrypt, + want: Encrypt, + }, + { + name: "Decrypt", + c: Decrypt, + want: Decrypt, + }, { name: "CheckConstraint", c: CheckConstraint, diff --git a/internal/errors/error.go b/internal/errors/error.go index eb2a797bc..582062ceb 100644 --- a/internal/errors/error.go +++ b/internal/errors/error.go @@ -23,7 +23,9 @@ type Err struct { // Msg for the error Msg string - // Op represents the operation raising/propagating an error and is optional + // Op represents the operation raising/propagating an error and is optional. + // Op should be formatted as "package.func" for functions, while methods should + // include the receiver type in parentheses "package.(type).func" Op Op // Wrapped is the error which this Err wraps and will be nil if there's no @@ -101,7 +103,7 @@ func Wrap(e error, op Op, opt ...Option) error { // this convert can be removed err := Convert(e) if err != nil { - // wrapped converted error + // wrap the converted error e = err } opt = append(opt, WithWrap(e)) diff --git a/internal/errors/info.go b/internal/errors/info.go index adbe4c9ce..751604e74 100644 --- a/internal/errors/info.go +++ b/internal/errors/info.go @@ -36,6 +36,10 @@ var errorCodeInfo = map[Code]Info{ Message: "empty field mask", Kind: Parameter, }, + KeyNotFound: { + Message: "key/version not found", + Kind: Integrity, + }, PasswordTooShort: { Message: "too short", Kind: Password, @@ -52,6 +56,14 @@ var errorCodeInfo = map[Code]Info{ Message: "old and new password are equal", Kind: Password, }, + Encrypt: { + Message: "error occurred during encrypt", + Kind: Encryption, + }, + Decrypt: { + Message: "error occurred during decrypt", + Kind: Encryption, + }, CheckConstraint: { Message: "constraint check failed", Kind: Integrity, diff --git a/internal/errors/kind.go b/internal/errors/kind.go index a532e3709..7fb1742f7 100644 --- a/internal/errors/kind.go +++ b/internal/errors/kind.go @@ -10,6 +10,7 @@ const ( Search Password Transaction + Encryption ) func (e Kind) String() string { @@ -20,5 +21,6 @@ func (e Kind) String() string { Search: "search issue", Password: "password violation", Transaction: "db transaction issue", + Encryption: "encryption issue", }[e] } diff --git a/internal/host/static/repository_host.go b/internal/host/static/repository_host.go index b06e53b44..1ad556611 100644 --- a/internal/host/static/repository_host.go +++ b/internal/host/static/repository_host.go @@ -22,7 +22,7 @@ import ( // Both h.Name and h.Description are optional. If h.Name is set, it must be // unique within h.CatalogId. func (r *Repository) CreateHost(ctx context.Context, scopeId string, h *Host, opt ...Option) (*Host, error) { - const op = "static.CreateHost" + const op = "static.(Repository).CreateHost" if h == nil { return nil, errors.New(errors.InvalidParameter, op, "nil Host") } @@ -72,7 +72,11 @@ func (r *Repository) CreateHost(ctx context.Context, scopeId string, h *Host, op _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { newHost = h.clone() - return w.Create(ctx, newHost, db.WithOplog(oplogWrapper, h.oplog(oplog.OpType_OP_TYPE_CREATE))) + err := w.Create(ctx, newHost, db.WithOplog(oplogWrapper, h.oplog(oplog.OpType_OP_TYPE_CREATE))) + if err != nil { + return errors.Wrap(err, op) + } + return nil }, ) @@ -106,7 +110,7 @@ func (r *Repository) CreateHost(ctx context.Context, scopeId string, h *Host, op // An attribute of h will be set to NULL in the database if the attribute // in h is the zero value and it is included in fieldMaskPaths. func (r *Repository) UpdateHost(ctx context.Context, scopeId string, h *Host, version uint32, fieldMaskPaths []string, opt ...Option) (*Host, int, error) { - const op = "static.UpdateHost" + const op = "static.(Repository).UpdateHost" if h == nil { return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "nil Host") } @@ -168,7 +172,7 @@ func (r *Repository) UpdateHost(ctx context.Context, scopeId string, h *Host, ve return errors.Wrap(err, op) } if rowsUpdated > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been updated") } return nil }, @@ -195,7 +199,7 @@ func (r *Repository) UpdateHost(ctx context.Context, scopeId string, h *Host, ve // LookupHost will look up a host in the repository. If the host is not // found, it will return nil, nil. All options are ignored. func (r *Repository) LookupHost(ctx context.Context, publicId string, opt ...Option) (*Host, error) { - const op = "static.LookupHost" + const op = "static.(Repository).LookupHost" if publicId == "" { return nil, errors.New(errors.InvalidParameter, op, "no public id") } @@ -213,7 +217,7 @@ func (r *Repository) LookupHost(ctx context.Context, publicId string, opt ...Opt // ListHosts returns a slice of Hosts for the catalogId. // WithLimit is the only option supported. func (r *Repository) ListHosts(ctx context.Context, catalogId string, opt ...Option) ([]*Host, error) { - const op = "static.ListHosts" + const op = "static.(Repository).ListHosts" if catalogId == "" { return nil, errors.New(errors.InvalidParameter, op, "no catalog id") } @@ -235,7 +239,7 @@ func (r *Repository) ListHosts(ctx context.Context, catalogId string, opt ...Opt // returning a count of the number of records deleted. All options are // ignored. func (r *Repository) DeleteHost(ctx context.Context, scopeId string, publicId string, opt ...Option) (int, error) { - const op = "static.DeleteHost" + const op = "static.(Repository).DeleteHost" if publicId == "" { return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "no public id") } @@ -257,7 +261,7 @@ func (r *Repository) DeleteHost(ctx context.Context, scopeId string, publicId st return errors.Wrap(err, op) } if rowsDeleted > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") } return nil }, diff --git a/internal/host/static/repository_host_catalog.go b/internal/host/static/repository_host_catalog.go index 3c54cafd8..53ce717af 100644 --- a/internal/host/static/repository_host_catalog.go +++ b/internal/host/static/repository_host_catalog.go @@ -21,7 +21,7 @@ import ( // // Both c.CreateTime and c.UpdateTime are ignored. func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, opt ...Option) (*HostCatalog, error) { - const op = "static.CreateCatalog" + const op = "static.(Repository).CreateCatalog" if c == nil { return nil, errors.New(errors.InvalidParameter, op, "nil HostCatalog") } @@ -69,11 +69,15 @@ func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, opt ...O db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { newHostCatalog = c.clone() - return w.Create( + err := w.Create( ctx, newHostCatalog, db.WithOplog(oplogWrapper, metadata), ) + if err != nil { + return errors.Wrap(err, op) + } + return nil }, ) @@ -98,7 +102,7 @@ func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, opt ...O // An attribute of c will be set to NULL in the database if the attribute // in c is the zero value and it is included in fieldMask. func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version uint32, fieldMask []string, opt ...Option) (*HostCatalog, int, error) { - const op = "static.UpdateCatalog" + const op = "static.(Repository).UpdateCatalog" if c == nil { return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "nil HostCatalog") } @@ -162,7 +166,7 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version return errors.Wrap(err, op) } if rowsUpdated > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been updated") } return nil }, @@ -181,7 +185,7 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version // LookupCatalog returns the HostCatalog for id. Returns nil, nil if no // HostCatalog is found for id. func (r *Repository) LookupCatalog(ctx context.Context, id string, opt ...Option) (*HostCatalog, error) { - const op = "static.LookupCatalog" + const op = "static.(Repository).LookupCatalog" if id == "" { return nil, errors.New(errors.InvalidParameter, op, "no public id") } @@ -198,7 +202,7 @@ func (r *Repository) LookupCatalog(ctx context.Context, id string, opt ...Option // ListCatalogs returns a slice of HostCatalogs for the scopeId. WithLimit is the only option supported. func (r *Repository) ListCatalogs(ctx context.Context, scopeId string, opt ...Option) ([]*HostCatalog, error) { - const op = "static.ListCatalogs" + const op = "static.(Repository).ListCatalogs" if scopeId == "" { return nil, errors.New(errors.InvalidParameter, op, "no scope id") } @@ -219,7 +223,7 @@ func (r *Repository) ListCatalogs(ctx context.Context, scopeId string, opt ...Op // DeleteCatalog deletes id from the repository returning a count of the // number of records deleted. func (r *Repository) DeleteCatalog(ctx context.Context, id string, opt ...Option) (int, error) { - const op = "static.DeleteCatalog" + const op = "static.(Repository).DeleteCatalog" if id == "" { return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "no public id") } @@ -260,7 +264,7 @@ func (r *Repository) DeleteCatalog(ctx context.Context, id string, opt ...Option return errors.Wrap(err, op) } if rowsDeleted > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") } return nil }, diff --git a/internal/host/static/repository_host_set.go b/internal/host/static/repository_host_set.go index 6dab30a78..21426362e 100644 --- a/internal/host/static/repository_host_set.go +++ b/internal/host/static/repository_host_set.go @@ -20,7 +20,7 @@ import ( // Both s.Name and s.Description are optional. If s.Name is set, it must be // unique within s.CatalogId. func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet, opt ...Option) (*HostSet, error) { - const op = "static.CreateSet" + const op = "static.(Repository).CreateSet" if s == nil { return nil, errors.New(errors.InvalidParameter, op, "nil HostSet") } @@ -66,7 +66,11 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet, _, err = r.writer.DoTx(ctx, db.StdRetryCnt, db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { newHostSet = s.clone() - return w.Create(ctx, newHostSet, db.WithOplog(oplogWrapper, s.oplog(oplog.OpType_OP_TYPE_CREATE))) + err := w.Create(ctx, newHostSet, db.WithOplog(oplogWrapper, s.oplog(oplog.OpType_OP_TYPE_CREATE))) + if err != nil { + return errors.Wrap(err, op) + } + return nil }, ) @@ -94,7 +98,7 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet, // The WithLimit option can be used to limit the number of hosts returned. // All other options are ignored. func (r *Repository) UpdateSet(ctx context.Context, scopeId string, s *HostSet, version uint32, fieldMaskPaths []string, opt ...Option) (*HostSet, []*Host, int, error) { - const op = "static.UpdateSet" + const op = "static.(Repository).UpdateSet" if s == nil { return nil, nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "nil HostSet") } @@ -158,7 +162,7 @@ func (r *Repository) UpdateSet(ctx context.Context, scopeId string, s *HostSet, return errors.Wrap(err, op) } if rowsUpdated > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been updated") } hosts, err = getHosts(ctx, reader, s.PublicId, limit) if err != nil { @@ -183,7 +187,7 @@ func (r *Repository) UpdateSet(ctx context.Context, scopeId string, s *HostSet, // found, it will return nil, nil, nil. The WithLimit option can be used to // limit the number of hosts returned. All other options are ignored. func (r *Repository) LookupSet(ctx context.Context, publicId string, opt ...Option) (*HostSet, []*Host, error) { - const op = "static.LookupSet" + const op = "static.(Repository).LookupSet" if publicId == "" { return nil, nil, errors.New(errors.InvalidParameter, op, "no public id") } @@ -226,7 +230,7 @@ func (r *Repository) LookupSet(ctx context.Context, publicId string, opt ...Opti // ListSets returns a slice of HostSets for the catalogId. WithLimit is the // only option supported. func (r *Repository) ListSets(ctx context.Context, catalogId string, opt ...Option) ([]*HostSet, error) { - const op = "static.ListSets" + const op = "static.(Repository).ListSets" if catalogId == "" { return nil, errors.New(errors.InvalidParameter, op, "no catalog id") } @@ -248,7 +252,7 @@ func (r *Repository) ListSets(ctx context.Context, catalogId string, opt ...Opti // returning a count of the number of records deleted. All options are // ignored. func (r *Repository) DeleteSet(ctx context.Context, scopeId string, publicId string, opt ...Option) (int, error) { - const op = "static.DeleteSet" + const op = "static.(Repository).DeleteSet" if publicId == "" { return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "no public id") } @@ -273,7 +277,7 @@ func (r *Repository) DeleteSet(ctx context.Context, scopeId string, publicId str return errors.Wrap(err, op) } if rowsDeleted > 1 { - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") } return nil }, diff --git a/internal/host/static/repository_host_set_member.go b/internal/host/static/repository_host_set_member.go index 1162a499f..75da2d13f 100644 --- a/internal/host/static/repository_host_set_member.go +++ b/internal/host/static/repository_host_set_member.go @@ -18,7 +18,7 @@ import ( // the set to be added. The version must match the current version of the // setId in the repository. func (r *Repository) AddSetMembers(ctx context.Context, scopeId string, setId string, version uint32, hostIds []string, opt ...Option) ([]*Host, error) { - const op = "static.AddSetMembers" + const op = "static.(Repository).AddSetMembers" if scopeId == "" { return nil, errors.New(errors.InvalidParameter, op, "no scope id") } @@ -100,7 +100,7 @@ func updateVersion(ctx context.Context, w db.Writer, wrapper wrapping.Wrapper, m case err != nil: return errors.Wrap(err, op) case rowsUpdated > 1: - return errors.E(errors.WithCode(errors.MultipleRecords)) + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been updated") } msgs = append(msgs, setMsg) @@ -159,7 +159,7 @@ func getHosts(ctx context.Context, reader db.Reader, setId string, limit int) ([ // returns the number of hosts deleted from the set. The version must match // the current version of the setId in the repository. func (r *Repository) DeleteSetMembers(ctx context.Context, scopeId string, setId string, version uint32, hostIds []string, opt ...Option) (int, error) { - const op = "static.DeleteSetMembers" + const op = "static.(Repository).DeleteSetMembers" if scopeId == "" { return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "no scope id") } @@ -227,7 +227,7 @@ func deleteMembers(ctx context.Context, w db.Writer, members []interface{}) ([]* // set to be added. The version must match the current version of the setId // in the repository. If hostIds is empty, all hosts will be removed setId. func (r *Repository) SetSetMembers(ctx context.Context, scopeId string, setId string, version uint32, hostIds []string, opt ...Option) ([]*Host, int, error) { - const op = "static.SetSetMembers" + const op = "static.(Repository).SetSetMembers" if scopeId == "" { return nil, db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "no scope id") } @@ -295,7 +295,7 @@ func (r *Repository) SetSetMembers(ctx context.Context, scopeId string, setId st if len(additions) > 0 { createdMsgs, err := createMembers(ctx, w, additions) if err != nil { - return err + return errors.Wrap(err, op) } msgs = append(msgs, createdMsgs...) metadata["op-type"] = append(metadata["op-type"], oplog.OpType_OP_TYPE_CREATE.String()) @@ -326,7 +326,7 @@ type change struct { } func (r *Repository) changes(ctx context.Context, setId string, hostIds []string) ([]*change, error) { - const op = "static.changes" + const op = "static.(Repository).changes" var inClauseSpots []string // starts at 2 because there is already a $1 in the query for i := 2; i < len(hostIds)+2; i++ { diff --git a/internal/iam/group_member_test.go b/internal/iam/group_member_test.go index c0cd0284f..13e1ae8c7 100644 --- a/internal/iam/group_member_test.go +++ b/internal/iam/group_member_test.go @@ -245,9 +245,7 @@ func Test_GroupMemberCreate(t *testing.T) { if tt.wantErr { require.Error(err) assert.Contains(err.Error(), tt.wantErrMsg) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } assert.NoError(err) diff --git a/internal/iam/group_test.go b/internal/iam/group_test.go index e676aa4f5..50228616d 100644 --- a/internal/iam/group_test.go +++ b/internal/iam/group_test.go @@ -82,9 +82,7 @@ func TestNewGroup(t *testing.T) { if tt.wantErr { require.Error(err) assert.Contains(err.Error(), tt.wantErrMsg) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/iam/principal_role_test.go b/internal/iam/principal_role_test.go index 9705ea1ad..e6af872bb 100644 --- a/internal/iam/principal_role_test.go +++ b/internal/iam/principal_role_test.go @@ -257,9 +257,7 @@ func TestUserRole_Create(t *testing.T) { if tt.wantErr { require.Error(err) assert.Contains(err.Error(), tt.wantErrMsg) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } assert.NoError(err) @@ -635,9 +633,7 @@ func TestGroupRole_Create(t *testing.T) { if tt.wantErr { require.Error(err) assert.Contains(err.Error(), tt.wantErrMsg) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } assert.NoError(err) diff --git a/internal/iam/repository.go b/internal/iam/repository.go index d65abbf7b..3550caadb 100644 --- a/internal/iam/repository.go +++ b/internal/iam/repository.go @@ -94,11 +94,15 @@ func (r *Repository) create(ctx context.Context, resource Resource, _ ...Option) db.ExpBackoff{}, func(_ db.Reader, w db.Writer) error { returnedResource = resourceCloner.Clone() - return w.Create( + err := w.Create( ctx, returnedResource, db.WithOplog(oplogWrapper, metadata), ) + if err != nil { + return errors.Wrap(err, op) + } + return nil }, ) if err != nil { diff --git a/internal/iam/repository_group_test.go b/internal/iam/repository_group_test.go index 3f55214ff..882ac937e 100644 --- a/internal/iam/repository_group_test.go +++ b/internal/iam/repository_group_test.go @@ -430,9 +430,7 @@ func TestRepository_UpdateGroup(t *testing.T) { } if tt.wantErr { assert.Error(err) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) assert.Nil(groupAfterUpdate) assert.Equal(0, updatedRows) assert.Contains(err.Error(), tt.wantErrMsg) @@ -979,9 +977,7 @@ func TestRepository_DeleteGroupMembers(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsErr != 0 { - assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) err = db.TestVerifyOplog(t, rw, tt.args.group.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.Match(errors.T(errors.RecordNotFound), err)) diff --git a/internal/iam/repository_principal_role_test.go b/internal/iam/repository_principal_role_test.go index 1fa5751eb..e04298b99 100644 --- a/internal/iam/repository_principal_role_test.go +++ b/internal/iam/repository_principal_role_test.go @@ -494,9 +494,7 @@ func TestRepository_DeletePrincipalRoles(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsErr != 0 { - assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) err = db.TestVerifyOplog(t, rw, tt.args.role.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) diff --git a/internal/iam/repository_role_grant_test.go b/internal/iam/repository_role_grant_test.go index 7db7340fa..96f35065f 100644 --- a/internal/iam/repository_role_grant_test.go +++ b/internal/iam/repository_role_grant_test.go @@ -375,9 +375,7 @@ func TestRepository_DeleteRoleGrants(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsErr != 0 { - assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "unexpected error %s", err.Error()) err = db.TestVerifyOplog(t, rw, tt.args.role.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) diff --git a/internal/iam/repository_role_test.go b/internal/iam/repository_role_test.go index d2e100e68..628400cdd 100644 --- a/internal/iam/repository_role_test.go +++ b/internal/iam/repository_role_test.go @@ -424,9 +424,7 @@ func TestRepository_UpdateRole(t *testing.T) { roleAfterUpdate, principals, grants, updatedRows, err := repo.UpdateRole(context.Background(), &updateRole, r.Version, tt.args.fieldMaskPaths, tt.args.opt...) if tt.wantErr { assert.Error(err) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) assert.Nil(roleAfterUpdate) assert.Equal(0, updatedRows) assert.Contains(err.Error(), tt.wantErrMsg) diff --git a/internal/iam/repository_user_test.go b/internal/iam/repository_user_test.go index 94ee4a897..04a126b36 100644 --- a/internal/iam/repository_user_test.go +++ b/internal/iam/repository_user_test.go @@ -339,9 +339,7 @@ func TestRepository_UpdateUser(t *testing.T) { } if tt.wantErr { require.Error(err) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) assert.Nil(userAfterUpdate) assert.Equal(0, updatedRows) switch tt.name { @@ -649,9 +647,7 @@ func TestRepository_LookupUserWithLogin(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) if tt.args.withAccountId != "" && tt.args.withAccountId != id { // need to assert that userid in auth_account is still null acct := allocAccount() @@ -820,9 +816,7 @@ func TestRepository_associateUserWithAccounts(t *testing.T) { err := associateUserWithAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) return } require.NoError(err) @@ -966,9 +960,7 @@ func TestRepository_dissociateUserWithAccount(t *testing.T) { err := dissociateUserFromAccounts(context.Background(), kms, rw, rw, tt.args.Ids.user, tt.args.Ids.accts, tt.args.opt...) if tt.wantErr { require.Error(err) - if tt.wantErrIs != 0 { - assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error %s", err.Error()) return } require.NoError(err) diff --git a/internal/iam/role_test.go b/internal/iam/role_test.go index 3ee0e2e5e..0c6cbca94 100644 --- a/internal/iam/role_test.go +++ b/internal/iam/role_test.go @@ -82,9 +82,7 @@ func TestNewRole(t *testing.T) { if tt.wantErr { require.Error(err) assert.Contains(err.Error(), tt.wantErrMsg) - if tt.wantIsErr != 0 { - assert.True(errors.Match(errors.T(tt.wantIsErr), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/database_key.go b/internal/kms/database_key.go index 6004a1dec..a81166d6d 100644 --- a/internal/kms/database_key.go +++ b/internal/kms/database_key.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -21,9 +20,10 @@ type DatabaseKey struct { // NewDatabaseKey creates a new in memory database key. No options // are currently supported. -func NewDatabaseKey(rootKeyId string, opt ...Option) (*DatabaseKey, error) { +func NewDatabaseKey(rootKeyId string, _ ...Option) (*DatabaseKey, error) { + const op = "kms.NewDatabaseKey" if rootKeyId == "" { - return nil, fmt.Errorf("new root key: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } c := &DatabaseKey{ DatabaseKey: &store.DatabaseKey{ @@ -51,16 +51,17 @@ func (k *DatabaseKey) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // before it's written. func (k *DatabaseKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { + const op = "kms.(DatabaseKey).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("database key vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } switch opType { case db.CreateOp: if k.RootKeyId == "" { - return fmt.Errorf("database key vet for write: missing root key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key id") } case db.UpdateOp: - return fmt.Errorf("database key vet for write: key is immutable: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "key is immutable") } return nil } diff --git a/internal/kms/database_key_test.go b/internal/kms/database_key_test.go index 376f88dcb..77eba15d6 100644 --- a/internal/kms/database_key_test.go +++ b/internal/kms/database_key_test.go @@ -33,7 +33,7 @@ func TestDatabaseKey_Create(t *testing.T) { args args want *kms.DatabaseKey wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -41,7 +41,7 @@ func TestDatabaseKey_Create(t *testing.T) { name: "empty-rootKeyId", args: args{}, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -63,7 +63,7 @@ func TestDatabaseKey_Create(t *testing.T) { got, err := kms.NewDatabaseKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/database_key_version.go b/internal/kms/database_key_version.go index 5d79b6372..bbe0a15a0 100644 --- a/internal/kms/database_key_version.go +++ b/internal/kms/database_key_version.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,15 +22,16 @@ type DatabaseKeyVersion struct { // NewDatabaseKeyVersion creates a new in memory database key version. No options are // currently supported. -func NewDatabaseKeyVersion(databaseKeyId string, key []byte, rootKeyVersionId string, opt ...Option) (*DatabaseKeyVersion, error) { +func NewDatabaseKeyVersion(databaseKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*DatabaseKeyVersion, error) { + const op = "kms.NewDatabaseKeyVersion" if databaseKeyId == "" { - return nil, fmt.Errorf("new database key version: missing database key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing database key id") } if len(key) == 0 { - return nil, fmt.Errorf("new database key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } if rootKeyVersionId == "" { - return nil, fmt.Errorf("new database key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } k := &DatabaseKeyVersion{ @@ -62,22 +62,23 @@ func (k *DatabaseKeyVersion) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the database key // version before it's written. func (k *DatabaseKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { + const op = "kms.(DatabaseKeyVersion).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("database key version vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } switch opType { case db.CreateOp: if k.CtKey == nil { - return fmt.Errorf("database key version vet for write: missing key: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing key") } if k.DatabaseKeyId == "" { - return fmt.Errorf("database key version vet for write: missing database key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing database key id") } if k.RootKeyVersionId == "" { - return fmt.Errorf("database key version vet for write: missing root key version id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key version id") } case db.UpdateOp: - return fmt.Errorf("database key version vet for write: key is immutable: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "key is immutable") } return nil } @@ -99,20 +100,22 @@ func (k *DatabaseKeyVersion) SetTableName(n string) { // Encrypt will encrypt the database key version's key func (k *DatabaseKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(DatabaseKeyVersion).Encrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.DatabaseKeyVersion directly if err := structwrapping.WrapStruct(ctx, cipher, k.DatabaseKeyVersion, nil); err != nil { - return fmt.Errorf("error encrypting kms database key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Encrypt)) } return nil } // Decrypt will decrypt the database key version's key func (k *DatabaseKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(DatabaseKeyVersion).Decrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.DatabaseKeyVersion directly if err := structwrapping.UnwrapStruct(ctx, cipher, k.DatabaseKeyVersion, nil); err != nil { - return fmt.Errorf("error decrypting kms database key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Decrypt)) } return nil } diff --git a/internal/kms/database_key_version_test.go b/internal/kms/database_key_version_test.go index 3eb457b22..bc43c5374 100644 --- a/internal/kms/database_key_version_test.go +++ b/internal/kms/database_key_version_test.go @@ -38,7 +38,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { args args want *kms.DatabaseKeyVersion wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -49,7 +49,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-key", @@ -58,7 +58,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-root-key-version-id", @@ -67,7 +67,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { key: []byte("database key"), }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -93,7 +93,7 @@ func TestDatabaseKeyVersion_Create(t *testing.T) { got, err := kms.NewDatabaseKeyVersion(tt.args.databaseKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/ids.go b/internal/kms/ids.go index 0a85fb18a..f05c6f56d 100644 --- a/internal/kms/ids.go +++ b/internal/kms/ids.go @@ -1,9 +1,8 @@ package kms import ( - "fmt" - "github.com/hashicorp/boundary/internal/db" + "github.com/hashicorp/boundary/internal/errors" ) const ( @@ -20,81 +19,91 @@ const ( ) func newRootKeyId() (string, error) { + const op = "kms.newRootKeyId" id, err := db.NewPublicId(RootKeyPrefix) if err != nil { - return "", fmt.Errorf("new root key id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newRootKeyVersionId() (string, error) { + const op = "kms.newRootKeyVersionId" id, err := db.NewPublicId(RootKeyVersionPrefix) if err != nil { - return "", fmt.Errorf("new root key version id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newDatabaseKeyId() (string, error) { + const op = "kms.newDatabaseKeyId" id, err := db.NewPublicId(DatabaseKeyPrefix) if err != nil { - return "", fmt.Errorf("new database key id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newDatabaseKeyVersionId() (string, error) { + const op = "kms.newDatabaseKeyVersionId" id, err := db.NewPublicId(DatabaseKeyVersionPrefix) if err != nil { - return "", fmt.Errorf("new database key version id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newOplogKeyId() (string, error) { + const op = "kms.newOplogKeyId" id, err := db.NewPublicId(OplogKeyPrefix) if err != nil { - return "", fmt.Errorf("new oplog key id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newOplogKeyVersionId() (string, error) { + const op = "kms.newOplogKeyVersionId" id, err := db.NewPublicId(OplogKeyVersionPrefix) if err != nil { - return "", fmt.Errorf("new oplog key version id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newTokenKeyId() (string, error) { + const op = "kms.newTokenKeyId" id, err := db.NewPublicId(TokenKeyPrefix) if err != nil { - return "", fmt.Errorf("new token key id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newTokenKeyVersionId() (string, error) { + const op = "kms.newTokenKeyVersionId" id, err := db.NewPublicId(TokenKeyVersionPrefix) if err != nil { - return "", fmt.Errorf("new token key version id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newSessionKeyId() (string, error) { + const op = "kms.newSessionKeyId" id, err := db.NewPublicId(SessionKeyPrefix) if err != nil { - return "", fmt.Errorf("new session key id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } func newSessionKeyVersionId() (string, error) { + const op = "kms.newSessionKeyVersionId" id, err := db.NewPublicId(SessionKeyVersionPrefix) if err != nil { - return "", fmt.Errorf("new session key version id: %w", err) + return "", errors.Wrap(err, op) } return id, nil } diff --git a/internal/kms/kms.go b/internal/kms/kms.go index 9dcdd5274..926cac3ef 100644 --- a/internal/kms/kms.go +++ b/internal/kms/kms.go @@ -2,10 +2,10 @@ package kms import ( "context" - stderrors "errors" "fmt" "sync" + "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/types/scope" "github.com/hashicorp/go-hclog" wrapping "github.com/hashicorp/go-kms-wrapping" @@ -61,8 +61,9 @@ type Kms struct { // NewKms takes in a repo and returns a Kms. Supported options: WithLogger. func NewKms(repo *Repository, opt ...Option) (*Kms, error) { + const op = "kms.NewKms" if repo == nil { - return nil, stderrors.New("new kms created without an underlying repo") + return nil, errors.New(errors.InvalidParameter, op, "missing underlying repo") } opts := getOpts(opt...) @@ -87,6 +88,7 @@ func (k *Kms) GetScopePurposeCache() *sync.Map { // of a key loss, there will need to be some refactoring here to have the values // being stored in the struct be a multiwrapper, but that's for a later project. func (k *Kms) AddExternalWrappers(opt ...Option) error { + const op = "kms.AddExternalWrappers" k.externalScopeCacheMutex.Lock() defer k.externalScopeCacheMutex.Unlock() @@ -101,19 +103,19 @@ func (k *Kms) AddExternalWrappers(opt ...Option) error { if opts.withRootWrapper != nil { ext.root = opts.withRootWrapper if ext.root.KeyID() == "" { - return fmt.Errorf("root wrapper has no key ID") + return errors.New(errors.InvalidParameter, op, "root wrapper has no key ID") } } if opts.withWorkerAuthWrapper != nil { ext.workerAuth = opts.withWorkerAuthWrapper if ext.workerAuth.KeyID() == "" { - return fmt.Errorf("worker auth wrapper has no key ID") + return errors.New(errors.InvalidParameter, op, "worker auth wrapper has no key ID") } } if opts.withRecoveryWrapper != nil { ext.recovery = opts.withRecoveryWrapper if ext.recovery.KeyID() == "" { - return fmt.Errorf("recovery wrapper has no key ID") + return errors.New(errors.InvalidParameter, op, "recovery wrapper has no key ID") } } @@ -146,16 +148,17 @@ func generateKeyId(scopeId string, purpose KeyPurpose, version uint32) string { // multiwrapper. This is not necesary for encryption but should be supplied for // decryption. func (k *Kms) GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose, opt ...Option) (wrapping.Wrapper, error) { + const op = "kms.GetWrapper" if scopeId == "" { - return nil, stderrors.New("no scope ID provided") + return nil, errors.New(errors.InvalidParameter, op, "missing scope id") } switch purpose { case KeyPurposeOplog, KeyPurposeDatabase, KeyPurposeTokens, KeyPurposeSessions: case KeyPurposeUnknown: - return nil, stderrors.New("key purpose not specified") + return nil, errors.New(errors.InvalidParameter, op, "missing key purpose") default: - return nil, fmt.Errorf("unsupported purpose %q", purpose) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("unsupported purpose %q", purpose)) } opts := getOpts(opt...) @@ -177,15 +180,15 @@ func (k *Kms) GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose // scope-purpose cache will catch everything in steady-state. rootWrapper, rootKeyId, err := k.loadRoot(ctx, scopeId, opt...) if err != nil { - return nil, fmt.Errorf("error loading root key for scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error loading root key for scope %s", scopeId))) } if rootWrapper == nil { - return nil, fmt.Errorf("got nil root wrapper for scope %s", scopeId) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("got nil root wrapper for scope %s", scopeId)) } wrapper, err := k.loadDek(ctx, scopeId, purpose, rootWrapper, rootKeyId, opt...) if err != nil { - return nil, fmt.Errorf("error loading %s for scope %s: %w", purpose.String(), scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error loading %s for scope %s", purpose.String(), scopeId))) } k.scopePurposeCache.Store(scopeId+purpose.String(), wrapper) @@ -193,6 +196,7 @@ func (k *Kms) GetWrapper(ctx context.Context, scopeId string, purpose KeyPurpose } func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*multiwrapper.MultiWrapper, string, error) { + const op = "kms.loadRoot" opts := getOpts(opt...) repo := opts.withRepository if repo == nil { @@ -200,7 +204,7 @@ func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*mul } rootKeys, err := repo.ListRootKeys(ctx) if err != nil { - return nil, "", fmt.Errorf("error listing root keys: %w", err) + return nil, "", errors.Wrap(err, op) } var rootKeyId string for _, k := range rootKeys { @@ -210,7 +214,7 @@ func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*mul } } if rootKeyId == "" { - return nil, "", fmt.Errorf("error finding root key for scope %s", scopeId) + return nil, "", errors.New(errors.KeyNotFound, op, fmt.Sprintf("missing root key for scope %s", scopeId)) } // Now: find the external KMS that can be used to decrypt the root values @@ -219,21 +223,21 @@ func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*mul externalWrappers := k.externalScopeCache[scope.Global.String()] k.externalScopeCacheMutex.Unlock() if externalWrappers == nil { - return nil, "", stderrors.New("could not find kms information at either the needed scope or global fallback") + return nil, "", errors.New(errors.KeyNotFound, op, "could not find kms information at either the needed scope or global fallback") } externalWrappers.m.RLock() defer externalWrappers.m.RUnlock() if externalWrappers.root == nil { - return nil, "", fmt.Errorf("root key wrapper for scope %s is nil", scopeId) + return nil, "", errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key wrapper for scope %s is nil", scopeId)) } rootKeyVersions, err := repo.ListRootKeyVersions(ctx, externalWrappers.root, rootKeyId, WithOrder("version desc")) if err != nil { - return nil, "", fmt.Errorf("error looking up root key versions for scope %s with key ID %s: %w", scopeId, externalWrappers.root.KeyID(), err) + return nil, "", errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error looking up root key versions for scope %s with key ID %s", scopeId, externalWrappers.root.KeyID()))) } if len(rootKeyVersions) == 0 { - return nil, "", fmt.Errorf("no root key versions found for scope %s", scopeId) + return nil, "", errors.New(errors.KeyNotFound, op, fmt.Sprintf("no root key versions found for scope %s", scopeId)) } var multi *multiwrapper.MultiWrapper @@ -242,10 +246,10 @@ func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*mul if _, err := wrapper.SetConfig(map[string]string{ "key_id": key.GetPrivateId(), }); err != nil { - return nil, "", fmt.Errorf("error setting config on aead root wrapper in scope %s: %w", scopeId, err) + return nil, "", errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead root wrapper in scope %s", scopeId))) } if err := wrapper.SetAESGCMKeyBytes(key.GetKey()); err != nil { - return nil, "", fmt.Errorf("error setting key bytes on aead root wrapper in scope %s: %w", scopeId, err) + return nil, "", errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead root wrapper in scope %s", scopeId))) } if i == 0 { multi = multiwrapper.NewMultiWrapper(wrapper) @@ -254,7 +258,7 @@ func (k *Kms) loadRoot(ctx context.Context, scopeId string, opt ...Option) (*mul } } - return multi, rootKeyId, err + return multi, rootKeyId, nil } // Dek is an interface wrapping dek types to allow a lot less switching in loadDek @@ -270,11 +274,12 @@ type DekVersion interface { } func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, rootWrapper wrapping.Wrapper, rootKeyId string, opt ...Option) (*multiwrapper.MultiWrapper, error) { + const op = "kms.loadDek" if rootWrapper == nil { - return nil, fmt.Errorf("got nil root wrapper in loadDek for scope %s", scopeId) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("nil root wrapper for scope %s", scopeId)) } if rootKeyId == "" { - return nil, fmt.Errorf("no root key ID provided for scope %s", scopeId) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("missing root key ID for scope %s", scopeId)) } opts := getOpts(opt...) @@ -296,7 +301,7 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r keys, err = repo.ListSessionKeys(ctx) } if err != nil { - return nil, fmt.Errorf("error listing root keys: %w", err) + return nil, errors.Wrap(err, op, errors.WithMsg("error listing root keys")) } var keyId string for _, k := range keys { @@ -306,7 +311,7 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r } } if keyId == "" { - return nil, fmt.Errorf("error finding %s key for scope %s", purpose.String(), scopeId) + return nil, errors.New(errors.KeyNotFound, op, fmt.Sprintf("error finding %s key for scope %s", purpose.String(), scopeId)) } var keyVersions []DekVersion @@ -321,10 +326,10 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r keyVersions, err = repo.ListSessionKeyVersions(ctx, rootWrapper, keyId, WithOrder("version desc")) } if err != nil { - return nil, fmt.Errorf("error looking up %s key versions for scope %s with key ID %s: %w", purpose.String(), scopeId, rootWrapper.KeyID(), err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error looking up %s key versions for scope %s with key ID %s", purpose.String(), scopeId, rootWrapper.KeyID()))) } if len(keyVersions) == 0 { - return nil, fmt.Errorf("no %s key versions found for scope %s", purpose.String(), scopeId) + return nil, errors.New(errors.KeyNotFound, op, fmt.Sprintf("no %s key versions found for scope %s", purpose.String(), scopeId)) } var multi *multiwrapper.MultiWrapper @@ -333,10 +338,10 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r if _, err := wrapper.SetConfig(map[string]string{ "key_id": keyVersion.GetPrivateId(), }); err != nil { - return nil, fmt.Errorf("error setting config on aead %s wrapper in scope %s: %w", purpose.String(), scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead %s wrapper in scope %s", purpose.String(), scopeId))) } if err := wrapper.SetAESGCMKeyBytes(keyVersion.GetKey()); err != nil { - return nil, fmt.Errorf("error setting key bytes on aead %s wrapper in scope %s: %w", purpose.String(), scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead %s wrapper in scope %s", purpose.String(), scopeId))) } if i == 0 { multi = multiwrapper.NewMultiWrapper(wrapper) @@ -345,5 +350,5 @@ func (k *Kms) loadDek(ctx context.Context, scopeId string, purpose KeyPurpose, r } } - return multi, err + return multi, nil } diff --git a/internal/kms/oplog_key.go b/internal/kms/oplog_key.go index c29f6aeb4..c674ad4d1 100644 --- a/internal/kms/oplog_key.go +++ b/internal/kms/oplog_key.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -21,9 +20,10 @@ type OplogKey struct { // NewOplogKey creates a new in memory key. No options // are currently supported. -func NewOplogKey(rootKeyId string, opt ...Option) (*OplogKey, error) { +func NewOplogKey(rootKeyId string, _ ...Option) (*OplogKey, error) { + const op = "kms.NewOplogKey" if rootKeyId == "" { - return nil, fmt.Errorf("new root key: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } c := &OplogKey{ OplogKey: &store.OplogKey{ @@ -50,13 +50,14 @@ func (k *OplogKey) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // before it's written. -func (k *OplogKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *OplogKey) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(OplogKey).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("oplog key vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.RootKeyId == "" { - return fmt.Errorf("oplog key vet for write: missing root key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key id") } } return nil diff --git a/internal/kms/oplog_key_test.go b/internal/kms/oplog_key_test.go index 9178c7ecc..852d20df0 100644 --- a/internal/kms/oplog_key_test.go +++ b/internal/kms/oplog_key_test.go @@ -33,7 +33,7 @@ func TestOplogKey_Create(t *testing.T) { args args want *kms.OplogKey wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -41,7 +41,7 @@ func TestOplogKey_Create(t *testing.T) { name: "empty-rootKeyId", args: args{}, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -63,7 +63,7 @@ func TestOplogKey_Create(t *testing.T) { got, err := kms.NewOplogKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/oplog_key_version.go b/internal/kms/oplog_key_version.go index fb1a3e973..5d36dbde9 100644 --- a/internal/kms/oplog_key_version.go +++ b/internal/kms/oplog_key_version.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,15 +22,16 @@ type OplogKeyVersion struct { // OplogKeyVersion creates a new in memory key version. No options are // currently supported. -func NewOplogKeyVersion(oplogKeyId string, key []byte, rootKeyVersionId string, opt ...Option) (*OplogKeyVersion, error) { +func NewOplogKeyVersion(oplogKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*OplogKeyVersion, error) { + const op = "kms.NewOplogKeyVersion" if oplogKeyId == "" { - return nil, fmt.Errorf("new oplog key version: missing oplog key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing oplog key id") } if len(key) == 0 { - return nil, fmt.Errorf("new oplog key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } if rootKeyVersionId == "" { - return nil, fmt.Errorf("new oplog key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } k := &OplogKeyVersion{ @@ -61,19 +61,20 @@ func (k *OplogKeyVersion) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // version before it's written. -func (k *OplogKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *OplogKeyVersion) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(OplogKeyVersion).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("oplog key version vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.CtKey == nil { - return fmt.Errorf("oplog key version vet for write: missing key: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing key") } if k.OplogKeyId == "" { - return fmt.Errorf("oplog key version vet for write: missing oplog key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing oplog key id") } if k.RootKeyVersionId == "" { - return fmt.Errorf("oplog key version vet for write: missing root key version id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key version id") } } return nil @@ -96,20 +97,22 @@ func (k *OplogKeyVersion) SetTableName(n string) { // Encrypt will encrypt the key version's key func (k *OplogKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(OplogKeyVersion).Encrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.OplogKeyVersion directly if err := structwrapping.WrapStruct(ctx, cipher, k.OplogKeyVersion, nil); err != nil { - return fmt.Errorf("error encrypting kms oplog key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Encrypt)) } return nil } // Decrypt will decrypt the key version's key func (k *OplogKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(OplogKeyVersion).Decrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.OplogKeyVersion directly if err := structwrapping.UnwrapStruct(ctx, cipher, k.OplogKeyVersion, nil); err != nil { - return fmt.Errorf("error decrypting kms oplog key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Decrypt)) } return nil } diff --git a/internal/kms/oplog_key_version_test.go b/internal/kms/oplog_key_version_test.go index 23c1df84e..d51864525 100644 --- a/internal/kms/oplog_key_version_test.go +++ b/internal/kms/oplog_key_version_test.go @@ -38,7 +38,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { args args want *kms.OplogKeyVersion wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -49,7 +49,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-key", @@ -58,7 +58,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-root-key-version-id", @@ -67,7 +67,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { key: []byte("test key"), }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -93,7 +93,7 @@ func TestOplogKeyVersion_Create(t *testing.T) { got, err := kms.NewOplogKeyVersion(tt.args.oplogKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/repository.go b/internal/kms/repository.go index 24160982e..51d9946b4 100644 --- a/internal/kms/repository.go +++ b/internal/kms/repository.go @@ -2,7 +2,6 @@ package kms import ( "context" - stderrors "errors" "fmt" "io" @@ -24,11 +23,12 @@ type Repository struct { // NewRepository creates a new kms Repository. Supports the options: WithLimit // which sets a default limit on results returned by repo operations. func NewRepository(r db.Reader, w db.Writer, opt ...Option) (*Repository, error) { + const op = "kms.NewRepository" if r == nil { - return nil, stderrors.New("error creating db repository with nil reader") + return nil, errors.New(errors.InvalidParameter, op, "nil reader") } if w == nil { - return nil, stderrors.New("error creating db repository with nil writer") + return nil, errors.New(errors.InvalidParameter, op, "nil writer") } opts := getOpts(opt...) if opts.withLimit == 0 { @@ -78,74 +78,75 @@ type Keys map[KeyType]KeyIder // This function encapsulates all the work required within a db.TxHandler and // allows this capability to be shared with the iam repo. func CreateKeysTx(ctx context.Context, dbReader db.Reader, dbWriter db.Writer, rootWrapper wrapping.Wrapper, randomReader io.Reader, scopeId string) (Keys, error) { + const op = "kms.CreateKeysTx" if dbReader == nil { - return nil, fmt.Errorf("create keys: missing db reader: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing db reader") } if dbWriter == nil { - return nil, fmt.Errorf("create keys: missing db writer: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing db writer") } if rootWrapper == nil { - return nil, fmt.Errorf("create keys: missing root wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root wrapper") } if randomReader == nil { - return nil, fmt.Errorf("create keys: missing random reader: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing random reader") } if scopeId == "" { - return nil, fmt.Errorf("create keys: missing scope id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing scope id") } k, err := generateKey(randomReader) if err != nil { - return nil, fmt.Errorf("create keys: error generating random bytes for root key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for root key in scope %s", scopeId))) } rootKey, rootKeyVersion, err := createRootKeyTx(ctx, dbWriter, rootWrapper, scopeId, k) if err != nil { - return nil, fmt.Errorf("create keys: unable to create root key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to create root key in scope %s", scopeId))) } rkvWrapper := aead.NewWrapper(nil) if _, err := rkvWrapper.SetConfig(map[string]string{ "key_id": rootKeyVersion.GetPrivateId(), }); err != nil { - return nil, fmt.Errorf("create keys: error setting config on aead root wrapper in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting config on aead root wrapper in scope %s", scopeId))) } if err := rkvWrapper.SetAESGCMKeyBytes(rootKeyVersion.GetKey()); err != nil { - return nil, fmt.Errorf("create keys: error setting key bytes on aead root wrapper in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error setting key bytes on aead root wrapper in scope %s", scopeId))) } k, err = generateKey(randomReader) if err != nil { - return nil, fmt.Errorf("create keys: error generating random bytes for database key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for database key in scope %s", scopeId))) } dbKey, dbKeyVersion, err := createDatabaseKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) if err != nil { - return nil, fmt.Errorf("create keys: unable to create database key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to create database key in scope %s", scopeId))) } k, err = generateKey(randomReader) if err != nil { - return nil, fmt.Errorf("create keys: error generating random bytes for oplog key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for oplog key in scope %s", scopeId))) } oplogKey, oplogKeyVersion, err := createOplogKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) if err != nil { - return nil, fmt.Errorf("create keys: unable to create oplog key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to create oplog key in scope %s", scopeId))) } k, err = generateKey(randomReader) if err != nil { - return nil, fmt.Errorf("create keys: error generating random bytes for session key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for session key in scope %s", scopeId))) } sessionKey, sessionKeyVersion, err := createSessionKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) if err != nil { - return nil, fmt.Errorf("create keys: unable to create session key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to create session key in scope %s", scopeId))) } k, err = generateKey(randomReader) if err != nil { - return nil, fmt.Errorf("create keys: error generating random bytes for token key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error generating random bytes for token key in scope %s", scopeId))) } tokenKey, tokenKeyVersion, err := createTokenKeyTx(ctx, dbReader, dbWriter, rkvWrapper, k) if err != nil { - return nil, fmt.Errorf("create keys: unable to create token key in scope %s: %w", scopeId, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to create token key in scope %s", scopeId))) } keys := Keys{ @@ -164,9 +165,10 @@ func CreateKeysTx(ctx context.Context, dbReader db.Reader, dbWriter db.Writer, r } func generateKey(randomReader io.Reader) ([]byte, error) { + const op = "kms.generateKey" k, err := uuid.GenerateRandomBytesWithReader(32, randomReader) if err != nil { - return nil, fmt.Errorf("error generating random bytes for key: %w", err) + return nil, errors.Wrap(err, op) } return k, nil } diff --git a/internal/kms/repository_database_key.go b/internal/kms/repository_database_key.go index b12389103..5807934d3 100644 --- a/internal/kms/repository_database_key.go +++ b/internal/kms/repository_database_key.go @@ -12,7 +12,8 @@ import ( // CreateDatabaseKey inserts into the repository and returns the new database key and // database key version. There are no valid options at this time. -func (r *Repository) CreateDatabaseKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, opt ...Option) (*DatabaseKey, *DatabaseKeyVersion, error) { +func (r *Repository) CreateDatabaseKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*DatabaseKey, *DatabaseKeyVersion, error) { + const op = "kms.(Repository).CreateDatabaseKey" var returnedDk, returnedDv interface{} _, err := r.writer.DoTx( ctx, @@ -21,84 +22,86 @@ func (r *Repository) CreateDatabaseKey(ctx context.Context, rkvWrapper wrapping. func(reader db.Reader, w db.Writer) error { var err error if returnedDk, returnedDv, err = createDatabaseKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("create database key: %w", err) + return nil, nil, errors.Wrap(err, op) } - return returnedDk.(*DatabaseKey), returnedDv.(*DatabaseKeyVersion), err + return returnedDk.(*DatabaseKey), returnedDv.(*DatabaseKeyVersion), nil } // createDatabaseKeyTx inserts into the db (via db.Writer) and returns the new database key // and database key version. This function encapsulates all the work required within // a db.TxHandler and allows this capability to be shared with the iam repo. func createDatabaseKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*DatabaseKey, *DatabaseKeyVersion, error) { + const op = "kms.createDatabaseKeyTx" if rkvWrapper == nil { - return nil, nil, fmt.Errorf("create database key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, nil, fmt.Errorf("create database key: missing key: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, fmt.Errorf("create database key: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, nil, fmt.Errorf("create database key: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } rv := AllocRootKeyVersion() rv.PrivateId = rootKeyVersionId err := r.LookupById(ctx, &rv) if err != nil { - return nil, nil, fmt.Errorf("create database key: unable to lookup root key version %s: %w", rootKeyVersionId, err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) } dk := AllocDatabaseKey() dv := AllocDatabaseKeyVersion() id, err := newDatabaseKeyId() if err != nil { - return nil, nil, fmt.Errorf("create database key: %w", err) + return nil, nil, errors.Wrap(err, op) } dk.PrivateId = id dk.RootKeyId = rv.RootKeyId id, err = newDatabaseKeyVersionId() if err != nil { - return nil, nil, fmt.Errorf("create database key: %w", err) + return nil, nil, errors.Wrap(err, op) } dv.PrivateId = id dv.DatabaseKeyId = dk.PrivateId dv.RootKeyVersionId = rootKeyVersionId dv.Key = key if err := dv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, fmt.Errorf("create database key: %w", err) + return nil, nil, errors.Wrap(err, op) } // no oplog entries for keys if err := w.Create(ctx, &dk); err != nil { - return nil, nil, fmt.Errorf("create database key: database create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("keys create")) } // no oplog entries for key versions if err := w.Create(ctx, &dv); err != nil { - return nil, nil, fmt.Errorf("create database key: version create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("key versions create")) } - return &dk, &dv, err + return &dk, &dv, nil } // LookupDatabaseKey will look up a key in the repository. If the key is not // found, it will return nil, nil. -func (r *Repository) LookupDatabaseKey(ctx context.Context, privateId string, opt ...Option) (*DatabaseKey, error) { +func (r *Repository) LookupDatabaseKey(ctx context.Context, privateId string, _ ...Option) (*DatabaseKey, error) { + const op = "kms.(Repository).LookupDatabaseKey" if privateId == "" { - return nil, fmt.Errorf("lookup database key: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocDatabaseKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup database key: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return &k, nil } @@ -106,14 +109,15 @@ func (r *Repository) LookupDatabaseKey(ctx context.Context, privateId string, op // DeleteDatabaseKey deletes the key for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteDatabaseKey(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteDatabaseKey(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).LookupDatabaseKey" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete database key: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocDatabaseKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete database key: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -125,24 +129,28 @@ func (r *Repository) DeleteDatabaseKey(ctx context.Context, privateId string, op dk := k.Clone() // no oplog entries for root keys rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete database key: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // ListDatabaseKeys will list the keys. Supports the WithLimit option. func (r *Repository) ListDatabaseKeys(ctx context.Context, opt ...Option) ([]Dek, error) { + const op = "kms.(Repository).ListDatabaseKeys" var keys []*DatabaseKey err := r.list(ctx, &keys, "1=1", nil, opt...) if err != nil { - return nil, fmt.Errorf("list database keys: %w", err) + return nil, errors.Wrap(err, op) } deks := make([]Dek, 0, len(keys)) for _, key := range keys { diff --git a/internal/kms/repository_database_key_test.go b/internal/kms/repository_database_key_test.go index e294a7143..12eb6cb7f 100644 --- a/internal/kms/repository_database_key_test.go +++ b/internal/kms/repository_database_key_test.go @@ -114,9 +114,7 @@ func TestRepository_CreateDatabaseKey(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(dk) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -209,9 +207,7 @@ func TestRepository_DeleteDatabaseKey(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) // make sure there was no oplog written err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) diff --git a/internal/kms/repository_database_key_version.go b/internal/kms/repository_database_key_version.go index 8013279b2..715313904 100644 --- a/internal/kms/repository_database_key_version.go +++ b/internal/kms/repository_database_key_version.go @@ -12,34 +12,35 @@ import ( // CreateDatabaseKeyVersion inserts into the repository and returns the new key // version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, key []byte, opt ...Option) (*DatabaseKeyVersion, error) { +func (r *Repository) CreateDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, key []byte, _ ...Option) (*DatabaseKeyVersion, error) { + const op = "kms.(Repository).CreateDatabaseKeyVersion" if rkvWrapper == nil { - return nil, fmt.Errorf("create database key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, fmt.Errorf("create database key version: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, fmt.Errorf("create database key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } if databaseKeyId == "" { - return nil, fmt.Errorf("create database key version: missing database key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing database key id") } if len(key) == 0 { - return nil, fmt.Errorf("create database key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } kv := AllocDatabaseKeyVersion() id, err := newDatabaseKeyVersionId() if err != nil { - return nil, fmt.Errorf("create database key version: %w", err) + return nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyVersionId = rootKeyVersionId kv.Key = key kv.DatabaseKeyId = databaseKeyId if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("create database key version: encrypt: %w", err) + return nil, errors.Wrap(err, op) } var returnedKey interface{} @@ -51,33 +52,34 @@ func (r *Repository) CreateDatabaseKeyVersion(ctx context.Context, rkvWrapper wr returnedKey = kv.Clone() // no oplog entries for root key version if err := w.Create(ctx, returnedKey); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, fmt.Errorf("create database key version: %w for %s database key id", err, kv.DatabaseKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s database key id", kv.DatabaseKeyId))) } - return returnedKey.(*DatabaseKeyVersion), err + return returnedKey.(*DatabaseKeyVersion), nil } // LookupDatabaseKeyVersion will look up a key version in the repository. If // the key version is not found, it will return nil, nil. -func (r *Repository) LookupDatabaseKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*DatabaseKeyVersion, error) { +func (r *Repository) LookupDatabaseKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*DatabaseKeyVersion, error) { + const op = "kms.(Repository).LookupDatabaseKeyVersion" if privateId == "" { - return nil, fmt.Errorf("lookup database key version: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup database key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocDatabaseKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup database key version: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("lookup database key version: decrypt: %w", err) + return nil, errors.Wrap(err, op) } return &k, nil } @@ -85,14 +87,15 @@ func (r *Repository) LookupDatabaseKeyVersion(ctx context.Context, keyWrapper wr // DeleteDatabaseKeyVersion deletes the key version for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteDatabaseKeyVersion(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteDatabaseKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteDatabaseKeyVersion" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete database key version: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocDatabaseKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete database key version: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -104,57 +107,62 @@ func (r *Repository) DeleteDatabaseKeyVersion(ctx context.Context, privateId str dk := k.Clone() // no oplog entries for the key version rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete database key version: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // LatestDatabaseKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil, -// errors.ErrRecordNotFound. -func (r *Repository) LatestDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, opt ...Option) (*DatabaseKeyVersion, error) { +// version number. When no results are found, it returns nil with an +// errors.RecordNotFound error. +func (r *Repository) LatestDatabaseKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, _ ...Option) (*DatabaseKeyVersion, error) { + const op = "kms.(Repository).LatestDatabaseKeyVersion" if databaseKeyId == "" { - return nil, fmt.Errorf("latest database key version: missing database key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing database key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("latest database key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var foundKeys []*DatabaseKeyVersion if err := r.reader.SearchWhere(ctx, &foundKeys, "database_key_id = ?", []interface{}{databaseKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, fmt.Errorf("latest database key version: failed %w for %s", err, databaseKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", databaseKeyId))) } if len(foundKeys) == 0 { - return nil, errors.ErrRecordNotFound + return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) } if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("latest database key version: %w", err) + return nil, errors.Wrap(err, op) } return foundKeys[0], nil } // ListDatabaseKeyVersions will lists versions of a key. Supports the WithLimit option. func (r *Repository) ListDatabaseKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, databaseKeyId string, opt ...Option) ([]DekVersion, error) { + const op = "kms.(Repository).ListDatabaseKeyVersions" if databaseKeyId == "" { - return nil, fmt.Errorf("list database key versions: missing database key id %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing database key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("list database key versions: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var versions []*DatabaseKeyVersion err := r.list(ctx, &versions, "database_key_id = ?", []interface{}{databaseKeyId}, opt...) if err != nil { - return nil, fmt.Errorf("list database key versions: %w", err) + return nil, errors.Wrap(err, op) } for i, k := range versions { if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("list database key versions: error decrypting key num %d: %w", i, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) } } dekVersions := make([]DekVersion, 0, len(versions)) diff --git a/internal/kms/repository_database_key_version_test.go b/internal/kms/repository_database_key_version_test.go index a41da0826..e5babcece 100644 --- a/internal/kms/repository_database_key_version_test.go +++ b/internal/kms/repository_database_key_version_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid", @@ -67,7 +67,7 @@ func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { databaseKeyId: dk.PrivateId, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -76,7 +76,7 @@ func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -86,9 +86,7 @@ func TestRepository_CreateDatabaseKeyVersion(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(k) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -173,9 +171,7 @@ func TestRepository_DeleteDatabaseKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) @@ -260,9 +256,7 @@ func TestRepository_LatestDatabaseKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) diff --git a/internal/kms/repository_oplog_key.go b/internal/kms/repository_oplog_key.go index a1b4b94f7..2b5a7afdd 100644 --- a/internal/kms/repository_oplog_key.go +++ b/internal/kms/repository_oplog_key.go @@ -12,7 +12,8 @@ import ( // CreateOplogKey inserts into the repository and returns the new key and the // key version. There are no valid options at this time. -func (r *Repository) CreateOplogKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, opt ...Option) (*OplogKey, *OplogKeyVersion, error) { +func (r *Repository) CreateOplogKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*OplogKey, *OplogKeyVersion, error) { + const op = "kms.(Repository).CreateOplogKey" var returnedDk, returnedDv interface{} _, err := r.writer.DoTx( ctx, @@ -21,84 +22,86 @@ func (r *Repository) CreateOplogKey(ctx context.Context, rkvWrapper wrapping.Wra func(reader db.Reader, w db.Writer) error { var err error if returnedDk, returnedDv, err = createOplogKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("create oplog key: %w", err) + return nil, nil, errors.Wrap(err, op) } - return returnedDk.(*OplogKey), returnedDv.(*OplogKeyVersion), err + return returnedDk.(*OplogKey), returnedDv.(*OplogKeyVersion), nil } // createOplogKeyTx inserts into the db (via db.Writer) and returns the new key // and the key version. This function encapsulates all the work required within // a db.TxHandler and allows this capability to be shared with the iam repo. func createOplogKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*OplogKey, *OplogKeyVersion, error) { + const op = "kms.createOplogKeyTx" if rkvWrapper == nil { - return nil, nil, fmt.Errorf("create oplog key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, nil, fmt.Errorf("create oplog key: missing key: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, fmt.Errorf("create oplog key: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, nil, fmt.Errorf("create oplog key: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } rv := AllocRootKeyVersion() rv.PrivateId = rootKeyVersionId err := r.LookupById(ctx, &rv) if err != nil { - return nil, nil, fmt.Errorf("create oplog key: unable to lookup root key version %s: %w", rootKeyVersionId, err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) } opk := AllocOplogKey() opv := AllocOplogKeyVersion() id, err := newOplogKeyId() if err != nil { - return nil, nil, fmt.Errorf("create oplog key: %w", err) + return nil, nil, errors.Wrap(err, op) } opk.PrivateId = id opk.RootKeyId = rv.RootKeyId id, err = newOplogKeyVersionId() if err != nil { - return nil, nil, fmt.Errorf("create oplog key: %w", err) + return nil, nil, errors.Wrap(err, op) } opv.PrivateId = id opv.OplogKeyId = opk.PrivateId opv.RootKeyVersionId = rootKeyVersionId opv.Key = key if err := opv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, fmt.Errorf("create oplog key: %w", err) + return nil, nil, errors.Wrap(err, op) } // no oplog entries for keys if err := w.Create(ctx, &opk); err != nil { - return nil, nil, fmt.Errorf("create oplog key: key create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("key create")) } // no oplog entries for key versions if err := w.Create(ctx, &opv); err != nil { - return nil, nil, fmt.Errorf("create oplog key: version create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("key versions create")) } - return &opk, &opv, err + return &opk, &opv, nil } // LookupOplogKey will look up a key in the repository. If the key is not // found, it will return nil, nil. -func (r *Repository) LookupOplogKey(ctx context.Context, privateId string, opt ...Option) (*OplogKey, error) { +func (r *Repository) LookupOplogKey(ctx context.Context, privateId string, _ ...Option) (*OplogKey, error) { + const op = "kms.(Repository).LookupOplogKey" if privateId == "" { - return nil, fmt.Errorf("lookup oplog key: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocOplogKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup oplog key: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return &k, nil } @@ -106,14 +109,15 @@ func (r *Repository) LookupOplogKey(ctx context.Context, privateId string, opt . // DeleteOplogKey deletes the key for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteOplogKey(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteOplogKey(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteOplogKey" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete oplog key: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocOplogKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete oplog key: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -125,24 +129,28 @@ func (r *Repository) DeleteOplogKey(ctx context.Context, privateId string, opt . dk := k.Clone() // no oplog entries for root keys rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete oplog key: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // ListOplogKeys will list the keys. Supports the WithLimit option. func (r *Repository) ListOplogKeys(ctx context.Context, opt ...Option) ([]Dek, error) { + const op = "kms.(Repository).ListOplogKeys" var keys []*OplogKey err := r.list(ctx, &keys, "1=1", nil, opt...) if err != nil { - return nil, fmt.Errorf("list oplog keys: %w", err) + return nil, errors.Wrap(err, op) } deks := make([]Dek, 0, len(keys)) for _, key := range keys { diff --git a/internal/kms/repository_oplog_key_test.go b/internal/kms/repository_oplog_key_test.go index 54cc87bb3..c585efd10 100644 --- a/internal/kms/repository_oplog_key_test.go +++ b/internal/kms/repository_oplog_key_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid-org", @@ -57,7 +57,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { keyWrapper: rkvWrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "empty-key", @@ -67,7 +67,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { key: []byte(""), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -77,7 +77,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "not-rkv-wrapper", @@ -87,7 +87,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { keyWrapper: wrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "wrapper-missing-id", @@ -104,7 +104,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { }(), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -114,9 +114,7 @@ func TestRepository_CreateOplogKey(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(opk) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -209,9 +207,7 @@ func TestRepository_DeleteOplogKey(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) // make sure there was no oplog written err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) diff --git a/internal/kms/repository_oplog_key_version.go b/internal/kms/repository_oplog_key_version.go index 92c40c945..a8d922809 100644 --- a/internal/kms/repository_oplog_key_version.go +++ b/internal/kms/repository_oplog_key_version.go @@ -12,34 +12,35 @@ import ( // CreateOplogKeyVersion inserts into the repository and returns the new key // version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, key []byte, opt ...Option) (*OplogKeyVersion, error) { +func (r *Repository) CreateOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, key []byte, _ ...Option) (*OplogKeyVersion, error) { + const op = "kms.(Repository).CreateOplogKeyVersion" if rkvWrapper == nil { - return nil, fmt.Errorf("create oplog key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, fmt.Errorf("create oplog key version: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, fmt.Errorf("create oplog key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } if oplogKeyId == "" { - return nil, fmt.Errorf("create oplog key version: missing oplog key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing oplog key id") } if len(key) == 0 { - return nil, fmt.Errorf("create oplog key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } kv := AllocOplogKeyVersion() id, err := newOplogKeyVersionId() if err != nil { - return nil, fmt.Errorf("create oplog key version: %w", err) + return nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyVersionId = rootKeyVersionId kv.Key = key kv.OplogKeyId = oplogKeyId if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("create oplog key version: encrypt: %w", err) + return nil, errors.Wrap(err, op) } var returnedKey interface{} @@ -51,33 +52,34 @@ func (r *Repository) CreateOplogKeyVersion(ctx context.Context, rkvWrapper wrapp returnedKey = kv.Clone() // no oplog entries for root key version if err := w.Create(ctx, returnedKey); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, fmt.Errorf("create oplog key version: %w for %s oplog key id", err, kv.OplogKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s oplog key id", kv.OplogKeyId))) } - return returnedKey.(*OplogKeyVersion), err + return returnedKey.(*OplogKeyVersion), nil } // LookupOplogKeyVersion will look up a key version in the repository. If // the key version is not found, it will return nil, nil. -func (r *Repository) LookupOplogKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*OplogKeyVersion, error) { +func (r *Repository) LookupOplogKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*OplogKeyVersion, error) { + const op = "kms.(Repository).LookupOplogKeyVersion" if privateId == "" { - return nil, fmt.Errorf("lookup oplog key version: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup oplog key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocOplogKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup oplog key version: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("lookup oplog key version: decrypt: %w", err) + return nil, errors.Wrap(err, op) } return &k, nil } @@ -85,14 +87,15 @@ func (r *Repository) LookupOplogKeyVersion(ctx context.Context, keyWrapper wrapp // DeleteOplogKeyVersion deletes the key version for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteOplogKeyVersion(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteOplogKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteOplogKeyVersion" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete oplog key version: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocOplogKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete oplog key version: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -104,57 +107,62 @@ func (r *Repository) DeleteOplogKeyVersion(ctx context.Context, privateId string dk := k.Clone() // no oplog entries for the key version rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete oplog key version: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // LatestOplogKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil, -// errors.ErrRecordNotFound. -func (r *Repository) LatestOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, opt ...Option) (*OplogKeyVersion, error) { +// version number. When no results are found, it returns nil with an +// errors.RecordNotFound error. +func (r *Repository) LatestOplogKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, _ ...Option) (*OplogKeyVersion, error) { + const op = "kms.(Repository).LatestOplogKeyVersion" if oplogKeyId == "" { - return nil, fmt.Errorf("latest oplog key version: missing oplog key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing oplog key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("latest oplog key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var foundKeys []*OplogKeyVersion if err := r.reader.SearchWhere(ctx, &foundKeys, "oplog_key_id = ?", []interface{}{oplogKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, fmt.Errorf("latest oplog key version: failed %w for %s", err, oplogKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", oplogKeyId))) } if len(foundKeys) == 0 { - return nil, errors.ErrRecordNotFound + return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) } if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("latest oplog key version: %w", err) + return nil, errors.Wrap(err, op) } return foundKeys[0], nil } // ListOplogKeyVersions will lists versions of a key. Supports the WithLimit option. func (r *Repository) ListOplogKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, oplogKeyId string, opt ...Option) ([]DekVersion, error) { + const op = "kms.(Repository).ListOplogKeyVersions" if oplogKeyId == "" { - return nil, fmt.Errorf("list oplog key versions: missing oplog key id %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing oplog key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("list oplog key versions: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var versions []*OplogKeyVersion err := r.list(ctx, &versions, "oplog_key_id = ?", []interface{}{oplogKeyId}, opt...) if err != nil { - return nil, fmt.Errorf("list oplog key versions: %w", err) + return nil, errors.Wrap(err, op) } for i, k := range versions { if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("list oplog key versions: error decrypting key num %d: %w", i, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) } } dekVersions := make([]DekVersion, 0, len(versions)) diff --git a/internal/kms/repository_oplog_key_version_test.go b/internal/kms/repository_oplog_key_version_test.go index e042e0051..e6b47ecf6 100644 --- a/internal/kms/repository_oplog_key_version_test.go +++ b/internal/kms/repository_oplog_key_version_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateOplogKeyVersion(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid", @@ -67,7 +67,7 @@ func TestRepository_CreateOplogKeyVersion(t *testing.T) { oplogKeyId: dk.PrivateId, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -76,7 +76,7 @@ func TestRepository_CreateOplogKeyVersion(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -86,9 +86,7 @@ func TestRepository_CreateOplogKeyVersion(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(k) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -173,9 +171,7 @@ func TestRepository_DeleteOplogKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) @@ -260,9 +256,7 @@ func TestRepository_LatestOplogKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) diff --git a/internal/kms/repository_root_key.go b/internal/kms/repository_root_key.go index 6d396e4a4..2851354f1 100644 --- a/internal/kms/repository_root_key.go +++ b/internal/kms/repository_root_key.go @@ -11,7 +11,8 @@ import ( // CreateRootKey inserts into the repository and returns the new root key and // root key version. There are no valid options at this time. -func (r *Repository) CreateRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, scopeId string, key []byte, opt ...Option) (*RootKey, *RootKeyVersion, error) { +func (r *Repository) CreateRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, scopeId string, key []byte, _ ...Option) (*RootKey, *RootKeyVersion, error) { + const op = "kms.(Repository).CreateRootKey" var returnedRk, returnedKv interface{} _, err := r.writer.DoTx( ctx, @@ -20,75 +21,77 @@ func (r *Repository) CreateRootKey(ctx context.Context, keyWrapper wrapping.Wrap func(_ db.Reader, w db.Writer) error { var err error if returnedRk, returnedKv, err = createRootKeyTx(ctx, w, keyWrapper, scopeId, key); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("create root key: %w in %s", err, scopeId) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", scopeId))) } - return returnedRk.(*RootKey), returnedKv.(*RootKeyVersion), err + return returnedRk.(*RootKey), returnedKv.(*RootKeyVersion), nil } // createRootKeyTx inserts into the db (via db.Writer) and returns the new root key // and root key version. This function encapsulates all the work required within // a db.TxHandler and allows this capability to be shared with the iam repo. func createRootKeyTx(ctx context.Context, w db.Writer, keyWrapper wrapping.Wrapper, scopeId string, key []byte) (*RootKey, *RootKeyVersion, error) { + const op = "kms.createRootKeyTx" if scopeId == "" { - return nil, nil, fmt.Errorf("create root key: missing scope id: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing scope id") } if keyWrapper == nil { - return nil, nil, fmt.Errorf("create root key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, nil, fmt.Errorf("create root key: missing key: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key") } rk := AllocRootKey() kv := AllocRootKeyVersion() id, err := newRootKeyId() if err != nil { - return nil, nil, fmt.Errorf("create root key: %w", err) + return nil, nil, errors.Wrap(err, op) } rk.PrivateId = id rk.ScopeId = scopeId id, err = newRootKeyVersionId() if err != nil { - return nil, nil, fmt.Errorf("create root key: %w", err) + return nil, nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyId = rk.PrivateId kv.Key = key if err := kv.Encrypt(ctx, keyWrapper); err != nil { - return nil, nil, fmt.Errorf("create root key: %w", err) + return nil, nil, errors.Wrap(err, op) } // no oplog entries for root keys if err := w.Create(ctx, &rk); err != nil { - return nil, nil, fmt.Errorf("create root key: root create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("root keys")) } // no oplog entries for root key versions if err := w.Create(ctx, &kv); err != nil { - return nil, nil, fmt.Errorf("create root key: version create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("key versions"))) } - return &rk, &kv, err + return &rk, &kv, nil } // LookupRootKey will look up a root key in the repository. If the key is not // found, it will return nil, nil. -func (r *Repository) LookupRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*RootKey, error) { +func (r *Repository) LookupRootKey(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*RootKey, error) { + const op = "kms.(Repository).LookupRootKey" if privateId == "" { - return nil, fmt.Errorf("lookup root key: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup root key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocRootKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup root key: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return &k, nil } @@ -96,14 +99,15 @@ func (r *Repository) LookupRootKey(ctx context.Context, keyWrapper wrapping.Wrap // DeleteRootKey deletes the root key for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteRootKey(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteRootKey(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteRootKey" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete root key: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocRootKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete root key: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -115,24 +119,28 @@ func (r *Repository) DeleteRootKey(ctx context.Context, privateId string, opt .. dk := k.Clone() // no oplog entries for root keys rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete root key: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // ListRootKeys will list the root keys. Supports the WithLimit option. func (r *Repository) ListRootKeys(ctx context.Context, opt ...Option) ([]*RootKey, error) { + const op = "kms.(Repository).ListRootKeys" var keys []*RootKey err := r.list(ctx, &keys, "1=1", nil, opt...) if err != nil { - return nil, fmt.Errorf("list root keys: %w", err) + return nil, errors.Wrap(err, op) } return keys, nil } diff --git a/internal/kms/repository_root_key_test.go b/internal/kms/repository_root_key_test.go index 456f3020b..a14e44a28 100644 --- a/internal/kms/repository_root_key_test.go +++ b/internal/kms/repository_root_key_test.go @@ -36,7 +36,7 @@ func TestRepository_CreateRootKey(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid-org", @@ -72,7 +72,7 @@ func TestRepository_CreateRootKey(t *testing.T) { keyWrapper: wrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -82,7 +82,7 @@ func TestRepository_CreateRootKey(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -92,9 +92,7 @@ func TestRepository_CreateRootKey(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(rk) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -186,9 +184,7 @@ func TestRepository_DeleteRootKey(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) // make sure there was no oplog written err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) diff --git a/internal/kms/repository_root_key_version.go b/internal/kms/repository_root_key_version.go index 3d98226e5..701f6dfa5 100644 --- a/internal/kms/repository_root_key_version.go +++ b/internal/kms/repository_root_key_version.go @@ -11,26 +11,27 @@ import ( // CreateRootKeyVersion inserts into the repository and returns the new root key // version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, key []byte, opt ...Option) (*RootKeyVersion, error) { +func (r *Repository) CreateRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, key []byte, _ ...Option) (*RootKeyVersion, error) { + const op = "kms.(Repository).CreateRootKeyVersion" if rootKeyId == "" { - return nil, fmt.Errorf("create root key version: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } if keyWrapper == nil { - return nil, fmt.Errorf("create root key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, fmt.Errorf("create root key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } kv := AllocRootKeyVersion() id, err := newRootKeyVersionId() if err != nil { - return nil, fmt.Errorf("create root key version: %w", err) + return nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyId = rootKeyId kv.Key = key if err := kv.Encrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("create root key version: encrypt: %w", err) + return nil, errors.Wrap(err, op) } var returnedKey interface{} @@ -42,33 +43,34 @@ func (r *Repository) CreateRootKeyVersion(ctx context.Context, keyWrapper wrappi returnedKey = kv.Clone() // no oplog entries for root key version if err := w.Create(ctx, returnedKey); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, fmt.Errorf("create root key version: %w for %s root key id", err, kv.RootKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s root key id", kv.RootKeyId))) } - return returnedKey.(*RootKeyVersion), err + return returnedKey.(*RootKeyVersion), nil } // LookupRootKeyVersion will look up a root key version in the repository. If // the key version is not found, it will return nil, nil. -func (r *Repository) LookupRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*RootKeyVersion, error) { +func (r *Repository) LookupRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*RootKeyVersion, error) { + const op = "kms.(Repository).LookupRootKeyVersion" if privateId == "" { - return nil, fmt.Errorf("lookup root key version: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup root key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocRootKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup root key version: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("lookup root key version: decrypt: %w", err) + return nil, errors.Wrap(err, op) } return &k, nil } @@ -76,14 +78,15 @@ func (r *Repository) LookupRootKeyVersion(ctx context.Context, keyWrapper wrappi // DeleteRootKeyVersion deletes the root key version for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteRootKeyVersion(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteRootKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteRootKeyVersion" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete root key version: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocRootKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete root key version: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -95,57 +98,62 @@ func (r *Repository) DeleteRootKeyVersion(ctx context.Context, privateId string, dk := k.Clone() // no oplog entries for root key version rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete root key version: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // LatestRootKeyVersion searches for the root key version with the highest -// version number. When no results are found, it returns nil, -// errors.ErrRecordNotFound. -func (r *Repository) LatestRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, opt ...Option) (*RootKeyVersion, error) { +// version number. When no results are found, it returns nil with an +// errors.RecordNotFound error. +func (r *Repository) LatestRootKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, _ ...Option) (*RootKeyVersion, error) { + const op = "kms.(Repository).LatestRootKeyVersion" if rootKeyId == "" { - return nil, fmt.Errorf("latest root key version: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } if keyWrapper == nil { - return nil, fmt.Errorf("latest root key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } var foundKeys []RootKeyVersion if err := r.reader.SearchWhere(ctx, &foundKeys, "root_key_id = ?", []interface{}{rootKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, fmt.Errorf("latest root key version: failed %w for %s", err, rootKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", rootKeyId))) } if len(foundKeys) == 0 { - return nil, errors.ErrRecordNotFound + return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) } if err := foundKeys[0].Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("latest root key version: %w", err) + return nil, errors.Wrap(err, op) } return &foundKeys[0], nil } // ListRootKeyVersions in versions of a root key. Supports the WithLimit option. func (r *Repository) ListRootKeyVersions(ctx context.Context, keyWrapper wrapping.Wrapper, rootKeyId string, opt ...Option) ([]*RootKeyVersion, error) { + const op = "kms.(Repository).ListRootKeyVersions" if rootKeyId == "" { - return nil, fmt.Errorf("list root key versions: missing root key id %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } if keyWrapper == nil { - return nil, fmt.Errorf("list root key versions: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } var versions []*RootKeyVersion err := r.list(ctx, &versions, "root_key_id = ?", []interface{}{rootKeyId}, opt...) if err != nil { - return nil, fmt.Errorf("list root key versions: %w", err) + return nil, errors.Wrap(err, op) } for i, k := range versions { if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("list root key versions: error decrypting key num %d: %w", i, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) } } return versions, nil diff --git a/internal/kms/repository_root_key_version_test.go b/internal/kms/repository_root_key_version_test.go index 63afcdf10..ba7f4a366 100644 --- a/internal/kms/repository_root_key_version_test.go +++ b/internal/kms/repository_root_key_version_test.go @@ -37,7 +37,7 @@ func TestRepository_CreateRootKeyVersion(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid", @@ -65,7 +65,7 @@ func TestRepository_CreateRootKeyVersion(t *testing.T) { keyWrapper: wrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -75,7 +75,7 @@ func TestRepository_CreateRootKeyVersion(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -85,9 +85,7 @@ func TestRepository_CreateRootKeyVersion(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(k) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -173,9 +171,7 @@ func TestRepository_DeleteRootKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) @@ -258,9 +254,7 @@ func TestRepository_LatestRootKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) diff --git a/internal/kms/repository_session_key.go b/internal/kms/repository_session_key.go index a3837a4cf..bffa58992 100644 --- a/internal/kms/repository_session_key.go +++ b/internal/kms/repository_session_key.go @@ -12,7 +12,8 @@ import ( // CreateSessionKey inserts into the repository and returns the new key and the // key version. There are no valid options at this time. -func (r *Repository) CreateSessionKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, opt ...Option) (*SessionKey, *SessionKeyVersion, error) { +func (r *Repository) CreateSessionKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*SessionKey, *SessionKeyVersion, error) { + const op = "kms.(Repository).CreateSessionKey" var returnedDk, returnedDv interface{} _, err := r.writer.DoTx( ctx, @@ -21,84 +22,86 @@ func (r *Repository) CreateSessionKey(ctx context.Context, rkvWrapper wrapping.W func(reader db.Reader, w db.Writer) error { var err error if returnedDk, returnedDv, err = createSessionKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("create session key: %w", err) + return nil, nil, errors.Wrap(err, op) } - return returnedDk.(*SessionKey), returnedDv.(*SessionKeyVersion), err + return returnedDk.(*SessionKey), returnedDv.(*SessionKeyVersion), nil } // createSessionKeyTx inserts into the db (via db.Writer) and returns the new key // and the key version. This function encapsulates all the work required within // a db.TxHandler and allows this capability to be shared with the iam repo. func createSessionKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*SessionKey, *SessionKeyVersion, error) { + const op = "kms.createSessionKeyTx" if rkvWrapper == nil { - return nil, nil, fmt.Errorf("create session key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, nil, fmt.Errorf("create session key: missing key: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, fmt.Errorf("create session key: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, nil, fmt.Errorf("create session key: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } rv := AllocRootKeyVersion() rv.PrivateId = rootKeyVersionId err := r.LookupById(ctx, &rv) if err != nil { - return nil, nil, fmt.Errorf("create session key: unable to lookup root key version %s: %w", rootKeyVersionId, err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) } tk := AllocSessionKey() tv := AllocSessionKeyVersion() id, err := newSessionKeyId() if err != nil { - return nil, nil, fmt.Errorf("create session key: %w", err) + return nil, nil, errors.Wrap(err, op) } tk.PrivateId = id tk.RootKeyId = rv.RootKeyId id, err = newSessionKeyVersionId() if err != nil { - return nil, nil, fmt.Errorf("create session key: %w", err) + return nil, nil, errors.Wrap(err, op) } tv.PrivateId = id tv.SessionKeyId = tk.PrivateId tv.RootKeyVersionId = rootKeyVersionId tv.Key = key if err := tv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, fmt.Errorf("create session key: %w", err) + return nil, nil, errors.Wrap(err, op) } // no session entries for keys if err := w.Create(ctx, &tk); err != nil { - return nil, nil, fmt.Errorf("create session key: key create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("keys create")) } // no session entries for key versions if err := w.Create(ctx, &tv); err != nil { - return nil, nil, fmt.Errorf("create session key: version create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("key versions create")) } - return &tk, &tv, err + return &tk, &tv, nil } // LookupSessionKey will look up a key in the repository. If the key is not // found, it will return nil, nil. -func (r *Repository) LookupSessionKey(ctx context.Context, privateId string, opt ...Option) (*SessionKey, error) { +func (r *Repository) LookupSessionKey(ctx context.Context, privateId string, _ ...Option) (*SessionKey, error) { + const op = "kms.(Repository).LookupSessionKey" if privateId == "" { - return nil, fmt.Errorf("lookup session key: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocSessionKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup session key: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return &k, nil } @@ -106,14 +109,15 @@ func (r *Repository) LookupSessionKey(ctx context.Context, privateId string, opt // DeleteSessionKey deletes the key for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteSessionKey(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteSessionKey(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteSessionKey" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete session key: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocSessionKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete session key: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -125,24 +129,28 @@ func (r *Repository) DeleteSessionKey(ctx context.Context, privateId string, opt dk := k.Clone() // no session entries for root keys rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete session key: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // ListSessionKeys will list the keys. Supports the WithLimit option. func (r *Repository) ListSessionKeys(ctx context.Context, opt ...Option) ([]Dek, error) { + const op = "kms.(Repository).ListSessionKeys" var keys []*SessionKey err := r.list(ctx, &keys, "1=1", nil, opt...) if err != nil { - return nil, fmt.Errorf("list session keys: %w", err) + return nil, errors.Wrap(err, op) } deks := make([]Dek, 0, len(keys)) for _, key := range keys { diff --git a/internal/kms/repository_session_key_test.go b/internal/kms/repository_session_key_test.go index b9c2574cd..a8623dbb9 100644 --- a/internal/kms/repository_session_key_test.go +++ b/internal/kms/repository_session_key_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid-org", @@ -57,7 +57,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { keyWrapper: rkvWrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "empty-key", @@ -67,7 +67,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { key: []byte(""), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -77,7 +77,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "not-rkv-wrapper", @@ -87,7 +87,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { keyWrapper: wrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "wrapper-missing-id", @@ -104,7 +104,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { }(), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -114,9 +114,7 @@ func TestRepository_CreateSessionKey(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(tk) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -209,9 +207,8 @@ func TestRepository_DeleteSessionKey(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) + // make sure there was no session written err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) diff --git a/internal/kms/repository_session_key_version.go b/internal/kms/repository_session_key_version.go index 45838ba36..663464be9 100644 --- a/internal/kms/repository_session_key_version.go +++ b/internal/kms/repository_session_key_version.go @@ -12,34 +12,35 @@ import ( // CreateSessionKeyVersion inserts into the repository and returns the new key // version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, key []byte, opt ...Option) (*SessionKeyVersion, error) { +func (r *Repository) CreateSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, key []byte, _ ...Option) (*SessionKeyVersion, error) { + const op = "kms.(Repository).CreateSessionKeyVersion" if rkvWrapper == nil { - return nil, fmt.Errorf("create session key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, fmt.Errorf("create session key version: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, fmt.Errorf("create session key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } if sessionKeyId == "" { - return nil, fmt.Errorf("create session key version: missing session key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing session key id") } if len(key) == 0 { - return nil, fmt.Errorf("create session key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } kv := AllocSessionKeyVersion() id, err := newSessionKeyVersionId() if err != nil { - return nil, fmt.Errorf("create session key version: %w", err) + return nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyVersionId = rootKeyVersionId kv.Key = key kv.SessionKeyId = sessionKeyId if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("create session key version: encrypt: %w", err) + return nil, errors.Wrap(err, op) } var returnedKey interface{} @@ -51,33 +52,34 @@ func (r *Repository) CreateSessionKeyVersion(ctx context.Context, rkvWrapper wra returnedKey = kv.Clone() // no session entries for root key version if err := w.Create(ctx, returnedKey); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, fmt.Errorf("create session key version: %w for %s session key id", err, kv.SessionKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s session key id", kv.SessionKeyId))) } - return returnedKey.(*SessionKeyVersion), err + return returnedKey.(*SessionKeyVersion), nil } // LookupSessionKeyVersion will look up a key version in the repository. If // the key version is not found, it will return nil, nil. -func (r *Repository) LookupSessionKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*SessionKeyVersion, error) { +func (r *Repository) LookupSessionKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*SessionKeyVersion, error) { + const op = "kms.(Repository).LookupSessionKeyVersion" if privateId == "" { - return nil, fmt.Errorf("lookup session key version: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup session key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocSessionKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup session key version: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("lookup session key version: decrypt: %w", err) + return nil, errors.Wrap(err, op) } return &k, nil } @@ -85,14 +87,15 @@ func (r *Repository) LookupSessionKeyVersion(ctx context.Context, keyWrapper wra // DeleteSessionKeyVersion deletes the key version for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteSessionKeyVersion(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteSessionKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteSessionKeyVersion" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete session key version: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocSessionKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete session key version: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -104,57 +107,62 @@ func (r *Repository) DeleteSessionKeyVersion(ctx context.Context, privateId stri dk := k.Clone() // no session entries for the key version rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete session key version: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // LatestSessionKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil, -// errors.ErrRecordNotFound. -func (r *Repository) LatestSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, opt ...Option) (*SessionKeyVersion, error) { +// version number. When no results are found, it returns nil with an +// errors.RecordNotFound error. +func (r *Repository) LatestSessionKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, _ ...Option) (*SessionKeyVersion, error) { + const op = "kms.(Repository).LatestSessionKeyVersion" if sessionKeyId == "" { - return nil, fmt.Errorf("latest session key version: missing session key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing session key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("latest session key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var foundKeys []*SessionKeyVersion if err := r.reader.SearchWhere(ctx, &foundKeys, "session_key_id = ?", []interface{}{sessionKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, fmt.Errorf("latest session key version: failed %w for %s", err, sessionKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", sessionKeyId))) } if len(foundKeys) == 0 { - return nil, errors.ErrRecordNotFound + return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) } if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("latest session key version: %w", err) + return nil, errors.Wrap(err, op) } return foundKeys[0], nil } // ListSessionKeyVersions will lists versions of a key. Supports the WithLimit option. func (r *Repository) ListSessionKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, sessionKeyId string, opt ...Option) ([]DekVersion, error) { + const op = "kms.(Repository).ListSessionKeyVersions" if sessionKeyId == "" { - return nil, fmt.Errorf("list session key versions: missing session key id %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing session key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("list session key versions: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var versions []*SessionKeyVersion err := r.list(ctx, &versions, "session_key_id = ?", []interface{}{sessionKeyId}, opt...) if err != nil { - return nil, fmt.Errorf("list session key versions: %w", err) + return nil, errors.Wrap(err, op) } for i, k := range versions { if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("list session key versions: error decrypting key num %d: %w", i, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) } } dekVersions := make([]DekVersion, 0, len(versions)) diff --git a/internal/kms/repository_session_key_version_test.go b/internal/kms/repository_session_key_version_test.go index eaf73644a..9b12404a2 100644 --- a/internal/kms/repository_session_key_version_test.go +++ b/internal/kms/repository_session_key_version_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateSessionKeyVersion(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid", @@ -67,7 +67,7 @@ func TestRepository_CreateSessionKeyVersion(t *testing.T) { sessionKeyId: sk.PrivateId, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -76,7 +76,7 @@ func TestRepository_CreateSessionKeyVersion(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -86,9 +86,7 @@ func TestRepository_CreateSessionKeyVersion(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(k) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -173,9 +171,7 @@ func TestRepository_DeleteSessionKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) @@ -260,9 +256,7 @@ func TestRepository_LatestSessionKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) diff --git a/internal/kms/repository_test.go b/internal/kms/repository_test.go index a2ab11617..99d83e62c 100644 --- a/internal/kms/repository_test.go +++ b/internal/kms/repository_test.go @@ -51,7 +51,7 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "error creating db repository with nil writer", + wantErrString: "kms.NewRepository: nil writer: parameter violation: error #100", }, { name: "nil-reader", @@ -61,7 +61,7 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "error creating db repository with nil reader", + wantErrString: "kms.NewRepository: nil reader: parameter violation: error #100", }, } for _, tt := range tests { @@ -99,7 +99,7 @@ func TestCreateKeysTx(t *testing.T) { name string args args wantErr bool - wantErrIs error + wantErrIs errors.Code }{ { name: "valid", @@ -121,7 +121,7 @@ func TestCreateKeysTx(t *testing.T) { scopeId: org.PublicId, }, wantErr: true, - wantErrIs: errors.ErrInvalidParameter, + wantErrIs: errors.InvalidParameter, }, { name: "nil-writer", @@ -133,7 +133,7 @@ func TestCreateKeysTx(t *testing.T) { scopeId: org.PublicId, }, wantErr: true, - wantErrIs: errors.ErrInvalidParameter, + wantErrIs: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -145,7 +145,7 @@ func TestCreateKeysTx(t *testing.T) { scopeId: org.PublicId, }, wantErr: true, - wantErrIs: errors.ErrInvalidParameter, + wantErrIs: errors.InvalidParameter, }, { name: "empty-scope", @@ -157,7 +157,7 @@ func TestCreateKeysTx(t *testing.T) { scopeId: "", }, wantErr: true, - wantErrIs: errors.ErrInvalidParameter, + wantErrIs: errors.InvalidParameter, }, { name: "bad-scope", @@ -177,9 +177,7 @@ func TestCreateKeysTx(t *testing.T) { keys, err := kms.CreateKeysTx(tt.args.ctx, tt.args.dbReader, tt.args.dbWriter, tt.args.rootWrapper, tt.args.randomReader, tt.args.scopeId) if tt.wantErr { require.Error(err) - if tt.wantErrIs != nil { - assert.Truef(errors.Is(err, tt.wantErrIs), "unexpected error: %s", err.Error()) - } + assert.Truef(errors.Match(errors.T(tt.wantErrIs), err), "unexpected error: %s", err.Error()) return } require.NoError(err) diff --git a/internal/kms/repository_token_key.go b/internal/kms/repository_token_key.go index d7667f629..debd92065 100644 --- a/internal/kms/repository_token_key.go +++ b/internal/kms/repository_token_key.go @@ -12,7 +12,8 @@ import ( // CreateTokenKey inserts into the repository and returns the new key and the // key version. There are no valid options at this time. -func (r *Repository) CreateTokenKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, opt ...Option) (*TokenKey, *TokenKeyVersion, error) { +func (r *Repository) CreateTokenKey(ctx context.Context, rkvWrapper wrapping.Wrapper, key []byte, _ ...Option) (*TokenKey, *TokenKeyVersion, error) { + const op = "kms.(Repository).CreateTokenKey" var returnedDk, returnedDv interface{} _, err := r.writer.DoTx( ctx, @@ -21,84 +22,86 @@ func (r *Repository) CreateTokenKey(ctx context.Context, rkvWrapper wrapping.Wra func(reader db.Reader, w db.Writer) error { var err error if returnedDk, returnedDv, err = createTokenKeyTx(ctx, reader, w, rkvWrapper, key); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, nil, fmt.Errorf("create token key: %w", err) + return nil, nil, errors.Wrap(err, op) } - return returnedDk.(*TokenKey), returnedDv.(*TokenKeyVersion), err + return returnedDk.(*TokenKey), returnedDv.(*TokenKeyVersion), nil } // createTokenKeyTx inserts into the db (via db.Writer) and returns the new key // and the key version. This function encapsulates all the work required within // a db.TxHandler and allows this capability to be shared with the iam repo. func createTokenKeyTx(ctx context.Context, r db.Reader, w db.Writer, rkvWrapper wrapping.Wrapper, key []byte) (*TokenKey, *TokenKeyVersion, error) { + const op = "kms.createTokenKeyTx" if rkvWrapper == nil { - return nil, nil, fmt.Errorf("create token key: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } if len(key) == 0 { - return nil, nil, fmt.Errorf("create token key: missing key: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing key") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, nil, fmt.Errorf("create token key: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, nil, fmt.Errorf("create token key: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } rv := AllocRootKeyVersion() rv.PrivateId = rootKeyVersionId err := r.LookupById(ctx, &rv) if err != nil { - return nil, nil, fmt.Errorf("create token key: unable to lookup root key version %s: %w", rootKeyVersionId, err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("unable to lookup root key version %s", rootKeyVersionId))) } tk := AllocTokenKey() tv := AllocTokenKeyVersion() id, err := newTokenKeyId() if err != nil { - return nil, nil, fmt.Errorf("create token key: %w", err) + return nil, nil, errors.Wrap(err, op) } tk.PrivateId = id tk.RootKeyId = rv.RootKeyId id, err = newTokenKeyVersionId() if err != nil { - return nil, nil, fmt.Errorf("create token key: %w", err) + return nil, nil, errors.Wrap(err, op) } tv.PrivateId = id tv.TokenKeyId = tk.PrivateId tv.RootKeyVersionId = rootKeyVersionId tv.Key = key if err := tv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, nil, fmt.Errorf("create token key: %w", err) + return nil, nil, errors.Wrap(err, op) } // no token entries for keys if err := w.Create(ctx, &tk); err != nil { - return nil, nil, fmt.Errorf("create token key: key create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("keys create")) } // no token entries for key versions if err := w.Create(ctx, &tv); err != nil { - return nil, nil, fmt.Errorf("create token key: version create: %w", err) + return nil, nil, errors.Wrap(err, op, errors.WithMsg("key versions create")) } - return &tk, &tv, err + return &tk, &tv, nil } // LookupTokenKey will look up a key in the repository. If the key is not // found, it will return nil, nil. -func (r *Repository) LookupTokenKey(ctx context.Context, privateId string, opt ...Option) (*TokenKey, error) { +func (r *Repository) LookupTokenKey(ctx context.Context, privateId string, _ ...Option) (*TokenKey, error) { + const op = "kms.(Repository).LookupTokenKey" if privateId == "" { - return nil, fmt.Errorf("lookup token key: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocTokenKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup token key: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return &k, nil } @@ -106,14 +109,15 @@ func (r *Repository) LookupTokenKey(ctx context.Context, privateId string, opt . // DeleteTokenKey deletes the key for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteTokenKey(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteTokenKey(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteTokenKey" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete token key: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocTokenKey() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete token key: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -125,24 +129,28 @@ func (r *Repository) DeleteTokenKey(ctx context.Context, privateId string, opt . dk := k.Clone() // no token entries for root keys rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete token key: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // ListTokenKeys will list the keys. Supports the WithLimit option. func (r *Repository) ListTokenKeys(ctx context.Context, opt ...Option) ([]Dek, error) { + const op = "kms.(Repository).ListTokenKeys" var keys []*TokenKey err := r.list(ctx, &keys, "1=1", nil, opt...) if err != nil { - return nil, fmt.Errorf("list token keys: %w", err) + return nil, errors.Wrap(err, op) } deks := make([]Dek, 0, len(keys)) for _, key := range keys { diff --git a/internal/kms/repository_token_key_test.go b/internal/kms/repository_token_key_test.go index d2825587c..85841921e 100644 --- a/internal/kms/repository_token_key_test.go +++ b/internal/kms/repository_token_key_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid-org", @@ -57,7 +57,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { keyWrapper: rkvWrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "empty-key", @@ -67,7 +67,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { key: []byte(""), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -77,7 +77,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "not-rkv-wrapper", @@ -87,7 +87,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { keyWrapper: wrapper, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "wrapper-missing-id", @@ -104,7 +104,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { }(), }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -114,9 +114,7 @@ func TestRepository_CreateTokenKey(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(tk) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -209,9 +207,7 @@ func TestRepository_DeleteTokenKey(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) // make sure there was no token written err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) diff --git a/internal/kms/repository_token_key_version.go b/internal/kms/repository_token_key_version.go index 8038ba576..c352d6ba1 100644 --- a/internal/kms/repository_token_key_version.go +++ b/internal/kms/repository_token_key_version.go @@ -12,34 +12,35 @@ import ( // CreateTokenKeyVersion inserts into the repository and returns the new key // version with its PrivateId. There are no valid options at this time. -func (r *Repository) CreateTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, key []byte, opt ...Option) (*TokenKeyVersion, error) { +func (r *Repository) CreateTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, key []byte, _ ...Option) (*TokenKeyVersion, error) { + const op = "kms.(Repository).CreateTokenKeyVersion" if rkvWrapper == nil { - return nil, fmt.Errorf("create token key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } rootKeyVersionId := rkvWrapper.KeyID() switch { case !strings.HasPrefix(rootKeyVersionId, RootKeyVersionPrefix): - return nil, fmt.Errorf("create token key version: root key version id %s doesn't start with prefix %s: %w", rootKeyVersionId, RootKeyVersionPrefix, errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, fmt.Sprintf("root key version id %s doesn't start with prefix %s", rootKeyVersionId, RootKeyVersionPrefix)) case rootKeyVersionId == "": - return nil, fmt.Errorf("create token key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } if tokenKeyId == "" { - return nil, fmt.Errorf("create token key version: missing token key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing token key id") } if len(key) == 0 { - return nil, fmt.Errorf("create token key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } kv := AllocTokenKeyVersion() id, err := newTokenKeyVersionId() if err != nil { - return nil, fmt.Errorf("create token key version: %w", err) + return nil, errors.Wrap(err, op) } kv.PrivateId = id kv.RootKeyVersionId = rootKeyVersionId kv.Key = key kv.TokenKeyId = tokenKeyId if err := kv.Encrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("create token key version: encrypt: %w", err) + return nil, errors.Wrap(err, op) } var returnedKey interface{} @@ -51,33 +52,34 @@ func (r *Repository) CreateTokenKeyVersion(ctx context.Context, rkvWrapper wrapp returnedKey = kv.Clone() // no token entries for root key version if err := w.Create(ctx, returnedKey); err != nil { - return err + return errors.Wrap(err, op) } return nil }, ) if err != nil { - return nil, fmt.Errorf("create token key version: %w for %s token key id", err, kv.TokenKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s token key id", kv.TokenKeyId))) } - return returnedKey.(*TokenKeyVersion), err + return returnedKey.(*TokenKeyVersion), nil } // LookupTokenKeyVersion will look up a key version in the repository. If // the key version is not found, it will return nil, nil. -func (r *Repository) LookupTokenKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, opt ...Option) (*TokenKeyVersion, error) { +func (r *Repository) LookupTokenKeyVersion(ctx context.Context, keyWrapper wrapping.Wrapper, privateId string, _ ...Option) (*TokenKeyVersion, error) { + const op = "kms.(Repository).LookupTokenKeyVersion" if privateId == "" { - return nil, fmt.Errorf("lookup token key version: missing private id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing private id") } if keyWrapper == nil { - return nil, fmt.Errorf("lookup token key version: missing key wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key wrapper") } k := AllocTokenKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return nil, fmt.Errorf("lookup token key version: failed %w for %s", err, privateId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } if err := k.Decrypt(ctx, keyWrapper); err != nil { - return nil, fmt.Errorf("lookup token key version: decrypt: %w", err) + return nil, errors.Wrap(err, op) } return &k, nil } @@ -85,14 +87,15 @@ func (r *Repository) LookupTokenKeyVersion(ctx context.Context, keyWrapper wrapp // DeleteTokenKeyVersion deletes the key version for the provided id from the // repository returning a count of the number of records deleted. All options // are ignored. -func (r *Repository) DeleteTokenKeyVersion(ctx context.Context, privateId string, opt ...Option) (int, error) { +func (r *Repository) DeleteTokenKeyVersion(ctx context.Context, privateId string, _ ...Option) (int, error) { + const op = "kms.(Repository).DeleteTokenKeyVersion" if privateId == "" { - return db.NoRowsAffected, fmt.Errorf("delete token key version: missing private id: %w", errors.ErrInvalidParameter) + return db.NoRowsAffected, errors.New(errors.InvalidParameter, op, "missing private id") } k := AllocTokenKeyVersion() k.PrivateId = privateId if err := r.reader.LookupById(ctx, &k); err != nil { - return db.NoRowsAffected, fmt.Errorf("delete token key version: failed %w for %s", err, privateId) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } var rowsDeleted int @@ -104,57 +107,62 @@ func (r *Repository) DeleteTokenKeyVersion(ctx context.Context, privateId string dk := k.Clone() // no token entries for the key version rowsDeleted, err = w.Delete(ctx, dk) - if err == nil && rowsDeleted > 1 { - return errors.ErrMultipleRecords + if err != nil { + return errors.Wrap(err, op) } - return err + if rowsDeleted > 1 { + return errors.New(errors.MultipleRecords, op, "more than 1 resource would have been deleted") + } + return nil }, ) if err != nil { - return db.NoRowsAffected, fmt.Errorf("delete token key version: %s: %w", privateId, err) + return db.NoRowsAffected, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", privateId))) } return rowsDeleted, nil } // LatestTokenKeyVersion searches for the key version with the highest -// version number. When no results are found, it returns nil, -// errors.ErrRecordNotFound. -func (r *Repository) LatestTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, opt ...Option) (*TokenKeyVersion, error) { +// version number. When no results are found, it returns nil with an +// errors.RecordNotFound error. +func (r *Repository) LatestTokenKeyVersion(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, _ ...Option) (*TokenKeyVersion, error) { + const op = "kms.(Repository).LatestTokenKeyVersion" if tokenKeyId == "" { - return nil, fmt.Errorf("latest token key version: missing token key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing token key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("latest token key version: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var foundKeys []*TokenKeyVersion if err := r.reader.SearchWhere(ctx, &foundKeys, "token_key_id = ?", []interface{}{tokenKeyId}, db.WithLimit(1), db.WithOrder("version desc")); err != nil { - return nil, fmt.Errorf("latest token key version: failed %w for %s", err, tokenKeyId) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("failed for %s", tokenKeyId))) } if len(foundKeys) == 0 { - return nil, errors.ErrRecordNotFound + return nil, errors.E(errors.WithCode(errors.RecordNotFound), errors.WithOp(op)) } if err := foundKeys[0].Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("latest token key version: %w", err) + return nil, errors.Wrap(err, op) } return foundKeys[0], nil } // ListTokenKeyVersions will lists versions of a key. Supports the WithLimit option. func (r *Repository) ListTokenKeyVersions(ctx context.Context, rkvWrapper wrapping.Wrapper, tokenKeyId string, opt ...Option) ([]DekVersion, error) { + const op = "kms.(Repository).ListTokenKeyVersions" if tokenKeyId == "" { - return nil, fmt.Errorf("list token key versions: missing token key id %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing token key id") } if rkvWrapper == nil { - return nil, fmt.Errorf("list token key versions: missing root key version wrapper: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version wrapper") } var versions []*TokenKeyVersion err := r.list(ctx, &versions, "token_key_id = ?", []interface{}{tokenKeyId}, opt...) if err != nil { - return nil, fmt.Errorf("list token key versions: %w", err) + return nil, errors.Wrap(err, op) } for i, k := range versions { if err := k.Decrypt(ctx, rkvWrapper); err != nil { - return nil, fmt.Errorf("list token key versions: error decrypting key num %d: %w", i, err) + return nil, errors.Wrap(err, op, errors.WithMsg(fmt.Sprintf("error decrypting key num %d", i))) } } dekVersions := make([]DekVersion, 0, len(versions)) diff --git a/internal/kms/repository_token_key_version_test.go b/internal/kms/repository_token_key_version_test.go index da86b2025..d2ae50bfb 100644 --- a/internal/kms/repository_token_key_version_test.go +++ b/internal/kms/repository_token_key_version_test.go @@ -39,7 +39,7 @@ func TestRepository_CreateTokenKeyVersion(t *testing.T) { name string args args wantErr bool - wantIsError error + wantIsError errors.Code }{ { name: "valid", @@ -67,7 +67,7 @@ func TestRepository_CreateTokenKeyVersion(t *testing.T) { tokenKeyId: dk.PrivateId, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, { name: "nil-wrapper", @@ -76,7 +76,7 @@ func TestRepository_CreateTokenKeyVersion(t *testing.T) { keyWrapper: nil, }, wantErr: true, - wantIsError: errors.ErrInvalidParameter, + wantIsError: errors.InvalidParameter, }, } for _, tt := range tests { @@ -86,9 +86,7 @@ func TestRepository_CreateTokenKeyVersion(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(k) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) @@ -173,9 +171,7 @@ func TestRepository_DeleteTokenKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Equal(0, deletedRows) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) err = db.TestVerifyOplog(t, rw, tt.args.key.PrivateId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)) assert.Error(err) assert.True(errors.IsNotFoundError(err)) @@ -260,9 +256,7 @@ func TestRepository_LatestTokenKeyVersion(t *testing.T) { if tt.wantErr { require.Error(err) assert.Nil(got) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) return } require.NoError(err) diff --git a/internal/kms/root_key.go b/internal/kms/root_key.go index b923f83ea..0e0fab25d 100644 --- a/internal/kms/root_key.go +++ b/internal/kms/root_key.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,9 +22,10 @@ type RootKey struct { // for a global or org scope, but the scope type validation will be deferred // until the in memory root key is written to the database. No options // are currently supported. -func NewRootKey(scopeId string, opt ...Option) (*RootKey, error) { +func NewRootKey(scopeId string, _ ...Option) (*RootKey, error) { + const op = "kms.NewRootKey" if scopeId == "" { - return nil, fmt.Errorf("new root key: missing scope id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing scope id") } c := &RootKey{ RootKey: &store.RootKey{ @@ -52,17 +52,18 @@ func (k *RootKey) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // before it's written. -func (k *RootKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *RootKey) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(RootKey).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("root key vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } switch opType { case db.CreateOp: if k.ScopeId == "" { - return fmt.Errorf("root key vet for write: missing scope id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing scope id") } case db.UpdateOp: - return fmt.Errorf("root key vet for write: key is immutable: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "key is immutable") } return nil } diff --git a/internal/kms/root_key_test.go b/internal/kms/root_key_test.go index 968056623..e5f038357 100644 --- a/internal/kms/root_key_test.go +++ b/internal/kms/root_key_test.go @@ -30,7 +30,7 @@ func TestRootKey_Create(t *testing.T) { args args want *kms.RootKey wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -38,7 +38,7 @@ func TestRootKey_Create(t *testing.T) { name: "empty-scopeId", args: args{}, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid-org-config", @@ -72,7 +72,7 @@ func TestRootKey_Create(t *testing.T) { got, err := kms.NewRootKey(tt.args.scopeId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/root_key_version.go b/internal/kms/root_key_version.go index a506b9e95..e070dde1b 100644 --- a/internal/kms/root_key_version.go +++ b/internal/kms/root_key_version.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,12 +22,13 @@ type RootKeyVersion struct { // NewRootKeyVersion creates a new in memory root key version. No options are // currently supported. -func NewRootKeyVersion(rootKeyId string, key []byte, opt ...Option) (*RootKeyVersion, error) { +func NewRootKeyVersion(rootKeyId string, key []byte, _ ...Option) (*RootKeyVersion, error) { + const op = "kms.NewRootKeyVersion" if rootKeyId == "" { - return nil, fmt.Errorf("new root key version: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } if len(key) == 0 { - return nil, fmt.Errorf("new root key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } k := &RootKeyVersion{ @@ -57,20 +57,21 @@ func (k *RootKeyVersion) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the root key // version before it's written. -func (k *RootKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *RootKeyVersion) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(RootKeyVersion).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("root key version vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } switch opType { case db.CreateOp: if k.CtKey == nil { - return fmt.Errorf("root key version vet for write: missing key: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing key") } if k.RootKeyId == "" { - return fmt.Errorf("root key version vet for write: missing root key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key id") } case db.UpdateOp: - return fmt.Errorf("root key version vet for write: key is immutable: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "key is immutable") } return nil } @@ -92,20 +93,22 @@ func (k *RootKeyVersion) SetTableName(n string) { // Encrypt will encrypt the root key version's key func (k *RootKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(RootKeyVersion).Encrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.RootKey directly if err := structwrapping.WrapStruct(ctx, cipher, k.RootKeyVersion, nil); err != nil { - return fmt.Errorf("error encrypting kms root key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Encrypt)) } return nil } // Decrypt will decrypt the root key version's key func (k *RootKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(RootKeyVersion).Decrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.RootKeyVersion directly if err := structwrapping.UnwrapStruct(ctx, cipher, k.RootKeyVersion, nil); err != nil { - return fmt.Errorf("error decrypting kms root key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Decrypt)) } return nil } diff --git a/internal/kms/root_key_version_test.go b/internal/kms/root_key_version_test.go index c68e8c011..f77988657 100644 --- a/internal/kms/root_key_version_test.go +++ b/internal/kms/root_key_version_test.go @@ -34,7 +34,7 @@ func TestRootKeyVersion_Create(t *testing.T) { args args want *kms.RootKeyVersion wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -44,7 +44,7 @@ func TestRootKeyVersion_Create(t *testing.T) { key: []byte("test key"), }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-key", @@ -52,7 +52,7 @@ func TestRootKeyVersion_Create(t *testing.T) { rootId: rootKey.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -76,7 +76,7 @@ func TestRootKeyVersion_Create(t *testing.T) { got, err := kms.NewRootKeyVersion(tt.args.rootId, tt.args.key, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/session_key.go b/internal/kms/session_key.go index 5cdcf5a08..b8c8ab033 100644 --- a/internal/kms/session_key.go +++ b/internal/kms/session_key.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -21,9 +20,10 @@ type SessionKey struct { // NewSessionKey creates a new in memory key. No options // are currently supported. -func NewSessionKey(rootKeyId string, opt ...Option) (*SessionKey, error) { +func NewSessionKey(rootKeyId string, _ ...Option) (*SessionKey, error) { + const op = "kms.NewSessionKey" if rootKeyId == "" { - return nil, fmt.Errorf("new root key: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } c := &SessionKey{ SessionKey: &store.SessionKey{ @@ -50,13 +50,14 @@ func (k *SessionKey) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // before it's written. -func (k *SessionKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *SessionKey) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(SessionKey).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("session key vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.RootKeyId == "" { - return fmt.Errorf("session key vet for write: missing root key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key id") } } return nil diff --git a/internal/kms/session_key_test.go b/internal/kms/session_key_test.go index 06348b0d6..7fc0d9127 100644 --- a/internal/kms/session_key_test.go +++ b/internal/kms/session_key_test.go @@ -33,7 +33,7 @@ func TestSessionKey_Create(t *testing.T) { args args want *kms.SessionKey wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -41,7 +41,7 @@ func TestSessionKey_Create(t *testing.T) { name: "empty-rootKeyId", args: args{}, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -63,7 +63,7 @@ func TestSessionKey_Create(t *testing.T) { got, err := kms.NewSessionKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/session_key_version.go b/internal/kms/session_key_version.go index b524dfc71..b5ef871f3 100644 --- a/internal/kms/session_key_version.go +++ b/internal/kms/session_key_version.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,15 +22,16 @@ type SessionKeyVersion struct { // SessionKeyVersion creates a new in memory key version. No options are // currently supported. -func NewSessionKeyVersion(sessionKeyId string, key []byte, rootKeyVersionId string, opt ...Option) (*SessionKeyVersion, error) { +func NewSessionKeyVersion(sessionKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*SessionKeyVersion, error) { + const op = "kms.NewSessionKeyVersion" if sessionKeyId == "" { - return nil, fmt.Errorf("new session key version: missing session key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing session key id") } if len(key) == 0 { - return nil, fmt.Errorf("new session key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } if rootKeyVersionId == "" { - return nil, fmt.Errorf("new session key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } k := &SessionKeyVersion{ @@ -62,18 +62,19 @@ func (k *SessionKeyVersion) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // version before it's written. func (k *SessionKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { + const op = "kms.(SessionKeyVersion).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("session key version vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.CtKey == nil { - return fmt.Errorf("session key version vet for write: missing key: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing key") } if k.SessionKeyId == "" { - return fmt.Errorf("session key version vet for write: missing session key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing session key id") } if k.RootKeyVersionId == "" { - return fmt.Errorf("session key version vet for write: missing root key version id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key version id") } } return nil @@ -96,20 +97,22 @@ func (k *SessionKeyVersion) SetTableName(n string) { // Encrypt will encrypt the key version's key func (k *SessionKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(SessionKeyVersion).Encrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.SessionKeyVersion directly if err := structwrapping.WrapStruct(ctx, cipher, k.SessionKeyVersion, nil); err != nil { - return fmt.Errorf("error encrypting kms session key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Encrypt)) } return nil } // Decrypt will decrypt the key version's key func (k *SessionKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(SessionKeyVersion).Decrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.SessionKeyVersion directly if err := structwrapping.UnwrapStruct(ctx, cipher, k.SessionKeyVersion, nil); err != nil { - return fmt.Errorf("error decrypting kms session key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Decrypt)) } return nil } diff --git a/internal/kms/session_key_version_test.go b/internal/kms/session_key_version_test.go index d8e083e16..6567c66af 100644 --- a/internal/kms/session_key_version_test.go +++ b/internal/kms/session_key_version_test.go @@ -38,7 +38,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { args args want *kms.SessionKeyVersion wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -49,7 +49,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-key", @@ -58,7 +58,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-root-key-version-id", @@ -67,7 +67,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { key: []byte("test key"), }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -93,7 +93,7 @@ func TestSessionKeyVersion_Create(t *testing.T) { got, err := kms.NewSessionKeyVersion(tt.args.sessionKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/token_key.go b/internal/kms/token_key.go index de22c2c6d..64c1d77b6 100644 --- a/internal/kms/token_key.go +++ b/internal/kms/token_key.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -21,9 +20,10 @@ type TokenKey struct { // NewTokenKey creates a new in memory key. No options // are currently supported. -func NewTokenKey(rootKeyId string, opt ...Option) (*TokenKey, error) { +func NewTokenKey(rootKeyId string, _ ...Option) (*TokenKey, error) { + const op = "kms.NewTokenKey" if rootKeyId == "" { - return nil, fmt.Errorf("new root key: missing root key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key id") } c := &TokenKey{ TokenKey: &store.TokenKey{ @@ -50,13 +50,14 @@ func (k *TokenKey) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // before it's written. -func (k *TokenKey) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *TokenKey) VetForWrite(_ context.Context, _ db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(TokenKey).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("token key vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.RootKeyId == "" { - return fmt.Errorf("token key vet for write: missing root key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key id") } } return nil diff --git a/internal/kms/token_key_test.go b/internal/kms/token_key_test.go index cc1f654f9..0aefbe1c4 100644 --- a/internal/kms/token_key_test.go +++ b/internal/kms/token_key_test.go @@ -33,7 +33,7 @@ func TestTokenKey_Create(t *testing.T) { args args want *kms.TokenKey wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -41,7 +41,7 @@ func TestTokenKey_Create(t *testing.T) { name: "empty-rootKeyId", args: args{}, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -63,7 +63,7 @@ func TestTokenKey_Create(t *testing.T) { got, err := kms.NewTokenKey(tt.args.rootKeyId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/kms/token_key_version.go b/internal/kms/token_key_version.go index 6ab6ea313..17da69876 100644 --- a/internal/kms/token_key_version.go +++ b/internal/kms/token_key_version.go @@ -2,7 +2,6 @@ package kms import ( "context" - "fmt" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -23,15 +22,16 @@ type TokenKeyVersion struct { // TokenKeyVersion creates a new in memory key version. No options are // currently supported. -func NewTokenKeyVersion(tokenKeyId string, key []byte, rootKeyVersionId string, opt ...Option) (*TokenKeyVersion, error) { +func NewTokenKeyVersion(tokenKeyId string, key []byte, rootKeyVersionId string, _ ...Option) (*TokenKeyVersion, error) { + const op = "kms.NewTokenKeyVersion" if tokenKeyId == "" { - return nil, fmt.Errorf("new token key version: missing token key id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing token key id") } if len(key) == 0 { - return nil, fmt.Errorf("new token key version: missing key: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing key") } if rootKeyVersionId == "" { - return nil, fmt.Errorf("new token key version: missing root key version id: %w", errors.ErrInvalidParameter) + return nil, errors.New(errors.InvalidParameter, op, "missing root key version id") } k := &TokenKeyVersion{ @@ -61,19 +61,20 @@ func (k *TokenKeyVersion) Clone() interface{} { // VetForWrite implements db.VetForWrite() interface and validates the key // version before it's written. -func (k *TokenKeyVersion) VetForWrite(ctx context.Context, r db.Reader, opType db.OpType, opt ...db.Option) error { +func (k *TokenKeyVersion) VetForWrite(_ context.Context, _r db.Reader, opType db.OpType, _ ...db.Option) error { + const op = "kms.(TokenKeyVersion).VetForWrite" if k.PrivateId == "" { - return fmt.Errorf("token key version vet for write: missing private id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing private id") } if opType == db.CreateOp { if k.CtKey == nil { - return fmt.Errorf("token key version vet for write: missing key: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing key") } if k.TokenKeyId == "" { - return fmt.Errorf("token key version vet for write: missing token key id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing token key id") } if k.RootKeyVersionId == "" { - return fmt.Errorf("token key version vet for write: missing root key version id: %w", errors.ErrInvalidParameter) + return errors.New(errors.InvalidParameter, op, "missing root key version id") } } return nil @@ -96,20 +97,22 @@ func (k *TokenKeyVersion) SetTableName(n string) { // Encrypt will encrypt the key version's key func (k *TokenKeyVersion) Encrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(TokenKeyVersion).Encrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.TokenKeyVersion directly if err := structwrapping.WrapStruct(ctx, cipher, k.TokenKeyVersion, nil); err != nil { - return fmt.Errorf("error encrypting kms token key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Encrypt)) } return nil } // Decrypt will decrypt the key version's key func (k *TokenKeyVersion) Decrypt(ctx context.Context, cipher wrapping.Wrapper) error { + const op = "kms.(TokenKeyVersion).Decrypt" // structwrapping doesn't support embedding, so we'll pass in the // store.TokenKeyVersion directly if err := structwrapping.UnwrapStruct(ctx, cipher, k.TokenKeyVersion, nil); err != nil { - return fmt.Errorf("error decrypting kms token key version: %w", err) + return errors.Wrap(err, op, errors.WithCode(errors.Decrypt)) } return nil } diff --git a/internal/kms/token_key_version_test.go b/internal/kms/token_key_version_test.go index cbb6b704c..dfa2c942b 100644 --- a/internal/kms/token_key_version_test.go +++ b/internal/kms/token_key_version_test.go @@ -38,7 +38,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { args args want *kms.TokenKeyVersion wantErr bool - wantIsErr error + wantIsErr errors.Code create bool wantCreateErr bool }{ @@ -49,7 +49,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-key", @@ -58,7 +58,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { rootKeyVersionId: rkv.PrivateId, }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "empty-root-key-version-id", @@ -67,7 +67,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { key: []byte("test key"), }, wantErr: true, - wantIsErr: errors.ErrInvalidParameter, + wantIsErr: errors.InvalidParameter, }, { name: "valid", @@ -93,7 +93,7 @@ func TestTokenKeyVersion_Create(t *testing.T) { got, err := kms.NewTokenKeyVersion(tt.args.tokenKeyId, tt.args.key, tt.args.rootKeyVersionId, tt.args.opt...) if tt.wantErr { require.Error(err) - assert.True(errors.Is(err, tt.wantIsErr)) + assert.True(errors.Match(errors.T(tt.wantIsErr), err)) return } require.NoError(err) diff --git a/internal/session/repository_test.go b/internal/session/repository_test.go index bed07756d..5326a1b3a 100644 --- a/internal/session/repository_test.go +++ b/internal/session/repository_test.go @@ -45,7 +45,7 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "error creating db repository with nil writer", + wantErrString: "kms.NewRepository: nil writer: parameter violation: error #100", }, { name: "nil-reader", @@ -55,7 +55,7 @@ func TestNewRepository(t *testing.T) { }, want: nil, wantErr: true, - wantErrString: "error creating db repository with nil reader", + wantErrString: "kms.NewRepository: nil reader: parameter violation: error #100", }, } for _, tt := range tests { diff --git a/internal/target/repository_tcp_target_test.go b/internal/target/repository_tcp_target_test.go index 8a2d94fac..20ae339b8 100644 --- a/internal/target/repository_tcp_target_test.go +++ b/internal/target/repository_tcp_target_test.go @@ -116,9 +116,7 @@ func TestRepository_CreateTcpTarget(t *testing.T) { if tt.wantErr { assert.Error(err) assert.Nil(target) - if tt.wantIsError != nil { - assert.True(errors.Is(err, tt.wantIsError)) - } + assert.True(errors.Is(err, tt.wantIsError)) return } require.NoError(err) @@ -381,9 +379,7 @@ func TestRepository_UpdateTcpTarget(t *testing.T) { targetAfterUpdate, hostSets, updatedRows, err := repo.UpdateTcpTarget(context.Background(), &updateTarget, target.Version, tt.args.fieldMaskPaths, tt.args.opt...) if tt.wantErr { assert.Error(err) - if tt.wantIsError != 0 { - assert.True(errors.Match(errors.T(tt.wantIsError), err)) - } + assert.True(errors.Match(errors.T(tt.wantIsError), err)) assert.Nil(targetAfterUpdate) assert.Equal(0, updatedRows) assert.Contains(err.Error(), tt.wantErrMsg)