Skip to content

Commit

Permalink
Extracting curl setup logic from the vault code (#136)
Browse files Browse the repository at this point in the history
  • Loading branch information
dutow authored Mar 7, 2024
1 parent 6b27bce commit 72d598f
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 58 deletions.
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ src/access/pg_tdeam_handler.o \
src/access/pg_tde_ddl.o \
src/transam/pg_tde_xact_handler.o \
src/keyring/keyring_config.o \
src/keyring/keyring_curl.o \
src/keyring/keyring_file.o \
src/keyring/keyring_vault.o \
src/keyring/keyring_api.o \
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pg_tde_sources = files(
'src/encryption/enc_aes.c',

'src/keyring/keyring_config.c',
'src/keyring/keyring_curl.c',
'src/keyring/keyring_file.c',
'src/keyring/keyring_vault.c',
'src/keyring/keyring_api.c',
Expand Down
31 changes: 31 additions & 0 deletions src/include/keyring/keyring_curl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*-------------------------------------------------------------------------
*
* keyring_curl.h
* Contains common curl related methods.
*
* IDENTIFICATION
* src/include/keyring/keyring_curl.h
*
*-------------------------------------------------------------------------
*/

#ifndef KEYRING_CURL_H
#define KEYRING_CURL_H

#include "pg_tde_defines.h"

#define VAULT_URL_MAX_LEN 512

#include <stdbool.h>
#include <curl/curl.h>

typedef struct CurlString {
char *ptr;
size_t len;
} CurlString;

extern CURL* keyringCurl;

bool curlSetupSession(const char* url, const char* caFile, CurlString* outStr);

#endif //KEYRING_CURL_H
3 changes: 2 additions & 1 deletion src/include/keyring/keyring_vault.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/*-------------------------------------------------------------------------
*
* keyring_vault.h
* Vault-V2 implementation
* HashiCorp Vault 2 based keyring provider
*
* IDENTIFICATION
* src/include/keyring/keyring_vault.h
*
*-------------------------------------------------------------------------
Expand Down
63 changes: 63 additions & 0 deletions src/keyring/keyring_curl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*-------------------------------------------------------------------------
*
* keyring_curl.c
* Contains common curl related methods.
*
* IDENTIFICATION
* contrib/pg_tde/src/keyring/keyring_curl.c
*
*-------------------------------------------------------------------------
*/

#include "keyring/keyring_curl.h"
#include "keyring/keyring_config.h"
#include "pg_tde_defines.h"

CURL* keyringCurl = NULL;

static
size_t write_func(void *ptr, size_t size, size_t nmemb, struct CurlString *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = repalloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;

return size*nmemb;
}

bool curlSetupSession(const char* url, const char* caFile, CurlString* outStr)
{
if(keyringCurl == NULL)
{
keyringCurl = curl_easy_init();

if(keyringCurl == NULL) return 0;
} else {
curl_easy_reset(keyringCurl);
}

if(curl_easy_setopt(keyringCurl, CURLOPT_SSL_VERIFYPEER, 1) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_SSL_VERIFYHOST, 1) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) return 0;
if(caFile != NULL && strlen(caFile) != 0)
{
if(curl_easy_setopt(keyringCurl, CURLOPT_CAINFO, caFile) != CURLE_OK) return 0;
}
if(curl_easy_setopt(keyringCurl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_CONNECTTIMEOUT, 3) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_TIMEOUT, 10) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_HTTP_VERSION,(long)CURL_HTTP_VERSION_1_1) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_WRITEFUNCTION,write_func) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_WRITEDATA,outStr) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_URL, url) != CURLE_OK) return 0;

if(curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, NULL) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_POST, 0) != CURLE_OK) return 0;

return 1;
}
85 changes: 28 additions & 57 deletions src/keyring/keyring_vault.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
/*-------------------------------------------------------------------------
*
* keyring_vault.c
* HashiCorp Vault 2 based keyring provider
*
* IDENTIFICATION
* contrib/pg_tde/src/keyring/keyring_vault.c
*
*-------------------------------------------------------------------------
*/

#include "postgres.h"

#include "keyring/keyring_vault.h"
#include "keyring/keyring_config.h"
#include "keyring/keyring_curl.h"
#include "keyring/keyring_api.h"
#include "pg_tde_defines.h"

Expand All @@ -12,19 +24,11 @@

#include "common/base64.h"

#define VAULT_URL_MAX_LEN 512
CURL *curl = NULL;
struct curl_slist *curlList = NULL;

typedef struct curlString
{
char *ptr;
size_t len;
} curlString;

