Move pg_tde files to one dir inside PGDATA (tablespaces issues)

We use tablespaceId as a part of IV for the internal keys encryption
which doesn't add any security because dbId (used as well) is unique
anyway.
But having tablespaceId really complicates things as a principal
created for the entire database but then different relations in this db
can be located in different tablespaces...

So it is better not to use tablespace with the principal key (database
level) as it belongs to the relation level.
pull/209/head
Andrew Pogrebnoi 10 months ago committed by GitHub
parent 8a69be4e01
commit 30cb32b5ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      meson.build
  2. 110
      src/access/pg_tde_tdemap.c
  3. 5
      src/access/pg_tde_xlog.c
  4. 1
      src/access/pg_tde_xlog_encrypt.c
  5. 24
      src/catalog/tde_global_space.c
  6. 85
      src/catalog/tde_keyring.c
  7. 59
      src/catalog/tde_principal_key.c
  8. 20
      src/common/pg_tde_utils.c
  9. 11
      src/encryption/enc_tde.c
  10. 22
      src/include/access/pg_tde_tdemap.h
  11. 7
      src/include/catalog/tde_global_space.h
  12. 15
      src/include/catalog/tde_keyring.h
  13. 7
      src/include/catalog/tde_principal_key.h
  14. 1
      src/include/common/pg_tde_utils.h
  15. 6
      src/include/encryption/enc_tde.h
  16. 5
      src/include/pg_tde.h
  17. 4
      src/include/pg_tde_defines.h
  18. 21
      src/pg_tde.c
  19. 14
      src/pg_tde_event_capture.c
  20. 2
      src/smgr/pg_tde_smgr.c
  21. 2
      src16/access/pg_tde_io.c
  22. 2
      src16/access/pg_tde_rewrite.c
  23. 6
      src16/access/pg_tdeam.c
  24. 2
      src17/access/pg_tde_io.c
  25. 2
      src17/access/pg_tde_rewrite.c
  26. 6
      src17/access/pg_tdeam.c

@ -128,7 +128,7 @@ if get_variable('percona_ext', false)
'trigger_on_view', 'trigger_on_view',
'change_access_method', 'change_access_method',
'insert_update_delete', 'insert_update_delete',
# 'tablespace', 'tablespace',
'vault_v2_test', 'vault_v2_test',
'alter_index', 'alter_index',
'merge_join', 'merge_join',

