Exemplo n.º 1
0
    Privilege AuthorizationSession::_modifyPrivilegeForSpecialCases(const Privilege& privilege) {
        ActionSet newActions;
        newActions.addAllActionsFromSet(privilege.getActions());
        NamespaceString ns( privilege.getResource() );

        if (ns.coll() == "system.users") {
            if (newActions.contains(ActionType::insert) ||
                    newActions.contains(ActionType::update) ||
                    newActions.contains(ActionType::remove)) {
                // End users can't modify system.users directly, only the system can.
                newActions.addAction(ActionType::userAdminV1);
            } else {
                newActions.addAction(ActionType::userAdmin);
            }
            newActions.removeAction(ActionType::find);
            newActions.removeAction(ActionType::insert);
            newActions.removeAction(ActionType::update);
            newActions.removeAction(ActionType::remove);
        } else if (ns.coll() == "system.profile") {
            newActions.removeAction(ActionType::find);
            newActions.addAction(ActionType::profileRead);
        } else if (ns.coll() == "system.indexes" && newActions.contains(ActionType::find)) {
            newActions.removeAction(ActionType::find);
            newActions.addAction(ActionType::indexRead);
        }

        return Privilege(privilege.getResource(), newActions);
    }
Exemplo n.º 2
0
    bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) {
        AuthorizationManager& authMan = getAuthorizationManager();
        const ResourcePattern& target(privilege.getResourcePattern());

        ResourcePattern resourceSearchList[resourceSearchListCapacity];
        const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList);

        ActionSet unmetRequirements = privilege.getActions();
        UserSet::iterator it = _authenticatedUsers.begin();
        while (it != _authenticatedUsers.end()) {
            User* user = *it;

            if (!user->isValid()) {
                // Make a good faith effort to acquire an up-to-date user object, since the one
                // we've cached is marked "out-of-date."
                UserName name = user->getName();
                User* updatedUser;

                Status status = authMan.acquireUser(name, &updatedUser);
                switch (status.code()) {
                case ErrorCodes::OK: {
                    // Success! Replace the old User object with the updated one.
                    fassert(17067, _authenticatedUsers.replaceAt(it, updatedUser) == user);
                    authMan.releaseUser(user);
                    user = updatedUser;
                    LOG(1) << "Updated session cache of user information for " << name;
                    break;
                }
                case ErrorCodes::UserNotFound: {
                    // User does not exist anymore; remove it from _authenticatedUsers.
                    fassert(17068, _authenticatedUsers.removeAt(it) == user);
                    authMan.releaseUser(user);
                    LOG(1) << "Removed deleted user " << name <<
                        " from session cache of user information.";
                    continue;  // No need to advance "it" in this case.
                }
                default:
                    // Unrecognized error; assume that it's transient, and continue working with the
                    // out-of-date privilege data.
                    warning() << "Could not fetch updated user privilege information for " <<
                        name << "; continuing to use old information.  Reason is " << status;
                    break;
                }
            }

            for (int i = 0; i < resourceSearchListLength; ++i) {
                ActionSet userActions = user->getActionsForResource(resourceSearchList[i]);
                unmetRequirements.removeAllActionsFromSet(userActions);

                if (unmetRequirements.empty())
                    return true;
            }
            ++it;
        }

        return false;
    }
