Status AuthzManagerExternalStateMongod::_getUserDocument(
                OperationContext* txn, const UserName& userName, BSONObj* userDoc) {

        Client::ReadContext ctx(txn, "admin");

        int authzVersion;
        Status status = getStoredAuthorizationVersion(txn, &authzVersion);
        if (!status.isOK())
            return status;

        switch (authzVersion) {
        case AuthorizationManager::schemaVersion26Upgrade:
        case AuthorizationManager::schemaVersion26Final:
            break;
        default:
            return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() <<
                          "Unsupported schema version for getUserDescription(): " <<
                          authzVersion);
        }

        status = findOne(
                txn,
                (authzVersion == AuthorizationManager::schemaVersion26Final ?
                 AuthorizationManager::usersCollectionNamespace :
                 AuthorizationManager::usersAltCollectionNamespace),
                BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
                     AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
                userDoc);
        if (status == ErrorCodes::NoMatchingDocument) {
            status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() <<
                            "Could not find user " << userName.getFullName());
        }
        return status;
    }
Пример #2
0
 /* fetch a single object from collection ns that matches query
    set your db SavedContext first
 */
 bool Helpers::findOne(const char *ns, const BSONObj &query, BSONObj& result, bool requireIndex) {
     DiskLoc loc = findOne( ns, query, requireIndex );
     if ( loc.isNull() )
         return false;
     result = loc.obj();
     return true;
 }
        void run() {
            const int expected = 100;

            drop();
            addInserts(100);
            applyOplog();

            ASSERT_EQUALS(expected, static_cast<int>(client()->count(ns())));

            drop();
            addVersionedInserts(100);
            applyOplog();

            ASSERT_EQUALS(expected, static_cast<int>(client()->count(ns())));

            drop();
            addUpdates();
            applyOplog();

            BSONObj obj = findOne();

            ASSERT_EQUALS(1334813340, obj["requests"]["1000001_2"]["timestamp"].number());
            ASSERT_EQUALS(1334813368, obj["requests"]["1000002_2"]["timestamp"].number());
            ASSERT_EQUALS(1334810820, obj["requests"]["100002_1"]["timestamp"].number());

            drop();
        }
Пример #4
0
        void run() {
            const int expected = 100;

            drop();
            addInserts(100);
            applyOplog();

            ASSERT_EQUALS(expected, static_cast<int>(client()->count(ns())));

            drop();
            addVersionedInserts(100);
            applyOplog();

            ASSERT_EQUALS(expected, static_cast<int>(client()->count(ns())));

            drop();
            addUpdates();
            applyOplog();

            BSONObj obj = findOne();

            ASSERT_EQUALS(1334813340, obj["requests"]["1000001_2"]["timestamp"].number());
            ASSERT_EQUALS(1334813368, obj["requests"]["1000002_2"]["timestamp"].number());
            ASSERT_EQUALS(1334810820, obj["requests"]["100002_1"]["timestamp"].number());

            drop();
            
            // test converting updates to upserts but only for version 2.2.1 and greater,
            // which means oplog version 2 and greater.
            addConflictingUpdates();
            applyOplog();

            drop();

        }
Пример #5
0
    Status AuthzManagerExternalState::getPrivilegeDocumentV1(const StringData& dbname,
                                                             const UserName& userName,
                                                             BSONObj* result) {
        if (userName == internalSecurity.user->getName()) {
            return Status(ErrorCodes::InternalError,
                          "Requested privilege document for the internal user");
        }

        if (!NamespaceString::validDBName(dbname)) {
            return Status(ErrorCodes::BadValue,
                          mongoutils::str::stream() << "Bad database name \"" << dbname << "\"");
        }

        const bool isUserFromTargetDB = (dbname == userName.getDB());

        // Build the query needed to get the privilege document

        BSONObjBuilder queryBuilder;
        const NamespaceString usersNamespace(dbname, "system.users");
        queryBuilder.append(AuthorizationManager::V1_USER_NAME_FIELD_NAME, userName.getUser());
        if (isUserFromTargetDB) {
            queryBuilder.appendNull(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME);
        }
        else {
            queryBuilder.append(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME, userName.getDB());
        }

        // Query for the privilege document
        BSONObj userBSONObj;
        Status found = findOne(usersNamespace, queryBuilder.done(), &userBSONObj);
        if (!found.isOK()) {
            if (found.code() == ErrorCodes::NoMatchingDocument) {
                // Return more detailed status that includes user name.
                return Status(ErrorCodes::UserNotFound,
                              mongoutils::str::stream() << "auth: couldn't find user " <<
                              userName.toString() << ", " << usersNamespace.ns(),
                              0);
            } else {
                return found;
            }
        }

        if (isUserFromTargetDB) {
            if (userBSONObj[AuthorizationManager::PASSWORD_FIELD_NAME].eoo()) {
                return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() <<
                              "User documents with schema version " <<
                              AuthorizationManager::schemaVersion24 <<
                              " must have a \"" <<
                              AuthorizationManager::PASSWORD_FIELD_NAME <<
                              "\" field.");
            }
        }

        *result = userBSONObj.getOwned();
        return Status::OK();
    }
