feat(sql): Add history tables for static credentials

This adds history tables for `credential_static_store`,
`credential_static_json_credential`,
`credential_static_username_password_credential`, and
`credential_static_ssh_private_key_credential`. This also adds a base
table for the static credential history tables.
pull/3251/head
Michael Gaffney 3 years ago committed by Timothy Messier
parent 386eac072c
commit 3a64fb3d58
No known key found for this signature in database
GPG Key ID: EFD2F184F7600572

@ -0,0 +1,180 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
create table credential_static_history_base (
history_id wt_url_safe_id primary key
);
comment on table credential_static_history_base is
'credential_static_history_base is a base history table '
'for credential_static history tables.';
create function insert_credential_static_history_subtype() returns trigger
as $$
begin
insert into credential_static_history_base
(history_id)
values
(new.history_id);
return new;
end;
$$ language plpgsql;
comment on function insert_credential_static_history_subtype is
'insert_credential_static_history_subtype is a before insert trigger '
'function for subtypes of credential_static_history_base.';
create function delete_credential_static_history_subtype() returns trigger
as $$
begin
delete
from credential_static_history_base
where history_id = old.history_id;
return null; -- result is ignored since this is an after trigger
end;
$$ language plpgsql;
comment on function delete_credential_static_history_subtype is
'delete_credential_static_history_subtype() is an after delete trigger '
'function for subtypes of credential_static_history_base.';
create table credential_static_json_credential_hst (
public_id wt_public_id not null,
name wt_name,
description wt_description,
project_id wt_public_id not null,
store_id wt_public_id not null,
object_hmac bytea not null,
history_id wt_url_safe_id default wt_url_safe_id() primary key
constraint credential_static_history_base_fkey
references credential_static_history_base (history_id)
on delete cascade
on update cascade,
valid_range tstzrange not null default tstzrange(current_timestamp, null),
constraint credential_static_json_credential_hst_valid_range_excl
exclude using gist (public_id with =, valid_range with &&)
);
comment on table credential_static_json_credential_hst is
'credential_static_json_credential_hst is a history table where each row contains the values from a row '
'in the credential_static_json_credential table during the time range in the valid_range column.';
create trigger insert_credential_static_history_subtype before insert on credential_static_json_credential_hst
for each row execute function insert_credential_static_history_subtype();
create trigger delete_credential_static_history_subtype after delete on credential_static_json_credential_hst
for each row execute function delete_credential_static_history_subtype();
create trigger hst_on_insert after insert on credential_static_json_credential
for each row execute function hst_on_insert();
create trigger hst_on_update after update on credential_static_json_credential
for each row execute function hst_on_update();
create trigger hst_on_delete after delete on credential_static_json_credential
for each row execute function hst_on_delete();
insert into credential_static_json_credential_hst
(public_id, name, description, project_id, store_id, object_hmac)
select public_id, name, description, project_id, store_id, object_hmac
from credential_static_json_credential;
create table credential_static_username_password_credential_hst (
public_id wt_public_id not null,
name wt_name,
description wt_description,
project_id wt_public_id not null,
store_id wt_public_id not null,
username text not null,
password_hmac bytea not null,
history_id wt_url_safe_id default wt_url_safe_id() primary key
constraint credential_static_history_base_fkey
references credential_static_history_base (history_id)
on delete cascade
on update cascade,
valid_range tstzrange not null default tstzrange(current_timestamp, null),
constraint credential_static_user_password_credential_hst_valid_range_excl
exclude using gist (public_id with =, valid_range with &&)
);
comment on table credential_static_username_password_credential_hst is
'credential_static_username_password_credential_hst is a history table where each row contains the values from a row '
'in the credential_static_username_password_credential table during the time range in the valid_range column.';
create trigger insert_credential_static_history_subtype before insert on credential_static_username_password_credential_hst
for each row execute function insert_credential_static_history_subtype();
create trigger delete_credential_static_history_subtype after delete on credential_static_username_password_credential_hst
for each row execute function delete_credential_static_history_subtype();
create trigger hst_on_insert after insert on credential_static_username_password_credential
for each row execute function hst_on_insert();
create trigger hst_on_update after update on credential_static_username_password_credential
for each row execute function hst_on_update();
create trigger hst_on_delete after delete on credential_static_username_password_credential
for each row execute function hst_on_delete();
insert into credential_static_username_password_credential_hst
(public_id, name, description, project_id, store_id, username, password_hmac)
select public_id, name, description, project_id, store_id, username, password_hmac
from credential_static_username_password_credential;
create table credential_static_ssh_private_key_credential_hst (
public_id wt_public_id not null,
name wt_name,
description wt_description,
project_id wt_public_id not null,
store_id wt_public_id not null,
username text not null,
private_key_hmac bytea not null,
private_key_passphrase_hmac bytea,
history_id wt_url_safe_id default wt_url_safe_id() primary key
constraint credential_static_history_base_fkey
references credential_static_history_base (history_id)
on delete cascade
on update cascade,
valid_range tstzrange not null default tstzrange(current_timestamp, null),
constraint credential_static_ssh_priv_key_credential_hst_valid_range_excl
exclude using gist (public_id with =, valid_range with &&)
);
comment on table credential_static_ssh_private_key_credential_hst is
'credential_static_ssh_private_key_credential_hst is a history table where each row contains the values from a row '
'in the credential_static_ssh_private_key_credential table during the time range in the valid_range column.';
create trigger insert_credential_static_history_subtype before insert on credential_static_ssh_private_key_credential_hst
for each row execute function insert_credential_static_history_subtype();
create trigger delete_credential_static_history_subtype after delete on credential_static_ssh_private_key_credential_hst
for each row execute function delete_credential_static_history_subtype();
create trigger hst_on_insert after insert on credential_static_ssh_private_key_credential
for each row execute function hst_on_insert();
create trigger hst_on_update after update on credential_static_ssh_private_key_credential
for each row execute function hst_on_update();
create trigger hst_on_delete after delete on credential_static_ssh_private_key_credential
for each row execute function hst_on_delete();
insert into credential_static_ssh_private_key_credential_hst
(public_id, name, description, project_id, store_id, username, private_key_hmac, private_key_passphrase_hmac)
select public_id, name, description, project_id, store_id, username, private_key_hmac, private_key_passphrase_hmac
from credential_static_ssh_private_key_credential;
create table credential_static_store_hst (
public_id wt_public_id not null,
name wt_name,
description wt_description,
project_id wt_scope_id not null,
history_id wt_url_safe_id default wt_url_safe_id() primary key,
valid_range tstzrange not null default tstzrange(current_timestamp, null),
constraint credential_static_store_hst_valid_range_excl
exclude using gist (public_id with =, valid_range with &&)
);
comment on table credential_static_store_hst is
'credential_static_store_hst is a history table where each row contains the values from a row '
'in the credential_static_store table during the time range in the valid_range column.';
create trigger hst_on_insert after insert on credential_static_store
for each row execute function hst_on_insert();
create trigger hst_on_update after update on credential_static_store
for each row execute function hst_on_update();
create trigger hst_on_delete after delete on credential_static_store
for each row execute function hst_on_delete();
insert into credential_static_store_hst
(public_id, name, description, project_id)
select public_id, name, description, project_id
from credential_static_store;
commit;

