Skip to content

Commit

Permalink
Add function to list available key provides for database (#239)
Browse files Browse the repository at this point in the history
* Add function to list available key provides for database
  • Loading branch information
codeforall authored Jul 25, 2024
1 parent af3d914 commit fd37374
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
8 changes: 8 additions & 0 deletions expected/keyprovider_dependency.out
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/va
3
(1 row)

SELECT * FROM pg_tde_list_all_key_providers();
id | provider_name | provider_type | options
----+---------------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------
1 | mk-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring.per"}
2 | free-file | file | {"type" : "file", "path" : "/tmp/pg_tde_test_keyring_2.per"}
3 | V2-vault | vault-v2 | {"type" : "vault-v2", "url" : "percona.com/vault-v2/percona", "token" : "vault-token", "mountPath" : "/mount/dev", "caPath" : "ca-cert-auth"}
(3 rows)

SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file');
pg_tde_set_principal_key
--------------------------
Expand Down
9 changes: 9 additions & 0 deletions pg_tde--1.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ AS $$
$$
LANGUAGE SQL;

CREATE FUNCTION pg_tde_list_all_key_providers
(OUT id INT,
OUT provider_name VARCHAR(128),
OUT provider_type VARCHAR(10),
OUT options JSON)
RETURNS SETOF record
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT VOLATILE;

-- Table access method
CREATE FUNCTION pg_tdeam_basic_handler(internal)
RETURNS table_am_handler
Expand Down
2 changes: 2 additions & 0 deletions sql/keyprovider_dependency.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ SELECT pg_tde_add_key_provider_file('mk-file','/tmp/pg_tde_test_keyring.per');
SELECT pg_tde_add_key_provider_file('free-file','/tmp/pg_tde_test_keyring_2.per');
SELECT pg_tde_add_key_provider_vault_v2('V2-vault','vault-token','percona.com/vault-v2/percona','/mount/dev','ca-cert-auth');

SELECT * FROM pg_tde_list_all_key_providers();

SELECT pg_tde_set_principal_key('test-db-principal-key','mk-file');

DROP EXTENSION pg_tde;
80 changes: 77 additions & 3 deletions src/catalog/tde_keyring.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "funcapi.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/pg_tde_xlog.h"
Expand All @@ -34,6 +35,8 @@
PG_FUNCTION_INFO_V1(pg_tde_add_key_provider_internal);
Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(pg_tde_list_all_key_providers);
Datum pg_tde_list_all_key_providers(PG_FUNCTION_ARGS);

#define PG_TDE_KEYRING_FILENAME "pg_tde_keyrings"
/*
Expand All @@ -51,6 +54,7 @@ Datum pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS);
*/
#define FILE_KEYRING_PATH_KEY "path"
#define FILE_KEYRING_TYPE_KEY "type"
#define PG_TDE_LIST_PROVIDERS_COLS 4

typedef enum ProviderScanType
{
Expand All @@ -70,7 +74,7 @@ static char *get_keyring_infofile_path(char *resPath, Oid dbOid, Oid spcOid);
static void key_provider_startup_cleanup(int tde_tbl_count, XLogExtensionInstall *ext_info, bool redo, void *arg);
static uint32 write_key_provider_info(KeyringProvideRecord *provider, Oid database_id, Oid tablespace_id, off_t position, bool redo);
static uint32 save_new_key_provider_info(KeyringProvideRecord *provider);

static const char *get_keyring_provider_typename(ProviderType p_type);
static Size initialize_shared_state(void *start_address);
static Size required_shared_mem_size(void);

Expand Down Expand Up @@ -141,8 +145,22 @@ get_keyring_provider_from_typename(char *provider_type)
return UNKNOWN_KEY_PROVIDER;
}

static GenericKeyring *
load_keyring_provider_from_record(KeyringProvideRecord* provider)
static const char *
get_keyring_provider_typename(ProviderType p_type)
{
switch (p_type)
{
case FILE_KEY_PROVIDER:
return FILE_KEYRING_TYPE;
case VAULT_V2_KEY_PROVIDER:
return VAULTV2_KEYRING_TYPE;
default:
break;
}
return NULL;
}

static GenericKeyring *load_keyring_provider_from_record(KeyringProvideRecord *provider)
{
Datum option_datum;
GenericKeyring *keyring = NULL;
Expand All @@ -155,6 +173,7 @@ load_keyring_provider_from_record(KeyringProvideRecord* provider)
keyring->key_id = provider->provider_id;
strncpy(keyring->provider_name, provider->provider_name, sizeof(keyring->provider_name));
keyring->type = provider->provider_type;
strncpy(keyring->options, provider->options, sizeof(keyring->options));
debug_print_kerying(keyring);
}
return keyring;
Expand Down Expand Up @@ -513,3 +532,58 @@ pg_tde_add_key_provider_internal(PG_FUNCTION_ARGS)

PG_RETURN_INT32(provider.provider_id);
}

Datum
pg_tde_list_all_key_providers(PG_FUNCTION_ARGS)
{
List* all_providers = GetAllKeyringProviders();
ListCell *lc;
Tuplestorestate *tupstore;
TupleDesc tupdesc;
MemoryContext per_query_ctx;
MemoryContext oldcontext;
ReturnSetInfo *rsinfo = (ReturnSetInfo *)fcinfo->resultinfo;
/* check to see if caller supports us returning a tuplestore */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("pg_tde_list_all_key_providers: set-valued function called in context that cannot accept a set")));
if (!(rsinfo->allowedModes & SFRM_Materialize))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("pg_tde_list_all_key_providers: materialize mode required, but it is not allowed in this context")));

/* Switch into long-lived context to construct returned data structures */
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx);

/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "pg_tde_list_all_key_providers: return type must be a row type");

tupstore = tuplestore_begin_heap(true, false, work_mem);
rsinfo->returnMode = SFRM_Materialize;
rsinfo->setResult = tupstore;
rsinfo->setDesc = tupdesc;

MemoryContextSwitchTo(oldcontext);

foreach (lc, all_providers)
{
Datum values[PG_TDE_LIST_PROVIDERS_COLS] = {0};
bool nulls[PG_TDE_LIST_PROVIDERS_COLS] = {0};
GenericKeyring *keyring = (GenericKeyring *)lfirst(lc);
int i = 0;

values[i++] = Int32GetDatum(keyring->key_id);
values[i++] = CStringGetTextDatum(keyring->provider_name);
values[i++] = CStringGetTextDatum(get_keyring_provider_typename(keyring->type));
values[i++] = CStringGetTextDatum(keyring->options);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);

debug_print_kerying(keyring);
}
tuplestore_donestoring(tupstore);
list_free_deep(all_providers);
return (Datum)0;
}
1 change: 1 addition & 0 deletions src/include/catalog/tde_keyring.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ typedef struct GenericKeyring
ProviderType type; /* Must be the first field */
Oid key_id;
char provider_name[MAX_PROVIDER_NAME_LEN];
char options[MAX_KEYRING_OPTION_LEN]; /* User provided options string*/
} GenericKeyring;

typedef struct FileKeyring
Expand Down

0 comments on commit fd37374

Please sign in to comment.