Пример #1
0
 bool CmdLogout::run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
     AuthenticationInfo *ai = ClientInfo::get()->getAuthenticationInfo();
     AuthorizationManager* authManager = ClientInfo::get()->getAuthorizationManager();
     ai->logout(dbname);
     authManager->logoutDatabase(dbname);
     return true;
 }
Пример #2
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Create role")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            BSONObj roleObj;
            BSONObj writeConcern;
            Status status = auth::parseAndValidateCreateRoleCommand(cmdObj,
                                                                    dbname,
                                                                    authzManager,
                                                                    &roleObj,
                                                                    &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            status = authzManager->insertRoleDocument(roleObj, writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }
            return true;
        }
Пример #3
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Grant role delegation to user")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            UserName userName;
            std::vector<RoleName> roles;
            BSONObj writeConcern;
            Status status = auth::parseUserRoleManipulationCommand(cmdObj,
                                                                   "grantDelegateRolesToUser",
                                                                   dbname,
                                                                   authzManager,
                                                                   &userName,
                                                                   &roles,
                                                                   &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            User::RoleDataMap userRoles;
            status = getCurrentUserRoles(authzManager, userName, &userRoles);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) {
                RoleName& roleName = *it;
                User::RoleData& role = userRoles[roleName];
                if (role.name.empty()) {
                    role.name = roleName;
                }
                role.canDelegate = true;
            }

            BSONArray newRolesBSONArray = rolesToBSONArray(userRoles);
            status = authzManager->updatePrivilegeDocument(
                    userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern);
            // Must invalidate even on bad status - what if the write succeeded but the GLE failed?
            authzManager->invalidateUserByName(userName);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            return true;
        }
Пример #4
0
void SASLServerMechanismRegistry::advertiseMechanismNamesForUser(OperationContext* opCtx,
                                                                 const BSONObj& isMasterCmd,
                                                                 BSONObjBuilder* builder) {
    BSONElement saslSupportedMechs = isMasterCmd["saslSupportedMechs"];
    if (saslSupportedMechs.type() == BSONType::String) {

        UserName userName = uassertStatusOK(UserName::parse(saslSupportedMechs.String()));


        // Authenticating the __system@local user to the admin database on mongos is required
        // by the auth passthrough test suite.
        if (getTestCommandsEnabled() &&
            userName.getUser() == internalSecurity.user->getName().getUser() &&
            userName.getDB() == "admin") {
            userName = internalSecurity.user->getName();
        }

        AuthorizationManager* authManager = AuthorizationManager::get(opCtx->getServiceContext());

        UserHandle user;
        const auto swUser = authManager->acquireUser(opCtx, userName);
        if (!swUser.isOK()) {
            auto& status = swUser.getStatus();
            if (status.code() == ErrorCodes::UserNotFound) {
                log() << "Supported SASL mechanisms requested for unknown user '" << userName
                      << "'";
                return;
            }
            uassertStatusOK(status);
        }

        user = std::move(swUser.getValue());
        BSONArrayBuilder mechanismsBuilder;
        const auto& mechList = _getMapRef(userName.getDB());

        for (const auto& factoryIt : mechList) {
            SecurityPropertySet properties = factoryIt->properties();
            if (!properties.hasAllProperties(SecurityPropertySet{SecurityProperty::kNoPlainText,
                                                                 SecurityProperty::kMutualAuth}) &&
                userName.getDB() != "$external") {
                continue;
            }

            auto mechanismEnabled = _mechanismSupportedByConfig(factoryIt->mechanismName());
            if (!mechanismEnabled && userName == internalSecurity.user->getName()) {
                mechanismEnabled = factoryIt->isInternalAuthMech();
            }

            if (mechanismEnabled && factoryIt->canMakeMechanismForUser(user.get())) {
                mechanismsBuilder << factoryIt->mechanismName();
            }
        }

        builder->appendArray("saslSupportedMechs", mechanismsBuilder.arr());
    }
}
 bool run(OperationContext* txn,
          const string& dbname,
          BSONObj& cmdObj,
          int options,
          string& errmsg,
          BSONObjBuilder& result) {
     AuthorizationManager* authzManager = getGlobalAuthorizationManager();
     invariant(authzManager);
     authzManager->invalidateUserCache();
     return true;
 }
Пример #6
0
        void _authorizePrincipal(const std::string& principalName, bool readOnly) {
            Principal* principal = new Principal(PrincipalName(principalName, "local"));
            ActionSet actions = AuthorizationManager::getActionsForOldStyleUser(
                    "admin", readOnly);

            AuthorizationManager* authorizationManager = cc().getAuthorizationManager();
            authorizationManager->addAuthorizedPrincipal(principal);
            Status status = authorizationManager->acquirePrivilege(
                    Privilege(PrivilegeSet::WILDCARD_RESOURCE, actions), principal->getName());
            verify (status == Status::OK());
        }