@ -53,7 +53,7 @@ begin;
insert into kms_data_key_version
(private_id, data_key_id, root_key_version_id, key)
values
('kdkv_______colors', 'kdk_______colors', 'krkv_______colors', '_______color2'::bytea);
('kdkv__colors', 'kdk_______colors', 'krkv_______colors', '_______color2'::bytea);
insert into iam_group
(scope_id, public_id, name)
@ -156,11 +156,11 @@ begin;
insert into auth_token
(key_id, auth_account_id, public_id, token)
values
('kdkv_______colors', 'apa____clare', 'tok____clare', 'tok____clare'::bytea),
('kdkv_______colors', 'apa____cindy', 'tok____cindy', 'tok____cindy'::bytea),
('kdkv_______colors', 'apa____ciara', 'tok____ciara', 'tok____ciara'::bytea),
('kdkv_______colors', 'apa____carly', 'tok____carly', 'tok____carly'::bytea),
('kdkv_______colors', 'apa_____cora', 'tok_____cora', 'tok_____cora'::bytea);
('kdkv__colors', 'apa____clare', 'tok____clare', 'tok____clare'::bytea),
('kdkv__colors', 'apa____cindy', 'tok____cindy', 'tok____cindy'::bytea),
('kdkv__colors', 'apa____ciara', 'tok____ciara', 'tok____ciara'::bytea),
('kdkv__colors', 'apa____carly', 'tok____carly', 'tok____carly'::bytea),
('kdkv__colors', 'apa_____cora', 'tok_____cora', 'tok_____cora'::bytea);
insert into static_host
(catalog_id, public_id, address)
@ -184,7 +184,7 @@ begin;
('c___cr-sthcl', 'h_____cr__07', '7.red.color'),
('c___cr-sthcl', 'h_____cr__08', '8.red.color'),
('c___cr-sthcl', 'h_____cr__09', '9.red.color'),
('c___cg-sthcl', 'h_____cg__01', '1.green.color'),
('c___cg-sthcl', 'h_____cg__02', '2.green.color'),
('c___cg-sthcl', 'h_____cg__03', '3.green.color'),
@ -217,7 +217,7 @@ begin;
('h_____cr__07', '7.red.color'),
('h_____cr__08', '8.red.color'),
('h_____cr__09', '9.red.color'),
('h_____cg__01', '1.green.color'),
('h_____cg__02', '2.green.color'),
('h_____cg__03', '3.green.color'),
@ -250,7 +250,7 @@ begin;
('h_____cr__07', '77.77.77.77'),
('h_____cr__08', '2001:4860:4860::8888'),
('h_____cr__09', '99.99.99.99'),
('h_____cg__01', '111.111.111.111'),
('h_____cg__02', '3001:5860:5860::3333'),
('h_____cg__03', '112.112.112.112'),
@ -350,7 +350,7 @@ begin;
(scope_id, public_id, name)
values
('global', 'plg____sb-plg', 'Storage Bucket Plugin');
insert into plugin_storage_supported
(public_id)
values
@ -406,6 +406,42 @@ begin;
values
('vs_______cvs1', 'vl______cvl', 'color vault library', 'None', '/secrets', 'GET');
insert into credential_static_store
(project_id, public_id, name, description)
values
('p____bcolors', 'css__bcolors', 'Blue Static Credential Store', 'Static Credential Store for the Blue project'),
('p____rcolors', 'css__rcolors', 'Red Static Credential Store', 'Static Credential Store for the Red project'),
('p____gcolors', 'css__gcolors', 'Green Static Credential Store', 'Static Credential Store for the Green project');
insert into credential_static_json_credential
(key_id, project_id, store_id, public_id, name, object_encrypted, object_hmac)
values
('kdkv__colors', 'p____bcolors', 'css__bcolors', 'csj__bcolors', 'Blue json cred', 'bjson-enc'::bytea, 'bjson-hmac'::bytea),
('kdkv__colors', 'p____rcolors', 'css__rcolors', 'csj__rcolors', 'Red json cred', 'rjson-enc'::bytea, 'rjson-hmac'::bytea),
('kdkv__colors', 'p____gcolors', 'css__gcolors', 'csj__gcolors', 'Green json cred', 'gjson-enc'::bytea, 'gjson-hmac'::bytea);
insert into credential_static_username_password_credential
(key_id, project_id, store_id, public_id, name, username, password_encrypted, password_hmac)
values
('kdkv__colors', 'p____bcolors', 'css__bcolors', 'csu__bcolors', 'Blue username password cred', 'buser', 'bpasswd-enc'::bytea, 'bpasswd-hmac'::bytea),
('kdkv__colors', 'p____rcolors', 'css__rcolors', 'csu__rcolors', 'Red username password cred', 'ruser', 'rpasswd-enc'::bytea, 'rpasswd-hmac'::bytea),
('kdkv__colors', 'p____gcolors', 'css__gcolors', 'csu__gcolors', 'Green username password cred', 'guser', 'gpasswd-enc'::bytea, 'gpasswd-hmac'::bytea);
insert into credential_static_ssh_private_key_credential
(key_id, project_id, store_id, public_id, name, username, private_key_encrypted, private_key_hmac)
values
('kdkv__colors', 'p____bcolors', 'css__bcolors', 'cspk_bcolors', 'Blue username password cred', 'buser', 'bprivkey-enc'::bytea, 'bprivkey-hmac'::bytea),
('kdkv__colors', 'p____rcolors', 'css__rcolors', 'cspk_rcolors', 'Red username password cred', 'ruser', 'rprivkey-enc'::bytea, 'rprivkey-hmac'::bytea),
('kdkv__colors', 'p____gcolors', 'css__gcolors', 'cspk_gcolors', 'Green username password cred', 'guser', 'gprivkey-enc'::bytea, 'gprivkey-hmac'::bytea);
insert into target_static_credential
(project_id, target_id, credential_static_id, credential_purpose)
values
('p____bcolors', 't_________cb', 'csj__bcolors', 'brokered'),
('p____bcolors', 'tssh______cb', 'csj__bcolors', 'injected_application'),
('p____gcolors', 'tssh______cg', 'csj__gcolors', 'brokered'),
('p____gcolors', 'tssh______cg', 'cspk_gcolors', 'injected_application');
insert into target_credential_library
(project_id, target_id, credential_library_id, credential_purpose)
values

