diff options
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r-- | src/mongo/db/auth/action_set.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/auth/action_set.h | 4 | ||||
-rw-r--r-- | src/mongo/db/auth/privilege_parser.cpp | 36 | ||||
-rw-r--r-- | src/mongo/db/auth/privilege_parser.h | 12 | ||||
-rw-r--r-- | src/mongo/db/auth/privilege_parser_test.cpp | 68 | ||||
-rw-r--r-- | src/mongo/db/auth/resource_pattern.h | 37 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.cpp | 2 |
7 files changed, 157 insertions, 13 deletions
diff --git a/src/mongo/db/auth/action_set.cpp b/src/mongo/db/auth/action_set.cpp index b7c17ae1996..e1f38a7746b 100644 --- a/src/mongo/db/auth/action_set.cpp +++ b/src/mongo/db/auth/action_set.cpp @@ -94,4 +94,15 @@ namespace mongo { return str.str(); } + std::vector<std::string> ActionSet::getActionsAsStrings() const { + std::vector<std::string> result; + for (int i = 0; i < ActionType::actionTypeEndValue; i++) { + ActionType action(i); + if (contains(action)) { + result.push_back(ActionType::actionToString(action)); + } + } + return result; + } + } // namespace mongo diff --git a/src/mongo/db/auth/action_set.h b/src/mongo/db/auth/action_set.h index 09cb1128341..ea1cab59017 100644 --- a/src/mongo/db/auth/action_set.h +++ b/src/mongo/db/auth/action_set.h @@ -16,6 +16,7 @@ #pragma once #include <bitset> +#include <vector> #include "mongo/base/status.h" #include "mongo/db/auth/action_type.h" @@ -52,6 +53,9 @@ namespace mongo { // Returns the string representation of this ActionSet std::string toString() const; + // Returns a vector of strings representing the actions in the ActionSet. + std::vector<std::string> getActionsAsStrings() const; + // Takes a comma-separated string of action type string representations and returns // an int bitmask of the actions. static Status parseActionSetFromString(const std::string& actionsString, ActionSet* result); diff --git a/src/mongo/db/auth/privilege_parser.cpp b/src/mongo/db/auth/privilege_parser.cpp index 7cdcb92f0aa..e7d1def99df 100644 --- a/src/mongo/db/auth/privilege_parser.cpp +++ b/src/mongo/db/auth/privilege_parser.cpp @@ -333,9 +333,9 @@ namespace mongo { return _resource; } - bool ParsedPrivilege::buildPrivilege(const ParsedPrivilege& parsedPrivilege, - Privilege* result, - std::string* errmsg) { + bool ParsedPrivilege::parsedPrivilegeToPrivilege(const ParsedPrivilege& parsedPrivilege, + Privilege* result, + std::string* errmsg) { if (!parsedPrivilege.isValid(errmsg)) { return false; } @@ -380,4 +380,34 @@ namespace mongo { *result = Privilege(resource, actions); return true; } + + 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 { + *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); + } } // namespace mongo diff --git a/src/mongo/db/auth/privilege_parser.h b/src/mongo/db/auth/privilege_parser.h index 4e28fec8493..235f6db12eb 100644 --- a/src/mongo/db/auth/privilege_parser.h +++ b/src/mongo/db/auth/privilege_parser.h @@ -122,9 +122,15 @@ namespace mongo { /** * Takes a parsedPrivilege and turns it into a true Privilege object. */ - static bool buildPrivilege(const ParsedPrivilege& parsedPrivilege, - Privilege* result, - std::string* errmsg); + static bool parsedPrivilegeToPrivilege(const ParsedPrivilege& parsedPrivilege, + Privilege* result, + std::string* errmsg); + /** + * Takes a Privilege object and turns it into a ParsedPrivilege. + */ + static bool privilegeToParsedPrivilege(const Privilege& privilege, + ParsedPrivilege* result, + std::string* errmsg); /** Copies all the fields present in 'this' to 'other'. */ void cloneTo(ParsedPrivilege* other) const; diff --git a/src/mongo/db/auth/privilege_parser_test.cpp b/src/mongo/db/auth/privilege_parser_test.cpp index 856772e3889..6f91f03cf66 100644 --- a/src/mongo/db/auth/privilege_parser_test.cpp +++ b/src/mongo/db/auth/privilege_parser_test.cpp @@ -97,64 +97,120 @@ namespace { ASSERT(parsedPrivilege.isValid(&errmsg)); } - TEST(PrivilegeParserTest, BuildPrivilegeTest) { + TEST(PrivilegeParserTest, ConvertBetweenPrivilegeTest) { ParsedPrivilege parsedPrivilege; Privilege privilege; std::string errmsg; + std::vector<std::string> actionsVector; + actionsVector.push_back("find"); // Works with wildcard db and resource parsedPrivilege.parseBSON(BSON("resource" << BSON("db" << "" << "collection" << "") << "actions" << BSON_ARRAY("find")), &errmsg); ASSERT(parsedPrivilege.isValid(&errmsg)); - ASSERT(ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)); + ASSERT(ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)); ASSERT(privilege.getActions().contains(ActionType::find)); ASSERT(!privilege.getActions().contains(ActionType::insert)); ASSERT_EQUALS(privilege.getResourcePattern(), ResourcePattern::forAnyNormalResource()); + ASSERT(ParsedPrivilege::privilegeToParsedPrivilege(privilege, &parsedPrivilege, &errmsg)); + ASSERT(parsedPrivilege.isValid(&errmsg)); + ASSERT(parsedPrivilege.isResourceSet()); + ASSERT_FALSE(parsedPrivilege.getResource().isClusterSet()); + ASSERT(parsedPrivilege.getResource().isDbSet()); + ASSERT(parsedPrivilege.getResource().isCollectionSet()); + ASSERT_EQUALS("", parsedPrivilege.getResource().getDb()); + ASSERT_EQUALS("", parsedPrivilege.getResource().getCollection()); + ASSERT(parsedPrivilege.isActionsSet()); + ASSERT(actionsVector == parsedPrivilege.getActions()); + // Works with exact namespaces parsedPrivilege.parseBSON(BSON("resource" << BSON("db" << "test" << "collection" << "foo") << "actions" << BSON_ARRAY("find")), &errmsg); ASSERT(parsedPrivilege.isValid(&errmsg)); - ASSERT(ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)); + ASSERT(ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)); ASSERT(privilege.getActions().contains(ActionType::find)); ASSERT(!privilege.getActions().contains(ActionType::insert)); ASSERT_EQUALS(privilege.getResourcePattern(), ResourcePattern::forExactNamespace(NamespaceString("test.foo"))); + ASSERT(ParsedPrivilege::privilegeToParsedPrivilege(privilege, &parsedPrivilege, &errmsg)); + ASSERT(parsedPrivilege.isValid(&errmsg)); + ASSERT(parsedPrivilege.isResourceSet()); + ASSERT_FALSE(parsedPrivilege.getResource().isClusterSet()); + ASSERT(parsedPrivilege.getResource().isDbSet()); + ASSERT(parsedPrivilege.getResource().isCollectionSet()); + ASSERT_EQUALS("test", parsedPrivilege.getResource().getDb()); + ASSERT_EQUALS("foo", parsedPrivilege.getResource().getCollection()); + ASSERT(parsedPrivilege.isActionsSet()); + ASSERT(actionsVector == parsedPrivilege.getActions()); + // Works with database resource parsedPrivilege.parseBSON(BSON("resource" << BSON("db" << "test" << "collection" << "") << "actions" << BSON_ARRAY("find")), &errmsg); ASSERT(parsedPrivilege.isValid(&errmsg)); - ASSERT(ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)); + ASSERT(ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)); ASSERT(privilege.getActions().contains(ActionType::find)); ASSERT(!privilege.getActions().contains(ActionType::insert)); ASSERT_EQUALS(privilege.getResourcePattern(), ResourcePattern::forDatabaseName("test")); + ASSERT(ParsedPrivilege::privilegeToParsedPrivilege(privilege, &parsedPrivilege, &errmsg)); + ASSERT(parsedPrivilege.isValid(&errmsg)); + ASSERT(parsedPrivilege.isResourceSet()); + ASSERT_FALSE(parsedPrivilege.getResource().isClusterSet()); + ASSERT(parsedPrivilege.getResource().isDbSet()); + ASSERT(parsedPrivilege.getResource().isCollectionSet()); + ASSERT_EQUALS("test", parsedPrivilege.getResource().getDb()); + ASSERT_EQUALS("", parsedPrivilege.getResource().getCollection()); + ASSERT(parsedPrivilege.isActionsSet()); + ASSERT(actionsVector == parsedPrivilege.getActions()); + // Works with collection resource parsedPrivilege.parseBSON(BSON("resource" << BSON("db" << "" << "collection" << "foo") << "actions" << BSON_ARRAY("find")), &errmsg); ASSERT(parsedPrivilege.isValid(&errmsg)); - ASSERT(ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)); + ASSERT(ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)); ASSERT(privilege.getActions().contains(ActionType::find)); ASSERT(!privilege.getActions().contains(ActionType::insert)); ASSERT_EQUALS(privilege.getResourcePattern(), ResourcePattern::forCollectionName("foo")); + ASSERT(ParsedPrivilege::privilegeToParsedPrivilege(privilege, &parsedPrivilege, &errmsg)); + ASSERT(parsedPrivilege.isValid(&errmsg)); + ASSERT(parsedPrivilege.isResourceSet()); + ASSERT_FALSE(parsedPrivilege.getResource().isClusterSet()); + ASSERT(parsedPrivilege.getResource().isDbSet()); + ASSERT(parsedPrivilege.getResource().isCollectionSet()); + ASSERT_EQUALS("", parsedPrivilege.getResource().getDb()); + ASSERT_EQUALS("foo", parsedPrivilege.getResource().getCollection()); + ASSERT(parsedPrivilege.isActionsSet()); + ASSERT(actionsVector == parsedPrivilege.getActions()); + // Works with cluster resource parsedPrivilege.parseBSON(BSON("resource" << BSON("cluster" << true) << "actions" << BSON_ARRAY("find")), &errmsg); ASSERT(parsedPrivilege.isValid(&errmsg)); - ASSERT(ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)); + ASSERT(ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)); ASSERT(privilege.getActions().contains(ActionType::find)); ASSERT(!privilege.getActions().contains(ActionType::insert)); ASSERT_EQUALS(privilege.getResourcePattern(), ResourcePattern::forClusterResource()); + + ASSERT(ParsedPrivilege::privilegeToParsedPrivilege(privilege, &parsedPrivilege, &errmsg)); + ASSERT(parsedPrivilege.isValid(&errmsg)); + ASSERT(parsedPrivilege.isResourceSet()); + ASSERT(parsedPrivilege.getResource().isClusterSet()); + ASSERT(parsedPrivilege.getResource().getCluster()); + ASSERT_FALSE(parsedPrivilege.getResource().isDbSet()); + ASSERT_FALSE(parsedPrivilege.getResource().isCollectionSet()); + ASSERT(parsedPrivilege.isActionsSet()); + ASSERT(actionsVector == parsedPrivilege.getActions()); } } // namespace diff --git a/src/mongo/db/auth/resource_pattern.h b/src/mongo/db/auth/resource_pattern.h index ba04e382e00..24bc1020301 100644 --- a/src/mongo/db/auth/resource_pattern.h +++ b/src/mongo/db/auth/resource_pattern.h @@ -98,6 +98,27 @@ namespace mongo { } /** + * Returns true if this pattern matches on the collection name only. + */ + bool isCollectionPattern() const { + return _matchType == matchCollectionName; + } + + /** + * Returns true if this pattern matches the cluster resource only. + */ + bool isClusterResourcePattern() const { + return _matchType == matchClusterResource; + } + + /** + * Returns true if this pattern matches only any normal resource. + */ + bool isAnyNormalResourcePattern() const { + return _matchType == matchAnyNormalResource; + } + + /** * Returns true if this pattern matches nothing at all. */ bool matchesNothing() const { return matchNever == _matchType; } @@ -155,6 +176,22 @@ namespace mongo { */ const NamespaceString& ns() const { return _ns; } + /** + * Returns the database that this pattern matches. + * + * Behavior is undefined unless the pattern is of type matchDatabaseName or + * matchExactNamespace + */ + StringData databaseToMatch() const { return _ns.db(); } + + /** + * Returns the collection that this pattern matches. + * + * Behavior is undefined unless the pattern is of type matchCollectionName or + * matchExactNamespace + */ + StringData collectionToMatch() const { return _ns.coll(); } + std::string toString() const; inline size_t hash() const { diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index 3fe5f107621..7f7c1fe04d4 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -553,7 +553,7 @@ namespace auth { } Privilege privilege; - if (!ParsedPrivilege::buildPrivilege(parsedPrivilege, &privilege, &errmsg)) { + if (!ParsedPrivilege::parsedPrivilegeToPrivilege(parsedPrivilege, &privilege, &errmsg)) { return Status(ErrorCodes::FailedToParse, errmsg); } |