Пример #7
0
 Status authenticateAndAuthorizePrincipal(const std::string& principalName,
                                          const std::string& dbname,
                                          const BSONObj& userObj) {
     AuthorizationManager* authorizationManager =
             ClientBasic::getCurrent()->getAuthorizationManager();
     Principal* principal = new Principal(principalName, dbname);
     authorizationManager->addAuthorizedPrincipal(principal);
     return authorizationManager->acquirePrivilegesFromPrivilegeDocument(dbname,
                                                                         principal,
                                                                         userObj);
 }
Пример #8
0
 void ClientInfo::_setupAuth() {
     std::string adminNs = "admin";
     DBConfigPtr config = grid.getDBConfig(adminNs);
     Shard shard = config->getShard(adminNs);
     ShardConnection conn(shard, adminNs);
     AuthorizationManager* authManager = new AuthorizationManager(new AuthExternalStateImpl());
     Status status = authManager->initialize(conn.get());
     massert(16479,
             mongoutils::str::stream() << "Error initializing AuthorizationManager: "
                                       << status.reason(),
             status == Status::OK());
     setAuthorizationManager(authManager);
 }
Пример #9
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Remove user")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            UserName userName;
            BSONObj writeConcern;

            Status status = auth::parseAndValidateRemoveUserCommand(cmdObj,
                                                                    dbname,
                                                                    &userName,
                                                                    &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            int numUpdated;
            status = authzManager->removePrivilegeDocuments(
                    BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
                         AuthorizationManager::USER_SOURCE_FIELD_NAME << userName.getDB()),
                    writeConcern,
                    &numUpdated);
            // Must invalidate even on bad status - what if the write succeeded but the GLE failed?
            authzManager->invalidateUserByName(userName);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            if (numUpdated == 0) {
                addStatus(Status(ErrorCodes::UserNotFound,
                                 mongoutils::str::stream() << "User '" << userName.getFullName() <<
                                         "' not found"),
                          result);
                return false;
            }

            return true;
        }
    bool run(OperationContext* txn,
             const string& dbname,
             BSONObj& cmdObj,
             int options,
             string& errmsg,
             BSONObjBuilder& result) {
        const bool ok = grid.catalogManager(txn)->runUserManagementWriteCommand(
            txn, this->name, dbname, cmdObj, &result);

        AuthorizationManager* authzManager = getGlobalAuthorizationManager();
        invariant(authzManager);
        authzManager->invalidateUserCache();

        return ok;
    }
    bool run(OperationContext* txn,
             const string& dbname,
             BSONObj& cmdObj,
             int options,
             string& errmsg,
             BSONObjBuilder& result) {
        auth::CreateOrUpdateUserArgs args;
        Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, this->name, dbname, &args);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }
        const bool ok = grid.catalogManager(txn)->runUserManagementWriteCommand(
            txn, this->name, dbname, cmdObj, &result);

        AuthorizationManager* authzManager = getGlobalAuthorizationManager();
        invariant(authzManager);
        authzManager->invalidateUserByName(args.userName);

        return ok;
    }
Пример #12
0
    void ClientInfo::_setupAuth() {
        std::string adminNs = "admin";
        DBConfigPtr config = grid.getDBConfig(adminNs);
        Shard shard = config->getShard(adminNs);
        scoped_ptr<ScopedDbConnection> connPtr(
                ScopedDbConnection::getInternalScopedDbConnection(shard.getConnString(), 30.0));
        ScopedDbConnection& conn = *connPtr;

        //
        // Note: The connection mechanism here is *not* ideal, and should not be used elsewhere.
        // It is safe in this particular case because the admin database is always on the config
        // server and does not move.
        //

        AuthorizationManager* authManager = new AuthorizationManager(new AuthExternalStateImpl());
        Status status = authManager->initialize(conn.get());
        massert(16479,
                mongoutils::str::stream() << "Error initializing AuthorizationManager: "
                                          << status.reason(),
                status == Status::OK());
        setAuthorizationManager(authManager);
    }
    bool run(OperationContext* txn,
             const string& dbname,
             BSONObj& cmdObj,
             int options,
             string& errmsg,
             BSONObjBuilder& result) {
        UserName userName;
        BSONObj unusedWriteConcern;
        Status status =
            auth::parseAndValidateDropUserCommand(cmdObj, dbname, &userName, &unusedWriteConcern);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }
        const bool ok = grid.catalogManager(txn)->runUserManagementWriteCommand(
            txn, this->name, dbname, cmdObj, &result);

        AuthorizationManager* authzManager = getGlobalAuthorizationManager();
        invariant(authzManager);
        authzManager->invalidateUserByName(userName);

        return ok;
    }
Пример #14
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {

            bool anyDB = false;
            BSONElement usersFilter;
            Status status = auth::parseAndValidateInfoCommands(cmdObj,
                                                               "usersInfo",
                                                               dbname,
                                                               &anyDB,
                                                               &usersFilter);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            BSONObjBuilder queryBuilder;
            queryBuilder.appendAs(usersFilter, "name");
            if (!anyDB) {
                queryBuilder.append("source", dbname);
            }

            BSONArrayBuilder usersArrayBuilder;
            BSONArrayBuilder& (BSONArrayBuilder::* appendBSONObj) (const BSONObj&) =
                    &BSONArrayBuilder::append<BSONObj>;
            const boost::function<void(const BSONObj&)> function =
                    boost::bind(appendBSONObj, &usersArrayBuilder, _1);
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            authzManager->queryAuthzDocument(NamespaceString("admin.system.users"),
                                             queryBuilder.done(),
                                             function);

            result.append("users", usersArrayBuilder.arr());
            return true;
        }