@ -69,8 +69,9 @@ begin;
begin
execute format('select results_eq( '
' ''select count(*) from %I'', '
' ''select count(*) from %I'') ',
op_table(history_table_name), history_table_name)
' ''select count(*) from %I'', '
' ''%I failed has_expected_row_count'') ',
op_table(history_table_name), history_table_name, history_table_name)
into result;
return result;
end;
@ -88,7 +89,7 @@ begin;
from get_columns(history_table_name);
select into _q1 format('select %s from %s', _cols, history_table_name);
select into _q2 format('select %s from %s', _cols, op_table(history_table_name));
return results_eq(_q1, _q2);
return results_eq(_q1, _q2, history_table_name || ' failed has_expected_content');
end;
$$ language plpgsql;
@ -149,7 +150,11 @@ begin;
-- tests for an exclusion index
create function has_exclusion_index(history_table_name name) returns text
as $$
select has_index(history_table_name, history_table_name || '_valid_range_excl', array['public_id', 'valid_range']);
select case when length(history_table_name || '_valid_range_excl') > 63
then hasnt_index(history_table_name, history_table_name || '_valid_range_excl', 'Index name to long: ' || history_table_name || '_valid_range_excl')
else collect_tap(
has_index(history_table_name, history_table_name || '_valid_range_excl', array['public_id', 'valid_range'])
) end;
$$ language sql;
-- tests to verify certain columns are not in the history table