Exemplo n.º 3
0
void User::addPrivilege(const Privilege& privilegeToAdd) {
    ResourcePrivilegeMap::iterator it = _privileges.find(privilegeToAdd.getResourcePattern());
    if (it == _privileges.end()) {
        // No privilege exists yet for this resource
        _privileges.insert(std::make_pair(privilegeToAdd.getResourcePattern(), privilegeToAdd));
    } else {
        dassert(it->first == privilegeToAdd.getResourcePattern());
        it->second.addActions(privilegeToAdd.getActions());
    }
}
Exemplo n.º 4
0
 void Privilege::addPrivilegeToPrivilegeVector(PrivilegeVector* privileges,
                                               const Privilege& privilegeToAdd) {
     for (PrivilegeVector::iterator it = privileges->begin(); it != privileges->end(); ++it) {
         if (it->getResourcePattern() == privilegeToAdd.getResourcePattern()) {
             it->addActions(privilegeToAdd.getActions());
             return;
         }
     }
     // No privilege exists yet for this resource
     privileges->push_back(privilegeToAdd);
 }
    bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) {
        const ResourcePattern& target(privilege.getResourcePattern());

        ResourcePattern resourceSearchList[resourceSearchListCapacity];
        const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList);

        ActionSet unmetRequirements = privilege.getActions();

        for (UserSet::iterator it = _authenticatedUsers.begin();
                it != _authenticatedUsers.end(); ++it) {
            User* user = *it;

            if (user->getSchemaVersion() == AuthorizationManager::schemaVersion24 &&
                (target.isDatabasePattern() || target.isExactNamespacePattern()) &&
                !user->hasProbedV1(target.databaseToMatch())) {

                UserName name = user->getName();
                User* updatedUser;
                Status status = getAuthorizationManager().acquireV1UserProbedForDb(
                        name,
                        target.databaseToMatch(),
                        &updatedUser);
                if (status.isOK()) {
                    if (user != updatedUser) {
                        LOG(1) << "Updated session cache with privileges on the " <<
                                target.databaseToMatch() << " database for V1 user " << name;
                        fassert(17226, _authenticatedUsers.replaceAt(it, updatedUser) == user);
                    }
                    getAuthorizationManager().releaseUser(user);
                    user = updatedUser;
                }
                else if (status != ErrorCodes::UserNotFound) {
                    warning() << "Could not fetch updated user privilege information for V1-style "
                        "user " << name << "; continuing to use old information.  Reason is "
                              << status;
                }
            }

            for (int i = 0; i < resourceSearchListLength; ++i) {
                ActionSet userActions = user->getActionsForResource(resourceSearchList[i]);
                unmetRequirements.removeAllActionsFromSet(userActions);

                if (unmetRequirements.empty())
                    return true;
            }
        }

        return false;
    }
Exemplo n.º 6
0
    Privilege AuthorizationManager::_modifyPrivilegeForSpecialCases(const Privilege& privilege) {
        ActionSet newActions;
        newActions.addAllActionsFromSet(privilege.getActions());
        std::string collectionName = NamespaceString(privilege.getResource()).coll;
        if (collectionName == "system.users") {
            newActions.removeAction(ActionType::find);
            newActions.removeAction(ActionType::insert);
            newActions.removeAction(ActionType::update);
            newActions.removeAction(ActionType::remove);
            newActions.addAction(ActionType::userAdmin);
        } else if (collectionName == "system.profle" && newActions.contains(ActionType::find)) {
            newActions.removeAction(ActionType::find);
            newActions.addAction(ActionType::profileRead);
        }

        return Privilege(privilege.getResource(), newActions);
    }
Exemplo n.º 7
0
    bool PrivilegeSet::hasPrivilege(const Privilege& desiredPrivilege) {
        if (desiredPrivilege.getActions().empty())
            return true;

        StringData resourceSearchList[2];
        resourceSearchList[0] = WILDCARD_RESOURCE;
        resourceSearchList[1] = desiredPrivilege.getResource();

        ActionSet unmetRequirements = desiredPrivilege.getActions();
        for (int i = 0; i < boost::size(resourceSearchList); ++i) {
            ResourcePrivilegeCacheEntry* entry = _lookupEntry(resourceSearchList[i]);
            if (NULL == entry)
                continue;
            if (entry->dirty)
                _rebuildEntry(resourceSearchList[i], entry);
            unmetRequirements.removeAllActionsFromSet(entry->actions);
            if (unmetRequirements.empty())
                return true;
        }
        return false;
    }
Exemplo n.º 8
0
    Status AuthorizationManager::_probeForPrivilege(const Privilege& privilege) {
        Privilege modifiedPrivilege = _modifyPrivilegeForSpecialCases(privilege);
        if (_acquiredPrivileges.hasPrivilege(modifiedPrivilege))
            return Status::OK();

        std::string dbname = nsToDatabase(modifiedPrivilege.getResource());
        for (PrincipalSet::iterator iter = _authenticatedPrincipals.begin(),
                 end = _authenticatedPrincipals.end();
             iter != end; ++iter) {

            Principal* principal = *iter;
            if (!principal->isImplicitPrivilegeAcquisitionEnabled())
                continue;
            if (principal->isDatabaseProbed(dbname))
                continue;
            _acquirePrivilegesForPrincipalFromDatabase(dbname, principal->getName());
            principal->markDatabaseAsProbed(dbname);
            if (_acquiredPrivileges.hasPrivilege(modifiedPrivilege))
                return Status::OK();
        }
        return Status(ErrorCodes::Unauthorized, "unauthorized", 0);
    }
