Skip to content

Commit

Permalink
Use common keyring and key rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
dAdAbird committed Jul 16, 2024
1 parent f684c5d commit be3c77f
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 106 deletions.
68 changes: 68 additions & 0 deletions pg_tde--1.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,59 @@ AS $$
$$
LANGUAGE SQL;

-- Global Tblespace Key Provider Management
CREATE FUNCTION pg_tde_add_global_key_provider_internal(provider_type VARCHAR(10), provider_name VARCHAR(128), options JSON)
RETURNS INT
AS 'MODULE_PATHNAME'
LANGUAGE C;

CREATE OR REPLACE FUNCTION pg_tde_add_global_key_provider(provider_type VARCHAR(10), provider_name VARCHAR(128), options JSON)
RETURNS INT
AS $$
SELECT pg_tde_add_global_key_provider_internal(provider_type, provider_name, options);
$$
LANGUAGE SQL;

CREATE OR REPLACE FUNCTION pg_tde_add_global_key_provider_file(provider_name VARCHAR(128), file_path TEXT)
RETURNS INT
AS $$
-- JSON keys in the options must be matched to the keys in
-- load_file_keyring_provider_options function.

SELECT pg_tde_add_global_key_provider('file', provider_name,
json_object('type' VALUE 'file', 'path' VALUE COALESCE(file_path, '')));
$$
LANGUAGE SQL;

CREATE OR REPLACE FUNCTION pg_tde_add_global_key_provider_file(provider_name VARCHAR(128), file_path JSON)
RETURNS INT
AS $$
-- JSON keys in the options must be matched to the keys in
-- load_file_keyring_provider_options function.

SELECT pg_tde_add_global_key_provider('file', provider_name,
json_object('type' VALUE 'file', 'path' VALUE file_path));
$$
LANGUAGE SQL;

CREATE OR REPLACE FUNCTION pg_tde_add_global_key_provider_vault_v2(provider_name VARCHAR(128),
vault_token TEXT,
vault_url TEXT,
vault_mount_path TEXT,
vault_ca_path TEXT)
RETURNS INT
AS $$
-- JSON keys in the options must be matched to the keys in
-- load_vaultV2_keyring_provider_options function.
SELECT pg_tde_add_global_key_provider('vault-v2', provider_name,
json_object('type' VALUE 'vault-v2',
'url' VALUE COALESCE(vault_url,''),
'token' VALUE COALESCE(vault_token,''),
'mountPath' VALUE COALESCE(vault_mount_path,''),
'caPath' VALUE COALESCE(vault_ca_path,'')));
$$
LANGUAGE SQL;

-- Table access method
CREATE FUNCTION pg_tdeam_basic_handler(internal)
RETURNS table_am_handler
Expand All @@ -78,6 +131,11 @@ RETURNS boolean
AS 'MODULE_PATHNAME'
LANGUAGE C;

CREATE FUNCTION pg_tde_rotate_global_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_database_key(principal_key_name VARCHAR(255), provider_name VARCHAR(255), ensure_new_key BOOLEAN DEFAULT FALSE)
RETURNS boolean
AS 'MODULE_PATHNAME'
Expand All @@ -98,6 +156,16 @@ RETURNS TABLE ( principal_key_name text,
AS 'MODULE_PATHNAME'
LANGUAGE C;

CREATE FUNCTION pg_tde_global_key_info()
RETURNS TABLE ( principal_key_name text,
key_provider_name text,
key_provider_id integer,
principal_key_internal_name text,
principal_key_version integer,
key_createion_time timestamp with time zone)
AS 'MODULE_PATHNAME'
LANGUAGE C;

CREATE FUNCTION pg_tde_version() RETURNS TEXT AS 'MODULE_PATHNAME' LANGUAGE C;

-- Access method
Expand Down
97 changes: 38 additions & 59 deletions src/catalog/tde_global_catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#ifdef PERCONA_FORK

#include "catalog/pg_tablespace_d.h"
#include "nodes/pg_list.h"
#include "storage/shmem.h"
#include "utils/guc.h"
#include "utils/memutils.h"
Expand All @@ -28,6 +30,10 @@
#include <sys/time.h>

#define PRINCIPAL_KEY_DEFAULT_NAME "tde-global-catalog-key"
#define KEYRING_DEFAULT_NAME "default_global_tablespace_keyring"

#define DefaultKeyProvider GetKeyProviderByName(KEYRING_DEFAULT_NAME, \
GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID)

