package kms_test import ( "context" "testing" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/db/timestamp" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" ) // TODO (jimlambrt 8/2020) define tests for immutable fields in the remaining // kms tables: // kms_oplog_key // kms_oplog_key_version // kms_session_key // kms_session_key_version func TestRootKeyVersion_ImmutableFields(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) rw := db.New(conn) ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKeyVersion()).Error) rk := kms.TestRootKey(t, conn, org.PublicId) new, _ := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) var tests = []struct { name string update *kms.RootKeyVersion fieldMask []string }{ { name: "private_id", update: func() *kms.RootKeyVersion { k := new.Clone().(*kms.RootKeyVersion) k.PrivateId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"PrivateId"}, }, { name: "create time", update: func() *kms.RootKeyVersion { k := new.Clone().(*kms.RootKeyVersion) k.CreateTime = &ts return k }(), fieldMask: []string{"CreateTime"}, }, { name: "root_key_id", update: func() *kms.RootKeyVersion { k := new.Clone().(*kms.RootKeyVersion) k.RootKeyId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"RootKeyId"}, }, { name: "version", update: func() *kms.RootKeyVersion { k := new.Clone().(*kms.RootKeyVersion) k.Version = uint32(22) return k }(), fieldMask: []string{"Version"}, }, { name: "key", update: func() *kms.RootKeyVersion { k := new.Clone().(*kms.RootKeyVersion) k.Key = []byte("updated key") return k }(), fieldMask: []string{"CtKey"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() err := rw.LookupById(context.Background(), orig) require.NoError(err) err = tt.update.Encrypt(context.Background(), wrapper) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) require.Error(err) assert.Equal(0, rowsUpdated) after := new.Clone() err = rw.LookupById(context.Background(), after) require.NoError(err) assert.True(proto.Equal(orig.(*kms.RootKeyVersion), after.(*kms.RootKeyVersion))) }) } } func TestRootKey_ImmutableFields(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) new := kms.TestRootKey(t, conn, org.PublicId) var tests = []struct { name string update *kms.RootKey fieldMask []string }{ { name: "private_id", update: func() *kms.RootKey { k := new.Clone().(*kms.RootKey) k.PrivateId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"PrivateId"}, }, { name: "create time", update: func() *kms.RootKey { k := new.Clone().(*kms.RootKey) k.CreateTime = &ts return k }(), fieldMask: []string{"CreateTime"}, }, { name: "scope_id", update: func() *kms.RootKey { k := new.Clone().(*kms.RootKey) k.ScopeId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"ScopeId"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() err := rw.LookupById(context.Background(), orig) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) require.Error(err) assert.Equal(0, rowsUpdated) after := new.Clone() err = rw.LookupById(context.Background(), after) require.NoError(err) assert.True(proto.Equal(orig.(*kms.RootKey), after.(*kms.RootKey))) }) } } func TestDatabaseKey_ImmutableFields(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} wrapper := db.TestWrapper(t) org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) require.NoError(t, conn.Where("1=1").Delete(kms.AllocDatabaseKey()).Error) rk := kms.TestRootKey(t, conn, org.PublicId) new := kms.TestDatabaseKey(t, conn, rk.PrivateId) var tests = []struct { name string update *kms.DatabaseKey fieldMask []string }{ { name: "private_id", update: func() *kms.DatabaseKey { k := new.Clone().(*kms.DatabaseKey) k.PrivateId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"PrivateId"}, }, { name: "create time", update: func() *kms.DatabaseKey { k := new.Clone().(*kms.DatabaseKey) k.CreateTime = &ts return k }(), fieldMask: []string{"CreateTime"}, }, { name: "root_key_id", update: func() *kms.DatabaseKey { k := new.Clone().(*kms.DatabaseKey) k.RootKeyId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"ScopeId"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() err := rw.LookupById(context.Background(), orig) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) require.Error(err) assert.Equal(0, rowsUpdated) after := new.Clone() err = rw.LookupById(context.Background(), after) require.NoError(err) assert.True(proto.Equal(orig.(*kms.DatabaseKey), after.(*kms.DatabaseKey))) }) } } func TestDatabaseKeyVersion_ImmutableFields(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) rw := db.New(conn) ts := timestamp.Timestamp{Timestamp: ×tamppb.Timestamp{Seconds: 0, Nanos: 0}} org, _ := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) require.NoError(t, conn.Where("1=1").Delete(kms.AllocRootKey()).Error) rk := kms.TestRootKey(t, conn, org.PublicId) _, rkvWrapper := kms.TestRootKeyVersion(t, conn, wrapper, rk.PrivateId) dk := kms.TestDatabaseKey(t, conn, rk.PrivateId) new := kms.TestDatabaseKeyVersion(t, conn, rkvWrapper, dk.PrivateId, []byte("database key")) var tests = []struct { name string update *kms.DatabaseKeyVersion fieldMask []string }{ { name: "private_id", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.PrivateId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"PrivateId"}, }, { name: "create time", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.CreateTime = &ts return k }(), fieldMask: []string{"CreateTime"}, }, { name: "database_key_id", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.DatabaseKeyId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"RootKeyId"}, }, { name: "root_key_version_id", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.RootKeyVersionId = "o_thisIsNotAValidId" return k }(), fieldMask: []string{"RootKeyId"}, }, { name: "version", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.Version = uint32(22) return k }(), fieldMask: []string{"Version"}, }, { name: "key", update: func() *kms.DatabaseKeyVersion { k := new.Clone().(*kms.DatabaseKeyVersion) k.Key = []byte("updated key") return k }(), fieldMask: []string{"CtKey"}, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) orig := new.Clone() err := rw.LookupById(context.Background(), orig) require.NoError(err) err = tt.update.Encrypt(context.Background(), wrapper) require.NoError(err) rowsUpdated, err := rw.Update(context.Background(), tt.update, tt.fieldMask, nil, db.WithSkipVetForWrite(true)) require.Error(err) assert.Equal(0, rowsUpdated) after := new.Clone() err = rw.LookupById(context.Background(), after) require.NoError(err) assert.True(proto.Equal(orig.(*kms.DatabaseKeyVersion), after.(*kms.DatabaseKeyVersion))) }) } }