Пример #15
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Remove all users from database")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            BSONObj writeConcern;
            Status status = auth::parseAndValidateRemoveUsersFromDatabaseCommand(cmdObj,
                                                                                 dbname,
                                                                                 &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            int numRemoved;
            status = authzManager->removePrivilegeDocuments(
                    BSON(AuthorizationManager::USER_SOURCE_FIELD_NAME << dbname),
                    writeConcern,
                    &numRemoved);
            // Must invalidate even on bad status - what if the write succeeded but the GLE failed?
            authzManager->invalidateUsersFromDB(dbname);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            result.append("n", numRemoved);
            return true;
        }
Пример #16
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Update user")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            BSONObj updateObj;
            UserName userName;
            BSONObj writeConcern;
            Status status = auth::parseAndValidateUpdateUserCommand(cmdObj,
                                                                    dbname,
                                                                    authzManager,
                                                                    &updateObj,
                                                                    &userName,
                                                                    &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            status = authzManager->updatePrivilegeDocument(userName, updateObj, writeConcern);
            // Must invalidate even on bad status - what if the write succeeded but the GLE failed?
            authzManager->invalidateUserByName(userName);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            return true;
        }
    bool run(OperationContext* txn,
             const string& dbname,
             BSONObj& cmdObj,
             int options,
             string& errmsg,
             BSONObjBuilder& result) {
        string userNameString;
        vector<RoleName> unusedRoles;
        BSONObj unusedWriteConcern;
        Status status = auth::parseRolePossessionManipulationCommands(
            cmdObj, this->name, dbname, &userNameString, &unusedRoles, &unusedWriteConcern);
        if (!status.isOK()) {
            return appendCommandStatus(result, status);
        }
        const bool ok = grid.catalogManager(txn)->runUserManagementWriteCommand(
            txn, this->name, dbname, cmdObj, &result);

        AuthorizationManager* authzManager = getGlobalAuthorizationManager();
        invariant(authzManager);
        authzManager->invalidateUserByName(UserName(userNameString, dbname));

        return ok;
    }