typedef enum
{
Expand All @@ -39,61 +45,30 @@ typedef enum

typedef struct EncryptionStateData
{
GenericKeyring *keyring;
RelKeyData *internal_keys;

/* TODO: Since for the global tablespace we always keep the Internal key in
* the memory and read it from disk only once during the server start, hence
* we need the Principal key only once and don't have to store it in a
* cache.
*/
TDEPrincipalKey principal_key;
} EncryptionStateData;

static EncryptionStateData * EncryptionState = NULL;

/* GUC */
static char *KRingProviderType = NULL;
static char *KRingProviderFilePath = NULL;

static void init_gl_catalog_keys(void);
static void init_keyring(void);
static void init_default_keyring(void);
static TDEPrincipalKey * create_principal_key(const char *key_name,
GenericKeyring * keyring, Oid dbOid, Oid spcOid,
bool ensure_new_key);
static void cache_internal_key(RelKeyData * ikey, InternalKeyType type);

void
TDEGlCatInitGUC(void)
{
DefineCustomStringVariable("pg_tde.global_keyring_type",
"Keyring type for global catalog",
NULL,
&KRingProviderType,
NULL,
PGC_POSTMASTER,
0, /* no flags required */
NULL,
NULL,
NULL
);
DefineCustomStringVariable("pg_tde.global_keyring_file_path",
"Keyring file options for global catalog",
NULL,
&KRingProviderFilePath,
NULL,
PGC_POSTMASTER,
0, /* no flags required */
NULL,
NULL,
NULL
);
}


Size
TDEGlCatEncStateSize(void)
{
Size size;

size = sizeof(EncryptionStateData);
size = add_size(size, sizeof(KeyringProviders));

return MAXALIGN(size);
return MAXALIGN(sizeof(EncryptionStateData));
}

void
Expand All @@ -106,9 +81,6 @@ TDEGlCatShmemInit(void)
ShmemInitStruct("TDE XLog Encryption State",
TDEGlCatEncStateSize(), &foundBuf);

allocptr = ((char *) EncryptionState) + MAXALIGN(sizeof(EncryptionStateData));
EncryptionState->keyring = (GenericKeyring *) allocptr;
memset(EncryptionState->keyring, 0, sizeof(KeyringProviders));
memset(&EncryptionState->principal_key, 0, sizeof(TDEPrincipalKey));
}

Expand All @@ -117,7 +89,7 @@ TDEGlCatKeyInit(void)
{
char db_map_path[MAXPGPATH] = {0};

init_keyring();
init_default_keyring();

pg_tde_set_db_file_paths(&GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID),
db_map_path, NULL);
Expand All @@ -129,7 +101,8 @@ TDEGlCatKeyInit(void)
{
RelKeyData *ikey;

ikey = pg_tde_get_key_from_file(&GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID), EncryptionState->keyring);
ikey = pg_tde_get_key_from_file(&GLOBAL_SPACE_RLOCATOR(XLOG_TDE_OID),
NULL);
cache_internal_key(ikey, TDE_INTERNAL_XLOG_KEY);
}
}
Expand Down Expand Up @@ -189,22 +162,27 @@ GetGlCatInternalKey(Oid obj_id)
return EncryptionState->internal_keys + ktype;
}

/*
* TODO: should be aligned with the rest of the keyring_provider code after its
* refactoring
*
* TODO: add Vault
*/
static void
init_keyring(void)
init_default_keyring(void)
{
EncryptionState->keyring->type = get_keyring_provider_from_typename(KRingProviderType);
switch (EncryptionState->keyring->type)
if (GetAllKeyringProviders(GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID) == NIL)
{
case FILE_KEY_PROVIDER:
FileKeyring * kring = (FileKeyring *) EncryptionState->keyring;
strncpy(kring->file_name, KRingProviderFilePath, sizeof(kring->file_name));
break;
static KeyringProvideRecord provider = {
.provider_name = KEYRING_DEFAULT_NAME,
.provider_type = FILE_KEY_PROVIDER,
.options =
"{"
"\"type\": \"file\","
" \"path\": \"pg_tde_default_keyring_CHANGE_IT_AND_REMOVE\"" /*TODO: not sure about the location*/
"}"
};

/* TODO: should we remove it automaticaly on pg_tde_rotate_global_key() ? */
save_new_key_provider_info(&provider, GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, true);
elog(INFO,
"default keyring has been created for the global tablespace (WAL)."
" Change it with pg_tde_add_global_key_provider_* and run pg_tde_rotate_global_key."
);
}
}

Expand All @@ -220,8 +198,9 @@ init_gl_catalog_keys(void)
RelFileLocator *rlocator;
TDEPrincipalKey *mkey;

/* TODO: Use SetPrincipalKey()? */
mkey = create_principal_key(PRINCIPAL_KEY_DEFAULT_NAME,
EncryptionState->keyring,
DefaultKeyProvider,
GLOBAL_DATA_TDE_OID, GLOBALTABLESPACE_OID, false);

memset(&int_key, 0, sizeof(InternalKey));
Expand Down Expand Up @@ -269,7 +248,7 @@ create_principal_key(const char *key_name, GenericKeyring * keyring,
if (keyInfo == NULL)
{
ereport(ERROR,
(errmsg("failed to retrieve principal key")));
(errmsg("failed to generate principal key")));
}

principalKey->keyLength = keyInfo->data.len;
Expand Down
Loading

0 comments on commit be3c77f

Please sign in to comment.