@ -55,9 +55,6 @@
} }
#endif #endif
#define PG_TDE_MAP_FILENAME "pg_tde.map"
#define PG_TDE_KEYDATA_FILENAME "pg_tde.dat"
#define PG_TDE_FILEMAGIC 0x01454454 /* version ID value = TDE 01 */ #define PG_TDE_FILEMAGIC 0x01454454 /* version ID value = TDE 01 */
@ -163,7 +160,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type
LWLock *lock_pk = tde_lwlock_enc_keys(); LWLock *lock_pk = tde_lwlock_enc_keys();
LWLockAcquire(lock_pk, LW_EXCLUSIVE); LWLockAcquire(lock_pk, LW_EXCLUSIVE);
principal_key = GetPrincipalKey(newrlocator->dbOid, newrlocator->spcOid, LW_EXCLUSIVE); principal_key = GetPrincipalKey(newrlocator->dbOid, LW_EXCLUSIVE);
if (principal_key == NULL) if (principal_key == NULL)
{ {
LWLockRelease(lock_pk); LWLockRelease(lock_pk);
@ -190,7 +187,7 @@ pg_tde_create_key_map_entry(const RelFileLocator *newrlocator, uint32 entry_type
/* Encrypt the key */ /* Encrypt the key */
rel_key_data = tde_create_rel_key(newrlocator->relNumber, &int_key, &principal_key->keyInfo); 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); enc_rel_key_data = tde_encrypt_rel_key(principal_key, rel_key_data, newrlocator->dbOid);
/* /*
* XLOG internal key * XLOG internal key
@ -244,12 +241,12 @@ tde_create_rel_key(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo
* Encrypts a given key and returns the encrypted one. * Encrypts a given key and returns the encrypted one.
*/ */
RelKeyData * RelKeyData *
tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, const RelFileLocator *rlocator) tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, Oid dbOid)
{ {
RelKeyData *enc_rel_key_data; RelKeyData *enc_rel_key_data;
size_t enc_key_bytes; size_t enc_key_bytes;
AesEncryptKey(principal_key, rlocator, rel_key_data, &enc_rel_key_data, &enc_key_bytes); AesEncryptKey(principal_key, dbOid, rel_key_data, &enc_rel_key_data, &enc_key_bytes);
return enc_rel_key_data; return enc_rel_key_data;
} }
@ -259,13 +256,13 @@ tde_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, co
* Returns true if both map and key data files are created. * Returns true if both map and key data files are created.
*/ */
void void
pg_tde_delete_tde_files(Oid dbOid, Oid spcOid) pg_tde_delete_tde_files(Oid dbOid)
{ {
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
char db_keydata_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0};
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(dbOid, spcOid, db_map_path, db_keydata_path); pg_tde_set_db_file_paths(dbOid, db_map_path, db_keydata_path);
/* Remove these files without emitting any error */ /* Remove these files without emitting any error */
PathNameDeleteTemporaryFile(db_map_path, false); PathNameDeleteTemporaryFile(db_map_path, false);
@ -294,7 +291,6 @@ pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info)
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(principal_key_info->databaseId, pg_tde_set_db_file_paths(principal_key_info->databaseId,
principal_key_info->tablespaceId,
db_map_path, db_keydata_path); db_map_path, db_keydata_path);
ereport(LOG, (errmsg("pg_tde_save_principal_key"))); ereport(LOG, (errmsg("pg_tde_save_principal_key")));
@ -434,7 +430,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{ {
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, NULL);
ereport(FATAL, ereport(FATAL,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not write tde map file \"%s\": %m", errmsg("could not write tde map file \"%s\": %m",
@ -444,7 +440,7 @@ pg_tde_write_one_map_entry(int fd, const RelFileLocator *rlocator, uint32 flags,
{ {
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, NULL);
ereport(data_sync_elevel(ERROR), ereport(data_sync_elevel(ERROR),
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", db_map_path))); errmsg("could not fsync file \"%s\": %m", db_map_path)));
@ -525,7 +521,7 @@ pg_tde_write_key_map_entry(const RelFileLocator *rlocator, RelKeyData *enc_rel_k
Assert(rlocator); Assert(rlocator);
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, db_keydata_path); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, db_keydata_path);
/* Create the map entry and then add the encrypted key to the data file */ /* Create the map entry and then add the encrypted key to the data file */
key_index = pg_tde_write_map_entry(rlocator, enc_rel_key_data->internal_key.rel_type, db_map_path, principal_key_info); key_index = pg_tde_write_map_entry(rlocator, enc_rel_key_data->internal_key.rel_type, db_map_path, principal_key_info);
@ -550,7 +546,7 @@ pg_tde_delete_key_map_entry(const RelFileLocator *rlocator, uint32 key_type)
Assert(rlocator); Assert(rlocator);
/* Get the file paths */ /* Get the file paths */
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, db_keydata_path); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, db_keydata_path);
errno = 0; errno = 0;
/* Remove the map entry if found */ /* Remove the map entry if found */
@ -596,7 +592,7 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t
Assert(rlocator); Assert(rlocator);
/* Get the file paths */ /* Get the file paths */
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, NULL);
/* Remove the map entry if found */ /* Remove the map entry if found */
key_index = pg_tde_process_map_entry(rlocator, key_type, db_map_path, &offset, true); key_index = pg_tde_process_map_entry(rlocator, key_type, db_map_path, &offset, true);
@ -610,17 +606,6 @@ pg_tde_free_key_map_entry(const RelFileLocator *rlocator, uint32 key_type, off_t
db_map_path))); db_map_path)));
} }
/*
* Remove TDE files it was the last TDE relation in a custom tablespace.
* DROP TABLESPACE needs an empty dir.
*/
if (rlocator->spcOid != GLOBALTABLESPACE_OID &&
rlocator->spcOid != DEFAULTTABLESPACE_OID &&
pg_tde_process_map_entry(NULL, key_type, db_map_path, &start, false) == -1)
{
pg_tde_delete_tde_files(rlocator->dbOid, rlocator->spcOid);
cleanup_key_provider_info(rlocator->dbOid, rlocator->spcOid);
}
} }
/* /*
@ -689,7 +674,6 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId,
principal_key->keyInfo.tablespaceId,
db_map_path, db_keydata_path); db_map_path, db_keydata_path);
/* /*
@ -729,14 +713,13 @@ pg_tde_perform_rotate_key(TDEPrincipalKey *principal_key, TDEPrincipalKey *new_p
rloc.relNumber = read_map_entry.relNumber; rloc.relNumber = read_map_entry.relNumber;
rloc.dbOid = principal_key->keyInfo.databaseId; rloc.dbOid = principal_key->keyInfo.databaseId;
rloc.spcOid = principal_key->keyInfo.tablespaceId;
/* Let's get the decrypted key and re-encrypt it with the new key. */ /* Let's get the decrypted key and re-encrypt it with the new 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); 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 */ /* Decrypt and re-encrypt keys */
rel_key_data[OLD_PRINCIPAL_KEY] = tde_decrypt_rel_key(principal_key, enc_rel_key_data[OLD_PRINCIPAL_KEY], &rloc); rel_key_data[OLD_PRINCIPAL_KEY] = tde_decrypt_rel_key(principal_key, enc_rel_key_data[OLD_PRINCIPAL_KEY], principal_key->keyInfo.databaseId);
enc_rel_key_data[NEW_PRINCIPAL_KEY] = tde_encrypt_rel_key(new_principal_key, 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], principal_key->keyInfo.databaseId);
/* Write the given entry at the location pointed by prev_pos */ /* Write the given entry at the location pointed by prev_pos */
prev_pos[NEW_PRINCIPAL_KEY] = curr_pos[NEW_PRINCIPAL_KEY]; prev_pos[NEW_PRINCIPAL_KEY] = curr_pos[NEW_PRINCIPAL_KEY];
@ -814,7 +797,6 @@ pg_tde_write_map_keydata_files(off_t map_size, char *m_file_data, off_t keydata_
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(fheader->principal_key_info.databaseId, pg_tde_set_db_file_paths(fheader->principal_key_info.databaseId,
fheader->principal_key_info.tablespaceId,
db_map_path, db_keydata_path); db_map_path, db_keydata_path);
/* Initialize the new files and set the names */ /* Initialize the new files and set the names */
@ -870,10 +852,7 @@ FINALIZE:
} }
/* /*
* Move relation's key to the new physical location and cache it with the new * Saves the relation key with the new relfilenode.
* relfilenode. It recreates *.map and *.dat files with the old principal key
* and re-encrypted with the new relfilenode internal key. And copies the
* old keyring to the new location.
* Needed by ALTER TABLE SET TABLESPACE for example. * Needed by ALTER TABLE SET TABLESPACE for example.
*/ */
bool bool
@ -890,40 +869,21 @@ pg_tde_move_rel_key(const RelFileLocator *newrlocator, const RelFileLocator *old
off_t offset = 0; off_t offset = 0;
int32 key_index = 0; int32 key_index = 0;
pg_tde_set_db_file_paths(oldrlocator->dbOid, oldrlocator->spcOid, db_map_path, db_keydata_path); pg_tde_set_db_file_paths(oldrlocator->dbOid, db_map_path, db_keydata_path);
LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE); LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE);
principal_key = GetPrincipalKey(oldrlocator->dbOid, oldrlocator->spcOid, LW_EXCLUSIVE); principal_key = GetPrincipalKey(oldrlocator->dbOid, LW_EXCLUSIVE);
Assert(principal_key); Assert(principal_key);
/* /*
* Copy kering provider info. * We don't use internal_key cache to avoid locking complications.
*
* TODO: we can potentially avoid moving keyring and key tde files keeping
* these files always in dbOid+MyDatabaseTableSpace path. But the
* background writer isn't aware of MyDatabaseTableSpace hence it won't
* work with SMGR -> tde_heap. Revisit this after chages in SMGR (mdcreate)
* interface.
*/ */
keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId, oldrlocator->dbOid, oldrlocator->spcOid);
Assert(keyring);
memcpy(provider_rec.provider_name, keyring->provider_name, sizeof(keyring->provider_name));
provider_rec.provider_type = keyring->type;
memcpy(provider_rec.options, keyring->options, sizeof(keyring->options));
copy_key_provider_info(&provider_rec, newrlocator->dbOid, newrlocator->spcOid, true);
principal_key->keyInfo.keyringId = provider_rec.provider_id;
key_index = pg_tde_process_map_entry(oldrlocator, MAP_ENTRY_VALID, db_map_path, &offset, false); key_index = pg_tde_process_map_entry(oldrlocator, MAP_ENTRY_VALID, db_map_path, &offset, false);
Assert(key_index != -1); Assert(key_index != -1);
/*
* Re-encrypt relation key. We don't use internal_key cache to avoid locking
* complications.
*/
enc_key = pg_tde_read_keydata(db_keydata_path, key_index, principal_key); enc_key = pg_tde_read_keydata(db_keydata_path, key_index, principal_key);
rel_key = tde_decrypt_rel_key(principal_key, enc_key, oldrlocator); rel_key = tde_decrypt_rel_key(principal_key, enc_key, oldrlocator->dbOid);
enc_key = tde_encrypt_rel_key(principal_key, rel_key, newrlocator);
xlrec.rlocator = *newrlocator; xlrec.rlocator = *newrlocator;
xlrec.relKey = *enc_key; xlrec.relKey = *enc_key;
@ -983,7 +943,7 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
* key. * key.
*/ */
LWLockAcquire(lock_pk, LW_SHARED); LWLockAcquire(lock_pk, LW_SHARED);
principal_key = GetPrincipalKey(rlocator->dbOid, rlocator->spcOid, LW_SHARED); principal_key = GetPrincipalKey(rlocator->dbOid, LW_SHARED);
if (principal_key == NULL) if (principal_key == NULL)
{ {
LWLockRelease(lock_pk); LWLockRelease(lock_pk);
@ -992,7 +952,7 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
} }
/* Get the file paths */ /* Get the file paths */
pg_tde_set_db_file_paths(rlocator->dbOid, rlocator->spcOid, db_map_path, db_keydata_path); pg_tde_set_db_file_paths(rlocator->dbOid, db_map_path, db_keydata_path);
if (no_map_ok && access(db_map_path, F_OK) == -1) if (no_map_ok && access(db_map_path, F_OK) == -1)
{ {
@ -1011,23 +971,11 @@ pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool n
enc_rel_key_data = pg_tde_read_keydata(db_keydata_path, key_index, principal_key); enc_rel_key_data = pg_tde_read_keydata(db_keydata_path, key_index, principal_key);
LWLockRelease(lock_pk); LWLockRelease(lock_pk);
rel_key_data = tde_decrypt_rel_key(principal_key, enc_rel_key_data, rlocator); rel_key_data = tde_decrypt_rel_key(principal_key, enc_rel_key_data, rlocator->dbOid);
return rel_key_data; return rel_key_data;
} }
inline void
pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_path)
{
char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid);
if (map_path)
join_path_components(map_path, db_path, PG_TDE_MAP_FILENAME);
if (keydata_path)
join_path_components(keydata_path, db_path, PG_TDE_KEYDATA_FILENAME);
pfree(db_path);
}
/* /*
* Returns the index of the read map if we find a valid match; i.e. * Returns the index of the read map if we find a valid match; i.e.
* - flags is set to MAP_ENTRY_VALID and the relNumber matches the one * - flags is set to MAP_ENTRY_VALID and the relNumber matches the one
@ -1147,12 +1095,12 @@ pg_tde_read_keydata(char *db_keydata_path, int32 key_index, TDEPrincipalKey *pri
* Decrypts a given key and returns the decrypted one. * Decrypts a given key and returns the decrypted one.
*/ */
RelKeyData * RelKeyData *
tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator) tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, Oid dbOid)
{ {
RelKeyData *rel_key_data = NULL; RelKeyData *rel_key_data = NULL;
size_t key_bytes; size_t key_bytes;
AesDecryptKey(principal_key, rlocator, &rel_key_data, enc_rel_key_data, &key_bytes); AesDecryptKey(principal_key, dbOid, &rel_key_data, enc_rel_key_data, &key_bytes);
return rel_key_data; return rel_key_data;
} }
@ -1321,7 +1269,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
{ {
char db_keydata_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, NULL, db_keydata_path);
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_NO_DATA_FOUND), (errcode(ERRCODE_NO_DATA_FOUND),
errmsg("could not find the required key at index %d in tde data file \"%s\": %m", errmsg("could not find the required key at index %d in tde data file \"%s\": %m",
@ -1335,7 +1283,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
{ {
char db_keydata_path[MAXPGPATH] = {0}; char db_keydata_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, principal_key->keyInfo.tablespaceId, NULL, db_keydata_path); pg_tde_set_db_file_paths(principal_key->keyInfo.databaseId, NULL, db_keydata_path);
ereport(FATAL, ereport(FATAL,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not read key at index %d in tde key data file \"%s\": %m", errmsg("could not read key at index %d in tde key data file \"%s\": %m",
@ -1352,7 +1300,7 @@ pg_tde_read_one_keydata(int keydata_fd, int32 key_index, TDEPrincipalKey *princi
* a LW_SHARED or higher lock on files before calling this function. * a LW_SHARED or higher lock on files before calling this function.
*/ */
TDEPrincipalKeyInfo * TDEPrincipalKeyInfo *
pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid) pg_tde_get_principal_key_info(Oid dbOid)
{ {
int fd = -1; int fd = -1;
TDEFileHeader fheader; TDEFileHeader fheader;
@ -1362,7 +1310,7 @@ pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid)
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
/* Set the file paths */ /* Set the file paths */
pg_tde_set_db_file_paths(dbOid, spcOid, db_map_path, NULL); pg_tde_set_db_file_paths(dbOid, db_map_path, NULL);
/* /*
* Ensuring that we always open the file in binary mode. The caller must * Ensuring that we always open the file in binary mode. The caller must

@ -17,7 +17,6 @@
#include "access/xlog.h" #include "access/xlog.h"
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "access/xloginsert.h" #include "access/xloginsert.h"
#include "catalog/pg_tablespace_d.h"
#include "catalog/tde_keyring.h" #include "catalog/tde_keyring.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/shmem.h" #include "storage/shmem.h"
@ -108,13 +107,13 @@ tdeheap_rmgr_desc(StringInfo buf, XLogReaderState *record)
{ {
TDEPrincipalKeyInfo *xlrec = (TDEPrincipalKeyInfo *) XLogRecGetData(record); TDEPrincipalKeyInfo *xlrec = (TDEPrincipalKeyInfo *) XLogRecGetData(record);
appendStringInfo(buf, "add tde principal key for db %u/%u", xlrec->databaseId, xlrec->tablespaceId); appendStringInfo(buf, "add tde principal key for db %u", xlrec->databaseId);
} }
if (info == XLOG_TDE_EXTENSION_INSTALL_KEY) if (info == XLOG_TDE_EXTENSION_INSTALL_KEY)
{ {
XLogExtensionInstall *xlrec = (XLogExtensionInstall *) XLogRecGetData(record); XLogExtensionInstall *xlrec = (XLogExtensionInstall *) XLogRecGetData(record);
appendStringInfo(buf, "tde extension install for db %u/%u", xlrec->database_id, xlrec->tablespace_id); appendStringInfo(buf, "tde extension install for db %u", xlrec->database_id);
} }
if (info == XLOG_TDE_ROTATE_KEY) if (info == XLOG_TDE_ROTATE_KEY)
{ {

@ -18,7 +18,6 @@
#include "access/xlog.h" #include "access/xlog.h"
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "access/xloginsert.h" #include "access/xloginsert.h"
#include "catalog/pg_tablespace_d.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/shmem.h" #include "storage/shmem.h"
#include "utils/guc.h" #include "utils/guc.h"

@ -14,7 +14,6 @@
#ifdef PERCONA_EXT #ifdef PERCONA_EXT
#include "catalog/pg_tablespace_d.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "access/pg_tde_tdemap.h" #include "access/pg_tde_tdemap.h"
@ -36,14 +35,13 @@
#define KEYRING_DEFAULT_FILE_NAME "pg_tde_default_keyring_CHANGE_AND_REMOVE_IT" #define KEYRING_DEFAULT_FILE_NAME "pg_tde_default_keyring_CHANGE_AND_REMOVE_IT"
#define DefaultKeyProvider GetKeyProviderByName(KEYRING_DEFAULT_NAME, \ #define DefaultKeyProvider GetKeyProviderByName(KEYRING_DEFAULT_NAME, \
GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID) GLOBAL_DATA_TDE_OID)
#ifndef FRONTEND #ifndef FRONTEND
static void init_keys(void); static void init_keys(void);
static void init_default_keyring(void); static void init_default_keyring(void);
static TDEPrincipalKey *create_principal_key(const char *key_name, static TDEPrincipalKey *create_principal_key(const char *key_name,
GenericKeyring *keyring, Oid dbOid, GenericKeyring *keyring, Oid dbOid);
Oid spcOid);
#endif /* !FRONTEND */ #endif /* !FRONTEND */
@ -53,7 +51,7 @@ TDEInitGlobalKeys(const char *dir)
#ifndef FRONTEND #ifndef FRONTEND
char db_map_path[MAXPGPATH] = {0}; char db_map_path[MAXPGPATH] = {0};
pg_tde_set_db_file_paths(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, db_map_path, NULL); pg_tde_set_db_file_paths(GLOBAL_DATA_TDE_OID, db_map_path, NULL);
if (access(db_map_path, F_OK) == -1) if (access(db_map_path, F_OK) == -1)
{ {
init_default_keyring(); init_default_keyring();
@ -87,7 +85,7 @@ TDEInitGlobalKeys(const char *dir)
static void static void
init_default_keyring(void) init_default_keyring(void)
{ {
if (GetAllKeyringProviders(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID) == NIL) if (GetAllKeyringProviders(GLOBAL_DATA_TDE_OID) == NIL)
{ {
char path[MAXPGPATH] = {0}; char path[MAXPGPATH] = {0};
static KeyringProvideRecord provider = static KeyringProvideRecord provider =
@ -100,7 +98,7 @@ init_default_keyring(void)
elog(WARNING, "unable to get current working dir"); elog(WARNING, "unable to get current working dir");
/* TODO: not sure about the location. Currently it's in $PGDATA */ /* TODO: not sure about the location. Currently it's in $PGDATA */
join_path_components(path, path, KEYRING_DEFAULT_FILE_NAME); join_path_components(path, PG_TDE_DATA_DIR, KEYRING_DEFAULT_FILE_NAME);
snprintf(provider.options, MAX_KEYRING_OPTION_LEN, snprintf(provider.options, MAX_KEYRING_OPTION_LEN,
"{" "{"
@ -109,11 +107,13 @@ init_default_keyring(void)
"}", path "}", path
); );
pg_tde_init_data_dir();
/* /*
* TODO: should we remove it automaticaly on * TODO: should we remove it automaticaly on
* pg_tde_rotate_principal_key() ? * pg_tde_rotate_principal_key() ?
*/ */
save_new_key_provider_info(&provider, GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, false); save_new_key_provider_info(&provider, GLOBAL_DATA_TDE_OID, false);
elog(INFO, elog(INFO,
"default keyring has been created for the global tablespace (WAL)." "default keyring has been created for the global tablespace (WAL)."
" Change it with pg_tde_add_key_provider_* and run pg_tde_rotate_principal_key." " Change it with pg_tde_add_key_provider_* and run pg_tde_rotate_principal_key."
@ -142,7 +142,7 @@ init_keys(void)
mkey = create_principal_key(PRINCIPAL_KEY_DEFAULT_NAME, mkey = create_principal_key(PRINCIPAL_KEY_DEFAULT_NAME,
DefaultKeyProvider, DefaultKeyProvider,
GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID); GLOBAL_DATA_TDE_OID);
memset(&int_key, 0, sizeof(InternalKey)); memset(&int_key, 0, sizeof(InternalKey));
@ -159,7 +159,7 @@ init_keys(void)
rlocator = &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID); rlocator = &GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID);
rel_key_data = tde_create_rel_key(rlocator->relNumber, &int_key, &mkey->keyInfo); rel_key_data = tde_create_rel_key(rlocator->relNumber, &int_key, &mkey->keyInfo);
enc_rel_key_data = tde_encrypt_rel_key(mkey, rel_key_data, rlocator); enc_rel_key_data = tde_encrypt_rel_key(mkey, rel_key_data, rlocator->dbOid);
pg_tde_write_key_map_entry(rlocator, enc_rel_key_data, &mkey->keyInfo); pg_tde_write_key_map_entry(rlocator, enc_rel_key_data, &mkey->keyInfo);
pfree(enc_rel_key_data); pfree(enc_rel_key_data);
pfree(mkey); pfree(mkey);
@ -175,15 +175,13 @@ init_keys(void)
* first. * first.
*/ */
static TDEPrincipalKey * static TDEPrincipalKey *
create_principal_key(const char *key_name, GenericKeyring *keyring, create_principal_key(const char *key_name, GenericKeyring *keyring, Oid dbOid)
Oid dbOid, Oid spcOid)
{ {
TDEPrincipalKey *principalKey; TDEPrincipalKey *principalKey;
keyInfo *keyInfo = NULL; keyInfo *keyInfo = NULL;
principalKey = palloc(sizeof(TDEPrincipalKey)); principalKey = palloc(sizeof(TDEPrincipalKey));
principalKey->keyInfo.databaseId = dbOid; principalKey->keyInfo.databaseId = dbOid;
principalKey->keyInfo.tablespaceId = spcOid;
principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION;
principalKey->keyInfo.keyringId = keyring->key_id; principalKey->keyInfo.keyringId = keyring->key_id;
strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN);

@ -47,24 +47,24 @@ typedef enum ProviderScanType
PROVIDER_SCAN_ALL PROVIDER_SCAN_ALL
} ProviderScanType; } ProviderScanType;
#define PG_TDE_KEYRING_FILENAME "pg_tde_keyrings" #define PG_TDE_KEYRING_FILENAME "pg_tde_%d_keyring"
static FileKeyring *load_file_keyring_provider_options(char *keyring_options); static FileKeyring *load_file_keyring_provider_options(char *keyring_options);
static GenericKeyring *load_keyring_provider_options(ProviderType provider_type, char *keyring_options); static GenericKeyring *load_keyring_provider_options(ProviderType provider_type, char *keyring_options);
static VaultV2Keyring *load_vaultV2_keyring_provider_options(char *keyring_options); static VaultV2Keyring *load_vaultV2_keyring_provider_options(char *keyring_options);
static void debug_print_kerying(GenericKeyring *keyring); static void debug_print_kerying(GenericKeyring *keyring);
static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider); static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider);
static char *get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid); static inline void get_keyring_infofile_path(char *resPath, Oid dbOid);
static bool fetch_next_key_provider(int fd, off_t *curr_pos, KeyringProvideRecord *provider); static bool fetch_next_key_provider(int fd, off_t *curr_pos, KeyringProvideRecord *provider);
#ifdef FRONTEND #ifdef FRONTEND
static SimplePtrList *scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid spcOid); static SimplePtrList *scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid);
static void simple_list_free(SimplePtrList *list); static void simple_list_free(SimplePtrList *list);
#else #else
static List *scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid spcOid); static List *scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid);
PG_FUNCTION_INFO_V1(pg_tde_add_key_provider_internal); PG_FUNCTION_INFO_V1(pg_tde_add_key_provider_internal);
Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS); Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS);
@ -77,9 +77,8 @@ Datum pg_tde_list_all_key_providers(PG_FUNCTION_ARGS);
static void key_provider_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg); static void key_provider_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
static const char *get_keyring_provider_typename(ProviderType p_type); static const char *get_keyring_provider_typename(ProviderType p_type);
static uint32 write_key_provider_info(KeyringProvideRecord *provider, static uint32 write_key_provider_info(KeyringProvideRecord *provider,
Oid database_id, Oid tablespace_id, Oid database_id, off_t position,
off_t position, bool error_if_exists, bool error_if_exists, bool write_xlog);
bool write_xlog);
static Size initialize_shared_state(void *start_address); static Size initialize_shared_state(void *start_address);
static Size required_shared_mem_size(void); static Size required_shared_mem_size(void);
@ -137,7 +136,7 @@ key_provider_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info,
(errmsg("failed to perform initialization. database already has %d TDE tables", tde_tbl_count))); (errmsg("failed to perform initialization. database already has %d TDE tables", tde_tbl_count)));
return; return;
} }
cleanup_key_provider_info(ext_info->database_id, ext_info->tablespace_id); cleanup_key_provider_info(ext_info->database_id);
} }
ProviderType ProviderType
@ -169,16 +168,16 @@ get_keyring_provider_typename(ProviderType p_type)
} }
List * List *
GetAllKeyringProviders(Oid dbOid, Oid spcOid) GetAllKeyringProviders(Oid dbOid)
{ {
return scan_key_provider_file(PROVIDER_SCAN_ALL, NULL, dbOid, spcOid); return scan_key_provider_file(PROVIDER_SCAN_ALL, NULL, dbOid);
} }
GenericKeyring * GenericKeyring *
GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid) GetKeyProviderByName(const char *provider_name, Oid dbOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_NAME, (void *) provider_name, dbOid, spcOid); List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_NAME, (void *) provider_name, dbOid);
if (providers != NIL) if (providers != NIL)
{ {
@ -197,8 +196,8 @@ GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid)
static uint32 static uint32
write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
Oid tablespace_id, off_t position, bool error_if_exists, bool write_xlog) off_t position, bool error_if_exists, bool write_xlog)
{ {
off_t bytes_written = 0; off_t bytes_written = 0;
off_t curr_pos = 0; off_t curr_pos = 0;
@ -209,7 +208,7 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
Assert(provider != NULL); Assert(provider != NULL);
get_keyring_infofile_path(kp_info_path, database_id, tablespace_id); get_keyring_infofile_path(kp_info_path, database_id);
LWLockAcquire(tde_provider_info_lock(), LW_EXCLUSIVE); LWLockAcquire(tde_provider_info_lock(), LW_EXCLUSIVE);
@ -258,7 +257,6 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
KeyringProviderXLRecord xlrec; KeyringProviderXLRecord xlrec;
xlrec.database_id = database_id; xlrec.database_id = database_id;
xlrec.tablespace_id = tablespace_id;
xlrec.offset_in_file = curr_pos; xlrec.offset_in_file = curr_pos;
memcpy(&xlrec.provider, provider, sizeof(KeyringProvideRecord)); memcpy(&xlrec.provider, provider, sizeof(KeyringProvideRecord));
@ -308,33 +306,24 @@ write_key_provider_info(KeyringProvideRecord *provider, Oid database_id,
* Save the key provider info to the file * Save the key provider info to the file
*/ */
uint32 uint32
save_new_key_provider_info(KeyringProvideRecord* provider, Oid databaseId, Oid tablespaceId, bool write_xlog) save_new_key_provider_info(KeyringProvideRecord* provider, Oid databaseId, bool write_xlog)
{ {
return write_key_provider_info(provider, databaseId, tablespaceId, -1, true, write_xlog); return write_key_provider_info(provider, databaseId, -1, true, write_xlog);
}
/*
* Save the key provider info to the file but don't fail if it is already exists.
*/
uint32
copy_key_provider_info(KeyringProvideRecord* provider, Oid newdatabaseId, Oid newtablespaceId, bool write_xlog)
{
return write_key_provider_info(provider, newdatabaseId, newtablespaceId, -1, false, write_xlog);
} }
uint32 uint32
redo_key_provider_info(KeyringProviderXLRecord *xlrec) redo_key_provider_info(KeyringProviderXLRecord *xlrec)
{ {
return write_key_provider_info(&xlrec->provider, xlrec->database_id, xlrec->tablespace_id, xlrec->offset_in_file, true, false); return write_key_provider_info(&xlrec->provider, xlrec->database_id, xlrec->offset_in_file, true, false);
} }
void void
cleanup_key_provider_info(Oid databaseId, Oid tablespaceId) cleanup_key_provider_info(Oid databaseId)
{ {
/* Remove the key provider info file */ /* Remove the key provider info file */
char kp_info_path[MAXPGPATH] = {0}; char kp_info_path[MAXPGPATH] = {0};
get_keyring_infofile_path(kp_info_path, databaseId, tablespaceId); get_keyring_infofile_path(kp_info_path, databaseId);
PathNameDeleteTemporaryFile(kp_info_path, false); PathNameDeleteTemporaryFile(kp_info_path, false);
} }
@ -346,19 +335,12 @@ pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS)
char *options = text_to_cstring(PG_GETARG_TEXT_PP(2)); char *options = text_to_cstring(PG_GETARG_TEXT_PP(2));
bool is_global = PG_GETARG_BOOL(3); bool is_global = PG_GETARG_BOOL(3);
KeyringProvideRecord provider; KeyringProvideRecord provider;
Oid dbOid = MyDatabaseId; Oid dbOid = is_global ? GLOBAL_DATA_TDE_OID : MyDatabaseId;
Oid spcOid = MyDatabaseTableSpace;
if (is_global)
{
dbOid = GLOBAL_DATA_TDE_OID;
spcOid = GLOBALTABLESPACE_OID;
}
strncpy(provider.options, options, sizeof(provider.options)); strncpy(provider.options, options, sizeof(provider.options));
strncpy(provider.provider_name, provider_name, sizeof(provider.provider_name)); strncpy(provider.provider_name, provider_name, sizeof(provider.provider_name));
provider.provider_type = get_keyring_provider_from_typename(provider_type); provider.provider_type = get_keyring_provider_from_typename(provider_type);
save_new_key_provider_info(&provider, dbOid, spcOid, true); save_new_key_provider_info(&provider, dbOid, true);
PG_RETURN_INT32(provider.provider_id); PG_RETURN_INT32(provider.provider_id);
} }
@ -366,7 +348,7 @@ pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS)
Datum Datum
pg_tde_list_all_key_providers(PG_FUNCTION_ARGS) pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
{ {
List *all_providers = GetAllKeyringProviders(MyDatabaseId, MyDatabaseTableSpace); List *all_providers = GetAllKeyringProviders(MyDatabaseId);
ListCell *lc; ListCell *lc;
Tuplestorestate *tupstore; Tuplestorestate *tupstore;
TupleDesc tupdesc; TupleDesc tupdesc;
@ -419,10 +401,10 @@ pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
} }
GenericKeyring * GenericKeyring *
GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid) GetKeyProviderByID(int provider_id, Oid dbOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid); List *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid);
if (providers != NIL) if (providers != NIL)
{ {
@ -436,10 +418,10 @@ GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid)
#ifdef FRONTEND #ifdef FRONTEND
GenericKeyring * GenericKeyring *
GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid) GetKeyProviderByID(int provider_id, Oid dbOid)
{ {
GenericKeyring *keyring = NULL; GenericKeyring *keyring = NULL;
SimplePtrList *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid, spcOid); SimplePtrList *providers = scan_key_provider_file(PROVIDER_SCAN_BY_ID, &provider_id, dbOid);
if (providers != NULL) if (providers != NULL)
{ {
@ -474,7 +456,7 @@ static List *
#else #else
static SimplePtrList * static SimplePtrList *
#endif #endif
scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid spcOid) scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid)
{ {
off_t curr_pos = 0; off_t curr_pos = 0;
int fd; int fd;
@ -489,7 +471,7 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid
if (scanType != PROVIDER_SCAN_ALL) if (scanType != PROVIDER_SCAN_ALL)
Assert(scanKey != NULL); Assert(scanKey != NULL);
get_keyring_infofile_path(kp_info_path, dbOid, spcOid); get_keyring_infofile_path(kp_info_path, dbOid);
LWLockAcquire(tde_provider_info_lock(), LW_SHARED); LWLockAcquire(tde_provider_info_lock(), LW_SHARED);
@ -661,15 +643,10 @@ debug_print_kerying(GenericKeyring *keyring)
} }
} }
static char * static inline void
get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid) get_keyring_infofile_path(char *resPath, Oid dbOid)
{ {
char *db_path = pg_tde_get_tde_file_dir(dbOid, spcOid); join_path_components(resPath, PG_TDE_DATA_DIR, psprintf(PG_TDE_KEYRING_FILENAME, dbOid));
Assert(db_path != NULL);
join_path_components(resPath, db_path, PG_TDE_KEYRING_FILENAME);
pfree(db_path);
return resPath;
} }
/* /*

@ -75,16 +75,16 @@ static void shared_memory_shutdown(int code, Datum arg);
static void principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg); static void principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
static void clear_principal_key_cache(Oid databaseId); static void clear_principal_key_cache(Oid databaseId);
static inline dshash_table *get_principal_key_Hash(void); static inline dshash_table *get_principal_key_Hash(void);
static TDEPrincipalKey *get_principal_key_from_keyring(Oid dbOid, Oid spcOid); static TDEPrincipalKey *get_principal_key_from_keyring(Oid dbOid);
static TDEPrincipalKey *get_principal_key_from_cache(Oid dbOid); static TDEPrincipalKey *get_principal_key_from_cache(Oid dbOid);
static void push_principal_key_to_cache(TDEPrincipalKey *principalKey); static void push_principal_key_to_cache(TDEPrincipalKey *principalKey);
static Datum pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid); static Datum pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid);
static keyInfo *load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info, static keyInfo *load_latest_versioned_key_name(TDEPrincipalKeyInfo *principal_key_info,
GenericKeyring *keyring, GenericKeyring *keyring,
bool ensure_new_key); bool ensure_new_key);
static TDEPrincipalKey *set_principal_key_with_keyring(const char *key_name, static TDEPrincipalKey *set_principal_key_with_keyring(const char *key_name,
GenericKeyring *keyring, GenericKeyring *keyring,
Oid dbOid, Oid spcOid, Oid dbOid,
bool ensure_new_key); bool ensure_new_key);
static const TDEShmemSetupRoutine principal_key_info_shmem_routine = { static const TDEShmemSetupRoutine principal_key_info_shmem_routine = {
@ -222,7 +222,7 @@ save_principal_key_info(TDEPrincipalKeyInfo *principal_key_info)
*/ */
TDEPrincipalKey * TDEPrincipalKey *
set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring, set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
Oid dbOid, Oid spcOid, bool ensure_new_key) Oid dbOid, bool ensure_new_key)
{ {
TDEPrincipalKey *principalKey = NULL; TDEPrincipalKey *principalKey = NULL;
LWLock *lock_files = tde_lwlock_enc_keys(); LWLock *lock_files = tde_lwlock_enc_keys();
@ -238,7 +238,7 @@ set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
/* TODO: Add the key in the cache? */ /* TODO: Add the key in the cache? */
if (!is_dup_key) if (!is_dup_key)
is_dup_key = (pg_tde_get_principal_key_info(dbOid, spcOid) != NULL); is_dup_key = (pg_tde_get_principal_key_info(dbOid) != NULL);
if (!is_dup_key) if (!is_dup_key)
{ {
@ -246,7 +246,6 @@ set_principal_key_with_keyring(const char *key_name, GenericKeyring *keyring,
principalKey = palloc(sizeof(TDEPrincipalKey)); principalKey = palloc(sizeof(TDEPrincipalKey));
principalKey->keyInfo.databaseId = dbOid; principalKey->keyInfo.databaseId = dbOid;
principalKey->keyInfo.tablespaceId = spcOid;
principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION; principalKey->keyInfo.keyId.version = DEFAULT_PRINCIPAL_KEY_VERSION;
principalKey->keyInfo.keyringId = keyring->key_id; principalKey->keyInfo.keyringId = keyring->key_id;
strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN);
@ -301,8 +300,8 @@ bool
SetPrincipalKey(const char *key_name, const char *provider_name, bool ensure_new_key) SetPrincipalKey(const char *key_name, const char *provider_name, bool ensure_new_key)
{ {
TDEPrincipalKey *principal_key = set_principal_key_with_keyring(key_name, TDEPrincipalKey *principal_key = set_principal_key_with_keyring(key_name,
GetKeyProviderByName(provider_name, MyDatabaseId, MyDatabaseTableSpace), GetKeyProviderByName(provider_name, MyDatabaseId),
MyDatabaseId, MyDatabaseTableSpace, MyDatabaseId,
ensure_new_key); ensure_new_key);
return (principal_key != NULL); return (principal_key != NULL);
@ -343,15 +342,13 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const
if (new_provider_name != NULL) if (new_provider_name != NULL)
{ {
new_principal_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name, new_principal_key.keyInfo.keyringId = GetKeyProviderByName(new_provider_name,
new_principal_key.keyInfo.databaseId, new_principal_key.keyInfo.databaseId)->key_id;
new_principal_key.keyInfo.tablespaceId)->key_id;
} }
} }
/* We need a valid keyring structure */ /* We need a valid keyring structure */
keyring = GetKeyProviderByID(new_principal_key.keyInfo.keyringId, keyring = GetKeyProviderByID(new_principal_key.keyInfo.keyringId,
new_principal_key.keyInfo.databaseId, new_principal_key.keyInfo.databaseId);
new_principal_key.keyInfo.tablespaceId);
keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key); keyInfo = load_latest_versioned_key_name(&new_principal_key.keyInfo, keyring, ensure_new_key);
@ -368,7 +365,7 @@ RotatePrincipalKey(TDEPrincipalKey *current_key, const char *new_key_name, const
memcpy(new_principal_key.keyData, keyInfo->data.data, keyInfo->data.len); memcpy(new_principal_key.keyData, keyInfo->data.data, keyInfo->data.len);
is_rotated = pg_tde_perform_rotate_key(current_key, &new_principal_key); is_rotated = pg_tde_perform_rotate_key(current_key, &new_principal_key);
if (is_rotated && current_key->keyInfo.tablespaceId != GLOBALTABLESPACE_OID) if (is_rotated && !TDEisInGlobalSpace(current_key->keyInfo.databaseId))
{ {
clear_principal_key_cache(current_key->keyInfo.databaseId); clear_principal_key_cache(current_key->keyInfo.databaseId);
push_principal_key_to_cache(&new_principal_key); push_principal_key_to_cache(&new_principal_key);
@ -493,7 +490,7 @@ GetPrincipalKeyProviderId(void)
* Principal key not present in cache. Try Loading it from the info * Principal key not present in cache. Try Loading it from the info
* file * file
*/ */
principalKeyInfo = pg_tde_get_principal_key_info(dbOid, MyDatabaseTableSpace); principalKeyInfo = pg_tde_get_principal_key_info(dbOid);
if (principalKeyInfo) if (principalKeyInfo)
{ {
keyringId = principalKeyInfo->keyringId; keyringId = principalKeyInfo->keyringId;
@ -582,11 +579,11 @@ principal_key_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info,
return; return;
} }
cleanup_principal_key_info(ext_info->database_id, ext_info->tablespace_id); cleanup_principal_key_info(ext_info->database_id);
} }
void void
cleanup_principal_key_info(Oid databaseId, Oid tablespaceId) cleanup_principal_key_info(Oid databaseId)
{ {
clear_principal_key_cache(databaseId); clear_principal_key_cache(databaseId);
@ -596,7 +593,7 @@ cleanup_principal_key_info(Oid databaseId, Oid tablespaceId)
*/ */
/* Remove the tde files */ /* Remove the tde files */
pg_tde_delete_tde_files(databaseId, tablespaceId); pg_tde_delete_tde_files(databaseId);
} }
static void static void
@ -646,7 +643,6 @@ pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS)
bool ret; bool ret;
TDEPrincipalKey *current_key; TDEPrincipalKey *current_key;
Oid dbOid = MyDatabaseId; Oid dbOid = MyDatabaseId;
Oid spcOid = MyDatabaseTableSpace;
if (!PG_ARGISNULL(0)) if (!PG_ARGISNULL(0))
new_principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0)); new_principal_key_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
@ -659,7 +655,6 @@ pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS)
if (is_global) if (is_global)
{ {
dbOid = GLOBAL_DATA_TDE_OID; dbOid = GLOBAL_DATA_TDE_OID;
spcOid = GLOBALTABLESPACE_OID;
} }
#endif #endif
@ -669,7 +664,7 @@ pg_tde_rotate_principal_key_internal(PG_FUNCTION_ARGS)
is_global ? "cluster" : "database"))); is_global ? "cluster" : "database")));
LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE); LWLockAcquire(tde_lwlock_enc_keys(), LW_EXCLUSIVE);
current_key = GetPrincipalKey(dbOid, spcOid, LW_EXCLUSIVE); current_key = GetPrincipalKey(dbOid, LW_EXCLUSIVE);
ret = RotatePrincipalKey(current_key, new_principal_key_name, new_provider_name, ensure_new_key); ret = RotatePrincipalKey(current_key, new_principal_key_name, new_provider_name, ensure_new_key);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
@ -681,20 +676,18 @@ Datum
pg_tde_principal_key_info_internal(PG_FUNCTION_ARGS) pg_tde_principal_key_info_internal(PG_FUNCTION_ARGS)
{ {
Oid dbOid = MyDatabaseId; Oid dbOid = MyDatabaseId;
Oid spcOid = MyDatabaseTableSpace;
bool is_global = PG_GETARG_BOOL(0); bool is_global = PG_GETARG_BOOL(0);
if (is_global) if (is_global)
{ {
dbOid = GLOBAL_DATA_TDE_OID; dbOid = GLOBAL_DATA_TDE_OID;
spcOid = GLOBALTABLESPACE_OID;
} }
return pg_tde_get_key_info(fcinfo, dbOid, spcOid); return pg_tde_get_key_info(fcinfo, dbOid);
} }
static Datum static Datum
pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid) pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid)
{ {
TupleDesc tupdesc; TupleDesc tupdesc;
Datum values[6]; Datum values[6];
@ -712,7 +705,7 @@ pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid)
errmsg("function returning record called in context that cannot accept type record"))); errmsg("function returning record called in context that cannot accept type record")));
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
principal_key = GetPrincipalKey(dbOid, spcOid, LW_SHARED); principal_key = GetPrincipalKey(dbOid, LW_SHARED);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
if (principal_key == NULL) if (principal_key == NULL)
{ {
@ -722,7 +715,7 @@ pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid)
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId, dbOid, spcOid); keyring = GetKeyProviderByID(principal_key->keyInfo.keyringId, dbOid);
/* Initialize the values and null flags */ /* Initialize the values and null flags */
@ -769,7 +762,7 @@ pg_tde_get_key_info(PG_FUNCTION_ARGS, Oid dbOid, Oid spcOid)
* Caller should hold an exclusive tde_lwlock_enc_keys lock * Caller should hold an exclusive tde_lwlock_enc_keys lock
*/ */
TDEPrincipalKey * TDEPrincipalKey *
get_principal_key_from_keyring(Oid dbOid, Oid spcOid) get_principal_key_from_keyring(Oid dbOid)
{ {
GenericKeyring *keyring; GenericKeyring *keyring;
TDEPrincipalKey *principalKey = NULL; TDEPrincipalKey *principalKey = NULL;
@ -779,13 +772,13 @@ get_principal_key_from_keyring(Oid dbOid, Oid spcOid)
Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), LW_EXCLUSIVE)); Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), LW_EXCLUSIVE));
principalKeyInfo = pg_tde_get_principal_key_info(dbOid, spcOid); principalKeyInfo = pg_tde_get_principal_key_info(dbOid);
if (principalKeyInfo == NULL) if (principalKeyInfo == NULL)
{ {
return NULL; return NULL;
} }
keyring = GetKeyProviderByID(principalKeyInfo->keyringId, dbOid, spcOid); keyring = GetKeyProviderByID(principalKeyInfo->keyringId, dbOid);
if (keyring == NULL) if (keyring == NULL)
{ {
return NULL; return NULL;
@ -808,7 +801,7 @@ get_principal_key_from_keyring(Oid dbOid, Oid spcOid)
#ifndef FRONTEND #ifndef FRONTEND
/* We don't store global space key in cache */ /* We don't store global space key in cache */
if (spcOid != GLOBALTABLESPACE_OID) if (!TDEisInGlobalSpace(dbOid))
{ {
push_principal_key_to_cache(principalKey); push_principal_key_to_cache(principalKey);
@ -842,14 +835,14 @@ get_principal_key_from_keyring(Oid dbOid, Oid spcOid)
* cache. * cache.
*/ */
TDEPrincipalKey * TDEPrincipalKey *
GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode) GetPrincipalKey(Oid dbOid, LWLockMode lockMode)
{ {
#ifndef FRONTEND #ifndef FRONTEND
TDEPrincipalKey *principalKey = NULL; TDEPrincipalKey *principalKey = NULL;
Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), lockMode)); Assert(LWLockHeldByMeInMode(tde_lwlock_enc_keys(), lockMode));
/* We don't store global space key in cache */ /* We don't store global space key in cache */
if (spcOid != GLOBALTABLESPACE_OID) if (!TDEisInGlobalSpace(dbOid))
{ {
principalKey = get_principal_key_from_cache(dbOid); principalKey = get_principal_key_from_cache(dbOid);
} }
@ -866,5 +859,5 @@ GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode)
} }
#endif #endif
return get_principal_key_from_keyring(dbOid, spcOid); return get_principal_key_from_keyring(dbOid);
} }

