cancel
Showing results for 
Search instead for 
Did you mean: 

multi tenant LDAP user isolation

Bauke_Roo
Star Contributor
Star Contributor

Hi there,

I'm using nuxeo 5.8HF10 in combination with LDAP.

I'm experiencing the following situation:

usera - tenantA
userb - tenantB

usera is a tenantA administrator. When searching in the admin center (users&groups) userb appears in the list.

How can we isolate the users?

I'm using the following LDAP configuration:

<fieldMapping name="username">email</fieldMapping>
<fieldMapping name="password">userpass</fieldMapping>
<fieldMapping name="firstName">name</fieldMapping>
<fieldMapping name="lastName">secondname</fieldMapping>
<fieldMapping name="company">organisation</fieldMapping>
<fieldMapping name="tenantId">organisation</fieldMapping>
<fieldMapping name="email">email</fieldMapping>

I think it is somewhere in the LDAP part, as running on a local machine without the LDAP it seems to work fine.

Do I need to configure the LDAP somehow different?

Thanks in advance, Bauke Roo


I've started working on this again and made some progress. It seems it is not needed to implement a new usermanager. The first change I made is a new operation based SuggestUserEntries.java, adding a filter in the run method. The code is at the bottom of this post.

I'm still experiencing an issue in the admin panel when searching for users these seem to be multi-tenant fit yet. the following ajax call is made to /nuxeo/view_admin.faces:

AJAX:EVENTS_COUNT	1
AJAXREQUEST	usersListingView:search_users_region
autoScroll	
javax.faces.ViewState	j_id7
usersListingView:searchFo...	usersListingView:searchForm
usersListingView:searchFo...	usersListingView:searchForm
usersListingView:searchFo...	Search
usersListingView:searchFo...	test

I cannot find in which class this call/method is executed, can someone please help?


update The search seems to be executed in the org.nuxeo.ecm.platform.usermanager.providers.UsersPageProvider

My plan is to create a new page provider in order to add a filter in the methods. The question now is: How can I get the tenantId of the users in this pageProvider?

I've tried passing it in the pageproviders-contrib.xml:

 <extension target="org.nuxeo.ecm.platform.query.api.PageProviderService"
    point="providers">

    <genericPageProvider name="users_listing"
      class="org.nuxeo.capgemini.LDAPMultiTenancyPageProvider">
      <pageSize>20</pageSize>
      <property name="tenantId">#{currentUser.tenantId}</property>
    </genericPageProvider>
   </extension>

However this just returns #{currentUser.tenantId} in the java code.

Is there a way to get the userInfo in a pageprovider?


code below