Пример #6
0
 /* fetch a single object from collection ns that matches query
    set your db SavedContext first
 */
 bool Helpers::findOne(Collection* collection, 
                       const BSONObj &query, 
                       BSONObj& result, 
                       bool requireIndex) {
     DiskLoc loc = findOne( collection, query, requireIndex );
     if ( loc.isNull() )
         return false;
     result = collection->docFor(loc);
     return true;
 }
 Status AuthzManagerExternalStateMock::_findUser(
         const std::string& usersNamespace,
         const BSONObj& query,
         BSONObj* result) {
     if (!findOne(NamespaceString(usersNamespace), query, result).isOK()) {
         return Status(ErrorCodes::UserNotFound,
                       "No matching user for query " + query.toString());
     }
     return Status::OK();
 }
Пример #8
0
/* fetch a single object from collection ns that matches query
   set your db SavedContext first
*/
RecordId Helpers::findOne(OperationContext* opCtx,
                          Collection* collection,
                          const BSONObj& query,
                          bool requireIndex) {
    if (!collection)
        return RecordId();

    auto qr = stdx::make_unique<QueryRequest>(collection->ns());
    qr->setFilter(query);
    return findOne(opCtx, collection, std::move(qr), requireIndex);
}
Пример #9
0
 /* fetch a single object from collection ns that matches query
    set your db SavedContext first
 */
 bool Helpers::findOne(OperationContext* txn,
                       Collection* collection, 
                       const BSONObj &query, 
                       BSONObj& result, 
                       bool requireIndex) {
     RecordId loc = findOne( txn, collection, query, requireIndex );
     if ( loc.isNull() )
         return false;
     result = collection->docFor(txn, loc).value();
     return true;
 }
Пример #10
0
QVariantMap TMongoQuery::findById(const QString &id, const QStringList &fields)
{
    QVariantMap criteria;

    if (id.isEmpty()) {
        tSystemError("TMongoQuery::findById : ObjectId not found");
        return QVariantMap();
    }

    criteria[ObjectIdKey] = id;
    return findOne(criteria, fields);
}
Пример #11
0
 bool AuthzManagerExternalState::hasAnyPrivilegeDocuments() {
     BSONObj userBSONObj;
     Status status = findOne(
             AuthorizationManager::usersCollectionNamespace,
             BSONObj(),
             &userBSONObj);
     // If the status is NoMatchingDocument, there are no privilege documents.
     // If it's OK, there are.  Otherwise, we were unable to complete the query,
     // so best to assume that there _are_ privilege documents.  This might happen
     // if the node contaning the users collection becomes transiently unavailable.
     // See SERVER-12616, for example.
     return status != ErrorCodes::NoMatchingDocument;
 }
Пример #12
0
        void run() {
            OpTime o(getNextGlobalOptime());

            BSONObjBuilder b;
            b.appendTimestamp("ts", o.asLL());
            b.append("op", "u");
            b.append("o", BSON("$set" << BSON("x" << 456)));
            b.append("o2", BSON("_id" << 123));
            b.append("ns", ns());
            BSONObj obj = b.obj();
            SyncTest2 sync2;
            std::vector<BSONObj> ops;
            ops.push_back(obj);

            sync2.insertOnRetry = true;
            // succeeds
            multiInitialSyncApply(ops, &sync2);

            BSONObj fin = findOne();
            verify(fin["x"].Number() == 456);

            drop();
        }