StatusWith<std::tuple<bool, std::string>> SASLPlainServerMechanism::stepImpl(
    OperationContext* opCtx, StringData inputData) {
    if (_authenticationDatabase == "$external") {
        return Status(ErrorCodes::AuthenticationFailed,
                      "PLAIN mechanism must be used with internal users");
    }

    AuthorizationManager* authManager = AuthorizationManager::get(opCtx->getServiceContext());

    // Expecting user input on the form: [authz-id]\0authn-id\0pwd
    std::string input = inputData.toString();

    SecureAllocatorAuthDomain::SecureString pwd = "";
    try {
        size_t firstNull = inputData.find('\0');
        if (firstNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing first NULL delimiter");
        }
        size_t secondNull = inputData.find('\0', firstNull + 1);
        if (secondNull == std::string::npos) {
            return Status(
                ErrorCodes::AuthenticationFailed,
                str::stream()
                    << "Incorrectly formatted PLAIN client message, missing second NULL delimiter");
        }

        std::string authorizationIdentity = input.substr(0, firstNull);
        ServerMechanismBase::_principalName =
            input.substr(firstNull + 1, (secondNull - firstNull) - 1);
        if (ServerMechanismBase::_principalName.empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty username");
        } else if (!authorizationIdentity.empty() &&
                   authorizationIdentity != ServerMechanismBase::_principalName) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "SASL authorization identity must match authentication identity");
        }
        pwd = SecureAllocatorAuthDomain::SecureString(input.substr(secondNull + 1).c_str());
        if (pwd->empty()) {
            return Status(ErrorCodes::AuthenticationFailed,
                          str::stream()
                              << "Incorrectly formatted PLAIN client message, empty password");
        }
    } catch (std::out_of_range&) {
        return Status(ErrorCodes::AuthenticationFailed,
                      str::stream() << "Incorrectly formatted PLAIN client message");
    }

    // The authentication database is also the source database for the user.
    auto swUser = authManager->acquireUser(
        opCtx, UserName(ServerMechanismBase::_principalName, _authenticationDatabase));

    if (!swUser.isOK()) {
        return swUser.getStatus();
    }

    auto userObj = std::move(swUser.getValue());
    const auto creds = userObj->getCredentials();

    const auto sha256Status = trySCRAM<SHA256Block>(creds, pwd->c_str());
    if (!sha256Status.isOK()) {
        return sha256Status.getStatus();
    }
    if (sha256Status.getValue()) {
        return std::make_tuple(true, std::string());
    }

    const auto authDigest = createPasswordDigest(ServerMechanismBase::_principalName, pwd->c_str());
    const auto sha1Status = trySCRAM<SHA1Block>(creds, authDigest);
    if (!sha1Status.isOK()) {
        return sha1Status.getStatus();
    }
    if (sha1Status.getValue()) {
        return std::make_tuple(true, std::string());
    }

    return Status(ErrorCodes::AuthenticationFailed, str::stream() << "No credentials available.");


    return std::make_tuple(true, std::string());
}
Пример #19
0
ExitCode _initAndListen(int listenPort) {
    Client::initThread("initandlisten");

    _initWireSpec();
    auto globalServiceContext = getGlobalServiceContext();

    globalServiceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    globalServiceContext->setOpObserver(stdx::make_unique<OpObserver>());

    DBDirectClientFactory::get(globalServiceContext)
        .registerImplementation([](OperationContext* txn) {
            return std::unique_ptr<DBClientBase>(new DBDirectClient(txn));
        });

    const repl::ReplSettings& replSettings = repl::getGlobalReplicationCoordinator()->getSettings();

    {
        ProcessId pid = ProcessId::getCurrent();
        LogstreamBuilder l = log(LogComponent::kControl);
        l << "MongoDB starting : pid=" << pid << " port=" << serverGlobalParams.port
          << " dbpath=" << storageGlobalParams.dbpath;
        if (replSettings.isMaster())
            l << " master=" << replSettings.isMaster();
        if (replSettings.isSlave())
            l << " slave=" << (int)replSettings.isSlave();

        const bool is32bit = sizeof(int*) == 4;
        l << (is32bit ? " 32" : " 64") << "-bit host=" << getHostNameCached() << endl;
    }

    DEV log(LogComponent::kControl) << "DEBUG build (which is slower)" << endl;

#if defined(_WIN32)
    VersionInfoInterface::instance().logTargetMinOS();
#endif

    logProcessDetails();

    checked_cast<ServiceContextMongoD*>(getGlobalServiceContext())->createLockFile();

    transport::TransportLayerLegacy::Options options;
    options.port = listenPort;
    options.ipList = serverGlobalParams.bind_ip;

    auto sep =
        stdx::make_unique<ServiceEntryPointMongod>(getGlobalServiceContext()->getTransportLayer());
    auto sepPtr = sep.get();

    getGlobalServiceContext()->setServiceEntryPoint(std::move(sep));

    // Create, start, and attach the TL
    auto transportLayer = stdx::make_unique<transport::TransportLayerLegacy>(options, sepPtr);
    auto res = transportLayer->setup();
    if (!res.isOK()) {
        error() << "Failed to set up listener: " << res;
        return EXIT_NET_ERROR;
    }

    std::shared_ptr<DbWebServer> dbWebServer;
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        dbWebServer.reset(new DbWebServer(serverGlobalParams.bind_ip,
                                          serverGlobalParams.port + 1000,
                                          getGlobalServiceContext(),
                                          new RestAdminAccess()));
        if (!dbWebServer->setupSockets()) {
            error() << "Failed to set up sockets for HTTP interface during startup.";
            return EXIT_NET_ERROR;
        }
    }

    getGlobalServiceContext()->initializeGlobalStorageEngine();

#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
    if (WiredTigerCustomizationHooks::get(getGlobalServiceContext())->restartRequired()) {
        exitCleanly(EXIT_CLEAN);
    }
#endif

    // Warn if we detect configurations for multiple registered storage engines in
    // the same configuration file/environment.
    if (serverGlobalParams.parsedOpts.hasField("storage")) {
        BSONElement storageElement = serverGlobalParams.parsedOpts.getField("storage");
        invariant(storageElement.isABSONObj());
        BSONObj storageParamsObj = storageElement.Obj();
        BSONObjIterator i = storageParamsObj.begin();
        while (i.more()) {
            BSONElement e = i.next();
            // Ignore if field name under "storage" matches current storage engine.
            if (storageGlobalParams.engine == e.fieldName()) {
                continue;
            }

            // Warn if field name matches non-active registered storage engine.
            if (getGlobalServiceContext()->isRegisteredStorageEngine(e.fieldName())) {
                warning() << "Detected configuration for non-active storage engine "
                          << e.fieldName() << " when current storage engine is "
                          << storageGlobalParams.engine;
            }
        }
    }

    if (!getGlobalServiceContext()->getGlobalStorageEngine()->getSnapshotManager()) {
        if (moe::startupOptionsParsed.count("replication.enableMajorityReadConcern") &&
            moe::startupOptionsParsed["replication.enableMajorityReadConcern"].as<bool>()) {
            // Note: we are intentionally only erroring if the user explicitly requested that we
            // enable majority read concern. We do not error if the they are implicitly enabled for
            // CSRS because a required step in the upgrade procedure can involve an mmapv1 node in
            // the CSRS in the REMOVED state. This is handled by the TopologyCoordinator.
            invariant(replSettings.isMajorityReadConcernEnabled());
            severe() << "Majority read concern requires a storage engine that supports"
                     << " snapshots, such as wiredTiger. " << storageGlobalParams.engine
                     << " does not support snapshots.";
            exitCleanly(EXIT_BADOPTIONS);
        }
    }

    logMongodStartupWarnings(storageGlobalParams, serverGlobalParams);

    {
        stringstream ss;
        ss << endl;
        ss << "*********************************************************************" << endl;
        ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
        ss << " Create this directory or give existing directory in --dbpath." << endl;
        ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
        ss << "*********************************************************************" << endl;
        uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
    }

    {
        stringstream ss;
        ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist";
        uassert(12590, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.repairpath));
    }

    // TODO:  This should go into a MONGO_INITIALIZER once we have figured out the correct
    // dependencies.
    if (snmpInit) {
        snmpInit();
    }

    if (!storageGlobalParams.readOnly) {
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    }

    if (mmapv1GlobalOptions.journalOptions & MMAPV1Options::JournalRecoverOnly)
        return EXIT_NET_ERROR;

    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
    }

    auto startupOpCtx = getGlobalServiceContext()->makeOperationContext(&cc());

    repairDatabasesAndCheckVersion(startupOpCtx.get());

    if (storageGlobalParams.upgrade) {
        log() << "finished checking dbs";
        exitCleanly(EXIT_CLEAN);
    }

    uassertStatusOK(getGlobalAuthorizationManager()->initialize(startupOpCtx.get()));

    /* this is for security on certain platforms (nonce generation) */
    srand((unsigned)(curTimeMicros64() ^ startupSrandTimer.micros()));

    // The snapshot thread provides historical collection level and lock statistics for use
    // by the web interface. Only needed when HTTP is enabled.
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        statsSnapshotThread.go();

        invariant(dbWebServer);
        stdx::thread web(stdx::bind(&webServerListenThread, dbWebServer));
        web.detach();
    }

