From d333448f2e5da98dfcaf9d87c095fa4353252bb9 Mon Sep 17 00:00:00 2001 From: Andrew Pogrebnoy Date: Wed, 28 Aug 2024 20:05:33 +0300 Subject: [PATCH] Add an option to set global kring dir ... and all the things work with pg_waldump --- src/access/pg_tde_xlog_encrypt.c | 4 ++ src/catalog/tde_global_space.c | 56 ++++++++++++++++---------- src/catalog/tde_keyring.c | 2 + src/common/pg_tde_utils.c | 14 +++++++ src/include/catalog/tde_global_space.h | 2 +- src/include/common/pg_tde_utils.h | 1 + src/include/pg_tde_fe.h | 14 +++++-- src/keyring/keyring_api.c | 6 +-- src/pg_tde.c | 2 +- 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/access/pg_tde_xlog_encrypt.c b/src/access/pg_tde_xlog_encrypt.c index 9016698e..dd5772ef 100644 --- a/src/access/pg_tde_xlog_encrypt.c +++ b/src/access/pg_tde_xlog_encrypt.c @@ -28,6 +28,10 @@ #include "catalog/tde_global_space.h" #include "encryption/enc_tde.h" +#ifdef FRONTEND +#include "pg_tde_fe.h" +#endif + static XLogPageHeaderData DecryptCurrentPageHrd; static void SetXLogPageIVPrefix(TimeLineID tli, XLogRecPtr lsn, char* iv_prefix); diff --git a/src/catalog/tde_global_space.c b/src/catalog/tde_global_space.c index 34ca4a05..6aebd3a3 100644 --- a/src/catalog/tde_global_space.c +++ b/src/catalog/tde_global_space.c @@ -32,6 +32,7 @@ #define PRINCIPAL_KEY_DEFAULT_NAME "tde-global-catalog-key" #define KEYRING_DEFAULT_NAME "default_global_tablespace_keyring" +#define KEYRING_DEFAULT_FILE_NAME "pg_tde_default_keyring_CHANGE_AND_REMOVE_IT" #define DefaultKeyProvider GetKeyProviderByName(KEYRING_DEFAULT_NAME, \ GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID) @@ -42,11 +43,11 @@ static void init_default_keyring(void); static TDEPrincipalKey * create_principal_key(const char *key_name, GenericKeyring * keyring, Oid dbOid, Oid spcOid); -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ void -TDEInitGlobalKeys() +TDEInitGlobalKeys(const char *dir) { #ifndef FRONTEND char db_map_path[MAXPGPATH] = {0}; @@ -59,20 +60,23 @@ TDEInitGlobalKeys() init_keys(); } else -#endif /* !FRONTEND */ +#endif /* !FRONTEND */ { RelKeyData *ikey; - + + if (dir != NULL) + pg_tde_set_globalspace_dir(dir); ikey = pg_tde_get_key_from_file(&GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID)); /* - * Internal Key should be in the TopMemmoryContext because of SSL contexts. This - * context is being initialized by OpenSSL with the pointer to the encryption - * context which is valid only for the current backend. So new backends have to - * inherit a cached key with NULL SSL connext and any changes to it have to remain - * local ot the backend. - * (see https://github.com/Percona-Lab/pg_tde/pull/214#discussion_r1648998317) - */ + * Internal Key should be in the TopMemmoryContext because of SSL + * contexts. This context is being initialized by OpenSSL with the + * pointer to the encryption context which is valid only for the + * current backend. So new backends have to inherit a cached key with + * NULL SSL connext and any changes to it have to remain local ot the + * backend. (see + * https://github.com/Percona-Lab/pg_tde/pull/214#discussion_r1648998317) + */ pg_tde_put_key_into_map(XLOG_TDE_OID, ikey); } } @@ -84,18 +88,26 @@ init_default_keyring(void) { if (GetAllKeyringProviders(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID) == NIL) { + char path[MAXPGPATH] = {0}; static KeyringProvideRecord provider = { .provider_name = KEYRING_DEFAULT_NAME, .provider_type = FILE_KEY_PROVIDER, - .options = - "{" - "\"type\": \"file\"," - " \"path\": \"pg_tde_default_keyring_CHANGE_AND_REMOVE_IT\"" /* TODO: not sure about - * the location */ - "}" }; + if (getcwd(path, sizeof(path)) == NULL) + elog(WARNING, "unable to get current working dir"); + + /* TODO: not sure about the location. Currently it's in $PGDATA */ + join_path_components(path, path, KEYRING_DEFAULT_FILE_NAME); + + snprintf(provider.options, MAX_KEYRING_OPTION_LEN, + "{" + "\"type\": \"file\"," + "\"path\": \"%s\"" + "}", path + ); + /* * TODO: should we remove it automaticaly on * pg_tde_rotate_principal_key() ? @@ -111,11 +123,11 @@ init_default_keyring(void) /* * Create and store global space keys (principal and internal) and cache the * internal key. - * - * Since we always keep an Internal key in the memory for the global tablespace + * + * Since we always keep an Internal key in the memory for the global tablespace * and read it from disk once, only during the server start, we need no cache for * the principal key. - * + * * This function has to be run during the cluster start only, so no locks needed. */ static void @@ -173,7 +185,7 @@ create_principal_key(const char *key_name, GenericKeyring * keyring, principalKey->keyInfo.keyringId = keyring->key_id; strncpy(principalKey->keyInfo.keyId.name, key_name, TDE_KEY_NAME_LEN); snprintf(principalKey->keyInfo.keyId.versioned_name, TDE_KEY_NAME_LEN, - "%s_%d", principalKey->keyInfo.keyId.name, principalKey->keyInfo.keyId.version); + "%s_%d", principalKey->keyInfo.keyId.name, principalKey->keyInfo.keyId.version); gettimeofday(&principalKey->keyInfo.creationTime, NULL); keyInfo = KeyringGenerateNewKeyAndStore(keyring, principalKey->keyInfo.keyId.versioned_name, INTERNAL_KEY_LEN, false); @@ -189,6 +201,6 @@ create_principal_key(const char *key_name, GenericKeyring * keyring, return principalKey; } -#endif /* FRONTEND */ +#endif /* FRONTEND */ #endif /* PERCONA_FORK */ diff --git a/src/catalog/tde_keyring.c b/src/catalog/tde_keyring.c index 01d3254a..f1a47d59 100644 --- a/src/catalog/tde_keyring.c +++ b/src/catalog/tde_keyring.c @@ -506,6 +506,8 @@ scan_key_provider_file(ProviderScanType scanType, void *scanKey, Oid dbOid, Oid #ifndef FRONTEND providers_list = lappend(providers_list, keyring); #else + if (providers_list == NULL) + providers_list = palloc(sizeof(providers_list)); simple_ptr_list_append(providers_list, keyring); #endif } diff --git a/src/common/pg_tde_utils.c b/src/common/pg_tde_utils.c index c1f190c4..c7768ff8 100644 --- a/src/common/pg_tde_utils.c +++ b/src/common/pg_tde_utils.c @@ -84,6 +84,15 @@ get_tde_tables_count(void) #endif /* !FRONTEND */ +static char globalspace_dir[MAXPGPATH] = {0}; + +void +pg_tde_set_globalspace_dir(const char *dir) +{ + Assert(dir != NULL); + strncpy(globalspace_dir, dir, sizeof(globalspace_dir)); +} + /* returns the palloc'd string */ char * pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid) @@ -92,6 +101,11 @@ pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid) * 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); } diff --git a/src/include/catalog/tde_global_space.h b/src/include/catalog/tde_global_space.h index 5f8548ba..959dde33 100644 --- a/src/include/catalog/tde_global_space.h +++ b/src/include/catalog/tde_global_space.h @@ -30,6 +30,6 @@ _obj_oid \ } -extern void TDEInitGlobalKeys(void); +extern void TDEInitGlobalKeys(const char *dir); #endif /* TDE_GLOBAL_CATALOG_H */ diff --git a/src/include/common/pg_tde_utils.h b/src/include/common/pg_tde_utils.h index 26edf8f9..bb0b3841 100644 --- a/src/include/common/pg_tde_utils.h +++ b/src/include/common/pg_tde_utils.h @@ -20,4 +20,5 @@ extern int get_tde_tables_count(void); #endif /* !FRONTEND */ extern char *pg_tde_get_tde_file_dir(Oid dbOid, Oid spcOid); +extern void pg_tde_set_globalspace_dir(const char *dir); #endif /*PG_TDE_UTILS_H*/ diff --git a/src/include/pg_tde_fe.h b/src/include/pg_tde_fe.h index 8862ef7d..029c434f 100644 --- a/src/include/pg_tde_fe.h +++ b/src/include/pg_tde_fe.h @@ -17,7 +17,6 @@ #include "common/logging.h" #include "common/file_perm.h" -// #pragma GCC diagnostic warning "-Wno-unused-value" #pragma GCC diagnostic ignored "-Wunused-macros" #pragma GCC diagnostic ignored "-Wunused-value" #pragma GCC diagnostic ignored "-Wunused-variable" @@ -46,16 +45,26 @@ #define errcode_for_file_access() NULL #define errcode(e) NULL +#define tde_error_handle_exit(elevel) \ + do { \ + if (elevel >= PANIC) \ + pg_unreachable(); \ + else if (elevel >= ERROR) \ + exit(1); \ + } while(0) + #define elog(elevel, fmt, ...) \ do { \ tde_fe_error_level = elevel; \ errmsg(fmt, ##__VA_ARGS__); \ + tde_error_handle_exit(elevel); \ } while(0) #define ereport(elevel,...) \ do { \ tde_fe_error_level = elevel; \ - __VA_ARGS__; \ + __VA_ARGS__; \ + tde_error_handle_exit(elevel); \ } while(0) static int tde_fe_error_level = 0; @@ -64,7 +73,6 @@ static int tde_fe_error_level = 0; * ------------- */ - #define LWLockAcquire(lock, mode) NULL #define LWLockRelease(lock_files) NULL #define LWLock void diff --git a/src/keyring/keyring_api.c b/src/keyring/keyring_api.c index cb702db0..24c9a060 100644 --- a/src/keyring/keyring_api.c +++ b/src/keyring/keyring_api.c @@ -25,7 +25,7 @@ typedef struct KeyProviders #ifndef FRONTEND List *registeredKeyProviders = NIL; #else -SimplePtrList *registeredKeyProviders = NULL; +SimplePtrList registeredKeyProviders = {NULL, NULL}; #endif static KeyProviders *find_key_provider(ProviderType type); @@ -49,7 +49,7 @@ static KeyProviders * find_key_provider(ProviderType type) { SimplePtrListCell *lc; - for (lc = registeredKeyProviders->head; lc; lc = lc->next) + for (lc = registeredKeyProviders.head; lc; lc = lc->next) { KeyProviders *kp = (KeyProviders *) lc->ptr; if (kp->type == type) @@ -88,7 +88,7 @@ bool RegisterKeyProvider(const TDEKeyringRoutine *routine, ProviderType type) registeredKeyProviders = lappend(registeredKeyProviders, kp); MemoryContextSwitchTo(oldcontext); #else - simple_ptr_list_append(registeredKeyProviders, kp); + simple_ptr_list_append(®isteredKeyProviders, kp); #endif return true; diff --git a/src/pg_tde.c b/src/pg_tde.c index 78ce4f7a..4209bfd6 100644 --- a/src/pg_tde.c +++ b/src/pg_tde.c @@ -87,7 +87,7 @@ tde_shmem_startup(void) AesInit(); #ifdef PERCONA_FORK - TDEInitGlobalKeys(); + TDEInitGlobalKeys(NULL); TDEXLogShmemInit(); TDEXLogSmgrInit();