Skip to content

Commit

Permalink
updated curl lib and iam_role_auth to use IMDSv2
Browse files Browse the repository at this point in the history
  • Loading branch information
jpswinski committed Dec 12, 2023
1 parent 615eefd commit 0f8039d
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 152 deletions.
212 changes: 120 additions & 92 deletions packages/netsvc/CurlLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,25 @@ void CurlLib::deinit (void)
}

/*----------------------------------------------------------------------------
* get
* request
*----------------------------------------------------------------------------*/
long CurlLib::get (const char* url, const char* data, const char** response, int* size, bool verify_peer, bool verify_hostname)
long CurlLib::request (EndpointObject::verb_t verb, const char* url, const char* data, const char** response, int* size, bool verify_peer, bool verify_hostname, vector<const char*>* headers)
{
long http_code = 0;
CURL* curl = NULL;

/* Initialize Request */
data_t rqst;
rqst.data = (char*)data;
rqst.size = StringLib::size(data);
if(data)
{
rqst.data = (char*)data;
rqst.size = StringLib::size(data);
}
else
{
rqst.data = NULL;
rqst.size = 0;
}

/* Initialize Response */
List<data_t> rsps_set(EXPECTED_RESPONSE_SEGMENTS);
Expand All @@ -91,99 +99,39 @@ long CurlLib::get (const char* url, const char* data, const char** response, int
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ".cookies");
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, ".cookies");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
if(rqst.size > 0)

if(verb == EndpointObject::GET && rqst.size > 0)
{
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, rqst.data);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)rqst.size);
}

/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
if(!verify_peer)
else if(verb == EndpointObject::POST)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, CurlLib::readData);
curl_easy_setopt(curl, CURLOPT_READDATA, &rqst);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)rqst.size);
}

/*
* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
if(!verify_hostname)
else if(verb == EndpointObject::PUT)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, CurlLib::readData);
curl_easy_setopt(curl, CURLOPT_READDATA, &rqst);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)rqst.size);
}

/* Perform the request, res will get the return code */
CURLcode res = curl_easy_perform(curl);

/* Check for Success */
if(res == CURLE_OK)
{
/* Get HTTP Code */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);

/* Get Response */
CurlLib::combineResponse(&rsps_set, response, size);
}
else
/* Add Headers */
struct curl_slist* hdr_slist = NULL;
if(headers && headers->size() > 0)
{
/* Unable to Perform cURL Call */
FString error_msg("%s", curl_easy_strerror(res));
*response = error_msg.c_str(true);
http_code = EndpointObject::Service_Unavailable;
for(const char* hdr: *headers)
{
hdr_slist = curl_slist_append(hdr_slist, hdr);
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hdr_slist);
}

/* Always Cleanup */
curl_easy_cleanup(curl);
}

/* Return HTTP Code */
return http_code;
}

/*----------------------------------------------------------------------------
* post
*----------------------------------------------------------------------------*/
long CurlLib::post (const char* url, const char* data, const char** response, int* size, bool verify_peer, bool verify_hostname)
{
long http_code = 0;
CURL* curl = NULL;

/* Initialize Request */
data_t rqst;
rqst.data = (char*)data;
rqst.size = StringLib::size(data);

/* Initialize Response */
List<data_t> rsps_set;
if(response) *response = NULL;
if(size) *size = 0;

/* Initialize cURL */
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, CONNECTION_TIMEOUT); // seconds
curl_easy_setopt(curl, CURLOPT_TIMEOUT, DATA_TIMEOUT); // seconds
curl_easy_setopt(curl, CURLOPT_READFUNCTION, CurlLib::readData);
curl_easy_setopt(curl, CURLOPT_READDATA, &rqst);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)rqst.size);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlLib::writeData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &rsps_set);