Exemplo n.º 9
0
bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) {
    const ResourcePattern& target(privilege.getResourcePattern());

    ResourcePattern resourceSearchList[resourceSearchListCapacity];
    const int resourceSearchListLength = buildResourceSearchList(target, resourceSearchList);

    ActionSet unmetRequirements = privilege.getActions();

    PrivilegeVector defaultPrivileges = getDefaultPrivileges();
    for (PrivilegeVector::iterator it = defaultPrivileges.begin(); it != defaultPrivileges.end();
         ++it) {
        for (int i = 0; i < resourceSearchListLength; ++i) {
            if (!(it->getResourcePattern() == resourceSearchList[i]))
                continue;

            ActionSet userActions = it->getActions();
            unmetRequirements.removeAllActionsFromSet(userActions);

            if (unmetRequirements.empty())
                return true;
        }
    }

    for (UserSet::iterator it = _authenticatedUsers.begin(); it != _authenticatedUsers.end();
         ++it) {
        User* user = *it;
        for (int i = 0; i < resourceSearchListLength; ++i) {
            ActionSet userActions = user->getActionsForResource(resourceSearchList[i]);
            unmetRequirements.removeAllActionsFromSet(userActions);

            if (unmetRequirements.empty())
                return true;
        }
    }

    return false;
}
Exemplo n.º 10
0
Status AuthorizationSession::checkAuthorizedToRevokePrivilege(const Privilege& privilege) {
    const ResourcePattern& resource = privilege.getResourcePattern();
    if (resource.isDatabasePattern() || resource.isExactNamespacePattern()) {
        if (!isAuthorizedForActionsOnResource(
                ResourcePattern::forDatabaseName(resource.databaseToMatch()),
                ActionType::revokeRole)) {
            return Status(ErrorCodes::Unauthorized,
                          str::stream() << "Not authorized to revoke privileges on the "
                                        << resource.databaseToMatch() << "database");
        }
    } else if (!isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName("admin"),
                                                 ActionType::revokeRole)) {
        return Status(ErrorCodes::Unauthorized,
                      "To revoke privileges affecting multiple databases or the cluster,"
                      " must be authorized to revoke roles from the admin database");
    }
    return Status::OK();
}
Exemplo n.º 11
0
Status RoleGraph::removePrivilegeFromRole(const RoleName& role,
                                          const Privilege& privilegeToRemove) {
    if (!roleExists(role)) {
        return Status(ErrorCodes::RoleNotFound,
                      mongoutils::str::stream() << "Role: " << role.getFullName()
                                                << " does not exist",
                      0);
    }
    if (isBuiltinRole(role)) {
        return Status(ErrorCodes::InvalidRoleModification,
                      mongoutils::str::stream() << "Cannot remove privileges from built-in role: "
                                                << role.getFullName());
    }

    PrivilegeVector& currentPrivileges = _directPrivilegesForRole[role];
    for (PrivilegeVector::iterator it = currentPrivileges.begin(); it != currentPrivileges.end();
         ++it) {
        Privilege& curPrivilege = *it;
        if (curPrivilege.getResourcePattern() == privilegeToRemove.getResourcePattern()) {
            ActionSet curActions = curPrivilege.getActions();

            if (!curActions.isSupersetOf(privilegeToRemove.getActions())) {
                // Didn't possess all the actions being removed.
                return Status(
                    ErrorCodes::PrivilegeNotFound,
                    mongoutils::str::stream() << "Role: " << role.getFullName()
                                              << " does not contain a privilege on "
                                              << privilegeToRemove.getResourcePattern().toString()
                                              << " with actions: "
                                              << privilegeToRemove.getActions().toString(),
                    0);
            }

            curPrivilege.removeActions(privilegeToRemove.getActions());
            if (curPrivilege.getActions().empty()) {
                currentPrivileges.erase(it);
            }
            return Status::OK();
        }
    }
    return Status(ErrorCodes::PrivilegeNotFound,
                  mongoutils::str::stream() << "Role: " << role.getFullName()
                                            << " does not "
                                               "contain any privileges on "
                                            << privilegeToRemove.getResourcePattern().toString(),
                  0);
}
Exemplo n.º 12
0
    Status AuthorizationSession::_checkAuthForPrivilegeHelper(const Privilege& privilege) {
        AuthorizationManager& authMan = getAuthorizationManager();
        Privilege modifiedPrivilege = _modifyPrivilegeForSpecialCases(privilege);

        // Need to check not just the resource of the privilege, but also just the database
        // component and the "*" resource.
        std::string resourceSearchList[3];
        resourceSearchList[0] = AuthorizationManager::WILDCARD_RESOURCE_NAME;
        resourceSearchList[1] = nsToDatabase(modifiedPrivilege.getResource());
        resourceSearchList[2] = modifiedPrivilege.getResource();


        ActionSet unmetRequirements = modifiedPrivilege.getActions();
        UserSet::iterator it = _authenticatedUsers.begin();
        while (it != _authenticatedUsers.end()) {
            User* user = *it;

            if (!user->isValid()) {
                // Make a good faith effort to acquire an up-to-date user object, since the one
                // we've cached is marked "out-of-date."
                UserName name = user->getName();
                User* updatedUser;

                Status status = authMan.acquireUser(name, &updatedUser);
                switch (status.code()) {
                case ErrorCodes::OK: {
                    // Success! Replace the old User object with the updated one.
                    fassert(17067, _authenticatedUsers.replaceAt(it, updatedUser) == user);
                    authMan.releaseUser(user);
                    user = updatedUser;
                    LOG(1) << "Updated session cache of user information for " << name;
                    break;
                }
                case ErrorCodes::UserNotFound: {
                    // User does not exist anymore; remove it from _authenticatedUsers.
                    fassert(17068, _authenticatedUsers.removeAt(it) == user);
                    authMan.releaseUser(user);
                    LOG(1) << "Removed deleted user " << name <<
                        " from session cache of user information.";
                    continue;  // No need to advance "it" in this case.
                }
                default:
                    // Unrecognized error; assume that it's transient, and continue working with the
                    // out-of-date privilege data.
                    warning() << "Could not fetch updated user privilege information for " <<
                        name << "; continuing to use old information.  Reason is " << status;
                    break;
                }
            }

            for (int i = 0; i < static_cast<int>(boost::size(resourceSearchList)); ++i) {
                ActionSet userActions = user->getActionsForResource(resourceSearchList[i]);
                unmetRequirements.removeAllActionsFromSet(userActions);

                if (unmetRequirements.empty())
                    return Status::OK();
            }
            ++it;
        }

        return Status(ErrorCodes::Unauthorized, "unauthorized");
    }
