From 756087c2ba1d0fe220c5cc031be59b73d7ebff2e Mon Sep 17 00:00:00 2001 From: Jonathan Lima Date: Mon, 14 Sep 2015 20:51:39 -0300 Subject: [PATCH] Add authentication support through user mappings. --- mongo_fdw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- mongo_fdw.h | 13 +++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/mongo_fdw.c b/mongo_fdw.c index daa5438..4a474f1 100644 --- a/mongo_fdw.c +++ b/mongo_fdw.c @@ -13,6 +13,7 @@ #include "postgres.h" #include "mongo_fdw.h" +#include "miscadmin.h" #include "access/reloptions.h" #include "catalog/pg_type.h" #include "commands/defrem.h" @@ -391,6 +392,7 @@ MongoBeginForeignScan(ForeignScanState *scanState, int executorFlags) mongo *mongoConnection = NULL; mongo_cursor *mongoCursor = NULL; int32 connectStatus = MONGO_ERROR; + int32 authStatus = MONGO_ERROR; Oid foreignTableId = InvalidOid; List *columnList = NIL; HTAB *columnMappingHash = NULL; @@ -433,6 +435,26 @@ MongoBeginForeignScan(ForeignScanState *scanState, int executorFlags) errhint("Mongo driver connection error: %d", errorCode))); } + if (mongoFdwOptions->username) + { + authStatus = mongo_cmd_authenticate(mongoConnection, mongoFdwOptions->databaseName, mongoFdwOptions->username, mongoFdwOptions->password); + } + else + { + authStatus = MONGO_OK; + } + + if (authStatus != MONGO_OK) + { + errorCode = (int32) mongoConnection->err; + + mongo_destroy(mongoConnection); + mongo_dispose(mongoConnection); + + ereport(ERROR, (errmsg("could not authenticate mongo to %s:%d", addressName, portNumber), + errhint("Mongo driver connection error: %d", errorCode))); + } + /* deserialize query document; and create column info hash */ foreignScan = (ForeignScan *) scanState->ss.ps.plan; foreignPrivateList = foreignScan->fdw_private; @@ -653,8 +675,20 @@ ForeignTableDocumentCount(Oid foreignTableId) status = mongo_connect(mongoConnection, options->addressName, options->portNumber); if (status == MONGO_OK) { - documentCount = mongo_count(mongoConnection, options->databaseName, - options->collectionName, emptyQuery); + if (options->username) + { + status = mongo_cmd_authenticate(mongoConnection, options->databaseName, options->username, options->password); + } + + if (status == MONGO_OK) + { + documentCount = mongo_count(mongoConnection, options->databaseName, + options->collectionName, emptyQuery); + } + else + { + documentCount = -1.0; + } } else { @@ -682,6 +716,8 @@ MongoGetOptions(Oid foreignTableId) int32 portNumber = 0; char *databaseName = NULL; char *collectionName = NULL; + char *username = NULL; + char *password = NULL; addressName = MongoGetOptionValue(foreignTableId, OPTION_NAME_ADDRESS); if (addressName == NULL) @@ -711,11 +747,16 @@ MongoGetOptions(Oid foreignTableId) collectionName = get_rel_name(foreignTableId); } + username = MongoGetOptionValue(foreignTableId, OPTION_NAME_USERNAME); + password = MongoGetOptionValue(foreignTableId, OPTION_NAME_PASSWORD); + mongoFdwOptions = (MongoFdwOptions *) palloc0(sizeof(MongoFdwOptions)); mongoFdwOptions->addressName = addressName; mongoFdwOptions->portNumber = portNumber; mongoFdwOptions->databaseName = databaseName; mongoFdwOptions->collectionName = collectionName; + mongoFdwOptions->username = username; + mongoFdwOptions->password = password; return mongoFdwOptions; } @@ -731,16 +772,23 @@ MongoGetOptionValue(Oid foreignTableId, const char *optionName) { ForeignTable *foreignTable = NULL; ForeignServer *foreignServer = NULL; + UserMapping *userMapping = NULL; List *optionList = NIL; ListCell *optionCell = NULL; char *optionValue = NULL; foreignTable = GetForeignTable(foreignTableId); foreignServer = GetForeignServer(foreignTable->serverid); + userMapping = GetUserMapping(GetUserId(), foreignServer->serverid); optionList = list_concat(optionList, foreignTable->options); optionList = list_concat(optionList, foreignServer->options); + if (userMapping) + { + optionList = list_concat(optionList, userMapping->options); + } + foreach(optionCell, optionList) { DefElem *optionDef = (DefElem *) lfirst(optionCell); diff --git a/mongo_fdw.h b/mongo_fdw.h index 60947a2..f0721d8 100644 --- a/mongo_fdw.h +++ b/mongo_fdw.h @@ -18,6 +18,7 @@ #include "fmgr.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_foreign_table.h" +#include "catalog/pg_user_mapping.h" #include "utils/datetime.h" #include "nodes/pg_list.h" #include "nodes/relation.h" @@ -29,6 +30,8 @@ #define OPTION_NAME_PORT "port" #define OPTION_NAME_DATABASE "database" #define OPTION_NAME_COLLECTION "collection" +#define OPTION_NAME_USERNAME "username" +#define OPTION_NAME_PASSWORD "password" /* Default values for option parameters */ #define DEFAULT_IP_ADDRESS "127.0.0.1" @@ -58,7 +61,7 @@ typedef struct MongoValidOption /* Array of options that are valid for mongo_fdw */ -static const uint32 ValidOptionCount = 4; +static const uint32 ValidOptionCount = 6; static const MongoValidOption ValidOptionArray[] = { /* foreign server options */ @@ -67,7 +70,11 @@ static const MongoValidOption ValidOptionArray[] = /* foreign table options */ { OPTION_NAME_DATABASE, ForeignTableRelationId }, - { OPTION_NAME_COLLECTION, ForeignTableRelationId } + { OPTION_NAME_COLLECTION, ForeignTableRelationId }, + + /* user mapping options */ + { OPTION_NAME_USERNAME, UserMappingRelationId }, + { OPTION_NAME_PASSWORD, UserMappingRelationId } }; @@ -82,6 +89,8 @@ typedef struct MongoFdwOptions int32 portNumber; char *databaseName; char *collectionName; + char *username; + char *password; } MongoFdwOptions;