/*
* If you want to connect to a site who isn't using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
Expand Down Expand Up @@ -225,12 +173,14 @@ long CurlLib::post (const char* url, const char* data, const char** response, in
else
{
/* Unable to Perform cURL Call */
mlog(ERROR, "Unable to perform cRUL call on %s: %s", url, curl_easy_strerror(res));
FString error_msg("%s", curl_easy_strerror(res));
if(response) *response = error_msg.c_str(true);
http_code = EndpointObject::Service_Unavailable;
}

/* Always Cleanup */
curl_easy_cleanup(curl);
curl_slist_free_all(hdr_slist);
}

/* Return HTTP Code */
Expand Down Expand Up @@ -375,25 +325,101 @@ long CurlLib::postAsRecord (const char* url, const char* data, Publisher* outq,
return http_code;
}

/*----------------------------------------------------------------------------
* getHeaders
*----------------------------------------------------------------------------*/
int CurlLib::getHeaders (lua_State* L, int index, vector<const char*>& header_list)
{
int num_hdrs = 0;

/* Must be table of strings */
if((lua_gettop(L) >= index) && lua_istable(L, index))
{
/* Iterate through each item in table */
int num_strings = lua_rawlen(L, index);
for(int i = 0; i < num_strings; i++)
{
/* Get item */
lua_rawgeti(L, index, i+1);
if(lua_isstring(L, -1))
{
const char* header = StringLib::duplicate(LuaObject::getLuaString(L, -1));
header_list.push_back(header);
num_hdrs++;
}

/* Clean up stack */
lua_pop(L, 1);
}
}

return num_hdrs;
}

/*----------------------------------------------------------------------------
* luaGet
*----------------------------------------------------------------------------*/
int CurlLib::luaGet (lua_State* L)
{
bool status = false;
vector<const char*> header_list;

try
{
/* Get Parameters */
const char* url = LuaObject::getLuaString(L, 1);
bool verify_peer = LuaObject::getLuaBoolean(L, 2, true, false);
bool verify_hostname = LuaObject::getLuaBoolean(L, 3, true, false);
const char* data = LuaObject::getLuaString(L, 4, true, "");
const char* data = LuaObject::getLuaString(L, 2, true, NULL);
int num_hdrs = CurlLib::getHeaders(L, 3, header_list); (void)num_hdrs;
bool verify_peer = LuaObject::getLuaBoolean(L, 4, true, false);
bool verify_hostname = LuaObject::getLuaBoolean(L, 5, true, false);

/* Perform Request */
const char* response = NULL;
int size = 0;
long http_code = CurlLib::get(url, data, &response, &size, verify_peer, verify_hostname);
long http_code = CurlLib::request(EndpointObject::GET, url, data, &response, &size, verify_peer, verify_hostname, &header_list);
if(response)
{
status = (http_code >= 200 && http_code < 300);
lua_pushlstring(L, response, size);
delete [] response;
}
else
{
lua_pushnil(L);
}
}
catch(const RunTimeException& e)
{
mlog(e.level(), "Error performing netsvc GET: %s", e.what());
lua_pushnil(L);
}

/* Return Status */
lua_pushboolean(L, status);
return 2;
}