@ -11,7 +11,6 @@
#include "postgres.h" #include "postgres.h"
#include "catalog/pg_tablespace_d.h"
#include "utils/snapmgr.h" #include "utils/snapmgr.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "common/pg_tde_utils.h" #include "common/pg_tde_utils.h"
@ -93,22 +92,3 @@ pg_tde_set_globalspace_dir(const char *dir)
Assert(dir != NULL); Assert(dir != NULL);
strncpy(globalspace_dir, dir, sizeof(globalspace_dir)); strncpy(globalspace_dir, dir, sizeof(globalspace_dir));
} }
/* returns the palloc'd string */
char *
pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid)
{
/*
* `dbOid` is set to a value for the XLog keys caching but
* GetDatabasePath() expects it (`dbOid`) to be `0` if this is a global
* space.
*/
if (spcOid == GLOBALTABLESPACE_OID)
{
if (strlen(globalspace_dir) > 0)
return pstrdup(globalspace_dir);
return pstrdup("global");
}
return GetDatabasePath(dbOid, spcOid);
}

@ -205,7 +205,6 @@ pg_tde_crypt_tuple(HeapTuple tuple, HeapTuple out_tuple, RelKeyData *key, const
OffsetNumber OffsetNumber
PGTdePageAddItemExtended(RelFileLocator rel, PGTdePageAddItemExtended(RelFileLocator rel,
Oid oid,
BlockNumber bn, BlockNumber bn,
Page page, Page page,
Item item, Item item,
@ -241,15 +240,14 @@ PGTdePageAddItemExtended(RelFileLocator rel,
* short lifespan until it is written to disk. * short lifespan until it is written to disk.
*/ */
void void
AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData *rel_key_data, RelKeyData **p_enc_rel_key_data, size_t *enc_key_bytes) AesEncryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, 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}; 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 */ /* Ensure we are getting a valid pointer here */
Assert(principal_key); Assert(principal_key);
memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv, &dbOid, sizeof(Oid));
memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid));
*p_enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData)); *p_enc_rel_key_data = (RelKeyData *) palloc(sizeof(RelKeyData));
memcpy(*p_enc_rel_key_data, rel_key_data, sizeof(RelKeyData)); memcpy(*p_enc_rel_key_data, rel_key_data, sizeof(RelKeyData));
@ -267,15 +265,14 @@ AesEncryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocat
* to our key cache. * to our key cache.
*/ */
void void
AesDecryptKey(const TDEPrincipalKey *principal_key, const RelFileLocator *rlocator, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes) AesDecryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, 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}; 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 */ /* Ensure we are getting a valid pointer here */
Assert(principal_key); Assert(principal_key);
memcpy(iv, &rlocator->spcOid, sizeof(Oid)); memcpy(iv, &dbOid, sizeof(Oid));
memcpy(iv + sizeof(Oid), &rlocator->dbOid, sizeof(Oid));
#ifndef FRONTEND #ifndef FRONTEND
MemoryContext oldcontext; MemoryContext oldcontext;