Exemplo n.º 13
0
bool ParsedPrivilege::privilegeToParsedPrivilege(const Privilege& privilege,
                                                 ParsedPrivilege* result,
                                                 std::string* errmsg) {
    ParsedResource parsedResource;
    if (privilege.getResourcePattern().isExactNamespacePattern()) {
        parsedResource.setDb(privilege.getResourcePattern().databaseToMatch());
        parsedResource.setCollection(privilege.getResourcePattern().collectionToMatch());
    } else if (privilege.getResourcePattern().isDatabasePattern()) {
        parsedResource.setDb(privilege.getResourcePattern().databaseToMatch());
        parsedResource.setCollection("");
    } else if (privilege.getResourcePattern().isCollectionPattern()) {
        parsedResource.setDb("");
        parsedResource.setCollection(privilege.getResourcePattern().collectionToMatch());
    } else if (privilege.getResourcePattern().isAnyNormalResourcePattern()) {
        parsedResource.setDb("");
        parsedResource.setCollection("");
    } else if (privilege.getResourcePattern().isClusterResourcePattern()) {
        parsedResource.setCluster(true);
    } else if (privilege.getResourcePattern().isAnyResourcePattern()) {
        parsedResource.setAnyResource(true);
    } else {
        *errmsg = stream() << privilege.getResourcePattern().toString()
                           << " is not a valid user-grantable resource pattern";
        return false;
    }

    result->clear();
    result->setResource(parsedResource);
    result->setActions(privilege.getActions().getActionsAsStrings());
    return result->isValid(errmsg);
}