Custom method for the new operation based on SuggestUserEntries.java:

 @OperationMethod
    public Blob run() throws ClientException {
    	
    	if(prefix.isEmpty())
    	{
    		prefix = searchTerm;
    	}
        JSONArray result = new JSONArray();
        boolean isGroupRestriction = !StringUtils.isBlank(groupRestriction);
        boolean groupOnly = false;
        boolean userOnly = isGroupRestriction;

        if (!isGroupRestriction && searchType != null && !searchType.isEmpty()) {
            if (searchType.equals(Select2Common.USER_TYPE)) {
                userOnly = true;
            } else if (searchType.equals(Select2Common.GROUP_TYPE)) {
                groupOnly = true;
            }
        }
        try {
            ArrayList<DocumentModel> userList = new ArrayList<DocumentModel>();
            DocumentModelList groupList = null;
            if (!groupOnly) {
            	log.info("userManager: "+userManager.getUserSchemaName());
                Schema schema = schemaManager.getSchema(userManager.getUserSchemaName());
                
                //changed this
                MultiTenantPrincipal principal = (MultiTenantPrincipal) ctx.getPrincipal();
                String tenantId = principal.getTenantId();
                
                for (String field : FULLTEXT_FIELDS) {
                    Map<String, Serializable> filter = new HashMap<String, Serializable>();
                    filter.put(field, prefix);

                    if (!StringUtils.isBlank(tenantId)) {
                        filter.put("tenantId", tenantId);
                    }

                    userList.addAll(userManager.searchUsers(filter, filter.keySet()));
                    
                }
                userList = removeDuplicates(userList);
                //changed this
                
                
                Directory userDir = directoryService.getDirectory(userManager.getUserDirectoryName());
                for (DocumentModel user : userList) {
                    JSONObject obj = new JSONObject();
                    for (Field field : schema.getFields()) {
                        QName fieldName = field.getName();
                        String key = fieldName.getLocalName();
                        Serializable value = user.getPropertyValue(fieldName.getPrefixedName());
                        if (key.equals(userDir.getPasswordField())) {
                            continue;
                        }
                        obj.element(key, value);
                    }
                    String userId = user.getId();
                    obj.put(Select2Common.ID, userId);
                    obj.put(Select2Common.TYPE_KEY_NAME,
                            Select2Common.USER_TYPE);
                    obj.put(Select2Common.PREFIXED_ID_KEY_NAME,
                            NuxeoPrincipal.PREFIX + userId);
                    Select2Common.computeUserLabel(obj, firstLabelField,
                            secondLabelField, thirdLabelField, hideFirstLabel,
                            hideSecondLabel, hideThirdLabel,
                            displayEmailInSuggestion, userId);
                    Select2Common.computeUserGroupIcon(obj, hideIcon);
                    if (isGroupRestriction) {
                        // We need to load all data about the user particularly
                        // its
                        // groups.
                        user = userManager.getUserModel(userId);
                        UserAdapter userAdapter = user.getAdapter(UserAdapter.class);
                        List<String> groups = userAdapter.getGroups();
                        if (groups != null && groups.contains(groupRestriction)) {
                            result.add(obj);
                        }
                    } else {
                        result.add(obj);
                    }
                }
            }
            if (!userOnly) {
                Schema schema = schemaManager.getSchema(userManager.getGroupSchemaName());
                groupList = userManager.searchGroups(prefix);
                for (DocumentModel group : groupList) {
                    JSONObject obj = new JSONObject();
                    for (Field field : schema.getFields()) {
                        QName fieldName = field.getName();
                        String key = fieldName.getLocalName();
                        Serializable value = group.getPropertyValue(fieldName.getPrefixedName());
                        obj.element(key, value);
                    }
                    String groupId = group.getId();
                    obj.put(Select2Common.ID, groupId);
                    // If the group hasn't an label, let's put the groupid
                    Select2Common.computeGroupLabel(obj, groupId,
                            userManager.getGroupLabelField(), hideFirstLabel);
                    obj.put(Select2Common.TYPE_KEY_NAME,
                            Select2Common.GROUP_TYPE);
                    obj.put(Select2Common.PREFIXED_ID_KEY_NAME,
                            NuxeoGroup.PREFIX + groupId);
                    Select2Common.computeUserGroupIcon(obj, hideIcon);
                    result.add(obj);
                }
            }

            // Limit size results.
            int userSize = userList != null ? userList.size() : 0;
            int groupSize = groupList != null ? groupList.size() : 0;
            int totalSize = userSize + groupSize;
            if (userSuggestionMaxSearchResults != null
                    && userSuggestionMaxSearchResults > 0) {
                if (userSize > userSuggestionMaxSearchResults
                        || groupSize > userSuggestionMaxSearchResults
                        || totalSize > userSuggestionMaxSearchResults) {
                    throw new SizeLimitExceededException();
                }
            }

        } catch (SizeLimitExceededException e) {
            return searchOverflowMessage();
        }

        return new StringBlob(result.toString(), "application/json");
    }
5 REPLIES 5

Esheng_
Champ on-the-rise
Champ on-the-rise

no reply, why?

promanov_
Star Contributor
Star Contributor

I'm interested in the answer as well, any clue?

Bauke_Roo
Star Contributor
Star Contributor

For now it seems it is not possible. I believe that in order to make this work a new usermanagerImpl class has to be written.

promanov_
Star Contributor
Star Contributor

thanks for your feedback

mathias_lin
Star Contributor
Star Contributor

I'm new to Nuxeo and also interested in this question and since it's already almost 3 years old, I wonder if anything has changed? Can I use a different Active Directory server for each tenant (without writing custom implementations from scratch)? Thanks!

Getting started

Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.