|
60 | 60 | namespace mongo {
|
61 | 61 | namespace {
|
62 | 62 |
|
| 63 | +using ResolveRoleOption = AuthorizationManager::ResolveRoleOption; |
| 64 | + |
63 | 65 | #ifdef MONGO_CONFIG_SSL
|
64 | 66 | // Construct a simple, structured X509 name equivalent to "CN=mongodb.com"
|
65 | 67 | SSLX509Name buildX509Name() {
|
@@ -113,32 +115,32 @@ class AuthorizationManagerTest : public ServiceContextTest {
|
113 | 115 | };
|
114 | 116 |
|
115 | 117 | TEST_F(AuthorizationManagerTest, testAcquireV2User) {
|
116 |
| - ASSERT_OK(externalState->insertPrivilegeDocument(opCtx.get(), |
117 |
| - BSON("_id" |
118 |
| - << "admin.v2read" |
119 |
| - << "user" |
120 |
| - << "v2read" |
121 |
| - << "db" |
122 |
| - << "test" |
123 |
| - << "credentials" << credentials << "roles" |
124 |
| - << BSON_ARRAY(BSON("role" |
125 |
| - << "read" |
126 |
| - << "db" |
127 |
| - << "test"))), |
128 |
| - BSONObj())); |
129 |
| - ASSERT_OK(externalState->insertPrivilegeDocument(opCtx.get(), |
130 |
| - BSON("_id" |
131 |
| - << "admin.v2cluster" |
132 |
| - << "user" |
133 |
| - << "v2cluster" |
134 |
| - << "db" |
135 |
| - << "admin" |
136 |
| - << "credentials" << credentials << "roles" |
137 |
| - << BSON_ARRAY(BSON("role" |
138 |
| - << "clusterAdmin" |
139 |
| - << "db" |
140 |
| - << "admin"))), |
141 |
| - BSONObj())); |
| 118 | + ASSERT_OK(externalState->insertUserDocument(opCtx.get(), |
| 119 | + BSON("_id" |
| 120 | + << "admin.v2read" |
| 121 | + << "user" |
| 122 | + << "v2read" |
| 123 | + << "db" |
| 124 | + << "test" |
| 125 | + << "credentials" << credentials << "roles" |
| 126 | + << BSON_ARRAY(BSON("role" |
| 127 | + << "read" |
| 128 | + << "db" |
| 129 | + << "test"))), |
| 130 | + BSONObj())); |
| 131 | + ASSERT_OK(externalState->insertUserDocument(opCtx.get(), |
| 132 | + BSON("_id" |
| 133 | + << "admin.v2cluster" |
| 134 | + << "user" |
| 135 | + << "v2cluster" |
| 136 | + << "db" |
| 137 | + << "admin" |
| 138 | + << "credentials" << credentials << "roles" |
| 139 | + << BSON_ARRAY(BSON("role" |
| 140 | + << "clusterAdmin" |
| 141 | + << "db" |
| 142 | + << "admin"))), |
| 143 | + BSONObj())); |
142 | 144 |
|
143 | 145 | auto swu = authzManager->acquireUser(opCtx.get(), {{"v2read", "test"}, boost::none});
|
144 | 146 | ASSERT_OK(swu.getStatus());
|
@@ -213,29 +215,30 @@ TEST_F(AuthorizationManagerTest, testLocalX509AuthenticationNoAuthorization) {
|
213 | 215 |
|
214 | 216 | // Tests SERVER-21535, unrecognized actions should be ignored rather than causing errors.
|
215 | 217 | TEST_F(AuthorizationManagerTest, testAcquireV2UserWithUnrecognizedActions) {
|
216 |
| - ASSERT_OK(externalState->insertPrivilegeDocument( |
217 |
| - opCtx.get(), |
218 |
| - BSON("_id" |
219 |
| - << "admin.myUser" |
220 |
| - << "user" |
221 |
| - << "myUser" |
222 |
| - << "db" |
223 |
| - << "test" |
224 |
| - << "credentials" << credentials << "roles" |
225 |
| - << BSON_ARRAY(BSON("role" |
226 |
| - << "myRole" |
227 |
| - << "db" |
228 |
| - << "test")) |
229 |
| - << "inheritedPrivileges" |
230 |
| - << BSON_ARRAY(BSON("resource" << BSON("db" |
231 |
| - << "test" |
232 |
| - << "collection" |
233 |
| - << "") |
234 |
| - << "actions" |
235 |
| - << BSON_ARRAY("find" |
236 |
| - << "fakeAction" |
237 |
| - << "insert")))), |
238 |
| - BSONObj())); |
| 218 | + ASSERT_OK( |
| 219 | + externalState->insertUserDocument(opCtx.get(), |
| 220 | + BSON("_id" |
| 221 | + << "admin.myUser" |
| 222 | + << "user" |
| 223 | + << "myUser" |
| 224 | + << "db" |
| 225 | + << "test" |
| 226 | + << "credentials" << credentials << "roles" |
| 227 | + << BSON_ARRAY(BSON("role" |
| 228 | + << "myRole" |
| 229 | + << "db" |
| 230 | + << "test")) |
| 231 | + << "inheritedPrivileges" |
| 232 | + << BSON_ARRAY(BSON("resource" |
| 233 | + << BSON("db" |
| 234 | + << "test" |
| 235 | + << "collection" |
| 236 | + << "") |
| 237 | + << "actions" |
| 238 | + << BSON_ARRAY("find" |
| 239 | + << "fakeAction" |
| 240 | + << "insert")))), |
| 241 | + BSONObj())); |
239 | 242 |
|
240 | 243 | auto swu = authzManager->acquireUser(opCtx.get(), {{"myUser", "test"}, boost::none});
|
241 | 244 | ASSERT_OK(swu.getStatus());
|
@@ -306,7 +309,7 @@ TEST_F(AuthorizationManagerTest, testRefreshExternalV2User) {
|
306 | 309 | << "test")};
|
307 | 310 |
|
308 | 311 | for (const auto& userDoc : userDocs) {
|
309 |
| - ASSERT_OK(externalState->insertPrivilegeDocument(opCtx.get(), userDoc, BSONObj())); |
| 312 | + ASSERT_OK(externalState->insertUserDocument(opCtx.get(), userDoc, BSONObj())); |
310 | 313 | }
|
311 | 314 |
|
312 | 315 | // Acquire these users to force the AuthorizationManager to load these users into the user
|
@@ -385,5 +388,84 @@ TEST_F(AuthorizationManagerTest, testRefreshExternalV2User) {
|
385 | 388 | }
|
386 | 389 | }
|
387 | 390 |
|
| 391 | +TEST_F(AuthorizationManagerTest, testAuthzManagerExternalStateResolveRoles) { |
| 392 | + BSONObj innerCustomRole{BSON("_id" |
| 393 | + << "admin.innerTestRole" |
| 394 | + << "db" |
| 395 | + << "admin" |
| 396 | + << "role" |
| 397 | + << "innerTestRole" |
| 398 | + << "roles" |
| 399 | + << BSON_ARRAY(BSON("db" |
| 400 | + << "test" |
| 401 | + << "role" |
| 402 | + << "read")))}; |
| 403 | + BSONObj middleCustomRole{BSON("_id" |
| 404 | + << "admin.middleTestRole" |
| 405 | + << "db" |
| 406 | + << "admin" |
| 407 | + << "role" |
| 408 | + << "middleTestRole" |
| 409 | + << "roles" << BSON_ARRAY(innerCustomRole))}; |
| 410 | + BSONObj outerCustomRole{BSON("_id" |
| 411 | + << "admin.outerTestRole" |
| 412 | + << "db" |
| 413 | + << "admin" |
| 414 | + << "role" |
| 415 | + << "outerTestRole" |
| 416 | + << "roles" << BSON_ARRAY(middleCustomRole) << "privileges" |
| 417 | + << BSON_ARRAY(BSON("resource" << BSON("cluster" << true) |
| 418 | + << "actions" |
| 419 | + << BSON_ARRAY("shutdown"))) |
| 420 | + << "authenticationRestrictions" |
| 421 | + << BSON_ARRAY(BSON("clientSource" << BSON_ARRAY("127.0.0.1/8"))))}; |
| 422 | + std::vector<BSONObj> customRoleDocuments{innerCustomRole, middleCustomRole, outerCustomRole}; |
| 423 | + |
| 424 | + for (const auto& roleDoc : customRoleDocuments) { |
| 425 | + ASSERT_OK(externalState->insertRoleDocument(opCtx.get(), roleDoc, BSONObj())); |
| 426 | + } |
| 427 | + |
| 428 | + // First, resolve all roles (but no privileges or restrictions). |
| 429 | + ResolveRoleOption option{ResolveRoleOption::kRoles()}; |
| 430 | + std::vector<RoleName> roleNames{RoleName{"outerTestRole", "admin"}}; |
| 431 | + auto swResolvedData = externalState->resolveRoles(opCtx.get(), roleNames, option); |
| 432 | + ASSERT_OK(swResolvedData.getStatus()); |
| 433 | + auto resolvedData = swResolvedData.getValue(); |
| 434 | + ASSERT_TRUE(resolvedData.roles.has_value()); |
| 435 | + ASSERT_EQ(resolvedData.roles->size(), 3); |
| 436 | + ASSERT_FALSE(resolvedData.privileges.has_value()); |
| 437 | + ASSERT_FALSE(resolvedData.restrictions.has_value()); |
| 438 | + |
| 439 | + // Resolve privileges and roles, no restrictions. |
| 440 | + option.setPrivileges(true /* shouldEnable */); |
| 441 | + swResolvedData = externalState->resolveRoles(opCtx.get(), roleNames, option); |
| 442 | + ASSERT_OK(swResolvedData.getStatus()); |
| 443 | + resolvedData = swResolvedData.getValue(); |
| 444 | + ASSERT_TRUE(resolvedData.roles.has_value()); |
| 445 | + ASSERT_EQ(resolvedData.roles->size(), 3); |
| 446 | + ASSERT_TRUE(resolvedData.privileges.has_value()); |
| 447 | + ASSERT_FALSE(resolvedData.restrictions.has_value()); |
| 448 | + |
| 449 | + // Resolve all roles, privileges, and restrictions. |
| 450 | + option.setRestrictions(true /* shouldEnable */); |
| 451 | + swResolvedData = externalState->resolveRoles(opCtx.get(), roleNames, option); |
| 452 | + ASSERT_OK(swResolvedData.getStatus()); |
| 453 | + resolvedData = swResolvedData.getValue(); |
| 454 | + ASSERT_TRUE(resolvedData.roles.has_value()); |
| 455 | + ASSERT_EQ(resolvedData.roles->size(), 3); |
| 456 | + ASSERT_TRUE(resolvedData.privileges.has_value()); |
| 457 | + ASSERT_TRUE(resolvedData.restrictions.has_value()); |
| 458 | + |
| 459 | + // Resolve only direct roles, privileges, and restrictions. |
| 460 | + option.setDirectOnly(true /* shouldEnable */); |
| 461 | + swResolvedData = externalState->resolveRoles(opCtx.get(), roleNames, option); |
| 462 | + ASSERT_OK(swResolvedData.getStatus()); |
| 463 | + resolvedData = swResolvedData.getValue(); |
| 464 | + ASSERT_TRUE(resolvedData.roles.has_value()); |
| 465 | + ASSERT_EQ(resolvedData.roles->size(), 1); |
| 466 | + ASSERT_TRUE(resolvedData.privileges.has_value()); |
| 467 | + ASSERT_TRUE(resolvedData.restrictions.has_value()); |
| 468 | +} |
| 469 | + |
388 | 470 | } // namespace
|
389 | 471 | } // namespace mongo
|
0 commit comments