opendj-sdk/opends/resource/config/config.ldif
@@ -1235,6 +1235,7 @@ ds-cfg-default-root-privilege-name: update-schema ds-cfg-default-root-privilege-name: privilege-change ds-cfg-default-root-privilege-name: index-rebuild ds-cfg-default-root-privilege-name: unindexed-search dn: cn=Directory Manager,cn=Root DNs,cn=config objectClass: top opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -31,6 +31,7 @@ import org.opends.server.api.AttributeSyntax; import org.opends.server.api.Backend; import org.opends.server.api.EntryCache; import org.opends.server.api.ClientConnection; import org.opends.server.core.AddOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryServer; @@ -43,22 +44,7 @@ import org.opends.server.controls.ServerSideSortRequestControl; import org.opends.server.controls.ServerSideSortResponseControl; import org.opends.server.controls.VLVRequestControl; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.CancelledOperationException; import org.opends.server.types.Control; import org.opends.server.types.DebugLogLevel; import org.opends.server.types.DirectoryException; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.LDAPException; import org.opends.server.types.LockType; import org.opends.server.types.Modification; import org.opends.server.types.Operation; import org.opends.server.types.RDN; import org.opends.server.types.ResultCode; import org.opends.server.types.SearchScope; import org.opends.server.types.*; import org.opends.server.util.StaticUtils; import org.opends.server.util.ServerConstants; @@ -720,8 +706,7 @@ // Evaluate the search scope against the id2children and id2subtree indexes. boolean candidatesAreInScope = false; if (entryIDList.isDefined() && entryIDList.size() > IndexFilter.FILTER_CANDIDATE_THRESHOLD) if (entryIDList.size() > IndexFilter.FILTER_CANDIDATE_THRESHOLD) { // Read the ID from dn2id. EntryID baseID = dn2id.get(null, baseDN); @@ -820,6 +805,17 @@ } else { ClientConnection clientConnection = searchOperation.getClientConnection(); if(! clientConnection.hasPrivilege(Privilege.UNINDEXED_SEARCH, searchOperation)) { int msgID = MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES; String message = getMessage(msgID); throw new DirectoryException(ResultCode.INSUFFICIENT_ACCESS_RIGHTS, message, msgID); } if (sortRequest != null) { // FIXME -- Add support for sorting unindexed searches using indexes opendj-sdk/opends/src/server/org/opends/server/messages/JebMessages.java
@@ -1143,6 +1143,14 @@ CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 144; /** * The message ID of an error indicating that unindexed searches are not * allowed without the unindexed search prilvilege. This does not take * any arguments. */ public static final int MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES = CATEGORY_MASK_JEB | SEVERITY_MASK_MILD_ERROR | 145; /** * Associates a set of generic messages with the message IDs defined in this * class. */ @@ -1467,5 +1475,8 @@ "Unable to prcess the virtual list view request because " + "no entry was found in the result set with a sort value " + "greater than or equal to the provided assertion value"); registerMessage(MSGID_JEB_SEARCH_UNINDEXED_INSUFFICIENT_PRIVILEGES, "You do not have sufficient privileges to perform an " + "unindexed search"); } } opendj-sdk/opends/src/server/org/opends/server/types/Privilege.java
@@ -214,7 +214,15 @@ * The privilege that provides the ability to rebuild one or more * indexes in a backend that supports indexing. */ INDEX_REBUILD("index-rebuild"); INDEX_REBUILD("index-rebuild"), /** * The privilege that provides the ability to perform an unindexed * search in the JE backend. */ UNINDEXED_SEARCH("unindexed-search"); @@ -274,6 +282,7 @@ PRIV_MAP.put("update-schema", UPDATE_SCHEMA); PRIV_MAP.put("privilege-change", PRIVILEGE_CHANGE); PRIV_MAP.put("index-rebuild", INDEX_REBUILD); PRIV_MAP.put("unindexed-search", UNINDEXED_SEARCH); PRIV_NAMES.add("bypass-acl"); PRIV_NAMES.add("modify-acl"); @@ -297,6 +306,7 @@ PRIV_NAMES.add("update-schema"); PRIV_NAMES.add("privilege-change"); PRIV_NAMES.add("index-rebuild"); PRIV_NAMES.add("unindexed-search"); DEFAULT_ROOT_PRIV_SET.add(BYPASS_ACL); DEFAULT_ROOT_PRIV_SET.add(MODIFY_ACL); @@ -315,6 +325,7 @@ DEFAULT_ROOT_PRIV_SET.add(UPDATE_SCHEMA); DEFAULT_ROOT_PRIV_SET.add(PRIVILEGE_CHANGE); DEFAULT_ROOT_PRIV_SET.add(INDEX_REBUILD); DEFAULT_ROOT_PRIV_SET.add(UNINDEXED_SEARCH); } opendj-sdk/opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -338,6 +338,46 @@ replace: ds-cfg-override-severity ds-cfg-override-severity: EXCEPTION=INFO dn: ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config changetype: add objectClass: top objectClass: ds-cfg-backend objectClass: ds-cfg-je-backend ds-cfg-backend-enabled: true ds-cfg-backend-class: org.opends.server.backends.jeb.BackendImpl ds-cfg-backend-id: unindexedRoot ds-cfg-backend-writability-mode: enabled ds-cfg-backend-base-dn: dc=unindexed,dc=jeb ds-cfg-backend-directory: db_unindexed ds-cfg-backend-mode: 700 ds-cfg-backend-index-entry-limit: 1 ds-cfg-backend-subtree-delete-size-limit: 100000 ds-cfg-backend-preload-time-limit: 0 seconds ds-cfg-backend-import-temp-directory: importTmp ds-cfg-backend-import-buffer-size: 256 megabytes ds-cfg-backend-import-queue-size: 100 ds-cfg-backend-import-pass-size: 0 ds-cfg-backend-import-thread-count: 8 ds-cfg-backend-entries-compressed: false ds-cfg-backend-deadlock-retry-limit: 10 dn: cn=Index,ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config changetype: add objectClass: top objectClass: ds-cfg-branch cn: Index dn: ds-cfg-index-attribute=mail,cn=Index,ds-cfg-backend-id=unindexedRoot,cn=Backends,cn=config changetype: add objectClass: top objectClass: ds-cfg-je-index ds-cfg-index-attribute: mail ds-cfg-index-type: presence ds-cfg-index-type: equality ds-cfg-index-type: substring ds-cfg-index-type: ordering ds-cfg-index-type: approximate dn: ds-cfg-backend-id=rebuildRoot,cn=Backends,cn=config changetype: add objectClass: top opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/TestCaseUtils.java
@@ -190,7 +190,7 @@ //db_rebuild is the third jeb backend used by the jeb rebuild test cases String[] subDirectories = { "bak", "bin", "changelogDb", "classes", "config", "db", "db_verify", "ldif", "lib", "locks", "logs", "db_rebuild", "locks", "logs", "db_rebuild", "db_unindexed", "db_index_test" }; for (String s : subDirectories) { opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/types/PrivilegeTestCase.java
@@ -40,6 +40,7 @@ import org.testng.annotations.Test; import org.opends.server.TestCaseUtils; import static org.opends.server.util.StaticUtils.createEntry; import org.opends.server.backends.task.Task; import org.opends.server.backends.task.TaskBackend; import org.opends.server.backends.task.TaskState; @@ -134,6 +135,8 @@ "ds-privilege-name: -ldif-export", "ds-privilege-name: -backend-backup", "ds-privilege-name: -backend-restore", "ds-privilege-name: -index-rebuild", "ds-privilege-name: -unindexed-search", "", "dn: cn=Proxy Root,cn=Root DNs,cn=config", "objectClass: top", @@ -168,6 +171,8 @@ "ds-privilege-name: backend-restore", "ds-privilege-name: proxied-auth", "ds-privilege-name: bypass-acl", "ds-privilege-name: index-rebuild", "ds-privilege-name: unindexed-search", "ds-pwp-password-policy-dn: cn=Clear UserPassword Policy," + "cn=Password Policies,cn=config", "", @@ -250,6 +255,30 @@ connections[i] = connList.get(i); successful[i] = successList.get(i); } TestCaseUtils.addEntries( "dn: dc=unindexed,dc=jeb", "objectClass: top", "objectClass: domain", "", "dn: cn=test1 user,dc=unindexed,dc=jeb", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "cn: test1 user", "givenName: user", "sn: test1", "", "dn: cn=test2 user,dc=unindexed,dc=jeb", "objectClass: top", "objectClass: person", "objectClass: organizationalPerson", "objectClass: inetOrgPerson", "cn: test2 user", "givenName: user", "sn: test2" ); } @@ -333,6 +362,43 @@ } } /** * Tests to ensure that unindexed search operations properly respect the * UNINDEXED_SEARCH privilege. * * @param conn The client connection to use to perform the search operation. * * @param hasPrivilege Indicates whether the authenticated user is expected * to have the UNINDEXED_SEARCH privilege and therefore * the search should succeed. * @throws Exception If an unexpected problem occurs. */ @Test(dataProvider = "testdata") public void testUnindexedSearch(InternalClientConnection conn, boolean hasPrivilege) throws Exception { assertEquals(conn.hasPrivilege(Privilege.UNINDEXED_SEARCH, null), hasPrivilege); for(DN dn : DirectoryServer.getBaseDNs().keySet()) { System.out.println(dn.toString()); } InternalSearchOperation searchOperation = conn.processSearch(DN.decode("dc=unindexed,dc=jeb"), SearchScope.WHOLE_SUBTREE, SearchFilter.createFilterFromString("(sn=test*)")); if (hasPrivilege) { assertEquals(searchOperation.getResultCode(), ResultCode.SUCCESS); } else { assertEquals(searchOperation.getResultCode(), ResultCode.INSUFFICIENT_ACCESS_RIGHTS); } } /** @@ -1016,6 +1082,52 @@ } } /** * Test to ensure that attempts to rebuild indexes will property respect * the INDEX_REBUILD privilege. * * @param conn The client connection to use to perform the rebuild. * @param hasPrivilege Indicates weather the authenticated user is * expected to have the INDEX_REBUILD privilege * and therefore the rebuild should succeed. * @throws Exception if an unexpected problem occurs. */ @Test(dataProvider = "testdata", groups = { "slow" }) public void testRebuildIndex(InternalClientConnection conn, boolean hasPrivilege) throws Exception { assertEquals(conn.hasPrivilege(Privilege.INDEX_REBUILD, null), hasPrivilege); Entry taskEntry = TestCaseUtils.makeEntry( "dn: ds-task-id=" + UUID.randomUUID() + ",cn=Scheduled Tasks,cn=Tasks", "objectclass: top", "objectclass: ds-task", "objectclass: ds-task-rebuild", "ds-task-class-name: org.opends.server.tasks.RebuildTask", "ds-task-rebuild-base-dn: dc=example,dc=com", "ds-task-rebuild-index: cn"); AddOperation addOperation = conn.processAdd(taskEntry.getDN(), taskEntry.getObjectClasses(), taskEntry.getUserAttributes(), taskEntry.getOperationalAttributes()); if (hasPrivilege) { assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS); Task task = getCompletedTask(taskEntry.getDN()); assertNotNull(task); assertTrue(TaskState.isSuccessful(task.getTaskState())); } else { assertEquals(addOperation.getResultCode(), ResultCode.INSUFFICIENT_ACCESS_RIGHTS); } } /**