Status checkAuthForRolesInfoCommand(ClientBasic* client,
                                    const std::string& dbname,
                                    const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::RolesInfoArgs args;
    Status status = auth::parseRolesInfoCommand(cmdObj, dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (args.allForDB) {
        if (!authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forDatabaseName(dbname), ActionType::viewRole)) {
            return Status(ErrorCodes::Unauthorized,
                          str::stream() << "Not authorized to view roles from the " << dbname
                                        << " database");
        }
    } else {
        for (size_t i = 0; i < args.roleNames.size(); ++i) {
            if (authzSession->isAuthenticatedAsUserWithRole(args.roleNames[i])) {
                continue;  // Can always see roles that you are a member of
            }

            if (!authzSession->isAuthorizedForActionsOnResource(
                    ResourcePattern::forDatabaseName(args.roleNames[i].getDB()),
                    ActionType::viewRole)) {
                return Status(ErrorCodes::Unauthorized,
                              str::stream() << "Not authorized to view roles from the "
                                            << args.roleNames[i].getDB() << " database");
            }
        }
    }

    return Status::OK();
}
Status checkAuthForUsersInfoCommand(ClientBasic* client,
                                    const std::string& dbname,
                                    const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::UsersInfoArgs args;
    Status status = auth::parseUsersInfoCommand(cmdObj, dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (args.allForDB) {
        if (!authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forDatabaseName(dbname), ActionType::viewUser)) {
            return Status(ErrorCodes::Unauthorized,
                          str::stream() << "Not authorized to view users from the " << dbname
                                        << " database");
        }
    } else {
        for (size_t i = 0; i < args.userNames.size(); ++i) {
            if (authzSession->lookupUser(args.userNames[i])) {
                continue;  // Can always view users you are logged in as
            }
            if (!authzSession->isAuthorizedForActionsOnResource(
                    ResourcePattern::forDatabaseName(args.userNames[i].getDB()),
                    ActionType::viewUser)) {
                return Status(ErrorCodes::Unauthorized,
                              str::stream() << "Not authorized to view users from the " << dbname
                                            << " database");
            }
        }
    }
    return Status::OK();
}
Status checkAuthForUpdateUserCommand(Client* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateUserArgs args;
    Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "updateUser", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (args.hasPassword) {
        if (!authzSession->isAuthorizedToChangeOwnPasswordAsUser(args.userName) &&
            !authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forDatabaseName(args.userName.getDB()),
                ActionType::changePassword)) {
            return Status(ErrorCodes::Unauthorized,
                          str::stream() << "Not authorized to change password of user: "******"Not authorized to change customData of user: "******"In order to use updateUser to set roles array, must be "
                          "authorized to revoke any role in the system");
        }

        status = checkAuthorizedToGrantRoles(authzSession, args.roles);
        if (!status.isOK()) {
            return status;
        }
    }

    status = checkAuthorizedToSetRestrictions(
        authzSession, static_cast<bool>(args.authenticationRestrictions), args.userName.getDB());
    if (!status.isOK()) {
        return status;
    }

    return Status::OK();
}
Status checkAuthForCreateUserCommand(Client* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateUserArgs args;
    Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "createUser", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forDatabaseName(args.userName.getDB()), ActionType::createUser)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to create users on db: "
                                    << args.userName.getDB());
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    status = checkAuthorizedToSetRestrictions(
        authzSession, static_cast<bool>(args.authenticationRestrictions), args.userName.getDB());
    if (!status.isOK()) {
        return status;
    }

    return Status::OK();
}
Status checkAuthForUpdateRoleCommand(ClientBasic* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateRoleArgs args;
    Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "updateRole", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    // You don't know what roles or privileges you might be revoking, so require the ability
    // to revoke any role (or privilege) in the system.
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forAnyNormalResource(),
                                                        ActionType::revokeRole)) {
        return Status(ErrorCodes::Unauthorized,
                      "updateRole command required the ability to revoke any role in the "
                      "system");
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
}
Status checkAuthForAuthSchemaUpgradeCommand(ClientBasic* client) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                        ActionType::authSchemaUpgrade)) {
        return Status(ErrorCodes::Unauthorized, "Not authorized to run authSchemaUpgrade command.");
    }
    return Status::OK();
}
Status checkAuthForInvalidateUserCacheCommand(Client* client) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                        ActionType::invalidateUserCache)) {
        return Status(ErrorCodes::Unauthorized, "Not authorized to invalidate user cache");
    }
    return Status::OK();
}
Status checkAuthForGetUserCacheGenerationCommand(Client* client) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                        ActionType::internal)) {
        return Status(ErrorCodes::Unauthorized, "Not authorized to get cache generation");
    }
    return Status::OK();
}
Пример #9
0
    virtual Status checkAuthForCommand(ClientBasic* client,
                                       const std::string& dbname,
                                       const BSONObj& cmdObj) {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);

        // Check for the listCollections ActionType on the database
        // or find on system.namespaces for pre 3.0 systems.
        if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbname),
                                                           ActionType::listCollections) ||
            authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(NamespaceString(dbname, "system.namespaces")),
                ActionType::find)) {
            return Status::OK();
        }

        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to create users on db: " << dbname);
    }