Пример #13
0
        void run() {
            writelock lk("");

            OpTime o1 = OpTime::now();
            OpTime o2 = OpTime::now();

            BSONObjBuilder b;
            b.appendTimestamp("ts", o2.asLL());
            b.append("op", "u");
            b.append("o", BSON("$set" << BSON("x" << 456)));
            b.append("o2", BSON("_id" << 123));
            b.append("ns", ns());
            BSONObj obj = b.obj();

            SyncTest2 sync;
            ASSERT_THROWS(sync.applyOp(obj, o1), UserException);

            sync.insertOnRetry = true;
            // succeeds
            sync.applyOp(obj, o1);

            BSONObj fin = findOne();
            assert(fin["x"].Number() == 456);
        }
 Status AuthzManagerExternalStateLocal::getStoredAuthorizationVersion(int* outVersion) {
     BSONObj versionDoc;
     Status status = findOne(AuthorizationManager::versionCollectionNamespace,
                             AuthorizationManager::versionDocumentQuery,
                             &versionDoc);
     if (status.isOK()) {
         BSONElement versionElement = versionDoc[AuthorizationManager::schemaVersionFieldName];
         if (versionElement.isNumber()) {
             *outVersion = versionElement.numberInt();
             return Status::OK();
         }
         else if (versionElement.eoo()) {
             return Status(ErrorCodes::NoSuchKey, mongoutils::str::stream() <<
                           "No " << AuthorizationManager::schemaVersionFieldName <<
                           " field in version document.");
         }
         else {
             return Status(ErrorCodes::TypeMismatch, mongoutils::str::stream() <<
                           "Bad (non-numeric) type " << versionElement.type() <<
                           "for " << AuthorizationManager::schemaVersionFieldName <<
                           " field in version document");
         }
     }
     else if (status == ErrorCodes::NoMatchingDocument) {
         if (hasAnyPrivilegeDocuments()) {
             *outVersion = AuthorizationManager::schemaVersion24;
         }
         else {
             *outVersion = AuthorizationManager::schemaVersion26Final;
         }
         return Status::OK();
     }
     else {
         return status;
     }
 }