#ifndef _WIN32
    mongo::signalForkSuccess();
#endif
    AuthorizationManager* globalAuthzManager = getGlobalAuthorizationManager();
    if (globalAuthzManager->shouldValidateAuthSchemaOnStartup()) {
        Status status = authindex::verifySystemIndexes(startupOpCtx.get());
        if (!status.isOK()) {
            log() << redact(status);
            exitCleanly(EXIT_NEED_UPGRADE);
        }

        // SERVER-14090: Verify that auth schema version is schemaVersion26Final.
        int foundSchemaVersion;
        status =
            globalAuthzManager->getAuthorizationVersion(startupOpCtx.get(), &foundSchemaVersion);
        if (!status.isOK()) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but startup could not verify schema version: " << status;
            exitCleanly(EXIT_NEED_UPGRADE);
        }
        if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but found " << foundSchemaVersion << ". In order to upgrade "
                  << "the auth schema, first downgrade MongoDB binaries to version "
                  << "2.6 and then run the authSchemaUpgrade command.";
            exitCleanly(EXIT_NEED_UPGRADE);
        }
    } else if (globalAuthzManager->isAuthEnabled()) {
        error() << "Auth must be disabled when starting without auth schema validation";
        exitCleanly(EXIT_BADOPTIONS);
    } else {
        // If authSchemaValidation is disabled and server is running without auth,
        // warn the user and continue startup without authSchema metadata checks.
        log() << startupWarningsLog;
        log() << "** WARNING: Startup auth schema validation checks are disabled for the "
                 "database."
              << startupWarningsLog;
        log() << "**          This mode should only be used to manually repair corrupted auth "
                 "data."
              << startupWarningsLog;
    }

    auto shardingInitialized =
        uassertStatusOK(ShardingState::get(startupOpCtx.get())
                            ->initializeShardingAwarenessIfNeeded(startupOpCtx.get()));
    if (shardingInitialized) {
        reloadShardRegistryUntilSuccess(startupOpCtx.get());
    }

    if (!storageGlobalParams.readOnly) {
        logStartup(startupOpCtx.get());

        startFTDC();

        getDeleter()->startWorkers();

        restartInProgressIndexesFromLastShutdown(startupOpCtx.get());

        if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
            // Note: For replica sets, ShardingStateRecovery happens on transition to primary.
            if (!repl::getGlobalReplicationCoordinator()->isReplEnabled()) {
                uassertStatusOK(ShardingStateRecovery::recover(startupOpCtx.get()));
            }
        } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
            uassertStatusOK(
                initializeGlobalShardingStateForMongod(startupOpCtx.get(),
                                                       ConnectionString::forLocal(),
                                                       kDistLockProcessIdForConfigServer));
            Balancer::create(startupOpCtx->getServiceContext());
        }

        repl::getGlobalReplicationCoordinator()->startup(startupOpCtx.get());

        const unsigned long long missingRepl =
            checkIfReplMissingFromCommandLine(startupOpCtx.get());
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset" << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and "
                  << " no other clients are connected." << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this."
                  << startupWarningsLog;
            log() << "**         ";
            log() << " For more info see http://dochub.mongodb.org/core/ttlcollections";
            log() << startupWarningsLog;
        } else {
            startTTLBackgroundJob();
        }

        if (!replSettings.usingReplSets() && !replSettings.isSlave() &&
            storageGlobalParams.engine != "devnull") {
            ScopedTransaction transaction(startupOpCtx.get(), MODE_X);
            Lock::GlobalWrite lk(startupOpCtx.get()->lockState());
            FeatureCompatibilityVersion::setIfCleanStartup(
                startupOpCtx.get(), repl::StorageInterface::get(getGlobalServiceContext()));
        }
    }

    startClientCursorMonitor();

    PeriodicTask::startRunningPeriodicTasks();

    // MessageServer::run will return when exit code closes its socket and we don't need the
    // operation context anymore
    startupOpCtx.reset();

    auto start = getGlobalServiceContext()->addAndStartTransportLayer(std::move(transportLayer));
    if (!start.isOK()) {
        error() << "Failed to start the listener: " << start.toString();
        return EXIT_NET_ERROR;
    }

    return waitForShutdown();
}
Пример #20
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Revoke role delegation from user")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            UserName userName;
            std::vector<RoleName> roles;
            BSONObj writeConcern;
            Status status = auth::parseUserRoleManipulationCommand(cmdObj,
                                                                   "revokeDelegateRolesFromUser",
                                                                   dbname,
                                                                   authzManager,
                                                                   &userName,
                                                                   &roles,
                                                                   &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            User::RoleDataMap userRoles;
            status = getCurrentUserRoles(authzManager, userName, &userRoles);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) {
                RoleName& roleName = *it;
                User::RoleDataMap::iterator roleDataIt = userRoles.find(roleName);
                if (roleDataIt == userRoles.end()) {
                    continue; // User already doesn't have the role, nothing to do
                }
                User::RoleData& role = roleDataIt->second;
                if (role.hasRole) {
                    // If the user still has the role, need to leave it in the roles array
                    role.canDelegate = false;
                } else {
                    // If the user doesn't have the role, and now can't delegate it either, remove
                    // the role from that user's roles array entirely
                    userRoles.erase(roleDataIt);
                }
            }

            BSONArray newRolesBSONArray = rolesToBSONArray(userRoles);
            status = authzManager->updatePrivilegeDocument(
                    userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern);
            // Must invalidate even on bad status - what if the write succeeded but the GLE failed?
            authzManager->invalidateUserByName(userName);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            return true;
        }
