mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 00:03:09 -04:00
PG-1419 Validate key provider access
This adds some validation to make sure we can access the key provider when it's created to make the user experience a little nicer. The actual access validation is very rudimentary for now but can easily be expanded.
This commit is contained in:
parent
1b8513c21e
commit
157230de39
@ -206,8 +206,6 @@ To add a database specific provider:
|
||||
pg_tde_add_database_key_provider_<TYPE>('provider_name', ... details ...)
|
||||
```
|
||||
|
||||
Note that in these functions do not verify the parameters. For that, see `pg_tde_verify_key`.
|
||||
|
||||
### Changing providers
|
||||
|
||||
To change a value of a global provider:
|
||||
|
@ -160,4 +160,7 @@ SELECT id, provider_name FROM pg_tde_list_all_global_key_providers();
|
||||
-1 | file-keyring
|
||||
(1 row)
|
||||
|
||||
-- Creating a file key provider fails if we can't open or create the file
|
||||
SELECT pg_tde_add_database_key_provider_file('will-not-work','/cant-create-file-in-root.per');
|
||||
ERROR: Failed to open keyring file /cant-create-file-in-root.per: Permission denied
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -164,4 +164,7 @@ SELECT id, provider_name FROM pg_tde_list_all_global_key_providers();
|
||||
-2 | file-keyring
|
||||
(2 rows)
|
||||
|
||||
-- Creating a file key provider fails if we can't open or create the file
|
||||
SELECT pg_tde_add_database_key_provider_file('will-not-work','/cant-create-file-in-root.per');
|
||||
ERROR: Failed to open keyring file /cant-create-file-in-root.per: Permission denied
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -34,4 +34,7 @@ SELECT pg_tde_verify_key();
|
||||
(1 row)
|
||||
|
||||
DROP TABLE test_enc;
|
||||
-- Creating provider fails if we can't connect to kmip server
|
||||
SELECT pg_tde_add_database_key_provider_kmip('will-not-work','127.0.0.1', 61, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem');
|
||||
ERROR: SSL error: BIO_do_connect failed
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -51,4 +51,7 @@ SELECT pg_tde_verify_key();
|
||||
(1 row)
|
||||
|
||||
DROP TABLE test_enc;
|
||||
-- Creating provider fails if we can't connect to vault
|
||||
SELECT pg_tde_add_database_key_provider_vault_v2('will-not-work', :'root_token', 'http://127.0.0.1:61', 'secret', NULL);
|
||||
ERROR: HTTP(S) request to keyring provider "will-not-work" failed
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -52,4 +52,7 @@ SELECT id, provider_name FROM pg_tde_list_all_global_key_providers();
|
||||
SELECT pg_tde_delete_global_key_provider('file-keyring2');
|
||||
SELECT id, provider_name FROM pg_tde_list_all_global_key_providers();
|
||||
|
||||
-- Creating a file key provider fails if we can't open or create the file
|
||||
SELECT pg_tde_add_database_key_provider_file('will-not-work','/cant-create-file-in-root.per');
|
||||
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -19,4 +19,7 @@ SELECT pg_tde_verify_key();
|
||||
|
||||
DROP TABLE test_enc;
|
||||
|
||||
-- Creating provider fails if we can't connect to kmip server
|
||||
SELECT pg_tde_add_database_key_provider_kmip('will-not-work','127.0.0.1', 61, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem');
|
||||
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -31,4 +31,7 @@ SELECT pg_tde_verify_key();
|
||||
|
||||
DROP TABLE test_enc;
|
||||
|
||||
-- Creating provider fails if we can't connect to vault
|
||||
SELECT pg_tde_add_database_key_provider_vault_v2('will-not-work', :'root_token', 'http://127.0.0.1:61', 'secret', NULL);
|
||||
|
||||
DROP EXTENSION pg_tde;
|
||||
|
@ -472,6 +472,8 @@ check_provider_record(KeyringProviderRecord *provider_record)
|
||||
errmsg("Invalid provider options."));
|
||||
}
|
||||
|
||||
KeyringValidate(provider);
|
||||
|
||||
pfree(provider);
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ typedef struct TDEKeyringRoutine
|
||||
{
|
||||
KeyInfo *(*keyring_get_key) (GenericKeyring *keyring, const char *key_name, KeyringReturnCodes *returnCode);
|
||||
void (*keyring_store_key) (GenericKeyring *keyring, KeyInfo *key);
|
||||
void (*keyring_validate) (GenericKeyring *keyring);
|
||||
} TDEKeyringRoutine;
|
||||
|
||||
typedef struct FileKeyring
|
||||
@ -91,5 +92,6 @@ extern void RegisterKeyProviderType(const TDEKeyringRoutine *routine, ProviderTy
|
||||
|
||||
extern KeyInfo *KeyringGetKey(GenericKeyring *keyring, const char *key_name, KeyringReturnCodes *returnCode);
|
||||
extern KeyInfo *KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, unsigned key_len);
|
||||
extern void KeyringValidate(GenericKeyring *keyring);
|
||||
|
||||
#endif /* KEYRING_API_H */
|
||||
|
@ -74,6 +74,7 @@ RegisterKeyProviderType(const TDEKeyringRoutine *routine, ProviderType type)
|
||||
Assert(routine != NULL);
|
||||
Assert(routine->keyring_get_key != NULL);
|
||||
Assert(routine->keyring_store_key != NULL);
|
||||
Assert(routine->keyring_validate != NULL);
|
||||
|
||||
kp = find_key_provider_type(type);
|
||||
if (kp)
|
||||
@ -148,3 +149,15 @@ KeyringGenerateNewKeyAndStore(GenericKeyring *keyring, const char *key_name, uns
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void
|
||||
KeyringValidate(GenericKeyring *keyring)
|
||||
{
|
||||
RegisteredKeyProviderType *kp = find_key_provider_type(keyring->type);
|
||||
|
||||
if (kp == NULL)
|
||||
ereport(ERROR,
|
||||
errmsg("Key provider of type %d not registered", keyring->type));
|
||||
|
||||
kp->routine->keyring_validate(keyring);
|
||||
}
|
||||
|
@ -28,10 +28,12 @@
|
||||
|
||||
static KeyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, KeyringReturnCodes *return_code);
|
||||
static void set_key_by_name(GenericKeyring *keyring, KeyInfo *key);
|
||||
static void validate(GenericKeyring *keyring);
|
||||
|
||||
const TDEKeyringRoutine keyringFileRoutine = {
|
||||
.keyring_get_key = get_key_by_name,
|
||||
.keyring_store_key = set_key_by_name
|
||||
.keyring_store_key = set_key_by_name,
|
||||
.keyring_validate = validate,
|
||||
};
|
||||
|
||||
void
|
||||
@ -143,3 +145,19 @@ set_key_by_name(GenericKeyring *keyring, KeyInfo *key)
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
validate(GenericKeyring *keyring)
|
||||
{
|
||||
FileKeyring *file_keyring = (FileKeyring *) keyring;
|
||||
int fd = BasicOpenFile(file_keyring->file_name, O_CREAT | O_RDWR | PG_BINARY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
ereport(ERROR,
|
||||
errcode_for_file_access(),
|
||||
errmsg("Failed to open keyring file %s: %m", file_keyring->file_name));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
@ -26,10 +26,12 @@
|
||||
|
||||
static void set_key_by_name(GenericKeyring *keyring, KeyInfo *key);
|
||||
static KeyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, KeyringReturnCodes *return_code);
|
||||
static void validate(GenericKeyring *keyring);
|
||||
|
||||
const TDEKeyringRoutine keyringKmipRoutine = {
|
||||
.keyring_get_key = get_key_by_name,
|
||||
.keyring_store_key = set_key_by_name
|
||||
.keyring_store_key = set_key_by_name,
|
||||
.keyring_validate = validate,
|
||||
};
|
||||
|
||||
void
|
||||
@ -204,3 +206,15 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, KeyringReturnCode
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
validate(GenericKeyring *keyring)
|
||||
{
|
||||
KmipKeyring *kmip_keyring = (KmipKeyring *) keyring;
|
||||
KmipCtx ctx;
|
||||
|
||||
kmipSslConnect(&ctx, kmip_keyring, true);
|
||||
|
||||
BIO_free_all(ctx.bio);
|
||||
SSL_CTX_free(ctx.ssl);
|
||||
}
|
||||
|
@ -70,10 +70,12 @@ static bool curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *o
|
||||
|
||||
static void set_key_by_name(GenericKeyring *keyring, KeyInfo *key);
|
||||
static KeyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, KeyringReturnCodes *return_code);
|
||||
static void validate(GenericKeyring *keyring);
|
||||
|
||||
const TDEKeyringRoutine keyringVaultV2Routine = {
|
||||
.keyring_get_key = get_key_by_name,
|
||||
.keyring_store_key = set_key_by_name
|
||||
.keyring_store_key = set_key_by_name,
|
||||
.keyring_validate = validate,
|
||||
};
|
||||
|
||||
void
|
||||
@ -300,6 +302,41 @@ cleanup:
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
validate(GenericKeyring *keyring)
|
||||
{
|
||||
VaultV2Keyring *vault_keyring = (VaultV2Keyring *) keyring;
|
||||
char url[VAULT_URL_MAX_LEN];
|
||||
CurlString str;
|
||||
long httpCode = 0;
|
||||
|
||||
/*
|
||||
* Validate connection by listing available keys at the root level of the
|
||||
* mount point
|
||||
*/
|
||||
snprintf(url, VAULT_URL_MAX_LEN, "%s/v1/%s/metadata/?list=true",
|
||||
vault_keyring->vault_url, vault_keyring->vault_mount_path);
|
||||
|
||||
if (!curl_perform(vault_keyring, url, &str, &httpCode, NULL))
|
||||
{
|
||||
ereport(ERROR,
|
||||
errmsg("HTTP(S) request to keyring provider \"%s\" failed",
|
||||
vault_keyring->keyring.provider_name));
|
||||
}
|
||||
|
||||
/* If the mount point doesn't have any secrets yet, we'll get a 404. */
|
||||
if (httpCode != 200 && httpCode != 404)
|
||||
{
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("Listing secrets of \"%s\" at mountpoint \"%s\" failed",
|
||||
vault_keyring->vault_url, vault_keyring->vault_mount_path));
|
||||
}
|
||||
|
||||
if (str.ptr != NULL)
|
||||
pfree(str.ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* JSON parser routines
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user