Author: orudyy
Date: Wed Jun  1 20:12:11 2016
New Revision: 1746494

URL: http://svn.apache.org/viewvc?rev=1746494&view=rev
Log:
[QPID-7116] Add ability to utilise group information from a LDAP compatible 
directory

Modified:
    
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
    
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
    
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
    
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java
    
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
    
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/show.html

Modified: 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
 (original)
+++ 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
 Wed Jun  1 20:12:11 2016
@@ -81,6 +81,18 @@ public interface SimpleLDAPAuthenticatio
     @ManagedAttribute( description = "(Optional) password for authenticated 
search", secure = true)
     String getSearchPassword();
 
+    @ManagedAttribute( description = "User entry attribute name containing 
group name user belongs to. ")
+    String getGroupAttributeName();
+
+    @ManagedAttribute( description = "Search context to look for role entries")
+    String getGroupSearchContext();
+
+    @ManagedAttribute( description = "Group search filter to search for groups 
in group search context")
+    String getGroupSearchFilter();
+
+    @ManagedAttribute( description = "Defines the group search scope. If true 
the search for group entries is performed in the entire subtree of the group 
search context")
+    boolean isGroupSubtreeSearchScope();
+
     @DerivedAttribute
     List<String> getTlsProtocolWhiteList();
 

Modified: 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
 (original)
+++ 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
 Wed Jun  1 20:12:11 2016
@@ -27,6 +27,8 @@ import java.io.IOException;
 import java.security.GeneralSecurityException;
 import java.security.Principal;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -36,6 +38,9 @@ import javax.naming.AuthenticationExcept
 import javax.naming.Context;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
@@ -51,6 +56,7 @@ import javax.security.sasl.SaslException
 import javax.security.sasl.SaslServer;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import org.apache.qpid.server.security.group.GroupPrincipal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -118,6 +124,18 @@ public class SimpleLDAPAuthenticationMan
     @ManagedAttributeField
     private String _searchPassword;
 
+    @ManagedAttributeField
+    private String _groupAttributeName;
+
+    @ManagedAttributeField
+    private String _groupSearchContext;
+
+    @ManagedAttributeField
+    private String _groupSearchFilter;
+
+    @ManagedAttributeField
+    private boolean _groupSubtreeSearchScope;
+
     private List<String> _tlsProtocolWhiteList;
     private List<String>  _tlsProtocolBlackList;
 
@@ -225,6 +243,29 @@ public class SimpleLDAPAuthenticationMan
         return _searchPassword;
     }
 
+    @Override
+    public String getGroupAttributeName()
+    {
+        return _groupAttributeName;
+    }
+
+    @Override
+    public String getGroupSearchContext()
+    {
+        return _groupSearchContext;
+    }
+
+    @Override
+    public String getGroupSearchFilter()
+    {
+        return _groupSearchFilter;
+    }
+
+    @Override
+    public boolean isGroupSubtreeSearchScope()
+    {
+        return _groupSubtreeSearchScope;
+    }
 
     @Override
     public List<String> getMechanisms()
@@ -258,7 +299,12 @@ public class SimpleLDAPAuthenticationMan
                 String authorizationID = server.getAuthorizationID();
                 _logger.debug("Authenticated as {}", authorizationID);
 
-                return new AuthenticationResult(new 
UsernamePrincipal(authorizationID), challenge);
+                AuthenticationResult result = 
(AuthenticationResult)server.getNegotiatedProperty(PlainSaslServer.AUTHENTICATION_RESULT);
+                if (result == null)
+                {
+                    return new 
AuthenticationResult(AuthenticationStatus.ERROR);
+                }
+                return new AuthenticationResult(result.getMainPrincipal(), 
result.getPrincipals(), challenge);
             }
             else
             {
@@ -276,16 +322,7 @@ public class SimpleLDAPAuthenticationMan
     {
         try
         {
-            AuthenticationResult result = 
doLDAPNameAuthentication(getNameFromId(username), password);
-            if(result.getStatus() == AuthenticationStatus.SUCCESS)
-            {
-                //Return a result based on the supplied username rather than 
the search name
-                return new AuthenticationResult(new 
UsernamePrincipal(username));
-            }
-            else
-            {
-                return result;
-            }
+            return doLDAPNameAuthentication(getNameFromId(username), password);
         }
         catch (NamingException e)
         {
@@ -301,7 +338,7 @@ public class SimpleLDAPAuthenticationMan
             return new AuthenticationResult(AuthenticationStatus.CONTINUE);
         }
 
-        String providerAuthUrl = _providerAuthUrl == null ? _providerUrl : 
_providerAuthUrl;
+        String providerAuthUrl = isSpecified(getProviderAuthUrl()) ? 
getProviderAuthUrl() : getProviderUrl();
         Hashtable<String, Object> env = 
createInitialDirContextEnvironment(providerAuthUrl);
 
         env.put(Context.SECURITY_AUTHENTICATION, "simple");
@@ -313,8 +350,19 @@ public class SimpleLDAPAuthenticationMan
         {
             ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass);
 
+            Set<Principal> groups = Collections.emptySet();
+            if (isGroupSearchRequired())
+            {
+                if (!providerAuthUrl.equals(getProviderUrl()))
+                {
+                    closeSafely(ctx);
+                    ctx = createSearchInitialDirContext();
+                }
+                groups = findGroups(ctx, name);
+            }
+
             //Authentication succeeded
-            return new AuthenticationResult(new UsernamePrincipal(name));
+            return new AuthenticationResult(new UsernamePrincipal(name), 
groups, null);
         }
         catch(AuthenticationException ae)
         {
@@ -335,6 +383,107 @@ public class SimpleLDAPAuthenticationMan
         }
     }
 
+    private boolean isGroupSearchRequired()
+    {
+        if (isSpecified(getGroupAttributeName()))
+        {
+            return true;
+        }
+
+        if (isSpecified(getGroupSearchContext()) && 
isSpecified(getGroupSearchFilter()))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean isSpecified(String value)
+    {
+        return value != null && !"".equals(value);
+    }
+
+    private Set<Principal> findGroups(DirContext context, String userDN) 
throws NamingException
+    {
+        Set<Principal> groupPrincipals = new HashSet<>();
+        if (getGroupAttributeName() != null && 
!"".equals(getGroupAttributeName()))
+        {
+            Attributes attributes = context.getAttributes(userDN, new 
String[]{getGroupAttributeName()});
+            NamingEnumeration<? extends Attribute> namingEnum = 
attributes.getAll();
+            while (namingEnum.hasMore())
+            {
+                Attribute attribute = namingEnum.next();
+                if (attribute != null)
+                {
+                    NamingEnumeration<?> attributeValues = attribute.getAll();
+                    while (attributeValues.hasMore())
+                    {
+                        Object attributeValue = attributeValues.next();
+                        if (attributeValue != null)
+                        {
+                            String groupDN = String.valueOf(attributeValue);
+                            groupPrincipals.add(new GroupPrincipal(groupDN));
+                        }
+                    }
+                }
+            }
+        }
+
+        if (getGroupSearchContext() != null && 
!"".equals(getGroupSearchContext()) &&
+            getGroupSearchFilter() != null && 
!"".equals(getGroupSearchFilter()))
+        {
+            SearchControls searchControls = new SearchControls();
+            searchControls.setReturningAttributes(new String[]{});
+            searchControls.setSearchScope(isGroupSubtreeSearchScope()
+                                                  ? 
SearchControls.SUBTREE_SCOPE
+                                                  : 
SearchControls.ONELEVEL_SCOPE);
+            NamingEnumeration<?> groupEnumeration = 
context.search(getGroupSearchContext(),
+                                                                   
getGroupSearchFilter(),
+                                                                   new 
String[]{encode(userDN)},
+                                                                   
searchControls);
+            while (groupEnumeration.hasMore())
+            {
+                SearchResult result = (SearchResult) groupEnumeration.next();
+                String groupDN = result.getNameInNamespace();
+                groupPrincipals.add(new GroupPrincipal(groupDN));
+            }
+        }
+
+        return groupPrincipals;
+    }
+
+    private String encode(String value)
+    {
+        StringBuilder encoded = new StringBuilder(value.length());
+        char[] chars = value.toCharArray();
+        for (int i = 0; i < chars.length; i++)
+        {
+            char ch = chars[i];
+            switch (ch)
+            {
+                case '\0':
+                    encoded.append("\\00");
+                    break;
+                case '(':
+                    encoded.append("\\28");
+                    break;
+                case ')':
+                    encoded.append("\\29");
+                    break;
+                case '*':
+                    encoded.append("\\2a");
+                    break;
+                case '\\':
+                    encoded.append("\\5c");
+                    break;
+                default:
+                    encoded.append(ch);
+                    break;
+            }
+        }
+        return encoded.toString();
+    }
+
     private Hashtable<String, Object> 
createInitialDirContextEnvironment(String providerUrl)
     {
         Hashtable<String,Object> env = new Hashtable<>();
@@ -501,6 +650,10 @@ public class SimpleLDAPAuthenticationMan
                 else if (callback instanceof AuthorizeCallback)
                 {
                     ((AuthorizeCallback) callback).setAuthorized(authenticated 
!= null && authenticated.getStatus() == 
AuthenticationResult.AuthenticationStatus.SUCCESS);
+                    if (callback instanceof 
PlainSaslServer.AuthenticationResultPreservingAuthorizeCallback)
+                    {
+                        
((PlainSaslServer.AuthenticationResultPreservingAuthorizeCallback)callback).setAuthenticationResult(authenticated);
+                    }
                 }
                 else
                 {
@@ -514,11 +667,7 @@ public class SimpleLDAPAuthenticationMan
     {
         if(!isBindWithoutSearch())
         {
-            Hashtable<String, Object> env = 
createInitialDirContextEnvironment(_providerUrl);
-
-            setupSearchContext(env, _searchUsername, _searchPassword);
-
-            InitialDirContext ctx = createInitialDirContext(env, 
_sslSocketFactoryOverrideClass);
+            InitialDirContext ctx = createSearchInitialDirContext();
 
             try
             {
@@ -555,6 +704,14 @@ public class SimpleLDAPAuthenticationMan
 
     }
 
+    private InitialDirContext createSearchInitialDirContext() throws 
NamingException
+    {
+        Hashtable<String, Object> env = 
createInitialDirContextEnvironment(_providerUrl);
+        setupSearchContext(env, _searchUsername, _searchPassword);
+        return createInitialDirContext(env, _sslSocketFactoryOverrideClass);
+    }
+
+
     @Override
     public boolean isBindWithoutSearch()
     {

Modified: 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
 (original)
+++ 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
 Wed Jun  1 20:12:11 2016
@@ -20,6 +20,8 @@
  */
 package org.apache.qpid.server.security.auth.sasl.plain;
 
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
@@ -32,12 +34,14 @@ import java.io.IOException;
 public class PlainSaslServer implements SaslServer
 {
     public static final String MECHANISM = "PLAIN";
+    public static final String AUTHENTICATION_RESULT = "authentication-result";
 
     private CallbackHandler _cbh;
 
     private String _authorizationId;
 
     private boolean _complete = false;
+    private volatile AuthenticationResult _authenticationResult;
 
     public PlainSaslServer(CallbackHandler cbh)
     {
@@ -63,7 +67,7 @@ public class PlainSaslServer implements
         }
 
         PlainPasswordCallback passwordCb;
-        AuthorizeCallback authzCb;
+        AuthenticationResultPreservingAuthorizeCallback authzCb;
 
         try
         {
@@ -77,10 +81,11 @@ public class PlainSaslServer implements
             // we do not care about the prompt but it throws if null
             NameCallback nameCb = new NameCallback("prompt", authzid);
             passwordCb = new PlainPasswordCallback("prompt", false, pwd);
-            authzCb = new AuthorizeCallback(authzid, authzid);
+            authzCb = new 
AuthenticationResultPreservingAuthorizeCallback(authzid, authzid);
 
             Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb};
             _cbh.handle(callbacks);
+            _authenticationResult = authzCb.getAuthenticationResult();
 
         }
         catch (IOException e)
@@ -154,6 +159,10 @@ public class PlainSaslServer implements
 
     public Object getNegotiatedProperty(String propName)
     {
+        if (AUTHENTICATION_RESULT.equals(propName))
+        {
+            return _authenticationResult;
+        }
         return null;
     }
 
@@ -162,4 +171,22 @@ public class PlainSaslServer implements
         _cbh = null;
     }
 
+    public static class AuthenticationResultPreservingAuthorizeCallback 
extends AuthorizeCallback
+    {
+        private volatile AuthenticationResult _authenticationResult;
+
+        public AuthenticationResultPreservingAuthorizeCallback(String authnID, 
String authzID) {
+            super(authnID, authzID);
+        }
+
+        public AuthenticationResult getAuthenticationResult()
+        {
+            return _authenticationResult;
+        }
+
+        public void setAuthenticationResult(AuthenticationResult 
authenticationResult)
+        {
+            this._authenticationResult = authenticationResult;
+        }
+    }
 }

Modified: 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java
 (original)
+++ 
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java
 Wed Jun  1 20:12:11 2016
@@ -97,4 +97,10 @@ public class GroupPrincipal implements G
             }
         }
     }
+
+    @Override
+    public String toString()
+    {
+        return "GroupPrincipal{" + _groupName + "}";
+    }
 }

Modified: 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
 (original)
+++ 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
 Wed Jun  1 20:12:11 2016
@@ -57,31 +57,18 @@
         </div>
     </div>
     <div class="clear">
-        <div class="formLabel-labelCell tableContainer-labelCell">Search 
context*:</div>
-        <div class="formLabel-controlCell tableContainer-valueCell">
-            <input type="text" class="searchContext"
-                   data-dojo-type="dijit/form/ValidationTextBox"
-                   data-dojo-props="
-                              name: 'searchContext',
-                              required: true,
-                              placeHolder: 'dc=users,dc=example,dc=com',
-                              title: 'Enter search context',
-                              promptMessage: 'Identifies the entry that is the 
base of the subtree containing users'"/>
-        </div>
-    </div>
-    <div class="clear">
-        <div class="formLabel-labelCell tableContainer-labelCell">Search 
filter*:</div>
+        <div class="formLabel-labelCell tableContainer-labelCell">LDAP Context 
Factory:</div>
         <div class="formLabel-controlCell tableContainer-valueCell">
-            <input type="text" class="searchFilter"
+            <input type="text" class="ldapContextFactory"
                    data-dojo-type="dijit/form/ValidationTextBox"
                    data-dojo-props="
-                              name: 'searchFilter',
-                              required: true,
-                              placeHolder: '(uid={0})',
-                              title: 'Enter user search filter ',
-                              promptMessage: 'Filter expression used to locate 
users within the subtree. {0} will be replaced by the user id.'"/>
+                              name: 'ldapContextFactory',
+                              placeHolder: 'com.sun.jndi.ldap.LdapCtxFactory',
+                              title: 'Enter fully qualified class name for 
LDAP Context Factory',
+                              promptMessage: 'Fully qualified class name for 
LDAP Context Factory'"/>
         </div>
     </div>
+
     <div class="clear">
         <div class="formLabel-labelCell tableContainer-labelCell">Search 
username:</div>
         <div class="formLabel-controlCell tableContainer-valueCell">
@@ -106,28 +93,115 @@
                               promptMessage: 'The password to be used with the 
search username'"/>
         </div>
     </div>
-    <div class="clear">
-        <div class="formLabel-labelCell tableContainer-labelCell">Authenticate 
without search:</div>
-        <div class="formLabel-controlCell tableContainer-valueCell">
-            <input type="text" class="bindWithoutSearch" 
id="addAuthenticationProvider.simpleldap.bindWithoutSearch"
-                   data-dojo-type="dijit/form/CheckBox"
-                   data-dojo-props=" name: 'bindWithoutSearch' " />
-        </div>
-    </div>
-    <div data-dojo-type="dijit/Tooltip"
-         data-dojo-props="connectId: 
['addAuthenticationProvider.simpleldap.bindWithoutSearch'],
-                                          label: 'If selected, the provider 
will not search the directory'">
-    </div>
-    <div class="clear">
-        <div class="formLabel-labelCell tableContainer-labelCell">LDAP Context 
Factory:</div>
-        <div class="formLabel-controlCell tableContainer-valueCell">
-            <input type="text" class="ldapContextFactory"
-                   data-dojo-type="dijit/form/ValidationTextBox"
-                   data-dojo-props="
-                              name: 'ldapContextFactory',
-                              placeHolder: 'com.sun.jndi.ldap.LdapCtxFactory',
-                              title: 'Enter fully qualified class name for 
LDAP Context Factory',
-                              promptMessage: 'Fully qualified class name for 
LDAP Context Factory'"/>
-        </div>
+
+    <div class="formBox">
+        <fieldset>
+            <legend>User Search</legend>
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Search context*:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="searchContext"
+                           data-dojo-type="dijit/form/ValidationTextBox"
+                           data-dojo-props="
+                                      name: 'searchContext',
+                                      required: true,
+                                      placeHolder: 
'dc=users,dc=example,dc=com',
+                                      title: 'Enter search context',
+                                      promptMessage: 'Identifies the entry 
that is the base of the subtree containing users'"/>
+                </div>
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Search filter*:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="searchFilter"
+                           data-dojo-type="dijit/form/ValidationTextBox"
+                           data-dojo-props="
+                                      name: 'searchFilter',
+                                      required: true,
+                                      placeHolder: '(uid={0})',
+                                      title: 'Enter user search filter ',
+                                      promptMessage: 'Filter expression used 
to locate users within the subtree. {0} will be replaced by the user id.'"/>
+                </div>
+            </div>
+
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Authenticate without search:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="bindWithoutSearch" 
id="addAuthenticationProvider.simpleldap.bindWithoutSearch".
+                           data-dojo-type="dijit/form/CheckBox"
+                           data-dojo-props=" name: 'bindWithoutSearch' " />
+                </div>
+            </div>
+            <div data-dojo-type="dijit/Tooltip"
+                 data-dojo-props="connectId: 
['addAuthenticationProvider.simpleldap.bindWithoutSearch'],
+                                                  label: 'If selected, the 
provider will not search the directory'">
+            </div>
+        </fieldset>
+    </div>
+
+    <div class="formBox">
+        <fieldset>
+            <legend>Group Search <span 
id="addAuthenticationProvider.simpleldap.groupSearchLegend" 
class="infoPane"></span></legend>
+            <div data-dojo-type="dijit/Tooltip"
+                 data-dojo-props="connectId: 
['addAuthenticationProvider.simpleldap.groupSearchLegend']">
+                There are two common ways of representing group membership in 
LDAP.<br/>
+                User entries can reference their groups or group entries can 
reference their members.<br/>
+                To use the former specify group attribute name.<br/>
+                To use the latter specify search context and filter.<br/>
+                A combination of both approaches can be used.
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Attribute name:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="groupAttributeName"
+                           data-dojo-type="dijit/form/ValidationTextBox"
+                           data-dojo-props="
+                              name: 'groupAttributeName',
+                              placeHolder: 'groupMembership',
+                              title: 'Enter name of user entry attribute 
holding the group name',
+                              promptMessage: 'The user entry attribute name 
holding the group name user belongs to.'"/>
+                </div>
+            </div>
+
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Search context:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="groupSearchContext"
+                           data-dojo-type="dijit/form/ValidationTextBox"
+                           data-dojo-props="
+                                      name: 'groupSearchContext',
+                                      required: true,
+                                      placeHolder: 
'dc=groups,dc=example,dc=com',
+                                      title: 'Enter group search context',
+                                      promptMessage: 'Identifies the entry 
that is the base of the subtree containing groups'"/>
+                </div>
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Search filter:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="groupSearchFilter"
+                           data-dojo-type="dijit/form/ValidationTextBox"
+                           data-dojo-props="
+                                      name: 'groupSearchFilter',
+                                      required: true,
+                                      placeHolder: '(uniquemember={0})',
+                                      title: 'Enter group search filter ',
+                                      promptMessage: 'Filter expression used 
to locate group containing the authenticated user. {0} will be replaced by the 
user DN.'"/>
+                </div>
+            </div>
+
+            <div class="clear">
+                <div class="formLabel-labelCell 
tableContainer-labelCell">Subtree search scope:</div>
+                <div class="formLabel-controlCell tableContainer-valueCell">
+                    <input type="text" class="groupSubtreeSearchScope" 
id="addAuthenticationProvider.simpleldap.groupSubtreeSearchScope"
+                           data-dojo-type="dijit/form/CheckBox"
+                           data-dojo-props=" name: 'groupSubtreeSearchScope' " 
/>
+                </div>
+            </div>
+            <div data-dojo-type="dijit/Tooltip"
+                 data-dojo-props="connectId: 
['addAuthenticationProvider.simpleldap.groupSubtreeSearchScope'],
+                                                  label: 'If selected, the he 
search for group entries is performed in the entire subtree of the group search 
context'">
+            </div>
+        </fieldset>
     </div>
 </div>

Modified: 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/show.html
URL: 
http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/show.html?rev=1746494&r1=1746493&r2=1746494&view=diff
==============================================================================
--- 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/show.html
 (original)
+++ 
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/show.html
 Wed Jun  1 20:12:11 2016
@@ -22,12 +22,16 @@
         <div ><span class="providerUrl" ></span></div>
     </div>
     <div class="clear">
-        <div class="formLabel-labelCell">Search context:</div>
-        <div><span class="searchContext" ></span></div>
+        <div class="formLabel-labelCell">LDAP authentication URL:</div>
+        <div><span class="providerAuthUrl" ></span></div>
+    </div>
+    <div class="clear">
+        <div class="formLabel-labelCell">Trust store:</div>
+        <div><span class="trustStore" ></span></div>
     </div>
     <div class="clear">
-        <div class="formLabel-labelCell">Search filter:</div>
-        <div><span class="searchFilter" ></span></div>
+        <div class="formLabel-labelCell">LDAP context factory:</div>
+        <div><span class="ldapContextFactory" ></span></div>
     </div>
     <div class="clear">
         <div class="formLabel-labelCell">Search user name:</div>
@@ -37,22 +41,49 @@
         <div class="formLabel-labelCell">Search password:</div>
         <div><span class="searchPassword" ></span></div>
     </div>
-    <div class="clear">
-        <div class="formLabel-labelCell">Trust Store:</div>
-        <div><span class="trustStore" ></span></div>
-    </div>
-    <div class="clear">
-        <div class="formLabel-labelCell">Bind without search:</div>
-        <div><span class="bindWithoutSearch" ></span></div>
-    </div>
-    <div class="clear">
-        <div class="formLabel-labelCell">LDAP Context Factory:</div>
-        <div><span class="ldapContextFactory" ></span></div>
-    </div>
-    <div class="clear">
-        <div class="formLabel-labelCell">LDAP authentication URL:</div>
-        <div><span class="providerAuthUrl" ></span></div>
+    <div class="clear"></div>
+
+    <div class="formBox">
+        <fieldset>
+            <legend>User Search</legend>
+            <div class="clear">
+                <div class="formLabel-labelCell">Search context:</div>
+                <div><span class="searchContext" ></span></div>
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell">Search filter:</div>
+                <div><span class="searchFilter" ></span></div>
+            </div>
+
+            <div class="clear">
+                <div class="formLabel-labelCell">Bind without search:</div>
+                <div><span class="bindWithoutSearch" ></span></div>
+            </div>
+        </fieldset>
     </div>
     <div class="clear"></div>
+    <div class="formBox">
+        <fieldset>
+            <legend>Group Search</legend>
+            <div class="clear">
+                <div class="formLabel-labelCell">Attribute name:</div>
+                <div><span class="groupAttributeName" ></span></div>
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell">Search context:</div>
+                <div><span class="groupSearchContext" ></span></div>
+            </div>
+            <div class="clear">
+                <div class="formLabel-labelCell">Search filter:</div>
+                <div><span class="groupSearchFilter" ></span></div>
+            </div>
+
+            <div class="clear">
+                <div class="formLabel-labelCell">Subtree search scope:</div>
+                <div><span class="groupSubtreeSearchScope" ></span></div>
+            </div>
+        </fieldset>
+    </div>
+
 </div>
 



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to