Пример #15
0
void OplogReader::connectToSyncSource(OperationContext* txn,
                                      const OpTime& lastOpTimeFetched,
                                      const OpTime& requiredOpTime,
                                      ReplicationCoordinator* replCoord) {
    const Timestamp sentinelTimestamp(duration_cast<Seconds>(Date_t::now().toDurationSinceEpoch()),
                                      0);
    const OpTime sentinel(sentinelTimestamp, std::numeric_limits<long long>::max());
    OpTime oldestOpTimeSeen = sentinel;

    invariant(conn() == NULL);

    while (true) {
        HostAndPort candidate = replCoord->chooseNewSyncSource(lastOpTimeFetched);

        if (candidate.empty()) {
            if (oldestOpTimeSeen == sentinel) {
                // If, in this invocation of connectToSyncSource(), we did not successfully
                // connect to any node ahead of us,
                // we apparently have no sync sources to connect to.
                // This situation is common; e.g. if there are no writes to the primary at
                // the moment.
                return;
            }

            // Connected to at least one member, but in all cases we were too stale to use them
            // as a sync source.
            error() << "too stale to catch up -- entering maintenance mode";
            log() << "our last optime : " << lastOpTimeFetched;
            log() << "oldest available is " << oldestOpTimeSeen;
            log() << "See http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember";
            auto status = replCoord->setMaintenanceMode(true);
            if (!status.isOK()) {
                warning() << "Failed to transition into maintenance mode: " << status;
            }
            bool worked = replCoord->setFollowerMode(MemberState::RS_RECOVERING);
            if (!worked) {
                warning() << "Failed to transition into " << MemberState(MemberState::RS_RECOVERING)
                          << ". Current state: " << replCoord->getMemberState();
            }
            return;
        }

        if (!connect(candidate)) {
            LOG(2) << "can't connect to " << candidate.toString() << " to read operations";
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t::now() + Seconds(10));
            continue;
        }
        // Read the first (oldest) op and confirm that it's not newer than our last
        // fetched op. Otherwise, we have fallen off the back of that source's oplog.
        BSONObj remoteOldestOp(findOne(rsOplogName.c_str(), Query()));
        OpTime remoteOldOpTime =
            fassertStatusOK(28776, OpTime::parseFromOplogEntry(remoteOldestOp));

        // remoteOldOpTime may come from a very old config, so we cannot compare their terms.
        if (!lastOpTimeFetched.isNull() &&
            lastOpTimeFetched.getTimestamp() < remoteOldOpTime.getTimestamp()) {
            // We're too stale to use this sync source.
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t::now() + Minutes(1));
            if (oldestOpTimeSeen.getTimestamp() > remoteOldOpTime.getTimestamp()) {
                warning() << "we are too stale to use " << candidate.toString()
                          << " as a sync source";
                oldestOpTimeSeen = remoteOldOpTime;
            }
            continue;
        }

        // Check if sync source contains required optime.
        if (!requiredOpTime.isNull()) {
            // This query is structured so that it is executed on the sync source using the oplog
            // start hack (oplogReplay=true and $gt/$gte predicate over "ts").
            auto ts = requiredOpTime.getTimestamp();
            tailingQuery(rsOplogName.c_str(), BSON("ts" << BSON("$gte" << ts << "$lte" << ts)));
            auto status = _compareRequiredOpTimeWithQueryResponse(requiredOpTime);
            if (!status.isOK()) {
                const auto blacklistDuration = Seconds(60);
                const auto until = Date_t::now() + blacklistDuration;
                warning() << "We cannot use " << candidate.toString()
                          << " as a sync source because it does not contain the necessary "
                             "operations for us to reach a consistent state: "
                          << status << " last fetched optime: " << lastOpTimeFetched
                          << ". required optime: " << requiredOpTime
                          << ". Blacklisting this sync source for " << blacklistDuration
                          << " until: " << until;
                resetConnection();
                replCoord->blacklistSyncSource(candidate, until);
                continue;
            }
            resetCursor();
        }

        // TODO: If we were too stale (recovering with maintenance mode on), then turn it off, to
        //       allow becoming secondary/etc.

        // Got a valid sync source.
        return;
    }  // while (true)
}
Пример #16
0
void OplogReader::connectToSyncSource(OperationContext* txn,
                                      const OpTime& lastOpTimeFetched,
                                      ReplicationCoordinator* replCoord) {
    const Timestamp sentinelTimestamp(duration_cast<Seconds>(Milliseconds(curTimeMillis64())), 0);
    const OpTime sentinel(sentinelTimestamp, std::numeric_limits<long long>::max());
    OpTime oldestOpTimeSeen = sentinel;

    invariant(conn() == NULL);

    while (true) {
        HostAndPort candidate = replCoord->chooseNewSyncSource(lastOpTimeFetched.getTimestamp());

        if (candidate.empty()) {
            if (oldestOpTimeSeen == sentinel) {
                // If, in this invocation of connectToSyncSource(), we did not successfully
                // connect to any node ahead of us,
                // we apparently have no sync sources to connect to.
                // This situation is common; e.g. if there are no writes to the primary at
                // the moment.
                return;
            }

            // Connected to at least one member, but in all cases we were too stale to use them
            // as a sync source.
            error() << "too stale to catch up";
            log() << "our last optime : " << lastOpTimeFetched;
            log() << "oldest available is " << oldestOpTimeSeen;
            log() << "See http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember";
            setMinValid(txn, oldestOpTimeSeen);
            bool worked = replCoord->setFollowerMode(MemberState::RS_RECOVERING);
            if (!worked) {
                warning() << "Failed to transition into " << MemberState(MemberState::RS_RECOVERING)
                          << ". Current state: " << replCoord->getMemberState();
            }
            return;
        }

        if (!connect(candidate)) {
            LOG(2) << "can't connect to " << candidate.toString() << " to read operations";
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t::now() + Seconds(10));
            continue;
        }
        // Read the first (oldest) op and confirm that it's not newer than our last
        // fetched op. Otherwise, we have fallen off the back of that source's oplog.
        BSONObj remoteOldestOp(findOne(rsOplogName.c_str(), Query()));
        OpTime remoteOldOpTime = fassertStatusOK(28776, OpTime::parseFromBSON(remoteOldestOp));

        // remoteOldOpTime may come from a very old config, so we cannot compare their terms.
        if (!lastOpTimeFetched.isNull() &&
            lastOpTimeFetched.getTimestamp() < remoteOldOpTime.getTimestamp()) {
            // We're too stale to use this sync source.
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t::now() + Minutes(1));
            if (oldestOpTimeSeen.getTimestamp() > remoteOldOpTime.getTimestamp()) {
                warning() << "we are too stale to use " << candidate.toString()
                          << " as a sync source";
                oldestOpTimeSeen = remoteOldOpTime;
            }
            continue;
        }

        // Got a valid sync source.
        return;
    }  // while (true)
}
Пример #17
0
 inline bool DBClientWithCommands::runCommand(const string &dbname, const BSONObj& cmd, BSONObj &info) {
     string ns = dbname + ".$cmd";
     info = findOne(ns, cmd);
     return isOk(info);
 }
