Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADBDEV-6683 TLS options implemented for PXF FDW #146

Open
wants to merge 1 commit into
base: pxf-6.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions external-table/src/libchurl.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ log_curl_debug(CURL *handle, curl_infotype type, char *data, size_t size, void *
}

static CHURL_HANDLE
churl_init(const char *url, CHURL_HEADERS headers)
churl_init(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options /* = NULL */)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it fdw?

{
churl_context *context = churl_new_context();

Expand Down Expand Up @@ -446,9 +446,9 @@ churl_init_upload_timeout(const char *url, CHURL_HEADERS headers, long timeout)
}

CHURL_HANDLE
churl_init_download(const char *url, CHURL_HEADERS headers)
churl_init_download(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options)
{
churl_context *context = churl_init(url, headers);
churl_context *context = churl_init(url, headers, ssl_options);

context->upload = false;

Expand Down
45 changes: 38 additions & 7 deletions fdw/libchurl.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ static JsonSemAction nullSemAction =
churl_context *churl_new_context(void);
static void create_curl_handle(churl_context *context);
static void set_curl_option(churl_context *context, CURLoption option, const void *data);
static void set_curl_ssl_options(churl_context *context, churl_ssl_options *ssl_options);
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userdata);
static void setup_multi_handle(churl_context *context);
static void multi_perform(churl_context *context);
Expand Down Expand Up @@ -388,7 +389,7 @@ log_curl_debug(CURL *handle, curl_infotype type, char *data, size_t size, void *
}

static CHURL_HANDLE
churl_init(const char *url, CHURL_HEADERS headers)
churl_init(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options /* = NULL*/)
{
churl_context *context = churl_new_context();

Expand Down Expand Up @@ -422,21 +423,51 @@ churl_init(const char *url, CHURL_HEADERS headers)
set_curl_option(context, CURLOPT_WRITEDATA, context);
set_curl_option(context, CURLOPT_HEADERFUNCTION, header_callback);
set_curl_option(context, CURLOPT_HEADERDATA, context);

set_curl_ssl_options(context, ssl_options);

churl_headers_set(context, headers);

return (CHURL_HANDLE) context;
}

static void
set_curl_ssl_options(churl_context *context, churl_ssl_options *ssl_options)
{
if (ssl_options != NULL) {
const char *cacert = ssl_options->pxf_ssl_cacert; // PXF_SSL_CACERT

if (ssl_options->pxf_ssl_cert)
set_curl_option(context, CURLOPT_SSLCERT, ssl_options->pxf_ssl_cert);

if (ssl_options->pxf_ssl_key)
set_curl_option(context, CURLOPT_SSLKEY, ssl_options->pxf_ssl_key);

if (ssl_options->pxf_ssl_cert_type)
set_curl_option(context, CURLOPT_SSLCERTTYPE, ssl_options->pxf_ssl_cert_type);

if (ssl_options->pxf_ssl_keypasswd != NULL) {
set_curl_option(context, CURLOPT_SSLKEYPASSWD, ssl_options->pxf_ssl_keypasswd);
}

if (cacert != NULL && cacert[0] != '\0') {
set_curl_option(context, CURLOPT_CAINFO, cacert);
}

set_curl_option(context, CURLOPT_SSL_VERIFYPEER, (const void *)ssl_options->pxf_ssl_verify_peer);
}
}

CHURL_HANDLE
churl_init_upload(const char *url, CHURL_HEADERS headers)
churl_init_upload(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options)
{
return churl_init_upload_timeout(url, headers, 0);
return churl_init_upload_timeout(url, headers, ssl_options, 0);
}

CHURL_HANDLE
churl_init_upload_timeout(const char *url, CHURL_HEADERS headers, long timeout)
churl_init_upload_timeout(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options, long timeout)
{
churl_context *context = churl_init(url, headers);
churl_context *context = churl_init(url, headers, ssl_options);

context->upload = true;

Expand All @@ -453,9 +484,9 @@ churl_init_upload_timeout(const char *url, CHURL_HEADERS headers, long timeout)
}

