diff --git a/expected/pgtde_is_encrypted.out b/expected/pgtde_is_encrypted.out index be395fb4..8198ad06 100644 --- a/expected/pgtde_is_encrypted.out +++ b/expected/pgtde_is_encrypted.out @@ -1,4 +1,7 @@ CREATE EXTENSION pg_tde; +SELECT * FROM tde_master_key_info(); +ERROR: Master key does not exists for the database +HINT: Use set_master_key interface to set the master key SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); pg_tde_add_key_provider_file ------------------------------ @@ -45,6 +48,13 @@ SELECT pgtde_is_encrypted('test_norm'); f (1 row) +SELECT key_provider_id, key_provider_name, master_key_name + FROM tde_master_key_info(); + key_provider_id | key_provider_name | master_key_name +-----------------+-------------------+-------------------- + 1 | file-vault | test-db-master-key +(1 row) + DROP TABLE test_enc; DROP TABLE test_norm; DROP EXTENSION pg_tde; diff --git a/pg_tde--1.0.sql b/pg_tde--1.0.sql index 25142ad0..a43b4204 100644 --- a/pg_tde--1.0.sql +++ b/pg_tde--1.0.sql @@ -113,6 +113,15 @@ RETURNS VOID AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION tde_master_key_info() +RETURNS TABLE ( master_key_name text, + key_provider_name text, + key_provider_id integer, + master_key_internal_name text, + master_key_version integer, + key_createion_time timestamp with time zone) +AS 'MODULE_PATHNAME' +LANGUAGE C; -- Access method CREATE ACCESS METHOD pg_tde TYPE TABLE HANDLER pg_tdeam_handler; diff --git a/sql/pgtde_is_encrypted.sql b/sql/pgtde_is_encrypted.sql index dcd4ad36..a3e71192 100644 --- a/sql/pgtde_is_encrypted.sql +++ b/sql/pgtde_is_encrypted.sql @@ -1,5 +1,7 @@ CREATE EXTENSION pg_tde; +SELECT * FROM tde_master_key_info(); + SELECT pg_tde_add_key_provider_file('file-vault','/tmp/pg_tde_test_keyring.per'); SELECT pg_tde_set_master_key('test-db-master-key','file-vault'); @@ -21,6 +23,9 @@ SELECT amname FROM pg_class INNER JOIN pg_am ON pg_am.oid = pg_class.relam WHERE SELECT pgtde_is_encrypted('test_enc'); SELECT pgtde_is_encrypted('test_norm'); +SELECT key_provider_id, key_provider_name, master_key_name + FROM tde_master_key_info(); + DROP TABLE test_enc; DROP TABLE test_norm; diff --git a/src/catalog/tde_master_key.c b/src/catalog/tde_master_key.c index d8517524..946bf7b1 100644 --- a/src/catalog/tde_master_key.c +++ b/src/catalog/tde_master_key.c @@ -19,6 +19,7 @@ #include "utils/palloc.h" #include "utils/memutils.h" #include "utils/wait_event.h" +#include "utils/timestamp.h" #include "common/relpath.h" #include "miscadmin.h" #include "funcapi.h" @@ -674,3 +675,66 @@ pg_tde_rotate_key(PG_FUNCTION_ARGS) ret = RotateMasterKey(new_master_key_name, new_provider_name, ensure_new_key); PG_RETURN_BOOL(ret); } + +PG_FUNCTION_INFO_V1(tde_master_key_info); +Datum tde_master_key_info(PG_FUNCTION_ARGS) +{ + TupleDesc tupdesc; + Datum values[6]; + bool isnull[6]; + HeapTuple tuple; + Datum result; + TDEMasterKey *master_key; + TimestampTz ts; + GenericKeyring *keyring; + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function returning record called in context that cannot accept type record"))); + + master_key = GetMasterKey(); + if (master_key == NULL) + PG_RETURN_NULL(); + + keyring = GetKeyProviderByID(master_key->keyInfo.keyringId); + + /* Initialize the values and null flags */ + + /* TEXT: Master key name */ + values[0] = CStringGetTextDatum(master_key->keyInfo.keyId.name); + isnull[0] = false; + /* TEXT: Keyring provider name */ + if (keyring) + { + values[1] = CStringGetTextDatum(keyring->provider_name); + isnull[1] = false; + } + else + isnull[1] = true; + + /* INTEGERT: key provider id */ + values[2] = Int32GetDatum(master_key->keyInfo.keyringId); + isnull[2] = false; + + /* TEXT: Master key versioned name */ + values[3] = CStringGetTextDatum(master_key->keyInfo.keyId.versioned_name); + isnull[3] = false; + /* INTEGERT: Master key version */ + values[4] = Int32GetDatum(master_key->keyInfo.keyId.version); + isnull[4] = false; + /* TIMESTAMP TZ: Master key creation time */ + ts = (TimestampTz)master_key->keyInfo.creationTime.tv_sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); + ts = (ts * USECS_PER_SEC) + master_key->keyInfo.creationTime.tv_usec; + values[5] = TimestampTzGetDatum(ts); + isnull[5] = false; + + /* Form the tuple */ + tuple = heap_form_tuple(tupdesc, values, isnull); + + /* Make the tuple into a datum */ + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +}