[New] added config for privilege handler, add ldap handler

This commit is contained in:
Reto Breitenmoser 2018-07-08 13:58:37 +02:00
parent 3ccfc3e942
commit 6deafccb33
6 changed files with 215 additions and 5 deletions

View File

@ -1255,7 +1255,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
* @throws InvalidCredentialsException
* if the given credentials are invalid, the user does not exist, or has no password set
*/
private synchronized User checkCredentialsAndUserState(String username, char[] password)
protected synchronized User checkCredentialsAndUserState(String username, char[] password)
throws InvalidCredentialsException, AccessDeniedException {
// and validate the password
@ -1519,7 +1519,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
}
/**
* Initializes the concrete {@link EncryptionHandler}. The passed parameter map contains any configuration this
* Initializes the concrete {@link PrivilegeHandler}. The passed parameter map contains any configuration this
* {@link PrivilegeHandler} might need. This method may only be called once and this must be enforced by the
* concrete implementation
*

View File

@ -0,0 +1,160 @@
package li.strolch.privilege.handler;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
public class LdapPrivilegeHandler extends DefaultPrivilegeHandler {
protected static final Logger logger = LoggerFactory.getLogger(LdapPrivilegeHandler.class);
private Map<String, Set<String>> rolesForLdapGroups;
private String providerUrl;
private String searchBase;
private String location;
private String domain;
private String adminUsers;
@Override
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
rolesForLdapGroups = getLdapGroupToRolesMappingFromConfig(parameterMap);
this.providerUrl = parameterMap.get("providerUrl");
this.searchBase = parameterMap.get("searchBase");
this.location = parameterMap.get("location");
this.domain = parameterMap.get("domain");
this.adminUsers = parameterMap.get("adminUsers");
super.initialize(parameterMap, encryptionHandler, persistenceHandler, userChallengeHandler, ssoHandler,
policyMap);
}
@Override
protected synchronized User checkCredentialsAndUserState(String username, char[] password)
throws InvalidCredentialsException, AccessDeniedException {
// Set up the environment for creating the initial context
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, providerUrl);
// Authenticate
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, username + domain);
env.put(Context.SECURITY_CREDENTIALS, new String(password));
logger.info("User {} tries to login on ldap", username + domain);
String memberOfLdapString = "";
Set<String> strolchRoles = new HashSet<>();
// Create the initial context
try {
DirContext ctx = new InitialDirContext(env);
//Create the search controls
SearchControls searchCtls = new SearchControls();
//Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(objectCategory=person)(objectClass=user)(userPrincipalName=" + username + domain
+ "))";
// Search for objects using the filter
NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
//Loop through the search results
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes attrs = sr.getAttributes();
memberOfLdapString = (attrs.get("memberOf") != null) ? attrs.get("memberOf").get().toString() : "";
// extract group name from ldap string -> CN=groupname,OU=company,DC=domain,DC=country
LdapName memberOfName = new LdapName(memberOfLdapString);
for (Rdn rdn : memberOfName.getRdns()) {
if (rdn.getType().equalsIgnoreCase("CN")) {
String groupName = rdn.getValue().toString();
Set<String> foundStrolchRoles = rolesForLdapGroups.get(groupName);
if (foundStrolchRoles != null)
strolchRoles.addAll(foundStrolchRoles);
break;
}
}
logger.info("User " + username + " is member of groups: " + memberOfLdapString);
}
ctx.close();
} catch (NamingException e) {
throw new AccessDeniedException("Could not login with user: " + username + domain + " on Ldap");
}
Map<String, String> properties = new HashMap<>();
// this must be changed, because the location param must be taken from the logged in person
properties.put("location", location);
if (adminUsers.contains(username)) {
strolchRoles = rolesForLdapGroups.get("admin");
}
return new User(username, username, null, null, null, -1, -1, username, username, UserState.ENABLED,
strolchRoles, Locale.GERMAN, properties);
}
private Map<String, Set<String>> getLdapGroupToRolesMappingFromConfig(Map<String, String> params) {
Map<String, Set<String>> result = new HashMap<>();
String rolesForLdapGroups = params.get("rolesForLdapGroups");
DBC.PRE.assertNotEmpty("No roles mapping for ldap directory groups defined (param: rolesForLdapGroups)",
rolesForLdapGroups);
// rolesForLdapGroups = admin=StrolchAdmin,UserPrivileges;user=UserPrivileges
String[] ldapGroupRoles = rolesForLdapGroups.split(";");
for (String ldapGroupRole : ldapGroupRoles) {
// admin=StrolchAdmin,UserPrivileges
String[] splittedGroupRoles = ldapGroupRole.split("=");
String ldapGroupName = splittedGroupRoles[0];
// StrolchAdmin,UserPrivileges
Set<String> roleNames = new HashSet<>(Arrays.asList(splittedGroupRoles[1].split(",")));
result.put(ldapGroupName, roleNames);
}
return result;
}
}

View File

@ -22,7 +22,12 @@ import java.text.MessageFormat;
import java.util.Map;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.*;
import li.strolch.privilege.handler.DefaultPrivilegeHandler;
import li.strolch.privilege.handler.EncryptionHandler;
import li.strolch.privilege.handler.PersistenceHandler;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.handler.SingleSignOnHandler;
import li.strolch.privilege.handler.UserChallengeHandler;
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.privilege.xml.PrivilegeConfigSaxReader;
@ -149,10 +154,19 @@ public class PrivilegeInitializationHelper {
throw new PrivilegeException(msg, e);
}
}
// initialize privilege handler
DefaultPrivilegeHandler privilegeHandler = new DefaultPrivilegeHandler();
DefaultPrivilegeHandler privilegeHandler;
parameterMap = containerModel.getParameterMap();
if (containerModel.getPrivilegeHandlerClassName() == null) {
privilegeHandler = new DefaultPrivilegeHandler();
} else {
String privilegeHandlerClassName = containerModel.getPrivilegeHandlerClassName();
privilegeHandler = ClassHelper.instantiateClass(privilegeHandlerClassName);
parameterMap.putAll(containerModel.getPrivilegeHandlerParameterMap());
}
Map<String, Class<PrivilegePolicy>> policyMap = containerModel.getPolicies();
try {
privilegeHandler

View File

@ -40,11 +40,13 @@ public class PrivilegeContainerModel {
private String persistenceHandlerClassName;
private String userChallengeHandlerClassName;
private String ssoHandlerClassName;
private String privilegeHandlerClassName;
private Map<String, String> encryptionHandlerParameterMap;
private Map<String, String> persistenceHandlerParameterMap;
private Map<String, String> challengeHandlerParameterMap;
private Map<String, String> ssoHandlerParameterMap;
private Map<String, String> privilegeHandlerParameterMap;
private Map<String, String> parameterMap;
@ -56,6 +58,7 @@ public class PrivilegeContainerModel {
this.persistenceHandlerParameterMap = new HashMap<>();
this.challengeHandlerParameterMap = new HashMap<>();
this.ssoHandlerParameterMap = new HashMap<>();
this.privilegeHandlerParameterMap = new HashMap<>();
}
public Map<String, String> getParameterMap() {
@ -113,6 +116,14 @@ public class PrivilegeContainerModel {
public void setSsoHandlerClassName(String ssoHandlerClassName) {
this.ssoHandlerClassName = ssoHandlerClassName;
}
public String getPrivilegeHandlerClassName() {
return this.privilegeHandlerClassName;
}
public void setPrivilegeHandlerClassName(String privilegeHandlerClassName) {
this.privilegeHandlerClassName = privilegeHandlerClassName;
}
public Map<String, String> getUserChallengeHandlerParameterMap() {
return this.challengeHandlerParameterMap;
@ -129,6 +140,14 @@ public class PrivilegeContainerModel {
public void setSsoHandlerParameterMap(Map<String, String> ssoHandlerParameterMap) {
this.ssoHandlerParameterMap = ssoHandlerParameterMap;
}
public Map<String, String> getPrivilegeHandlerParameterMap() {
return this.privilegeHandlerParameterMap;
}
public void setPrivilegeHandlerParameterMap(Map<String, String> privilegeHandlerParameterMap) {
this.privilegeHandlerParameterMap = privilegeHandlerParameterMap;
}
public void addPolicy(String privilegeName, String policyClassName) {
@ -181,6 +200,8 @@ public class PrivilegeContainerModel {
builder.append(this.challengeHandlerParameterMap.size());
builder.append(", ssoHandlerParameterMap=");
builder.append(this.ssoHandlerParameterMap.size());
builder.append(", privilegeHandlerParameterMap=");
builder.append(this.privilegeHandlerParameterMap.size());
builder.append(", parameterMap=");
builder.append(this.parameterMap.size());
builder.append(", policies=");

View File

@ -88,6 +88,15 @@ public class PrivilegeConfigDomWriter {
// Parameters
fillParameterMap(doc, ssoHandlerElem, this.containerModel.getSsoHandlerParameterMap());
}
// create PrivilegeHandler
if (this.containerModel.getSsoHandlerClassName() != null) {
Element privilegeHandlerElem = doc.createElement(XML_HANDLER_PRIVILEGE);
containerElement.appendChild(privilegeHandlerElem);
privilegeHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getPrivilegeHandlerClassName());
// Parameters
fillParameterMap(doc, privilegeHandlerElem, this.containerModel.getPrivilegeHandlerParameterMap());
}
// Policies
Element policiesElem = doc.createElement(XML_POLICIES);

View File

@ -109,6 +109,10 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
this.currentElement = qName;
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
getContainerModel().setSsoHandlerClassName(className);
} else if (qName.equals(XmlConstants.XML_HANDLER_PRIVILEGE)) {
this.currentElement = qName;
String className = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
getContainerModel().setPrivilegeHandlerClassName(className);
}
}
@ -129,6 +133,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
getContainerModel().setUserChallengeHandlerParameterMap(parametersChild.getParameterMap());
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_SSO)) {
getContainerModel().setSsoHandlerParameterMap(parametersChild.getParameterMap());
} else if (this.currentElement.equals(XmlConstants.XML_HANDLER_PRIVILEGE)) {
getContainerModel().setPrivilegeHandlerParameterMap(parametersChild.getParameterMap());
}
}
}