This commit is contained in:
eitch 2010-06-05 21:06:03 +00:00
parent 0ca04da053
commit dc414218e6
11 changed files with 448 additions and 59 deletions

View File

@ -8,6 +8,7 @@
<Locale>en_GB</Locale>
<Roles>
<Role>admin</Role>
<Role>PrivilegeAdmin</Role>
</Roles>
</User>

View File

@ -27,6 +27,12 @@ import ch.eitchnet.privilege.i18n.PrivilegeException;
* @author rvonburg
*/
public class PrivilegeContainer {
/**
* This is the role users must have, if they can modify the {@link PrivilegeContainer} and its objects
*/
public static final String PRIVILEGE_ADMIN_ROLE = "PrivilegeAdmin";
private static final Logger logger = Logger.getLogger(PrivilegeContainer.class);
private static final PrivilegeContainer instance;

View File

@ -22,10 +22,13 @@ public class XmlConstants {
public static final String XML_ROLES = "Roles";
public static final String XML_ROLE = "Role";
public static final String XML_USERS = "Users";
public static final String XML_USER = "User";
public static final String XML_PRIVILEGES = "Privileges";
public static final String XML_PRIVILEGE = "Privilege";
public static final String XML_POLICY = "Policy";
public static final String XML_PARAMETERS = "Parameters";
public static final String XML_PARAMETER = "Parameter";
public static final String XML_ALL_ALLOWED = "AllAllowed";
public static final String XML_DENY = "Deny";
public static final String XML_ALLOW = "Allow";
@ -36,6 +39,7 @@ public class XmlConstants {
public static final String XML_ATTR_CLASS = "class";
public static final String XML_ATTR_NAME = "name";
public static final String XML_ATTR_VALUE = "value";
public static final String XML_ATTR_POLICY = "policy";
public static final String XML_ATTR_USERNAME = "username";
public static final String XML_ATTR_PASSWORD = "password";

View File

@ -20,11 +20,13 @@ import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import ch.eitchnet.privilege.base.PrivilegeContainer;
import ch.eitchnet.privilege.base.XmlConstants;
import ch.eitchnet.privilege.helper.ConfigurationHelper;
import ch.eitchnet.privilege.helper.PrivilegeHelper;
import ch.eitchnet.privilege.helper.XmlHelper;
import ch.eitchnet.privilege.i18n.PrivilegeException;
import ch.eitchnet.privilege.model.Certificate;
@ -43,11 +45,13 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
private Map<String, User> userMap;
private Map<String, Role> roleMap;
private Map<String, Privilege> privilegesMap;
private Map<String, Privilege> privilegeMap;
private Map<String, User> transientUserMap;
private Map<String, Role> transientRoleMap;
private Map<String, Privilege> transientPrivilegesMap;
private boolean userMapDirty;
private boolean roleMapDirty;
private boolean privilegeMapDirty;
private Map<String, String> parameterMap;
/**
* @see ch.eitchnet.privilege.handler.PersistenceHandler#addPrivilege(ch.eitchnet.privilege.model.Certificate,
@ -55,10 +59,12 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
*/
@Override
public void addPrivilege(Certificate certificate, Privilege privilege) {
// TODO validate who is doing this
privilegesMap.put(privilege.getName(), privilege);
transientPrivilegesMap.put(privilege.getName(), privilege);
// validate who is doing this
PrivilegeHelper.isUserPrivilegeAdmin(certificate);
privilegeMap.put(privilege.getName(), privilege);
privilegeMapDirty = true;
}
/**
@ -67,10 +73,12 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
*/
@Override
public void addRole(Certificate certificate, Role role) {
// TODO validate who is doing this
roleMap.put(role.getRoleName(), role);
transientRoleMap.put(role.getRoleName(), role);
// validate who is doing this
PrivilegeHelper.isUserPrivilegeAdmin(certificate);
roleMap.put(role.getName(), role);
roleMapDirty = true;
}
/**
@ -79,10 +87,12 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
*/
@Override
public void addUser(Certificate certificate, User user) {
// TODO validate who is doing this
// validate who is doing this
PrivilegeHelper.isUserPrivilegeAdmin(certificate);
userMap.put(user.getUsername(), user);
transientUserMap.put(user.getUsername(), user);
userMapDirty = true;
}
/**
@ -90,7 +100,7 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
*/
@Override
public Privilege getPrivilege(String privilegeName) {
return privilegesMap.get(privilegeName);
return privilegeMap.get(privilegeName);
}
/**
@ -115,10 +125,93 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
@Override
public void persist(Certificate certificate) {
// TODO validate who is doing this
// validate who is doing this
PrivilegeHelper.isUserPrivilegeAdmin(certificate);
// TODO Auto-generated method stub
// USERS
if (!userMapDirty) {
logger.warn("No users unpersisted.");
} else {
logger.info("Persisting users...");
// build XML DOM of users
List<Element> users = toDomUsers();
Element rootElement = DocumentFactory.getInstance().createElement(XmlConstants.XML_USERS);
for (Element userElement : users) {
rootElement.add(userElement);
}
// get users file name
String usersFileName = parameterMap.get(XmlConstants.XML_PARAM_USERS_FILE);
if (usersFileName == null || usersFileName.isEmpty()) {
throw new PrivilegeException("[" + SessionHandler.class.getName() + "] Defined parameter "
+ XmlConstants.XML_PARAM_USERS_FILE + " is invalid");
}
// get users file
File usersFile = new File(PrivilegeContainer.getInstance().getBasePath() + "/" + usersFileName);
// write DOM to file
XmlHelper.writeDocument(rootElement, usersFile);
}
// ROLES
if (!roleMapDirty) {
logger.warn("No roles unpersisted.");
} else {
logger.info("Persisting roles...");
// build XML DOM of roles
List<Element> roles = toDomRoles();
Element rootElement = DocumentFactory.getInstance().createElement(XmlConstants.XML_ROLES);
for (Element roleElement : roles) {
rootElement.add(roleElement);
}
// get roles file name
String rolesFileName = parameterMap.get(XmlConstants.XML_PARAM_ROLES_FILE);
if (rolesFileName == null || rolesFileName.isEmpty()) {
throw new PrivilegeException("[" + SessionHandler.class.getName() + "] Defined parameter "
+ XmlConstants.XML_PARAM_ROLES_FILE + " is invalid");
}
// get roles file
File rolesFile = new File(PrivilegeContainer.getInstance().getBasePath() + "/" + rolesFileName);
// write DOM to file
XmlHelper.writeDocument(rootElement, rolesFile);
}
// PRIVILEGES
if (!privilegeMapDirty) {
logger.warn("No privileges unpersisted.");
} else {
logger.info("Persisting privileges...");
// build XML DOM of privileges
List<Element> privileges = toDomPrivileges();
Element rootElement = DocumentFactory.getInstance().createElement(XmlConstants.XML_PRIVILEGES);
for (Element privilegeElement : privileges) {
rootElement.add(privilegeElement);
}
// get privileges file name
String privilegesFileName = parameterMap.get(XmlConstants.XML_PARAM_PRIVILEGES_FILE);
if (privilegesFileName == null || privilegesFileName.isEmpty()) {
throw new PrivilegeException("[" + SessionHandler.class.getName() + "] Defined parameter "
+ XmlConstants.XML_PARAM_PRIVILEGES_FILE + " is invalid");
}
// get privileges file
File privilegesFile = new File(PrivilegeContainer.getInstance().getBasePath() + "/" + privilegesFileName);
// write DOM to file
XmlHelper.writeDocument(rootElement, privilegesFile);
}
userMapDirty = false;
roleMapDirty = false;
privilegeMapDirty = false;
}
/**
@ -129,11 +222,11 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
roleMap = new HashMap<String, Role>();
userMap = new HashMap<String, User>();
privilegesMap = new HashMap<String, Privilege>();
privilegeMap = new HashMap<String, Privilege>();
// get parameters
Element parameterElement = element.element(XmlConstants.XML_PARAMETERS);
Map<String, String> parameterMap = ConfigurationHelper.convertToParameterMap(parameterElement);
parameterMap = ConfigurationHelper.convertToParameterMap(parameterElement);
// get roles file name
String rolesFileName = parameterMap.get(XmlConstants.XML_PARAM_ROLES_FILE);
@ -198,9 +291,26 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
// read privileges
readPrivileges(privilegesRootElement);
userMapDirty = false;
roleMapDirty = false;
privilegeMapDirty = false;
logger.info("Read " + userMap.size() + " Users");
logger.info("Read " + roleMap.size() + " Roles");
logger.info("Read " + privilegesMap.size() + " Privileges");
logger.info("Read " + privilegeMap.size() + " Privileges");
// validate we have a user with PrivilegeAdmin access
boolean privilegeAdminExists = false;
for (String username : userMap.keySet()) {
User user = userMap.get(username);
if (user.hasRole(PrivilegeContainer.PRIVILEGE_ADMIN_ROLE)) {
privilegeAdminExists = true;
break;
}
}
if (!privilegeAdminExists) {
logger.warn("No User with PrivilegeAdmin role exists. Privilege modifications will not be possible!");
}
}
/**
@ -229,7 +339,7 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
for (Element roleElement : rolesElementList) {
String roleName = roleElement.getTextTrim();
if (roleName.isEmpty()) {
logger.warn("User " + username + " has a role defined with no name, Skipped.");
logger.error("User " + username + " has a role defined with no name, Skipped.");
} else {
roles.add(roleName);
}
@ -303,7 +413,127 @@ public class DefaultPersistenceHandler implements PersistenceHandler {
}
Privilege privilege = new Privilege(privilegeName, privilegePolicy, allAllowed, denyList, allowList);
privilegesMap.put(privilegeName, privilege);
privilegeMap.put(privilegeName, privilege);
}
}
private List<Element> toDomPrivileges() {
List<Element> privilegesAsElements = new ArrayList<Element>(privilegeMap.size());
DocumentFactory documentFactory = DocumentFactory.getInstance();
for (String privilegeName : privilegeMap.keySet()) {
// get the privilege object
Privilege privilege = privilegeMap.get(privilegeName);
// create the privilege element
Element privilegeElement = documentFactory.createElement(XmlConstants.XML_PRIVILEGE);
privilegeElement.addAttribute(XmlConstants.XML_ATTR_NAME, privilege.getName());
privilegeElement.addAttribute(XmlConstants.XML_ATTR_POLICY, privilege.getPolicy());
// add the all allowed element
Element allAllowedElement = documentFactory.createElement(XmlConstants.XML_ALL_ALLOWED);
allAllowedElement.setText(Boolean.toString(privilege.isAllAllowed()));
privilegeElement.add(allAllowedElement);
// add all the deny values
for (String denyValue : privilege.getDenyList()) {
Element denyValueElement = documentFactory.createElement(XmlConstants.XML_DENY);
denyValueElement.setText(denyValue);
privilegeElement.add(denyValueElement);
}
// add all the allow values
for (String allowValue : privilege.getAllowList()) {
Element allowValueElement = documentFactory.createElement(XmlConstants.XML_ALLOW);
allowValueElement.setText(allowValue);
privilegeElement.add(allowValueElement);
}
// add element to return list
privilegesAsElements.add(privilegeElement);
}
return privilegesAsElements;
}
private List<Element> toDomRoles() {
List<Element> rolesAsElements = new ArrayList<Element>(roleMap.size());
DocumentFactory documentFactory = DocumentFactory.getInstance();
for (String roleName : roleMap.keySet()) {
// get the role object
Role role = roleMap.get(roleName);
// create the role element
Element roleElement = documentFactory.createElement(XmlConstants.XML_ROLE);
roleElement.addAttribute(XmlConstants.XML_ATTR_NAME, role.getName());
// add all the privileges
for (String privilegeName : role.getPrivileges()) {
Element privilegeElement = documentFactory.createElement(XmlConstants.XML_PRIVILEGE);
privilegeElement.addAttribute(XmlConstants.XML_ATTR_NAME, privilegeName);
roleElement.add(privilegeElement);
}
// add element to return list
rolesAsElements.add(roleElement);
}
return rolesAsElements;
}
private List<Element> toDomUsers() {
List<Element> usersAsElements = new ArrayList<Element>(userMap.size());
DocumentFactory documentFactory = DocumentFactory.getInstance();
for (String userName : userMap.keySet()) {
// get the user object
User user = userMap.get(userName);
// create the user element
Element userElement = documentFactory.createElement(XmlConstants.XML_USER);
userElement.addAttribute(XmlConstants.XML_ATTR_USERNAME, user.getUsername());
userElement.addAttribute(XmlConstants.XML_ATTR_PASSWORD, user.getPassword());
// add first name element
Element firstnameElement = documentFactory.createElement(XmlConstants.XML_FIRSTNAME);
firstnameElement.setText(user.getFirstname());
userElement.add(firstnameElement);
// add surname element
Element surnameElement = documentFactory.createElement(XmlConstants.XML_SURNAME);
surnameElement.setText(user.getSurname());
userElement.add(surnameElement);
// add state element
Element stateElement = documentFactory.createElement(XmlConstants.XML_STATE);
stateElement.setText(user.getState().toString());
userElement.add(stateElement);
// add locale element
Element localeElement = documentFactory.createElement(XmlConstants.XML_LOCALE);
localeElement.setText(user.getLocale().toString());
userElement.add(localeElement);
// add all the role elements
Element rolesElement = documentFactory.createElement(XmlConstants.XML_ROLES);
userElement.add(rolesElement);
for (String roleName : user.getRoles()) {
Element roleElement = documentFactory.createElement(XmlConstants.XML_ROLE);
roleElement.setText(roleName);
rolesElement.add(roleElement);
}
// add element to return list
usersAsElements.add(userElement);
}
return usersAsElements;
}
}

View File

@ -51,11 +51,60 @@ public class DefaultSessionHandler implements SessionHandler {
@Override
public boolean actionAllowed(Certificate certificate, Restrictable restrictable) {
// certificate and restrictable must not be null
// first validate certificate
if (!isCertificateValid(certificate)) {
logger.info("Certificate is not valid, so action is not allowed: " + certificate + " for restrictable: "
+ restrictable);
return false;
}
// restrictable must not be null
if (restrictable == null)
throw new PrivilegeException("Restrictable may not be null!");
PrivilegeContainer privilegeContainer = PrivilegeContainer.getInstance();
PersistenceHandler persistenceHandler = privilegeContainer.getPersistenceHandler();
// get user object
User user = persistenceHandler.getUser(certificate.getUsername());
if (user == null) {
throw new PrivilegeException(
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
}
// default is to not allow the action
// TODO should default deny/allow policy be configurable?
boolean actionAllowed = false;
// now iterate roles and validate on policy handler
PolicyHandler policyHandler = privilegeContainer.getPolicyHandler();
for (String roleName : user.getRoles()) {
Role role = privilegeContainer.getPersistenceHandler().getRole(roleName);
if (role == null) {
logger.error("No role is defined with name " + roleName + " which is configured for user " + user);
continue;
}
actionAllowed = policyHandler.actionAllowed(role, restrictable);
// if action is allowed, then break iteration as a privilege match has been made
if (actionAllowed)
break;
}
return actionAllowed;
}
/**
* @see ch.eitchnet.privilege.handler.SessionHandler#isCertificateValid(ch.eitchnet.privilege.model.Certificate)
*/
@Override
public boolean isCertificateValid(Certificate certificate) {
// certificate must not be null
if (certificate == null)
throw new PrivilegeException("Certificate may not be null!");
else if (restrictable == null)
throw new PrivilegeException("Restrictable may not be null!");
// first see if a session exists for this certificate
CertificateSessionPair certificateSessionPair = sessionMap.get(certificate.getSessionId());
@ -77,33 +126,14 @@ public class DefaultSessionHandler implements SessionHandler {
// get user object
User user = PrivilegeContainer.getInstance().getPersistenceHandler().getUser(
certificateSessionPair.session.getUsername());
// if user exists, then certificate is valid
if (user == null) {
throw new PrivilegeException(
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
} else {
return true;
}
// default is to not allow the action
// TODO should default deny/allow policy be configurable?
boolean actionAllowed = false;
// now iterate roles and validate on policy handler
PolicyHandler policyHandler = PrivilegeContainer.getInstance().getPolicyHandler();
for (String roleName : user.getRoles()) {
Role role = PrivilegeContainer.getInstance().getPersistenceHandler().getRole(roleName);
if (role == null) {
logger.error("No role is defined with name " + roleName + " which is configured for user " + user);
continue;
}
actionAllowed = policyHandler.actionAllowed(role, restrictable);
// if action is allowed, then break iteration as a privilege match has been made
if (actionAllowed)
break;
}
return actionAllowed;
}
/**

View File

@ -12,6 +12,7 @@ package ch.eitchnet.privilege.handler;
import ch.eitchnet.privilege.base.PrivilegeContainerObject;
import ch.eitchnet.privilege.i18n.AccessDeniedException;
import ch.eitchnet.privilege.i18n.PrivilegeException;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.internal.User;
@ -25,17 +26,32 @@ public interface SessionHandler extends PrivilegeContainerObject {
/**
* @param certificate
* @param restrictable
*
* @return
*
* @throws AccessDeniedException
* if the {@link Certificate} is not for a currently logged in {@link User} or if the user may not
* perform the action defined by the {@link Restrictable} implementation
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public boolean actionAllowed(Certificate certificate, Restrictable restrictable);
/**
* @param certificate
* @return
*
* @throws AccessDeniedException
* if the {@link Certificate} is not for a currently logged in {@link User}
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public boolean isCertificateValid(Certificate certificate);
/**
* @param user
* @param password
*
* @return
*
* @throws AccessDeniedException

View File

@ -16,6 +16,8 @@ import java.util.Map;
import org.dom4j.Element;
import ch.eitchnet.privilege.base.XmlConstants;
/**
* @author rvonburg
*
@ -27,10 +29,10 @@ public class ConfigurationHelper {
Map<String, String> parameterMap = new HashMap<String, String>();
List<Element> elements = element.elements("Parameter");
List<Element> elements = element.elements(XmlConstants.XML_PARAMETER);
for (Element parameter : elements) {
String name = parameter.attributeValue("name");
String value = parameter.attributeValue("value");
String name = parameter.attributeValue(XmlConstants.XML_ATTR_NAME);
String value = parameter.attributeValue(XmlConstants.XML_ATTR_VALUE);
parameterMap.put(name, value);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2010
*
* Robert von Burg
* eitch@eitchnet.ch
*
* All rights reserved.
*
*/
package ch.eitchnet.privilege.helper;
import ch.eitchnet.privilege.base.PrivilegeContainer;
import ch.eitchnet.privilege.i18n.AccessDeniedException;
import ch.eitchnet.privilege.i18n.PrivilegeException;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.internal.User;
/**
* @author rvonburg
*
*/
public class PrivilegeHelper {
public static boolean isUserPrivilegeAdmin(Certificate certificate) {
// validate certificate
if (!PrivilegeContainer.getInstance().getSessionHandler().isCertificateValid(certificate)) {
throw new PrivilegeException("Certificate " + certificate + " is not valid!");
}
// get user object
User user = PrivilegeContainer.getInstance().getPersistenceHandler().getUser(certificate.getUsername());
if (user == null) {
throw new PrivilegeException(
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
}
// validate user has PrivilegeAdmin role
if (!user.hasRole(PrivilegeContainer.PRIVILEGE_ADMIN_ROLE)) {
throw new AccessDeniedException("User does not have " + PrivilegeContainer.PRIVILEGE_ADMIN_ROLE + " role!");
} else {
return true;
}
}
}

View File

@ -13,12 +13,19 @@ package ch.eitchnet.privilege.helper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import ch.eitchnet.privilege.i18n.PrivilegeException;
@ -31,6 +38,7 @@ public class XmlHelper {
private static final Logger logger = Logger.getLogger(XmlHelper.class);
public static Document parseDocument(File xmlFile) {
try {
InputStream inStream = new FileInputStream(xmlFile);
@ -38,13 +46,48 @@ public class XmlHelper {
SAXReader reader = new SAXReader();
Document document = reader.read(inStream);
logger.info("Read Xml document " + document.getRootElement().getName());
logger.info("Read XML document " + document.getRootElement().getName());
return document;
} catch (FileNotFoundException e) {
throw new PrivilegeException("The Xml file does not exist or is not readable: " + xmlFile.getAbsolutePath());
throw new PrivilegeException("The XML file does not exist or is not readable: " + xmlFile.getAbsolutePath());
} catch (DocumentException e) {
throw new PrivilegeException("the Xml file " + xmlFile.getAbsolutePath() + " is not parseable:", e);
throw new PrivilegeException("the XML file " + xmlFile.getAbsolutePath() + " is not parseable:", e);
}
}
public static void writeDocument(Element rootElement, File file) {
logger.info("Exporting root element " + rootElement.getName() + " to " + file.getAbsolutePath());
OutputStream fileOutputStream = null;
try {
Document document = DocumentFactory.getInstance().createDocument();
document.setRootElement(rootElement);
fileOutputStream = new FileOutputStream(file);
String aEncodingScheme = "UTF-8";
OutputFormat outformat = OutputFormat.createPrettyPrint();
outformat.setEncoding(aEncodingScheme);
XMLWriter writer = new XMLWriter(fileOutputStream, outformat);
writer.write(document);
writer.flush();
} catch (Exception e) {
throw new PrivilegeException("Exception while exporting to file: " + e, e);
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
logger.error("Could not close file output stream: " + e, e);
}
}
}
}
}

View File

@ -19,22 +19,24 @@ import java.util.Set;
*/
public final class Role {
private final String roleName;
private final String name;
private final Set<String> privileges;
/**
* @param privilegeMap
*
* @param name
* @param privileges
*/
public Role(String roleName, Set<String> privileges) {
this.roleName = roleName;
public Role(String name, Set<String> privileges) {
this.name = name;
this.privileges = Collections.unmodifiableSet(privileges);
}
/**
* @return the roleName
* @return the name
*/
public String getRoleName() {
return roleName;
public String getName() {
return name;
}
/**

View File

@ -95,6 +95,16 @@ public final class User {
return roles;
}
/**
* Returns true if this user has the specified role
*
* @param role
* @return true if the this user has the specified role
*/
public boolean hasRole(String role) {
return roles.contains(role);
}
/**
* @return the locale
*/