From 2a4f0d876d06c4248f532895595e5632800fbe82 Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Thu, 27 Jun 2024 12:32:28 +0100 Subject: [PATCH] Renamed master key to principal key (#228) This commit contains lots of changes, but it's just a repeated execution of find <...> -exec sed <...>, so everything should work as before. --- .../postgresql-16-src-meson-perf.yml | 2 +- Makefile.in | 2 +- README.md | 10 +- documentation/docs/functions.md | 22 +- .../docs/release-notes/release-notes.md | 2 +- documentation/docs/setup.md | 4 +- documentation/docs/tde.md | 8 +- documentation/docs/test.md | 6 +- expected/change_access_method.out | 6 +- expected/insert_update_delete.out | 6 +- expected/keyprovider_dependency.out | 8 +- expected/move_large_tuples.out | 6 +- expected/multi_insert.out | 6 +- expected/non_sorted_off_compact.out | 6 +- expected/pgtde_is_encrypted.out | 22 +- expected/test_issue_153_fix.out | 12 +- expected/toast_decrypt.out | 6 +- expected/toast_extended_storage.out | 6 +- expected/trigger_on_view.out | 6 +- expected/update_compare_indexes.out | 6 +- expected/vault_v2_test.out | 6 +- meson.build | 2 +- pg_tde--1.0.sql | 14 +- sql/change_access_method.sql | 2 +- sql/insert_update_delete.sql | 2 +- sql/keyprovider_dependency.sql | 2 +- sql/move_large_tuples.sql | 2 +- sql/multi_insert.sql | 2 +- sql/non_sorted_off_compact.sql | 2 +- sql/pgtde_is_encrypted.sql | 8 +- sql/test_issue_153_fix.sql | 4 +- sql/toast_decrypt.sql | 2 +- sql/toast_extended_storage.sql | 2 +- sql/trigger_on_view.sql | 2 +- sql/update_compare_indexes.sql | 2 +- sql/vault_v2_test.sql | 2 +- src/access/pg_tde_tdemap.c | 262 +++--- src/access/pg_tde_xlog.c | 38 +- src/catalog/tde_global_catalog.c | 58 +- src/catalog/tde_keyring.c | 16 +- src/catalog/tde_master_key.c | 825 ------------------ src/catalog/tde_principal_key.c | 825 ++++++++++++++++++ src/common/pg_tde_shmem.c | 8 +- src/encryption/enc_tde.c | 12 +- src/include/access/pg_tde_tdemap.h | 18 +- src/include/access/pg_tde_xlog.h | 4 +- src/include/catalog/tde_global_catalog.h | 6 +- src/include/catalog/tde_master_key.h | 84 -- src/include/catalog/tde_principal_key.h | 84 ++ src/include/encryption/enc_tde.h | 4 +- src/pg_tde.c | 4 +- src/smgr/pg_tde_smgr.c | 4 +- t/001_basic.pl | 2 +- t/002_rotate_key.pl | 6 +- t/003_remote_config.pl | 2 +- t/004_file_config.pl | 2 +- t/expected/002_rotate_key.out | 2 +- 57 files changed, 1237 insertions(+), 1237 deletions(-) delete mode 100644 src/catalog/tde_master_key.c create mode 100644 src/catalog/tde_principal_key.c delete mode 100644 src/include/catalog/tde_master_key.h create mode 100644 src/include/catalog/tde_principal_key.h diff --git a/.github/workflows/postgresql-16-src-meson-perf.yml b/.github/workflows/postgresql-16-src-meson-perf.yml index 7f529e73..56f9949a 100644 --- a/.github/workflows/postgresql-16-src-meson-perf.yml +++ b/.github/workflows/postgresql-16-src-meson-perf.yml @@ -91,7 +91,7 @@ jobs: bin/createuser sbtest -s bin/psql sbtest2 <<< "CREATE EXTENSION pg_tde;" bin/psql sbtest2 <<< "SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per');" - bin/psql sbtest2 <<< "SELECT pg_tde_set_master_key('test-db-master-key','file-vault');" + bin/psql sbtest2 <<< "SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault');" cp -r ../src/contrib/pg_tde/sysbench . working-directory: inst diff --git a/Makefile.in b/Makefile.in index 8413cabd..e3a32a3a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -44,7 +44,7 @@ src/keyring/keyring_vault.o \ src/keyring/keyring_api.o \ src/catalog/tde_global_catalog.o \ src/catalog/tde_keyring.o \ -src/catalog/tde_master_key.o \ +src/catalog/tde_principal_key.o \ src/common/pg_tde_shmem.o \ src/common/pg_tde_utils.o \ src/smgr/pg_tde_smgr.o \ diff --git a/README.md b/README.md index 07c3ef24..5deacc03 100644 --- a/README.md +++ b/README.md @@ -65,15 +65,15 @@ FUNCTION pg_tde_add_key_provider_file( SELECT pg_tde_add_key_provider_file('file','/tmp/pgkeyring'); ``` **Note: The `File` provided is intended for development and stores the keys unencrypted in the specified data file.** -6. Set the master key for the database using the `pg_tde_set_master_key` function. +6. Set the principal key for the database using the `pg_tde_set_principal_key` function. ```sql -FUNCTION pg_tde_set_master_key ( - master_key_name VARCHAR(255), +FUNCTION pg_tde_set_principal_key ( + principal_key_name VARCHAR(255), provider_name VARCHAR(255)); ``` -**Example**: Set the master key named `my-master-key` using the `file` as a key provider. +**Example**: Set the principal key named `my-principal-key` using the `file` as a key provider. ```sql -SELECT pg_tde_set_master_key('my-master-key','file'); +SELECT pg_tde_set_principal_key('my-principal-key','file'); ``` 7. You are all set to create encrypted tables. For that, specify `USING pg_tde` in the `CREATE TABLE` statement. diff --git a/documentation/docs/functions.md b/documentation/docs/functions.md index b3089a19..fa59cf38 100644 --- a/documentation/docs/functions.md +++ b/documentation/docs/functions.md @@ -33,24 +33,24 @@ where: All parameters can be either strings, or JSON objects [referencing remote parameters](external-parameters.md). -## pg_tde_set_master_key +## pg_tde_set_principal_key -Sets the master key for the database using the specified key provider. +Sets the principal key for the database using the specified key provider. -The master key name is also used for constructing the name in the provider, for example on the remote Vault server. +The principal key name is also used for constructing the name in the provider, for example on the remote Vault server. -You can use this function only to a master key. For changes in the master key, use the [`pg_tde_rotate_key`](#pg_tde_rotate_key) function. +You can use this function only to a principal key. For changes in the principal key, use the [`pg_tde_rotate_key`](#pg_tde_rotate_key) function. ```sql -SELECT pg_tde_set_master_key('name-of-the-master-key', 'provider-name'); +SELECT pg_tde_set_principal_key('name-of-the-principal-key', 'provider-name'); ``` ## pg_tde_rotate_key -Creates a new version of the specified master key and updates the database so that it uses the new master key version. +Creates a new version of the specified principal key and updates the database so that it uses the new principal key version. When used without any parameters, the function will just create a new version of the current database -master key, using the same provider: +principal key, using the same provider: ```sql SELECT pg_tde_rotate_key(); @@ -59,16 +59,16 @@ SELECT pg_tde_rotate_key(); Alternatively, you can pass two parameters to the function, specifying both a new key name and a new provider name: ```sql -SELECT pg_tde_rotate_key('name-of-the-new-master-key', 'name-of-the-new-provider'); +SELECT pg_tde_rotate_key('name-of-the-new-principal-key', 'name-of-the-new-provider'); ``` Both parameters support the `NULL` value, which means that the parameter won't be changed: ```sql --- creates new master key on the same provider as before -SELECT pg_tde_rotate_key('name-of-the-new-master-key', NULL); +-- creates new principal key on the same provider as before +SELECT pg_tde_rotate_key('name-of-the-new-principal-key', NULL); --- copies the current master key to a new provider +-- copies the current principal key to a new provider SELECT pg_tde_rotate_key(NULL, 'name-of-the-new-provider'); ``` diff --git a/documentation/docs/release-notes/release-notes.md b/documentation/docs/release-notes/release-notes.md index 90771615..767ae6df 100644 --- a/documentation/docs/release-notes/release-notes.md +++ b/documentation/docs/release-notes/release-notes.md @@ -10,7 +10,7 @@ The technical preview of the extension introduces the following key features: -* You can now rotate master keys used for data encryption. This reduces the risk of long-term exposure to potential attacks and helps you comply with security standards such as GDPR, HIPAA, and PCI DSS. +* You can now rotate principal keys used for data encryption. This reduces the risk of long-term exposure to potential attacks and helps you comply with security standards such as GDPR, HIPAA, and PCI DSS. * You can now configure encryption differently for each database. For example, encrypt specific tables in some databases with different encryption keys while keeping others non-encrypted. diff --git a/documentation/docs/setup.md b/documentation/docs/setup.md index daf39f40..04be1c59 100644 --- a/documentation/docs/setup.md +++ b/documentation/docs/setup.md @@ -63,10 +63,10 @@ Load the `pg_tde` at the start time. The extension requires additional shared me ``` -5. Add a master key +5. Add a principal key ```sql - SELECT pg_tde_set_master_key('name-of-the-master-key', 'provider-name'); + SELECT pg_tde_set_principal_key('name-of-the-principal-key', 'provider-name'); ``` :material-information: Info: The key provider configuration is stored in the database catalog in an unencrypted table. See [how to use external reference to parameters](external-parameters.md) to add an extra security layer to your setup. diff --git a/documentation/docs/tde.md b/documentation/docs/tde.md index 9da5d4b5..bd90b958 100644 --- a/documentation/docs/tde.md +++ b/documentation/docs/tde.md @@ -7,9 +7,9 @@ Transparent Data Encryption offers encryption at the file level and solves the p To encrypt the data, two types of keys are used: * Database keys to encrypt user data. These are stored internally, near the data that they encrypt. -* The master key to encrypt database keys. It is kept separately from the database keys and is managed externally. +* The principal key to encrypt database keys. It is kept separately from the database keys and is managed externally. -`pg_tde` is integrated with HashiCorp Vault server to store and manage master keys. Only the back end KV Secrets Engine - Version 2 (API) is supported. +`pg_tde` is integrated with HashiCorp Vault server to store and manage principal keys. Only the back end KV Secrets Engine - Version 2 (API) is supported. The encryption process is the following: @@ -17,9 +17,9 @@ The encryption process is the following: When a user creates an encrypted table using `pg_tde`, a new random key is generated for that table. This key is used to encrypt all data the user inserts in that table. Eventually the encrypted data gets stored in the underlying storage. -The table itself is encrypted using the master key. The master key is stored externally in the Vault key management store. +The table itself is encrypted using the principal key. The principal key is stored externally in the Vault key management store. -Similarly when the user queries the encrypted table, the master key is retrieved from the key store to decrypt the table. Then the same unique internal key for that table is used to decrypt the data, and unencrypted data gets returned to the user. So, effectively, every TDE table has a unique key, and each table key is encrypted using the master key. +Similarly when the user queries the encrypted table, the principal key is retrieved from the key store to decrypt the table. Then the same unique internal key for that table is used to decrypt the data, and unencrypted data gets returned to the user. So, effectively, every TDE table has a unique key, and each table key is encrypted using the principal key. ## Why do you need TDE? diff --git a/documentation/docs/test.md b/documentation/docs/test.md index 628e1922..81f2bdbe 100644 --- a/documentation/docs/test.md +++ b/documentation/docs/test.md @@ -24,12 +24,12 @@ To check if the data is encrypted, do the following: The function returns `t` if the table is encrypted and `f` - if not. -3. Rotate the master key when needed: +3. Rotate the principal key when needed: ```sql SELECT pg_tde_rotate_key(); -- uses automatic key versionin -- or - SELECT pg_tde_rotate_key('new-master-key', NULL); -- specify new key name + SELECT pg_tde_rotate_key('new-principal-key', NULL); -- specify new key name -- or - SELECT pg_tde_rotate_key('new-master-key', 'new-provider'); -- change provider + SELECT pg_tde_rotate_key('new-principal-key', 'new-provider'); -- change provider ``` \ No newline at end of file diff --git a/expected/change_access_method.out b/expected/change_access_method.out index 3583884c..5a7436cb 100644 --- a/expected/change_access_method.out +++ b/expected/change_access_method.out @@ -5,9 +5,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/insert_update_delete.out b/expected/insert_update_delete.out index 956e0a24..8013c86a 100644 --- a/expected/insert_update_delete.out +++ b/expected/insert_update_delete.out @@ -5,9 +5,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/keyprovider_dependency.out b/expected/keyprovider_dependency.out index 33cd8b0d..ea5eec97 100644 --- a/expected/keyprovider_dependency.out +++ b/expected/keyprovider_dependency.out @@ -17,16 +17,16 @@ SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/va 3 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','mk-file'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file'); + pg_tde_set_principal_key +-------------------------- t (1 row) -- Try dropping the in-use key provider DELETE FROM percona_tde.pg_tde_key_provider WHERE provider_name = 'mk-file'; -- Should fail ERROR: Key provider "mk-file" cannot be deleted -DETAIL: The master key for the database depends on this key provider. +DETAIL: The principal key for the database depends on this key provider. -- Now delete the un-used key provider DELETE FROM percona_tde.pg_tde_key_provider WHERE provider_name = 'free-file'; -- Should pass DELETE FROM percona_tde.pg_tde_key_provider WHERE provider_name = 'V2-vault'; -- Should pass diff --git a/expected/move_large_tuples.out b/expected/move_large_tuples.out index 780d9c67..da7a0b9c 100644 --- a/expected/move_large_tuples.out +++ b/expected/move_large_tuples.out @@ -6,9 +6,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/multi_insert.out b/expected/multi_insert.out index 11f5ea56..322a8795 100644 --- a/expected/multi_insert.out +++ b/expected/multi_insert.out @@ -7,9 +7,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/non_sorted_off_compact.out b/expected/non_sorted_off_compact.out index 972d7e84..c9c5120f 100644 --- a/expected/non_sorted_off_compact.out +++ b/expected/non_sorted_off_compact.out @@ -7,9 +7,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/pgtde_is_encrypted.out b/expected/pgtde_is_encrypted.out index f0b1642a..0a156dcc 100644 --- a/expected/pgtde_is_encrypted.out +++ b/expected/pgtde_is_encrypted.out @@ -1,16 +1,16 @@ CREATE EXTENSION pg_tde; -SELECT * FROM pg_tde_master_key_info(); -ERROR: Master key does not exists for the database -HINT: Use set_master_key interface to set the master key +SELECT * FROM pg_tde_principal_key_info(); +ERROR: Principal key does not exists for the database +HINT: Use set_principal_key interface to set the principal key SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); pg_tde_add_key_provider_file ------------------------------ 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) @@ -48,11 +48,11 @@ SELECT pgtde_is_encrypted('test_norm'); f (1 row) -SELECT key_provider_id, key_provider_name, master_key_name - FROM pg_tde_master_key_info(); - key_provider_id | key_provider_name | master_key_name ------------------+-------------------+-------------------- - 1 | file-vault | test-db-master-key +SELECT key_provider_id, key_provider_name, principal_key_name + FROM pg_tde_principal_key_info(); + key_provider_id | key_provider_name | principal_key_name +-----------------+-------------------+----------------------- + 1 | file-vault | test-db-principal-key (1 row) DROP TABLE test_enc; diff --git a/expected/test_issue_153_fix.out b/expected/test_issue_153_fix.out index 8a5150e8..b6fe4382 100644 --- a/expected/test_issue_153_fix.out +++ b/expected/test_issue_153_fix.out @@ -1,17 +1,17 @@ CREATE EXTENSION pg_tde; SET datestyle TO 'iso, dmy'; -SELECT * FROM pg_tde_master_key_info(); -ERROR: Master key does not exists for the database -HINT: Use set_master_key interface to set the master key +SELECT * FROM pg_tde_principal_key_info(); +ERROR: Principal key does not exists for the database +HINT: Use set_principal_key interface to set the principal key SELECT pg_tde_add_key_provider_file('file-ring','/tmp/pg_tde_test_keyring.per'); pg_tde_add_key_provider_file ------------------------------ 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-ring'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-ring'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/toast_decrypt.out b/expected/toast_decrypt.out index 06907dc3..16c3a31a 100644 --- a/expected/toast_decrypt.out +++ b/expected/toast_decrypt.out @@ -5,9 +5,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/toast_extended_storage.out b/expected/toast_extended_storage.out index 9ec47e91..cc1513ae 100644 --- a/expected/toast_extended_storage.out +++ b/expected/toast_extended_storage.out @@ -6,9 +6,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/trigger_on_view.out b/expected/trigger_on_view.out index 6750c603..88bb7125 100644 --- a/expected/trigger_on_view.out +++ b/expected/trigger_on_view.out @@ -5,9 +5,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/update_compare_indexes.out b/expected/update_compare_indexes.out index c84d297e..918fb7c9 100644 --- a/expected/update_compare_indexes.out +++ b/expected/update_compare_indexes.out @@ -5,9 +5,9 @@ SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per') 1 (1 row) -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/expected/vault_v2_test.out b/expected/vault_v2_test.out index 4eec680d..9429c0ea 100644 --- a/expected/vault_v2_test.out +++ b/expected/vault_v2_test.out @@ -6,9 +6,9 @@ SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0 1 (1 row) -SELECT pg_tde_set_master_key('vault-v2-master-key','vault-v2'); - pg_tde_set_master_key ------------------------ +SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-v2'); + pg_tde_set_principal_key +-------------------------- t (1 row) diff --git a/meson.build b/meson.build index a339d13d..98b43425 100644 --- a/meson.build +++ b/meson.build @@ -43,7 +43,7 @@ pg_tde_sources = files( 'src/catalog/tde_global_catalog.c', 'src/catalog/tde_keyring.c', - 'src/catalog/tde_master_key.c', + 'src/catalog/tde_principal_key.c', 'src/common/pg_tde_shmem.c', 'src/common/pg_tde_utils.c', 'src/pg_tde_defs.c', diff --git a/pg_tde--1.0.sql b/pg_tde--1.0.sql index 9d43e98a..81e5f6d2 100644 --- a/pg_tde--1.0.sql +++ b/pg_tde--1.0.sql @@ -17,7 +17,7 @@ CREATE TABLE percona_tde.pg_tde_key_provider(provider_id SERIAL, SELECT pg_catalog.pg_extension_config_dump('percona_tde.pg_tde_key_provider', ''); --- Trigger function to check master key dependency on key provider row +-- Trigger function to check principal key dependency on key provider row CREATE FUNCTION keyring_delete_dependency_check_trigger() RETURNS TRIGGER AS 'MODULE_PATHNAME' @@ -104,12 +104,12 @@ SELECT EXISTS ( )$$ LANGUAGE SQL; -CREATE FUNCTION pg_tde_rotate_key(new_master_key_name VARCHAR(255) DEFAULT NULL, new_provider_name VARCHAR(255) DEFAULT NULL, ensure_new_key BOOLEAN DEFAULT TRUE) +CREATE FUNCTION pg_tde_rotate_key(new_principal_key_name VARCHAR(255) DEFAULT NULL, new_provider_name VARCHAR(255) DEFAULT NULL, ensure_new_key BOOLEAN DEFAULT TRUE) RETURNS boolean AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION pg_tde_set_master_key(master_key_name VARCHAR(255), provider_name VARCHAR(255), ensure_new_key BOOLEAN DEFAULT FALSE) +CREATE FUNCTION pg_tde_set_principal_key(principal_key_name VARCHAR(255), provider_name VARCHAR(255), ensure_new_key BOOLEAN DEFAULT FALSE) RETURNS boolean AS 'MODULE_PATHNAME' LANGUAGE C; @@ -119,12 +119,12 @@ RETURNS VOID AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION pg_tde_master_key_info() -RETURNS TABLE ( master_key_name text, +CREATE FUNCTION pg_tde_principal_key_info() +RETURNS TABLE ( principal_key_name text, key_provider_name text, key_provider_id integer, - master_key_internal_name text, - master_key_version integer, + principal_key_internal_name text, + principal_key_version integer, key_createion_time timestamp with time zone) AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/sql/change_access_method.sql b/sql/change_access_method.sql index 456e9dd9..48e756df 100644 --- a/sql/change_access_method.sql +++ b/sql/change_access_method.sql @@ -1,7 +1,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE country_table ( country_id serial primary key, diff --git a/sql/insert_update_delete.sql b/sql/insert_update_delete.sql index 505131f3..633bfbf1 100644 --- a/sql/insert_update_delete.sql +++ b/sql/insert_update_delete.sql @@ -1,7 +1,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE albums ( id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, diff --git a/sql/keyprovider_dependency.sql b/sql/keyprovider_dependency.sql index c58f3454..40fb59f8 100644 --- a/sql/keyprovider_dependency.sql +++ b/sql/keyprovider_dependency.sql @@ -4,7 +4,7 @@ SELECT pg_tde_add_key_provider_file('mk-file','/tmp/pg_tde_test_keyring.per'); SELECT pg_tde_add_key_provider_file('free-file','/tmp/pg_tde_test_keyring_2.per'); SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/vault-v2/percona','/mount/dev','ca-cert-auth'); -SELECT pg_tde_set_master_key('test-db-master-key','mk-file'); +SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file'); -- Try dropping the in-use key provider DELETE FROM percona_tde.pg_tde_key_provider WHERE provider_name = 'mk-file'; -- Should fail diff --git a/sql/move_large_tuples.sql b/sql/move_large_tuples.sql index ae168c12..07d630f3 100644 --- a/sql/move_large_tuples.sql +++ b/sql/move_large_tuples.sql @@ -2,7 +2,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE sbtest2( id SERIAL, diff --git a/sql/multi_insert.sql b/sql/multi_insert.sql index 8d1f257c..94166139 100644 --- a/sql/multi_insert.sql +++ b/sql/multi_insert.sql @@ -3,7 +3,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE albums ( album_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, diff --git a/sql/non_sorted_off_compact.sql b/sql/non_sorted_off_compact.sql index f58bbc23..0412a6f1 100644 --- a/sql/non_sorted_off_compact.sql +++ b/sql/non_sorted_off_compact.sql @@ -3,7 +3,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); DROP TABLE IF EXISTS sbtest1; CREATE TABLE sbtest1( diff --git a/sql/pgtde_is_encrypted.sql b/sql/pgtde_is_encrypted.sql index 95b646a8..c897209d 100644 --- a/sql/pgtde_is_encrypted.sql +++ b/sql/pgtde_is_encrypted.sql @@ -1,9 +1,9 @@ CREATE EXTENSION pg_tde; -SELECT * FROM pg_tde_master_key_info(); +SELECT * FROM pg_tde_principal_key_info(); SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE test_enc( id SERIAL, @@ -23,8 +23,8 @@ SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE SELECT pgtde_is_encrypted('test_enc'); SELECT pgtde_is_encrypted('test_norm'); -SELECT key_provider_id, key_provider_name, master_key_name - FROM pg_tde_master_key_info(); +SELECT key_provider_id, key_provider_name, principal_key_name + FROM pg_tde_principal_key_info(); DROP TABLE test_enc; DROP TABLE test_norm; diff --git a/sql/test_issue_153_fix.sql b/sql/test_issue_153_fix.sql index 17a665a0..74d70dcd 100644 --- a/sql/test_issue_153_fix.sql +++ b/sql/test_issue_153_fix.sql @@ -1,10 +1,10 @@ CREATE EXTENSION pg_tde; SET datestyle TO 'iso, dmy'; -SELECT * FROM pg_tde_master_key_info(); +SELECT * FROM pg_tde_principal_key_info(); SELECT pg_tde_add_key_provider_file('file-ring','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-ring'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-ring'); -- -- Script that creates the 'sample' tde encrypted tables, views diff --git a/sql/toast_decrypt.sql b/sql/toast_decrypt.sql index efd727ad..f4cafaf5 100644 --- a/sql/toast_decrypt.sql +++ b/sql/toast_decrypt.sql @@ -1,7 +1,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TABLE src (f1 TEXT STORAGE EXTERNAL) USING pg_tde; INSERT INTO src VALUES(repeat('abcdeF',1000)); diff --git a/sql/toast_extended_storage.sql b/sql/toast_extended_storage.sql index 4153ff43..6ca0de26 100644 --- a/sql/toast_extended_storage.sql +++ b/sql/toast_extended_storage.sql @@ -2,7 +2,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); CREATE TEMP TABLE src (f1 text) USING pg_tde; -- Crash on INSERT diff --git a/sql/trigger_on_view.sql b/sql/trigger_on_view.sql index 7b2048f7..eb955484 100644 --- a/sql/trigger_on_view.sql +++ b/sql/trigger_on_view.sql @@ -1,7 +1,7 @@ CREATE extension pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); -- -- 2 -- Test triggers on a join view diff --git a/sql/update_compare_indexes.sql b/sql/update_compare_indexes.sql index 012bf56b..862b9558 100644 --- a/sql/update_compare_indexes.sql +++ b/sql/update_compare_indexes.sql @@ -1,7 +1,7 @@ CREATE EXTENSION pg_tde; SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); -SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); +SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault'); DROP TABLE IF EXISTS pvactst; CREATE TABLE pvactst (i INT, a INT[], p POINT) USING pg_tde; diff --git a/sql/vault_v2_test.sql b/sql/vault_v2_test.sql index a2be5af5..94c5d596 100644 --- a/sql/vault_v2_test.sql +++ b/sql/vault_v2_test.sql @@ -2,7 +2,7 @@ CREATE EXTENSION pg_tde; \getenv root_token ROOT_TOKEN SELECT pg_tde_add_key_provider_vault_v2('vault-v2',:'root_token','http://127.0.0.1:8200','secret',NULL); -SELECT pg_tde_set_master_key('vault-v2-master-key','vault-v2'); +SELECT pg_tde_set_principal_key('vault-v2-principal-key','vault-v2'); CREATE TABLE test_enc( id SERIAL, diff --git a/src/access/pg_tde_tdemap.c b/src/access/pg_tde_tdemap.c index e424b83f..e2ed4465 100644 --- a/src/access/pg_tde_tdemap.c +++ b/src/access/pg_tde_tdemap.c @@ -25,7 +25,7 @@ #include "access/pg_tde_tdemap.h" #include "access/pg_tde_xlog.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" #include "encryption/enc_aes.h" #include "encryption/enc_tde.h" #include "keyring/keyring_api.h" @@ -63,7 +63,7 @@ typedef struct TDEFileHeader { int32 file_version; - TDEMasterKeyInfo master_key_info; + TDEPrincipalKeyInfo principal_key_info; } TDEFileHeader; typedef struct TDEMapEntry @@ -80,23 +80,23 @@ typedef struct TDEMapFilePath } TDEMapFilePath; static int pg_tde_open_file_basic(char *tde_filename, int fileFlags, bool ignore_missing); -static int pg_tde_file_header_write(char *tde_filename, int fd, TDEMasterKeyInfo *master_key_info, off_t *bytes_written); +static int pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *principal_key_info, off_t *bytes_written); static int pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool *is_new_file, off_t *bytes_read); -static int pg_tde_open_file(char *tde_filename, TDEMasterKeyInfo *master_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *offset); +static int pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *offset); -static int32 pg_tde_write_map_entry(const RelFileLocator *rlocator, char *db_map_path, TDEMasterKeyInfo *master_key_info); +static int32 pg_tde_write_map_entry(const RelFileLocator *rlocator, char *db_map_path, TDEPrincipalKeyInfo *principal_key_info); static off_t pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, int32 key_index, TDEMapEntry *map_entry, off_t *offset); static int32 pg_tde_process_map_entry(const RelFileLocator *rlocator, char *db_map_path, off_t *offset, bool should_delete); static bool pg_tde_read_one_map_entry(int fd, const RelFileLocator *rlocator, int flags, TDEMapEntry *map_entry, off_t *offset); -static void pg_tde_write_keydata(char *db_keydata_path, TDEMasterKeyInfo *master_key_info, int32 key_index, RelKeyData *enc_rel_key_data); +static void pg_tde_write_keydata(char *db_keydata_path, TDEPrincipalKeyInfo *principal_key_info, int32 key_index, RelKeyData *enc_rel_key_data); static void pg_tde_write_one_keydata(int keydata_fd, int32 key_index, RelKeyData *enc_rel_key_data); static RelKeyData* pg_tde_get_key_from_file(const RelFileLocator *rlocator, GenericKeyring *keyring); -static RelKeyData* pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEMasterKey *master_key); -static RelKeyData* pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_key); +static RelKeyData* pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *principal_key); +static RelKeyData* pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *principal_key); -static int keyrotation_init_file(TDEMasterKeyInfo *new_master_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos); +static int keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos); static void finalize_key_rotation(char *m_path_old, char *k_path_old, char *m_path_new, char *k_path_new); /* @@ -108,14 +108,14 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator) InternalKey int_key; RelKeyData *rel_key_data; RelKeyData *enc_rel_key_data; - TDEMasterKey *master_key; + TDEPrincipalKey *principal_key; XLogRelKey xlrec; - master_key = GetMasterKey(newrlocator->dbOid, newrlocator->spcOid, NULL); - if (master_key == NULL) + principal_key = GetPrincipalKey(newrlocator->dbOid, newrlocator->spcOid, NULL); + if (principal_key == NULL) { ereport(ERROR, - (errmsg("failed to retrieve master key"))); + (errmsg("failed to retrieve principal key"))); return NULL; } @@ -133,8 +133,8 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator) } /* Encrypt the key */ - rel_key_data = tde_create_rel_key(newrlocator->relNumber, &int_key, &master_key->keyInfo); - enc_rel_key_data = tde_encrypt_rel_key(master_key, rel_key_data, newrlocator); + rel_key_data = tde_create_rel_key(newrlocator->relNumber, &int_key, &principal_key->keyInfo); + enc_rel_key_data = tde_encrypt_rel_key(principal_key, rel_key_data, newrlocator); /* * XLOG internal key @@ -149,7 +149,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator) /* * Add the encyrpted key to the key map data file structure. */ - pg_tde_write_key_map_entry(newrlocator, enc_rel_key_data, &master_key->keyInfo); + pg_tde_write_key_map_entry(newrlocator, enc_rel_key_data, &principal_key->keyInfo); return rel_key_data; } @@ -226,13 +226,13 @@ tde_sprint_key(InternalKey *k) * created key. */ RelKeyData * -tde_create_rel_key(Oid rel_id, InternalKey *key, TDEMasterKeyInfo *master_key_info) +tde_create_rel_key(Oid rel_id, InternalKey *key, TDEPrincipalKeyInfo *principal_key_info) { RelKeyData *rel_key_data; rel_key_data = (RelKeyData *) MemoryContextAlloc(TopMemoryContext, sizeof(RelKeyData)); - memcpy(&rel_key_data->master_key_id, &master_key_info->keyId, sizeof(TDEMasterKeyId)); + memcpy(&rel_key_data->principal_key_id, &principal_key_info->keyId, sizeof(TDEPrincipalKeyId)); memcpy(&rel_key_data->internal_key, key, sizeof(InternalKey)); rel_key_data->internal_key.ctx = NULL; @@ -246,12 +246,12 @@ tde_create_rel_key(Oid rel_id, InternalKey *key, TDEMasterKeyInfo *master_key_in * Encrypts a given key and returns the encrypted one. */ RelKeyData * -tde_encrypt_rel_key(TDEMasterKey *master_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator) +tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator) { RelKeyData *enc_rel_key_data; size_t enc_key_bytes; - AesEncryptKey(master_key, rlocator, rel_key_data, &enc_rel_key_data, &enc_key_bytes); + AesEncryptKey(principal_key, rlocator, rel_key_data, &enc_rel_key_data, &enc_key_bytes); return enc_rel_key_data; } @@ -260,12 +260,12 @@ tde_encrypt_rel_key(TDEMasterKey *master_key, RelKeyData *rel_key_data, const Re * Decrypts a given key and returns the decrypted one. */ RelKeyData * -tde_decrypt_rel_key(TDEMasterKey *master_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator) +tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator) { RelKeyData *rel_key_data = NULL; size_t key_bytes; - AesDecryptKey(master_key, rlocator, &rel_key_data, enc_rel_key_data, &key_bytes); + AesDecryptKey(principal_key, rlocator, &rel_key_data, enc_rel_key_data, &key_bytes); return rel_key_data; } @@ -291,7 +291,7 @@ pg_tde_set_db_file_paths(const RelFileLocator *rlocator, char *map_path, char *k } /* - * Creates the pair of map and key data file and save the master key information. + * Creates the pair of map and key data file and save the principal key information. * Returns true if both map and key data files are created. */ void @@ -313,16 +313,16 @@ pg_tde_delete_tde_files(Oid dbOid, Oid spcOid) } /* - * Creates the pair of map and key data file and save the master key information. + * Creates the pair of map and key data file and save the principal key information. * Returns true if both map and key data files are created. * - * If the files pre-exist, it truncates both files before adding master key + * If the files pre-exist, it truncates both files before adding principal key * information. * * The caller must have an EXCLUSIVE LOCK on the files before calling this function. */ bool -pg_tde_save_master_key(TDEMasterKeyInfo *master_key_info) +pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info) { int map_fd = -1; int keydata_fd = -1; @@ -334,16 +334,16 @@ pg_tde_save_master_key(TDEMasterKeyInfo *master_key_info) /* Set the file paths */ pg_tde_set_db_file_paths(&(RelFileLocator) { - master_key_info->tablespaceId, - master_key_info->databaseId, + principal_key_info->tablespaceId, + principal_key_info->databaseId, 0}, db_map_path, db_keydata_path); - ereport(LOG, (errmsg("pg_tde_save_master_key"))); + ereport(LOG, (errmsg("pg_tde_save_principal_key"))); /* Create or truncate these map and keydata files. */ - map_fd = pg_tde_open_file(db_map_path, master_key_info, false, O_RDWR | O_CREAT | O_TRUNC, &is_new_map, &curr_pos); - keydata_fd = pg_tde_open_file(db_keydata_path, master_key_info, false, O_RDWR | O_CREAT | O_TRUNC, &is_new_key_data, &curr_pos); + map_fd = pg_tde_open_file(db_map_path, principal_key_info, false, O_RDWR | O_CREAT | O_TRUNC, &is_new_map, &curr_pos); + keydata_fd = pg_tde_open_file(db_keydata_path, principal_key_info, false, O_RDWR | O_CREAT | O_TRUNC, &is_new_key_data, &curr_pos); /* Closing files. */ close(map_fd); @@ -353,15 +353,15 @@ pg_tde_save_master_key(TDEMasterKeyInfo *master_key_info) } /* - * Get the master key from the map file. The caller must hold + * Get the principal key from the map file. The caller must hold * a LW_SHARED or higher lock on files before calling this function. */ -TDEMasterKeyInfo * -pg_tde_get_master_key(Oid dbOid, Oid spcOid) +TDEPrincipalKeyInfo * +pg_tde_get_principal_key(Oid dbOid, Oid spcOid) { int fd = -1; TDEFileHeader fheader; - TDEMasterKeyInfo *master_key_info = NULL; + TDEPrincipalKeyInfo *principal_key_info = NULL; bool is_new_file = false; off_t bytes_read = 0; char db_map_path[MAXPGPATH] = {0}; @@ -387,16 +387,16 @@ pg_tde_get_master_key(Oid dbOid, Oid spcOid) close(fd); - /* It's not a new file. So we can memcpy the master key info from the header */ + /* It's not a new file. So we can memcpy the principal key info from the header */ if (!is_new_file) { - size_t sz = sizeof(TDEMasterKeyInfo); + size_t sz = sizeof(TDEPrincipalKeyInfo); - master_key_info = (TDEMasterKeyInfo *) palloc(sz); - memcpy(master_key_info, &fheader.master_key_info, sz); + principal_key_info = (TDEPrincipalKeyInfo *) palloc(sz); + memcpy(principal_key_info, &fheader.principal_key_info, sz); } - return master_key_info; + return principal_key_info; } /* @@ -430,19 +430,19 @@ pg_tde_open_file_basic(char *tde_filename, int fileFlags, bool ignore_missing) * Write TDE file header to a TDE file. */ static int -pg_tde_file_header_write(char *tde_filename, int fd, TDEMasterKeyInfo *master_key_info, off_t *bytes_written) +pg_tde_file_header_write(char *tde_filename, int fd, TDEPrincipalKeyInfo *principal_key_info, off_t *bytes_written) { TDEFileHeader fheader; - size_t sz = sizeof(TDEMasterKeyInfo); + size_t sz = sizeof(TDEPrincipalKeyInfo); - Assert(master_key_info); + Assert(principal_key_info); /* Create the header for this file. */ fheader.file_version = PG_TDE_FILEMAGIC; /* Fill in the data */ - memset(&fheader.master_key_info, 0, sz); - memcpy(&fheader.master_key_info, master_key_info, sz); + memset(&fheader.principal_key_info, 0, sz); + memcpy(&fheader.principal_key_info, principal_key_info, sz); /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ *bytes_written = pg_pwrite(fd, &fheader, TDE_FILE_HEADER_SIZE, 0); @@ -496,7 +496,7 @@ pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool /* * Open and Validate File Header [pg_tde.*]: - * header: {Format Version, Master Key Name} + * header: {Format Version, Principal Key Name} * * Returns the file descriptor in case of a success. Otherwise, fatal error * is raised. @@ -512,7 +512,7 @@ pg_tde_file_header_read(char *tde_filename, int fd, TDEFileHeader *fheader, bool * or an error is thrown if the file does not exist. */ int -pg_tde_open_file(char *tde_filename, TDEMasterKeyInfo *master_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *curr_pos) +pg_tde_open_file(char *tde_filename, TDEPrincipalKeyInfo *principal_key_info, bool should_fill_info, int fileFlags, bool *is_new_file, off_t *curr_pos) { int fd = -1; TDEFileHeader fheader; @@ -528,8 +528,8 @@ pg_tde_open_file(char *tde_filename, TDEMasterKeyInfo *master_key_info, bool sho pg_tde_file_header_read(tde_filename, fd, &fheader, is_new_file, &bytes_read); /* In case it's a new file, let's add the header now. */ - if (*is_new_file && master_key_info) - pg_tde_file_header_write(tde_filename, fd, master_key_info, &bytes_written); + if (*is_new_file && principal_key_info) + pg_tde_file_header_write(tde_filename, fd, principal_key_info, &bytes_written); *curr_pos = bytes_read + bytes_written; return fd; @@ -537,7 +537,7 @@ pg_tde_open_file(char *tde_filename, TDEMasterKeyInfo *master_key_info, bool sho /* * Key Map Table [pg_tde.map]: - * header: {Format Version, Master Key Name} + * header: {Format Version, Principal Key Name} * data: {OID, Flag, index of key in pg_tde.dat}... * * Returns the index of the key to be written in the key data file. @@ -545,7 +545,7 @@ pg_tde_open_file(char *tde_filename, TDEMasterKeyInfo *master_key_info, bool sho * concurrent in place updates leading to data conflicts. */ static int32 -pg_tde_write_map_entry(const RelFileLocator *rlocator, char *db_map_path, TDEMasterKeyInfo *master_key_info) +pg_tde_write_map_entry(const RelFileLocator *rlocator, char *db_map_path, TDEPrincipalKeyInfo *principal_key_info) { int map_fd = -1; int32 key_index = 0; @@ -556,7 +556,7 @@ pg_tde_write_map_entry(const RelFileLocator *rlocator, char *db_map_path, TDEMas bool found = false; /* Open and vaidate file for basic correctness. */ - map_fd = pg_tde_open_file(db_map_path, master_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); + map_fd = pg_tde_open_file(db_map_path, principal_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); prev_pos = curr_pos; /* @@ -768,14 +768,14 @@ pg_tde_read_one_map_entry(File map_file, const RelFileLocator *rlocator, int fla * job finds an empty index. */ static void -pg_tde_write_keydata(char *db_keydata_path, TDEMasterKeyInfo *master_key_info, int32 key_index, RelKeyData *enc_rel_key_data) +pg_tde_write_keydata(char *db_keydata_path, TDEPrincipalKeyInfo *principal_key_info, int32 key_index, RelKeyData *enc_rel_key_data) { File fd = -1; bool is_new_file; off_t curr_pos = 0; /* Open and validate file for basic correctness. */ - fd = pg_tde_open_file(db_keydata_path, master_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); + fd = pg_tde_open_file(db_keydata_path, principal_key_info, false, O_RDWR | O_CREAT, &is_new_file, &curr_pos); /* Write a single key data */ pg_tde_write_one_keydata(fd, key_index, enc_rel_key_data); @@ -817,7 +817,7 @@ pg_tde_write_one_keydata(int fd, int32 key_index, RelKeyData *enc_rel_key_data) * Open the file and read the required key data from file and return encrypted key. */ static RelKeyData * -pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEMasterKey *master_key) +pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *principal_key) { int fd = -1; RelKeyData *enc_rel_key_data; @@ -827,10 +827,10 @@ pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEMasterKey *master /* Open and validate file for basic correctness. */ LWLockAcquire(lock_files, LW_SHARED); - fd = pg_tde_open_file(db_keydata_path, &master_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos); + fd = pg_tde_open_file(db_keydata_path, &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos); /* Read the encrypted key from file */ - enc_rel_key_data = pg_tde_read_one_keydata(fd, key_index, master_key); + enc_rel_key_data = pg_tde_read_one_keydata(fd, key_index, principal_key); /* Let's close the file. */ close(fd); @@ -843,7 +843,7 @@ pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEMasterKey *master * Reads a single keydata from the file. */ static RelKeyData * -pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_key) +pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *principal_key) { RelKeyData *enc_rel_key_data; off_t read_pos = 0; @@ -851,7 +851,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_ke /* Allocate and fill in the structure */ enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); - strncpy(enc_rel_key_data->master_key_id.name, master_key->keyInfo.keyId.name, MASTER_KEY_NAME_LEN); + strncpy(enc_rel_key_data->principal_key_id.name, principal_key->keyInfo.keyId.name, PRINCIPAL_KEY_NAME_LEN); /* Calculate the reading position in the file. */ read_pos += (key_index * INTERNAL_KEY_LEN) + TDE_FILE_HEADER_SIZE; @@ -861,8 +861,8 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_ke { char db_keydata_path[MAXPGPATH] = {0}; pg_tde_set_db_file_paths(&(RelFileLocator) { - master_key->keyInfo.tablespaceId, - master_key->keyInfo.databaseId, + principal_key->keyInfo.tablespaceId, + principal_key->keyInfo.databaseId, 0}, NULL, db_keydata_path); ereport(FATAL, @@ -878,8 +878,8 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_ke { char db_keydata_path[MAXPGPATH] = {0}; pg_tde_set_db_file_paths(&(RelFileLocator) { - master_key->keyInfo.tablespaceId, - master_key->keyInfo.databaseId, + principal_key->keyInfo.tablespaceId, + principal_key->keyInfo.databaseId, 0}, NULL, db_keydata_path); ereport(FATAL, @@ -900,7 +900,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEMasterKey *master_ke * The map file must be updated while holding an exclusive lock. */ void -pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_key_data, TDEMasterKeyInfo *master_key_info) +pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_key_data, TDEPrincipalKeyInfo *principal_key_info) { int32 key_index = 0; LWLock *lock_files = tde_lwlock_mk_files(); @@ -914,10 +914,10 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_k /* Create the map entry and then add the encrypted key to the data file */ LWLockAcquire(lock_files, LW_EXCLUSIVE); - key_index = pg_tde_write_map_entry(rlocator, db_map_path, master_key_info); + key_index = pg_tde_write_map_entry(rlocator, db_map_path, principal_key_info); /* Add the encrypted key to the data file. */ - pg_tde_write_keydata(db_keydata_path, master_key_info, key_index, enc_rel_key_data); + pg_tde_write_keydata(db_keydata_path, principal_key_info, key_index, enc_rel_key_data); LWLockRelease(lock_files); } @@ -1008,7 +1008,7 @@ static RelKeyData * pg_tde_get_key_from_file(const RelFileLocator *rlocator, GenericKeyring *keyring) { int32 key_index = 0; - TDEMasterKey *master_key; + TDEPrincipalKey *principal_key; RelKeyData *rel_key_data; RelKeyData *enc_rel_key_data; off_t offset = 0; @@ -1020,13 +1020,13 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, GenericKeyring *keyring LWLockAcquire(lock_files, LW_SHARED); - /* Get/generate a master, create the key for relation and get the encrypted key with bytes to write */ - master_key = GetMasterKey(rlocator->dbOid, rlocator->spcOid, keyring); - if (master_key == NULL) + /* Get/generate a principal key, create the key for relation and get the encrypted key with bytes to write */ + principal_key = GetPrincipalKey(rlocator->dbOid, rlocator->spcOid, keyring); + if (principal_key == NULL) { LWLockRelease(lock_files); ereport(ERROR, - (errmsg("failed to retrieve master key"))); + (errmsg("failed to retrieve principal key"))); } /* Get the file paths */ @@ -1041,10 +1041,10 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, GenericKeyring *keyring return NULL; } - enc_rel_key_data = pg_tde_read_keydata(db_keydata_path, key_index, master_key); + enc_rel_key_data = pg_tde_read_keydata(db_keydata_path, key_index, principal_key); LWLockRelease(lock_files); - rel_key_data = tde_decrypt_rel_key(master_key, enc_rel_key_data, rlocator); + rel_key_data = tde_decrypt_rel_key(principal_key, enc_rel_key_data, rlocator); return rel_key_data; } @@ -1057,13 +1057,13 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, GenericKeyring *keyring * No error checking by this function. */ static File -keyrotation_init_file(TDEMasterKeyInfo *new_master_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos) +keyrotation_init_file(TDEPrincipalKeyInfo *new_principal_key_info, char *rotated_filename, char *filename, bool *is_new_file, off_t *curr_pos) { /* Set the new filenames for the key rotation process - temporary at the moment */ snprintf(rotated_filename, MAXPGPATH, "%s.r", filename); /* Create file, truncate if the rotate file already exits */ - return pg_tde_open_file(rotated_filename, new_master_key_info, false, O_RDWR | O_CREAT | O_TRUNC, is_new_file, curr_pos); + return pg_tde_open_file(rotated_filename, new_principal_key_info, false, O_RDWR | O_CREAT | O_TRUNC, is_new_file, curr_pos); } /* @@ -1085,21 +1085,21 @@ finalize_key_rotation(char *m_path_old, char *k_path_old, char *m_path_new, char * Rotate keys and generates the WAL record for it. */ bool -pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key) +pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_principal_key) { -#define OLD_MASTER_KEY 0 -#define NEW_MASTER_KEY 1 -#define MASTER_KEY_COUNT 2 - - off_t curr_pos[MASTER_KEY_COUNT] = {0}; - off_t prev_pos[MASTER_KEY_COUNT] = {0}; - int32 key_index[MASTER_KEY_COUNT] = {0}; - RelKeyData *rel_key_data[MASTER_KEY_COUNT]; - RelKeyData *enc_rel_key_data[MASTER_KEY_COUNT]; - int m_fd[MASTER_KEY_COUNT] = {-1}; - int k_fd[MASTER_KEY_COUNT] = {-1}; - char m_path[MASTER_KEY_COUNT][MAXPGPATH]; - char k_path[MASTER_KEY_COUNT][MAXPGPATH]; +#define OLD_PRINCIPAL_KEY 0 +#define NEW_PRINCIPAL_KEY 1 +#define PRINCIPAL_KEY_COUNT 2 + + off_t curr_pos[PRINCIPAL_KEY_COUNT] = {0}; + off_t prev_pos[PRINCIPAL_KEY_COUNT] = {0}; + int32 key_index[PRINCIPAL_KEY_COUNT] = {0}; + RelKeyData *rel_key_data[PRINCIPAL_KEY_COUNT]; + RelKeyData *enc_rel_key_data[PRINCIPAL_KEY_COUNT]; + int m_fd[PRINCIPAL_KEY_COUNT] = {-1}; + int k_fd[PRINCIPAL_KEY_COUNT] = {-1}; + char m_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; + char k_path[PRINCIPAL_KEY_COUNT][MAXPGPATH]; TDEMapEntry map_entry; RelFileLocator rloc; bool found = false; @@ -1107,7 +1107,7 @@ pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key bool is_new_file; off_t map_size; off_t keydata_size; - XLogMasterKeyRotate *xlrec; + XLogPrincipalKeyRotate *xlrec; off_t xlrec_size; LWLock *lock_files = tde_lwlock_mk_files(); LWLock *lock_cache = tde_lwlock_mk_cache(); @@ -1116,33 +1116,33 @@ pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key /* Set the file paths */ pg_tde_set_db_file_paths(&(RelFileLocator) { - master_key->keyInfo.tablespaceId, - master_key->keyInfo.databaseId, + principal_key->keyInfo.tablespaceId, + principal_key->keyInfo.databaseId, 0}, db_map_path, db_keydata_path); /* Let's update the pathnames in the local variable for ease of use/readability */ - strncpy(m_path[OLD_MASTER_KEY], db_map_path, MAXPGPATH); - strncpy(k_path[OLD_MASTER_KEY], db_keydata_path, MAXPGPATH); + strncpy(m_path[OLD_PRINCIPAL_KEY], db_map_path, MAXPGPATH); + strncpy(k_path[OLD_PRINCIPAL_KEY], db_keydata_path, MAXPGPATH); LWLockAcquire(lock_files, LW_EXCLUSIVE); LWLockAcquire(lock_cache, LW_EXCLUSIVE); /* Open both files in read only mode. We don't need to track the current position of the keydata file. We always use the key index */ - m_fd[OLD_MASTER_KEY] = pg_tde_open_file(m_path[OLD_MASTER_KEY], &master_key->keyInfo, false, O_RDONLY, &is_new_file, &curr_pos[OLD_MASTER_KEY]); - k_fd[OLD_MASTER_KEY] = pg_tde_open_file(k_path[OLD_MASTER_KEY], &master_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos_tmp); + m_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(m_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &curr_pos[OLD_PRINCIPAL_KEY]); + k_fd[OLD_PRINCIPAL_KEY] = pg_tde_open_file(k_path[OLD_PRINCIPAL_KEY], &principal_key->keyInfo, false, O_RDONLY, &is_new_file, &read_pos_tmp); - m_fd[NEW_MASTER_KEY] = keyrotation_init_file(&new_master_key->keyInfo, m_path[NEW_MASTER_KEY], m_path[OLD_MASTER_KEY], &is_new_file, &curr_pos[NEW_MASTER_KEY]); - k_fd[NEW_MASTER_KEY] = keyrotation_init_file(&new_master_key->keyInfo, k_path[NEW_MASTER_KEY], k_path[OLD_MASTER_KEY], &is_new_file, &read_pos_tmp); + m_fd[NEW_PRINCIPAL_KEY] = keyrotation_init_file(&new_principal_key->keyInfo, m_path[NEW_PRINCIPAL_KEY], m_path[OLD_PRINCIPAL_KEY], &is_new_file, &curr_pos[NEW_PRINCIPAL_KEY]); + k_fd[NEW_PRINCIPAL_KEY] = keyrotation_init_file(&new_principal_key->keyInfo, k_path[NEW_PRINCIPAL_KEY], k_path[OLD_PRINCIPAL_KEY], &is_new_file, &read_pos_tmp); /* Read all entries until EOF */ - for(key_index[OLD_MASTER_KEY] = 0; ; key_index[OLD_MASTER_KEY]++) + for(key_index[OLD_PRINCIPAL_KEY] = 0; ; key_index[OLD_PRINCIPAL_KEY]++) { - prev_pos[OLD_MASTER_KEY] = curr_pos[OLD_MASTER_KEY]; - found = pg_tde_read_one_map_entry(m_fd[OLD_MASTER_KEY], NULL, MAP_ENTRY_VALID, &map_entry, &curr_pos[OLD_MASTER_KEY]); + prev_pos[OLD_PRINCIPAL_KEY] = curr_pos[OLD_PRINCIPAL_KEY]; + found = pg_tde_read_one_map_entry(m_fd[OLD_PRINCIPAL_KEY], NULL, MAP_ENTRY_VALID, &map_entry, &curr_pos[OLD_PRINCIPAL_KEY]); /* We either reach EOF */ - if (prev_pos[OLD_MASTER_KEY] == curr_pos[OLD_MASTER_KEY]) + if (prev_pos[OLD_PRINCIPAL_KEY] == curr_pos[OLD_PRINCIPAL_KEY]) break; /* We didn't find a valid entry */ @@ -1151,48 +1151,48 @@ pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key /* Set the relNumber of rlocator. Ignore the tablespace Oid since we only place our files under the default. */ rloc.relNumber = map_entry.relNumber; - rloc.dbOid = master_key->keyInfo.databaseId; + rloc.dbOid = principal_key->keyInfo.databaseId; rloc.spcOid = DEFAULTTABLESPACE_OID; /* Let's get the decrypted key and re-encrypt it with the new key. */ - enc_rel_key_data[OLD_MASTER_KEY] = pg_tde_read_one_keydata(k_fd[OLD_MASTER_KEY], key_index[OLD_MASTER_KEY], master_key); + enc_rel_key_data[OLD_PRINCIPAL_KEY] = pg_tde_read_one_keydata(k_fd[OLD_PRINCIPAL_KEY], key_index[OLD_PRINCIPAL_KEY], principal_key); /* Decrypt and re-encrypt keys */ - rel_key_data[OLD_MASTER_KEY] = tde_decrypt_rel_key(master_key, enc_rel_key_data[OLD_MASTER_KEY], &rloc); - enc_rel_key_data[NEW_MASTER_KEY] = tde_encrypt_rel_key(new_master_key, rel_key_data[OLD_MASTER_KEY], &rloc); + rel_key_data[OLD_PRINCIPAL_KEY] = tde_decrypt_rel_key(principal_key, enc_rel_key_data[OLD_PRINCIPAL_KEY], &rloc); + enc_rel_key_data[NEW_PRINCIPAL_KEY] = tde_encrypt_rel_key(new_principal_key, rel_key_data[OLD_PRINCIPAL_KEY], &rloc); /* Write the given entry at the location pointed by prev_pos */ - prev_pos[NEW_MASTER_KEY] = curr_pos[NEW_MASTER_KEY]; - curr_pos[NEW_MASTER_KEY] = pg_tde_write_one_map_entry(m_fd[NEW_MASTER_KEY], &rloc, MAP_ENTRY_VALID, key_index[NEW_MASTER_KEY], &map_entry, &prev_pos[NEW_MASTER_KEY]); - pg_tde_write_one_keydata(k_fd[NEW_MASTER_KEY], key_index[NEW_MASTER_KEY], enc_rel_key_data[NEW_MASTER_KEY]); + prev_pos[NEW_PRINCIPAL_KEY] = curr_pos[NEW_PRINCIPAL_KEY]; + curr_pos[NEW_PRINCIPAL_KEY] = pg_tde_write_one_map_entry(m_fd[NEW_PRINCIPAL_KEY], &rloc, MAP_ENTRY_VALID, key_index[NEW_PRINCIPAL_KEY], &map_entry, &prev_pos[NEW_PRINCIPAL_KEY]); + pg_tde_write_one_keydata(k_fd[NEW_PRINCIPAL_KEY], key_index[NEW_PRINCIPAL_KEY], enc_rel_key_data[NEW_PRINCIPAL_KEY]); - /* Increment the key index for the new master key */ - key_index[NEW_MASTER_KEY]++; + /* Increment the key index for the new principal key */ + key_index[NEW_PRINCIPAL_KEY]++; } /* Close unrotated files */ - close(m_fd[OLD_MASTER_KEY]); - close(k_fd[OLD_MASTER_KEY]); + close(m_fd[OLD_PRINCIPAL_KEY]); + close(k_fd[OLD_PRINCIPAL_KEY]); /* Let's calculate sizes */ - map_size = lseek(m_fd[NEW_MASTER_KEY], 0, SEEK_END); - keydata_size = lseek(k_fd[NEW_MASTER_KEY], 0, SEEK_END); - xlrec_size = map_size + keydata_size + SizeoOfXLogMasterKeyRotate; + map_size = lseek(m_fd[NEW_PRINCIPAL_KEY], 0, SEEK_END); + keydata_size = lseek(k_fd[NEW_PRINCIPAL_KEY], 0, SEEK_END); + xlrec_size = map_size + keydata_size + SizeoOfXLogPrincipalKeyRotate; /* palloc and fill in the structure */ - xlrec = (XLogMasterKeyRotate *) palloc(xlrec_size); + xlrec = (XLogPrincipalKeyRotate *) palloc(xlrec_size); - xlrec->databaseId = master_key->keyInfo.databaseId; + xlrec->databaseId = principal_key->keyInfo.databaseId; xlrec->map_size = map_size; xlrec->keydata_size = keydata_size; /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ - pg_pread(m_fd[NEW_MASTER_KEY], xlrec->buff, xlrec->map_size, 0); - pg_pread(k_fd[NEW_MASTER_KEY], &xlrec->buff[xlrec->map_size], xlrec->keydata_size, 0); + pg_pread(m_fd[NEW_PRINCIPAL_KEY], xlrec->buff, xlrec->map_size, 0); + pg_pread(k_fd[NEW_PRINCIPAL_KEY], &xlrec->buff[xlrec->map_size], xlrec->keydata_size, 0); /* Close the files */ - close(m_fd[NEW_MASTER_KEY]); - close(k_fd[NEW_MASTER_KEY]); + close(m_fd[NEW_PRINCIPAL_KEY]); + close(k_fd[NEW_PRINCIPAL_KEY]); /* Insert the XLog record */ XLogBeginInsert(); @@ -1200,8 +1200,8 @@ pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ROTATE_KEY); /* Do the final steps */ - finalize_key_rotation(m_path[OLD_MASTER_KEY], k_path[OLD_MASTER_KEY], - m_path[NEW_MASTER_KEY], k_path[NEW_MASTER_KEY]); + finalize_key_rotation(m_path[OLD_PRINCIPAL_KEY], k_path[OLD_PRINCIPAL_KEY], + m_path[NEW_PRINCIPAL_KEY], k_path[NEW_PRINCIPAL_KEY]); LWLockRelease(lock_cache); LWLockRelease(lock_files); @@ -1211,9 +1211,9 @@ pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key return true; -#undef OLD_MASTER_KEY -#undef NEW_MASTER_KEY -#undef MASTER_KEY_COUNT +#undef OLD_PRINCIPAL_KEY +#undef NEW_PRINCIPAL_KEY +#undef PRINCIPAL_KEY_COUNT } /* @@ -1241,8 +1241,8 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_ /* Set the file paths */ pg_tde_set_db_file_paths(&(RelFileLocator) { - fheader->master_key_info.tablespaceId, - fheader->master_key_info.databaseId, + fheader->principal_key_info.tablespaceId, + fheader->principal_key_info.databaseId, 0}, db_map_path, db_keydata_path); @@ -1250,8 +1250,8 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_ LWLockAcquire(lock_cache, LW_EXCLUSIVE); /* Initialize the new files and set the names */ - m_fd_new = keyrotation_init_file(&fheader->master_key_info, m_path_new, db_map_path, &is_new_file, &curr_pos); - k_fd_new = keyrotation_init_file(&fheader->master_key_info, k_path_new, db_keydata_path, &is_new_file, &read_pos_tmp); + m_fd_new = keyrotation_init_file(&fheader->principal_key_info, m_path_new, db_map_path, &is_new_file, &curr_pos); + k_fd_new = keyrotation_init_file(&fheader->principal_key_info, k_path_new, db_keydata_path, &is_new_file, &read_pos_tmp); /* TODO: pgstat_report_wait_start / pgstat_report_wait_end */ if (pg_pwrite(m_fd_new, m_file_data, map_size, 0) != map_size) diff --git a/src/access/pg_tde_xlog.c b/src/access/pg_tde_xlog.c index 246ef195..0e57e170 100644 --- a/src/access/pg_tde_xlog.c +++ b/src/access/pg_tde_xlog.c @@ -55,21 +55,21 @@ pg_tde_rmgr_redo(XLogReaderState *record) pg_tde_write_key_map_entry(&xlrec->rlocator, &xlrec->relKey, NULL); } - else if (info == XLOG_TDE_ADD_MASTER_KEY) + else if (info == XLOG_TDE_ADD_PRINCIPAL_KEY) { - TDEMasterKeyInfo *mkey = (TDEMasterKeyInfo *) XLogRecGetData(record); + TDEPrincipalKeyInfo *mkey = (TDEPrincipalKeyInfo *) XLogRecGetData(record); - save_master_key_info(mkey); + save_principal_key_info(mkey); } - else if (info == XLOG_TDE_CLEAN_MASTER_KEY) + else if (info == XLOG_TDE_CLEAN_PRINCIPAL_KEY) { - XLogMasterKeyCleanup *xlrec = (XLogMasterKeyCleanup *) XLogRecGetData(record); + XLogPrincipalKeyCleanup *xlrec = (XLogPrincipalKeyCleanup *) XLogRecGetData(record); - cleanup_master_key_info(xlrec->databaseId, xlrec->tablespaceId); + cleanup_principal_key_info(xlrec->databaseId, xlrec->tablespaceId); } else if (info == XLOG_TDE_ROTATE_KEY) { - XLogMasterKeyRotate *xlrec = (XLogMasterKeyRotate *) XLogRecGetData(record); + XLogPrincipalKeyRotate *xlrec = (XLogPrincipalKeyRotate *) XLogRecGetData(record); xl_tde_perform_rotate_key(xlrec); } @@ -90,23 +90,23 @@ pg_tde_rmgr_desc(StringInfo buf, XLogReaderState *record) appendStringInfo(buf, "add tde internal key for relation %u/%u", xlrec->rlocator.dbOid, xlrec->rlocator.relNumber); } - if (info == XLOG_TDE_ADD_MASTER_KEY) + if (info == XLOG_TDE_ADD_PRINCIPAL_KEY) { - TDEMasterKeyInfo *xlrec = (TDEMasterKeyInfo *) XLogRecGetData(record); + TDEPrincipalKeyInfo *xlrec = (TDEPrincipalKeyInfo *) XLogRecGetData(record); - appendStringInfo(buf, "add tde master key for db %u/%u", xlrec->databaseId, xlrec->tablespaceId); + appendStringInfo(buf, "add tde principal key for db %u/%u", xlrec->databaseId, xlrec->tablespaceId); } - if (info == XLOG_TDE_CLEAN_MASTER_KEY) + if (info == XLOG_TDE_CLEAN_PRINCIPAL_KEY) { - XLogMasterKeyCleanup *xlrec = (XLogMasterKeyCleanup *) XLogRecGetData(record); + XLogPrincipalKeyCleanup *xlrec = (XLogPrincipalKeyCleanup *) XLogRecGetData(record); - appendStringInfo(buf, "cleanup tde master key info for db %u/%u", xlrec->databaseId, xlrec->tablespaceId); + appendStringInfo(buf, "cleanup tde principal key info for db %u/%u", xlrec->databaseId, xlrec->tablespaceId); } if (info == XLOG_TDE_ROTATE_KEY) { - XLogMasterKeyRotate *xlrec = (XLogMasterKeyRotate *) XLogRecGetData(record); + XLogPrincipalKeyRotate *xlrec = (XLogPrincipalKeyRotate *) XLogRecGetData(record); - appendStringInfo(buf, "rotate master key for %u", xlrec->databaseId); + appendStringInfo(buf, "rotate principal key for %u", xlrec->databaseId); } } @@ -116,11 +116,11 @@ pg_tde_rmgr_identify(uint8 info) if ((info & ~XLR_INFO_MASK) == XLOG_TDE_ADD_RELATION_KEY) return "XLOG_TDE_ADD_RELATION_KEY"; - if ((info & ~XLR_INFO_MASK) == XLOG_TDE_ADD_MASTER_KEY) - return "XLOG_TDE_ADD_MASTER_KEY"; + if ((info & ~XLR_INFO_MASK) == XLOG_TDE_ADD_PRINCIPAL_KEY) + return "XLOG_TDE_ADD_PRINCIPAL_KEY"; - if ((info & ~XLR_INFO_MASK) == XLOG_TDE_CLEAN_MASTER_KEY) - return "XLOG_TDE_CLEAN_MASTER_KEY"; + if ((info & ~XLR_INFO_MASK) == XLOG_TDE_CLEAN_PRINCIPAL_KEY) + return "XLOG_TDE_CLEAN_PRINCIPAL_KEY"; return NULL; } diff --git a/src/catalog/tde_global_catalog.c b/src/catalog/tde_global_catalog.c index 4fb72908..4124079b 100644 --- a/src/catalog/tde_global_catalog.c +++ b/src/catalog/tde_global_catalog.c @@ -20,15 +20,15 @@ #include "access/pg_tde_tdemap.h" #include "catalog/tde_global_catalog.h" #include "catalog/tde_keyring.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" #include #include #include -#define MASTER_KEY_DEFAULT_NAME "tde-global-catalog-key" +#define PRINCIPAL_KEY_DEFAULT_NAME "tde-global-catalog-key" -/* TODO: not sure if we need an option of multiple master keys for the global catalog */ +/* TODO: not sure if we need an option of multiple principal keys for the global catalog */ typedef enum { TDE_GCAT_XLOG_KEY, @@ -40,7 +40,7 @@ typedef enum typedef struct EncryptionStateData { GenericKeyring *keyring; - TDEMasterKey master_keys[TDE_GCAT_KEYS_COUNT]; + TDEPrincipalKey principal_keys[TDE_GCAT_KEYS_COUNT]; } EncryptionStateData; static EncryptionStateData * EncryptionState = NULL; @@ -51,7 +51,7 @@ static char *KRingProviderFilePath = NULL; static void init_gl_catalog_keys(void); static void init_keyring(void); -static TDEMasterKey * create_master_key(const char *key_name, +static TDEPrincipalKey * create_principal_key(const char *key_name, GenericKeyring * keyring, Oid dbOid, Oid spcOid, bool ensure_new_key); @@ -107,7 +107,7 @@ TDEGlCatShmemInit(void) allocptr = ((char *) EncryptionState) + MAXALIGN(sizeof(EncryptionStateData)); EncryptionState->keyring = (GenericKeyring *) allocptr; memset(EncryptionState->keyring, 0, sizeof(KeyringProviders)); - memset(EncryptionState->master_keys, 0, sizeof(TDEMasterKey) * TDE_GCAT_KEYS_COUNT); + memset(EncryptionState->principal_keys, 0, sizeof(TDEPrincipalKey) * TDE_GCAT_KEYS_COUNT); } void @@ -130,12 +130,12 @@ TDEGlCatKeyInit(void) } } -TDEMasterKey * +TDEPrincipalKey * TDEGetGlCatKeyFromCache(void) { - TDEMasterKey *mkey; + TDEPrincipalKey *mkey; - mkey = &EncryptionState->master_keys[TDE_GCAT_XLOG_KEY]; + mkey = &EncryptionState->principal_keys[TDE_GCAT_XLOG_KEY]; if (mkey->keyLength == 0) return NULL; @@ -143,9 +143,9 @@ TDEGetGlCatKeyFromCache(void) } void -TDEPutGlCatKeyInCache(TDEMasterKey * mkey) +TDEPutGlCatKeyInCache(TDEPrincipalKey * mkey) { - memcpy(EncryptionState->master_keys + TDE_GCAT_XLOG_KEY, mkey, sizeof(TDEMasterKey)); + memcpy(EncryptionState->principal_keys + TDE_GCAT_XLOG_KEY, mkey, sizeof(TDEPrincipalKey)); } RelKeyData * @@ -183,9 +183,9 @@ init_gl_catalog_keys(void) RelKeyData *rel_key_data; RelKeyData *enc_rel_key_data; RelFileLocator *rlocator; - TDEMasterKey *mkey; + TDEPrincipalKey *mkey; - mkey = create_master_key(MASTER_KEY_DEFAULT_NAME, + mkey = create_principal_key(PRINCIPAL_KEY_DEFAULT_NAME, EncryptionState->keyring, GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, false); @@ -214,35 +214,35 @@ init_gl_catalog_keys(void) TDEPutGlCatKeyInCache(mkey); } -static TDEMasterKey * -create_master_key(const char *key_name, GenericKeyring * keyring, +static TDEPrincipalKey * +create_principal_key(const char *key_name, GenericKeyring * keyring, Oid dbOid, Oid spcOid, bool ensure_new_key) { - TDEMasterKey *masterKey; + TDEPrincipalKey *principalKey; keyInfo *keyInfo = NULL; - masterKey = palloc(sizeof(TDEMasterKey)); - masterKey->keyInfo.databaseId = dbOid; - masterKey->keyInfo.tablespaceId = spcOid; - masterKey->keyInfo.keyId.version = DEFAULT_MASTER_KEY_VERSION; - masterKey->keyInfo.keyringId = keyring->key_id; - strncpy(masterKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); - gettimeofday(&masterKey->keyInfo.creationTime, NULL); + principalKey = palloc(sizeof(TDEPrincipalKey)); + principalKey->keyInfo.databaseId = dbOid; + principalKey->keyInfo.tablespaceId = spcOid; + principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; + principalKey->keyInfo.keyringId = keyring->key_id; + strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); + gettimeofday(&principalKey->keyInfo.creationTime, NULL); - keyInfo = load_latest_versioned_key_name(&masterKey->keyInfo, keyring, ensure_new_key); + keyInfo = load_latest_versioned_key_name(&principalKey->keyInfo, keyring, ensure_new_key); if (keyInfo == NULL) - keyInfo = KeyringGenerateNewKeyAndStore(keyring, masterKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); + keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); if (keyInfo == NULL) { ereport(ERROR, - (errmsg("failed to retrieve master key"))); + (errmsg("failed to retrieve principal key"))); } - masterKey->keyLength = keyInfo->data.len; - memcpy(masterKey->keyData, keyInfo->data.data, keyInfo->data.len); + principalKey->keyLength = keyInfo->data.len; + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); - return masterKey; + return principalKey; } #endif /* PERCONA_FORK */ diff --git a/src/catalog/tde_keyring.c b/src/catalog/tde_keyring.c index 5397dcb7..e894dba6 100644 --- a/src/catalog/tde_keyring.c +++ b/src/catalog/tde_keyring.c @@ -11,7 +11,7 @@ */ #include "catalog/tde_keyring.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" #include "access/skey.h" #include "access/relscan.h" #include "access/relation.h" @@ -289,13 +289,13 @@ debug_print_kerying(GenericKeyring *keyring) /* * Trigger function on keyring catalog to ensure the keyring - * used by the master key should not get deleted. + * used by the principal key should not get deleted. */ Datum keyring_delete_dependency_check_trigger(PG_FUNCTION_ARGS) { TriggerData *trig_data = (TriggerData *)fcinfo->context; - Oid master_key_keyring_id; + Oid principal_key_keyring_id; if (!CALLED_AS_TRIGGER(fcinfo)) { @@ -310,10 +310,10 @@ keyring_delete_dependency_check_trigger(PG_FUNCTION_ARGS) (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("keyring dependency check trigger: trigger should be fired before delete"))); } - master_key_keyring_id = GetMasterKeyProviderId(); - if (master_key_keyring_id == InvalidOid) + principal_key_keyring_id = GetPrincipalKeyProviderId(); + if (principal_key_keyring_id == InvalidOid) { - /* No master key set. We are good to delete anything */ + /* No principal key set. We are good to delete anything */ return PointerGetDatum(trig_data->tg_trigtuple); } @@ -328,7 +328,7 @@ keyring_delete_dependency_check_trigger(PG_FUNCTION_ARGS) Oid provider_id; datum = heap_getattr(oldtuple, PG_TDE_KEY_PROVIDER_ID_ATTRNUM, trig_data->tg_relation->rd_att, &isnull); provider_id = DatumGetInt32(datum); - if (provider_id == master_key_keyring_id) + if (provider_id == principal_key_keyring_id) { char *keyring_name; datum = heap_getattr(oldtuple, PG_TDE_KEY_PROVIDER_NAME_ATTRNUM, trig_data->tg_relation->rd_att, &isnull); @@ -337,7 +337,7 @@ keyring_delete_dependency_check_trigger(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("Key provider \"%s\" cannot be deleted", keyring_name), - errdetail("The master key for the database depends on this key provider."))); + errdetail("The principal key for the database depends on this key provider."))); SPI_finish(); trig_data->tg_trigtuple = NULL; return PointerGetDatum(NULL); diff --git a/src/catalog/tde_master_key.c b/src/catalog/tde_master_key.c deleted file mode 100644 index 8d1fd707..00000000 --- a/src/catalog/tde_master_key.c +++ /dev/null @@ -1,825 +0,0 @@ -/*------------------------------------------------------------------------- - * - * tde_master_key.c - * Deals with the tde master key configuration catalog - * routines. - * - * IDENTIFICATION - * contrib/pg_tde/src/catalog/tde_master_key.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" -#include "access/xlog.h" -#include "access/xloginsert.h" -#include "catalog/tde_master_key.h" -#include "common/pg_tde_shmem.h" -#include "storage/lwlock.h" -#include "storage/fd.h" -#include "utils/palloc.h" -#include "utils/memutils.h" -#include "utils/wait_event.h" -#include "utils/timestamp.h" -#include "common/relpath.h" -#include "miscadmin.h" -#include "funcapi.h" -#include "utils/builtins.h" -#include "pg_tde.h" -#include "access/pg_tde_xlog.h" -#include - -#include "access/pg_tde_tdemap.h" -#ifdef PERCONA_FORK -#include "catalog/tde_global_catalog.h" -#endif - -typedef struct TdeMasterKeySharedState -{ - LWLock *Locks; - int hashTrancheId; - dshash_table_handle hashHandle; - void *rawDsaArea; /* DSA area pointer */ - -} TdeMasterKeySharedState; - -typedef struct TdeMasterKeylocalState -{ - TdeMasterKeySharedState *sharedMasterKeyState; - dsa_area *dsa; /* local dsa area for backend attached to the - * dsa area created by postmaster at startup. - */ - dshash_table *sharedHash; -} TdeMasterKeylocalState; - -/* parameter for the master key info shared hash */ -static dshash_parameters master_key_dsh_params = { - sizeof(Oid), - sizeof(TDEMasterKey), - dshash_memcmp, /* TODO use int compare instead */ - dshash_memhash}; - -TdeMasterKeylocalState masterKeyLocalState; - -static void master_key_info_attach_shmem(void); -static Size initialize_shared_state(void *start_address); -static void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area); -static Size cache_area_size(void); -static Size required_shared_mem_size(void); -static int required_locks_count(void); -static void shared_memory_shutdown(int code, Datum arg); -static void master_key_startup_cleanup(int tde_tbl_count, void *arg); -static void clear_master_key_cache(Oid databaseId) ; -static inline dshash_table *get_master_key_Hash(void); -static TDEMasterKey *get_master_key_from_cache(Oid dbOid); -static void push_master_key_to_cache(TDEMasterKey *masterKey); - -static const TDEShmemSetupRoutine master_key_info_shmem_routine = { - .init_shared_state = initialize_shared_state, - .init_dsa_area_objects = initialize_objects_in_dsa_area, - .required_shared_mem_size = required_shared_mem_size, - .required_locks_count = required_locks_count, - .shmem_kill = shared_memory_shutdown - }; - -void InitializeMasterKeyInfo(void) -{ - ereport(LOG, (errmsg("Initializing TDE master key info"))); - RegisterShmemRequest(&master_key_info_shmem_routine); - on_ext_install(master_key_startup_cleanup, NULL); -} - -LWLock * -tde_lwlock_mk_files(void) -{ - Assert(masterKeyLocalState.sharedMasterKeyState); - - return &masterKeyLocalState.sharedMasterKeyState->Locks[TDE_LWLOCK_MK_FILES]; -} - -LWLock * -tde_lwlock_mk_cache(void) -{ - Assert(masterKeyLocalState.sharedMasterKeyState); - - return &masterKeyLocalState.sharedMasterKeyState->Locks[TDE_LWLOCK_MK_CACHE]; -} - -static int -required_locks_count(void) -{ - return TDE_LWLOCK_COUNT; -} - -static Size -cache_area_size(void) -{ - return MAXALIGN(8192 * 100); /* TODO: Probably get it from guc */ -} - -static Size -required_shared_mem_size(void) -{ - Size sz = cache_area_size(); - sz = add_size(sz, sizeof(TdeMasterKeySharedState)); - return MAXALIGN(sz); -} - -/* - * Initialize the shared area for Master key info. - * This includes locks and cache area for master key info - */ - -static Size -initialize_shared_state(void *start_address) -{ - TdeMasterKeySharedState *sharedState = (TdeMasterKeySharedState *)start_address; - ereport(LOG, (errmsg("initializing shared state for master key"))); - masterKeyLocalState.dsa = NULL; - masterKeyLocalState.sharedHash = NULL; - - sharedState->Locks = GetNewLWLock(); - masterKeyLocalState.sharedMasterKeyState = sharedState; - return sizeof(TdeMasterKeySharedState); -} - -void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area) -{ - dshash_table *dsh; - TdeMasterKeySharedState *sharedState = masterKeyLocalState.sharedMasterKeyState; - - ereport(LOG, (errmsg("initializing dsa area objects for master key"))); - - Assert(sharedState != NULL); - - sharedState->rawDsaArea = raw_dsa_area; - sharedState->hashTrancheId = LWLockNewTrancheId(); - master_key_dsh_params.tranche_id = sharedState->hashTrancheId; - dsh = dshash_create(dsa, &master_key_dsh_params, 0); - sharedState->hashHandle = dshash_get_hash_table_handle(dsh); - dshash_detach(dsh); -} - -/* - * Attaches to the DSA to local backend - */ -static void -master_key_info_attach_shmem(void) -{ - MemoryContext oldcontext; - - if (masterKeyLocalState.dsa) - return; - - /* - * We want the dsa to remain valid throughout the lifecycle of this - * process. so switch to TopMemoryContext before attaching - */ - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - - masterKeyLocalState.dsa = dsa_attach_in_place(masterKeyLocalState.sharedMasterKeyState->rawDsaArea, - NULL); - - /* - * pin the attached area to keep the area attached until end of session or - * explicit detach. - */ - dsa_pin_mapping(masterKeyLocalState.dsa); - - master_key_dsh_params.tranche_id = masterKeyLocalState.sharedMasterKeyState->hashTrancheId; - masterKeyLocalState.sharedHash = dshash_attach(masterKeyLocalState.dsa, &master_key_dsh_params, - masterKeyLocalState.sharedMasterKeyState->hashHandle, 0); - MemoryContextSwitchTo(oldcontext); -} - -static void -shared_memory_shutdown(int code, Datum arg) -{ - masterKeyLocalState.sharedMasterKeyState = NULL; -} - -bool -save_master_key_info(TDEMasterKeyInfo *master_key_info) -{ - Assert(master_key_info != NULL); - - return pg_tde_save_master_key(master_key_info); -} - -/* - * Public interface to get the master key for the current database - * If the master key is not present in the cache, it is loaded from - * the keyring and stored in the cache. - * When the master key is not set for the database. The function returns - * throws an error. - */ -TDEMasterKey * -GetMasterKey(Oid dbOid, Oid spcOid, GenericKeyring *keyring) -{ - TDEMasterKey *masterKey = NULL; - TDEMasterKeyInfo *masterKeyInfo = NULL; - const keyInfo *keyInfo = NULL; - KeyringReturnCodes keyring_ret; - LWLock *lock_files = tde_lwlock_mk_files(); - LWLock *lock_cache = tde_lwlock_mk_cache(); - - // TODO: This recursion counter is a dirty hack until the metadata is in the catalog - // As otherwise we would call GetMasterKey recursively and deadlock - static int recursion = 0; - - if(recursion > 0) - { - return NULL; - } - - recursion++; - - LWLockAcquire(lock_cache, LW_SHARED); -#ifdef PERCONA_FORK - /* Global catalog has its own cache */ - if (spcOid == GLOBALTABLESPACE_OID) - masterKey = TDEGetGlCatKeyFromCache(); - else -#endif - masterKey = get_master_key_from_cache(dbOid); - LWLockRelease(lock_cache); - - if (masterKey) - { - recursion--; - return masterKey; - } - - /* - * We should hold an exclusive lock here to ensure that a valid master key, if found, is added - * to the cache without any interference. - */ - LWLockAcquire(lock_files, LW_SHARED); - LWLockAcquire(lock_cache, LW_EXCLUSIVE); - -#ifdef PERCONA_FORK - /* Global catalog has its own cache */ - if (spcOid == GLOBALTABLESPACE_OID) - masterKey = TDEGetGlCatKeyFromCache(); - else -#endif - masterKey = get_master_key_from_cache(dbOid); - - if (masterKey) - { - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - recursion--; - return masterKey; - } - - /* Master key not present in cache. Load from the keyring */ - masterKeyInfo = pg_tde_get_master_key(dbOid, spcOid); - if (masterKeyInfo == NULL) - { - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - recursion--; - return NULL; - } - - if (keyring == NULL) - { - keyring = GetKeyProviderByID(masterKeyInfo->keyringId); - if (keyring == NULL) - { - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - recursion--; - return NULL; - } - } - - keyInfo = KeyringGetKey(keyring, masterKeyInfo->keyId.versioned_name, false, &keyring_ret); - if (keyInfo == NULL) - { - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - recursion--; - return NULL; - } - - masterKey = palloc(sizeof(TDEMasterKey)); - - memcpy(&masterKey->keyInfo, masterKeyInfo, sizeof(masterKey->keyInfo)); - memcpy(masterKey->keyData, keyInfo->data.data, keyInfo->data.len); - masterKey->keyLength = keyInfo->data.len; - - Assert(dbOid == masterKey->keyInfo.databaseId); -#ifdef PERCONA_FORK - if (spcOid == GLOBALTABLESPACE_OID) - TDEPutGlCatKeyInCache(masterKey); - else -#endif - push_master_key_to_cache(masterKey); - - /* Release the exclusive locks here */ - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - if (masterKeyInfo) - pfree(masterKeyInfo); - - recursion--; - return masterKey; -} - -/* - * SetMasterkey: - * We need to ensure that only one master key is set for a database. - * To do that we take a little help from cache. Before setting the - * master key we take an exclusive lock on the cache entry for the - * database. - * After acquiring the exclusive lock we check for the entry again - * to make sure if some other caller has not added a master key for - * same database while we were waiting for the lock. - */ -TDEMasterKey * -set_master_key_with_keyring(const char *key_name, GenericKeyring *keyring, - Oid dbOid, Oid spcOid, bool ensure_new_key) -{ - TDEMasterKey *masterKey = NULL; - LWLock *lock_files = tde_lwlock_mk_files(); - LWLock *lock_cache = tde_lwlock_mk_cache(); - bool is_dup_key = false; - - /* - * Try to get master key from cache. - */ - LWLockAcquire(lock_files, LW_EXCLUSIVE); - LWLockAcquire(lock_cache, LW_EXCLUSIVE); - - masterKey = get_master_key_from_cache(dbOid); - is_dup_key = (masterKey != NULL); - - /* TODO: Add the key in the cache? */ - if (is_dup_key == false) - is_dup_key = (pg_tde_get_master_key(dbOid, spcOid) != NULL); - - if (is_dup_key == false) - { - const keyInfo *keyInfo = NULL; - - masterKey = palloc(sizeof(TDEMasterKey)); - masterKey->keyInfo.databaseId = dbOid; - masterKey->keyInfo.tablespaceId = spcOid; - masterKey->keyInfo.keyId.version = DEFAULT_MASTER_KEY_VERSION; - masterKey->keyInfo.keyringId = keyring->key_id; - strncpy(masterKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); - gettimeofday(&masterKey->keyInfo.creationTime, NULL); - - keyInfo = load_latest_versioned_key_name(&masterKey->keyInfo, keyring, ensure_new_key); - - if (keyInfo == NULL) - keyInfo = KeyringGenerateNewKeyAndStore(keyring, masterKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); - - if (keyInfo == NULL) - { - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - ereport(ERROR, - (errmsg("failed to retrieve master key"))); - } - - masterKey->keyLength = keyInfo->data.len; - memcpy(masterKey->keyData, keyInfo->data.data, keyInfo->data.len); - - save_master_key_info(&masterKey->keyInfo); - - /* XLog the new key*/ - XLogBeginInsert(); - XLogRegisterData((char *) &masterKey->keyInfo, sizeof(TDEMasterKeyInfo)); - XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_MASTER_KEY); - - push_master_key_to_cache(masterKey); - } - - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - if (is_dup_key) - { - /* - * Seems like just before we got the lock, the key was installed by some other caller - * Throw an error and mover no - */ - - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("Master key already exists for the database"), - errhint("Use rotate_key interface to change the master key"))); - } - - return masterKey; -} - -bool -SetMasterKey(const char *key_name, const char *provider_name, bool ensure_new_key) -{ - TDEMasterKey *master_key = set_master_key_with_keyring(key_name, - GetKeyProviderByName(provider_name), - MyDatabaseId, MyDatabaseTableSpace, - ensure_new_key); - - return (master_key != NULL); -} - -bool -RotateMasterKey(const char *new_key_name, const char *new_provider_name, bool ensure_new_key) -{ - TDEMasterKey *master_key = GetMasterKey(MyDatabaseId, MyDatabaseTableSpace, NULL); - TDEMasterKey new_master_key; - const keyInfo *keyInfo = NULL; - GenericKeyring *keyring; - bool is_rotated; - - /* - * Let's set everything the same as the older master key and - * update only the required attributes. - * */ - memcpy(&new_master_key, master_key, sizeof(TDEMasterKey)); - - if (new_key_name == NULL) - { - new_master_key.keyInfo.keyId.version++; - } - else - { - strncpy(new_master_key.keyInfo.keyId.name, new_key_name, sizeof(new_master_key.keyInfo.keyId.name)); - new_master_key.keyInfo.keyId.version = DEFAULT_MASTER_KEY_VERSION; - - if (new_provider_name != NULL) - { - new_master_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name)->key_id; - } - } - - /* We need a valid keyring structure */ - keyring = GetKeyProviderByID(new_master_key.keyInfo.keyringId); - - keyInfo = load_latest_versioned_key_name(&new_master_key.keyInfo, keyring, ensure_new_key); - - if (keyInfo == NULL) - keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_master_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); - - if (keyInfo == NULL) - { - ereport(ERROR, - (errmsg("Failed to generate new key name"))); - } - - new_master_key.keyLength = keyInfo->data.len; - memcpy(new_master_key.keyData, keyInfo->data.data, keyInfo->data.len); - is_rotated = pg_tde_perform_rotate_key(master_key, &new_master_key); - if (is_rotated) { - clear_master_key_cache(master_key->keyInfo.databaseId); - push_master_key_to_cache(&new_master_key); - } - - return is_rotated; -} - -/* - * Rotate keys on a standby. - */ -bool -xl_tde_perform_rotate_key(XLogMasterKeyRotate *xlrec) -{ - bool ret; - - ret = pg_tde_write_map_keydata_files(xlrec->map_size, xlrec->buff, xlrec->keydata_size, &xlrec->buff[xlrec->map_size]); - clear_master_key_cache(MyDatabaseId); - - return ret; -} - -/* -* Load the latest versioned key name for the master key -* If ensure_new_key is true, then we will keep on incrementing the version number -* till we get a key name that is not present in the keyring -*/ -keyInfo * -load_latest_versioned_key_name(TDEMasterKeyInfo *mastere_key_info, GenericKeyring *keyring, bool ensure_new_key) -{ - KeyringReturnCodes kr_ret; - keyInfo *keyInfo = NULL; - int base_version = mastere_key_info->keyId.version; - Assert(mastere_key_info != NULL); - Assert(keyring != NULL); - Assert(strlen(mastere_key_info->keyId.name) > 0); - /* Start with the passed in version number - * We expect the name and the version number are already properly initialized - * and contain the correct values - */ - snprintf(mastere_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, - "%s_%d", mastere_key_info->keyId.name, mastere_key_info->keyId.version); - - while (true) - { - keyInfo = KeyringGetKey(keyring, mastere_key_info->keyId.versioned_name, false, &kr_ret); - /* vault-v2 returns 404 (KEYRING_CODE_RESOURCE_NOT_AVAILABLE) when key is not found */ - if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE) - { - ereport(ERROR, - (errmsg("failed to retrieve master key from keyring provider :\"%s\"", keyring->provider_name), - errdetail("Error code: %d", kr_ret))); - } - if (keyInfo == NULL) - { - if (ensure_new_key == false) - { - /* - * If ensure_key is false and we are not at the base version, - * We should return the last existent version. - */ - if (base_version < mastere_key_info->keyId.version) - { - /* Not optimal but keep the things simple */ - mastere_key_info->keyId.version -= 1; - snprintf(mastere_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, - "%s_%d", mastere_key_info->keyId.name, mastere_key_info->keyId.version); - keyInfo = KeyringGetKey(keyring, mastere_key_info->keyId.versioned_name, false, &kr_ret); - } - } - return keyInfo; - } - - mastere_key_info->keyId.version++; - snprintf(mastere_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, "%s_%d", mastere_key_info->keyId.name, mastere_key_info->keyId.version); - - /* - * Not really required. Just to break the infinite loop in case the key provider is not behaving sane. - */ - if (mastere_key_info->keyId.version > MAX_MASTER_KEY_VERSION_NUM) - { - ereport(ERROR, - (errmsg("failed to retrieve master key. %d versions already exist", MAX_MASTER_KEY_VERSION_NUM))); - } - } - return NULL; /* Just to keep compiler quite */ -} -/* - * Returns the provider ID of the keyring that holds the master key - * Return InvalidOid if the master key is not set for the database - */ -Oid -GetMasterKeyProviderId(void) -{ - TDEMasterKey *masterKey = NULL; - TDEMasterKeyInfo *masterKeyInfo = NULL; - Oid keyringId = InvalidOid; - Oid dbOid = MyDatabaseId; - LWLock *lock_files = tde_lwlock_mk_files(); - LWLock *lock_cache = tde_lwlock_mk_cache(); - - LWLockAcquire(lock_files, LW_SHARED); - LWLockAcquire(lock_cache, LW_SHARED); - - masterKey = get_master_key_from_cache(dbOid); - if (masterKey) - { - keyringId = masterKey->keyInfo.keyringId; - } - { - /* Master key not present in cache. Try Loading it from the info file */ - masterKeyInfo = pg_tde_get_master_key(dbOid, MyDatabaseTableSpace); - if (masterKeyInfo) - { - keyringId = masterKeyInfo->keyringId; - pfree(masterKeyInfo); - } - } - - LWLockRelease(lock_cache); - LWLockRelease(lock_files); - - return keyringId; -} - -/* - * ------------------------------ - * Master key cache realted stuff - */ - -static inline dshash_table * -get_master_key_Hash(void) -{ - master_key_info_attach_shmem(); - return masterKeyLocalState.sharedHash; -} - -/* - * Gets the master key for current database from cache - */ -static TDEMasterKey * -get_master_key_from_cache(Oid dbOid) -{ - TDEMasterKey *cacheEntry = NULL; - - cacheEntry = (TDEMasterKey *)dshash_find(get_master_key_Hash(), - &dbOid, false); - if (cacheEntry) - dshash_release_lock(get_master_key_Hash(), cacheEntry); - - return cacheEntry; -} - -/* - * Push the master key for current database to the shared memory cache. - * TODO: Add eviction policy - * For now we just keep pushing the master keys to the cache and do not have - * any eviction policy. We have one master key for a database, so at max, - * we could have as many entries in the cache as the number of databases. - * Which in practice would not be a huge number, but still we need to have - * some eviction policy in place. Moreover, we need to have some mechanism to - * remove the cache entry when the database is dropped. - */ -static void -push_master_key_to_cache(TDEMasterKey *masterKey) -{ - TDEMasterKey *cacheEntry = NULL; - Oid databaseId = masterKey->keyInfo.databaseId; - bool found = false; - cacheEntry = dshash_find_or_insert(get_master_key_Hash(), - &databaseId, &found); - if (!found) - memcpy(cacheEntry, masterKey, sizeof(TDEMasterKey)); - dshash_release_lock(get_master_key_Hash(), cacheEntry); -} - -/* - * Cleanup the master key cache entry for the current database. - * This function is a hack to handle the situation if the - * extension was dropped from the database and had created the - * master key info file and cache entry in its previous encarnation. - * We need to remove the cache entry and the master key info file - * at the time of extension creation to start fresh again. - * Idelly we should have a mechanism to remove these when the extension - * but unfortunately we do not have any such mechanism in PG. -*/ -static void -master_key_startup_cleanup(int tde_tbl_count, void* arg) -{ - XLogMasterKeyCleanup xlrec; - - if (tde_tbl_count > 0) - { - ereport(WARNING, - (errmsg("Failed to perform initialization. database already has %d TDE tables", tde_tbl_count))); - return; - } - - cleanup_master_key_info(MyDatabaseId, MyDatabaseTableSpace); - - /* XLog the key cleanup */ - xlrec.databaseId = MyDatabaseId; - xlrec.tablespaceId = MyDatabaseTableSpace; - XLogBeginInsert(); - XLogRegisterData((char *) &xlrec, sizeof(TDEMasterKeyInfo)); - XLogInsert(RM_TDERMGR_ID, XLOG_TDE_CLEAN_MASTER_KEY); -} - -void -cleanup_master_key_info(Oid databaseId, Oid tablespaceId) -{ - clear_master_key_cache(databaseId); - /* - * TODO: Although should never happen. Still verify if any table in the - * database is using tde - */ - - /* Remove the tde files */ - pg_tde_delete_tde_files(databaseId, tablespaceId); -} - -static void -clear_master_key_cache(Oid databaseId) -{ - TDEMasterKey *cache_entry; - - /* Start with deleting the cache entry for the database */ - cache_entry = (TDEMasterKey *)dshash_find(get_master_key_Hash(), - &databaseId, true); - if (cache_entry) - { - dshash_delete_entry(get_master_key_Hash(), cache_entry); - } -} - -/* - * SQL interface to set master key - */ -PG_FUNCTION_INFO_V1(pg_tde_set_master_key); -Datum pg_tde_set_master_key(PG_FUNCTION_ARGS); - -Datum pg_tde_set_master_key(PG_FUNCTION_ARGS) -{ - char *master_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); - char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); - bool ensure_new_key = PG_GETARG_BOOL(2); - bool ret; - - ereport(LOG, (errmsg("Setting master key [%s : %s] for the database", master_key_name, provider_name))); - ret = SetMasterKey(master_key_name, provider_name, ensure_new_key); - PG_RETURN_BOOL(ret); -} - -/* - * SQL interface for key rotation - */ -PG_FUNCTION_INFO_V1(pg_tde_rotate_key); -Datum -pg_tde_rotate_key(PG_FUNCTION_ARGS) -{ - char *new_master_key_name = NULL; - char *new_provider_name = NULL; - bool ensure_new_key; - bool ret; - - if (!PG_ARGISNULL(0)) - new_master_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); - if (!PG_ARGISNULL(1)) - new_provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); - ensure_new_key = PG_GETARG_BOOL(2); - - - ereport(LOG, (errmsg("Rotating master key to [%s : %s] for the database", new_master_key_name, new_provider_name))); - ret = RotateMasterKey(new_master_key_name, new_provider_name, ensure_new_key); - PG_RETURN_BOOL(ret); -} - -PG_FUNCTION_INFO_V1(pg_tde_master_key_info); -Datum pg_tde_master_key_info(PG_FUNCTION_ARGS) -{ - TupleDesc tupdesc; - Datum values[6]; - bool isnull[6]; - HeapTuple tuple; - Datum result; - TDEMasterKey *master_key; - TimestampTz ts; - GenericKeyring *keyring; - - /* Build a tuple descriptor for our result type */ - if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function returning record called in context that cannot accept type record"))); - - master_key = GetMasterKey(MyDatabaseId, MyDatabaseTableSpace, NULL); - if (master_key == NULL) - { - ereport(ERROR, - (errmsg("Master key does not exists for the database"), - errhint("Use set_master_key interface to set the master key"))); - PG_RETURN_NULL(); - } - - keyring = GetKeyProviderByID(master_key->keyInfo.keyringId); - - /* Initialize the values and null flags */ - - /* TEXT: Master key name */ - values[0] = CStringGetTextDatum(master_key->keyInfo.keyId.name); - isnull[0] = false; - /* TEXT: Keyring provider name */ - if (keyring) - { - values[1] = CStringGetTextDatum(keyring->provider_name); - isnull[1] = false; - } - else - isnull[1] = true; - - /* INTEGERT: key provider id */ - values[2] = Int32GetDatum(master_key->keyInfo.keyringId); - isnull[2] = false; - - /* TEXT: Master key versioned name */ - values[3] = CStringGetTextDatum(master_key->keyInfo.keyId.versioned_name); - isnull[3] = false; - /* INTEGERT: Master key version */ - values[4] = Int32GetDatum(master_key->keyInfo.keyId.version); - isnull[4] = false; - /* TIMESTAMP TZ: Master key creation time */ - ts = (TimestampTz)master_key->keyInfo.creationTime.tv_sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); - ts = (ts * USECS_PER_SEC) + master_key->keyInfo.creationTime.tv_usec; - values[5] = TimestampTzGetDatum(ts); - isnull[5] = false; - - /* Form the tuple */ - tuple = heap_form_tuple(tupdesc, values, isnull); - - /* Make the tuple into a datum */ - result = HeapTupleGetDatum(tuple); - - PG_RETURN_DATUM(result); -} diff --git a/src/catalog/tde_principal_key.c b/src/catalog/tde_principal_key.c new file mode 100644 index 00000000..39146851 --- /dev/null +++ b/src/catalog/tde_principal_key.c @@ -0,0 +1,825 @@ +/*------------------------------------------------------------------------- + * + * tde_principal_key.c + * Deals with the tde principal key configuration catalog + * routines. + * + * IDENTIFICATION + * contrib/pg_tde/src/catalog/tde_principal_key.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "access/xlog.h" +#include "access/xloginsert.h" +#include "catalog/tde_principal_key.h" +#include "common/pg_tde_shmem.h" +#include "storage/lwlock.h" +#include "storage/fd.h" +#include "utils/palloc.h" +#include "utils/memutils.h" +#include "utils/wait_event.h" +#include "utils/timestamp.h" +#include "common/relpath.h" +#include "miscadmin.h" +#include "funcapi.h" +#include "utils/builtins.h" +#include "pg_tde.h" +#include "access/pg_tde_xlog.h" +#include + +#include "access/pg_tde_tdemap.h" +#ifdef PERCONA_FORK +#include "catalog/tde_global_catalog.h" +#endif + +typedef struct TdePrincipalKeySharedState +{ + LWLock *Locks; + int hashTrancheId; + dshash_table_handle hashHandle; + void *rawDsaArea; /* DSA area pointer */ + +} TdePrincipalKeySharedState; + +typedef struct TdePrincipalKeylocalState +{ + TdePrincipalKeySharedState *sharedPrincipalKeyState; + dsa_area *dsa; /* local dsa area for backend attached to the + * dsa area created by postmaster at startup. + */ + dshash_table *sharedHash; +} TdePrincipalKeylocalState; + +/* parameter for the principal key info shared hash */ +static dshash_parameters principal_key_dsh_params = { + sizeof(Oid), + sizeof(TDEPrincipalKey), + dshash_memcmp, /* TODO use int compare instead */ + dshash_memhash}; + +TdePrincipalKeylocalState principalKeyLocalState; + +static void principal_key_info_attach_shmem(void); +static Size initialize_shared_state(void *start_address); +static void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area); +static Size cache_area_size(void); +static Size required_shared_mem_size(void); +static int required_locks_count(void); +static void shared_memory_shutdown(int code, Datum arg); +static void principal_key_startup_cleanup(int tde_tbl_count, void *arg); +static void clear_principal_key_cache(Oid databaseId) ; +static inline dshash_table *get_principal_key_Hash(void); +static TDEPrincipalKey *get_principal_key_from_cache(Oid dbOid); +static void push_principal_key_to_cache(TDEPrincipalKey *principalKey); + +static const TDEShmemSetupRoutine principal_key_info_shmem_routine = { + .init_shared_state = initialize_shared_state, + .init_dsa_area_objects = initialize_objects_in_dsa_area, + .required_shared_mem_size = required_shared_mem_size, + .required_locks_count = required_locks_count, + .shmem_kill = shared_memory_shutdown + }; + +void InitializePrincipalKeyInfo(void) +{ + ereport(LOG, (errmsg("Initializing TDE principal key info"))); + RegisterShmemRequest(&principal_key_info_shmem_routine); + on_ext_install(principal_key_startup_cleanup, NULL); +} + +LWLock * +tde_lwlock_mk_files(void) +{ + Assert(principalKeyLocalState.sharedPrincipalKeyState); + + return &principalKeyLocalState.sharedPrincipalKeyState->Locks[TDE_LWLOCK_MK_FILES]; +} + +LWLock * +tde_lwlock_mk_cache(void) +{ + Assert(principalKeyLocalState.sharedPrincipalKeyState); + + return &principalKeyLocalState.sharedPrincipalKeyState->Locks[TDE_LWLOCK_MK_CACHE]; +} + +static int +required_locks_count(void) +{ + return TDE_LWLOCK_COUNT; +} + +static Size +cache_area_size(void) +{ + return MAXALIGN(8192 * 100); /* TODO: Probably get it from guc */ +} + +static Size +required_shared_mem_size(void) +{ + Size sz = cache_area_size(); + sz = add_size(sz, sizeof(TdePrincipalKeySharedState)); + return MAXALIGN(sz); +} + +/* + * Initialize the shared area for Principal key info. + * This includes locks and cache area for principal key info + */ + +static Size +initialize_shared_state(void *start_address) +{ + TdePrincipalKeySharedState *sharedState = (TdePrincipalKeySharedState *)start_address; + ereport(LOG, (errmsg("initializing shared state for principal key"))); + principalKeyLocalState.dsa = NULL; + principalKeyLocalState.sharedHash = NULL; + + sharedState->Locks = GetNewLWLock(); + principalKeyLocalState.sharedPrincipalKeyState = sharedState; + return sizeof(TdePrincipalKeySharedState); +} + +void initialize_objects_in_dsa_area(dsa_area *dsa, void *raw_dsa_area) +{ + dshash_table *dsh; + TdePrincipalKeySharedState *sharedState = principalKeyLocalState.sharedPrincipalKeyState; + + ereport(LOG, (errmsg("initializing dsa area objects for principal key"))); + + Assert(sharedState != NULL); + + sharedState->rawDsaArea = raw_dsa_area; + sharedState->hashTrancheId = LWLockNewTrancheId(); + principal_key_dsh_params.tranche_id = sharedState->hashTrancheId; + dsh = dshash_create(dsa, &principal_key_dsh_params, 0); + sharedState->hashHandle = dshash_get_hash_table_handle(dsh); + dshash_detach(dsh); +} + +/* + * Attaches to the DSA to local backend + */ +static void +principal_key_info_attach_shmem(void) +{ + MemoryContext oldcontext; + + if (principalKeyLocalState.dsa) + return; + + /* + * We want the dsa to remain valid throughout the lifecycle of this + * process. so switch to TopMemoryContext before attaching + */ + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + + principalKeyLocalState.dsa = dsa_attach_in_place(principalKeyLocalState.sharedPrincipalKeyState->rawDsaArea, + NULL); + + /* + * pin the attached area to keep the area attached until end of session or + * explicit detach. + */ + dsa_pin_mapping(principalKeyLocalState.dsa); + + principal_key_dsh_params.tranche_id = principalKeyLocalState.sharedPrincipalKeyState->hashTrancheId; + principalKeyLocalState.sharedHash = dshash_attach(principalKeyLocalState.dsa, &principal_key_dsh_params, + principalKeyLocalState.sharedPrincipalKeyState->hashHandle, 0); + MemoryContextSwitchTo(oldcontext); +} + +static void +shared_memory_shutdown(int code, Datum arg) +{ + principalKeyLocalState.sharedPrincipalKeyState = NULL; +} + +bool +save_principal_key_info(TDEPrincipalKeyInfo *principal_key_info) +{ + Assert(principal_key_info != NULL); + + return pg_tde_save_principal_key(principal_key_info); +} + +/* + * Public interface to get the principal key for the current database + * If the principal key is not present in the cache, it is loaded from + * the keyring and stored in the cache. + * When the principal key is not set for the database. The function returns + * throws an error. + */ +TDEPrincipalKey * +GetPrincipalKey(Oid dbOid, Oid spcOid, GenericKeyring *keyring) +{ + TDEPrincipalKey *principalKey = NULL; + TDEPrincipalKeyInfo *principalKeyInfo = NULL; + const keyInfo *keyInfo = NULL; + KeyringReturnCodes keyring_ret; + LWLock *lock_files = tde_lwlock_mk_files(); + LWLock *lock_cache = tde_lwlock_mk_cache(); + + // TODO: This recursion counter is a dirty hack until the metadata is in the catalog + // As otherwise we would call GetPrincipalKey recursively and deadlock + static int recursion = 0; + + if(recursion > 0) + { + return NULL; + } + + recursion++; + + LWLockAcquire(lock_cache, LW_SHARED); +#ifdef PERCONA_FORK + /* Global catalog has its own cache */ + if (spcOid == GLOBALTABLESPACE_OID) + principalKey = TDEGetGlCatKeyFromCache(); + else +#endif + principalKey = get_principal_key_from_cache(dbOid); + LWLockRelease(lock_cache); + + if (principalKey) + { + recursion--; + return principalKey; + } + + /* + * We should hold an exclusive lock here to ensure that a valid principal key, if found, is added + * to the cache without any interference. + */ + LWLockAcquire(lock_files, LW_SHARED); + LWLockAcquire(lock_cache, LW_EXCLUSIVE); + +#ifdef PERCONA_FORK + /* Global catalog has its own cache */ + if (spcOid == GLOBALTABLESPACE_OID) + principalKey = TDEGetGlCatKeyFromCache(); + else +#endif + principalKey = get_principal_key_from_cache(dbOid); + + if (principalKey) + { + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + recursion--; + return principalKey; + } + + /* Principal key not present in cache. Load from the keyring */ + principalKeyInfo = pg_tde_get_principal_key(dbOid, spcOid); + if (principalKeyInfo == NULL) + { + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + recursion--; + return NULL; + } + + if (keyring == NULL) + { + keyring = GetKeyProviderByID(principalKeyInfo->keyringId); + if (keyring == NULL) + { + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + recursion--; + return NULL; + } + } + + keyInfo = KeyringGetKey(keyring, principalKeyInfo->keyId.versioned_name, false, &keyring_ret); + if (keyInfo == NULL) + { + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + recursion--; + return NULL; + } + + principalKey = palloc(sizeof(TDEPrincipalKey)); + + memcpy(&principalKey->keyInfo, principalKeyInfo, sizeof(principalKey->keyInfo)); + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); + principalKey->keyLength = keyInfo->data.len; + + Assert(dbOid == principalKey->keyInfo.databaseId); +#ifdef PERCONA_FORK + if (spcOid == GLOBALTABLESPACE_OID) + TDEPutGlCatKeyInCache(principalKey); + else +#endif + push_principal_key_to_cache(principalKey); + + /* Release the exclusive locks here */ + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + if (principalKeyInfo) + pfree(principalKeyInfo); + + recursion--; + return principalKey; +} + +/* + * SetPrincipalkey: + * We need to ensure that only one principal key is set for a database. + * To do that we take a little help from cache. Before setting the + * principal key we take an exclusive lock on the cache entry for the + * database. + * After acquiring the exclusive lock we check for the entry again + * to make sure if some other caller has not added a principal key for + * same database while we were waiting for the lock. + */ +TDEPrincipalKey * +set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring, + Oid dbOid, Oid spcOid, bool ensure_new_key) +{ + TDEPrincipalKey *principalKey = NULL; + LWLock *lock_files = tde_lwlock_mk_files(); + LWLock *lock_cache = tde_lwlock_mk_cache(); + bool is_dup_key = false; + + /* + * Try to get principal key from cache. + */ + LWLockAcquire(lock_files, LW_EXCLUSIVE); + LWLockAcquire(lock_cache, LW_EXCLUSIVE); + + principalKey = get_principal_key_from_cache(dbOid); + is_dup_key = (principalKey != NULL); + + /* TODO: Add the key in the cache? */ + if (is_dup_key == false) + is_dup_key = (pg_tde_get_principal_key(dbOid, spcOid) != NULL); + + if (is_dup_key == false) + { + const keyInfo *keyInfo = NULL; + + principalKey = palloc(sizeof(TDEPrincipalKey)); + principalKey->keyInfo.databaseId = dbOid; + principalKey->keyInfo.tablespaceId = spcOid; + principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; + principalKey->keyInfo.keyringId = keyring->key_id; + strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); + gettimeofday(&principalKey->keyInfo.creationTime, NULL); + + keyInfo = load_latest_versioned_key_name(&principalKey->keyInfo, keyring, ensure_new_key); + + if (keyInfo == NULL) + keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); + + if (keyInfo == NULL) + { + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + ereport(ERROR, + (errmsg("failed to retrieve principal key"))); + } + + principalKey->keyLength = keyInfo->data.len; + memcpy(principalKey->keyData, keyInfo->data.data, keyInfo->data.len); + + save_principal_key_info(&principalKey->keyInfo); + + /* XLog the new key*/ + XLogBeginInsert(); + XLogRegisterData((char *) &principalKey->keyInfo, sizeof(TDEPrincipalKeyInfo)); + XLogInsert(RM_TDERMGR_ID, XLOG_TDE_ADD_PRINCIPAL_KEY); + + push_principal_key_to_cache(principalKey); + } + + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + if (is_dup_key) + { + /* + * Seems like just before we got the lock, the key was installed by some other caller + * Throw an error and mover no + */ + + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("Principal key already exists for the database"), + errhint("Use rotate_key interface to change the principal key"))); + } + + return principalKey; +} + +bool +SetPrincipalKey(const char *key_name, const char *provider_name, bool ensure_new_key) +{ + TDEPrincipalKey *principal_key = set_principal_key_with_keyring(key_name, + GetKeyProviderByName(provider_name), + MyDatabaseId, MyDatabaseTableSpace, + ensure_new_key); + + return (principal_key != NULL); +} + +bool +RotatePrincipalKey(const char *new_key_name, const char *new_provider_name, bool ensure_new_key) +{ + TDEPrincipalKey *principal_key = GetPrincipalKey(MyDatabaseId, MyDatabaseTableSpace, NULL); + TDEPrincipalKey new_principal_key; + const keyInfo *keyInfo = NULL; + GenericKeyring *keyring; + bool is_rotated; + + /* + * Let's set everything the same as the older principal key and + * update only the required attributes. + * */ + memcpy(&new_principal_key, principal_key, sizeof(TDEPrincipalKey)); + + if (new_key_name == NULL) + { + new_principal_key.keyInfo.keyId.version++; + } + else + { + strncpy(new_principal_key.keyInfo.keyId.name, new_key_name, sizeof(new_principal_key.keyInfo.keyId.name)); + new_principal_key.keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; + + if (new_provider_name != NULL) + { + new_principal_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name)->key_id; + } + } + + /* We need a valid keyring structure */ + keyring = GetKeyProviderByID(new_principal_key.keyInfo.keyringId); + + keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key); + + if (keyInfo == NULL) + keyInfo = KeyringGenerateNewKeyAndStore(keyring, new_principal_key.keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); + + if (keyInfo == NULL) + { + ereport(ERROR, + (errmsg("Failed to generate new key name"))); + } + + new_principal_key.keyLength = keyInfo->data.len; + memcpy(new_principal_key.keyData, keyInfo->data.data, keyInfo->data.len); + is_rotated = pg_tde_perform_rotate_key(principal_key, &new_principal_key); + if (is_rotated) { + clear_principal_key_cache(principal_key->keyInfo.databaseId); + push_principal_key_to_cache(&new_principal_key); + } + + return is_rotated; +} + +/* + * Rotate keys on a standby. + */ +bool +xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec) +{ + bool ret; + + ret = pg_tde_write_map_keydata_files(xlrec->map_size, xlrec->buff, xlrec->keydata_size, &xlrec->buff[xlrec->map_size]); + clear_principal_key_cache(MyDatabaseId); + + return ret; +} + +/* +* Load the latest versioned key name for the principal key +* If ensure_new_key is true, then we will keep on incrementing the version number +* till we get a key name that is not present in the keyring +*/ +keyInfo * +load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, GenericKeyring *keyring, bool ensure_new_key) +{ + KeyringReturnCodes kr_ret; + keyInfo *keyInfo = NULL; + int base_version = principal_key_info->keyId.version; + Assert(principal_key_info != NULL); + Assert(keyring != NULL); + Assert(strlen(principal_key_info->keyId.name) > 0); + /* Start with the passed in version number + * We expect the name and the version number are already properly initialized + * and contain the correct values + */ + snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, + "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); + + while (true) + { + keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret); + /* vault-v2 returns 404 (KEYRING_CODE_RESOURCE_NOT_AVAILABLE) when key is not found */ + if (kr_ret != KEYRING_CODE_SUCCESS && kr_ret != KEYRING_CODE_RESOURCE_NOT_AVAILABLE) + { + ereport(ERROR, + (errmsg("failed to retrieve principal key from keyring provider :\"%s\"", keyring->provider_name), + errdetail("Error code: %d", kr_ret))); + } + if (keyInfo == NULL) + { + if (ensure_new_key == false) + { + /* + * If ensure_key is false and we are not at the base version, + * We should return the last existent version. + */ + if (base_version < principal_key_info->keyId.version) + { + /* Not optimal but keep the things simple */ + principal_key_info->keyId.version -= 1; + snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, + "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); + keyInfo = KeyringGetKey(keyring, principal_key_info->keyId.versioned_name, false, &kr_ret); + } + } + return keyInfo; + } + + principal_key_info->keyId.version++; + snprintf(principal_key_info->keyId.versioned_name, TDE_KEY_NAME_LEN, "%s_%d", principal_key_info->keyId.name, principal_key_info->keyId.version); + + /* + * Not really required. Just to break the infinite loop in case the key provider is not behaving sane. + */ + if (principal_key_info->keyId.version > MAX_PRINCIPAL_KEY_VERSION_NUM) + { + ereport(ERROR, + (errmsg("failed to retrieve principal key. %d versions already exist", MAX_PRINCIPAL_KEY_VERSION_NUM))); + } + } + return NULL; /* Just to keep compiler quite */ +} +/* + * Returns the provider ID of the keyring that holds the principal key + * Return InvalidOid if the principal key is not set for the database + */ +Oid +GetPrincipalKeyProviderId(void) +{ + TDEPrincipalKey *principalKey = NULL; + TDEPrincipalKeyInfo *principalKeyInfo = NULL; + Oid keyringId = InvalidOid; + Oid dbOid = MyDatabaseId; + LWLock *lock_files = tde_lwlock_mk_files(); + LWLock *lock_cache = tde_lwlock_mk_cache(); + + LWLockAcquire(lock_files, LW_SHARED); + LWLockAcquire(lock_cache, LW_SHARED); + + principalKey = get_principal_key_from_cache(dbOid); + if (principalKey) + { + keyringId = principalKey->keyInfo.keyringId; + } + { + /* Principal key not present in cache. Try Loading it from the info file */ + principalKeyInfo = pg_tde_get_principal_key(dbOid, MyDatabaseTableSpace); + if (principalKeyInfo) + { + keyringId = principalKeyInfo->keyringId; + pfree(principalKeyInfo); + } + } + + LWLockRelease(lock_cache); + LWLockRelease(lock_files); + + return keyringId; +} + +/* + * ------------------------------ + * Principal key cache realted stuff + */ + +static inline dshash_table * +get_principal_key_Hash(void) +{ + principal_key_info_attach_shmem(); + return principalKeyLocalState.sharedHash; +} + +/* + * Gets the principal key for current database from cache + */ +static TDEPrincipalKey * +get_principal_key_from_cache(Oid dbOid) +{ + TDEPrincipalKey *cacheEntry = NULL; + + cacheEntry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), + &dbOid, false); + if (cacheEntry) + dshash_release_lock(get_principal_key_Hash(), cacheEntry); + + return cacheEntry; +} + +/* + * Push the principal key for current database to the shared memory cache. + * TODO: Add eviction policy + * For now we just keep pushing the principal keys to the cache and do not have + * any eviction policy. We have one principal key for a database, so at max, + * we could have as many entries in the cache as the number of databases. + * Which in practice would not be a huge number, but still we need to have + * some eviction policy in place. Moreover, we need to have some mechanism to + * remove the cache entry when the database is dropped. + */ +static void +push_principal_key_to_cache(TDEPrincipalKey *principalKey) +{ + TDEPrincipalKey *cacheEntry = NULL; + Oid databaseId = principalKey->keyInfo.databaseId; + bool found = false; + cacheEntry = dshash_find_or_insert(get_principal_key_Hash(), + &databaseId, &found); + if (!found) + memcpy(cacheEntry, principalKey, sizeof(TDEPrincipalKey)); + dshash_release_lock(get_principal_key_Hash(), cacheEntry); +} + +/* + * Cleanup the principal key cache entry for the current database. + * This function is a hack to handle the situation if the + * extension was dropped from the database and had created the + * principal key info file and cache entry in its previous encarnation. + * We need to remove the cache entry and the principal key info file + * at the time of extension creation to start fresh again. + * Idelly we should have a mechanism to remove these when the extension + * but unfortunately we do not have any such mechanism in PG. +*/ +static void +principal_key_startup_cleanup(int tde_tbl_count, void* arg) +{ + XLogPrincipalKeyCleanup xlrec; + + if (tde_tbl_count > 0) + { + ereport(WARNING, + (errmsg("Failed to perform initialization. database already has %d TDE tables", tde_tbl_count))); + return; + } + + cleanup_principal_key_info(MyDatabaseId, MyDatabaseTableSpace); + + /* XLog the key cleanup */ + xlrec.databaseId = MyDatabaseId; + xlrec.tablespaceId = MyDatabaseTableSpace; + XLogBeginInsert(); + XLogRegisterData((char *) &xlrec, sizeof(TDEPrincipalKeyInfo)); + XLogInsert(RM_TDERMGR_ID, XLOG_TDE_CLEAN_PRINCIPAL_KEY); +} + +void +cleanup_principal_key_info(Oid databaseId, Oid tablespaceId) +{ + clear_principal_key_cache(databaseId); + /* + * TODO: Although should never happen. Still verify if any table in the + * database is using tde + */ + + /* Remove the tde files */ + pg_tde_delete_tde_files(databaseId, tablespaceId); +} + +static void +clear_principal_key_cache(Oid databaseId) +{ + TDEPrincipalKey *cache_entry; + + /* Start with deleting the cache entry for the database */ + cache_entry = (TDEPrincipalKey *)dshash_find(get_principal_key_Hash(), + &databaseId, true); + if (cache_entry) + { + dshash_delete_entry(get_principal_key_Hash(), cache_entry); + } +} + +/* + * SQL interface to set principal key + */ +PG_FUNCTION_INFO_V1(pg_tde_set_principal_key); +Datum pg_tde_set_principal_key(PG_FUNCTION_ARGS); + +Datum pg_tde_set_principal_key(PG_FUNCTION_ARGS) +{ + char *principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + char *provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + bool ensure_new_key = PG_GETARG_BOOL(2); + bool ret; + + ereport(LOG, (errmsg("Setting principal key [%s : %s] for the database", principal_key_name, provider_name))); + ret = SetPrincipalKey(principal_key_name, provider_name, ensure_new_key); + PG_RETURN_BOOL(ret); +} + +/* + * SQL interface for key rotation + */ +PG_FUNCTION_INFO_V1(pg_tde_rotate_key); +Datum +pg_tde_rotate_key(PG_FUNCTION_ARGS) +{ + char *new_principal_key_name = NULL; + char *new_provider_name = NULL; + bool ensure_new_key; + bool ret; + + if (!PG_ARGISNULL(0)) + new_principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); + if (!PG_ARGISNULL(1)) + new_provider_name = text_to_cstring(PG_GETARG_TEXT_PP(1)); + ensure_new_key = PG_GETARG_BOOL(2); + + + ereport(LOG, (errmsg("Rotating principal key to [%s : %s] for the database", new_principal_key_name, new_provider_name))); + ret = RotatePrincipalKey(new_principal_key_name, new_provider_name, ensure_new_key); + PG_RETURN_BOOL(ret); +} + +PG_FUNCTION_INFO_V1(pg_tde_principal_key_info); +Datum pg_tde_principal_key_info(PG_FUNCTION_ARGS) +{ + TupleDesc tupdesc; + Datum values[6]; + bool isnull[6]; + HeapTuple tuple; + Datum result; + TDEPrincipalKey *principal_key; + TimestampTz ts; + GenericKeyring *keyring; + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context that cannot accept type record"))); + + principal_key = GetPrincipalKey(MyDatabaseId, MyDatabaseTableSpace, NULL); + if (principal_key == NULL) + { + ereport(ERROR, + (errmsg("Principal key does not exists for the database"), + errhint("Use set_principal_key interface to set the principal key"))); + PG_RETURN_NULL(); + } + + keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId); + + /* Initialize the values and null flags */ + + /* TEXT: Principal key name */ + values[0] = CStringGetTextDatum(principal_key->keyInfo.keyId.name); + isnull[0] = false; + /* TEXT: Keyring provider name */ + if (keyring) + { + values[1] = CStringGetTextDatum(keyring->provider_name); + isnull[1] = false; + } + else + isnull[1] = true; + + /* INTEGERT: key provider id */ + values[2] = Int32GetDatum(principal_key->keyInfo.keyringId); + isnull[2] = false; + + /* TEXT: Principal key versioned name */ + values[3] = CStringGetTextDatum(principal_key->keyInfo.keyId.versioned_name); + isnull[3] = false; + /* INTEGERT: Principal key version */ + values[4] = Int32GetDatum(principal_key->keyInfo.keyId.version); + isnull[4] = false; + /* TIMESTAMP TZ: Principal key creation time */ + ts = (TimestampTz)principal_key->keyInfo.creationTime.tv_sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); + ts = (ts * USECS_PER_SEC) + principal_key->keyInfo.creationTime.tv_usec; + values[5] = TimestampTzGetDatum(ts); + isnull[5] = false; + + /* Form the tuple */ + tuple = heap_form_tuple(tupdesc, values, isnull); + + /* Make the tuple into a datum */ + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +} diff --git a/src/common/pg_tde_shmem.c b/src/common/pg_tde_shmem.c index db90b00a..628bc3b3 100644 --- a/src/common/pg_tde_shmem.c +++ b/src/common/pg_tde_shmem.c @@ -17,10 +17,10 @@ typedef struct TdeSharedState { - LWLock *masterKeyLock; - int masterKeyHashTrancheId; + LWLock *principalKeyLock; + int principalKeyHashTrancheId; void *rawDsaArea; /* DSA area pointer to store cache hashes */ - dshash_table_handle masterKeyHashHandle; + dshash_table_handle principalKeyHashHandle; } TdeSharedState; typedef struct TDELocalState @@ -29,7 +29,7 @@ typedef struct TDELocalState dsa_area **dsa; /* local dsa area for backend attached to the * dsa area created by postmaster at startup. */ - dshash_table *masterKeySharedHash; + dshash_table *principalKeySharedHash; } TDELocalState; static void tde_shmem_shutdown(int code, Datum arg); diff --git a/src/encryption/enc_tde.c b/src/encryption/enc_tde.c index 360d6533..f3973b70 100644 --- a/src/encryption/enc_tde.c +++ b/src/encryption/enc_tde.c @@ -232,12 +232,12 @@ PGTdePageAddItemExtended(RelFileLocator rel, * short lifespan until it is written to disk. */ void -AesEncryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes) +AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes) { unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Ensure we are getting a valid pointer here */ - Assert(master_key); + Assert(principal_key); memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid)); @@ -245,7 +245,7 @@ AesEncryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, Re *p_enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); memcpy(*p_enc_rel_key_data, rel_key_data, sizeof(RelKeyData)); - AesEncrypt(master_key->keyData, iv, ((unsigned char*)&rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_enc_rel_key_data)->internal_key), (int *)enc_key_bytes); + AesEncrypt(principal_key->keyData, iv, ((unsigned char*)&rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_enc_rel_key_data)->internal_key), (int *)enc_key_bytes); } /* @@ -255,12 +255,12 @@ AesEncryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, Re * to note that memory is allocated in the TopMemoryContext so we expect this to be added * to our key cache. */ -void AesDecryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes) +void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes) { unsigned char iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Ensure we are getting a valid pointer here */ - Assert(master_key); + Assert(principal_key); memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid)); @@ -271,5 +271,5 @@ void AesDecryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocato memcpy(*p_rel_key_data, enc_rel_key_data, sizeof(RelKeyData)); (*p_rel_key_data)->internal_key.ctx = NULL; - AesDecrypt(master_key->keyData, iv, ((unsigned char*) &enc_rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_rel_key_data)->internal_key) , (int *)key_bytes); + AesDecrypt(principal_key->keyData, iv, ((unsigned char*) &enc_rel_key_data->internal_key), INTERNAL_KEY_LEN, ((unsigned char *)&(*p_rel_key_data)->internal_key) , (int *)key_bytes); } diff --git a/src/include/access/pg_tde_tdemap.h b/src/include/access/pg_tde_tdemap.h index e0e06b63..5c2cbee9 100644 --- a/src/include/access/pg_tde_tdemap.h +++ b/src/include/access/pg_tde_tdemap.h @@ -11,7 +11,7 @@ #include "utils/rel.h" #include "access/xlog_internal.h" #include "catalog/pg_tablespace_d.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" #include "storage/fd.h" #include "storage/relfilelocator.h" @@ -23,7 +23,7 @@ typedef struct InternalKey typedef struct RelKeyData { - TDEMasterKeyId master_key_id; + TDEPrincipalKeyId principal_key_id; InternalKey internal_key; } RelKeyData; @@ -48,7 +48,7 @@ typedef struct XLogRelKey } XLogRelKey; extern RelKeyData* pg_tde_create_key_map_entry(const RelFileLocator *newrlocator); -extern void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_key_data, TDEMasterKeyInfo *master_key_info); +extern void pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_key_data, TDEPrincipalKeyInfo *principal_key_info); extern void pg_tde_delete_key_map_entry(const RelFileLocator *rlocator); extern void pg_tde_free_key_map_entry(const RelFileLocator *rlocator, off_t offset); @@ -57,13 +57,13 @@ extern RelKeyData *GetRelationKeyWithKeyring(RelFileLocator rel, GenericKeyring extern void pg_tde_delete_tde_files(Oid dbOid, Oid spcOid); -extern TDEMasterKeyInfo *pg_tde_get_master_key(Oid dbOid, Oid spcOid); -extern bool pg_tde_save_master_key(TDEMasterKeyInfo *master_key_info); -extern bool pg_tde_perform_rotate_key(TDEMasterKey *master_key, TDEMasterKey *new_master_key); +extern TDEPrincipalKeyInfo *pg_tde_get_principal_key(Oid dbOid, Oid spcOid); +extern bool pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info); +extern bool pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_principal_key); extern bool pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_size, char *k_file_data); -extern RelKeyData* tde_create_rel_key(Oid rel_id, InternalKey *key, TDEMasterKeyInfo *master_key_info); -extern RelKeyData *tde_encrypt_rel_key(TDEMasterKey *master_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator); -extern RelKeyData *tde_decrypt_rel_key(TDEMasterKey *master_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator); +extern RelKeyData* tde_create_rel_key(Oid rel_id, InternalKey *key, TDEPrincipalKeyInfo *principal_key_info); +extern RelKeyData *tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator); +extern RelKeyData *tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator); extern void pg_tde_set_db_file_paths(const RelFileLocator *rlocator, char *map_path, char *keydata_path); diff --git a/src/include/access/pg_tde_xlog.h b/src/include/access/pg_tde_xlog.h index 17a1c65c..1ed2e010 100644 --- a/src/include/access/pg_tde_xlog.h +++ b/src/include/access/pg_tde_xlog.h @@ -18,8 +18,8 @@ /* TDE XLOG resource manager */ #define XLOG_TDE_ADD_RELATION_KEY 0x00 -#define XLOG_TDE_ADD_MASTER_KEY 0x10 -#define XLOG_TDE_CLEAN_MASTER_KEY 0x20 +#define XLOG_TDE_ADD_PRINCIPAL_KEY 0x10 +#define XLOG_TDE_CLEAN_PRINCIPAL_KEY 0x20 #define XLOG_TDE_ROTATE_KEY 0x30 /* TODO: ID has to be registedred and changed: https://wiki.postgresql.org/wiki/CustomWALResourceManagers */ diff --git a/src/include/catalog/tde_global_catalog.h b/src/include/catalog/tde_global_catalog.h index 5dd44b9e..23d57380 100644 --- a/src/include/catalog/tde_global_catalog.h +++ b/src/include/catalog/tde_global_catalog.h @@ -13,7 +13,7 @@ #include "postgres.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" /* * Needed for glogbal data (WAL etc) keys identification in caches and storage. @@ -34,8 +34,8 @@ extern Size TDEGlCatEncStateSize(void); extern void TDEGlCatShmemInit(void); extern void TDEGlCatKeyInit(void); -extern TDEMasterKey *TDEGetGlCatKeyFromCache(void); -extern void TDEPutGlCatKeyInCache(TDEMasterKey *mkey); +extern TDEPrincipalKey *TDEGetGlCatKeyFromCache(void); +extern void TDEPutGlCatKeyInCache(TDEPrincipalKey *mkey); extern RelKeyData *GetGlCatInternalKey(Oid obj_id); #endif /*TDE_GLOBAL_CATALOG_H*/ diff --git a/src/include/catalog/tde_master_key.h b/src/include/catalog/tde_master_key.h deleted file mode 100644 index 2f70c9c9..00000000 --- a/src/include/catalog/tde_master_key.h +++ /dev/null @@ -1,84 +0,0 @@ -/*------------------------------------------------------------------------- - * - * tde_master_key.h - * TDE master key handling - * - * src/include/catalog/tde_master_key.h - * - *------------------------------------------------------------------------- - */ -#ifndef PG_TDE_MASTER_KEY_H -#define PG_TDE_MASTER_KEY_H - - -#include "postgres.h" -#include "catalog/tde_keyring.h" -#include "keyring/keyring_api.h" -#include "nodes/pg_list.h" -#include "storage/lwlock.h" - -#define DEFAULT_MASTER_KEY_VERSION 1 -#define MASTER_KEY_NAME_LEN TDE_KEY_NAME_LEN -#define MAX_MASTER_KEY_VERSION_NUM 100000 - -typedef struct TDEMasterKeyId -{ - uint32 version; - char name[MASTER_KEY_NAME_LEN]; - char versioned_name[MASTER_KEY_NAME_LEN + 4]; -} TDEMasterKeyId; - -typedef struct TDEMasterKeyInfo -{ - Oid databaseId; - Oid tablespaceId; - Oid userId; - Oid keyringId; - struct timeval creationTime; - TDEMasterKeyId keyId; -} TDEMasterKeyInfo; - -typedef struct TDEMasterKey -{ - TDEMasterKeyInfo keyInfo; - unsigned char keyData[MAX_KEY_DATA_SIZE]; - uint32 keyLength; -} TDEMasterKey; - -typedef struct XLogMasterKeyRotate -{ - Oid databaseId; - off_t map_size; - off_t keydata_size; - char buff[FLEXIBLE_ARRAY_MEMBER]; -} XLogMasterKeyRotate; - -#define SizeoOfXLogMasterKeyRotate offsetof(XLogMasterKeyRotate, buff) - -typedef struct XLogMasterKeyCleanup -{ - Oid databaseId; - Oid tablespaceId; -} XLogMasterKeyCleanup; - -extern void InitializeMasterKeyInfo(void); -extern void cleanup_master_key_info(Oid databaseId, Oid tablespaceId); -extern LWLock *tde_lwlock_mk_files(void); -extern LWLock *tde_lwlock_mk_cache(void); - -extern bool save_master_key_info(TDEMasterKeyInfo *masterKeyInfo); - -extern Oid GetMasterKeyProviderId(void); -extern TDEMasterKey* GetMasterKey(Oid dbOid, Oid spcOid, GenericKeyring *keyring); -extern bool SetMasterKey(const char *key_name, const char *provider_name, bool ensure_new_key); -extern bool RotateMasterKey(const char *new_key_name, const char *new_provider_name, bool ensure_new_key); -extern bool xl_tde_perform_rotate_key(XLogMasterKeyRotate *xlrec); -extern TDEMasterKey *set_master_key_with_keyring(const char *key_name, - GenericKeyring *keyring, - Oid dbOid, Oid spcOid, - bool ensure_new_key); -extern keyInfo *load_latest_versioned_key_name(TDEMasterKeyInfo *mastere_key_info, - GenericKeyring *keyring, - bool ensure_new_key); - -#endif /*PG_TDE_MASTER_KEY_H*/ diff --git a/src/include/catalog/tde_principal_key.h b/src/include/catalog/tde_principal_key.h new file mode 100644 index 00000000..ad273000 --- /dev/null +++ b/src/include/catalog/tde_principal_key.h @@ -0,0 +1,84 @@ +/*------------------------------------------------------------------------- + * + * tde_principal_key.h + * TDE principal key handling + * + * src/include/catalog/tde_principal_key.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_TDE_PRINCIPAL_KEY_H +#define PG_TDE_PRINCIPAL_KEY_H + + +#include "postgres.h" +#include "catalog/tde_keyring.h" +#include "keyring/keyring_api.h" +#include "nodes/pg_list.h" +#include "storage/lwlock.h" + +#define DEFAULT_PRINCIPAL_KEY_VERSION 1 +#define PRINCIPAL_KEY_NAME_LEN TDE_KEY_NAME_LEN +#define MAX_PRINCIPAL_KEY_VERSION_NUM 100000 + +typedef struct TDEPrincipalKeyId +{ + uint32 version; + char name[PRINCIPAL_KEY_NAME_LEN]; + char versioned_name[PRINCIPAL_KEY_NAME_LEN + 4]; +} TDEPrincipalKeyId; + +typedef struct TDEPrincipalKeyInfo +{ + Oid databaseId; + Oid tablespaceId; + Oid userId; + Oid keyringId; + struct timeval creationTime; + TDEPrincipalKeyId keyId; +} TDEPrincipalKeyInfo; + +typedef struct TDEPrincipalKey +{ + TDEPrincipalKeyInfo keyInfo; + unsigned char keyData[MAX_KEY_DATA_SIZE]; + uint32 keyLength; +} TDEPrincipalKey; + +typedef struct XLogPrincipalKeyRotate +{ + Oid databaseId; + off_t map_size; + off_t keydata_size; + char buff[FLEXIBLE_ARRAY_MEMBER]; +} XLogPrincipalKeyRotate; + +#define SizeoOfXLogPrincipalKeyRotate offsetof(XLogPrincipalKeyRotate, buff) + +typedef struct XLogPrincipalKeyCleanup +{ + Oid databaseId; + Oid tablespaceId; +} XLogPrincipalKeyCleanup; + +extern void InitializePrincipalKeyInfo(void); +extern void cleanup_principal_key_info(Oid databaseId, Oid tablespaceId); +extern LWLock *tde_lwlock_mk_files(void); +extern LWLock *tde_lwlock_mk_cache(void); + +extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo); + +extern Oid GetPrincipalKeyProviderId(void); +extern TDEPrincipalKey* GetPrincipalKey(Oid dbOid, Oid spcOid, GenericKeyring *keyring); +extern bool SetPrincipalKey(const char *key_name, const char *provider_name, bool ensure_new_key); +extern bool RotatePrincipalKey(const char *new_key_name, const char *new_provider_name, bool ensure_new_key); +extern bool xl_tde_perform_rotate_key(XLogPrincipalKeyRotate *xlrec); +extern TDEPrincipalKey *set_principal_key_with_keyring(const char *key_name, + GenericKeyring *keyring, + Oid dbOid, Oid spcOid, + bool ensure_new_key); +extern keyInfo *load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, + GenericKeyring *keyring, + bool ensure_new_key); + +#endif /*PG_TDE_PRINCIPAL_KEY_H*/ diff --git a/src/include/encryption/enc_tde.h b/src/include/encryption/enc_tde.h index ec7411de..1eef8100 100644 --- a/src/include/encryption/enc_tde.h +++ b/src/include/encryption/enc_tde.h @@ -52,7 +52,7 @@ PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page, pg_tde_crypt(_iv_prefix, _iv_prefix_len, _data, _data_len, _out, _key, "ENCRYPT-PAGE-ITEM"); \ } while(0) -extern void AesEncryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes); -extern void AesDecryptKey(const TDEMasterKey *master_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes); +extern void AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes); +extern void AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes); #endif /*ENC_TDE_H*/ diff --git a/src/pg_tde.c b/src/pg_tde.c index 2298fe67..632dc42c 100644 --- a/src/pg_tde.c +++ b/src/pg_tde.c @@ -26,7 +26,7 @@ #include "keyring/keyring_api.h" #include "common/pg_tde_shmem.h" #include "common/pg_tde_utils.h" -#include "catalog/tde_master_key.h" +#include "catalog/tde_principal_key.h" #include "keyring/keyring_file.h" #include "keyring/keyring_vault.h" #include "utils/builtins.h" @@ -102,7 +102,7 @@ _PG_init(void) } keyringRegisterVariables(); - InitializeMasterKeyInfo(); + InitializePrincipalKeyInfo(); #ifdef PERCONA_FORK XLogInitGUC(); TDEGlCatInitGUC(); diff --git a/src/smgr/pg_tde_smgr.c b/src/smgr/pg_tde_smgr.c index 7c4aa49f..0badb8fe 100644 --- a/src/smgr/pg_tde_smgr.c +++ b/src/smgr/pg_tde_smgr.c @@ -18,7 +18,7 @@ static RelKeyData* tde_smgr_get_key(SMgrRelation reln) { // TODO: This recursion counter is a dirty hack until the metadata is in the catalog - // As otherwise we would call GetMasterKey recursively and deadlock + // As otherwise we would call GetPrincipalKey recursively and deadlock static int recursion = 0; if(IsCatalogRelationOid(reln->smgr_rlocator.locator.relNumber)) @@ -35,7 +35,7 @@ tde_smgr_get_key(SMgrRelation reln) recursion++; - if(GetMasterKey(reln->smgr_rlocator.locator.relNumber, reln->smgr_rlocator.locator.spcOid, NULL)==NULL) + if(GetPrincipalKey(reln->smgr_rlocator.locator.relNumber, reln->smgr_rlocator.locator.spcOid, NULL)==NULL) { recursion--; return NULL; diff --git a/t/001_basic.pl b/t/001_basic.pl index 78b7da1f..599ddcb4 100644 --- a/t/001_basic.pl +++ b/t/001_basic.pl @@ -43,7 +43,7 @@ ok($rt_value == 1, "Restart Server"); $rt_value = $node->psql('postgres', "SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per');", extra_params => ['-a']); -$rt_value = $node->psql('postgres', "SELECT pg_tde_set_master_key('test-db-master-key','file-vault');", extra_params => ['-a']); +$rt_value = $node->psql('postgres', "SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault');", extra_params => ['-a']); $stdout = $node->safe_psql('postgres', 'CREATE TABLE test_enc(id SERIAL,k INTEGER,PRIMARY KEY (id)) USING pg_tde;', extra_params => ['-a']); PGTDE::append_to_file($stdout); diff --git a/t/002_rotate_key.pl b/t/002_rotate_key.pl index b51dd32f..9baf5d89 100644 --- a/t/002_rotate_key.pl +++ b/t/002_rotate_key.pl @@ -44,7 +44,7 @@ $rt_value = $node->psql('postgres', "SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per');", extra_params => ['-a']); $rt_value = $node->psql('postgres', "SELECT pg_tde_add_key_provider_file('file-2','/tmp/pg_tde_test_keyring_2.per');", extra_params => ['-a']); -$rt_value = $node->psql('postgres', "SELECT pg_tde_set_master_key('test-db-master-key','file-vault');", extra_params => ['-a']); +$rt_value = $node->psql('postgres', "SELECT pg_tde_set_principal_key('test-db-principal-key','file-vault');", extra_params => ['-a']); $stdout = $node->safe_psql('postgres', 'CREATE TABLE test_enc(id SERIAL,k INTEGER,PRIMARY KEY (id)) USING pg_tde;', extra_params => ['-a']); PGTDE::append_to_file($stdout); @@ -56,8 +56,8 @@ PGTDE::append_to_file($stdout); #rotate key -PGTDE::append_to_file("-- ROTATE KEY pg_tde_rotate_key('rotated-master-key','file-2');"); -$rt_value = $node->psql('postgres', "SELECT pg_tde_rotate_key('rotated-master-key','file-2');", extra_params => ['-a']); +PGTDE::append_to_file("-- ROTATE KEY pg_tde_rotate_key('rotated-principal-key','file-2');"); +$rt_value = $node->psql('postgres', "SELECT pg_tde_rotate_key('rotated-principal-key','file-2');", extra_params => ['-a']); $stdout = $node->safe_psql('postgres', 'SELECT * FROM test_enc ORDER BY id ASC;', extra_params => ['-a']); PGTDE::append_to_file($stdout); diff --git a/t/003_remote_config.pl b/t/003_remote_config.pl index 236206f5..10349afa 100644 --- a/t/003_remote_config.pl +++ b/t/003_remote_config.pl @@ -71,7 +71,7 @@ sub resp_hello { PGTDE::append_to_file($stdout); $rt_value = $node->psql('postgres', "SELECT pg_tde_add_key_provider_file('file-provider', json_object( 'type' VALUE 'remote', 'url' VALUE 'http://localhost:8888/hello' ));", extra_params => ['-a']); -$rt_value = $node->psql('postgres', "SELECT pg_tde_set_master_key('test-db-master-key','file-provider');", extra_params => ['-a']); +$rt_value = $node->psql('postgres', "SELECT pg_tde_set_principal_key('test-db-principal-key','file-provider');", extra_params => ['-a']); $stdout = $node->safe_psql('postgres', 'CREATE TABLE test_enc2(id SERIAL,k INTEGER,PRIMARY KEY (id)) USING pg_tde;', extra_params => ['-a']); PGTDE::append_to_file($stdout); diff --git a/t/004_file_config.pl b/t/004_file_config.pl index 0487510e..80ef9a77 100644 --- a/t/004_file_config.pl +++ b/t/004_file_config.pl @@ -35,7 +35,7 @@ PGTDE::append_to_file($stdout); $rt_value = $node->psql('postgres', "SELECT pg_tde_add_key_provider_file('file-provider', json_object( 'type' VALUE 'file', 'path' VALUE '/tmp/datafile-location' ));", extra_params => ['-a']); -$rt_value = $node->psql('postgres', "SELECT pg_tde_set_master_key('test-db-master-key','file-provider');", extra_params => ['-a']); +$rt_value = $node->psql('postgres', "SELECT pg_tde_set_principal_key('test-db-principal-key','file-provider');", extra_params => ['-a']); my $stdout = $node->safe_psql('postgres', 'CREATE TABLE test_enc1(id SERIAL,k INTEGER,PRIMARY KEY (id)) USING pg_tde;', extra_params => ['-a']); PGTDE::append_to_file($stdout); diff --git a/t/expected/002_rotate_key.out b/t/expected/002_rotate_key.out index a1730f4a..17c85d86 100644 --- a/t/expected/002_rotate_key.out +++ b/t/expected/002_rotate_key.out @@ -5,7 +5,7 @@ INSERT INTO test_enc (k) VALUES (5),(6); SELECT * FROM test_enc ORDER BY id ASC; 1|5 2|6 --- ROTATE KEY pg_tde_rotate_key('rotated-master-key','file-2'); +-- ROTATE KEY pg_tde_rotate_key('rotated-principal-key','file-2'); SELECT * FROM test_enc ORDER BY id ASC; 1|5 2|6