CHURL_HANDLE
churl_init_download(const char *url, CHURL_HEADERS headers)
churl_init_download(const char *url, CHURL_HEADERS headers, churl_ssl_options *ssl_options)
{
churl_context *context = churl_init(url, headers);
churl_context *context = churl_init(url, headers, ssl_options);

context->upload = false;

Expand Down
21 changes: 18 additions & 3 deletions fdw/libchurl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@
typedef void *CHURL_HEADERS;
typedef void *CHURL_HANDLE;

/*
SSL options
*/
typedef struct {
char *pxf_ssl_cacert;
char *pxf_ssl_cert;
char *pxf_ssl_cert_type;
char *pxf_ssl_key;
char *pxf_ssl_keypasswd;
long pxf_ssl_verify_peer;
} churl_ssl_options;

/*
* PUT example
* -----------
Expand Down Expand Up @@ -104,8 +116,10 @@ void churl_headers_cleanup(CHURL_HEADERS headers);
* Start an upload to url
* returns a handle to churl transfer
*/
CHURL_HANDLE churl_init_upload(const char *url, CHURL_HEADERS headers);
CHURL_HANDLE churl_init_upload_timeout(const char *url, CHURL_HEADERS headers, long timeout);
CHURL_HANDLE churl_init_upload(const char *url, CHURL_HEADERS headers,
churl_ssl_options *ssl_options);
CHURL_HANDLE churl_init_upload_timeout(const char *url, CHURL_HEADERS headers,
churl_ssl_options *ssl_options, long timeout);

/*
* Returns local port of connected handle or 0
Expand All @@ -116,7 +130,8 @@ int churl_get_local_port(CHURL_HANDLE handle);
* Start a download to url
* returns a handle to churl transfer
*/
CHURL_HANDLE churl_init_download(const char *url, CHURL_HEADERS headers);
CHURL_HANDLE churl_init_download(const char *url, CHURL_HEADERS headers,
churl_ssl_options *ssl_options);

/*
* Restart a session to a new URL
Expand Down
85 changes: 79 additions & 6 deletions fdw/pxf_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ typedef struct PxfFdwCancelState
CHURL_HANDLE churl_handle;
ResourceOwner owner;
StringInfoData uri;
char *pxf_protocol;
int pxf_port; /* port number for the PXF Service */
char *pxf_host; /* hostname for the PXF Service */
churl_ssl_options *ssl_options; /* NULL if SSL not configured */
} PxfFdwCancelState;

/* helper function declarations */
Expand All @@ -47,6 +49,50 @@ static size_t FillBuffer(PxfFdwScanState *pxfsstate, char *start, int minlen, in
static size_t FillBuffer(PxfFdwScanState *pxfsstate, char *start, size_t size);
#endif

static churl_ssl_options *churl_make_ssl_options(PxfOptions *options)
{
churl_ssl_options *ssl_options = palloc0(sizeof(churl_ssl_options));

if (options->pxf_ssl_cacert)
ssl_options->pxf_ssl_cacert = pstrdup(options->pxf_ssl_cacert);

if (options->pxf_ssl_cert)
ssl_options->pxf_ssl_cert = pstrdup(options->pxf_ssl_cert);

if (options->pxf_ssl_cert_type)
ssl_options->pxf_ssl_cert_type = pstrdup(options->pxf_ssl_cert_type);

if (options->pxf_ssl_key)
ssl_options->pxf_ssl_key = pstrdup(options->pxf_ssl_key);

if (options->pxf_ssl_keypasswd)
ssl_options->pxf_ssl_keypasswd = pstrdup(options->pxf_ssl_keypasswd);

ssl_options->pxf_ssl_verify_peer = options->pxf_ssl_verify_peer;

return ssl_options;
}

static void free_churl_ssl_options(churl_ssl_options *ssl_options)
{
if (ssl_options->pxf_ssl_cacert)
pfree(ssl_options->pxf_ssl_cacert);

if (ssl_options->pxf_ssl_cert)
pfree(ssl_options->pxf_ssl_cert);

if (ssl_options->pxf_ssl_cert_type)
pfree(ssl_options->pxf_ssl_cert_type);

if (ssl_options->pxf_ssl_key)
pfree(ssl_options->pxf_ssl_key);

if (ssl_options->pxf_ssl_keypasswd)
pfree(ssl_options->pxf_ssl_keypasswd);

pfree(ssl_options);
}

static void
PxfBridgeAbortCallback(ResourceReleasePhase phase,
bool isCommit,
Expand Down Expand Up @@ -84,7 +130,7 @@ PxfBridgeCancel(PxfFdwCancelState *pxfcstate)

initStringInfo(&pxfcstate->uri);
BuildUriForCancel(pxfcstate);
churl_handle = churl_init_upload_timeout(pxfcstate->uri.data, pxfcstate->churl_headers, 1L);
churl_handle = churl_init_upload_timeout(pxfcstate->uri.data, pxfcstate->churl_headers, pxfcstate->ssl_options, 1L);

churl_cleanup(churl_handle, false);
}
Expand Down Expand Up @@ -112,9 +158,16 @@ PxfBridgeCancelCleanup(PxfFdwCancelState *pxfcstate)
if (IsAbortInProgress())
PxfBridgeCancel(pxfcstate);

if (pxfcstate->pxf_protocol)
pfree(pxfcstate->pxf_protocol);

if (pxfcstate->pxf_host)
pfree(pxfcstate->pxf_host);

if (pxfcstate->ssl_options) {
free_churl_ssl_options(pxfcstate->ssl_options);
}

pfree(pxfcstate);
}