Пример #21
0
    void CursorCache::gotKillCursors(Message& m ) {
        int *x = (int *) m.singleData()->_data;
        x++; // reserved
        int n = *x++;

        if ( n > 2000 ) {
            LOG( n < 30000 ? LL_WARNING : LL_ERROR ) << "receivedKillCursors, n=" << n << endl;
        }


        uassert( 13286 , "sent 0 cursors to kill" , n >= 1 );
        uassert( 13287 , "too many cursors to kill" , n < 30000 );

        long long * cursors = (long long *)x;
        AuthorizationManager* authManager =
                ClientBasic::getCurrent()->getAuthorizationManager();
        for ( int i=0; i<n; i++ ) {
            long long id = cursors[i];
            LOG(_myLogLevel) << "CursorCache::gotKillCursors id: " << id << endl;

            if ( ! id ) {
                LOG( LL_WARNING ) << " got cursor id of 0 to kill" << endl;
                continue;
            }

            string server;
            {
                scoped_lock lk( _mutex );

                MapSharded::iterator i = _cursors.find( id );
                if ( i != _cursors.end() ) {
                    if (authManager->checkAuthorization(i->second->getNS(),
                                                        ActionType::killCursors)) {
                        _cursors.erase( i );
                    }
                    continue;
                }

                MapNormal::iterator refsIt = _refs.find(id);
                MapNormal::iterator refsNSIt = _refsNS.find(id);
                if (refsIt == _refs.end()) {
                    LOG( LL_WARNING ) << "can't find cursor: " << id << endl;
                    continue;
                }
                verify(refsNSIt != _refsNS.end());
                if (!authManager->checkAuthorization(refsNSIt->second, ActionType::killCursors)) {
                    continue;
                }
                server = refsIt->second;
                _refs.erase(refsIt);
                _refsNS.erase(refsNSIt);
            }

            LOG(_myLogLevel) << "CursorCache::found gotKillCursors id: " << id << " server: " << server << endl;

            verify( server.size() );
            scoped_ptr<ScopedDbConnection> conn(
                    ScopedDbConnection::getScopedDbConnection( server ) );
            conn->get()->killCursor( id );
            conn->done();
        }
    }