static bool curl_setup_token(VaultV2Keyring *keyring);
static char *get_keyring_vault_url(VaultV2Keyring *keyring, const char *key_name, char *out, size_t out_size);
static bool curl_setup_session(VaultV2Keyring *keyring, const char *url, curlString *str);
static bool curl_perform(VaultV2Keyring *keyring, const char *url, curlString *outStr, long *httpCode, const char *postData);
static bool curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long *httpCode, const char *postData);

static KeyringReturnCodes set_key_by_name(GenericKeyring *keyring, keyInfo *key, bool throw_error);
static keyInfo *get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error, KeyringReturnCodes *return_code);
Expand All @@ -40,29 +44,9 @@ bool InstallVaultV2Keyring(void)
return RegisterKeyProvider(&keyringVaultV2Routine, VAULT_V2_KEY_PROVIDER);
}

static size_t writefunc(void *ptr, size_t size, size_t nmemb, struct curlString *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = repalloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;

return size*nmemb;
}

static bool
curl_setup_session(VaultV2Keyring *keyring, const char *url, curlString *str)
curl_setup_token(VaultV2Keyring *keyring)
{
if(curl == NULL)
{
curl = curl_easy_init();
if (curl == NULL) return 0;
}

if(curlList == NULL)
{
char tokenHeader[256];
Expand All @@ -76,26 +60,13 @@ curl_setup_session(VaultV2Keyring *keyring, const char *url, curlString *str)
if(curlList == NULL) return 0;
}

if(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curlList) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) return 0;
if (strlen(keyring->vault_ca_path) > 0 &&
curl_easy_setopt(curl, CURLOPT_CAINFO, keyring->vault_ca_path) != CURLE_OK)
return 0;
if(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,(long)CURL_HTTP_VERSION_1_1) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,writefunc) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_WRITEDATA,str) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_URL, url) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_HTTPHEADER, curlList) != CURLE_OK) return 0;

return 1;
}

static bool
curl_perform(VaultV2Keyring *keyring, const char *url, curlString *outStr, long *httpCode, const char *postData)
curl_perform(VaultV2Keyring *keyring, const char *url, CurlString *outStr, long *httpCode, const char *postData)
{
CURLcode ret;
#if KEYRING_DEBUG
Expand All @@ -108,25 +79,25 @@ curl_perform(VaultV2Keyring *keyring, const char *url, curlString *outStr, long
outStr->ptr = palloc0(1);
outStr->len = 0;

if (!curl_setup_session(keyring, url, outStr))
if (!curlSetupSession(url, keyring->vault_ca_path, outStr))
return 0;

if (!curl_setup_token(keyring))
return 0;

if(postData != NULL)
{
if(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData) != CURLE_OK) return 0;
} else
{
if(curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL) != CURLE_OK) return 0;
if(curl_easy_setopt(curl, CURLOPT_POST, 0) != CURLE_OK) return 0;
if(curl_easy_setopt(keyringCurl, CURLOPT_POSTFIELDS, postData) != CURLE_OK) return 0;
}

ret = curl_easy_perform(curl);
ret = curl_easy_perform(keyringCurl);
if (ret != CURLE_OK)
{
elog(LOG, "curl_easy_perform failed with return code: %d", ret);
return 0;
}
if(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, httpCode) != CURLE_OK) return 0;

if(curl_easy_getinfo(keyringCurl, CURLINFO_RESPONSE_CODE, httpCode) != CURLE_OK) return 0;

#if KEYRING_DEBUG
elog(DEBUG2, "Vault response [%li] '%s'", *httpCode, outStr->ptr != NULL ? outStr->ptr : "");
Expand Down Expand Up @@ -155,7 +126,7 @@ set_key_by_name(GenericKeyring* keyring, keyInfo *key, bool throw_error)
{
VaultV2Keyring *vault_keyring = (VaultV2Keyring *)keyring;
char url[VAULT_URL_MAX_LEN];
curlString str;
CurlString str;
long httpCode = 0;

json_object *request = json_object_new_object();
Expand Down Expand Up @@ -204,7 +175,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error,
VaultV2Keyring *vault_keyring = (VaultV2Keyring *)keyring;
keyInfo* key = NULL;
char url[VAULT_URL_MAX_LEN];
curlString str;
CurlString str;
json_object *response = NULL;
long httpCode = 0;

Expand Down Expand Up @@ -292,7 +263,7 @@ get_key_by_name(GenericKeyring *keyring, const char *key_name, bool throw_error,
}

#if KEYRING_DEBUG
elog(DEBUG1, "Retrieved base64 key: %s", key);
elog(DEBUG1, "Retrieved base64 key: %s", response_key);
#endif

key = palloc(sizeof(keyInfo));
Expand Down

0 comments on commit 72d598f

Please sign in to comment.