refactor (kms): adopt the go-kms-wrapping/extras/kms package (#2027)

* feature (db): add Db.UnderlyingDB()

This is needed to allow for integration with bits that need a *dbw.DB

* feature (kms): add new go-kms-wrapping/extras/kms dependency

* refactor (kms): schema changes required to adopt extras/kms pkg

* refactor (kms/iam): rename to DeprecateCreateKeysTx(...)

* refactor (kms): remove deprecated test

* refactor (kms): refactor Kms type

This refactor includes renaming the existing type to DeprecatedKms
and then refactoring the Kms type to become a wrapper of
go-kms-wrapping/extras/kms

* refactor (kms): delete all the unneeded bits

All this stuff is not needed now that we're using
go-kms-wrapping/extras/kms

* refactor (db): fixup tests after kms refactor

* refactor (kms/tests): use testing.TB for test helpers

Our test helper packages were not possible to use
with benchmarks. This refactor switches to testing.TB
to allow both tests and benchmarks to use the helpers.

* tests (session benchmarks): refactor to use new Kms type

* refactor (schema): rm test which relies on deprecated Kms code

* refactor (kms): post rebase on main changes required

* chore (kms refactor): re-add unit test from main

* refactor (kms): uses migrations that don't include KMS schema changes
This commit is contained in:
Jim authored and GitHub committed 2022-05-13 13:53:22 -04:00
1 parent 8cef1017e9
commit 785241237e
97 files changed
+2580 -15154

No files matched your search

+5
View File
@@ -208,6 +208,11 @@ func New(underlying *DB) *Db {
return &Db{underlying: underlying}
}
// UnderlyingDB returns the underlying *dbw.DB
func (rw *Db) UnderlyingDB() *dbw.DB {
return rw.underlying.wrapped
}
// Exec will execute the sql with the values as parameters. The int returned
// is the number of rows affected by the sql. WithDebug is supported.
func (rw *Db) Exec(ctx context.Context, sql string, values []interface{}, opt ...Option) (int, error) {
@@ -0,0 +1,103 @@
begin;
-- make the required schema changes to adopt
-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2
-- this migration is from:
-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/01_domain_types.up.sql
create domain kms_private_id as text
not null
check(
length(trim(value)) > 0
);
comment on domain kms_private_id is
'standard column for private id';
create domain kms_scope_id as text
check(
length(trim(value)) > 0
);
comment on domain kms_scope_id is
'standard column for scope id';
create domain kms_timestamp as
timestamp with time zone
default current_timestamp;
comment on domain kms_timestamp is
'Standard timestamp for all create_time and update_time columns';
create domain kms_version as bigint
default 1
not null
check(
value > 0
);
comment on domain kms_version is
'standard column for row version';
-- kms_immutable_columns() will make the column names immutable which are passed as
-- parameters when the trigger is created. It raises error code 23601 which is a
-- class 23 integrity constraint violation: immutable column
create function kms_immutable_columns()
returns trigger
as $$
declare
col_name text;
new_value text;
old_value text;
begin
foreach col_name in array tg_argv loop
execute format('SELECT $1.%I', col_name) into new_value using new;
execute format('SELECT $1.%I', col_name) into old_value using old;
if new_value is distinct from old_value then
raise exception 'immutable column: %.%', tg_table_name, col_name using
errcode = '23601',
schema = tg_table_schema,
table = tg_table_name,
column = col_name;
end if;
end loop;
return new;
end;
$$ language plpgsql;
comment on function
kms_immutable_columns()
is
'function used in before update triggers to make columns immutable';
create function kms_default_create_time()
returns trigger
as $$
begin
if new.create_time is distinct from now() then
new.create_time = now();
end if;
return new;
end;
$$ language plpgsql;
comment on function
kms_default_create_time()
is
'function used to properly set create_time columns';
create function
kms_update_time_column()
returns trigger
as $$
begin
if row(new.*) is distinct from row(old.*) then
new.update_time = now();
return new;
else
return old;
end if;
end;
$$ language plpgsql;
comment on function
kms_update_time_column()
is
'function used in before update triggers to properly set update_time columns';
commit;
@@ -0,0 +1,40 @@
begin;
-- make the required schema changes to adopt
-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2
-- this migration is from:
-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/02_version.up.sql
create table kms_schema_version(
version text not null,
create_time kms_timestamp,
update_time kms_timestamp
);
comment on table kms_schema_version is
'kms_schema_version contains the kms schema version';
-- this index ensures that there will only ever be one row in the
-- table. see:
-- https://www.postgresql.org/docs/current/indexes-expressional.html
create unique index kms_schema_version_one_row
ON kms_schema_version((version is not null));
-- define the immutable fields for kms_root_key (all of them)
create trigger kms_immutable_columns
before
update on kms_schema_version
for each row execute procedure kms_immutable_columns('create_time');
create trigger kms_default_create_time_column
before
insert on kms_schema_version
for each row execute procedure kms_default_create_time();
create trigger kms_update_time_column
before
update on kms_schema_version
for each row execute procedure kms_update_time_column();
insert into kms_schema_version(version) values('v0.0.1');
commit;
@@ -0,0 +1,37 @@
begin;
-- make the required schema changes to adopt
-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2
-- this migration is from:
-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/03_keys.up.sql
-- we need to replace the existing function and there are existing tables that
-- depend on it.. so let's just create/replace it
-- kms_version_column() will increment the version column whenever row data
-- is inserted and should only be used in an before insert trigger. This
-- function will overwrite any explicit values to the version column.
create or replace function kms_version_column()
returns trigger
as $$
declare
_key_id text;
_max bigint;
begin
execute format('SELECT $1.%I', tg_argv[0]) into _key_id using new;
execute format('select max(version) + 1 from %I where %I = $1', tg_relid::regclass, tg_argv[0]) using _key_id into _max;
if _max is null then
_max = 1;
end if;
new.version = _max;
return new;
end;
$$ language plpgsql;
comment on function
kms_version_column()
is
'function used in before insert triggers to properly set version columns for kms_* tables with a version column';
commit;
@@ -0,0 +1,281 @@
begin;
-- make the required schema changes to adopt
-- github.com/hashicorp/go-kms-wrapping/extras/kms/v2
-- this migration is from:
-- https://github.com/hashicorp/go-kms-wrapping/blob/main/extras/kms/migrations/postgres/04_keys.up.sql
alter table kms_root_key rename to kms_deprecated_root_key;
alter table kms_root_key_version rename to kms_deprecated_root_key_version;
create table kms_root_key (
private_id kms_private_id primary key,
scope_id kms_scope_id not null unique -- there can only be one root key for a scope.
references iam_scope(public_id)
on delete cascade
on update cascade,
create_time kms_timestamp
);
comment on table kms_root_key is
'kms_root_key defines a root key for a scope';
-- define the immutable fields for kms_root_key (all of them)
create trigger kms_immutable_columns
before
update on kms_root_key
for each row execute procedure kms_immutable_columns('private_id', 'scope_id', 'create_time');
-- not adding the kms_default_create_time_column trigger until after we've
-- converted the data (we don't want the timestamp to change)
create table kms_root_key_version (
private_id kms_private_id primary key,
root_key_id kms_private_id not null
constraint kms_root_key_fkey
references kms_root_key(private_id)
on delete cascade
on update cascade,
version kms_version,
key bytea not null
constraint not_empty_key
check (
length(key) > 0
),
create_time kms_timestamp,
constraint kms_root_key_version_root_key_id_version_uq
unique(root_key_id, version)
);
comment on table kms_root_key_version is
'kms_root_key_version contains versions of a kms_root_key';
-- define the immutable fields for kms_root_key_version (all of them)
create trigger kms_immutable_columns
before
update on kms_root_key_version
for each row execute procedure kms_immutable_columns('private_id', 'root_key_id', 'version', 'key', 'create_time');
-- not adding the kms_default_create_time_column or kms_version_column triggers
-- until after we've converted the data (we don't want the timestamp or versions
-- to change)
create table kms_data_key (
private_id kms_private_id primary key,
root_key_id kms_private_id not null
constraint kms_root_key_fkey
references kms_root_key(private_id)
on delete cascade
on update cascade,
purpose text not null
constraint not_start_end_whitespace_purpose
check (length(trim(purpose)) = length(purpose)),
create_time kms_timestamp,
constraint kms_data_key_root_key_id_purpose_uq
unique (root_key_id, purpose) -- there can only be one dek for a specific purpose per root key
);
comment on table kms_data_key is
'kms_data_key contains deks (data keys) for specific purposes';
-- define the immutable fields for kms_data_key (all of them)
create trigger kms_immutable_columns
before
update on kms_data_key
for each row execute procedure kms_immutable_columns('private_id', 'root_key_id', 'purpose', 'create_time');
-- not adding the kms_default_create_time_column trigger until after we've
-- converted the data (we don't want the timestamp to change)
create table kms_data_key_version (
private_id kms_private_id primary key,
data_key_id kms_private_id not null
constraint kms_data_key_fkey
references kms_data_key(private_id)
on delete cascade
on update cascade,
root_key_version_id kms_private_id not null
constraint kms_root_key_version_fkey
references kms_root_key_version(private_id)
on delete cascade
on update cascade,
version kms_version,
key bytea not null
constraint not_empty_key
check (
length(key) > 0
),
create_time kms_timestamp,
constraint kms_data_key_version_data_key_id_version_uq
unique(data_key_id, version)
);
comment on table kms_data_key is
'kms_data_key_version contains versions of a kms_data_key (dek aka data keys)';
-- define the immutable fields for kms_data_key_version (all of them)
create trigger kms_immutable_columns
before
update on kms_data_key_version
for each row execute procedure immutable_columns('private_id', 'data_key_id', 'root_key_version_id', 'version', 'key', 'create_time');
-- not adding the kms_default_create_time_column or kms_version_column triggers
-- until after we've converted the data (we don't want the timestamp or versions
-- to change)
-- ############################################################################
-- Next: we will convert all the existing KEKs/DEKs into the new schema model
-- before adding triggers for create_time, and version
-- this is important, especially for the version column!
-- convert KEK tables
insert into kms_root_key (private_id, scope_id, create_time)
select private_id, scope_id, create_time
from kms_deprecated_root_key;
insert into kms_root_key_version (private_id, root_key_id, version, key, create_time)
select private_id, root_key_id, version, key, create_time
from kms_deprecated_root_key_version;
-- convert database DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'database', create_time
from kms_database_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, database_key_id, root_key_version_id, version, key, create_time
from kms_database_key_version;
-- convert oplog DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'oplog', create_time
from kms_oplog_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, oplog_key_id, root_key_version_id, version, key, create_time
from kms_oplog_key_version;
-- convert the audit DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'audit', create_time
from kms_audit_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, audit_key_id, root_key_version_id, version, key, create_time
from kms_audit_key_version;
-- convert the oidc DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'oidc', create_time
from kms_oidc_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, oidc_key_id, root_key_version_id, version, key, create_time
from kms_oidc_key_version;
-- convert the token DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'tokens', create_time
from kms_token_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, token_key_id, root_key_version_id, version, key, create_time
from kms_token_key_version;
-- convert the session DEK tables
insert into kms_data_key (private_id, root_key_id, purpose, create_time)
select private_id, root_key_id, 'sessions', create_time
from kms_session_key;
insert into kms_data_key_version (private_id, data_key_id, root_key_version_id, version, key, create_time)
select private_id, session_key_id, root_key_version_id, version, key, create_time
from kms_session_key_version;
-- ############################################################################
-- post conversion, we add the required triggers
create trigger kms_default_create_time_column
before
insert on kms_root_key
for each row execute procedure kms_default_create_time();
create trigger kms_default_create_time_column
before
insert on kms_root_key_version
for each row execute procedure kms_default_create_time();
create trigger kms_version_column
before insert on kms_root_key_version
for each row execute procedure kms_version_column('root_key_id');
create trigger default_create_time_column
before
insert on kms_data_key
for each row execute procedure kms_default_create_time();
create trigger default_create_time
before
insert on kms_data_key_version
for each row execute procedure kms_default_create_time();
create trigger kms_version_column
before insert on kms_data_key_version
for each row execute procedure kms_version_column('data_key_id');
-- Next: we will convert all the existing DEKs FKs to the new model
alter table credential_vault_token drop constraint kms_database_key_version_fkey;
alter table credential_vault_token
add constraint kms_data_key_version_fkey
foreign key(key_id)
references kms_data_key_version (private_id)
on delete restrict
on update cascade;
alter table credential_vault_client_certificate drop constraint kms_database_key_version_fkey;
alter table credential_vault_client_certificate
add constraint kms_data_key_version_fkey
foreign key(key_id)
references kms_data_key_version (private_id)
on delete restrict
on update cascade;
alter table auth_oidc_method drop constraint kms_database_key_version_fkey;
alter table auth_oidc_method
add constraint kms_data_key_version_fkey
foreign key(key_id)
references kms_data_key_version (private_id)
on delete restrict
on update cascade;
alter table host_plugin_catalog_secret drop constraint kms_database_key_version_fkey;
alter table host_plugin_catalog_secret
add constraint kms_data_key_version_fkey
foreign key(key_id)
references kms_data_key_version (private_id)
on delete restrict
on update cascade;
alter table session_credential drop constraint kms_database_key_version_fkey;
alter table session_credential
add constraint kms_data_key_version_fkey
foreign key(key_id)
references kms_data_key_version (private_id)
on delete restrict
on update cascade;
-- rename tables so we know that they won't be used by mistake
alter table kms_database_key_version rename to kms_deprecated_database_key_version;
alter table kms_database_key rename to kms_deprecated_database_key;
alter table kms_oplog_key_version rename to kms_deprecated_oplog_key_version;
alter table kms_oplog_key rename to kms_deprecated_oplog_key;
alter table kms_audit_key_version rename to kms_deprecated_audit_key_version;
alter table kms_audit_key rename to kms_audit_database_key;
alter table kms_oidc_key_version rename to kms_deprecated_oidc_key_version;
alter table kms_oidc_key rename to kms_deprecated_oidc_key;
alter table kms_session_key_version rename to kms_deprecated_session_key_version;
alter table kms_session_key rename to kms_deprecated_session_key;
alter table kms_token_key_version rename to kms_deprecated_token_key_version;
alter table kms_token_key rename to kms_deprecated_token_key;
commit;
@@ -1,162 +0,0 @@
package oss_test
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/servers"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMigrations_Nonce(t *testing.T) {
const (
priorMigration = 16005
currentMigration = 18001
)
t.Parallel()
assert, require := assert.New(t), require.New(t)
ctx := context.Background()
dialect := dbtest.Postgres
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(err)
t.Cleanup(func() {
require.NoError(c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err := m.CurrentState(ctx)
require.NoError(err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// get a connection
dbType, err := db.StringToDbType(dialect)
require.NoError(err)
conn, err := db.Open(dbType, u)
require.NoError(err)
rw := db.New(conn)
// okay, now we can seed the database with test data and validate existing
// functionality. At the end of this we will have two values in the table
// with no purpose.
{
// Create an old version of the struct
type RecoveryNonce struct {
Nonce string
}
require.NoError(rw.CreateItems(ctx, []interface{}{
&RecoveryNonce{Nonce: "abcd"},
&RecoveryNonce{Nonce: "dcba"},
}))
var results []*RecoveryNonce
require.NoError(rw.SearchWhere(ctx, &results, "", nil))
require.Len(results, 2)
}
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err = m.CurrentState(ctx)
require.NoError(err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// now we have migrated and we will validate functionality; we'll do this
// via the repo
{
wrapper := db.TestWrapper(t)
kmsCache := kms.TestKms(t, conn, wrapper)
rw := db.New(conn)
repo, err := servers.NewRepository(rw, rw, kmsCache)
require.NoError(err)
require.NotNil(repo)
// First list and validate that the upgrade adjusted purpose correctly
results, err := repo.ListNonces(ctx, servers.NoncePurposeRecovery)
require.NoError(err)
assert.Len(results, 2)
for _, n := range results {
assert.Equal(servers.NoncePurposeRecovery, n.Purpose)
}
// Test the constraint, first via the repo, then directly
const badPurpose = "foobar"
err = repo.AddNonce(ctx, "xyz", badPurpose)
require.Error(err)
assert.Contains(err.Error(), "unknown nonce purpose")
// Check that null errors
require.Error(rw.CreateItems(ctx, []interface{}{
&servers.Nonce{Nonce: "dcba"},
}))
// Check that bad purpose errors
require.Error(rw.CreateItems(ctx, []interface{}{
&servers.Nonce{Nonce: "dcba", Purpose: badPurpose},
}))
// Add some valid values, ensure that we can then list for both purposes
// and get different values
require.NoError(repo.AddNonce(ctx, "wxyz", servers.NoncePurposeWorkerAuth))
require.NoError(repo.AddNonce(ctx, "zyxw", servers.NoncePurposeWorkerAuth))
results, err = repo.ListNonces(ctx, servers.NoncePurposeRecovery)
require.NoError(err)
assert.Len(results, 2)
for _, n := range results {
assert.Equal(servers.NoncePurposeRecovery, n.Purpose)
}
results, err = repo.ListNonces(ctx, servers.NoncePurposeWorkerAuth)
require.NoError(err)
assert.Len(results, 2)
for _, n := range results {
assert.Equal(servers.NoncePurposeWorkerAuth, n.Purpose)
}
// Last: add the same nonce, ensure we error
require.NoError(repo.AddNonce(ctx, "double", servers.NoncePurposeWorkerAuth))
err = repo.AddNonce(ctx, "double", servers.NoncePurposeWorkerAuth)
require.Error(err)
require.Contains(err.Error(), "duplicate key value")
}
}
@@ -1,166 +0,0 @@
package oss_test
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/require"
)
func TestMigrations_SessionState(t *testing.T) {
t.Parallel()
require := require.New(t)
const (
priorMigration = 21002
currentMigration = 24001
)
dialect := dbtest.Postgres
ctx := context.Background()
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(err)
t.Cleanup(func() {
require.NoError(c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err := m.CurrentState(ctx)
require.NoError(err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// Seed the database with test data
dbType, err := db.StringToDbType(dialect)
require.NoError(err)
conn, err := db.Open(dbType, u)
require.NoError(err)
rw := db.New(conn)
wrapper := db.TestWrapper(t)
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NotNil(prj)
hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0]
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
kmsCache := kms.TestKms(t, conn, wrapper)
{
at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId())
uId := at.GetIamUserId()
sess := session.TestSession(t, conn, wrapper, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: prj.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
ConnectionLimit: -1,
})
session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22,
"127.0.0.2", 23, "127.0.0.1")
}
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err = m.CurrentState(ctx)
require.NoError(err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
sessionRepo, err := session.NewRepository(rw, rw, kmsCache)
connectionRepo, err := session.NewConnectionRepository(ctx, rw, rw, kmsCache)
require.NoError(err)
// Ensure session is cancelled
repoSessions, err := sessionRepo.ListSessions(ctx)
require.NoError(err)
var sessionTermReason []string
var repoSessionId string
for i := 0; i < len(repoSessions); i++ {
s := repoSessions[i]
repoSessionId = s.PublicId
sessionTermReason = append(sessionTermReason, s.TerminationReason)
}
require.Equal([]string{"canceled"}, sessionTermReason)
// Ensure connection is also cancelled
connections, err := connectionRepo.ListConnectionsBySessionId(ctx, repoSessionId)
require.NoError(err)
var connTermReason []string
for i := 0; i < len(connections); i++ {
c := connections[i]
connTermReason = append(connTermReason, c.ClosedReason)
}
require.Equal([]string{"canceled"}, connTermReason)
// Validate new table contents
rows, err := d.QueryContext(ctx, "select * from session_valid_state")
require.NoError(err)
var validStates []string
for rows.Next() {
var a, b string
require.NoError(rows.Scan(&a, &b))
validStates = append(validStates, []string{a, b}...)
}
require.Equal([]string{
"pending", "pending", "pending", "active", "pending", "terminated",
"pending", "canceling", "active", "canceling", "active", "terminated", "canceling", "terminated",
}, validStates)
}
@@ -1,151 +0,0 @@
package oss_test
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/require"
)
func TestMigrations_SessionStateTrigger(t *testing.T) {
t.Parallel()
require := require.New(t)
const (
priorMigration = 27002
currentMigration = 28002
)
dialect := dbtest.Postgres
ctx := context.Background()
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(err)
t.Cleanup(func() {
require.NoError(c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err := m.CurrentState(ctx)
require.NoError(err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// Seed the database with test data
dbType, err := db.StringToDbType(dialect)
require.NoError(err)
conn, err := db.Open(dbType, u)
require.NoError(err)
rw := db.New(conn)
wrapper := db.TestWrapper(t)
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NotNil(prj)
hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0]
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
kmsCache := kms.TestKms(t, conn, wrapper)
serverId := "worker"
tofu := session.TestTofu(t)
session.TestWorker(t, conn, wrapper, session.WithServerId(serverId))
at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId())
uId := at.GetIamUserId()
sess := session.TestSession(t, conn, wrapper, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: prj.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
ConnectionLimit: 1,
})
sessionRepo, err := session.NewRepository(rw, rw, kmsCache)
require.NoError(err)
// Make and transition a valid session through pending, active, canceling, and terminated
// Unfortunately, could not recreate an invalid session P-A-T-C using the session repo
_, _, err = sessionRepo.ActivateSession(ctx, sess.PublicId, sess.Version, serverId, resource.Worker.String(), tofu)
require.NoError(err)
connection := session.TestConnection(t, conn, sess.PublicId, "127.0.0.1", 22,
"127.0.0.2", 23, "127.0.0.1")
session.TestConnectionState(t, conn, connection.PublicId, session.StatusConnected)
session.TestConnectionState(t, conn, connection.PublicId, session.StatusClosed)
_, err = sessionRepo.CancelSession(ctx, sess.PublicId, sess.Version+1)
require.NoError(err)
sessionRepo.TerminateCompletedSessions(ctx)
repoSessions, err := sessionRepo.ListSessions(ctx)
require.NoError(err)
var numStates int
for _, s := range repoSessions {
numStates = len(s.States)
}
require.Equal(4, numStates)
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err = m.CurrentState(ctx)
require.NoError(err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// Check that we haven't removed a state
repoSessions, err = sessionRepo.ListSessions(ctx)
require.NoError(err)
for _, s := range repoSessions {
numStates = len(s.States)
}
require.Equal(4, numStates)
}
@@ -1,140 +0,0 @@
package oss_test
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
"github.com/hashicorp/boundary/internal/target/tcp"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/require"
)
func TestMigrations_SessionFKeyDelete(t *testing.T) {
t.Parallel()
require := require.New(t)
const (
priorMigration = 28002
currentMigration = 29001
)
dialect := dbtest.Postgres
ctx := context.Background()
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(err)
t.Cleanup(func() {
require.NoError(c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err := m.CurrentState(ctx)
require.NoError(err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// Seed the database with test data
dbType, err := db.StringToDbType(dialect)
require.NoError(err)
conn, err := db.Open(dbType, u)
require.NoError(err)
rw := db.New(conn)
wrapper := db.TestWrapper(t)
org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
require.NotNil(prj)
hc := static.TestCatalogs(t, conn, prj.GetPublicId(), 1)[0]
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0]
static.TestSetMembers(t, conn, hs.GetPublicId(), []*static.Host{h})
tar := tcp.TestTarget(ctx, t, conn, prj.GetPublicId(), "test", target.WithHostSources([]string{hs.GetPublicId()}))
kmsCache := kms.TestKms(t, conn, wrapper)
targetRepo, err := target.NewRepository(rw, rw, kmsCache)
require.NoError(err)
serverId := "worker"
tofu := session.TestTofu(t)
session.TestWorker(t, conn, wrapper, session.WithServerId(serverId))
at := authtoken.TestAuthToken(t, conn, kmsCache, org.GetPublicId())
uId := at.GetIamUserId()
sess := session.TestSession(t, conn, wrapper, session.ComposedOf{
UserId: uId,
HostId: h.GetPublicId(),
TargetId: tar.GetPublicId(),
HostSetId: hs.GetPublicId(),
AuthTokenId: at.GetPublicId(),
ScopeId: prj.GetPublicId(),
Endpoint: "tcp://127.0.0.1:22",
ConnectionLimit: 1,
})
sessionRepo, err := session.NewRepository(rw, rw, kmsCache)
require.NoError(err)
// Create and terminate session without canceling
_, _, err = sessionRepo.ActivateSession(ctx, sess.PublicId, sess.Version, serverId, resource.Worker.String(), tofu)
require.NoError(err)
session.TestState(t, conn, sess.PublicId, session.StatusTerminated)
// Delete target; expect a session_state violation and failure to delete target
rows, err := targetRepo.DeleteTarget(ctx, tar.GetPublicId())
require.Errorf(err, "target.(Repository).DeleteTarget: db.DoTx: target.(Repository).DeleteTarget: db.Delete: insert or update on table \"session_state\" violates foreign key constraint \"session_valid_state_enm_fkey\": integrity violation: error #1003")
require.Equal(0, rows)
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(err)
require.NoError(m.ApplyMigrations(ctx))
state, err = m.CurrentState(ctx)
require.NoError(err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(want, state)
// Try to delete target again, should succeed without error
rows, err = targetRepo.DeleteTarget(ctx, tar.GetPublicId())
require.NoError(err)
require.Equal(1, rows)
}
@@ -0,0 +1,587 @@
package oss_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/hashicorp/boundary/internal/db"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMigrations_KMS_Refactor(t *testing.T) {
const (
priorMigration = 28002
currentMigration = 30004
)
t.Parallel()
ctx := context.Background()
dialect := dbtest.Postgres
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
d, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
// migration to the prior migration (before the one we want to test)
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
))
require.NoError(t, err)
require.NoError(t, m.ApplyMigrations(ctx))
state, err := m.CurrentState(ctx)
require.NoError(t, err)
want := &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: priorMigration,
DatabaseSchemaVersion: priorMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(t, want, state)
// get a connection
dbType, err := db.StringToDbType(dialect)
require.NoError(t, err)
conn, err := db.Open(dbType, u)
require.NoError(t, err)
rw := db.New(conn)
generateTestKeys(t, rw)
// load up the current KEKs and their versions
existingKeks := loadKeks(t, rw)
existingKeksVersions := loadKekVersions(t, rw)
// load up the current DEKs and their versions
existingDeks := loadCurrentDeks(t, rw)
existingKeyVersions := loadCurrentDekVersions(t, rw)
// now we're ready for the migration we want to test.
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
))
require.NoError(t, err)
require.NoError(t, m.ApplyMigrations(ctx))
state, err = m.CurrentState(ctx)
require.NoError(t, err)
want = &schema.State{
Initialized: true,
Editions: []schema.EditionState{
{
Name: "oss",
BinarySchemaVersion: currentMigration,
DatabaseSchemaVersion: currentMigration,
DatabaseSchemaState: schema.Equal,
},
},
}
require.Equal(t, want, state)
// Now read all the converted keys and see if we have transformed them correctly
{
// get a new connection
dbType, err := db.StringToDbType(dialect)
require.NoError(t, err)
conn, err := db.Open(dbType, u)
require.NoError(t, err)
rw := db.New(conn)
newKeks := loadKeks(t, rw)
assert.ElementsMatch(t, newKeks, existingKeks)
newKeksVersions := loadKekVersions(t, rw)
assert.ElementsMatch(t, newKeksVersions, existingKeksVersions)
newDeks := loadNewDeks(t, rw)
assert.ElementsMatch(t, newDeks, existingDeks)
newKeyVersions := loadNewDekVersions(t, rw)
assert.ElementsMatch(t, newKeyVersions, existingKeyVersions)
}
}
// we can't use the new KMS bits since all the tables have changed, so we'll
// generate a bit of test data by hand
func generateTestKeys(t *testing.T, rw *db.Db) {
t.Helper()
require := require.New(t)
testCtx := context.Background()
for i := 0; i < 10; i++ {
k := kek{
PrivateId: testId(t, "rk"),
ScopeId: testScope(t, rw).PublicId,
}
require.NoError(rw.Create(testCtx, &k))
var kv kekVersion
for i := 0; i < 2; i++ {
kv = kekVersion{
PrivateId: testId(t, "rkv"),
RootKeyId: k.PrivateId,
Version: 1 + uint32(i),
Key: []byte("test-key"),
}
require.NoError(rw.Create(testCtx, &kv))
}
{
dbk := kmsDatabaseKey{
PrivateId: testId(t, "dk"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &dbk))
dbkv := kmsDatabaseKeyVersion{
PrivateId: testId(t, "dkv"),
DatabaseKeyId: dbk.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &dbkv))
}
{
ak := kmsAuditKey{
PrivateId: testId(t, "ak"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &ak))
akv := kmsAuditKeyVersion{
PrivateId: testId(t, "dkv"),
AuditKeyId: ak.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &akv))
}
{
oidck := kmsOidcKey{
PrivateId: testId(t, "oidck"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &oidck))
oidckv := kmsOidcKeyVersion{
PrivateId: testId(t, "dkv"),
OidcKeyId: oidck.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &oidckv))
}
{
opk := kmsOplogKey{
PrivateId: testId(t, "opk"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &opk))
opkv := kmsOplogKeyVersion{
PrivateId: testId(t, "dkv"),
OplogKeyId: opk.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &opkv))
}
{
sk := kmsSessionKey{
PrivateId: testId(t, "sk"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &sk))
skv := kmsSessionKeyVersion{
PrivateId: testId(t, "dkv"),
SessionKeyId: sk.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &skv))
}
{
tk := kmsTokenKey{
PrivateId: testId(t, "tk"),
RootKeyId: k.PrivateId,
}
require.NoError(rw.Create(testCtx, &tk))
tkv := kmsTokenKeyVersion{
PrivateId: testId(t, "dkv"),
TokenKeyId: tk.PrivateId,
RootKeyVersionId: kv.PrivateId,
Key: []byte("test-key"),
Version: 1,
}
require.NoError(rw.Create(testCtx, &tkv))
}
}
}
func loadKeks(t *testing.T, rw *db.Db) []kek {
t.Helper()
testCtx := context.Background()
rows, err := rw.Query(testCtx, `select private_id, scope_id, create_time from kms_root_key order by private_id`, nil)
require.NoError(t, err)
require.NoError(t, err)
var keks []kek
for rows.Next() {
var key kek
require.NoError(t, rw.ScanRows(context.Background(), rows, &key))
keks = append(keks, key)
}
return keks
}
func loadKekVersions(t *testing.T, rw *db.Db) []kekVersion {
t.Helper()
testCtx := context.Background()
rows, err := rw.Query(testCtx, `select private_id, root_key_id, version, key, create_time from kms_root_key_version order by private_id`, nil)
require.NoError(t, err)
require.NoError(t, err)
var kekVersions []kekVersion
for rows.Next() {
var v kekVersion
require.NoError(t, rw.ScanRows(context.Background(), rows, &v))
kekVersions = append(kekVersions, v)
}
return kekVersions
}
func loadNewDeks(t *testing.T, rw *db.Db) []dek {
t.Helper()
testCtx := context.Background()
rows, err := rw.Query(testCtx, `select private_id, root_key_id, create_time, purpose from kms_data_key order by private_id`, nil)
require.NoError(t, err)
require.NoError(t, err)
var deks []dek
for rows.Next() {
var key dek
require.NoError(t, rw.ScanRows(context.Background(), rows, &key))
deks = append(deks, key)
}
return deks
}
func loadCurrentDeks(t *testing.T, rw *db.Db) []dek {
t.Helper()
testCtx := context.Background()
var deks []dek
for _, purpose := range []string{"audit", "database", "oidc", "oplog", "sessions", "tokens"} {
var table string
switch purpose {
case "audit":
table = "kms_audit_key"
case "database":
table = "kms_database_key"
case "oidc":
table = "kms_oidc_key"
case "oplog":
table = "kms_oplog_key"
case "sessions":
table = "kms_session_key"
case "tokens":
table = "kms_token_key"
default:
t.Fatalf("not a supported dek %q", purpose)
}
sql := fmt.Sprintf(`select private_id, root_key_id, create_time, '%s' as purpose from %s order by private_id`, purpose, table)
rows, err := rw.Query(testCtx, sql, nil)
require.NoError(t, err)
require.NoError(t, err)
for rows.Next() {
var key dek
require.NoError(t, rw.ScanRows(context.Background(), rows, &key))
deks = append(deks, key)
}
}
return deks
}
func loadNewDekVersions(t *testing.T, rw *db.Db) []dekVersion {
t.Helper()
testCtx := context.Background()
rows, err := rw.Query(testCtx, `select private_id, data_key_id, root_key_version_id, version, key, create_time from kms_data_key_version order by private_id`, nil)
require.NoError(t, err)
require.NoError(t, err)
var dekVersions []dekVersion
for rows.Next() {
var v dekVersion
require.NoError(t, rw.ScanRows(context.Background(), rows, &v))
dekVersions = append(dekVersions, v)
}
return dekVersions
}
func loadCurrentDekVersions(t *testing.T, rw *db.Db) []dekVersion {
t.Helper()
testCtx := context.Background()
var dekVersions []dekVersion
for _, versionType := range []string{"audit", "database", "oidc", "oplog", "session", "token"} {
var table string
switch versionType {
case "audit":
table = "kms_audit_key_version"
case "database":
table = "kms_database_key_version"
case "oidc":
table = "kms_oidc_key_version"
case "oplog":
table = "kms_oplog_key_version"
case "session":
table = "kms_session_key_version"
case "token":
table = "kms_token_key_version"
}
sql := fmt.Sprintf(`select private_id, %s_key_id, root_key_version_id, key, version, create_time from %s order by private_id`, versionType, table)
rows, err := rw.Query(testCtx, sql, nil)
require.NoError(t, err)
require.NoError(t, err)
for rows.Next() {
result := map[string]interface{}{}
require.NoError(t, rw.ScanRows(context.Background(), rows, &result))
var v dekVersion
switch versionType {
case "audit":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["audit_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
case "database":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["database_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
case "oidc":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["oidc_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
case "oplog":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["oplog_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
case "session":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["session_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
case "token":
v = dekVersion{
PrivateId: result["private_id"].(string),
DataKeyId: result["token_key_id"].(string),
RootKeyVersionId: result["root_key_version_id"].(string),
Key: result["key"].([]byte),
Version: uint32(result["version"].(int64)),
CreateTime: result["create_time"].(time.Time),
}
}
dekVersions = append(dekVersions, v)
}
}
return dekVersions
}
func testId(t testing.TB, prefix string) string {
t.Helper()
id, err := db.NewPublicId(prefix)
require.NoError(t, err)
return id
}
func testScope(t *testing.T, rw *db.Db) *iam.Scope {
t.Helper()
require := require.New(t)
testCtx := context.Background()
s, err := iam.NewOrg()
require.NoError(err)
s.PublicId = testId(t, "o")
require.NoError(rw.Create(testCtx, &s))
return s
}
type kek struct {
PrivateId string
ScopeId string
CreateTime time.Time
}
func (*kek) TableName() string { return "kms_root_key" }
type kekVersion struct {
PrivateId string
RootKeyId string
Version uint32
Key []byte
CreateTime time.Time
}
func (*kekVersion) TableName() string { return "kms_root_key_version" }
type dek struct {
PrivateId string
RootKeyId string
CreateTime time.Time
Purpose string
}
type dekVersion struct {
PrivateId string
DataKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
type kmsDatabaseKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsDatabaseKey) TableName() string { return "kms_database_key" }
type kmsDatabaseKeyVersion struct {
PrivateId string
DatabaseKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsDatabaseKeyVersion) TableName() string { return "kms_database_key_version" }
type kmsAuditKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsAuditKey) TableName() string { return "kms_audit_key" }
type kmsAuditKeyVersion struct {
PrivateId string
AuditKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsAuditKeyVersion) TableName() string { return "kms_audit_key_version" }
type kmsOidcKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsOidcKey) TableName() string { return "kms_oidc_key" }
type kmsOidcKeyVersion struct {
PrivateId string
OidcKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsOidcKeyVersion) TableName() string { return "kms_oidc_key_version" }
type kmsOplogKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsOplogKey) TableName() string { return "kms_oplog_key" }
type kmsOplogKeyVersion struct {
PrivateId string
OplogKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsOplogKeyVersion) TableName() string { return "kms_oplog_key_version" }
type kmsSessionKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsSessionKey) TableName() string { return "kms_session_key" }
type kmsSessionKeyVersion struct {
PrivateId string
SessionKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsSessionKeyVersion) TableName() string { return "kms_session_key_version" }
type kmsTokenKey struct {
PrivateId string
RootKeyId string
CreateTime time.Time
}
func (*kmsTokenKey) TableName() string { return "kms_token_key" }
type kmsTokenKeyVersion struct {
PrivateId string
TokenKeyId string
RootKeyVersionId string
Key []byte
Version uint32
CreateTime time.Time
}
func (*kmsTokenKeyVersion) TableName() string { return "kms_token_key_version" }
@@ -105,13 +105,13 @@ begin;
values
('krkv___widget', 'krk___widget', 'krk___widget'::bytea);
insert into kms_database_key
(private_id, root_key_id)
insert into kms_data_key
(private_id, root_key_id, purpose)
values
('kdk____widget', 'krk___widget');
('kdk____widget', 'krk___widget', 'database');
insert into kms_database_key_version
(private_id, database_key_id, root_key_version_id, key)
insert into kms_data_key_version
(private_id, data_key_id, root_key_version_id, key)
values
('kdkv___widget', 'kdk____widget', 'krkv___widget', 'kdk____widget'::bytea);