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.