Пример #10
0
 Status checkAuthForCommand(Client* client,
                            const std::string& dbname,
                            const BSONObj& cmdObj) final {
     AuthorizationSession* authzSession = AuthorizationSession::get(client);
     if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                        ActionType::replSetResizeOplog)) {
         return Status::OK();
     }
     return Status(ErrorCodes::Unauthorized, "Unauthorized");
 }
Status checkAuthForDropAllRolesFromDatabaseCommand(Client* client, const std::string& dbname) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbname),
                                                        ActionType::dropRole)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to drop roles from the " << dbname
                                    << " database");
    }
    return Status::OK();
}
Пример #12
0
    Status checkAuthForCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);
        ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);

        if (authzSession->isAuthorizedForActionsOnResource(pattern, _actionType)) {
            return Status::OK();
        }

        return Status(ErrorCodes::Unauthorized, "unauthorized");
    }
Пример #13
0
Status IndexFilterCommand::checkAuthForCommand(ClientBasic* client, const std::string& dbname,
        const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = client->getAuthorizationSession();
    ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);

    if (authzSession->isAuthorizedForActionsOnResource(pattern, ActionType::planCacheIndexFilter)) {
        return Status::OK();
    }

    return Status(ErrorCodes::Unauthorized, "unauthorized");
}
Пример #14
0
    Status checkAuthForCommand(Client* client,
                               const std::string& dbname,
                               const BSONObj& cmdObj) const override {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);

        // Check for the listIndexes ActionType on the database, or find on system.indexes for pre
        // 3.0 systems.
        const NamespaceString ns(parseNs(dbname, cmdObj));

        if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns),
                                                           ActionType::listIndexes) ||
            authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace(NamespaceString(dbname, "system.indexes")),
                ActionType::find)) {
            return Status::OK();
        }

        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to list indexes on collection: "
                                    << ns.coll());
    }
