/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2009 Sun Microsystems, Inc.
*/
package org.opends.server.core.networkgroups;
import java.util.ArrayList;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import org.opends.messages.Message;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.std.meta.RequestFilteringQOSPolicyCfgDefn.AllowedOperations;
import org.opends.server.admin.std.meta.RequestFilteringQOSPolicyCfgDefn.AllowedSearchScopes;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.types.Attribute;
import org.opends.server.types.Attributes;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.OperationType;
import org.opends.server.types.SearchScope;
import org.opends.server.types.operation.PreParseAddOperation;
import org.opends.server.types.operation.PreParseBindOperation;
import org.opends.server.types.operation.PreParseCompareOperation;
import org.opends.server.types.operation.PreParseDeleteOperation;
import org.opends.server.types.operation.PreParseExtendedOperation;
import org.opends.server.types.operation.PreParseModifyDNOperation;
import org.opends.server.types.operation.PreParseModifyOperation;
import org.opends.server.types.operation.PreParseOperation;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.opends.server.util.ServerConstants.*;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
/*
* This set of tests test the resource limits.
*/
public class RequestFilteringPolicyTest extends DirectoryServerTestCase {
//===========================================================================
//
// B E F O R E C L A S S
//
//===========================================================================
/**
* Sets up the environment for performing the tests in this suite.
*
* @throws Exception if the environment could not be set up.
*/
@BeforeClass
public void setUp()
throws Exception
{
// This test suite depends on having the schema available,
// so we'll start the server.
TestCaseUtils.startServer();
}
//===========================================================================
//
// D A T A P R O V I D E R
//
//===========================================================================
/* Provides information to create an allowedAttribute policy and a filter
* to test.
*/
@DataProvider (name = "AllowedAttributesSet")
public Object[][] initAllowedAttributesSet()
{
TreeSet<String> allowedAttr_uid_cn = new TreeSet<String>();
allowedAttr_uid_cn.add("uid");
allowedAttr_uid_cn.add("cn");
TreeSet<String> allowedAttr_cn = new TreeSet<String>();
allowedAttr_cn.add("cn");
TreeSet<String> allowedAttr_uid = new TreeSet<String>();
allowedAttr_uid.add("uid");
Object[][] myData = {
// allowed attributes, attribute to test, success
{allowedAttr_uid_cn, "uid=*", true},
{allowedAttr_uid_cn, "cn=*", true},
{allowedAttr_uid_cn, "(&(uid=user.1)(cn=*))", true},
{allowedAttr_cn, "cn=*", true},
{allowedAttr_cn, "uid=*", false},
{allowedAttr_cn, "(&(uid=user.1)(cn=*))", false},
{allowedAttr_uid, "cn=*", false},
{allowedAttr_uid, "uid=*", true},
{allowedAttr_uid, "(&(uid=user.1)(cn=*))", false}
};
return myData;
}
/* Provides information to create a prohibitedAttribute policy and a filter
* to test.
*/
@DataProvider (name = "ProhibitedAttributesSet")
public Object[][] initProhibitedAttributesSet()
{
TreeSet<String> prohibitedAttr_uid = new TreeSet<String>();
prohibitedAttr_uid.add("uid");
TreeSet<String> prohibitedAttr_cn = new TreeSet<String>();
prohibitedAttr_cn.add("cn");
Object[][] myData = {
// prohibited attributes, attribute to test, success
{prohibitedAttr_uid, "uid=*", false},
{prohibitedAttr_cn, "uid=*", true},
{prohibitedAttr_cn, "(&(uid=user.1)(cn=*))", false}
};
return myData;
}
/* Provides information to create an allowedSearchScopes policy and a
* scope to test.
*/
@DataProvider (name = "AllowedSearchScopesSet")
public Object[][] initAllowedSearchScopesSet()
{
TreeSet<AllowedSearchScopes> scopes_all =
new TreeSet<AllowedSearchScopes>();
scopes_all.add(AllowedSearchScopes.BASE);
scopes_all.add(AllowedSearchScopes.CHILDREN);
scopes_all.add(AllowedSearchScopes.ONE);
scopes_all.add(AllowedSearchScopes.SUB);
TreeSet<AllowedSearchScopes> scope_base =
new TreeSet<AllowedSearchScopes>();
scope_base.add(AllowedSearchScopes.BASE);
TreeSet<AllowedSearchScopes> scope_children =
new TreeSet<AllowedSearchScopes>();
scope_children.add(AllowedSearchScopes.CHILDREN);
TreeSet<AllowedSearchScopes> scope_one =
new TreeSet<AllowedSearchScopes>();
scope_one.add(AllowedSearchScopes.ONE);
TreeSet<AllowedSearchScopes> scope_sub =
new TreeSet<AllowedSearchScopes>();
scope_sub.add(AllowedSearchScopes.SUB);
Object[][] myData = {
// allowed search scopes, scope to test, success
{scopes_all, SearchScope.BASE_OBJECT, true},
{scope_base, SearchScope.BASE_OBJECT, true},
{scope_base, SearchScope.SINGLE_LEVEL, false},
{scope_base, SearchScope.SUBORDINATE_SUBTREE, false},
{scope_base, SearchScope.WHOLE_SUBTREE, false},
{scope_children, SearchScope.BASE_OBJECT, false},
{scope_children, SearchScope.SINGLE_LEVEL, false},
{scope_children, SearchScope.SUBORDINATE_SUBTREE, true},
{scope_children, SearchScope.WHOLE_SUBTREE, false},
{scope_one, SearchScope.BASE_OBJECT, false},
{scope_one, SearchScope.SINGLE_LEVEL, true},
{scope_one, SearchScope.SUBORDINATE_SUBTREE, false},
{scope_one, SearchScope.WHOLE_SUBTREE, false},
{scope_sub, SearchScope.BASE_OBJECT, false},
{scope_sub, SearchScope.SINGLE_LEVEL, false},
{scope_sub, SearchScope.SUBORDINATE_SUBTREE, false},
{scope_sub, SearchScope.WHOLE_SUBTREE, true}
};
return myData;
}
/* Provides information to create a allowedSubtree policy and
* a subtree search to test.
*/
@DataProvider (name = "AllowedSubtreesSet")
public Object[][] initAllowedSubtreesSet()
throws DirectoryException
{
TreeSet<DN> subtrees1 = new TreeSet<DN>();
subtrees1.add(DN.decode("ou=people,dc=example,dc=com"));
TreeSet<DN> subtrees2 = new TreeSet<DN>();
subtrees2.add(DN.decode("ou=test,dc=example,dc=com"));
TreeSet<DN> subtrees3 = new TreeSet<DN>();
subtrees3.add(DN.decode("dc=example,dc=com"));
TreeSet<DN> subtrees4 = new TreeSet<DN>();
subtrees4.add(DN.decode("dc=example,dc=com"));
subtrees4.add(DN.decode("dc=test,dc=com"));
Object[][] myData = {
// allowed subtrees, subtree to test, success
{subtrees1, "ou=people,dc=example,dc=com", true},
{subtrees2, "ou=people,dc=example,dc=com", false},
{subtrees3, "ou=people,dc=example,dc=com", true},
{subtrees1, "dc=example,dc=com", false},
{subtrees4, "dc=example,dc=com", true},
{subtrees4, "ou=people,dc=example,dc=com", true}
};
return myData;
}
/* Provides information to create a prohibitedSubtree policy and
* a subtree search to test.
*/
@DataProvider (name = "ProhibitedSubtreesSet")
public Object[][] initProhibitedSubtreesSet() throws DirectoryException
{
TreeSet<DN> subtrees1 = new TreeSet<DN>();
subtrees1.add(DN.decode("ou=people,dc=example,dc=com"));
TreeSet<DN> subtrees2 = new TreeSet<DN>();
subtrees2.add(DN.decode("ou=test,dc=example,dc=com"));
TreeSet<DN> subtrees3 = new TreeSet<DN>();
subtrees3.add(DN.decode("dc=example,dc=com"));
TreeSet<DN> subtrees4 = new TreeSet<DN>();
subtrees4.add(DN.decode("dc=example,dc=com"));
subtrees4.add(DN.decode("dc=test,dc=com"));
Object[][] myData = {
// prohibited subtrees, subtree to test, success
{subtrees1, "ou=people,dc=example,dc=com", false},
{subtrees2, "ou=people,dc=example,dc=com", true},
{subtrees3, "ou=people,dc=example,dc=com", false},
{subtrees1, "dc=example,dc=com", true},
{subtrees4, "ou=people,dc=example,dc=com", false}
};
return myData;
}
/* Provides information to create a complex subtree policy and a
* subtree search to test.
*/
@DataProvider (name = "ComplexSubtreesSet")
public Object[][] initComplexSubtreesSet() throws DirectoryException
{
TreeSet<DN> subtrees_empty = new TreeSet<DN>();
TreeSet<DN> subtrees_root = new TreeSet<DN>();
subtrees_root.add(DN.decode("dc=example,dc=com"));
TreeSet<DN> subtrees_people = new TreeSet<DN>();
subtrees_people.add(DN.decode("ou=people,dc=example,dc=com"));
TreeSet<DN> subtrees_entry = new TreeSet<DN>();
subtrees_entry.add(DN.decode("uid=user.1,ou=people,dc=example,dc=com"));
Object[][] myData = {
// allowed subtree, prohibited subtree, subtree to test, success
{subtrees_root, subtrees_people, "dc=example,dc=com", true},
{subtrees_root, subtrees_people, "ou=people,dc=example,dc=com", false},
{subtrees_root, subtrees_entry, "ou=people,dc=example,dc=com", true},
{subtrees_empty, subtrees_people, "dc=example,dc=com", true},
{subtrees_empty, subtrees_people, "ou=people,dc=example,dc=com", false}
};
return myData;
}
/* Provides information to create an allowed operations policy.
*/
@DataProvider (name = "AllowedOperationsSet")
public Object[][] initAllowedOperationsSet()
{
TreeSet<AllowedOperations> ops_all = new TreeSet<AllowedOperations>();
ops_all.add(AllowedOperations.ADD);
ops_all.add(AllowedOperations.BIND);
ops_all.add(AllowedOperations.COMPARE);
ops_all.add(AllowedOperations.DELETE);
ops_all.add(AllowedOperations.EXTENDED);
ops_all.add(AllowedOperations.INEQUALITY_SEARCH);
ops_all.add(AllowedOperations.MODIFY);
ops_all.add(AllowedOperations.RENAME);
ops_all.add(AllowedOperations.SEARCH);
TreeSet<AllowedOperations> ops_search = new TreeSet<AllowedOperations>();
ops_search.add(AllowedOperations.INEQUALITY_SEARCH);
ops_search.add(AllowedOperations.SEARCH);
TreeSet<AllowedOperations> ops_add_del = new TreeSet<AllowedOperations>();
ops_add_del.add(AllowedOperations.ADD);
ops_add_del.add(AllowedOperations.DELETE);
Object[][] myData = {
// allowed operations, operation to test, success
{ops_all, OperationType.ABANDON, true},
{ops_all, OperationType.ADD, true},
{ops_all, OperationType.BIND, true},
{ops_all, OperationType.COMPARE, true},
{ops_all, OperationType.DELETE, true},
{ops_all, OperationType.EXTENDED, true},
{ops_all, OperationType.MODIFY, true},
{ops_all, OperationType.MODIFY_DN, true},
{ops_all, OperationType.SEARCH, true},
{ops_all, OperationType.UNBIND, true},
{ops_search, OperationType.SEARCH, true},
{ops_search, OperationType.ADD, false},
{ops_search, OperationType.BIND, false},
{ops_add_del, OperationType.ADD, true},
{ops_add_del, OperationType.DELETE, true},
{ops_add_del, OperationType.EXTENDED, false}
};
return myData;
}
//===========================================================================
//
// T E S T C A S E S
//
//===========================================================================
/**
* Tests the "allowed attributes" policy
*/
@Test (dataProvider = "AllowedAttributesSet", groups = "virtual")
public void testAllowedAttributes(
final SortedSet<String> allowedAttributes,
String searchFilter,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<String> getAllowedAttributes()
{
return Collections.unmodifiableSortedSet(allowedAttributes);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode("dc=example,dc=com"),
SearchScope.BASE_OBJECT,
LDAPFilter.decode(searchFilter).toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the "prohibited operations" policy
*/
@Test (dataProvider = "ProhibitedAttributesSet", groups = "virtual")
public void testProhibitedAttributes(
final SortedSet<String> prohibitedAttributes,
String searchFilter,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<String> getProhibitedAttributes()
{
return Collections.unmodifiableSortedSet(prohibitedAttributes);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode("dc=example,dc=com"),
SearchScope.BASE_OBJECT,
LDAPFilter.decode(searchFilter).toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the "allowed search scopes" policy.
*/
@Test (dataProvider = "AllowedSearchScopesSet", groups = "virtual")
public void testAllowedSearchScopes(
final SortedSet<AllowedSearchScopes> allowedScopes,
SearchScope searchScope,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<AllowedSearchScopes> getAllowedSearchScopes()
{
return Collections.unmodifiableSortedSet(allowedScopes);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode("dc=example,dc=com"),
searchScope,
LDAPFilter.decode("objectclass=*").toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the "allowed subtrees" policy.
*/
@Test (dataProvider = "AllowedSubtreesSet", groups = "virtual")
public void testAllowedSubtrees(
final SortedSet<DN> allowedSubtrees,
String searchSubtree,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<DN> getAllowedSubtrees()
{
return Collections.unmodifiableSortedSet(allowedSubtrees);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode(searchSubtree),
SearchScope.WHOLE_SUBTREE,
LDAPFilter.decode("objectclass=*").toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the "prohibited subtrees" policy.
*/
@Test (dataProvider = "ProhibitedSubtreesSet", groups = "virtual")
public void testProhibitedSubtrees(
final SortedSet<DN> prohibitedSubtrees,
String searchSubtree,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<DN> getProhibitedSubtrees()
{
return Collections.unmodifiableSortedSet(prohibitedSubtrees);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode(searchSubtree),
SearchScope.WHOLE_SUBTREE,
LDAPFilter.decode("objectclass=*").toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the subtrees policy.
*/
@Test (dataProvider = "ComplexSubtreesSet", groups = "virtual")
public void testComplexSubtrees(
final SortedSet<DN> allowedSubtrees,
final SortedSet<DN> prohibitedSubtrees,
String searchSubtree,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<DN> getAllowedSubtrees()
{
return Collections.unmodifiableSortedSet(allowedSubtrees);
}
@Override
public SortedSet<DN> getProhibitedSubtrees()
{
return Collections.unmodifiableSortedSet(prohibitedSubtrees);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
InternalSearchOperation search = conn.processSearch(
DN.decode(searchSubtree),
SearchScope.WHOLE_SUBTREE,
LDAPFilter.decode("objectclass=*").toSearchFilter());
boolean check = policy.isAllowed(search, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
/**
* Tests the allowed operations policy.
*/
@Test (dataProvider = "AllowedOperationsSet", groups = "virtual")
public void testAllowedOperations(
final SortedSet<AllowedOperations> allowedOps,
OperationType type,
boolean success)
throws Exception
{
ArrayList<Message> messages = new ArrayList<Message>();
RequestFilteringPolicyFactory factory = new RequestFilteringPolicyFactory();
RequestFilteringPolicy policy = factory.createQOSPolicy(new MockRequestFilteringQOSPolicyCfg() {
@Override
public SortedSet<AllowedOperations> getAllowedOperations()
{
return Collections.unmodifiableSortedSet(allowedOps);
}
});
InternalClientConnection conn = new InternalClientConnection(DN.NULL_DN);
PreParseOperation op = null;
switch (type) {
case ABANDON:
return;
case ADD:
Entry e = TestCaseUtils.makeEntry(
"dn: ou=People,o=ldif",
"objectClass: top",
"objectClass: organizationalUnit",
"ou: People");
op = (PreParseAddOperation) conn.processAdd(e);
break;
case BIND:
op = (PreParseBindOperation) conn.processSimpleBind(
"cn=Directory Manager", "password");
break;
case COMPARE:
op = (PreParseCompareOperation) conn.processCompare(
"uid=user.1,ou=People,o=ldif", "uid", "user.1");
break;
case DELETE:
op = (PreParseDeleteOperation) conn.processDelete(
"uid=user.1,ou=people,dc=example,dc=com");
break;
case EXTENDED:
op = (PreParseExtendedOperation) conn.processExtendedOperation(
OID_WHO_AM_I_REQUEST, null);
break;
case MODIFY:
ArrayList<Modification> mods = new ArrayList<Modification>();
Attribute attributeToModify = Attributes.create("attr", "newVal");
mods.add(new Modification(ModificationType.ADD, attributeToModify));
op = (PreParseModifyOperation) conn.processModify(
DN.decode("uid=user.1,ou=people,dc=example,dc=com"), mods);
break;
case MODIFY_DN:
op = (PreParseModifyDNOperation) conn.processModifyDN(
"uid=user.1,ou=people,dc=example,dc=com",
"uid=usr.1,ou=people,dc=example,dc=com", true);
break;
case SEARCH:
op = conn.processSearch(DN.decode("dc=example,dc=com"),
SearchScope.WHOLE_SUBTREE,
LDAPFilter.decode("uid>=user.1").toSearchFilter());
break;
case UNBIND:
return;
}
boolean check = policy.isAllowed(op, messages);
if (success) {
assertTrue(check);
} else {
assertFalse(check);
}
}
}