@ -8,9 +8,9 @@
#ifndef PG_TDE_MAP_H #ifndef PG_TDE_MAP_H
#define PG_TDE_MAP_H #define PG_TDE_MAP_H
#include "pg_tde.h"
#include "utils/rel.h" #include "utils/rel.h"
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "catalog/pg_tablespace_d.h"
#include "catalog/tde_principal_key.h" #include "catalog/tde_principal_key.h"
#include "storage/relfilelocator.h" #include "storage/relfilelocator.h"
@ -62,19 +62,29 @@ extern RelKeyData *GetSMGRRelationKey(RelFileLocator rel);
extern RelKeyData *GetHeapBaiscRelationKey(RelFileLocator rel); extern RelKeyData *GetHeapBaiscRelationKey(RelFileLocator rel);
extern RelKeyData *GetTdeGlobaleRelationKey(RelFileLocator rel); extern RelKeyData *GetTdeGlobaleRelationKey(RelFileLocator rel);
extern void pg_tde_delete_tde_files(Oid dbOid, Oid spcOid); extern void pg_tde_delete_tde_files(Oid dbOid);
extern TDEPrincipalKeyInfo *pg_tde_get_principal_key_info(Oid dbOid, Oid spcOid); extern TDEPrincipalKeyInfo *pg_tde_get_principal_key_info(Oid dbOid);
extern bool pg_tde_save_principal_key(TDEPrincipalKeyInfo *principal_key_info); 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_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 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(RelFileNumber rel_num, InternalKey *key, TDEPrincipalKeyInfo *principal_key_info); extern RelKeyData *tde_create_rel_key(RelFileNumber rel_num, 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_encrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *rel_key_data, Oid dbOid);
extern RelKeyData *tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, const RelFileLocator *rlocator); extern RelKeyData *tde_decrypt_rel_key(TDEPrincipalKey *principal_key, RelKeyData *enc_rel_key_data, Oid dbOid);
extern RelKeyData *pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool no_map_ok); extern RelKeyData *pg_tde_get_key_from_file(const RelFileLocator *rlocator, uint32 key_type, bool no_map_ok);
extern bool pg_tde_move_rel_key(const RelFileLocator *newrlocator, const RelFileLocator *oldrlocator); extern bool pg_tde_move_rel_key(const RelFileLocator *newrlocator, const RelFileLocator *oldrlocator);
extern void pg_tde_set_db_file_paths(Oid dbOid, Oid spcOid, char *map_path, char *keydata_path); #define PG_TDE_MAP_FILENAME "pg_tde_%d_map"
#define PG_TDE_KEYDATA_FILENAME "pg_tde_%d_dat"
static inline void
pg_tde_set_db_file_paths(Oid dbOid, char *map_path, char *keydata_path)
{
if (map_path)
join_path_components(map_path, PG_TDE_DATA_DIR, psprintf(PG_TDE_MAP_FILENAME, dbOid));
if (keydata_path)
join_path_components(keydata_path, PG_TDE_DATA_DIR, psprintf(PG_TDE_KEYDATA_FILENAME, dbOid));
}
const char *tde_sprint_key(InternalKey *k); const char *tde_sprint_key(InternalKey *k);