Status checkAuthForMergeAuthzCollectionsCommand(Client* client, const BSONObj& cmdObj) {
    auth::MergeAuthzCollectionsArgs args;
    Status status = auth::parseMergeAuthzCollectionsCommand(cmdObj, &args);
    if (!status.isOK()) {
        return status;
    }

    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    ActionSet actions;
    actions.addAction(ActionType::createUser);
    actions.addAction(ActionType::createRole);
    actions.addAction(ActionType::grantRole);
    actions.addAction(ActionType::revokeRole);
    if (args.drop) {
        actions.addAction(ActionType::dropUser);
        actions.addAction(ActionType::dropRole);
    }
    if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forAnyNormalResource(),
                                                        actions)) {
        return Status(ErrorCodes::Unauthorized,
                      "Not authorized to update user/role data using _mergeAuthzCollections"
                      " command");
    }
    if (!args.usersCollName.empty() &&
        !authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forExactNamespace(NamespaceString(args.usersCollName)),
            ActionType::find)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to read " << args.usersCollName);
    }
    if (!args.rolesCollName.empty() &&
        !authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forExactNamespace(NamespaceString(args.rolesCollName)),
            ActionType::find)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to read " << args.rolesCollName);
    }
    return Status::OK();
}
Пример #16
0
Status ProfileCmdBase::checkAuthForCommand(Client* client,
                                           const std::string& dbName,
                                           const BSONObj& cmdObj) const {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);

    auto request = ProfileCmdRequest::parse(IDLParserErrorContext("profile"), cmdObj);
    const auto profilingLevel = request.getCommandParameter();

    if (profilingLevel < 0 && !request.getSlowms() && !request.getSampleRate()) {
        // If the user just wants to view the current values of 'slowms' and 'sampleRate', they
        // only need read rights on system.profile, even if they can't change the profiling level.
        if (authzSession->isAuthorizedForActionsOnResource(
                ResourcePattern::forExactNamespace({dbName, "system.profile"}), ActionType::find)) {
            return Status::OK();
        }
    }

    return authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbName),
                                                          ActionType::enableProfiler)
        ? Status::OK()
        : Status(ErrorCodes::Unauthorized, "unauthorized");
}
Пример #17
0
Status checkAuthForApplyOpsCommand(OperationContext* txn,
                                   const std::string& dbname,
                                   const BSONObj& cmdObj) {
    AuthorizationSession* authSession = AuthorizationSession::get(txn->getClient());

    ApplyOpsValidity validity = validateApplyOpsCommand(cmdObj);
    if (validity == ApplyOpsValidity::kNeedsSuperuser) {
        std::vector<Privilege> universalPrivileges;
        RoleGraph::generateUniversalPrivileges(&universalPrivileges);
        if (!authSession->isAuthorizedForPrivileges(universalPrivileges)) {
            return Status(ErrorCodes::Unauthorized, "Unauthorized");
        }
        return Status::OK();
    }
    fassert(40314, validity == ApplyOpsValidity::kOk);

    boost::optional<DisableDocumentValidation> maybeDisableValidation;
    if (shouldBypassDocumentValidationForCommand(cmdObj))
        maybeDisableValidation.emplace(txn);


    const bool alwaysUpsert =
        cmdObj.hasField("alwaysUpsert") ? cmdObj["alwaysUpsert"].trueValue() : true;

    checkBSONType(BSONType::Array, cmdObj.firstElement());
    for (const BSONElement& e : cmdObj.firstElement().Array()) {
        checkBSONType(BSONType::Object, e);
        Status status = checkOperationAuthorization(txn, dbname, e.Obj(), alwaysUpsert);
        if (!status.isOK()) {
            return status;
        }
    }

    BSONElement preconditions = cmdObj["preCondition"];
    if (!preconditions.eoo()) {
        for (const BSONElement& precondition : preconditions.Array()) {
            checkBSONType(BSONType::Object, precondition);
            BSONElement nsElem = precondition.Obj()["ns"];
            checkBSONType(BSONType::String, nsElem);
            NamespaceString nss(nsElem.checkAndGetStringData());

            if (!authSession->isAuthorizedForActionsOnResource(
                    ResourcePattern::forExactNamespace(nss), ActionType::find)) {
                return Status(ErrorCodes::Unauthorized, "Unauthorized to check precondition");
            }
        }
    }

    return Status::OK();
}
Пример #18
0
    Status checkAuthForCommand(Client* client,
                               const std::string& dbName,
                               const BSONObj& cmdObj) const final {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);
        if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                           ActionType::inprog)) {
            return Status::OK();
        }

        if (authzSession->isAuthenticated() && cmdObj["$ownOps"].trueValue()) {
            return Status::OK();
        }

        return Status(ErrorCodes::Unauthorized, "Unauthorized");
    }
