/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.zeppelin.rest; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.shiro.realm.jdbc.JdbcRealm; import org.apache.shiro.realm.ldap.JndiLdapContextFactory; import org.apache.shiro.realm.ldap.JndiLdapRealm; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.util.JdbcUtils; import org.apache.zeppelin.realm.ActiveDirectoryGroupRealm; import org.apache.zeppelin.realm.LdapRealm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.NamingEnumeration; import javax.naming.directory.Attributes; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.LdapContext; import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; /** * This is class which help fetching users from different realms. * getUserList() function is overloaded and according to the realm passed to the function it * extracts users from its respective realm */ public class GetUserList { private static final Logger LOG = LoggerFactory.getLogger(GetUserList.class); /** * function to extract users from shiro.ini */ public List<String> getUserList(IniRealm r) { List<String> userList = new ArrayList<>(); Map getIniUser = r.getIni().get("users"); if (getIniUser != null) { Iterator it = getIniUser.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); userList.add(pair.getKey().toString().trim()); } } return userList; } /*** * Get user roles from shiro.ini * @param r * @return */ public List<String> getRolesList(IniRealm r) { List<String> roleList = new ArrayList<>(); Map getIniRoles = r.getIni().get("roles"); if (getIniRoles != null) { Iterator it = getIniRoles.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); roleList.add(pair.getKey().toString().trim()); } } return roleList; } /** * function to extract users from LDAP */ public List<String> getUserList(JndiLdapRealm r, String searchText) { List<String> userList = new ArrayList<>(); String userDnTemplate = r.getUserDnTemplate(); String userDn[] = userDnTemplate.split(",", 2); String userDnPrefix = userDn[0].split("=")[0]; String userDnSuffix = userDn[1]; JndiLdapContextFactory CF = (JndiLdapContextFactory) r.getContextFactory(); try { LdapContext ctx = CF.getSystemLdapContext(); SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); String[] attrIDs = {userDnPrefix}; constraints.setReturningAttributes(attrIDs); NamingEnumeration result = ctx.search(userDnSuffix, "(" + userDnPrefix + "=*" + searchText + "*)", constraints); while (result.hasMore()) { Attributes attrs = ((SearchResult) result.next()).getAttributes(); if (attrs.get(userDnPrefix) != null) { String currentUser = attrs.get(userDnPrefix).toString(); userList.add(currentUser.split(":")[1].trim()); } } } catch (Exception e) { LOG.error("Error retrieving User list from Ldap Realm", e); } LOG.info("UserList: " + userList); return userList; } /** * function to extract users from Zeppelin LdapRealm */ public List<String> getUserList(LdapRealm r, String searchText) { List<String> userList = new ArrayList<>(); if (LOG.isDebugEnabled()) { LOG.debug("SearchText: " + searchText); } String userAttribute = r.getUserSearchAttributeName(); String userSearchRealm = r.getUserSearchBase(); String userObjectClass = r.getUserObjectClass(); JndiLdapContextFactory CF = (JndiLdapContextFactory) r.getContextFactory(); try { LdapContext ctx = CF.getSystemLdapContext(); SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); String[] attrIDs = {userAttribute}; constraints.setReturningAttributes(attrIDs); NamingEnumeration result = ctx.search(userSearchRealm, "(&(objectclass=" + userObjectClass + ")(" + userAttribute + "=" + searchText + "))", constraints); while (result.hasMore()) { Attributes attrs = ((SearchResult) result.next()).getAttributes(); if (attrs.get(userAttribute) != null) { String currentUser; if (r.getUserLowerCase()) { LOG.debug("userLowerCase true"); currentUser = ((String) attrs.get(userAttribute).get()).toLowerCase(); } else { LOG.debug("userLowerCase false"); currentUser = (String) attrs.get(userAttribute).get(); } if (LOG.isDebugEnabled()) { LOG.debug("CurrentUser: " + currentUser); } userList.add(currentUser.trim()); } } } catch (Exception e) { LOG.error("Error retrieving User list from Ldap Realm", e); } return userList; } /*** * Get user roles from shiro.ini for Zeppelin LdapRealm * @param r * @return */ public List<String> getRolesList(LdapRealm r) { List<String> roleList = new ArrayList<>(); Map<String, String> roles = r.getListRoles(); if (roles != null) { Iterator it = roles.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = (Map.Entry) it.next(); if (LOG.isDebugEnabled()) { LOG.debug("RoleKeyValue: " + pair.getKey() + " = " + pair.getValue()); } roleList.add((String) pair.getKey()); } } return roleList; } public List<String> getUserList(ActiveDirectoryGroupRealm r, String searchText) { List<String> userList = new ArrayList<>(); try { LdapContext ctx = r.getLdapContextFactory().getSystemLdapContext(); userList = r.searchForUserName(searchText, ctx); } catch (Exception e) { LOG.error("Error retrieving User list from ActiveDirectory Realm", e); } return userList; } /** * function to extract users from JDBCs */ public List<String> getUserList(JdbcRealm obj) { List<String> userlist = new ArrayList<>(); PreparedStatement ps = null; ResultSet rs = null; DataSource dataSource = null; String authQuery = ""; String retval[]; String tablename = ""; String username = ""; String userquery = ""; try { dataSource = (DataSource) FieldUtils.readField(obj, "dataSource", true); authQuery = (String) FieldUtils.readField(obj, "DEFAULT_AUTHENTICATION_QUERY", true); LOG.info(authQuery); String authQueryLowerCase = authQuery.toLowerCase(); retval = authQueryLowerCase.split("from", 2); if (retval.length >= 2) { retval = retval[1].split("with|where", 2); tablename = retval[0]; retval = retval[1].split("where", 2); if (retval.length >= 2) retval = retval[1].split("=", 2); else retval = retval[0].split("=", 2); username = retval[0]; } if (StringUtils.isBlank(username) || StringUtils.isBlank(tablename)) { return userlist; } userquery = "select " + username + " from " + tablename; } catch (IllegalAccessException e) { LOG.error("Error while accessing dataSource for JDBC Realm", e); return null; } try { Connection con = dataSource.getConnection(); ps = con.prepareStatement(userquery); rs = ps.executeQuery(); while (rs.next()) { userlist.add(rs.getString(1).trim()); } } catch (Exception e) { LOG.error("Error retrieving User list from JDBC Realm", e); } finally { JdbcUtils.closeResultSet(rs); JdbcUtils.closeStatement(ps); } return userlist; } }