Пример #22
0
        bool run(const string& dbname,
                 BSONObj& cmdObj,
                 int options,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool fromRepl) {
            AuthorizationManager* authzManager = getGlobalAuthorizationManager();
            AuthzDocumentsUpdateGuard updateGuard(authzManager);
            if (!updateGuard.tryLock("Grant privileges to role")) {
                addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."),
                          result);
                return false;
            }

            RoleName roleName;
            PrivilegeVector privilegesToAdd;
            BSONObj writeConcern;
            Status status = auth::parseAndValidateRolePrivilegeManipulationCommands(
                    cmdObj,
                    "grantPrivilegesToRole",
                    dbname,
                    &roleName,
                    &privilegesToAdd,
                    &writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            if (!authzManager->roleExists(roleName)) {
                addStatus(Status(ErrorCodes::RoleNotFound,
                                 mongoutils::str::stream() << roleName.getFullName() <<
                                         " does not name an existing role"),
                          result);
                return false;
            }

            if (authzManager->isBuiltinRole(roleName)) {
                addStatus(Status(ErrorCodes::InvalidRoleModification,
                                 mongoutils::str::stream() << roleName.getFullName() <<
                                         " is a built-in role and cannot be modified."),
                          result);
                return false;
            }

            PrivilegeVector privileges = authzManager->getDirectPrivilegesForRole(roleName);
            for (PrivilegeVector::iterator it = privilegesToAdd.begin();
                    it != privilegesToAdd.end(); ++it) {
                Privilege::addPrivilegeToPrivilegeVector(&privileges, *it);
            }

            // Build up update modifier object to $set privileges.
            mutablebson::Document updateObj;
            mutablebson::Element setElement = updateObj.makeElementObject("$set");
            status = updateObj.root().pushBack(setElement);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }
            mutablebson::Element privilegesElement = updateObj.makeElementArray("privileges");
            status = setElement.pushBack(privilegesElement);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }
            status = authzManager->getBSONForPrivileges(privileges, privilegesElement);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            BSONObjBuilder updateBSONBuilder;
            updateObj.writeTo(&updateBSONBuilder);
            status = authzManager->updateRoleDocument(
                    roleName,
                    updateBSONBuilder.done(),
                    writeConcern);
            if (!status.isOK()) {
                addStatus(status, result);
                return false;
            }

            return true;
        }
Пример #23
0
        bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            
            _runCalled = true;

            long long start = Listener::getElapsedTimeMillis();
            BSONObjBuilder timeBuilder(256);

            const ClientBasic* myClientBasic = ClientBasic::getCurrent();
            AuthorizationManager* authManager = myClientBasic->getAuthorizationManager();
            
            // --- basic fields that are global

            result.append("host", prettyHostName() );
            result.append("version", versionString);
            result.append("process",cmdLine.binaryName);
            result.append("pid", (int)getpid());
            result.append("uptime",(double) (time(0)-cmdLine.started));
            result.append("uptimeMillis", (long long)(curTimeMillis64()-_started));
            result.append("uptimeEstimate",(double) (start/1000));
            result.appendDate( "localTime" , jsTime() );

            timeBuilder.appendNumber( "after basic" , Listener::getElapsedTimeMillis() - start );
            
            // --- all sections
            
            for ( SectionMap::const_iterator i = _sections->begin(); i != _sections->end(); ++i ) {
                ServerStatusSection* section = i->second;
                
                std::vector<Privilege> requiredPrivileges;
                section->addRequiredPrivileges(&requiredPrivileges);
                if (!authManager->checkAuthForPrivileges(requiredPrivileges).isOK())
                    continue;

                bool include = section->includeByDefault();
                
                BSONElement e = cmdObj[section->getSectionName()];
                if ( e.type() ) {
                    include = e.trueValue();
                }
                
                if ( ! include )
                    continue;
                
                BSONObj data = section->generateSection(e);
                if ( data.isEmpty() )
                    continue;

                result.append( section->getSectionName(), data );
                timeBuilder.appendNumber( static_cast<string>(str::stream() << "after " << section->getSectionName()), 
                                          Listener::getElapsedTimeMillis() - start );
            }

            // --- counters
            
            if ( MetricTree::theMetricTree ) {
                MetricTree::theMetricTree->appendTo( result );
            }

            // --- some hard coded global things hard to pull out

            {
                RamLog* rl = RamLog::get( "warnings" );
                massert(15880, "no ram log for warnings?" , rl);
                
                if (rl->lastWrite() >= time(0)-(10*60)){ // only show warnings from last 10 minutes
                    vector<const char*> lines;
                    rl->get( lines );
                    
                    BSONArrayBuilder arr( result.subarrayStart( "warnings" ) );
                    for ( unsigned i=std::max(0,(int)lines.size()-10); i<lines.size(); i++ )
                        arr.append( lines[i] );
                    arr.done();
                }
            }
            
            timeBuilder.appendNumber( "at end" , Listener::getElapsedTimeMillis() - start );
            if ( Listener::getElapsedTimeMillis() - start > 1000 ) {
                BSONObj t = timeBuilder.obj();
                log() << "serverStatus was very slow: " << t << endl;
                result.append( "timing" , t );
            }

            return true;
        }
