multi tenant LDAP user isolation
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");
}