@ -12,6 +12,7 @@
#define TDE_GLOBAL_CATALOG_H #define TDE_GLOBAL_CATALOG_H
#include "postgres.h" #include "postgres.h"
#include "catalog/pg_tablespace_d.h"
#include "access/pg_tde_tdemap.h" #include "access/pg_tde_tdemap.h"
#include "catalog/tde_principal_key.h" #include "catalog/tde_principal_key.h"
@ -21,17 +22,17 @@
* We take Oids of the sql operators, so there is no overlap with the "real" * We take Oids of the sql operators, so there is no overlap with the "real"
* catalog objects possible. * catalog objects possible.
*/ */
#define GLOBAL_DATA_TDE_OID InvalidOid #define GLOBAL_DATA_TDE_OID 607
#define XLOG_TDE_OID 608 #define XLOG_TDE_OID 608
#define GLOBAL_DATA_TDE_OID InvalidOid
#define GLOBAL_SPACE_RLOCATOR(_obj_oid) (RelFileLocator) { \ #define GLOBAL_SPACE_RLOCATOR(_obj_oid) (RelFileLocator) { \
GLOBALTABLESPACE_OID, \ GLOBALTABLESPACE_OID, \
GLOBAL_DATA_TDE_OID, \ GLOBAL_DATA_TDE_OID, \
_obj_oid \ _obj_oid \
} }
#define TDEisInGlobalSpace(dbOid) (dbOid == GLOBAL_DATA_TDE_OID)
extern void TDEInitGlobalKeys(const char *dir); extern void TDEInitGlobalKeys(const char *dir);
#endif /* TDE_GLOBAL_CATALOG_H */ #endif /* TDE_GLOBAL_CATALOG_H */