@ -0,0 +1,38 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
select plan(16);
-- Verify the trigger functions exist and are declared properly
select has_function('insert_credential_static_history_subtype');
select volatility_is('insert_credential_static_history_subtype', 'volatile');
select isnt_strict('insert_credential_static_history_subtype');
select has_function('delete_credential_static_history_subtype');
select volatility_is('delete_credential_static_history_subtype', 'volatile');
select isnt_strict('delete_credential_static_history_subtype');
select has_trigger('credential_static_json_credential_hst', 'insert_credential_static_history_subtype');
select has_trigger('credential_static_json_credential_hst', 'delete_credential_static_history_subtype');
select fk_ok('credential_static_json_credential_hst', 'history_id', 'credential_static_history_base' , 'history_id');
select has_trigger('credential_static_username_password_credential_hst', 'insert_credential_static_history_subtype');
select has_trigger('credential_static_username_password_credential_hst', 'delete_credential_static_history_subtype');
select fk_ok('credential_static_username_password_credential_hst', 'history_id', 'credential_static_history_base' , 'history_id');
select has_trigger('credential_static_ssh_private_key_credential_hst', 'insert_credential_static_history_subtype');
select has_trigger('credential_static_ssh_private_key_credential_hst', 'delete_credential_static_history_subtype');
select fk_ok('credential_static_ssh_private_key_credential_hst', 'history_id', 'credential_static_history_base' , 'history_id');
select results_eq(
'select '
'(select count(*) from credential_static_json_credential_hst) + '
'(select count(*) from credential_static_username_password_credential_hst) + '
'(select count(*) from credential_static_ssh_private_key_credential_hst)',
'select count(*) from credential_static_history_base'
);
select * from finish();
rollback;

@ -26,7 +26,7 @@ begin;
insert into kms_data_key_version_destruction_job
(key_id)
values
('kdkv_______colors');
('kdkv__colors');
select lives_ok('insert_new_key_id', 'insert of valid key_id in kms_data_key_version_destruction_job failed');
-- Should fail when inserting an unknown table_name

Loading…
Cancel
Save