Expand Down Expand Up @@ -181,6 +234,7 @@ PxfBridgeImportStart(PxfFdwScanState *pxfsstate)
{
MemoryContext oldcontext;
PxfFdwCancelState *pxfcstate;
churl_ssl_options *ssl_options = NULL;

pxfsstate->churl_headers = churl_headers_init();

Expand All @@ -192,11 +246,23 @@ PxfBridgeImportStart(PxfFdwScanState *pxfsstate)
pxfsstate->retrieved_attrs,
pxfsstate->projectionInfo);

pxfsstate->churl_handle = churl_init_download(pxfsstate->uri.data, pxfsstate->churl_headers);
if (strcmp("https", pxfsstate->options->pxf_protocol) == 0) {
ssl_options = churl_make_ssl_options(pxfsstate->options);
}

pxfsstate->churl_handle = churl_init_download(pxfsstate->uri.data, pxfsstate->churl_headers, ssl_options);
if (ssl_options != NULL) {
free_churl_ssl_options(ssl_options);
}

oldcontext = MemoryContextSwitchTo(CurTransactionContext);
pxfcstate = palloc0(sizeof(PxfFdwCancelState));
pxfcstate->pxf_protocol = pstrdup(pxfsstate->options->pxf_protocol);
pxfcstate->pxf_host = pstrdup(pxfsstate->options->pxf_host);
if (ssl_options != 0) {
/* make another copy for transaction context */
pxfcstate->ssl_options = churl_make_ssl_options(pxfsstate->options);
}
MemoryContextSwitchTo(oldcontext);
pxfsstate->pxfcstate = pxfcstate;
pxfcstate->churl_headers = pxfsstate->churl_headers;
Expand All @@ -223,7 +289,7 @@ PxfBridgeExportStart(PxfFdwModifyState *pxfmstate)
NULL,
NULL,
NULL);
pxfmstate->churl_handle = churl_init_upload(pxfmstate->uri.data, pxfmstate->churl_headers);
pxfmstate->churl_handle = churl_init_upload(pxfmstate->uri.data, pxfmstate->churl_headers, pxfmstate->ssl_options);
}

