mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
13.59.2007 2021fe3e69527d25fb1b2dc67e4e931e6a56260a
Update the member virtual attribute implementation so that it provides a
mechanism for preventing the entire member list from being returned, which can
be a very expensive operation. When running with this configuration, the
attribute will handle requests that determine whether a given user is a member
of the group, but will not list the entire set of membership.

OpenDS Issue Number: 1506
1 files added
5 files modified
169 ■■■■■ changed files
opends/resource/config/config.ldif 4 ●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 7 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/MemberVirtualAttributeConfiguration.xml 42 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/MemberVirtualAttributeProvider.java 47 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/resource/config-changes.ldif 10 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/VirtualStaticGroupTestCase.java 59 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1741,22 +1741,26 @@
dn: cn=Virtual Static member,cn=Virtual Attributes,cn=config
objectClass: top
objectClass: ds-cfg-virtual-attribute
objectClass: ds-cfg-member-virtual-attribute
cn: Virtual Static member
ds-cfg-virtual-attribute-class: org.opends.server.extensions.MemberVirtualAttributeProvider
ds-cfg-virtual-attribute-enabled: true
ds-cfg-virtual-attribute-type: member
ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real
ds-cfg-virtual-attribute-filter: (&(objectClass=groupOfNames)(objectClass=ds-virtual-static-group))
ds-cfg-allow-retrieving-membership: false
dn: cn=Virtual Static uniqueMember,cn=Virtual Attributes,cn=config
objectClass: top
objectClass: ds-cfg-virtual-attribute
objectClass: ds-cfg-member-virtual-attribute
cn: Virtual Static uniqueMember
ds-cfg-virtual-attribute-class: org.opends.server.extensions.MemberVirtualAttributeProvider
ds-cfg-virtual-attribute-enabled: true
ds-cfg-virtual-attribute-type: uniqueMember
ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real
ds-cfg-virtual-attribute-filter: (&(objectClass=groupOfUniqueNames)(objectClass=ds-virtual-static-group))
ds-cfg-allow-retrieving-membership: false
dn: cn=Work Queue,cn=config
objectClass: top
opends/resource/schema/02-config.ldif
@@ -1156,6 +1156,9 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.344
  NAME 'ds-cfg-virtual-attribute-value' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.345
  NAME 'ds-cfg-allow-retrieving-membership' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
  NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
  MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1615,4 +1618,8 @@
  NAME 'ds-cfg-user-defined-virtual-attribute' SUP ds-cfg-virtual-attribute
  STRUCTURAL MUST ds-cfg-virtual-attribute-value
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.101
  NAME 'ds-cfg-member-virtual-attribute' SUP ds-cfg-virtual-attribute
  STRUCTURAL MUST ds-cfg-allow-retrieving-membership
  X-ORIGIN 'OpenDS Directory Server' )
opends/src/admin/defn/org/opends/server/admin/std/MemberVirtualAttributeConfiguration.xml
New file
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<adm:managed-object name="member-virtual-attribute"
plural-name="user-defined-virtual-attributes"
package="org.opends.server.admin.std" extends="virtual-attribute"
xmlns:adm="http://www.opends.org/admin"
xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to generate a member or uniqueMember attribute whose values are the
    DNs of the members of a specified group.  This is used to implement virtual
    static group functionality, in which it is possible to create an entry which
    looks like a static group but obtains all of its membership from a dynamic
    group (or some other type of group, including another static group).
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.101</ldap:oid>
      <ldap:name>ds-cfg-member-virtual-attribute</ldap:name>
      <ldap:superior>ds-cfg-virtual-attribute</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property name="allow-retrieving-membership" mandatory="true">
    <adm:synopsis>
      Indicates whether to handle requests that request all values for the
      virtual attribute.  This can be a very expensive operation in some cases,
      and is not in-line with the primary function of virtual static groups,
      which is to make it possible to use static group idioms to determine
      whether a given user is a member.
    </adm:synopsis>
    <adm:syntax>
      <adm:boolean />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:oid>1.3.6.1.4.1.26027.1.1.345</ldap:oid>
        <ldap:name>ds-cfg-allow-retrieving-membership</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/server/org/opends/server/extensions/MemberVirtualAttributeProvider.java
@@ -32,7 +32,8 @@
import java.util.LinkedHashSet;
import java.util.List;
import org.opends.server.admin.std.server.VirtualAttributeCfg;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.MemberVirtualAttributeCfg;
import org.opends.server.api.Group;
import org.opends.server.api.VirtualAttributeProvider;
import org.opends.server.config.ConfigException;
@@ -42,6 +43,7 @@
import org.opends.server.types.AttributeValue;
import org.opends.server.types.ByteString;
import org.opends.server.types.ConditionResult;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -62,12 +64,16 @@
 * uniqueMember attribute.
 */
