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.
This commit is contained in:
1 parent
386eac072c
commit
3a64fb3d58
5 files changed
+274
-15
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user