diff options
author | Spencer Jackson <spencer.jackson@mongodb.com> | 2020-01-15 16:30:37 +0000 |
---|---|---|
committer | Spencer Jackson <spencer.jackson@mongodb.com> | 2020-01-15 19:25:51 -0500 |
commit | fb87cc88ecb5d300f14cda7bc238d7d5132118f5 (patch) | |
tree | 9eeca0696fc271314e1e69d9a8ad647002f1f08b | |
parent | c742b66899f2942788d959b048d9b580130781e9 (diff) | |
download | mongo-fb87cc88ecb5d300f14cda7bc238d7d5132118f5.tar.gz |
SERVER-45472 Ensure RoleGraph can serialize authentication restrictions to BSON
(cherry picked from commit 521e56b407ac72bc69a97a24d1253f51a5b6e81b)
(cherry picked from commit a10d0a22d5d009d27664967181042933ec1bef36)
-rw-r--r-- | jstests/auth/authentication_restrictions_role.js | 8 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph_test.cpp | 36 |
3 files changed, 52 insertions, 1 deletions
diff --git a/jstests/auth/authentication_restrictions_role.js b/jstests/auth/authentication_restrictions_role.js index 3f23cfdcb92..691491a0765 100644 --- a/jstests/auth/authentication_restrictions_role.js +++ b/jstests/auth/authentication_restrictions_role.js @@ -42,6 +42,14 @@ assert.commandWorked(admin.runCommand({createRole: "role3", roles: [], privileges: []})); print("=== Role creation tests"); + print("When a role is updated, it retains authenticationRestrictions"); + assert.commandWorked(admin.runCommand({updateRole: "role2", roles: ["root"]})); + const role2Info = assert.commandWorked( + admin.runCommand({rolesInfo: "role2", showAuthenticationRestrictions: true})); + printjson(role2Info); + assert.eq(JSON.stringify([[{clientSource: ["127.0.0.1/32"]}]]), + JSON.stringify(role2Info.roles[0].authenticationRestrictions)); + print( "When a client creates roles with empty authenticationRestrictions, the operation succeeds, though it has no effect"); assert.commandWorked(admin.runCommand( diff --git a/src/mongo/db/auth/role_graph.cpp b/src/mongo/db/auth/role_graph.cpp index fc55b6a1d43..03776361e3c 100644 --- a/src/mongo/db/auth/role_graph.cpp +++ b/src/mongo/db/auth/role_graph.cpp @@ -590,6 +590,15 @@ Status RoleGraph::getBSONForRole(RoleGraph* graph, uassertStatusOK(rolesArrayElement.pushBack(roleObj)); } + // Build authentication restrictions + auto restrictions = graph->getDirectAuthenticationRestrictions(roleName); + mutablebson::Element authenticationRestrictionsElement = + result.getDocument().makeElementArray("authenticationRestrictions"); + uassertStatusOK(result.pushBack(authenticationRestrictionsElement)); + if (restrictions) { + uassertStatusOK(authenticationRestrictionsElement.setValueArray(restrictions->toBSON())); + } + return Status::OK(); } catch (...) { return exceptionToStatus(); diff --git a/src/mongo/db/auth/role_graph_test.cpp b/src/mongo/db/auth/role_graph_test.cpp index 0e22892f4eb..e763b0929f9 100644 --- a/src/mongo/db/auth/role_graph_test.cpp +++ b/src/mongo/db/auth/role_graph_test.cpp @@ -35,6 +35,7 @@ #include <algorithm> #include "mongo/bson/mutable/document.h" +#include "mongo/db/auth/address_restriction.h" #include "mongo/db/auth/role_graph.h" #include "mongo/unittest/unittest.h" #include "mongo/util/mongoutils/str.h" @@ -48,16 +49,21 @@ TEST(RoleParsingTest, BuildRoleBSON) { RoleName roleA("roleA", "dbA"); RoleName roleB("roleB", "dbB"); RoleName roleC("roleC", "dbC"); + RoleName roleD("roleD", "dbD"); ActionSet actions; actions.addAction(ActionType::find); actions.addAction(ActionType::insert); + SharedRestrictionDocument restrictions = uassertStatusOK(parseAuthenticationRestriction( + BSON_ARRAY(BSON("clientSource" << BSON_ARRAY("127.0.0.1"))))); ASSERT_OK(graph.createRole(roleA)); ASSERT_OK(graph.createRole(roleB)); ASSERT_OK(graph.createRole(roleC)); + ASSERT_OK(graph.createRole(roleD)); ASSERT_OK(graph.addRoleToRole(roleA, roleC)); ASSERT_OK(graph.addRoleToRole(roleA, roleB)); + ASSERT_OK(graph.addRoleToRole(roleA, roleD)); ASSERT_OK(graph.addRoleToRole(roleB, roleC)); ASSERT_OK(graph.addPrivilegeToRole( @@ -66,6 +72,7 @@ TEST(RoleParsingTest, BuildRoleBSON) { roleB, Privilege(ResourcePattern::forExactNamespace(NamespaceString("dbB.foo")), actions))); ASSERT_OK( graph.addPrivilegeToRole(roleC, Privilege(ResourcePattern::forClusterResource(), actions))); + ASSERT_OK(graph.replaceRestrictionsForRole(roleD, restrictions)); ASSERT_OK(graph.recomputePrivilegeData()); @@ -78,6 +85,8 @@ TEST(RoleParsingTest, BuildRoleBSON) { ASSERT_EQUALS("roleA", roleDoc["role"].String()); ASSERT_EQUALS("dbA", roleDoc["db"].String()); + ASSERT_TRUE(roleDoc["authenticationRestrictions"].Array().empty()); + std::vector<BSONElement> privs = roleDoc["privileges"].Array(); ASSERT_EQUALS(1U, privs.size()); ASSERT_EQUALS("", privs[0].Obj()["resource"].Obj()["db"].String()); @@ -89,7 +98,7 @@ TEST(RoleParsingTest, BuildRoleBSON) { ASSERT_EQUALS("insert", actionElements[1].String()); std::vector<BSONElement> roles = roleDoc["roles"].Array(); - ASSERT_EQUALS(2U, roles.size()); + ASSERT_EQUALS(3U, roles.size()); ASSERT_EQUALS("roleC", roles[0].Obj()["role"].String()); ASSERT_EQUALS("dbC", roles[0].Obj()["db"].String()); ASSERT_EQUALS("roleB", roles[1].Obj()["role"].String()); @@ -104,6 +113,8 @@ TEST(RoleParsingTest, BuildRoleBSON) { ASSERT_EQUALS("roleB", roleDoc["role"].String()); ASSERT_EQUALS("dbB", roleDoc["db"].String()); + ASSERT_TRUE(roleDoc["authenticationRestrictions"].Array().empty()); + privs = roleDoc["privileges"].Array(); ASSERT_EQUALS(1U, privs.size()); ASSERT_EQUALS("dbB", privs[0].Obj()["resource"].Obj()["db"].String()); @@ -128,6 +139,8 @@ TEST(RoleParsingTest, BuildRoleBSON) { ASSERT_EQUALS("roleC", roleDoc["role"].String()); ASSERT_EQUALS("dbC", roleDoc["db"].String()); + ASSERT_TRUE(roleDoc["authenticationRestrictions"].Array().empty()); + privs = roleDoc["privileges"].Array(); ASSERT_EQUALS(1U, privs.size()); ASSERT(privs[0].Obj()["resource"].Obj()["cluster"].Bool()); @@ -140,6 +153,27 @@ TEST(RoleParsingTest, BuildRoleBSON) { roles = roleDoc["roles"].Array(); ASSERT_EQUALS(0U, roles.size()); + + // Role D + doc.reset(); + ASSERT_OK(RoleGraph::getBSONForRole(&graph, roleD, doc.root())); + roleDoc = doc.getObject(); + + ASSERT_EQUALS("dbD.roleD", roleDoc["_id"].String()); + ASSERT_EQUALS("roleD", roleDoc["role"].String()); + ASSERT_EQUALS("dbD", roleDoc["db"].String()); + + ASSERT_FALSE(roleDoc["authenticationRestrictions"].Array().empty()); + auto restrictionObj = BSONArray(roleDoc["authenticationRestrictions"].Obj()); + SharedRestrictionDocument parsedRestrictions = + uassertStatusOK(parseAuthenticationRestriction(restrictionObj)); + ASSERT_EQ(restrictions->toString(), parsedRestrictions->toString()); + + privs = roleDoc["privileges"].Array(); + ASSERT_TRUE(privs.empty()); + + roles = roleDoc["roles"].Array(); + ASSERT_EQUALS(0U, roles.size()); } // Tests adding and removing roles from other roles, the RoleNameIterator, and the |