Пример #18
0
void OplogReader::connectToSyncSource(OperationContext* txn,
                                      OpTime lastOpTimeFetched,
                                      ReplicationCoordinator* replCoord) {
    const OpTime sentinel(Milliseconds(curTimeMillis64()).total_seconds(), 0);
    OpTime oldestOpTimeSeen = sentinel;

    invariant(conn() == NULL);

    while (true) {
        HostAndPort candidate = replCoord->chooseNewSyncSource(lastOpTimeFetched);

        if (candidate.empty()) {
            if (oldestOpTimeSeen == sentinel) {
                // If, in this invocation of connectToSyncSource(), we did not successfully
                // connect to any node ahead of us,
                // we apparently have no sync sources to connect to.
                // This situation is common; e.g. if there are no writes to the primary at
                // the moment.
                return;
            }

            // Connected to at least one member, but in all cases we were too stale to use them
            // as a sync source.
            log() << "replSet error RS102 too stale to catch up";
            log() << "replSet our last optime : " << lastOpTimeFetched.toStringLong();
            log() << "replSet oldest available is " << oldestOpTimeSeen.toStringLong();
            log() << "replSet "
                     "See http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember";
            setMinValid(txn, oldestOpTimeSeen);
            bool worked = replCoord->setFollowerMode(MemberState::RS_RECOVERING);
            if (!worked) {
                warning() << "Failed to transition into " << MemberState(MemberState::RS_RECOVERING)
                          << ". Current state: " << replCoord->getMemberState();
            }
            return;
        }

        if (!connect(candidate)) {
            LOG(2) << "replSet can't connect to " << candidate.toString() << " to read operations";
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t(curTimeMillis64() + 10 * 1000));
            continue;
        }
        // Read the first (oldest) op and confirm that it's not newer than our last
        // fetched op. Otherwise, we have fallen off the back of that source's oplog.
        BSONObj remoteOldestOp(findOne(rsoplog, Query()));
        BSONElement tsElem(remoteOldestOp["ts"]);
        if (tsElem.type() != Timestamp) {
            // This member's got a bad op in its oplog.
            warning() << "oplog invalid format on node " << candidate.toString();
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t(curTimeMillis64() + 600 * 1000));
            continue;
        }
        OpTime remoteOldOpTime = tsElem._opTime();

        if (!lastOpTimeFetched.isNull() && lastOpTimeFetched < remoteOldOpTime) {
            // We're too stale to use this sync source.
            resetConnection();
            replCoord->blacklistSyncSource(candidate, Date_t(curTimeMillis64() + 600 * 1000));
            if (oldestOpTimeSeen > remoteOldOpTime) {
                warning() << "we are too stale to use " << candidate.toString()
                          << " as a sync source";
                oldestOpTimeSeen = remoteOldOpTime;
            }
            continue;
        }

        // Got a valid sync source.
        return;
    }  // while (true)
}