From 497c158b9da48bfd45b1a120e4dce2884cb7a5ea Mon Sep 17 00:00:00 2001 From: Johan Brandhorst-Satzkorn Date: Wed, 29 Nov 2023 16:44:59 -0800 Subject: [PATCH] internal/db: add migration for static credential table The static credential table is used rather than the credential table as all credentials returned by ListCredentials are static at this time. --- .../oss/postgres/46/01_credentials.up.sql | 1 + ...redential_static_base_table_updates.up.sql | 69 +++++++++++++++++++ .../sqltest/tests/pagination/credential.sql | 33 +++++++++ 3 files changed, 103 insertions(+) create mode 100644 internal/db/schema/migrations/oss/postgres/80/03_credential_static_base_table_updates.up.sql create mode 100644 internal/db/sqltest/tests/pagination/credential.sql diff --git a/internal/db/schema/migrations/oss/postgres/46/01_credentials.up.sql b/internal/db/schema/migrations/oss/postgres/46/01_credentials.up.sql index 0d46eba05..15cdcde21 100644 --- a/internal/db/schema/migrations/oss/postgres/46/01_credentials.up.sql +++ b/internal/db/schema/migrations/oss/postgres/46/01_credentials.up.sql @@ -97,6 +97,7 @@ begin; -- insert_credential_static_subtype() is a before insert trigger -- function for subtypes of credential_static -- Replaces the insert_credential_static_subtype function defined in 10/03_credential.up.sql + -- Replaced in 79/03_credential_static_base_table_updates.up.sql create or replace function insert_credential_static_subtype() returns trigger as $$ begin diff --git a/internal/db/schema/migrations/oss/postgres/80/03_credential_static_base_table_updates.up.sql b/internal/db/schema/migrations/oss/postgres/80/03_credential_static_base_table_updates.up.sql new file mode 100644 index 000000000..146199139 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/80/03_credential_static_base_table_updates.up.sql @@ -0,0 +1,69 @@ +-- Copyright (c) HashiCorp, Inc. +-- SPDX-License-Identifier: BUSL-1.1 + +begin; + + -- Add create_time and update_time to credential_static table. + alter table credential_static add column create_time wt_timestamp; + alter table credential_static add column update_time wt_timestamp; + + -- Update rows with current values + update credential_static + set create_time = csj.create_time, update_time = csj.update_time + from credential_static as cs + left join credential_static_json_credential as csj on cs.public_id = csj.public_id; + update credential_static + set create_time = cssshpk.create_time, update_time = cssshpk.update_time + from credential_static as cs + left join credential_static_ssh_private_key_credential as cssshpk on cs.public_id = cssshpk.public_id; + update credential_static + set create_time = csupw.create_time, update_time = csupw.update_time + from credential_static as cs + left join credential_static_username_password_credential as csupw on cs.public_id = csupw.public_id; + + -- Replace the insert trigger to also set the create_time + -- Replaces the insert_credential_static_subtype function defined in 46/01_credentials.up.sql + create or replace function insert_credential_static_subtype() returns trigger + as $$ + begin + select project_id into new.project_id + from credential_store + where credential_store.public_id = new.store_id; + + insert into credential_static + (public_id, store_id, project_id, create_time) + values + (new.public_id, new.store_id, new.project_id, new.create_time); + return new; + end; + $$ language plpgsql; + + -- Add trigger to update the new update_time column on every subtype update. + create function update_credential_static_table_update_time() returns trigger + as $$ + begin + update credential_static set update_time = now() where public_id = new.public_id; + return new; + end; + $$ language plpgsql; + comment on function update_credential_static_table_update_time() is + 'update_credential_static_table_update_time is used to automatically update the update_time ' + 'of the base table whenever one of the subtype tables are updated'; + + -- Add triggers to subtype tables + create trigger update_credential_static_table_update_time before update on credential_static_json_credential + for each row execute procedure update_credential_static_table_update_time(); + create trigger update_credential_static_table_update_time before update on credential_static_ssh_private_key_credential + for each row execute procedure update_credential_static_table_update_time(); + create trigger update_credential_static_table_update_time before update on credential_static_username_password_credential + for each row execute procedure update_credential_static_table_update_time(); + + -- Add new indexes for the create and update time queries. + create index credential_static_create_time_public_id_idx + on credential_static (create_time desc, public_id asc); + create index credential_static_update_time_public_id_idx + on credential_static (update_time desc, public_id asc); + + analyze credential_static; + +commit; diff --git a/internal/db/sqltest/tests/pagination/credential.sql b/internal/db/sqltest/tests/pagination/credential.sql new file mode 100644 index 000000000..d6728c2d8 --- /dev/null +++ b/internal/db/sqltest/tests/pagination/credential.sql @@ -0,0 +1,33 @@ +-- Copyright (c) HashiCorp, Inc. +-- SPDX-License-Identifier: BUSL-1.1 + +begin; + select plan(10); + + -- Verify the trigger functions exist and are declared properly + select has_function('update_credential_static_table_update_time'); + select volatility_is('update_credential_static_table_update_time', 'volatile'); + select isnt_strict('update_credential_static_table_update_time'); + select has_trigger('credential_static_json_credential', 'update_credential_static_table_update_time'); + select has_trigger('credential_static_ssh_private_key_credential', 'update_credential_static_table_update_time'); + select has_trigger('credential_static_username_password_credential', 'update_credential_static_table_update_time'); + select has_index('credential_static', 'credential_static_create_time_public_id_idx', array['create_time', 'public_id']); + select has_index('credential_static', 'credential_static_update_time_public_id_idx', array['update_time', 'public_id']); + + -- To test that the trigger that sets the create_time of the base table + -- when an insert into a subtype table happens works, we check that the + -- create time of the entries in both tables match + prepare credential_static_create_time as select create_time from credential_static where public_id='csj__bcolors'; + prepare credential_static_json_credential_create_time as select create_time from credential_static_json_credential where public_id='csj__bcolors'; + select results_eq('credential_static_create_time','credential_static_json_credential_create_time'); + -- To test the trigger that updates the update_time of the base table, + -- we update one of the existing creds and check that the base table + -- entry has the same update_time as the subtype one. + update credential_static_json_credential set name='Blue black json cred' where public_id='csj__bcolors'; + prepare credential_static_update_time as select update_time from credential_static where public_id='csj__bcolors'; + prepare credential_static_json_credential_update_time as select update_time from credential_static_json_credential where public_id='csj__bcolors'; + select results_eq('credential_static_update_time','credential_static_json_credential_update_time'); + + select * from finish(); + +rollback;