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:
97 files changed
+2580
-15154
No files matched your search
@@ -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;
|
||||
Reference in new issue
Block a user