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

This adds the `recording_static_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_static_store_hst`,
`credential_static_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:18 +00:00
1 parent 3a64fb3d58
commit 06e4e46248
3 files changed
+179 -9

No files matched your search

@@ -0,0 +1,82 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
create table recording_static_credential (
recording_id wt_public_id not null
constraint recording_session_fk
references recording_session (public_id)
on delete cascade
on update cascade,
credential_static_store_hst_id wt_url_safe_id not null
constraint credential_static_store_hst_fk
references credential_static_store_hst (history_id)
on delete restrict -- History records with session recordings cannot be deleted
on update cascade,
credential_static_hst_id wt_url_safe_id not null
constraint credential_static_history_base_fk
references credential_static_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_static_store_hst_id, credential_static_hst_id, credential_purpose)
);
comment on table recording_static_credential is
'recording_static_credential table is a join table that associates a session recording with '
'a static credential, the static credential''s static credential store, and the credential''s purpose '
'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_static_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_static_creds(cred_id, purpose, recording_id) as (
select credential_static_id, credential_purpose, recording_id
from session_credential_static
join session_recording using (session_id)
),
static_cred_history(public_id, store_id, cred_hst_id, valid_range) as (
select public_id, store_id, history_id, valid_range
from credential_static_json_credential_hst
union
select public_id, store_id, history_id, valid_range
from credential_static_ssh_private_key_credential_hst
union
select public_id, store_id, history_id, valid_range
from credential_static_username_password_credential_hst
),
final(recording_id, cred_id, store_id, cred_hst_id, store_hst_id, cred_purpose) as (
select ssc.recording_id, sc.public_id, sc.store_id, sc.cred_hst_id, store_hst.history_id, ssc.purpose
from static_cred_history as sc
join credential_static_store_hst as store_hst on sc.store_id = store_hst.public_id
and store_hst.valid_range @> current_timestamp
join session_static_creds as ssc on sc.public_id = ssc.cred_id
where sc.public_id in (select cred_id from session_static_creds)
and sc.valid_range @> current_timestamp
)
insert into recording_static_credential
(recording_id, credential_static_store_hst_id, credential_static_hst_id, credential_purpose)
select recording_id, store_hst_id, cred_hst_id, cred_purpose
from final;
return new;
end;
$$ language plpgsql;
comment on function insert_recording_static_credentials is
'insert_recording_static_credentials is an after insert trigger for the recording_session table.';
create trigger insert_recording_static_credentials after insert on recording_session
for each row execute procedure insert_recording_static_credentials();
commit;
@@ -440,6 +440,7 @@ begin;
('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', 'csu__gcolors', 'brokered'),
('p____gcolors', 'tssh______cg', 'cspk_gcolors', 'injected_application');
insert into target_credential_library
@@ -449,16 +450,30 @@ begin;
('p____bcolors', 'tssh______cb', 'vl______cvl', 'brokered');
insert into session
(project_id, target_id, user_id, auth_token_id, certificate, endpoint, public_id)
values
('p____bcolors', 'tssh______cb', 'u______clare', 'tok____clare', 'abc'::bytea, 'ep1', 's1_____clare'),
('p____bcolors', 't_________cb', 'u______cindy', 'tok____cindy', 'abc'::bytea, 'ep1', 's1_____cindy'),
('p____bcolors', 't_________cb', 'u______cindy', 'tok____cindy', 'abc'::bytea, 'ep1', 's1_____ciara'),
('p____bcolors', 't_________cb', 'u______carly', 'tok____carly', 'abc'::bytea, 'ep1', 's1_____carly'),
('p____gcolors', 'tssh______cg', 'u_______cora', 'tok_____cora', 'abc'::bytea, 'ep1', 's1______cora'),
(project_id, target_id, public_id, user_id, auth_token_id, certificate, endpoint)
values
('p____bcolors', 'tssh______cb', 's1_____clare', 'u______clare', 'tok____clare', 'abc'::bytea, 'ep1'),
('p____bcolors', 't_________cb', 's1_____cindy', 'u______cindy', 'tok____cindy', 'abc'::bytea, 'ep1'),
('p____bcolors', 't_________cb', 's1_____ciara', 'u______cindy', 'tok____cindy', 'abc'::bytea, 'ep1'),
('p____bcolors', 't_________cb', 's1_____carly', 'u______carly', 'tok____carly', 'abc'::bytea, 'ep1'),
('p____gcolors', 'tssh______cg', 's1______cora', 'u_______cora', 'tok_____cora', 'abc'::bytea, 'ep1'),
--- the next two are used in recording_session tests
('p____bcolors', 'tssh______cb', 'u______clare', 'tok____clare', 'abc'::bytea, 'ep1', 's2_____clare'),
('p____gcolors', 'tssh______cg', 'u_______cora', 'tok_____cora', 'abc'::bytea, 'ep1', 's2______cora');
('p____bcolors', 'tssh______cb', 's2_____clare', 'u______clare', 'tok____clare', 'abc'::bytea, 'ep1'),
('p____gcolors', 'tssh______cg', 's2______cora', 'u_______cora', 'tok_____cora', 'abc'::bytea, 'ep1');
insert into session_credential_static
(session_id, credential_static_id, credential_purpose)
values
('s1_____clare', 'csj__bcolors', 'injected_application'), -- tssh______cb
('s2_____clare', 'csj__bcolors', 'injected_application'), -- tssh______cb
('s1_____cindy', 'csj__bcolors', 'brokered'), -- t_________cb
('s1_____ciara', 'csj__bcolors', 'brokered'), -- t_________cb
('s1_____carly', 'csj__bcolors', 'brokered'), -- t_________cb
('s1______cora', 'csj__gcolors', 'brokered'), -- tssh______cg
('s1______cora', 'csu__gcolors', 'brokered'), -- tssh______cg
('s1______cora', 'cspk_gcolors', 'injected_application'), -- tssh______cg
('s2______cora', 'csj__gcolors', 'brokered'), -- tssh______cg
('s2______cora', 'cspk_gcolors', 'injected_application'); -- tssh______cg
insert into session_host_set_host
(session_id, host_set_id, host_id)
@@ -0,0 +1,73 @@
-- Copyright (c) HashiCorp, Inc.
-- SPDX-License-Identifier: MPL-2.0
begin;
select plan(27);
select has_table('recording_static_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_static_credential', column_name),
col_not_null('recording_static_credential', column_name),
col_type_is('recording_static_credential', column_name, 'wt_url_safe_id'), -- should be the same type as the operational table
col_hasnt_default('recording_static_credential', column_name),
fk_ok('recording_static_credential', column_name, pk_table, 'history_id')
);
$$ language sql;
select hst_fk_column('credential_static_store_hst_id', 'credential_static_store_hst');
select hst_fk_column('credential_static_hst_id', 'credential_static_history_base');
select has_column('recording_static_credential', 'recording_id');
select col_not_null('recording_static_credential', 'recording_id');
select col_type_is('recording_static_credential', 'recording_id', 'wt_public_id'); -- should be the same type as the operational table
select col_hasnt_default('recording_static_credential', 'recording_id');
select fk_ok('recording_static_credential', 'recording_id', 'recording_session', 'public_id');
select has_column('recording_static_credential', 'credential_purpose');
select col_not_null('recording_static_credential', 'credential_purpose');
select col_type_is('recording_static_credential', 'credential_purpose', 'text'); -- should be the same type as the operational table
select col_hasnt_default('recording_static_credential', 'credential_purpose');
select fk_ok('recording_static_credential', 'credential_purpose', 'credential_purpose_enm', 'name');
select col_is_pk('recording_static_credential',
array['recording_id', 'credential_static_store_hst_id', 'credential_static_hst_id', 'credential_purpose']);
-- 22
prepare get_target_creds as
select credential_static_id, credential_purpose
from target_static_credential
where target_id = 'tssh______cg';
prepare get_session_creds as
select credential_static_id, credential_purpose
from session_credential_static
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(*), 3::bigint)
from target_static_credential
where target_id = 'tssh______cg';
select is(count(*), 3::bigint)
from session_credential_static
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(*), 3::bigint)
from recording_static_credential
where recording_id = 'sr1_____cora';
select * from finish();
rollback;