@ -68,23 +68,18 @@ typedef struct KeyringProvideRecord
typedef struct KeyringProviderXLRecord typedef struct KeyringProviderXLRecord
{ {
Oid database_id; Oid database_id;
Oid tablespace_id;
off_t offset_in_file; off_t offset_in_file;
KeyringProvideRecord provider; KeyringProvideRecord provider;
} KeyringProviderXLRecord; } KeyringProviderXLRecord;
extern List *GetAllKeyringProviders(Oid dbOid, Oid spcOid); extern List *GetAllKeyringProviders(Oid dbOid);
extern GenericKeyring *GetKeyProviderByName(const char *provider_name, Oid dbOid, Oid spcOid); extern GenericKeyring *GetKeyProviderByName(const char *provider_name, Oid dbOid);
extern GenericKeyring *GetKeyProviderByID(int provider_id, Oid dbOid, Oid spcOid); extern GenericKeyring *GetKeyProviderByID(int provider_id, Oid dbOid);
extern ProviderType get_keyring_provider_from_typename(char *provider_type); extern ProviderType get_keyring_provider_from_typename(char *provider_type);
extern void cleanup_key_provider_info(Oid databaseId, Oid tablespaceId); extern void cleanup_key_provider_info(Oid databaseId);
extern void InitializeKeyProviderInfo(void); extern void InitializeKeyProviderInfo(void);
extern uint32 save_new_key_provider_info(KeyringProvideRecord *provider, extern uint32 save_new_key_provider_info(KeyringProvideRecord *provider,
Oid databaseId, Oid tablespaceId, Oid databaseId, bool write_xlog);
bool write_xlog);
extern uint32 copy_key_provider_info(KeyringProvideRecord* provider,
Oid newdatabaseId, Oid newtablespaceId,
bool write_xlog);
extern uint32 redo_key_provider_info(KeyringProviderXLRecord *xlrec); extern uint32 redo_key_provider_info(KeyringProviderXLRecord *xlrec);
extern bool ParseKeyringJSONOptions(ProviderType provider_type, void *out_opts, extern bool ParseKeyringJSONOptions(ProviderType provider_type, void *out_opts,

@ -33,7 +33,6 @@ typedef struct TDEPrincipalKeyId
typedef struct TDEPrincipalKeyInfo typedef struct TDEPrincipalKeyInfo
{ {
Oid databaseId; Oid databaseId;
Oid tablespaceId;
Oid userId; Oid userId;
Oid keyringId; Oid keyringId;
struct timeval creationTime; struct timeval creationTime;
@ -58,13 +57,13 @@ typedef struct XLogPrincipalKeyRotate
#define SizeoOfXLogPrincipalKeyRotate offsetof(XLogPrincipalKeyRotate, buff) #define SizeoOfXLogPrincipalKeyRotate offsetof(XLogPrincipalKeyRotate, buff)
extern void InitializePrincipalKeyInfo(void); extern void InitializePrincipalKeyInfo(void);
extern void cleanup_principal_key_info(Oid databaseId, Oid tablespaceId); extern void cleanup_principal_key_info(Oid databaseId);
#ifndef FRONTEND #ifndef FRONTEND
extern LWLock *tde_lwlock_enc_keys(void); extern LWLock *tde_lwlock_enc_keys(void);
extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, Oid spcOid, LWLockMode lockMode); extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, LWLockMode lockMode);
#else #else
extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, Oid spcOid, void *lockMode); extern TDEPrincipalKey *GetPrincipalKey(Oid dbOid, void *lockMode);
#endif #endif
extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo); extern bool save_principal_key_info(TDEPrincipalKeyInfo *principalKeyInfo);

