From 02772eb5f28b3c3a98f0d739b6210ca82d58f7ee Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Thu, 8 Feb 2018 18:13:13 -0700 Subject: [PATCH] omelasticsearch - add support for CA cert, client cert auth This allows omelasticsearch to perform client cert based authentication to Elasticsearch. Add the following parameters: `tls.cacert` - Full path and filename of the file containing the CA cert for the CA that issued the Elasticsearch server(s) cert(s) `tls.mycert` - Full path and filename of the file containing the client cert used to authenticate to Elasticsearch `tls.myprivkey` - Full path and filename of the file containing the client key used to authenticate to Elasticsearch --- plugins/omelasticsearch/omelasticsearch.c | 79 ++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/plugins/omelasticsearch/omelasticsearch.c b/plugins/omelasticsearch/omelasticsearch.c index 97d8fb233..88bd5e16c 100644 --- a/plugins/omelasticsearch/omelasticsearch.c +++ b/plugins/omelasticsearch/omelasticsearch.c @@ -110,6 +110,9 @@ typedef struct _instanceData { size_t maxbytes; sbool useHttps; sbool allowUnsignedCerts; + uchar *caCertFile; + uchar *myCertFile; + uchar *myPrivKeyFile; } instanceData; typedef struct wrkrInstanceData { @@ -154,7 +157,10 @@ static struct cnfparamdescr actpdescr[] = { { "template", eCmdHdlrGetWord, 0 }, { "dynbulkid", eCmdHdlrBinary, 0 }, { "bulkid", eCmdHdlrGetWord, 0 }, - { "allowunsignedcerts", eCmdHdlrBinary, 0 } + { "allowunsignedcerts", eCmdHdlrBinary, 0 }, + { "tls.cacert", eCmdHdlrString, 0 }, + { "tls.mycert", eCmdHdlrString, 0 }, + { "tls.myprivkey", eCmdHdlrString, 0 } }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, @@ -168,6 +174,9 @@ BEGINcreateInstance CODESTARTcreateInstance pData->fdErrFile = -1; pthread_mutex_init(&pData->mutErrFile, NULL); + pData->caCertFile = NULL; + pData->myCertFile = NULL; + pData->myPrivKeyFile = NULL; ENDcreateInstance BEGINcreateWrkrInstance @@ -216,6 +225,9 @@ CODESTARTfreeInstance free(pData->timeout); free(pData->errorFile); free(pData->bulkId); + free(pData->caCertFile); + free(pData->myCertFile); + free(pData->myPrivKeyFile); ENDfreeInstance BEGINfreeWrkrInstance @@ -270,6 +282,9 @@ CODESTARTdbgPrintInstInfo dbgprintf("\tinterleaved=%d\n", pData->interleaved); dbgprintf("\tdynbulkid=%d\n", pData->dynBulkId); dbgprintf("\tbulkid='%s'\n", pData->bulkId); + dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile); + dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile); + dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile); ENDdbgPrintInstInfo @@ -311,7 +326,7 @@ computeBaseUrl(const char*const serverParam, r = useHttps ? es_addBuf(&urlBuf, SCHEME_HTTPS, sizeof(SCHEME_HTTPS)-1) : es_addBuf(&urlBuf, SCHEME_HTTP, sizeof(SCHEME_HTTP)-1); - if (r == 0) r = es_addBuf(&urlBuf, serverParam, strlen(serverParam)); + if (r == 0) r = es_addBuf(&urlBuf, (char *)serverParam, strlen(serverParam)); if (r == 0 && !strchr(host, ':')) { snprintf(portBuf, sizeof(portBuf), ":%d", defaultPort); r = es_addBuf(&urlBuf, portBuf, strlen(portBuf)); @@ -1296,7 +1311,7 @@ finalize_it: } static void -curlCheckConnSetup(CURL *handle, HEADER *header, long timeout, sbool allowUnsignedCerts) +curlCheckConnSetup(CURL *handle, HEADER *header, long timeout, sbool allowUnsignedCerts, wrkrInstanceData_t *pWrkrData) { curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); curl_easy_setopt(handle, CURLOPT_NOBODY, TRUE); @@ -1305,13 +1320,21 @@ curlCheckConnSetup(CURL *handle, HEADER *header, long timeout, sbool allowUnsign if(allowUnsignedCerts) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE); + if(pWrkrData->pData->caCertFile) + curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); + if(pWrkrData->pData->myCertFile) + curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); + if(pWrkrData->pData->myPrivKeyFile) + curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); + /* uncomment for in-dept debuggung: + curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */ /* Only enable for debugging curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); */ } static void -curlPostSetup(CURL *handle, HEADER *header, uchar* authBuf) +curlPostSetup(CURL *handle, HEADER *header, uchar* authBuf, wrkrInstanceData_t *pWrkrData) { curl_easy_setopt(handle, CURLOPT_HTTPHEADER, header); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); @@ -1322,6 +1345,12 @@ curlPostSetup(CURL *handle, HEADER *header, uchar* authBuf) curl_easy_setopt(handle, CURLOPT_USERPWD, authBuf); curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); } + if(pWrkrData->pData->caCertFile) + curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); + if(pWrkrData->pData->myCertFile) + curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); + if(pWrkrData->pData->myPrivKeyFile) + curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); } static rsRetVal @@ -1332,7 +1361,7 @@ curlSetup(wrkrInstanceData_t *pWrkrData, instanceData *pData) if (pWrkrData->curlPostHandle == NULL) { return RS_RET_OBJ_CREATION_FAILED; } - curlPostSetup(pWrkrData->curlPostHandle, pWrkrData->curlHeader, pData->authBuf); + curlPostSetup(pWrkrData->curlPostHandle, pWrkrData->curlHeader, pData->authBuf, pWrkrData); pWrkrData->curlCheckConnHandle = curl_easy_init(); if (pWrkrData->curlCheckConnHandle == NULL) { @@ -1341,7 +1370,7 @@ curlSetup(wrkrInstanceData_t *pWrkrData, instanceData *pData) return RS_RET_OBJ_CREATION_FAILED; } curlCheckConnSetup(pWrkrData->curlCheckConnHandle, pWrkrData->curlHeader, - pData->healthCheckTimeout, pData->allowUnsignedCerts); + pData->healthCheckTimeout, pData->allowUnsignedCerts, pWrkrData); return RS_RET_OK; } @@ -1372,6 +1401,9 @@ setInstParamDefaults(instanceData *pData) pData->interleaved=0; pData->dynBulkId= 0; pData->bulkId = NULL; + pData->caCertFile = NULL; + pData->myCertFile = NULL; + pData->myPrivKeyFile = NULL; } BEGINnewActInst @@ -1380,6 +1412,8 @@ BEGINnewActInst struct cnfarray* servers = NULL; int i; int iNumTpls; + FILE *fp; + char errStr[1024]; CODESTARTnewActInst if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); @@ -1435,6 +1469,39 @@ CODESTARTnewActInst pData->dynBulkId = pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "bulkid")) { pData->bulkId = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) { + pData->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + fp = fopen((const char*)pData->caCertFile, "r"); + if(fp == NULL) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, + "error: 'tls.cacert' file %s couldn't be accessed: %s\n", + pData->caCertFile, errStr); + } else { + fclose(fp); + } + } else if(!strcmp(actpblk.descr[i].name, "tls.mycert")) { + pData->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + fp = fopen((const char*)pData->myCertFile, "r"); + if(fp == NULL) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, + "error: 'tls.mycert' file %s couldn't be accessed: %s\n", + pData->myCertFile, errStr); + } else { + fclose(fp); + } + } else if(!strcmp(actpblk.descr[i].name, "tls.myprivkey")) { + pData->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + fp = fopen((const char*)pData->myPrivKeyFile, "r"); + if(fp == NULL) { + rs_strerror_r(errno, errStr, sizeof(errStr)); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, + "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n", + pData->myPrivKeyFile, errStr); + } else { + fclose(fp); + } } else { dbgprintf("omelasticsearch: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); -- 2.14.3