private DirSearch createDirSearch(String user, String password) throws AuthenticationException { if (StringUtils.isBlank(user)) { throw new AuthenticationException("Error validating LDAP user:" + " a null or blank user name has been provided"); } if (StringUtils.isBlank(password) || password.getBytes()[0] == 0) { throw new AuthenticationException("Error validating LDAP user:" + " a null or blank password has been provided"); } List<String> principals = LdapUtils.createCandidatePrincipals(conf, user); for (Iterator<String> iterator = principals.iterator(); iterator.hasNext();) { String principal = iterator.next(); try { return searchFactory.getInstance(conf, principal, password); } catch (AuthenticationException ex) { if (!iterator.hasNext()) { throw ex; } } } throw new AuthenticationException( String.format("No candidate principals for %s was found.", user)); }
/** * {@inheritDoc} */ @Override public String findUserDn(String user) throws NamingException { List<String> allLdapNames; if (LdapUtils.isDn(user)) { String userBaseDn = LdapUtils.extractBaseDn(user); String userRdn = LdapUtils.extractFirstRdn(user); allLdapNames = execute(Collections.singletonList(userBaseDn), queries.findUserDnByRdn(userRdn)).getAllLdapNames(); } else { allLdapNames = findDnByPattern(userPatterns, user); if (allLdapNames.isEmpty()) { allLdapNames = execute(userBases, queries.findUserDnByName(user)).getAllLdapNames(); } } if (allLdapNames.size() == 1) { return allLdapNames.get(0); } else { LOG.info("Expected exactly one user result for the user: {}, but got {}. Returning null", user, allLdapNames.size()); LOG.debug("Matched users: {}", allLdapNames); return null; } }
private void applyFilter(DirSearch client, String user) throws AuthenticationException { if (filter != null) { if (LdapUtils.hasDomain(user)) { filter.apply(client, LdapUtils.extractUserName(user)); } else { filter.apply(client, user); } } } }
/** * Construct an instance of {@code LdapSearch}. * @param conf Hive configuration * @param ctx Directory service that will be used for the queries. * @throws NamingException */ public LdapSearch(HiveConf conf, DirContext ctx) throws NamingException { baseDn = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN); userPatterns = LdapUtils.parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN); groupBases = LdapUtils.patternsToBaseDns(LdapUtils.parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN)); userBases = LdapUtils.patternsToBaseDns(userPatterns); this.ctx = ctx; queries = new QueryFactory(conf); }
private List<String> findDnByPattern(List<String> patterns, String name) throws NamingException { for (String pattern : patterns) { String baseDnFromPattern = LdapUtils.extractBaseDn(pattern); String rdn = LdapUtils.extractFirstRdn(pattern).replaceAll("%s", name); List<String> list = execute(Collections.singletonList(baseDnFromPattern), queries.findDnByPattern(rdn)).getAllLdapNames(); if (!list.isEmpty()) { return list; } } return Collections.emptyList(); }
/** * Creates a list of principals to be used for user authentication. * @param conf Hive configuration * @param user username * @return a list of user's principals */ public static List<String> createCandidatePrincipals(HiveConf conf, String user) { if (hasDomain(user) || isDn(user)) { return Collections.singletonList(user); } String ldapDomain = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_DOMAIN); if (StringUtils.isNotBlank(ldapDomain)) { return Collections.singletonList(user + "@" + ldapDomain); } List<String> userPatterns = parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN); if (userPatterns.isEmpty()) { return Collections.singletonList(user); } List<String> candidatePrincipals = new ArrayList<>(); for (String userPattern : userPatterns) { candidatePrincipals.add(userPattern.replaceAll("%s", user)); } return candidatePrincipals; }
@Test public void testExtractBaseDnNegative() { String dn = "cn=user1"; assertNull(LdapUtils.extractBaseDn(dn)); } }
/** * Extracts username from user DN. * <br> * <b>Examples:</b> * <pre> * LdapUtils.extractUserName("UserName") = "UserName" * LdapUtils.extractUserName("UserName@mycorp.com") = "UserName" * LdapUtils.extractUserName("cn=UserName,dc=mycompany,dc=com") = "UserName" * </pre> * @param userDn * @return */ public static String extractUserName(String userDn) { if (!isDn(userDn) && !hasDomain(userDn)) { return userDn; } int domainIdx = ServiceUtils.indexOfDomainMatch(userDn); if (domainIdx > 0) { return userDn.substring(0, domainIdx); } if (userDn.contains("=")) { return userDn.substring(userDn.indexOf("=") + 1, userDn.indexOf(",")); } return userDn; }
@Test public void testExtractFirstRdn() { String dn = "cn=user1,ou=CORP1,dc=mycompany,dc=com"; String expected = "cn=user1"; String actual = LdapUtils.extractFirstRdn(dn); assertEquals(expected, actual); }
@Override public void apply(DirSearch ldap, String user) throws AuthenticationException { LOG.info("Authenticating user '{}' using user filter", user); String userName = LdapUtils.extractUserName(user).toLowerCase(); if (!userFilter.contains(userName)) { LOG.info("Authentication failed based on user membership"); throw new AuthenticationException("Authentication failed: " + "User not a member of specified list"); } } }
@Override public void apply(DirSearch client, String user) throws AuthenticationException { List<String> resultList; try { resultList = client.executeCustomQuery(query); } catch (NamingException e) { throw new AuthenticationException("LDAP Authentication failed for user", e); } if (resultList != null) { for (String matchedDn : resultList) { String shortUserName = LdapUtils.getShortName(matchedDn); LOG.info("<queried user=" + shortUserName + ",user=" + user + ">"); if (shortUserName.equalsIgnoreCase(user) || matchedDn.equalsIgnoreCase(user)) { LOG.info("Authentication succeeded based on result set from LDAP query"); return; } } } LOG.info("Authentication failed based on result set from custom LDAP query"); throw new AuthenticationException("Authentication failed: LDAP query " + "from property returned no data"); } }
/** * Converts a collection of Distinguished Name patterns to a collection of base DNs. * @param patterns Distinguished Name patterns * @return a list of base DNs * @see HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN * @see HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN */ public static List<String> patternsToBaseDns(Collection<String> patterns) { List<String> result = new ArrayList<>(); for (String pattern : patterns) { result.add(patternToBaseDn(pattern)); } return result; }
private List<String> findDnByPattern(List<String> patterns, String name) throws NamingException { for (String pattern : patterns) { String baseDnFromPattern = LdapUtils.extractBaseDn(pattern); String rdn = LdapUtils.extractFirstRdn(pattern).replaceAll("%s", name); List<String> list = execute(Collections.singletonList(baseDnFromPattern), queries.findDnByPattern(rdn)).getAllLdapNames(); if (!list.isEmpty()) { return list; } } return Collections.emptyList(); }
/** * Creates a list of principals to be used for user authentication. * @param conf Hive configuration * @param user username * @return a list of user's principals */ public static List<String> createCandidatePrincipals(HiveConf conf, String user) { if (hasDomain(user) || isDn(user)) { return Collections.singletonList(user); } String ldapDomain = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_DOMAIN); if (StringUtils.isNotBlank(ldapDomain)) { return Collections.singletonList(user + "@" + ldapDomain); } List<String> userPatterns = parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN); if (userPatterns.isEmpty()) { return Collections.singletonList(user); } List<String> candidatePrincipals = new ArrayList<>(); for (String userPattern : userPatterns) { candidatePrincipals.add(userPattern.replaceAll("%s", user)); } return candidatePrincipals; }
@Test public void testExtractBaseDn() { String dn = "cn=user1,ou=CORP1,dc=mycompany,dc=com"; String expected = "ou=CORP1,dc=mycompany,dc=com"; String actual = LdapUtils.extractBaseDn(dn); assertEquals(expected, actual); }
/** * Construct an instance of {@code LdapSearch}. * @param conf Hive configuration * @param ctx Directory service that will be used for the queries. * @throws NamingException */ public LdapSearch(HiveConf conf, DirContext ctx) throws NamingException { baseDn = conf.getVar(HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_BASEDN); userPatterns = LdapUtils.parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN); groupBases = LdapUtils.patternsToBaseDns(LdapUtils.parseDnPatterns(conf, HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN)); userBases = LdapUtils.patternsToBaseDns(userPatterns); this.ctx = ctx; queries = new QueryFactory(conf); }
/** * Extracts username from user DN. * <br> * <b>Examples:</b> * <pre> * LdapUtils.extractUserName("UserName") = "UserName" * LdapUtils.extractUserName("UserName@mycorp.com") = "UserName" * LdapUtils.extractUserName("cn=UserName,dc=mycompany,dc=com") = "UserName" * </pre> * @param userDn * @return */ public static String extractUserName(String userDn) { if (!isDn(userDn) && !hasDomain(userDn)) { return userDn; } int domainIdx = ServiceUtils.indexOfDomainMatch(userDn); if (domainIdx > 0) { return userDn.substring(0, domainIdx); } if (userDn.contains("=")) { return userDn.substring(userDn.indexOf("=") + 1, userDn.indexOf(",")); } return userDn; }
/** * {@inheritDoc} */ @Override public List<String> findGroupsForUser(String userDn) throws NamingException { String userName = LdapUtils.extractUserName(userDn); return execute(groupBases, queries.findGroupsForUser(userName, userDn)).getAllLdapNames(); }
@Override public void apply(DirSearch ldap, String user) throws AuthenticationException { LOG.info("Authenticating user '{}' using {}", user, GroupMembershipKeyFilter.class.getSimpleName()); List<String> memberOf = null; try { String userDn = ldap.findUserDn(user); memberOf = ldap.findGroupsForUser(userDn); LOG.debug("User {} member of : {}", userDn, memberOf); } catch (NamingException e) { throw new AuthenticationException("LDAP Authentication failed for user", e); } for (String groupDn : memberOf) { String shortName = LdapUtils.getShortName(groupDn); if (groupFilter.contains(shortName)) { LOG.debug("GroupMembershipKeyFilter passes: user '{}' is a member of '{}' group", user, groupDn); LOG.info("Authentication succeeded based on group membership"); return; } } LOG.info("Authentication failed based on user membership"); throw new AuthenticationException("Authentication failed: " + "User not a member of specified list"); } }
/** * Converts a collection of Distinguished Name patterns to a collection of base DNs. * @param patterns Distinguished Name patterns * @return a list of base DNs * @see HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_GROUPDNPATTERN * @see HiveConf.ConfVars.HIVE_SERVER2_PLAIN_LDAP_USERDNPATTERN */ public static List<String> patternsToBaseDns(Collection<String> patterns) { List<String> result = new ArrayList<>(); for (String pattern : patterns) { result.add(patternToBaseDn(pattern)); } return result; }