Пример #24
0
        bool handleSpecialNamespaces( Request& r , QueryMessage& q ) {
            const char * ns = r.getns();
            ns = strstr( r.getns() , ".$cmd.sys." );
            if ( ! ns )
                return false;
            ns += 10;

            BSONObjBuilder b;
            vector<Shard> shards;

            AuthorizationManager* authManager =
                    ClientBasic::getCurrent()->getAuthorizationManager();

            if ( strcmp( ns , "inprog" ) == 0 ) {
                uassert(16545,
                        "not authorized to run inprog",
                        authManager->checkAuthorization(AuthorizationManager::SERVER_RESOURCE_NAME,
                                                        ActionType::inprog));

                Shard::getAllShards( shards );

                BSONArrayBuilder arr( b.subarrayStart( "inprog" ) );

                for ( unsigned i=0; i<shards.size(); i++ ) {
                    Shard shard = shards[i];
                    scoped_ptr<ScopedDbConnection> conn(
                            ScopedDbConnection::getScopedDbConnection( shard.getConnString() ) );
                    BSONObj temp = conn->get()->findOne( r.getns() , q.query );
                    if ( temp["inprog"].isABSONObj() ) {
                        BSONObjIterator i( temp["inprog"].Obj() );
                        while ( i.more() ) {
                            BSONObjBuilder x;

                            BSONObjIterator j( i.next().Obj() );
                            while( j.more() ) {
                                BSONElement e = j.next();
                                if ( str::equals( e.fieldName() , "opid" ) ) {
                                    stringstream ss;
                                    ss << shard.getName() << ':' << e.numberInt();
                                    x.append( "opid" , ss.str() );
                                }
                                else if ( str::equals( e.fieldName() , "client" ) ) {
                                    x.appendAs( e , "client_s" );
                                }
                                else {
                                    x.append( e );
                                }
                            }
                            arr.append( x.obj() );
                        }
                    }
                    conn->done();
                }

                arr.done();
            }
            else if ( strcmp( ns , "killop" ) == 0 ) {
                uassert(16546,
                        "not authorized to run killop",
                        authManager->checkAuthorization(AuthorizationManager::SERVER_RESOURCE_NAME,
                                                        ActionType::killop));

                BSONElement e = q.query["op"];
                if ( e.type() != String ) {
                    b.append( "err" , "bad op" );
                    b.append( e );
                }
                else {
                    b.append( e );
                    string s = e.String();
                    string::size_type i = s.find( ':' );
                    if ( i == string::npos ) {
                        b.append( "err" , "bad opid" );
                    }
                    else {
                        string shard = s.substr( 0 , i );
                        int opid = atoi( s.substr( i + 1 ).c_str() );
                        b.append( "shard" , shard );
                        b.append( "shardid" , opid );

                        log() << "want to kill op: " << e << endl;
                        Shard s(shard);

                        scoped_ptr<ScopedDbConnection> conn(
                                ScopedDbConnection::getScopedDbConnection( s.getConnString() ) );
                        conn->get()->findOne( r.getns() , BSON( "op" << opid ) );
                        conn->done();
                    }
                }
            }
            else if ( strcmp( ns , "unlock" ) == 0 ) {
                b.append( "err" , "can't do unlock through mongos" );
            }
            else {
                LOG( LL_WARNING ) << "unknown sys command [" << ns << "]" << endl;
                return false;
            }

            BSONObj x = b.done();
            replyToQuery(0, r.p(), r.m(), x);
            return true;
        }
Пример #25
0
    void Command::execCommandClientBasic(Command * c ,
                                         ClientBasic& client,
                                         int queryOptions,
                                         const char *ns,
                                         BSONObj& cmdObj,
                                         BSONObjBuilder& result,
                                         bool fromRepl ) {
        verify(c);

        std::string dbname = nsToDatabase(ns);

        // Access control checks
        if (!noauth) {
            std::vector<Privilege> privileges;
            c->addRequiredPrivileges(dbname, cmdObj, &privileges);
            AuthorizationManager* authManager = client.getAuthorizationManager();
            if (!authManager->checkAuthForPrivileges(privileges).isOK()) {
                result.append("note", str::stream() << "not authorized for command: " <<
                                    c->name << " on database " << dbname);
                appendCommandStatus(result, false, "unauthorized");
                return;
            }
        }
        if (c->adminOnly() && c->localHostOnlyIfNoAuth(cmdObj) && noauth &&
                !client.getIsLocalHostConnection()) {
            log() << "command denied: " << cmdObj.toString() << endl;
            appendCommandStatus(result,
                               false,
                               "unauthorized: this command must run from localhost when running db "
                               "without auth");
            return;
        }
        if (c->adminOnly() && !startsWith(ns, "admin.")) {
            log() << "command denied: " << cmdObj.toString() << endl;
            appendCommandStatus(result, false, "access denied - use admin db");
            return;
        }
        // End of access control checks

        if (cmdObj.getBoolField("help")) {
            stringstream help;
            help << "help for: " << c->name << " ";
            c->help( help );
            result.append( "help" , help.str() );
            result.append( "lockType" , c->locktype() );
            appendCommandStatus(result, true, "");
            return;
        }
        std::string errmsg;
        bool ok;
        try {
            ok = c->run( dbname , cmdObj, queryOptions, errmsg, result, false );
        }
        catch (DBException& e) {
            ok = false;
            int code = e.getCode();
            if (code == RecvStaleConfigCode) { // code for StaleConfigException
                throw;
            }

            stringstream ss;
            ss << "exception: " << e.what();
            errmsg = ss.str();
            result.append( "code" , code );
        }

        appendCommandStatus(result, ok, errmsg);
    }