/*----------------------------------------------------------------------------
* luaPut
*----------------------------------------------------------------------------*/
int CurlLib::luaPut (lua_State* L)
{
bool status = false;
vector<const char*> header_list;

try
{
/* Get Parameters */
const char* url = LuaObject::getLuaString(L, 1);
const char* data = LuaObject::getLuaString(L, 2, true, NULL);
int num_hdrs = CurlLib::getHeaders(L, 3, header_list); (void)num_hdrs;
bool verify_peer = LuaObject::getLuaBoolean(L, 4, true, false);
bool verify_hostname = LuaObject::getLuaBoolean(L, 5, true, false);

/* Perform Request */
const char* response = NULL;
int size = 0;
long http_code = CurlLib::request(EndpointObject::PUT, url, data, &response, &size, verify_peer, verify_hostname, &header_list);
if(response)
{
status = (http_code >= 200 && http_code < 300);
Expand Down Expand Up @@ -422,17 +448,19 @@ int CurlLib::luaGet (lua_State* L)
int CurlLib::luaPost (lua_State* L)
{
bool status = false;
vector<const char*> header_list;

try
{
/* Get Parameters */
const char* url = LuaObject::getLuaString(L, 1);
const char* data = LuaObject::getLuaString(L, 2, true, "{}");
const char* url = LuaObject::getLuaString(L, 1);
const char* data = LuaObject::getLuaString(L, 2, true, "{}");
int num_hdrs = CurlLib::getHeaders(L, 3, header_list); (void)num_hdrs;

/* Perform Request */
const char* response = NULL;
int size = 0;
long http_code = CurlLib::post(url, data, &response, &size);
long http_code = CurlLib::request(EndpointObject::POST, url, data, &response, &size, false, false, &header_list);
if(response)
{
status = (http_code >= 200 && http_code < 300);
Expand Down
13 changes: 10 additions & 3 deletions packages/netsvc/CurlLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
* INCLUDES
******************************************************************************/

#include "core.h"
#include "LuaObject.h"
#include "EndpointObject.h"
#include "OsApi.h"
#include "MsgQ.h"

/******************************************************************************
* cURL LIBRARY CLASS
Expand All @@ -53,11 +56,15 @@ class CurlLib
static void init (void);
static void deinit (void);

static long get (const char* url, const char* data, const char** response, int* size=NULL, bool verify_peer=false, bool verify_hostname=false);
static long post (const char* url, const char* data, const char** response, int* size=NULL, bool verify_peer=false, bool verify_hostname=false);
static long request (EndpointObject::verb_t verb, const char* url, const char* data, const char** response, int* size, bool verify_peer=false, bool verify_hostname=false, vector<const char*>* headers=NULL);
static long get (const char* url, const char* data, const char** response, int* size, bool verify_peer=false, bool verify_hostname=false);
static long put (const char* url, const char* data, const char** response, int* size, bool verify_peer=false, bool verify_hostname=false);
static long post (const char* url, const char* data, const char** response, int* size, bool verify_peer=false, bool verify_hostname=false);
static long postAsStream (const char* url, const char* data, Publisher* outq, bool with_terminator);
static long postAsRecord (const char* url, const char* data, Publisher* outq, bool with_terminator, int timeout, bool* active=NULL);
static int getHeaders (lua_State* L, int index, vector<const char*>& header_list);
static int luaGet (lua_State* L);
static int luaPut (lua_State* L);
static int luaPost (lua_State* L);

private:
Expand Down
23 changes: 3 additions & 20 deletions packages/netsvc/OrchestratorLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,10 @@ void OrchestratorLib::deinit (void)
*----------------------------------------------------------------------------*/
OrchestratorLib::rsps_t OrchestratorLib::request (EndpointObject::verb_t verb, const char* resource, const char* data)
{
rsps_t rsps;
FString path("%s%s", URL, resource);
if(verb == EndpointObject::GET)
{
rsps_t rsps;
rsps.code = CurlLib::get(path.c_str(), data, &rsps.response, &rsps.size);
return rsps;
}

if(verb == EndpointObject::POST)
{
rsps_t rsps;
rsps.code = CurlLib::post(path.c_str(), data, &rsps.response, &rsps.size);
return rsps;
}

rsps_t err_rsps = {
.code = static_cast<long>(EndpointObject::Bad_Request),
.response = NULL,
.size = 0
};
return err_rsps;
rsps.code = CurlLib::request(verb, path.c_str(), data, &rsps.response, &rsps.size);
return rsps;
}

/*----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions packages/netsvc/netsvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ int netsvc_open (lua_State* L)
{
static const struct luaL_Reg netsvc_functions[] = {
{"get", CurlLib::luaGet},
{"put", CurlLib::luaPut},
{"post", CurlLib::luaPost},
{"proxy", EndpointProxy::luaCreate},
{"orchurl", OrchestratorLib::luaUrl},
Expand Down

0 comments on commit 0f8039d

Please sign in to comment.