From 78ef03d9a7ca0ed8a550695f96993eb78ed5abf8 Mon Sep 17 00:00:00 2001 From: holgerhagen <19706592+holgerhagen@users.noreply.github.com> Date: Thu, 2 Jul 2020 13:55:54 +0200 Subject: [PATCH] TSK-1321: Fixed user lookup with dn. --- .../taskana/common/rest/ldap/LdapClient.java | 51 +++++++++++++++---- .../rest/AccessIdControllerIntTest.java | 16 ++++++ .../common/rest/ldap/LdapClientTest.java | 5 +- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java index d5d591b77..f81da902f 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/common/rest/ldap/LdapClient.java @@ -6,6 +6,7 @@ import java.util.Comparator; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.PostConstruct; import javax.naming.directory.SearchControls; import org.slf4j.Logger; @@ -66,7 +67,7 @@ public class LdapClient { List accessIds = new ArrayList<>(); if (nameIsDn(name)) { - AccessIdRepresentationModel groupByDn = searchGroupByDn(name); + AccessIdRepresentationModel groupByDn = searchAccessIdByDn(name); if (groupByDn != null) { accessIds.add(groupByDn); } @@ -101,16 +102,12 @@ public class LdapClient { orFilter.or(new WhitespaceWildcardsFilter(getUserIdAttribute(), name)); andFilter.and(orFilter); - String[] userAttributesToReturn = { - getUserFirstnameAttribute(), getUserLastnameAttribute(), getUserIdAttribute() - }; - final List accessIds = ldapTemplate.search( getUserSearchBase(), andFilter.encode(), SearchControls.SUBTREE_SCOPE, - userAttributesToReturn, + getLookUpUserAttributesToReturn(), new UserContextMapper()); LOGGER.debug( "exit from searchUsersByNameOrAccessId. Retrieved the following users: {}.", accessIds); @@ -166,19 +163,19 @@ public class LdapClient { return accessIds; } - public AccessIdRepresentationModel searchGroupByDn(final String name) { - LOGGER.debug("entry to searchGroupByDn(name = {}).", name); + public AccessIdRepresentationModel searchAccessIdByDn(final String dn) { + LOGGER.debug("entry to searchGroupByDn(name = {}).", dn); isInitOrFail(); // Obviously Spring LdapTemplate does have a inconsistency and always adds the base name to the // given DN. // https://stackoverflow.com/questions/55285743/spring-ldaptemplate-how-to-lookup-fully-qualified-dn-with-configured-base-dn // Therefore we have to remove the base name from the dn before performing the lookup - String nameWithoutBaseDn = getNameWithoutBaseDn(name); + String nameWithoutBaseDn = getNameWithoutBaseDn(dn); LOGGER.debug( "Removed baseDN {} from given DN. New DN to be used: {}", getBaseDn(), nameWithoutBaseDn); final AccessIdRepresentationModel accessId = ldapTemplate.lookup( - nameWithoutBaseDn, getLookUpGroupAttributesToReturn(), new GroupContextMapper()); + nameWithoutBaseDn, getLookUpUserAndGroupAttributesToReturn(), new DnContextMapper()); LOGGER.debug("Exit from searchGroupByDn. Retrieved the following group: {}", accessId); return accessId; } @@ -332,6 +329,19 @@ public class LdapClient { return new String[] {getGroupNameAttribute(), CN}; } + String[] getLookUpUserAndGroupAttributesToReturn() { + return Stream.concat( + Arrays.stream(getLookUpUserAttributesToReturn()), + Arrays.stream(getLookUpGroupAttributesToReturn())) + .toArray(String[]::new); + } + + String[] getLookUpUserAttributesToReturn() { + return new String[] { + getUserFirstnameAttribute(), getUserLastnameAttribute(), getUserIdAttribute() + }; + } + @PostConstruct void init() { LOGGER.debug("Entry to init()"); @@ -403,4 +413,25 @@ public class LdapClient { return accessId; } } + + /** General Context Mapper for DNs, which can be both, user or groups. */ + class DnContextMapper extends AbstractContextMapper { + + @Override + public AccessIdRepresentationModel doMapFromContext(final DirContextOperations context) { + final AccessIdRepresentationModel accessId = new AccessIdRepresentationModel(); + String userId = context.getStringAttribute(getUserIdAttribute()); + if (userId != null) { + accessId.setAccessId(userId); + String firstName = context.getStringAttribute(getUserFirstnameAttribute()); + String lastName = context.getStringAttribute(getUserLastnameAttribute()); + accessId.setName(String.format("%s, %s", lastName, firstName)); + } else { + String dn = getDnWithBaseDn(context.getDn().toString()); + accessId.setAccessId(dn); // fully qualified dn + accessId.setName(context.getStringAttribute(getGroupNameAttribute())); + } + return accessId; + } + } } diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/AccessIdControllerIntTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/AccessIdControllerIntTest.java index 48154acb1..7ed28df31 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/AccessIdControllerIntTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/AccessIdControllerIntTest.java @@ -46,6 +46,22 @@ class AccessIdControllerIntTest { .containsExactly("cn=ksc-users,cn=groups,OU=Test,O=TASKANA"); } + @Test + void testQueryUserByDn() { + ResponseEntity response = + TEMPLATE.exchange( + restHelper.toUrl(Mapping.URL_ACCESSID) + + "?search-for=uid=teamlead-1,cn=users,OU=Test,O=TASKANA", + HttpMethod.GET, + restHelper.defaultRequest(), + ParameterizedTypeReference.forType(AccessIdListResource.class)); + assertThat(response.getBody()) + .isNotNull() + .extracting(AccessIdRepresentationModel::getAccessId) + .usingElementComparator(String.CASE_INSENSITIVE_ORDER) + .containsExactly("teamlead-1"); + } + @Test void testQueryGroupsByCn() { ResponseEntity response = diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/ldap/LdapClientTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/ldap/LdapClientTest.java index 956012f4f..e86a36406 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/ldap/LdapClientTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/common/rest/ldap/LdapClientTest.java @@ -42,11 +42,10 @@ class LdapClientTest { setUpEnvMock(); cut.init(); - cut.searchGroupByDn("cn=developersgroup,ou=groups,o=taskanatest"); + cut.searchAccessIdByDn("cn=developersgroup,ou=groups,o=taskanatest"); verify(ldapTemplate) - .lookup( - eq("cn=developersgroup,ou=groups"), any(), any(LdapClient.GroupContextMapper.class)); + .lookup(eq("cn=developersgroup,ou=groups"), any(), any(LdapClient.DnContextMapper.class)); } @Test