public class MemberVirtualAttributeProvider
       extends VirtualAttributeProvider<VirtualAttributeCfg>
       extends VirtualAttributeProvider<MemberVirtualAttributeCfg>
       implements ConfigurationChangeListener<MemberVirtualAttributeCfg>
{
  // The attribute type used to indicate which target group should be used to
  // obtain the member list.
  private AttributeType targetGroupType;
  // The current configuration for this member virtual attribute.
  private MemberVirtualAttributeCfg currentConfig;
  /**
@@ -88,9 +94,12 @@
   */
  @Override()
  public void initializeVirtualAttributeProvider(
                            VirtualAttributeCfg configuration)
                            MemberVirtualAttributeCfg configuration)
         throws ConfigException, InitializationException
  {
    configuration.addMemberChangeListener(this);
    currentConfig = configuration;
    targetGroupType =
         DirectoryServer.getAttributeType(ATTR_TARGET_GROUP_DN, true);
  }
@@ -115,6 +124,11 @@
  public LinkedHashSet<AttributeValue> getValues(Entry entry,
                                                 VirtualAttributeRule rule)
  {
    if (! currentConfig.isAllowRetrievingMembership())
    {
      return new LinkedHashSet<AttributeValue>(0);
    }
    Group g = DirectoryServer.getGroupManager().getGroupInstance(entry.getDN());
    if (g == null)
    {
@@ -336,5 +350,32 @@
    searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
    return;
  }
  /**
   * {@inheritDoc}
   */
  public boolean isConfigurationChangeAcceptable(
                      MemberVirtualAttributeCfg configuration,
                      List<String> unacceptableReasons)
  {
    // The new configuration should always be acceptable.
    return true;
  }
  /**
   * {@inheritDoc}
   */
  public ConfigChangeResult applyConfigurationChange(
                                 MemberVirtualAttributeCfg configuration)
  {
    // Just accept the new configuration as-is.
    currentConfig = configuration;
    return new ConfigChangeResult(ResultCode.SUCCESS, false);
  }
}
opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -525,3 +525,13 @@
ds-cfg-database-checkpointer-wakeup-interval: 30 seconds
ds-cfg-database-lock-num-lock-tables: 19
dn: cn=Virtual Static member,cn=Virtual Attributes,cn=config
changetype: modify
replace: ds-cfg-allow-retrieving-membership
ds-cfg-allow-retrieving-membership: true
dn: cn=Virtual Static uniqueMember,cn=Virtual Attributes,cn=config
changetype: modify
replace: ds-cfg-allow-retrieving-membership
ds-cfg-allow-retrieving-membership: true
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/VirtualStaticGroupTestCase.java
@@ -837,6 +837,65 @@
  /**
   * Tests the behavior of the member virtual attribute with different settings
   * for the "allow retrieving membership" attribute.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testAllowRetrievingMembership()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    TestCaseUtils.addEntries(LDIF_LINES);
    Entry e = DirectoryServer.getEntry(vmd1);
    assertNotNull(e);
    assertTrue(e.hasAttribute(memberType));
    Attribute a = e.getAttribute(memberType).get(0);
    assertEquals(a.getValues().size(), 1);
    AttributeValue v = new AttributeValue(memberType, u4.toString());
    assertTrue(a.hasValue(v));
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    LinkedList<Modification> mods = new LinkedList<Modification>();
    mods.add(new Modification(ModificationType.REPLACE,
         new Attribute("ds-cfg-allow-retrieving-membership", "false")));
    DN definitionDN =
         DN.decode("cn=Virtual Static member,cn=Virtual Attributes,cn=config");
    ModifyOperation modifyOperation = conn.processModify(definitionDN, mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
    e = DirectoryServer.getEntry(vmd1);
    assertNotNull(e);
    assertTrue(e.hasAttribute(memberType));
    a = e.getAttribute(memberType).get(0);
    assertEquals(a.getValues().size(), 0);
    v = new AttributeValue(memberType, u4.toString());
    assertTrue(a.hasValue(v));
    mods = new LinkedList<Modification>();
    mods.add(new Modification(ModificationType.REPLACE,
         new Attribute("ds-cfg-allow-retrieving-membership", "true")));
    modifyOperation = conn.processModify(definitionDN, mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
    cleanUp();
  }
  /**
   * Removes all of the groups that have been added to the server.
   *
   * @throws  Exception  If an unexpected problem occurs.