summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2020-01-15 16:30:37 +0000
committerSpencer Jackson <spencer.jackson@mongodb.com>2020-01-15 15:42:20 -0500
commita10d0a22d5d009d27664967181042933ec1bef36 (patch)
tree729a3622da26c8adc76207a7366a3440bd85f32c
parentd0e18b320827819ee08efb7f8d65e9abd5f28d4f (diff)
downloadmongo-a10d0a22d5d009d27664967181042933ec1bef36.tar.gz
SERVER-45472 Ensure RoleGraph can serialize authentication restrictions to BSON
(cherry picked from commit 521e56b407ac72bc69a97a24d1253f51a5b6e81b)
-rw-r--r--jstests/auth/authentication_restrictions_role.js8
-rw-r--r--src/mongo/db/auth/role_graph.cpp9
-rw-r--r--src/mongo/db/auth/role_graph_test.cpp36
3 files changed, 52 insertions, 1 deletions
diff --git a/jstests/auth/authentication_restrictions_role.js b/jstests/auth/authentication_restrictions_role.js
index 70256fba7f5..9e7ed765c2f 100644
--- a/jstests/auth/authentication_restrictions_role.js
+++ b/jstests/auth/authentication_restrictions_role.js
@@ -42,6 +42,14 @@ function testRestrictionCreationAndEnforcement(
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 b05a29fff4d..99c92d8d4b6 100644
--- a/src/mongo/db/auth/role_graph.cpp
+++ b/src/mongo/db/auth/role_graph.cpp
@@ -575,6 +575,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 765d3d3c61c..694a6b1884b 100644
--- a/src/mongo/db/auth/role_graph_test.cpp
+++ b/src/mongo/db/auth/role_graph_test.cpp
@@ -34,6 +34,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/sequence_util.h"
@@ -47,16 +48,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(
@@ -65,6 +71,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());
@@ -77,6 +84,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());
@@ -88,7 +97,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());
@@ -103,6 +112,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());
@@ -127,6 +138,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());
@@ -139,6 +152,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