TSK-1634: Endpoint in AccessIdController to search users and members of groups configured with TASKANA user role

This commit is contained in:
Joerg Heffner 2021-05-05 14:16:45 +02:00 committed by gitgoodjhe
parent 4c94281a64
commit 38363b81d6
11 changed files with 134 additions and 1 deletions

View File

@ -14,6 +14,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=cn=groups
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupOfUniqueNames

View File

@ -68,6 +68,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupofuniquenames

View File

@ -24,6 +24,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=cn=groups
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupOfUniqueNames

View File

@ -19,6 +19,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupOfUniqueNames

View File

@ -19,6 +19,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupOfUniqueNames

View File

@ -62,6 +62,47 @@ public class AccessIdController {
return response;
}
/**
* This endpoint searches users for a provided name or Access Id. It will only search and return
* users and members of groups which are configured with the requested TASKANA role. This
* search will only work if the users in the configured LDAP have an attribute that shows their
* group memberships, e.g. "memberOf"
*
* @title Search for Access Id (users) in TASKANA user role
* @param nameOrAccessId the name or Access Id which should be searched for.
* @param role the role for which all users should be searched for
* @return a list of all found Access Ids (users)
* @throws InvalidArgumentException if the provided search for Access Id is shorter than the
* configured one.
*/
@GetMapping(path = RestEndpoints.URL_USER)
public ResponseEntity<List<AccessIdRepresentationModel>> searchUsersByNameOrAccessIdForRole(
@RequestParam("search-for") String nameOrAccessId, @RequestParam("role") String role)
throws InvalidArgumentException {
LOGGER.debug(
"Entry to searchUsersByNameOrAccessIdForRole(search-for= {}, role= {})",
nameOrAccessId,
role);
if (role.equals("user")) {
List<AccessIdRepresentationModel> accessIdUsers =
ldapClient.searchUsersByNameOrAccessIdInUserRole(nameOrAccessId);
ResponseEntity<List<AccessIdRepresentationModel>> response = ResponseEntity.ok(accessIdUsers);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"Exit from searchUsersByNameOrAccessIdForRole(), returning {}", response);
}
return response;
} else {
throw new InvalidArgumentException(
String.format(
"Requested users for not supported role %s. Only role 'user' is supported'", role));
}
}
/**
* This endpoint retrieves all groups a given Access Id belongs to.
*

View File

@ -17,6 +17,7 @@ public final class RestEndpoints {
// access id endpoints
public static final String URL_ACCESS_ID = API_V1 + "access-ids";
public static final String URL_USER = API_V1 + "users";
public static final String URL_ACCESS_ID_GROUPS = API_V1 + "access-ids/groups";
// import / export endpoints

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -23,6 +24,8 @@ import org.springframework.ldap.filter.WhitespaceWildcardsFilter;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.stereotype.Component;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.rest.models.AccessIdRepresentationModel;
@ -34,6 +37,7 @@ public class LdapClient {
private static final Logger LOGGER = LoggerFactory.getLogger(LdapClient.class);
private static final String CN = "cn";
private final TaskanaEngineConfiguration taskanaEngineConfiguration;
private final Environment env;
private final LdapTemplate ldapTemplate;
private boolean active = false;
@ -42,9 +46,13 @@ public class LdapClient {
private String message;
@Autowired
public LdapClient(Environment env, LdapTemplate ldapTemplate) {
public LdapClient(
Environment env,
LdapTemplate ldapTemplate,
TaskanaEngineConfiguration taskanaEngineConfiguration) {
this.env = env;
this.ldapTemplate = ldapTemplate;
this.taskanaEngineConfiguration = taskanaEngineConfiguration;
}
/**
@ -83,6 +91,49 @@ public class LdapClient {
return result;
}
public List<AccessIdRepresentationModel> searchUsersByNameOrAccessIdInUserRole(
final String nameOrAccessId) throws InvalidArgumentException {
LOGGER.debug(
"entry to searchUsersByNameOrAccessIdInUserRoleGroups(nameOrAccessId = {}).",
nameOrAccessId);
isInitOrFail();
testMinSearchForLength(nameOrAccessId);
final OrFilter userDetailsOrFilter = new OrFilter();
userDetailsOrFilter.or(
new WhitespaceWildcardsFilter(getUserFirstnameAttribute(), nameOrAccessId));
userDetailsOrFilter.or(
new WhitespaceWildcardsFilter(getUserLastnameAttribute(), nameOrAccessId));
userDetailsOrFilter.or(
new WhitespaceWildcardsFilter(getUserFullnameAttribute(), nameOrAccessId));
userDetailsOrFilter.or(new WhitespaceWildcardsFilter(getUserIdAttribute(), nameOrAccessId));
Set<String> userGroups = taskanaEngineConfiguration.getRoleMap().get(TaskanaRole.USER);
final OrFilter groupMembershipOrFilter = new OrFilter();
userGroups.forEach(
group ->
groupMembershipOrFilter.or(new EqualsFilter(getUserMemberOfGroupAttribute(), group)));
final AndFilter andFilter = new AndFilter();
andFilter.and(userDetailsOrFilter);
andFilter.and(groupMembershipOrFilter);
final List<AccessIdRepresentationModel> accessIds =
ldapTemplate.search(
getUserSearchBase(),
andFilter.encode(),
SearchControls.SUBTREE_SCOPE,
getLookUpUserAttributesToReturn(),
new UserContextMapper());
LOGGER.debug(
"exit from searchUsersByNameOrAccessIdInUserRoleGroups. Retrieved the following users: {}.",
accessIds);
return accessIds;
}
public List<AccessIdRepresentationModel> searchUsersByNameOrAccessId(final String name)
throws InvalidArgumentException {
LOGGER.debug("entry to searchUsersByNameOrAccessId(name = {}).", name);
@ -278,6 +329,10 @@ public class LdapClient {
return LdapSettings.TASKANA_LDAP_USER_ID_ATTRIBUTE.getValueFromEnv(env);
}
public String getUserMemberOfGroupAttribute() {
return LdapSettings.TASKANA_LDAP_USER_MEMBER_OF_GROUP_ATTRIBUTE.getValueFromEnv(env);
}
public String getGroupSearchBase() {
return LdapSettings.TASKANA_LDAP_GROUP_SEARCH_BASE.getValueFromEnv(env);
}

View File

@ -11,6 +11,7 @@ enum LdapSettings {
TASKANA_LDAP_USER_LASTNAME_ATTRIBUTE("taskana.ldap.userLastnameAttribute"),
TASKANA_LDAP_USER_FULLNAME_ATTRIBUTE("taskana.ldap.userFullnameAttribute"),
TASKANA_LDAP_USER_ID_ATTRIBUTE("taskana.ldap.userIdAttribute"),
TASKANA_LDAP_USER_MEMBER_OF_GROUP_ATTRIBUTE("taskana.ldap.userMemberOfGroupAttribute"),
TASKANA_LDAP_GROUP_SEARCH_BASE("taskana.ldap.groupSearchBase"),
TASKANA_LDAP_BASE_DN("taskana.ldap.baseDn"),
TASKANA_LDAP_GROUP_SEARCH_FILTER_NAME("taskana.ldap.groupSearchFilterName"),

View File

@ -11,7 +11,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@ -23,6 +26,8 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.env.Environment;
import org.springframework.ldap.core.LdapTemplate;
import pro.taskana.TaskanaEngineConfiguration;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.rest.models.AccessIdRepresentationModel;
@ -33,6 +38,8 @@ class LdapClientTest {
@Mock LdapTemplate ldapTemplate;
@Mock TaskanaEngineConfiguration taskanaEngineConfiguration;
@InjectMocks LdapClient cut;
@Test
@ -90,6 +97,27 @@ class LdapClientTest {
assertThat(accessIds.get(3).getAccessId()).isNull();
}
@Test
void should_ReturnAllUsersAndMembersOfGroupsWithTaskanaUserRole() throws Exception {
setUpEnvMock();
cut.init();
AccessIdRepresentationModel user = new AccessIdRepresentationModel("testU", "testUId");
Set<String> groupsOfUserRole = new HashSet<>();
Map<TaskanaRole, Set<String>> roleMap = new HashMap<>();
roleMap.put(TaskanaRole.USER, groupsOfUserRole);
when(taskanaEngineConfiguration.getRoleMap()).thenReturn(roleMap);
when(ldapTemplate.search(
any(String.class), any(), anyInt(), any(), any(LdapClient.UserContextMapper.class)))
.thenReturn(List.of(user));
assertThat(cut.searchUsersByNameOrAccessIdInUserRole("test")).hasSize(1).containsExactly(user);
}
@Test
void testLdap_getNameWithoutBaseDn() {
@ -159,6 +187,7 @@ class LdapClientTest {
{"taskana.ldap.groupSearchFilterName", "objectclass"},
{"taskana.ldap.groupSearchBase", "ou=groups"},
{"taskana.ldap.userIdAttribute", "uid"},
{"taskana.ldap.userMemberOfGroupAttribute", "memberOf"},
{"taskana.ldap.userLastnameAttribute", "sn"},
{"taskana.ldap.userFirstnameAttribute", "givenName"},
{"taskana.ldap.userFullnameAttribute", "cn"},

View File

@ -23,6 +23,7 @@ taskana.ldap.userFirstnameAttribute=givenName
taskana.ldap.userLastnameAttribute=sn
taskana.ldap.userFullnameAttribute=cn
taskana.ldap.userIdAttribute=uid
taskana.ldap.userMemberOfGroupAttribute=
taskana.ldap.groupSearchBase=
taskana.ldap.groupSearchFilterName=objectclass
taskana.ldap.groupSearchFilterValue=groupOfUniqueNames