@ -19,6 +19,5 @@ extern List *get_all_tde_tables(void);
extern int get_tde_tables_count(void); extern int get_tde_tables_count(void);
#endif /* !FRONTEND */ #endif /* !FRONTEND */
extern char *pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid);
extern void pg_tde_set_globalspace_dir(const char *dir); extern void pg_tde_set_globalspace_dir(const char *dir);
#endif /* PG_TDE_UTILS_H */ #endif /* PG_TDE_UTILS_H */

@ -24,7 +24,7 @@ extern void
/* A wrapper to encrypt a tuple before adding it to the buffer */ /* A wrapper to encrypt a tuple before adding it to the buffer */
extern OffsetNumber extern OffsetNumber
PGTdePageAddItemExtended(RelFileLocator rel, Oid oid, BlockNumber bn, Page page, PGTdePageAddItemExtended(RelFileLocator rel, BlockNumber bn, Page page,
Item item, Item item,
Size size, Size size,
OffsetNumber offsetNumber, OffsetNumber offsetNumber,
@ -52,7 +52,7 @@ extern OffsetNumber
pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, "ENCRYPT-PAGE-ITEM"); \ pg_tde_crypt(_iv_prefix, _start_offset, _data, _data_len, _out, _key, "ENCRYPT-PAGE-ITEM"); \
} while(0) } while(0)
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 AesEncryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, 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); extern void AesDecryptKey(const TDEPrincipalKey *principal_key, Oid dbOid, RelKeyData **p_rel_key_data, RelKeyData *enc_rel_key_data, size_t *key_bytes);
#endif /* ENC_TDE_H */ #endif /* ENC_TDE_H */

