feat(sql): Add dynamic credential hst tables to session recording

This adds the `recording_dynamic_credential` join table and a trigger
that runs as an after insert on the `recording_session` table. The join
table joins the `recording_session`, `credential_vault_store_hst`,
`credential_library_history_base`, and the `credential_purpose_enm`
tables.
This commit is contained in:
Michael Gaffney authored and Timothy Messier committed 2023-05-31 12:18:19 +00:00
1 parent 3769f0851c
commit a783c91b2d
5 files changed
+178 -12

No files matched your search

@@ -0,0 +1,79 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
create table recording_dynamic_credential (
recording_id wt_public_id not null
constraint recording_session_fk
references recording_session (public_id)
on delete cascade
on update cascade,
credential_vault_store_hst_id wt_url_safe_id not null
constraint credential_vault_store_hst_fk
references credential_vault_store_hst (history_id)
on delete restrict -- History records with session recordings cannot be deleted
on update cascade,
credential_library_hst_id wt_url_safe_id not null
constraint credential_library_history_base_fk
references credential_library_history_base (history_id)
on delete restrict -- History records with session recordings cannot be deleted
on update cascade,
credential_purpose text not null
constraint credential_purpose_fkey
references credential_purpose_enm (name)
on delete restrict
on update cascade,
primary key(recording_id, credential_vault_store_hst_id, credential_library_hst_id, credential_purpose)
);
comment on table recording_dynamic_credential is
'recording_dynamic_credential table is a join table that associates a session recording with '
'a credential library, the credential library''s credential store, '
'and the purpose of the credential produced by the library '
'along with the values of those entities at the time of the recording. '
'These values are also stored in the BSR file.';
create function insert_recording_dynamic_credentials() returns trigger
as $$
begin
with
session_recording(session_id, recording_id) as (
select session_id, public_id
from recording_session
where session_id = new.session_id
),
session_dynamic_creds(library_id, purpose, recording_id) as (
select library_id, credential_purpose, recording_id
from session_credential_dynamic
join session_recording using (session_id)
),
library_history(public_id, store_id, library_hst_id, valid_range) as (
select public_id, store_id, history_id, valid_range
from credential_vault_library_hst
union
select public_id, store_id, history_id, valid_range
from credential_vault_ssh_cert_library_hst
),
final(recording_id, library_id, store_id, library_hst_id, store_hst_id, cred_purpose) as (
select sdc.recording_id, lib.public_id, lib.store_id, lib.library_hst_id, store_hst.history_id, sdc.purpose
from library_history as lib
join credential_vault_store_hst as store_hst on lib.store_id = store_hst.public_id
and store_hst.valid_range @> current_timestamp
join session_dynamic_creds as sdc on lib.public_id = sdc.library_id
where lib.public_id in (select library_id from session_dynamic_creds)
and lib.valid_range @> current_timestamp
)
insert into recording_dynamic_credential
(recording_id, credential_vault_store_hst_id, credential_library_hst_id, credential_purpose)
select recording_id, store_hst_id, library_hst_id, cred_purpose
from final;
return new;
end;
$$ language plpgsql;
comment on function insert_recording_dynamic_credentials is
'insert_recording_dynamic_credentials is an after insert trigger for the recording_session table.';
create trigger insert_recording_dynamic_credentials after insert on recording_session
for each row execute procedure insert_recording_dynamic_credentials();
commit;
@@ -440,6 +440,13 @@ begin;
('cvs__rcolors', 'cvl_______r1', 'red vault library', 'None', '/secrets', 'GET'),
('cvs__gcolors', 'cvl_______g1', 'green vault library', 'None', '/secrets', 'GET');
insert into credential_vault_ssh_cert_library
(store_id, public_id, name, vault_path, username, key_type, key_bits)
values
('cvs__bcolors', 'cvl__ssh__b1', 'blue vault ssh library', '/ssh/sign/blue', 'admin', 'ed25519', 0),
('cvs__rcolors', 'cvl__ssh__r1', 'red vault ssh library', '/ssh/issue/red', 'webdev', 'ecdsa', 521),
('cvs__gcolors', 'cvl__ssh__g1', 'green vault ssh library', '/ssh/issue/green', 'dba', 'rsa', 4096);
insert into credential_static_store
(project_id, public_id, name, description)
values
@@ -480,8 +487,10 @@ begin;
insert into target_credential_library
(project_id, target_id, credential_library_id, credential_purpose)
values
('p____bcolors', 't_________cb', 'cvl_______b1', 'brokered'),
('p____bcolors', 'tssh______cb', 'cvl_______b1', 'brokered');
('p____bcolors', 't_________cb', 'cvl_______b1', 'brokered'),
('p____bcolors', 'tssh______cb', 'cvl__ssh__b1', 'brokered'),
('p____gcolors', 'tssh______cg', 'cvl_______g1', 'brokered'),
('p____gcolors', 'tssh______cg', 'cvl__ssh__g1', 'injected_application');
insert into session
(project_id, target_id, public_id, user_id, auth_token_id, certificate, endpoint)
@@ -511,6 +520,12 @@ begin;
('s2______cora', 'csj__gcolors', 'brokered'), -- tssh______cg
('s2______cora', 'cspk_gcolors', 'injected_application'); -- tssh______cg
insert into session_credential_dynamic
(session_id, library_id, credential_purpose)
values
('s1______cora', 'cvl_______g1', 'brokered'), -- tssh______cg
('s1______cora', 'cvl__ssh__g1', 'injected_application'); -- tssh______cg
insert into session_host_set_host
(session_id, host_set_id, host_id)
values
@@ -0,0 +1,72 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
select plan(27);
select has_table('recording_dynamic_credential');
-- tests a fk column referencing a history table
-- add 5 to the plan for each time this function is called
create function hst_fk_column(column_name name, pk_table name) returns text
as $$
select * from collect_tap(
has_column('recording_dynamic_credential', column_name),
col_not_null('recording_dynamic_credential', column_name),
col_type_is('recording_dynamic_credential', column_name, 'wt_url_safe_id'), -- should be the same type as the operational table
col_hasnt_default('recording_dynamic_credential', column_name),
fk_ok('recording_dynamic_credential', column_name, pk_table, 'history_id')
);
$$ language sql;
select hst_fk_column('credential_vault_store_hst_id', 'credential_vault_store_hst');
select hst_fk_column('credential_library_hst_id', 'credential_library_history_base');
select has_column('recording_dynamic_credential', 'recording_id');
select col_not_null('recording_dynamic_credential', 'recording_id');
select col_type_is('recording_dynamic_credential', 'recording_id', 'wt_public_id'); -- should be the same type as the operational table
select col_hasnt_default('recording_dynamic_credential', 'recording_id');
select fk_ok('recording_dynamic_credential', 'recording_id', 'recording_session', 'public_id');
select has_column('recording_dynamic_credential', 'credential_purpose');
select col_not_null('recording_dynamic_credential', 'credential_purpose');
select col_type_is('recording_dynamic_credential', 'credential_purpose', 'text'); -- should be the same type as the operational table
select col_hasnt_default('recording_dynamic_credential', 'credential_purpose');
select fk_ok('recording_dynamic_credential', 'credential_purpose', 'credential_purpose_enm', 'name');
select col_is_pk('recording_dynamic_credential',
array['recording_id', 'credential_vault_store_hst_id', 'credential_library_hst_id', 'credential_purpose']);
prepare get_target_creds as
select credential_library_id, credential_purpose
from target_credential_library
where target_id = 'tssh______cg';
prepare get_session_creds as
select library_id, credential_purpose
from session_credential_dynamic
join session on session_id = public_id
where target_id = 'tssh______cg'
and session_id = 's1______cora';
select results_eq('get_target_creds', 'get_session_creds');
select is(count(*), 2::bigint)
from target_credential_library
where target_id = 'tssh______cg';
select is(count(*), 2::bigint)
from session_credential_dynamic
where session_id = 's1______cora';
select is(count(*), 1::bigint)
from recording_session
where session_id = 's1______cora'
and public_id = 'sr1_____cora';
select is(count(*), 2::bigint)
from recording_dynamic_credential
where recording_id = 'sr1_____cora';
select * from finish();
rollback;
@@ -6,10 +6,10 @@ begin;
select plan(6);
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'credentials');
-- ensure no existing dimensions or bridge table rows
select is(count(*), 0::bigint) from wh_credential_dimension where organization_id = 'o_____widget';
select is(count(*), 0::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 0::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select is(count(*), 2::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 1::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
--- insert single credential
insert into session
@@ -26,8 +26,8 @@ begin;
('s1____walter', 'vl______wvl1', null, 'brokered');
select is(count(*), 1::bigint) from wh_credential_dimension where organization_id = 'o_____widget';
select is(count(*), 1::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 1::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select is(count(*), 3::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 2::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select * from finish();
rollback;
@@ -6,10 +6,10 @@ begin;
select plan(6);
select wtt_load('widgets', 'iam', 'kms', 'auth', 'hosts', 'targets', 'credentials');
-- ensure no existing dimensions
select is(count(*), 0::bigint) from wh_credential_dimension where organization_id = 'o_____widget';
select is(count(*), 0::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 0::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select is(count(*), 2::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 1::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
--- multiple single credentials
insert into session
@@ -29,8 +29,8 @@ begin;
('s1____walter', 'vl______wvl3', null, 'injected_application');
select is(count(*), 4::bigint) from wh_credential_dimension where organization_id = 'o_____widget';
select is(count(*), 4::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 1::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select is(count(*), 6::bigint) from wh_credential_group_membership where credential_group_key != 'no credentials' and credential_group_key != 'Unknown';
select is(count(*), 2::bigint) from wh_credential_group where key != 'no credentials' and key != 'Unknown';
select * from finish();
rollback;