/*
Expand Down Expand Up @@ -280,8 +346,11 @@ PxfBridgeWrite(PxfFdwModifyState *pxfmstate, char *databuf, int datalen)
static void
BuildUriForCancel(PxfFdwCancelState *pxfcstate)
{
const char *proto = strcmp("https", pxfcstate->pxf_protocol) == 0 ? "https" : "http";

resetStringInfo(&pxfcstate->uri);
appendStringInfo(&pxfcstate->uri, "http://%s:%d/%s/cancel", pxfcstate->pxf_host, pxfcstate->pxf_port, PXF_SERVICE_PREFIX);
appendStringInfo(&pxfcstate->uri, "%s://%s:%d/%s/cancel",
proto, pxfcstate->pxf_host, pxfcstate->pxf_port, PXF_SERVICE_PREFIX);
elog(DEBUG2, "pxf_fdw: uri %s for cancel", pxfcstate->uri.data);
}

Expand All @@ -292,9 +361,11 @@ static void
BuildUriForRead(PxfFdwScanState *pxfsstate)
{
PxfOptions *options = pxfsstate->options;
const char *proto = strcmp("https", options->pxf_protocol) == 0 ? "https" : "http";

resetStringInfo(&pxfsstate->uri);
appendStringInfo(&pxfsstate->uri, "http://%s:%d/%s/read", options->pxf_host, options->pxf_port, PXF_SERVICE_PREFIX);
appendStringInfo(&pxfsstate->uri, "%s://%s:%d/%s/read",
proto, options->pxf_host, options->pxf_port, PXF_SERVICE_PREFIX);
elog(DEBUG2, "pxf_fdw: uri %s for read", pxfsstate->uri.data);
}

Expand All @@ -305,9 +376,11 @@ static void
BuildUriForWrite(PxfFdwModifyState *pxfmstate)
{
PxfOptions *options = pxfmstate->options;
const char *proto = strcmp("https", options->pxf_protocol) == 0 ? "https" : "http";

resetStringInfo(&pxfmstate->uri);
appendStringInfo(&pxfmstate->uri, "http://%s:%d/%s/write", options->pxf_host, options->pxf_port, PXF_SERVICE_PREFIX);
appendStringInfo(&pxfmstate->uri, "%s://%s:%d/%s/write",
proto, options->pxf_host, options->pxf_port, PXF_SERVICE_PREFIX);
elog(DEBUG2, "pxf_fdw: uri %s with file name for write: %s", pxfmstate->uri.data, options->resource);
}

Expand Down
1 change: 1 addition & 0 deletions fdw/pxf_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ typedef struct PxfFdwModifyState

CHURL_HANDLE churl_handle; /* curl handle */
CHURL_HEADERS churl_headers; /* curl headers */
churl_ssl_options *ssl_options; /* NULL if SSL not used */
StringInfoData uri; /* rest endpoint URI for modify */
Relation relation;
PxfOptions *options; /* FDW options */
Expand Down
18 changes: 18 additions & 0 deletions fdw/pxf_option.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
#define FDW_OPTION_PXF_HOST "pxf_host"
#define FDW_OPTION_PXF_PORT "pxf_port"
#define FDW_OPTION_PXF_PROTOCOL "pxf_protocol"
#define FDW_OPTION_SSL_CACERT "pxf_ssl_cacert"
#define FDW_OPTION_SSL_CERT "pxf_ssl_cert"
#define FDW_OPTION_SSL_CERT_TYPE "pxf_ssl_cert_type"
#define FDW_OPTION_SSL_KEY "pxf_ssl_key"
#define FDW_OPTION_SSL_KEYPASSWD "pxf_ssl_keypasswd"
#define FDW_OPTION_SSL_VERIFY_PEER "pxf_ssl_verify_peer"
#define FDW_OPTION_REJECT_LIMIT "reject_limit"
#define FDW_OPTION_REJECT_LIMIT_TYPE "reject_limit_type"
#define FDW_OPTION_RESOURCE "resource"
Expand Down Expand Up @@ -446,6 +452,18 @@ PxfGetOptions(Oid foreigntableid)
opt->pxf_port = atoi(defGetString(def));
else if (strcmp(def->defname, FDW_OPTION_PXF_PROTOCOL) == 0)
opt->pxf_protocol = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_CACERT) == 0)
opt->pxf_ssl_cacert = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_CERT) == 0)
opt->pxf_ssl_cert = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_CERT_TYPE) == 0)
opt->pxf_ssl_cert_type = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_KEY) == 0)
opt->pxf_ssl_key = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_KEYPASSWD) == 0)
opt->pxf_ssl_keypasswd = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_SSL_VERIFY_PEER) == 0)
opt->pxf_ssl_verify_peer = atol(defGetString(def));
else if (strcmp(def->defname, FDW_OPTION_PROTOCOL) == 0)
opt->protocol = defGetString(def);
else if (strcmp(def->defname, FDW_OPTION_RESOURCE) == 0)
Expand Down
8 changes: 8 additions & 0 deletions fdw/pxf_option.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ typedef struct PxfOptions
char *pxf_protocol; /* protocol for the PXF Service (i.e HTTP or
* HTTPS) */

/* SSL options, used when protocol is HTTPS */
const char *pxf_ssl_cacert;
const char *pxf_ssl_cert;
const char *pxf_ssl_cert_type;
const char *pxf_ssl_key;
const char *pxf_ssl_keypasswd;
long pxf_ssl_verify_peer;

/* Server doesn't come from options, it is the actual SERVER name */
char *server; /* the name of the external server */

Expand Down