Status checkAuthForDropRoleCommand(Client* client,
                                   const std::string& dbname,
                                   const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    RoleName roleName;
    Status status = auth::parseDropRoleCommand(cmdObj, dbname, &roleName);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forDatabaseName(roleName.getDB()), ActionType::dropRole)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to drop roles from the " << roleName.getDB()
                                    << " database");
    }
    return Status::OK();
}
Status checkAuthForDropUserCommand(ClientBasic* client,
                                   const std::string& dbname,
                                   const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    UserName userName;
    BSONObj unusedWriteConcern;
    Status status =
        auth::parseAndValidateDropUserCommand(cmdObj, dbname, &userName, &unusedWriteConcern);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forDatabaseName(userName.getDB()), ActionType::dropUser)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream() << "Not authorized to drop users from the " << userName.getDB()
                                    << " database");
    }
    return Status::OK();
}
Пример #21
0
    static StatusWith<std::tuple<stdx::unique_lock<Client>, OperationContext*>> _findOp(
        ClientBasic* client, unsigned int opId) {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);

        for (ServiceContext::LockedClientsCursor cursor(client->getServiceContext());
             Client* opClient = cursor.next();) {
            stdx::unique_lock<Client> lk(*opClient);

            OperationContext* opCtx = opClient->getOperationContext();
            if (opCtx && opCtx->getOpID() == opId) {
                if (authzSession->isAuthorizedForActionsOnResource(
                        ResourcePattern::forClusterResource(), ActionType::killop) ||
                    authzSession->isCoauthorizedWithClient(opClient)) {
                    return {std::make_tuple(std::move(lk), opCtx)};
                }
                break;
            }
        }

        return Status(ErrorCodes::NoSuchKey, str::stream() << "Could not access opID: " << opId);
    }
Status checkAuthForCreateRoleCommand(ClientBasic* client,
                                     const std::string& dbname,
                                     const BSONObj& cmdObj) {
    AuthorizationSession* authzSession = AuthorizationSession::get(client);
    auth::CreateOrUpdateRoleArgs args;
    Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "createRole", dbname, &args);
    if (!status.isOK()) {
        return status;
    }

    if (!authzSession->isAuthorizedForActionsOnResource(
            ResourcePattern::forDatabaseName(args.roleName.getDB()), ActionType::createRole)) {
        return Status(ErrorCodes::Unauthorized,
                      str::stream()
                          << "Not authorized to create roles on db: " << args.roleName.getDB());
    }

    status = checkAuthorizedToGrantRoles(authzSession, args.roles);
    if (!status.isOK()) {
        return status;
    }

    return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
}
Пример #23
0
    Status checkAuthForCommand(ClientBasic* client,
                               const std::string& dbname,
                               const BSONObj& cmdObj) final {
        AuthorizationSession* authzSession = AuthorizationSession::get(client);

        if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
                                                           ActionType::killop)) {
            // If we have administrative permission to run killop, we don't need to traverse the
            // Client list to figure out if we own the operation which will be terminated.
            return Status::OK();
        }

        bool isAuthenticated =
            AuthorizationSession::get(client)->getAuthenticatedUserNames().more();
        if (isAuthenticated) {
            long long opId = parseOpId(cmdObj);
            auto swLkAndOp = _findOp(client, opId);
            if (swLkAndOp.isOK()) {
                // We were able to find the Operation, and we were authorized to interact with it.
                return Status::OK();
            }
        }
        return Status(ErrorCodes::Unauthorized, "Unauthorized");
    }
Пример #24
0
        bool handleSpecialNamespaces( Request& r , QueryMessage& q ) {
            const char * ns = strstr( r.getns() , ".$cmd.sys." );
            if ( ! ns )
                return false;
            ns += 10;

            BSONObjBuilder b;
            vector<Shard> shards;

            ClientBasic* client = ClientBasic::getCurrent();
            AuthorizationSession* authSession = client->getAuthorizationSession();
            if ( strcmp( ns , "inprog" ) == 0 ) {
                const bool isAuthorized = authSession->isAuthorizedForActionsOnResource(
                        ResourcePattern::forClusterResource(), ActionType::inprog);
                audit::logInProgAuthzCheck(
                        client, q.query, isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
                uassert(ErrorCodes::Unauthorized, "not authorized to run inprog", isAuthorized);

                Shard::getAllShards( shards );

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

                for ( unsigned i=0; i<shards.size(); i++ ) {
                    Shard shard = shards[i];
                    ScopedDbConnection conn(shard.getConnString());
                    BSONObj temp = conn->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 ) {
                const bool isAuthorized = authSession->isAuthorizedForActionsOnResource(
                        ResourcePattern::forClusterResource(), ActionType::killop);
                audit::logKillOpAuthzCheck(
                        client,
                        q.query,
                        isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
                uassert(ErrorCodes::Unauthorized, "not authorized to run killop", isAuthorized);

                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);

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

            BSONObj x = b.done();
            replyToQuery(0, r.p(), r.m(), x);
            return true;
        }