@ -8,10 +8,11 @@
#ifndef PG_TDE_H #ifndef PG_TDE_H
#define PG_TDE_H #define PG_TDE_H
#define PG_TDE_DATA_DIR "pg_tde"
typedef struct XLogExtensionInstall typedef struct XLogExtensionInstall
{ {
Oid database_id; Oid database_id;
Oid tablespace_id;
} XLogExtensionInstall; } XLogExtensionInstall;
typedef void (*pg_tde_on_ext_install_callback) (int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg); typedef void (*pg_tde_on_ext_install_callback) (int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
@ -19,4 +20,6 @@ typedef void (*pg_tde_on_ext_install_callback) (int tde_tbl_count, XLogExtension
extern void on_ext_install(pg_tde_on_ext_install_callback function, void *arg); extern void on_ext_install(pg_tde_on_ext_install_callback function, void *arg);
extern void extension_install_redo(XLogExtensionInstall *xlrec); extern void extension_install_redo(XLogExtensionInstall *xlrec);
extern void pg_tde_init_data_dir(void);
#endif /* PG_TDE_H */ #endif /* PG_TDE_H */

@ -40,8 +40,8 @@
#define pgstat_count_tdeheap_delete pgstat_count_heap_delete #define pgstat_count_tdeheap_delete pgstat_count_heap_delete
#define pgstat_count_tdeheap_insert pgstat_count_heap_insert #define pgstat_count_tdeheap_insert pgstat_count_heap_insert
#define TDE_PageAddItem(rel, oid, blkno, page, item, size, offsetNumber, overwrite, is_heap) \ #define TDE_PageAddItem(rel, blkno, page, item, size, offsetNumber, overwrite, is_heap) \
PGTdePageAddItemExtended(rel, oid, blkno, page, item, size, offsetNumber, \ PGTdePageAddItemExtended(rel, blkno, page, item, size, offsetNumber, \
((overwrite) ? PAI_OVERWRITE : 0) | \ ((overwrite) ? PAI_OVERWRITE : 0) | \
((is_heap) ? PAI_IS_HEAP : 0)) ((is_heap) ? PAI_IS_HEAP : 0))

@ -39,6 +39,8 @@
#include "utils/percona.h" #include "utils/percona.h"
#endif #endif
#include <sys/stat.h>
#define MAX_ON_INSTALLS 5 #define MAX_ON_INSTALLS 5
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
@ -130,11 +132,12 @@ _PG_init(void)
Datum Datum
pg_tde_extension_initialize(PG_FUNCTION_ARGS) pg_tde_extension_initialize(PG_FUNCTION_ARGS)
{ {
pg_tde_init_data_dir();
/* Initialize the TDE map */ /* Initialize the TDE map */
XLogExtensionInstall xlrec; XLogExtensionInstall xlrec;
xlrec.database_id = MyDatabaseId; xlrec.database_id = MyDatabaseId;
xlrec.tablespace_id = MyDatabaseTableSpace;
run_extension_install_callbacks(&xlrec, false); run_extension_install_callbacks(&xlrec, false);
/* /*
@ -174,6 +177,22 @@ on_ext_install(pg_tde_on_ext_install_callback function, void *arg)
++on_ext_install_index; ++on_ext_install_index;
} }
/* Creates a tde directory for internal files if not exists */
void
pg_tde_init_data_dir(void)
{
struct stat st;
if (stat(PG_TDE_DATA_DIR, &st) < 0)
{
if (MakePGDirectory(PG_TDE_DATA_DIR) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create tde directory \"%s\": %m",
PG_TDE_DATA_DIR)));
}
}
/* ------------------ /* ------------------
* Run all of the on_ext_install routines and execute those one by one * Run all of the on_ext_install routines and execute those one by one
* ------------------ * ------------------

@ -21,7 +21,6 @@
#include "commands/event_trigger.h" #include "commands/event_trigger.h"
#include "common/pg_tde_utils.h" #include "common/pg_tde_utils.h"
#include "pg_tde_event_capture.h" #include "pg_tde_event_capture.h"
#include "commands/tablespace.h"
#include "catalog/tde_principal_key.h" #include "catalog/tde_principal_key.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "access/tableam.h" #include "access/tableam.h"
@ -102,7 +101,6 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
{ {
CreateStmt *stmt = (CreateStmt *) parsetree; CreateStmt *stmt = (CreateStmt *) parsetree;
TDEPrincipalKey *principal_key; TDEPrincipalKey *principal_key;
Oid tablespace_oid;
tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT; tdeCurrentCreateEvent.eventType = TDE_TABLE_CREATE_EVENT;
tdeCurrentCreateEvent.relation = stmt->relation; tdeCurrentCreateEvent.relation = stmt->relation;
@ -118,10 +116,8 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
if (tdeCurrentCreateEvent.encryptMode) if (tdeCurrentCreateEvent.encryptMode)
{ {
tablespace_oid = stmt->tablespacename != NULL ? get_tablespace_oid(stmt->tablespacename, false)
: MyDatabaseTableSpace;
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
principal_key = GetPrincipalKey(MyDatabaseId, tablespace_oid, LW_SHARED); principal_key = GetPrincipalKey(MyDatabaseId, LW_SHARED);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
if (principal_key == NULL) if (principal_key == NULL)
{ {
@ -152,21 +148,15 @@ pg_tde_ddl_command_start_capture(PG_FUNCTION_ARGS)
} }
} }
/*
* TODO: also check for tablespace change, if current or new AM is
* tde_heap!
*/
if (tdeCurrentCreateEvent.encryptMode) if (tdeCurrentCreateEvent.encryptMode)
{ {
TDEPrincipalKey * principal_key; TDEPrincipalKey * principal_key;
Oid relationId = RangeVarGetRelid(stmt->relation, NoLock, true); Oid relationId = RangeVarGetRelid(stmt->relation, NoLock, true);
Relation rel = table_open(relationId, lockmode); Relation rel = table_open(relationId, lockmode);
Oid tablespace_oid = rel->rd_locator.spcOid;
table_close(rel, lockmode); table_close(rel, lockmode);
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
principal_key = GetPrincipalKey(MyDatabaseId, tablespace_oid, LW_SHARED); principal_key = GetPrincipalKey(MyDatabaseId, LW_SHARED);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
if (principal_key == NULL) if (principal_key == NULL)
{ {

@ -51,7 +51,7 @@ tde_smgr_get_key(SMgrRelation reln, RelFileLocator* old_locator, bool can_create
} }
LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED); LWLockAcquire(tde_lwlock_enc_keys(), LW_SHARED);
pk = GetPrincipalKey(reln->smgr_rlocator.locator.dbOid, reln->smgr_rlocator.locator.spcOid, LW_SHARED); pk = GetPrincipalKey(reln->smgr_rlocator.locator.dbOid, LW_SHARED);
LWLockRelease(tde_lwlock_enc_keys()); LWLockRelease(tde_lwlock_enc_keys());
if (pk == NULL) if (pk == NULL)
{ {

@ -65,7 +65,7 @@ tdeheap_RelationPutHeapTuple(Relation relation,
pageHeader = BufferGetPage(buffer); pageHeader = BufferGetPage(buffer);
if (encrypt) if (encrypt)
offnum = TDE_PageAddItem(relation->rd_locator, tuple->t_tableOid, BufferGetBlockNumber(buffer), pageHeader, (Item) tuple->t_data, offnum = TDE_PageAddItem(relation->rd_locator, BufferGetBlockNumber(buffer), pageHeader, (Item) tuple->t_data,
tuple->t_len, InvalidOffsetNumber, false, true); tuple->t_len, InvalidOffsetNumber, false, true);
else else
offnum = PageAddItem(pageHeader, (Item) tuple->t_data, offnum = PageAddItem(pageHeader, (Item) tuple->t_data,

@ -711,7 +711,7 @@ raw_tdeheap_insert(RewriteState state, HeapTuple tup)
} }
/* And now we can insert the tuple into the page */ /* And now we can insert the tuple into the page */
newoff = TDE_PageAddItem(state->rs_new_rel->rd_locator, heaptup->t_tableOid, state->rs_blockno, page, (Item) heaptup->t_data, heaptup->t_len, newoff = TDE_PageAddItem(state->rs_new_rel->rd_locator, state->rs_blockno, page, (Item) heaptup->t_data, heaptup->t_len,
InvalidOffsetNumber, false, true); InvalidOffsetNumber, false, true);
if (newoff == InvalidOffsetNumber) if (newoff == InvalidOffsetNumber)
elog(ERROR, "failed to add tuple"); elog(ERROR, "failed to add tuple");

@ -9382,7 +9382,7 @@ tdeheap_xlog_insert(XLogReaderState *record)
HeapTupleHeaderSetCmin(htup, FirstCommandId); HeapTupleHeaderSetCmin(htup, FirstCommandId);
htup->t_ctid = target_tid; htup->t_ctid = target_tid;
if (TDE_PageAddItem(target_locator, target_locator.spcOid, blkno, page, (Item) htup, newlen, xlrec->offnum, if (TDE_PageAddItem(target_locator, blkno, page, (Item) htup, newlen, xlrec->offnum,
true, true) == InvalidOffsetNumber) true, true) == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");
@ -9526,7 +9526,7 @@ tdeheap_xlog_multi_insert(XLogReaderState *record)
ItemPointerSetBlockNumber(&htup->t_ctid, blkno); ItemPointerSetBlockNumber(&htup->t_ctid, blkno);
ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); ItemPointerSetOffsetNumber(&htup->t_ctid, offnum);
offnum = TDE_PageAddItem(rlocator, rlocator.spcOid, blkno, page, (Item) htup, newlen, offnum, true, true); offnum = TDE_PageAddItem(rlocator, blkno, page, (Item) htup, newlen, offnum, true, true);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");
} }
@ -9800,7 +9800,7 @@ tdeheap_xlog_update(XLogReaderState *record, bool hot_update)
/* Make sure there is no forward chain link in t_ctid */ /* Make sure there is no forward chain link in t_ctid */
htup->t_ctid = newtid; htup->t_ctid = newtid;
offnum = TDE_PageAddItem(rlocator, rlocator.spcOid, newblk, page, (Item) htup, newlen, offnum, true, true); offnum = TDE_PageAddItem(rlocator, newblk, page, (Item) htup, newlen, offnum, true, true);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");

@ -64,7 +64,7 @@ tdeheap_RelationPutHeapTuple(Relation relation,
pageHeader = BufferGetPage(buffer); pageHeader = BufferGetPage(buffer);
if (encrypt) if (encrypt)
offnum = TDE_PageAddItem(relation->rd_locator, tuple->t_tableOid, BufferGetBlockNumber(buffer), pageHeader, (Item) tuple->t_data, offnum = TDE_PageAddItem(relation->rd_locator, BufferGetBlockNumber(buffer), pageHeader, (Item) tuple->t_data,
tuple->t_len, InvalidOffsetNumber, false, true); tuple->t_len, InvalidOffsetNumber, false, true);
else else
offnum = PageAddItem(pageHeader, (Item) tuple->t_data, offnum = PageAddItem(pageHeader, (Item) tuple->t_data,

@ -677,7 +677,7 @@ raw_tdeheap_insert(RewriteState state, HeapTuple tup)
} }
/* And now we can insert the tuple into the page */ /* And now we can insert the tuple into the page */
newoff = TDE_PageAddItem(state->rs_new_rel->rd_locator, heaptup->t_tableOid, state->rs_blockno, page, (Item) heaptup->t_data, heaptup->t_len, newoff = TDE_PageAddItem(state->rs_new_rel->rd_locator, state->rs_blockno, page, (Item) heaptup->t_data, heaptup->t_len,
InvalidOffsetNumber, false, true); InvalidOffsetNumber, false, true);
if (newoff == InvalidOffsetNumber) if (newoff == InvalidOffsetNumber)
elog(ERROR, "failed to add tuple"); elog(ERROR, "failed to add tuple");

@ -9282,7 +9282,7 @@ tdeheap_xlog_insert(XLogReaderState *record)
HeapTupleHeaderSetCmin(htup, FirstCommandId); HeapTupleHeaderSetCmin(htup, FirstCommandId);
htup->t_ctid = target_tid; htup->t_ctid = target_tid;
if (TDE_PageAddItem(target_locator, target_locator.spcOid, blkno, page, (Item) htup, newlen, xlrec->offnum, if (TDE_PageAddItem(target_locator, blkno, page, (Item) htup, newlen, xlrec->offnum,
true, true) == InvalidOffsetNumber) true, true) == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");
@ -9426,7 +9426,7 @@ tdeheap_xlog_multi_insert(XLogReaderState *record)
ItemPointerSetBlockNumber(&htup->t_ctid, blkno); ItemPointerSetBlockNumber(&htup->t_ctid, blkno);
ItemPointerSetOffsetNumber(&htup->t_ctid, offnum); ItemPointerSetOffsetNumber(&htup->t_ctid, offnum);
offnum = TDE_PageAddItem(rlocator, rlocator.spcOid, blkno, page, (Item) htup, newlen, offnum, true, true); offnum = TDE_PageAddItem(rlocator, blkno, page, (Item) htup, newlen, offnum, true, true);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");
} }
@ -9700,7 +9700,7 @@ tdeheap_xlog_update(XLogReaderState *record, bool hot_update)
/* Make sure there is no forward chain link in t_ctid */ /* Make sure there is no forward chain link in t_ctid */
htup->t_ctid = newtid; htup->t_ctid = newtid;
offnum = TDE_PageAddItem(rlocator, rlocator.spcOid, newblk, page, (Item) htup, newlen, offnum, true, true); offnum = TDE_PageAddItem(rlocator, newblk, page, (Item) htup, newlen, offnum, true, true);
if (offnum == InvalidOffsetNumber) if (offnum == InvalidOffsetNumber)
elog(PANIC, "failed to add tuple"); elog(PANIC, "failed to add tuple");

Loading…
Cancel
Save