[Major] Added persisting of sessions
This commit is contained in:
parent
c6f531c08e
commit
5dc94514e1
|
@ -5,6 +5,10 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
|
<Parameter name="secretKey" value="5185F447-6317-4856-B40E-573919BA0A16" />
|
||||||
|
<Parameter name="secretSalt" value="00F6E88C-A64F-410A-8FCF-9CD340E340F7" />
|
||||||
|
<Parameter name="persistSessions" value="true" />
|
||||||
|
<Parameter name="persistSessionsPath" value="./target/${target}/sessions.dat" />
|
||||||
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
<Parameter name="privilegeConflictResolution" value="STRICT" />
|
<Parameter name="privilegeConflictResolution" value="STRICT" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
@ -17,7 +21,7 @@
|
||||||
|
|
||||||
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<Parameter name="basePath" value="./target/testPrivilege" />
|
<Parameter name="basePath" value="./target/${target}" />
|
||||||
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
|
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
</PersistenceHandler>
|
</PersistenceHandler>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<Parameter name="basePath" value="./target/testPrivilege" />
|
<Parameter name="basePath" value="./target/${target}" />
|
||||||
<Parameter name="modelXmlFile" value="PrivilegeModelMerge.xml" />
|
<Parameter name="modelXmlFile" value="PrivilegeModelMerge.xml" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
</PersistenceHandler>
|
</PersistenceHandler>
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package ch.eitchnet.privilege.handler;
|
package ch.eitchnet.privilege.handler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -31,6 +36,8 @@ import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -49,7 +56,11 @@ import ch.eitchnet.privilege.model.internal.PrivilegeImpl;
|
||||||
import ch.eitchnet.privilege.model.internal.Role;
|
import ch.eitchnet.privilege.model.internal.Role;
|
||||||
import ch.eitchnet.privilege.model.internal.User;
|
import ch.eitchnet.privilege.model.internal.User;
|
||||||
import ch.eitchnet.privilege.policy.PrivilegePolicy;
|
import ch.eitchnet.privilege.policy.PrivilegePolicy;
|
||||||
|
import ch.eitchnet.privilege.xml.CertificateStubsDomWriter;
|
||||||
|
import ch.eitchnet.privilege.xml.CertificateStubsSaxReader;
|
||||||
|
import ch.eitchnet.privilege.xml.CertificateStubsSaxReader.CertificateStub;
|
||||||
import ch.eitchnet.utils.collections.Tuple;
|
import ch.eitchnet.utils.collections.Tuple;
|
||||||
|
import ch.eitchnet.utils.helper.AesCryptoHelper;
|
||||||
import ch.eitchnet.utils.helper.StringHelper;
|
import ch.eitchnet.utils.helper.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,6 +118,21 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
*/
|
*/
|
||||||
private boolean autoPersistOnUserChangesData;
|
private boolean autoPersistOnUserChangesData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flag to define if sessions should be persisted
|
||||||
|
*/
|
||||||
|
private boolean persistSessions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path to sessions file for persistence
|
||||||
|
*/
|
||||||
|
private File persistSessionsPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Secret key
|
||||||
|
*/
|
||||||
|
private SecretKey secretKey;
|
||||||
|
|
||||||
private PrivilegeConflictResolution privilegeConflictResolution;
|
private PrivilegeConflictResolution privilegeConflictResolution;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,6 +185,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
return policyDef;
|
return policyDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Certificate> getCertificates(Certificate certificate) {
|
||||||
|
|
||||||
|
// validate user actually has this type of privilege
|
||||||
|
PrivilegeContext prvCtx = getPrivilegeContext(certificate);
|
||||||
|
prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ACTION, PRIVILEGE_ACTION_GET_CERTIFICATES));
|
||||||
|
|
||||||
|
return this.privilegeContextMap.values().stream().map(p -> p.getCertificate()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RoleRep> getRoles(Certificate certificate) {
|
public List<RoleRep> getRoles(Certificate certificate) {
|
||||||
|
|
||||||
|
@ -958,8 +994,6 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
@Override
|
@Override
|
||||||
public Certificate authenticate(String username, byte[] password) {
|
public Certificate authenticate(String username, byte[] password) {
|
||||||
|
|
||||||
// create certificate
|
|
||||||
Certificate certificate;
|
|
||||||
try {
|
try {
|
||||||
// username must be at least 2 characters in length
|
// username must be at least 2 characters in length
|
||||||
if (username == null || username.length() < 2) {
|
if (username == null || username.length() < 2) {
|
||||||
|
@ -984,16 +1018,23 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
String sessionId = UUID.randomUUID().toString();
|
String sessionId = UUID.randomUUID().toString();
|
||||||
|
|
||||||
// create a new certificate, with details of the user
|
// create a new certificate, with details of the user
|
||||||
certificate = new Certificate(sessionId, new Date(), username, user.getFirstname(), user.getLastname(),
|
Certificate certificate = new Certificate(sessionId, username, user.getFirstname(), user.getLastname(),
|
||||||
authToken, user.getLocale(), userRoles, new HashMap<>(user.getProperties()));
|
user.getUserState(), authToken, new Date(), user.getLocale(), userRoles,
|
||||||
|
new HashMap<>(user.getProperties()));
|
||||||
|
certificate.setLastAccess(new Date());
|
||||||
|
|
||||||
PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user);
|
PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user);
|
||||||
this.privilegeContextMap.put(sessionId, privilegeContext);
|
this.privilegeContextMap.put(sessionId, privilegeContext);
|
||||||
|
|
||||||
|
persistSessions();
|
||||||
|
|
||||||
// log
|
// log
|
||||||
DefaultPrivilegeHandler.logger
|
DefaultPrivilegeHandler.logger
|
||||||
.info(MessageFormat.format("User {0} authenticated: {1}", username, certificate)); //$NON-NLS-1$
|
.info(MessageFormat.format("User {0} authenticated: {1}", username, certificate)); //$NON-NLS-1$
|
||||||
|
|
||||||
|
// return the certificate
|
||||||
|
return certificate;
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
String msg = "User {0} Failed to authenticate: {1}"; //$NON-NLS-1$
|
String msg = "User {0} Failed to authenticate: {1}"; //$NON-NLS-1$
|
||||||
msg = MessageFormat.format(msg, username, e.getMessage());
|
msg = MessageFormat.format(msg, username, e.getMessage());
|
||||||
|
@ -1002,9 +1043,88 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
} finally {
|
} finally {
|
||||||
clearPassword(password);
|
clearPassword(password);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return the certificate
|
private boolean persistSessions() {
|
||||||
return certificate;
|
if (!this.persistSessions)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<Certificate> sessions = this.privilegeContextMap.values().stream().map(p -> p.getCertificate())
|
||||||
|
.filter(c -> !c.getUserState().isSystem()).collect(Collectors.toList());
|
||||||
|
|
||||||
|
try (OutputStream outputStream = AesCryptoHelper.wrapEncrypt(this.secretKey,
|
||||||
|
new FileOutputStream(this.persistSessionsPath))) {
|
||||||
|
|
||||||
|
CertificateStubsDomWriter writer = new CertificateStubsDomWriter(sessions, outputStream);
|
||||||
|
writer.write();
|
||||||
|
outputStream.flush();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PrivilegeException("Failed to persist sessions!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean loadSessions() {
|
||||||
|
if (!this.persistSessions) {
|
||||||
|
logger.info("Persisteding of sessions not enabled, so not loading!.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.persistSessionsPath.exists()) {
|
||||||
|
logger.info("No persisted sessions exist to be loaded.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.persistSessionsPath.isFile())
|
||||||
|
throw new PrivilegeException(
|
||||||
|
"Sessions data file is not a file but exists at " + this.persistSessionsPath.getAbsolutePath());
|
||||||
|
|
||||||
|
List<CertificateStub> certificateStubs;
|
||||||
|
try (InputStream inputStream = AesCryptoHelper.wrapDecrypt(this.secretKey,
|
||||||
|
new FileInputStream(this.persistSessionsPath))) {
|
||||||
|
|
||||||
|
CertificateStubsSaxReader reader = new CertificateStubsSaxReader(inputStream);
|
||||||
|
certificateStubs = reader.read();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PrivilegeException("Failed to load sessions!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certificateStubs.isEmpty()) {
|
||||||
|
logger.info("No persisted sessions exist to be loaded.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CertificateStub certificateStub : certificateStubs) {
|
||||||
|
String username = certificateStub.getUsername();
|
||||||
|
String sessionId = certificateStub.getSessionId();
|
||||||
|
String authToken = certificateStub.getAuthToken();
|
||||||
|
User user = this.persistenceHandler.getUser(username);
|
||||||
|
if (user == null) {
|
||||||
|
logger.error("Ignoring session data for missing user " + username);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> userRoles = user.getRoles();
|
||||||
|
if (userRoles.isEmpty()) {
|
||||||
|
logger.error("Ignoring session data for user " + username + " which has not roles defined!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new certificate, with details of the user
|
||||||
|
Certificate certificate = new Certificate(sessionId, username, user.getFirstname(), user.getLastname(),
|
||||||
|
user.getUserState(), authToken, certificateStub.getLoginTime(), certificateStub.getLocale(),
|
||||||
|
userRoles, new HashMap<>(user.getProperties()));
|
||||||
|
certificate.setLastAccess(certificateStub.getLastAccess());
|
||||||
|
|
||||||
|
PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user);
|
||||||
|
this.privilegeContextMap.put(sessionId, privilegeContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Loaded " + this.privilegeContextMap.size() + " sessions.");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1146,6 +1266,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
// remove registration
|
// remove registration
|
||||||
PrivilegeContext privilegeContext = this.privilegeContextMap.remove(certificate.getSessionId());
|
PrivilegeContext privilegeContext = this.privilegeContextMap.remove(certificate.getSessionId());
|
||||||
|
|
||||||
|
// persist sessions
|
||||||
|
persistSessions();
|
||||||
|
|
||||||
// return true if object was really removed
|
// return true if object was really removed
|
||||||
boolean loggedOut = privilegeContext != null;
|
boolean loggedOut = privilegeContext != null;
|
||||||
if (loggedOut)
|
if (loggedOut)
|
||||||
|
@ -1236,6 +1359,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
return this.persistenceHandler.persist();
|
return this.persistenceHandler.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean persistSessions(Certificate certificate) {
|
||||||
|
|
||||||
|
// validate who is doing this
|
||||||
|
PrivilegeContext prvCtx = getPrivilegeContext(certificate);
|
||||||
|
prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ACTION, PRIVILEGE_ACTION_PERSIST_SESSIONS));
|
||||||
|
|
||||||
|
return persistSessions();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean reload(Certificate certificate) {
|
public boolean reload(Certificate certificate) {
|
||||||
|
|
||||||
|
@ -1273,8 +1406,29 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
this.encryptionHandler = encryptionHandler;
|
this.encryptionHandler = encryptionHandler;
|
||||||
this.persistenceHandler = persistenceHandler;
|
this.persistenceHandler = persistenceHandler;
|
||||||
|
|
||||||
|
handleAutoPersistOnUserDataChange(parameterMap);
|
||||||
|
handlePersistSessionsParam(parameterMap);
|
||||||
|
handleConflictResolutionParam(parameterMap);
|
||||||
|
handleSecretParams(parameterMap);
|
||||||
|
|
||||||
|
// validate policies on privileges of Roles
|
||||||
|
for (Role role : persistenceHandler.getAllRoles()) {
|
||||||
|
validatePolicies(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate privilege conflicts
|
||||||
|
validatePrivilegeConflicts();
|
||||||
|
|
||||||
|
this.privilegeContextMap = Collections.synchronizedMap(new HashMap<String, PrivilegeContext>());
|
||||||
|
|
||||||
|
loadSessions();
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAutoPersistOnUserDataChange(Map<String, String> parameterMap) {
|
||||||
String autoPersistS = parameterMap.get(PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA);
|
String autoPersistS = parameterMap.get(PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA);
|
||||||
if (autoPersistS == null || autoPersistS.equals(Boolean.FALSE.toString())) {
|
if (StringHelper.isEmpty(autoPersistS) || autoPersistS.equals(Boolean.FALSE.toString())) {
|
||||||
this.autoPersistOnUserChangesData = false;
|
this.autoPersistOnUserChangesData = false;
|
||||||
} else if (autoPersistS.equals(Boolean.TRUE.toString())) {
|
} else if (autoPersistS.equals(Boolean.TRUE.toString())) {
|
||||||
this.autoPersistOnUserChangesData = true;
|
this.autoPersistOnUserChangesData = true;
|
||||||
|
@ -1283,8 +1437,48 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
String msg = "Parameter {0} has illegal value {1}. Overriding with {2}"; //$NON-NLS-1$
|
String msg = "Parameter {0} has illegal value {1}. Overriding with {2}"; //$NON-NLS-1$
|
||||||
msg = MessageFormat.format(msg, PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA, autoPersistS, Boolean.FALSE);
|
msg = MessageFormat.format(msg, PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA, autoPersistS, Boolean.FALSE);
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
|
this.autoPersistOnUserChangesData = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePersistSessionsParam(Map<String, String> parameterMap) {
|
||||||
|
String persistSessionsS = parameterMap.get(PARAM_PERSIST_SESSIONS);
|
||||||
|
if (StringHelper.isEmpty(persistSessionsS) || persistSessionsS.equals(Boolean.FALSE.toString())) {
|
||||||
|
this.persistSessions = false;
|
||||||
|
} else if (persistSessionsS.equals(Boolean.TRUE.toString())) {
|
||||||
|
this.persistSessions = true;
|
||||||
|
|
||||||
|
String persistSessionsPathS = parameterMap.get(PARAM_PERSIST_SESSIONS_PATH);
|
||||||
|
if (StringHelper.isEmpty(persistSessionsPathS)) {
|
||||||
|
String msg = "Parameter {0} has illegal value {1}."; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPathS);
|
||||||
|
throw new PrivilegeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
File persistSessionsPath = new File(persistSessionsPathS);
|
||||||
|
if (!persistSessionsPath.getParentFile().isDirectory()) {
|
||||||
|
String msg = "Path for param {0} is invalid as parent does not exist or is not a directory. Value: {1}"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPath.getAbsolutePath());
|
||||||
|
throw new PrivilegeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (persistSessionsPath.exists() && (!persistSessionsPath.isFile() || !persistSessionsPath.canWrite())) {
|
||||||
|
String msg = "Path for param {0} is invalid as file exists but is not a file or not writeable. Value: {1}"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPath.getAbsolutePath());
|
||||||
|
throw new PrivilegeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.persistSessionsPath = persistSessionsPath;
|
||||||
|
logger.info("Enabling persistence of sessions."); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
String msg = "Parameter {0} has illegal value {1}. Overriding with {2}"; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS, persistSessionsS, Boolean.FALSE);
|
||||||
|
logger.error(msg);
|
||||||
|
this.persistSessions = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleConflictResolutionParam(Map<String, String> parameterMap) {
|
||||||
String privilegeConflictResolutionS = parameterMap.get(PARAM_PRIVILEGE_CONFLICT_RESOLUTION);
|
String privilegeConflictResolutionS = parameterMap.get(PARAM_PRIVILEGE_CONFLICT_RESOLUTION);
|
||||||
if (privilegeConflictResolutionS == null) {
|
if (privilegeConflictResolutionS == null) {
|
||||||
this.privilegeConflictResolution = PrivilegeConflictResolution.STRICT;
|
this.privilegeConflictResolution = PrivilegeConflictResolution.STRICT;
|
||||||
|
@ -1301,17 +1495,28 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info("Privilege conflict resolution set to " + this.privilegeConflictResolution); //$NON-NLS-1$
|
logger.info("Privilege conflict resolution set to " + this.privilegeConflictResolution); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
// validate policies on privileges of Roles
|
private void handleSecretParams(Map<String, String> parameterMap) {
|
||||||
for (Role role : persistenceHandler.getAllRoles()) {
|
|
||||||
validatePolicies(role);
|
if (!this.persistSessions)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String secretKeyS = parameterMap.get(PARAM_SECRET_KEY);
|
||||||
|
if (StringHelper.isEmpty(secretKeyS)) {
|
||||||
|
String msg = "Parameter {0} may not be empty if parameter {1} is enabled."; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_SECRET_KEY, PARAM_PRIVILEGE_CONFLICT_RESOLUTION);
|
||||||
|
throw new PrivilegeException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate privilege conflicts
|
String secretSaltS = parameterMap.get(PARAM_SECRET_SALT);
|
||||||
validatePrivilegeConflicts();
|
if (StringHelper.isEmpty(secretSaltS)) {
|
||||||
|
String msg = "Parameter {0} may not be empty if parameter {1} is enabled."; //$NON-NLS-1$
|
||||||
|
msg = MessageFormat.format(msg, PARAM_SECRET_SALT, PARAM_PRIVILEGE_CONFLICT_RESOLUTION);
|
||||||
|
throw new PrivilegeException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
this.privilegeContextMap = Collections.synchronizedMap(new HashMap<String, PrivilegeContext>());
|
this.secretKey = AesCryptoHelper.buildSecret(secretKeyS.toCharArray(), secretSaltS.getBytes());
|
||||||
this.initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePrivilegeConflicts() {
|
private void validatePrivilegeConflicts() {
|
||||||
|
@ -1502,8 +1707,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
||||||
String sessionId = UUID.randomUUID().toString();
|
String sessionId = UUID.randomUUID().toString();
|
||||||
|
|
||||||
// create a new certificate, with details of the user
|
// create a new certificate, with details of the user
|
||||||
Certificate systemUserCertificate = new Certificate(sessionId, new Date(), systemUsername, user.getFirstname(),
|
Certificate systemUserCertificate = new Certificate(sessionId, systemUsername, user.getFirstname(),
|
||||||
user.getLastname(), authToken, user.getLocale(), user.getRoles(), new HashMap<>(user.getProperties()));
|
user.getLastname(), user.getUserState(), authToken, new Date(), user.getLocale(), user.getRoles(),
|
||||||
|
new HashMap<>(user.getProperties()));
|
||||||
|
systemUserCertificate.setLastAccess(new Date());
|
||||||
|
|
||||||
// create and save a new privilege context
|
// create and save a new privilege context
|
||||||
PrivilegeContext privilegeContext = buildPrivilegeContext(systemUserCertificate, user);
|
PrivilegeContext privilegeContext = buildPrivilegeContext(systemUserCertificate, user);
|
||||||
|
|
|
@ -55,6 +55,11 @@ public interface PrivilegeHandler {
|
||||||
* <code>allAllowed</code>
|
* <code>allAllowed</code>
|
||||||
*/
|
*/
|
||||||
public static final String PRIVILEGE_ACTION_PERSIST = "Persist";
|
public static final String PRIVILEGE_ACTION_PERSIST = "Persist";
|
||||||
|
/**
|
||||||
|
* For Privilege "PrivilegeAction" value required to be able to persist session if not exempted by
|
||||||
|
* <code>allAllowed</code>
|
||||||
|
*/
|
||||||
|
public static final String PRIVILEGE_ACTION_PERSIST_SESSIONS = "PersistSessions";
|
||||||
/**
|
/**
|
||||||
* For Privilege "PrivilegeAction" value required to be able to reload changes if not exempted by
|
* For Privilege "PrivilegeAction" value required to be able to reload changes if not exempted by
|
||||||
* <code>allAllowed</code>
|
* <code>allAllowed</code>
|
||||||
|
@ -65,6 +70,14 @@ public interface PrivilegeHandler {
|
||||||
* <code>allAllowed</code>
|
* <code>allAllowed</code>
|
||||||
*/
|
*/
|
||||||
public static final String PRIVILEGE_ACTION_GET_POLICIES = "GetPolicies";
|
public static final String PRIVILEGE_ACTION_GET_POLICIES = "GetPolicies";
|
||||||
|
/**
|
||||||
|
* For Privilege "PrivilegeAction" value required to get a certificate if not <code>allAllowed</code>
|
||||||
|
*/
|
||||||
|
public static final String PRIVILEGE_ACTION_GET_CERTIFICATE = "GetCertificate";
|
||||||
|
/**
|
||||||
|
* For Privilege "PrivilegeAction" value required to get all certificates if not <code>allAllowed</code>
|
||||||
|
*/
|
||||||
|
public static final String PRIVILEGE_ACTION_GET_CERTIFICATES = "GetCertificates";
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
|
@ -131,11 +144,31 @@ public interface PrivilegeHandler {
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
|
/**
|
||||||
|
* configuration parameter to define a secret_key
|
||||||
|
*/
|
||||||
|
public static final String PARAM_SECRET_KEY = "secretKey"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* configuration parameter to define a secret salt
|
||||||
|
*/
|
||||||
|
public static final String PARAM_SECRET_SALT = "secretSalt"; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* configuration parameter to define automatic persisting on password change
|
* configuration parameter to define automatic persisting on password change
|
||||||
*/
|
*/
|
||||||
public static final String PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA = "autoPersistOnUserChangesData"; //$NON-NLS-1$
|
public static final String PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA = "autoPersistOnUserChangesData"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* configuration parameter to define if sessions should be persisted
|
||||||
|
*/
|
||||||
|
public static final String PARAM_PERSIST_SESSIONS = "persistSessions"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* configuration parameter to define where sessions are to be persisted
|
||||||
|
*/
|
||||||
|
public static final String PARAM_PERSIST_SESSIONS_PATH = "persistSessionsPath"; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* configuration parameter to define {@link PrivilegeConflictResolution}
|
* configuration parameter to define {@link PrivilegeConflictResolution}
|
||||||
*/
|
*/
|
||||||
|
@ -175,6 +208,16 @@ public interface PrivilegeHandler {
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getPolicyDefs(Certificate certificate);
|
public Map<String, String> getPolicyDefs(Certificate certificate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of {@link Certificate Certificates}
|
||||||
|
*
|
||||||
|
* @param certificate
|
||||||
|
* the {@link Certificate} of the user which has the privilege to perform this action
|
||||||
|
*
|
||||||
|
* @return the list of {@link Certificate Certificates}
|
||||||
|
*/
|
||||||
|
public List<Certificate> getCertificates(Certificate certificate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all {@link RoleRep RoleReps}
|
* Returns all {@link RoleRep RoleReps}
|
||||||
*
|
*
|
||||||
|
@ -607,6 +650,19 @@ public interface PrivilegeHandler {
|
||||||
*/
|
*/
|
||||||
public boolean persist(Certificate certificate) throws AccessDeniedException;
|
public boolean persist(Certificate certificate) throws AccessDeniedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists all currently active sessions
|
||||||
|
*
|
||||||
|
* @param certificate
|
||||||
|
* the {@link Certificate} of the user which has the privilege to perform this action
|
||||||
|
*
|
||||||
|
* @return true if changes were persisted, false if not (i.e. not enabled)
|
||||||
|
*
|
||||||
|
* @throws AccessDeniedException
|
||||||
|
* if the users of the given certificate does not have the privilege to perform this action
|
||||||
|
*/
|
||||||
|
public boolean persistSessions(Certificate certificate) throws AccessDeniedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special method to perform work as a System user, meaning the given systemUsername corresponds to an account which
|
* Special method to perform work as a System user, meaning the given systemUsername corresponds to an account which
|
||||||
* has the state {@link UserState#SYSTEM} and this user must have privilege to perform the concrete implementation
|
* has the state {@link UserState#SYSTEM} and this user must have privilege to perform the concrete implementation
|
||||||
|
|
|
@ -104,8 +104,8 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
||||||
@Override
|
@Override
|
||||||
public void replaceUser(User user) {
|
public void replaceUser(User user) {
|
||||||
if (!this.userMap.containsKey(user.getUsername()))
|
if (!this.userMap.containsKey(user.getUsername()))
|
||||||
throw new IllegalStateException(MessageFormat.format(
|
throw new IllegalStateException(MessageFormat
|
||||||
"The user {0} can not be replaced as it does not exiset!", user.getUsername()));
|
.format("The user {0} can not be replaced as it does not exiset!", user.getUsername()));
|
||||||
this.userMap.put(user.getUsername(), user);
|
this.userMap.put(user.getUsername(), user);
|
||||||
this.userMapDirty = true;
|
this.userMapDirty = true;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +121,8 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
||||||
@Override
|
@Override
|
||||||
public void replaceRole(Role role) {
|
public void replaceRole(Role role) {
|
||||||
if (!this.roleMap.containsKey(role.getName()))
|
if (!this.roleMap.containsKey(role.getName()))
|
||||||
throw new IllegalStateException(MessageFormat.format(
|
throw new IllegalStateException(
|
||||||
"The role {0} can not be replaced as it does not exist!", role.getName()));
|
MessageFormat.format("The role {0} can not be replaced as it does not exist!", role.getName()));
|
||||||
this.roleMap.put(role.getName(), role);
|
this.roleMap.put(role.getName(), role);
|
||||||
this.roleMapDirty = true;
|
this.roleMapDirty = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,11 @@ public class XmlConstants {
|
||||||
*/
|
*/
|
||||||
public static final String XML_ROOT_PRIVILEGE_USERS_AND_ROLES = "UsersAndRoles";
|
public static final String XML_ROOT_PRIVILEGE_USERS_AND_ROLES = "UsersAndRoles";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ROOT_CERTIFICATES = "Certificates" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ROOT_CERTIFICATES = "Certificates";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_HANDLER_PERSISTENCE = "PersistenceHandler" :
|
* XML_HANDLER_PERSISTENCE = "PersistenceHandler" :
|
||||||
*/
|
*/
|
||||||
|
@ -78,6 +83,16 @@ public class XmlConstants {
|
||||||
*/
|
*/
|
||||||
public static final String XML_USERS = "Users";
|
public static final String XML_USERS = "Users";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_CERTIFICATE = "Certificate" :
|
||||||
|
*/
|
||||||
|
public static final String XML_CERTIFICATE = "Certificate";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_SESSION_DATA = "SessionData" :
|
||||||
|
*/
|
||||||
|
public static final String XML_SESSION_DATA = "SessionData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_USER = "User"
|
* XML_USER = "User"
|
||||||
*/
|
*/
|
||||||
|
@ -153,6 +168,16 @@ public class XmlConstants {
|
||||||
*/
|
*/
|
||||||
public static final String XML_ATTR_CLASS = "class";
|
public static final String XML_ATTR_CLASS = "class";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ATTR_LOGIN_TIME = "loginTime" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ATTR_LOGIN_TIME = "loginTime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ATTR_LAST_ACCESS = "lastAccess" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ATTR_LAST_ACCESS = "lastAccess";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_ATTR_NAME = "name" :
|
* XML_ATTR_NAME = "name" :
|
||||||
*/
|
*/
|
||||||
|
@ -173,11 +198,26 @@ public class XmlConstants {
|
||||||
*/
|
*/
|
||||||
public static final String XML_ATTR_USER_ID = "userId";
|
public static final String XML_ATTR_USER_ID = "userId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ATTR_SESSION_ID = "sessionId" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ATTR_SESSION_ID = "sessionId";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_ATTR_USERNAME = "username" :
|
* XML_ATTR_USERNAME = "username" :
|
||||||
*/
|
*/
|
||||||
public static final String XML_ATTR_USERNAME = "username";
|
public static final String XML_ATTR_USERNAME = "username";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ATTR_AUTH_TOKEN = "authToken" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ATTR_AUTH_TOKEN = "authToken";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XML_ATTR_LOCALE = "locale" :
|
||||||
|
*/
|
||||||
|
public static final String XML_ATTR_LOCALE = "locale";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XML_ATTR_PASSWORD = "password" :
|
* XML_ATTR_PASSWORD = "password" :
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,7 +18,6 @@ package ch.eitchnet.privilege.model;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -40,15 +39,15 @@ public final class Certificate implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final String sessionId;
|
private final String sessionId;
|
||||||
private final Date loginTime;
|
|
||||||
private final String username;
|
private final String username;
|
||||||
private final String firstname;
|
private final String firstname;
|
||||||
private final String lastname;
|
private final String lastname;
|
||||||
|
private final UserState userState;
|
||||||
private final String authToken;
|
private final String authToken;
|
||||||
|
private final Date loginTime;
|
||||||
|
|
||||||
private final Set<String> userRoles;
|
private final Set<String> userRoles;
|
||||||
private final Map<String, String> propertyMap;
|
private final Map<String, String> propertyMap;
|
||||||
private final Map<String, String> sessionDataMap;
|
|
||||||
|
|
||||||
private Locale locale;
|
private Locale locale;
|
||||||
private Date lastAccess;
|
private Date lastAccess;
|
||||||
|
@ -79,8 +78,8 @@ public final class Certificate implements Serializable {
|
||||||
* a {@link Map} containing string value pairs of properties for the logged in user. These properties can
|
* a {@link Map} containing string value pairs of properties for the logged in user. These properties can
|
||||||
* be edited and can be used for the user to change settings of this session
|
* be edited and can be used for the user to change settings of this session
|
||||||
*/
|
*/
|
||||||
public Certificate(String sessionId, Date loginTime, String username, String firstname, String lastname,
|
public Certificate(String sessionId, String username, String firstname, String lastname, UserState userState,
|
||||||
String authToken, Locale locale, Set<String> userRoles, Map<String, String> propertyMap) {
|
String authToken, Date loginTime, Locale locale, Set<String> userRoles, Map<String, String> propertyMap) {
|
||||||
|
|
||||||
// validate arguments are not null
|
// validate arguments are not null
|
||||||
if (StringHelper.isEmpty(sessionId)) {
|
if (StringHelper.isEmpty(sessionId)) {
|
||||||
|
@ -92,13 +91,17 @@ public final class Certificate implements Serializable {
|
||||||
if (StringHelper.isEmpty(authToken)) {
|
if (StringHelper.isEmpty(authToken)) {
|
||||||
throw new PrivilegeException("authToken is null!"); //$NON-NLS-1$
|
throw new PrivilegeException("authToken is null!"); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
if (userState == null) {
|
||||||
|
throw new PrivilegeException("userState is null!"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.loginTime = loginTime;
|
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.firstname = firstname;
|
this.firstname = firstname;
|
||||||
this.lastname = lastname;
|
this.lastname = lastname;
|
||||||
|
this.userState = userState;
|
||||||
this.authToken = authToken;
|
this.authToken = authToken;
|
||||||
|
this.loginTime = loginTime;
|
||||||
|
|
||||||
// if no locale is given, set default
|
// if no locale is given, set default
|
||||||
if (locale == null)
|
if (locale == null)
|
||||||
|
@ -112,7 +115,6 @@ public final class Certificate implements Serializable {
|
||||||
this.propertyMap = Collections.unmodifiableMap(propertyMap);
|
this.propertyMap = Collections.unmodifiableMap(propertyMap);
|
||||||
|
|
||||||
this.userRoles = Collections.unmodifiableSet(userRoles);
|
this.userRoles = Collections.unmodifiableSet(userRoles);
|
||||||
this.sessionDataMap = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -157,15 +159,6 @@ public final class Certificate implements Serializable {
|
||||||
return this.propertyMap.get(key);
|
return this.propertyMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a mutable {@link Map} for storing session relevant data
|
|
||||||
*
|
|
||||||
* @return the sessionDataMap
|
|
||||||
*/
|
|
||||||
public Map<String, String> getSessionDataMap() {
|
|
||||||
return this.sessionDataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the locale
|
* @return the locale
|
||||||
*/
|
*/
|
||||||
|
@ -209,6 +202,13 @@ public final class Certificate implements Serializable {
|
||||||
return this.lastname;
|
return this.lastname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the userState
|
||||||
|
*/
|
||||||
|
public UserState getUserState() {
|
||||||
|
return userState;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the loginTime
|
* @return the loginTime
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -53,4 +53,8 @@ public enum UserState {
|
||||||
* This is the System user state which is special and thus exempted from normal uses
|
* This is the System user state which is special and thus exempted from normal uses
|
||||||
*/
|
*/
|
||||||
SYSTEM;
|
SYSTEM;
|
||||||
|
|
||||||
|
public boolean isSystem() {
|
||||||
|
return this == UserState.SYSTEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* Licensed 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 ch.eitchnet.privilege.xml;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
import ch.eitchnet.privilege.helper.XmlConstants;
|
||||||
|
import ch.eitchnet.privilege.model.Certificate;
|
||||||
|
import ch.eitchnet.utils.helper.XmlHelper;
|
||||||
|
import ch.eitchnet.utils.iso8601.ISO8601FormatFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*/
|
||||||
|
public class CertificateStubsDomWriter {
|
||||||
|
|
||||||
|
private List<Certificate> certificates;
|
||||||
|
private OutputStream outputStream;
|
||||||
|
|
||||||
|
public CertificateStubsDomWriter(List<Certificate> certificates, OutputStream outputStream) {
|
||||||
|
this.certificates = certificates;
|
||||||
|
this.outputStream = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write() {
|
||||||
|
|
||||||
|
// create document root
|
||||||
|
Document doc = XmlHelper.createDocument();
|
||||||
|
Element rootElement = doc.createElement(XmlConstants.XML_ROOT_CERTIFICATES);
|
||||||
|
doc.appendChild(rootElement);
|
||||||
|
|
||||||
|
this.certificates.stream().sorted((c1, c2) -> c1.getSessionId().compareTo(c2.getSessionId())).forEach(cert -> {
|
||||||
|
|
||||||
|
// create the certificate element
|
||||||
|
Element certElement = doc.createElement(XmlConstants.XML_CERTIFICATE);
|
||||||
|
rootElement.appendChild(certElement);
|
||||||
|
|
||||||
|
// sessionId;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_SESSION_ID, cert.getSessionId());
|
||||||
|
|
||||||
|
// username;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_USERNAME, cert.getUsername());
|
||||||
|
|
||||||
|
// authToken;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_AUTH_TOKEN, cert.getAuthToken());
|
||||||
|
|
||||||
|
// locale;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_LOCALE, cert.getLocale().toString());
|
||||||
|
|
||||||
|
// loginTime;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_LOGIN_TIME,
|
||||||
|
ISO8601FormatFactory.getInstance().formatDate(cert.getLoginTime()));
|
||||||
|
|
||||||
|
// lastAccess;
|
||||||
|
certElement.setAttribute(XmlConstants.XML_ATTR_LAST_ACCESS,
|
||||||
|
ISO8601FormatFactory.getInstance().formatDate(cert.getLastAccess()));
|
||||||
|
});
|
||||||
|
|
||||||
|
// write the container file to disk
|
||||||
|
XmlHelper.writeDocument(doc, this.outputStream);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*
|
||||||
|
* Licensed 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 ch.eitchnet.privilege.xml;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
import ch.eitchnet.privilege.base.PrivilegeException;
|
||||||
|
import ch.eitchnet.privilege.helper.XmlConstants;
|
||||||
|
import ch.eitchnet.utils.dbc.DBC;
|
||||||
|
import ch.eitchnet.utils.helper.XmlHelper;
|
||||||
|
import ch.eitchnet.utils.iso8601.ISO8601FormatFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*/
|
||||||
|
public class CertificateStubsSaxReader extends DefaultHandler {
|
||||||
|
|
||||||
|
private InputStream inputStream;
|
||||||
|
private List<CertificateStub> stubs;
|
||||||
|
|
||||||
|
public CertificateStubsSaxReader(InputStream inputStream) {
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CertificateStub> read() {
|
||||||
|
this.stubs = new ArrayList<>();
|
||||||
|
XmlHelper.parseDocument(this.inputStream, this);
|
||||||
|
return stubs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
|
|
||||||
|
switch (qName) {
|
||||||
|
case XmlConstants.XML_ROOT_CERTIFICATES:
|
||||||
|
break;
|
||||||
|
case XmlConstants.XML_CERTIFICATE:
|
||||||
|
|
||||||
|
CertificateStub stub = new CertificateStub();
|
||||||
|
stub.sessionId = attributes.getValue(XmlConstants.XML_ATTR_SESSION_ID);
|
||||||
|
stub.username = attributes.getValue(XmlConstants.XML_ATTR_USERNAME);
|
||||||
|
stub.authToken = attributes.getValue(XmlConstants.XML_ATTR_AUTH_TOKEN);
|
||||||
|
stub.locale = new Locale(attributes.getValue(XmlConstants.XML_ATTR_LOCALE));
|
||||||
|
stub.loginTime = ISO8601FormatFactory.getInstance()
|
||||||
|
.parseDate(attributes.getValue(XmlConstants.XML_ATTR_LOGIN_TIME));
|
||||||
|
stub.lastAccess = ISO8601FormatFactory.getInstance()
|
||||||
|
.parseDate(attributes.getValue(XmlConstants.XML_ATTR_LAST_ACCESS));
|
||||||
|
|
||||||
|
DBC.INTERIM.assertNotEmpty("sessionId missing on sessions data!", stub.sessionId);
|
||||||
|
DBC.INTERIM.assertNotEmpty("username missing on sessions data!", stub.username);
|
||||||
|
DBC.INTERIM.assertNotEmpty("authToken missing on sessions data!", stub.authToken);
|
||||||
|
|
||||||
|
this.stubs.add(stub);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new PrivilegeException("Unhandled tag " + qName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CertificateStub {
|
||||||
|
private String sessionId;
|
||||||
|
private String username;
|
||||||
|
private String authToken;
|
||||||
|
private Locale locale;
|
||||||
|
private Date loginTime;
|
||||||
|
private Date lastAccess;
|
||||||
|
|
||||||
|
public String getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthToken() {
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Locale getLocale() {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLoginTime() {
|
||||||
|
return loginTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastAccess() {
|
||||||
|
return lastAccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,8 +32,6 @@ import ch.eitchnet.privilege.model.internal.PrivilegeContainerModel;
|
||||||
*/
|
*/
|
||||||
public class PrivilegeConfigSaxReader extends DefaultHandler {
|
public class PrivilegeConfigSaxReader extends DefaultHandler {
|
||||||
|
|
||||||
// private static final Logger logger = LoggerFactory.getLogger(PrivilegeConfigSaxReader.class);
|
|
||||||
|
|
||||||
private Deque<ElementParser> buildersStack = new ArrayDeque<ElementParser>();
|
private Deque<ElementParser> buildersStack = new ArrayDeque<ElementParser>();
|
||||||
|
|
||||||
private PrivilegeContainerModel containerModel;
|
private PrivilegeContainerModel containerModel;
|
||||||
|
@ -109,7 +107,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
||||||
private String currentElement;
|
private String currentElement;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
|
throws SAXException {
|
||||||
if (qName.equals(XmlConstants.XML_CONTAINER)) {
|
if (qName.equals(XmlConstants.XML_CONTAINER)) {
|
||||||
this.currentElement = qName;
|
this.currentElement = qName;
|
||||||
} else if (qName.equals(XmlConstants.XML_HANDLER_ENCRYPTION)) {
|
} else if (qName.equals(XmlConstants.XML_HANDLER_ENCRYPTION)) {
|
||||||
|
@ -147,7 +146,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
||||||
private Map<String, String> parameterMap = new HashMap<String, String>();
|
private Map<String, String> parameterMap = new HashMap<String, String>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
|
throws SAXException {
|
||||||
if (qName.equals(XmlConstants.XML_PARAMETER)) {
|
if (qName.equals(XmlConstants.XML_PARAMETER)) {
|
||||||
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
||||||
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE);
|
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE);
|
||||||
|
@ -168,7 +168,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
||||||
// <Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
|
// <Policy name="DefaultPrivilege" class="ch.eitchnet.privilege.policy.DefaultPrivilege" />
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
|
throws SAXException {
|
||||||
if (qName.equals(XmlConstants.XML_POLICY)) {
|
if (qName.equals(XmlConstants.XML_POLICY)) {
|
||||||
String policyName = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
String policyName = attributes.getValue(XmlConstants.XML_ATTR_NAME);
|
||||||
String policyClassName = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
String policyClassName = attributes.getValue(XmlConstants.XML_ATTR_CLASS);
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package ch.eitchnet.privilege.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ch.eitchnet.privilege.base.PrivilegeException;
|
||||||
|
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
||||||
|
import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper;
|
||||||
|
import ch.eitchnet.privilege.model.Certificate;
|
||||||
|
import ch.eitchnet.privilege.model.PrivilegeContext;
|
||||||
|
import ch.eitchnet.utils.helper.FileHelper;
|
||||||
|
|
||||||
|
public class AbstractPrivilegeTest {
|
||||||
|
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger(AbstractPrivilegeTest.class);
|
||||||
|
|
||||||
|
protected PrivilegeHandler privilegeHandler;
|
||||||
|
protected PrivilegeContext ctx;
|
||||||
|
|
||||||
|
protected void login(String username, byte[] password) {
|
||||||
|
Certificate certificate = privilegeHandler.authenticate(username, password);
|
||||||
|
assertTrue("Certificate is null!", certificate != null);
|
||||||
|
PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate);
|
||||||
|
this.ctx = privilegeContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logout() {
|
||||||
|
if (this.ctx != null) {
|
||||||
|
try {
|
||||||
|
PrivilegeContext privilegeContext = this.ctx;
|
||||||
|
this.ctx = null;
|
||||||
|
privilegeHandler.invalidateSession(privilegeContext.getCertificate());
|
||||||
|
} catch (PrivilegeException e) {
|
||||||
|
String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!";
|
||||||
|
if (!e.getMessage().equals(msg))
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void prepareConfigs(String dst, String configFilename, String modelFilename) {
|
||||||
|
try {
|
||||||
|
String pwd = System.getProperty("user.dir");
|
||||||
|
|
||||||
|
File configPath = new File(pwd, "config");
|
||||||
|
|
||||||
|
File privilegeConfigFile = new File(configPath, configFilename);
|
||||||
|
File privilegeModelFile = new File(configPath, modelFilename);
|
||||||
|
|
||||||
|
File targetPath = new File(pwd, "target/" + dst);
|
||||||
|
if (!targetPath.mkdirs())
|
||||||
|
throw new RuntimeException("Could not create parent " + targetPath);
|
||||||
|
|
||||||
|
File dstConfig = new File(targetPath, configFilename);
|
||||||
|
File dstModel = new File(targetPath, modelFilename);
|
||||||
|
|
||||||
|
// write config
|
||||||
|
String config = new String(Files.readAllBytes(privilegeConfigFile.toPath()), "UTF-8");
|
||||||
|
config = config.replace("${target}", dst);
|
||||||
|
Files.write(dstConfig.toPath(), config.getBytes("UTF-8"));
|
||||||
|
|
||||||
|
// copy model
|
||||||
|
Files.copy(privilegeModelFile.toPath(), dstModel.toPath());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void removeConfigs(String dst) {
|
||||||
|
try {
|
||||||
|
String pwd = System.getProperty("user.dir");
|
||||||
|
File targetPath = new File(pwd, "target");
|
||||||
|
targetPath = new File(targetPath, dst);
|
||||||
|
if (targetPath.exists() && !FileHelper.deleteFile(targetPath, true)) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Tmp configuration still exists and can not be deleted at " + targetPath.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static File getPrivilegeConfigFile(String dst, String configFilename) {
|
||||||
|
try {
|
||||||
|
String pwd = System.getProperty("user.dir");
|
||||||
|
File targetPath = new File(pwd, "target");
|
||||||
|
targetPath = new File(targetPath, dst);
|
||||||
|
return new File(targetPath, configFilename);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initialize(String dst, String configFilename) {
|
||||||
|
try {
|
||||||
|
File privilegeConfigFile = getPrivilegeConfigFile(dst, configFilename);
|
||||||
|
this.privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException("Initialization failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ch.eitchnet.privilege.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PersistSessionsTest extends AbstractPrivilegeTest {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() throws Exception {
|
||||||
|
removeConfigs(PersistSessionsTest.class.getSimpleName());
|
||||||
|
prepareConfigs(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeModel.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void destroy() throws Exception {
|
||||||
|
removeConfigs(PersistSessionsTest.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
initialize(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldPersistAndReloadSessions() {
|
||||||
|
|
||||||
|
// assert no sessions file
|
||||||
|
File sessionsFile = new File("target/PersistSessionsTest/sessions.dat");
|
||||||
|
assertFalse("Sessions File should no yet exist", sessionsFile.exists());
|
||||||
|
|
||||||
|
// login and assert sessions file was written
|
||||||
|
login("admin", "admin".getBytes());
|
||||||
|
this.privilegeHandler.isCertificateValid(ctx.getCertificate());
|
||||||
|
assertTrue("Sessions File should have been created!", sessionsFile.isFile());
|
||||||
|
|
||||||
|
// re-initialize and assert still logged in
|
||||||
|
initialize(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml");
|
||||||
|
this.privilegeHandler.isCertificateValid(ctx.getCertificate());
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,120 +19,33 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ch.eitchnet.privilege.base.PrivilegeException;
|
|
||||||
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
|
||||||
import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper;
|
|
||||||
import ch.eitchnet.privilege.model.Certificate;
|
|
||||||
import ch.eitchnet.privilege.model.IPrivilege;
|
import ch.eitchnet.privilege.model.IPrivilege;
|
||||||
import ch.eitchnet.privilege.model.PrivilegeContext;
|
|
||||||
import ch.eitchnet.utils.helper.FileHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
public class PrivilegeConflictMergeTest {
|
public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PrivilegeConflictMergeTest.class);
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
try {
|
removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName());
|
||||||
destroy();
|
prepareConfigs(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml",
|
||||||
|
"PrivilegeModelMerge.xml");
|
||||||
// copy configuration to tmp
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File origPrivilegeModelFile = new File(pwd + "/config/PrivilegeModelMerge.xml");
|
|
||||||
File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModelMerge.xml");
|
|
||||||
if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) {
|
|
||||||
throw new RuntimeException("Tmp configuration still exists and can not be deleted at "
|
|
||||||
+ tmpPrivilegeModelFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
File parentFile = tmpPrivilegeModelFile.getParentFile();
|
|
||||||
if (!parentFile.exists()) {
|
|
||||||
if (!parentFile.mkdirs())
|
|
||||||
throw new RuntimeException("Could not create parent for tmp " + tmpPrivilegeModelFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FileHelper.copy(origPrivilegeModelFile, tmpPrivilegeModelFile, true))
|
|
||||||
throw new RuntimeException("Failed to copy " + origPrivilegeModelFile + " to " + tmpPrivilegeModelFile);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
|
|
||||||
throw new RuntimeException("Initialization failed: " + e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void destroy() throws Exception {
|
public static void destroy() throws Exception {
|
||||||
|
removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName());
|
||||||
// delete temporary file
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModelMerge.xml");
|
|
||||||
if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) {
|
|
||||||
throw new RuntimeException("Tmp configuration still exists and can not be deleted at "
|
|
||||||
+ tmpPrivilegeModelFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
// and temporary parent
|
|
||||||
File parentFile = tmpPrivilegeModelFile.getParentFile();
|
|
||||||
if (parentFile.exists() && !parentFile.delete()) {
|
|
||||||
throw new RuntimeException("Could not remove temporary parent for tmp " + tmpPrivilegeModelFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PrivilegeHandler privilegeHandler;
|
|
||||||
private PrivilegeContext ctx;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
try {
|
initialize(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml");
|
||||||
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File privilegeConfigFile = new File(pwd + "/config/PrivilegeConfigMerge.xml");
|
|
||||||
|
|
||||||
// initialize privilege
|
|
||||||
privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
|
|
||||||
throw new RuntimeException("Setup failed: " + e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void login(String username, byte[] password) {
|
|
||||||
Certificate certificate = privilegeHandler.authenticate(username, password);
|
|
||||||
assertTrue("Certificate is null!", certificate != null);
|
|
||||||
PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate);
|
|
||||||
this.ctx = privilegeContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logout() {
|
|
||||||
if (this.ctx != null) {
|
|
||||||
try {
|
|
||||||
PrivilegeContext privilegeContext = this.ctx;
|
|
||||||
this.ctx = null;
|
|
||||||
privilegeHandler.invalidateSession(privilegeContext.getCertificate());
|
|
||||||
} catch (PrivilegeException e) {
|
|
||||||
String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!";
|
|
||||||
if (!e.getMessage().equals(msg))
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -17,10 +17,8 @@ package ch.eitchnet.privilege.test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -42,10 +40,8 @@ import org.slf4j.LoggerFactory;
|
||||||
import ch.eitchnet.privilege.base.AccessDeniedException;
|
import ch.eitchnet.privilege.base.AccessDeniedException;
|
||||||
import ch.eitchnet.privilege.base.PrivilegeException;
|
import ch.eitchnet.privilege.base.PrivilegeException;
|
||||||
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
||||||
import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper;
|
|
||||||
import ch.eitchnet.privilege.i18n.PrivilegeMessages;
|
import ch.eitchnet.privilege.i18n.PrivilegeMessages;
|
||||||
import ch.eitchnet.privilege.model.Certificate;
|
import ch.eitchnet.privilege.model.Certificate;
|
||||||
import ch.eitchnet.privilege.model.PrivilegeContext;
|
|
||||||
import ch.eitchnet.privilege.model.PrivilegeRep;
|
import ch.eitchnet.privilege.model.PrivilegeRep;
|
||||||
import ch.eitchnet.privilege.model.Restrictable;
|
import ch.eitchnet.privilege.model.Restrictable;
|
||||||
import ch.eitchnet.privilege.model.RoleRep;
|
import ch.eitchnet.privilege.model.RoleRep;
|
||||||
|
@ -55,7 +51,6 @@ import ch.eitchnet.privilege.test.model.TestRestrictable;
|
||||||
import ch.eitchnet.privilege.test.model.TestSystemUserAction;
|
import ch.eitchnet.privilege.test.model.TestSystemUserAction;
|
||||||
import ch.eitchnet.privilege.test.model.TestSystemUserActionDeny;
|
import ch.eitchnet.privilege.test.model.TestSystemUserActionDeny;
|
||||||
import ch.eitchnet.utils.helper.ArraysHelper;
|
import ch.eitchnet.utils.helper.ArraysHelper;
|
||||||
import ch.eitchnet.utils.helper.FileHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JUnit for performing Privilege tests. This JUnit is by no means complete, but checks the bare minimum.br />
|
* JUnit for performing Privilege tests. This JUnit is by no means complete, but checks the bare minimum.br />
|
||||||
|
@ -65,7 +60,7 @@ import ch.eitchnet.utils.helper.FileHelper;
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("nls")
|
@SuppressWarnings("nls")
|
||||||
public class PrivilegeTest {
|
public class PrivilegeTest extends AbstractPrivilegeTest {
|
||||||
|
|
||||||
private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin";
|
private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin";
|
||||||
private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege";
|
private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege";
|
||||||
|
@ -91,96 +86,20 @@ public class PrivilegeTest {
|
||||||
@Rule
|
@Rule
|
||||||
public ExpectedException exception = ExpectedException.none();
|
public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
private static PrivilegeHandler privilegeHandler;
|
|
||||||
private PrivilegeContext ctx;
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
try {
|
removeConfigs(PrivilegeTest.class.getSimpleName());
|
||||||
destroy();
|
prepareConfigs(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeModel.xml");
|
||||||
|
|
||||||
// copy configuration to tmp
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File origPrivilegeModelFile = new File(pwd + "/config/PrivilegeModel.xml");
|
|
||||||
File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModel.xml");
|
|
||||||
if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) {
|
|
||||||
throw new RuntimeException("Tmp configuration still exists and can not be deleted at "
|
|
||||||
+ tmpPrivilegeModelFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
File parentFile = tmpPrivilegeModelFile.getParentFile();
|
|
||||||
if (!parentFile.exists()) {
|
|
||||||
if (!parentFile.mkdirs())
|
|
||||||
throw new RuntimeException("Could not create parent for tmp " + tmpPrivilegeModelFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FileHelper.copy(origPrivilegeModelFile, tmpPrivilegeModelFile, true))
|
|
||||||
throw new RuntimeException("Failed to copy " + origPrivilegeModelFile + " to " + tmpPrivilegeModelFile);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
|
|
||||||
throw new RuntimeException("Initialization failed: " + e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void destroy() throws Exception {
|
public static void destroy() throws Exception {
|
||||||
|
removeConfigs(PrivilegeTest.class.getSimpleName());
|
||||||
// delete temporary file
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModel.xml");
|
|
||||||
if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) {
|
|
||||||
throw new RuntimeException("Tmp configuration still exists and can not be deleted at "
|
|
||||||
+ tmpPrivilegeModelFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
// and temporary parent
|
|
||||||
File parentFile = tmpPrivilegeModelFile.getParentFile();
|
|
||||||
if (parentFile.exists() && !parentFile.delete()) {
|
|
||||||
throw new RuntimeException("Could not remove temporary parent for tmp " + tmpPrivilegeModelFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
try {
|
initialize(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml");
|
||||||
|
|
||||||
String pwd = System.getProperty("user.dir");
|
|
||||||
|
|
||||||
File privilegeConfigFile = new File(pwd + "/config/PrivilegeConfig.xml");
|
|
||||||
|
|
||||||
// initialize privilege
|
|
||||||
privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
|
|
||||||
throw new RuntimeException("Setup failed: " + e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void login(String username, byte[] password) {
|
|
||||||
Certificate certificate = privilegeHandler.authenticate(username, password);
|
|
||||||
assertTrue("Certificate is null!", certificate != null);
|
|
||||||
PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate);
|
|
||||||
this.ctx = privilegeContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logout() {
|
|
||||||
if (this.ctx != null) {
|
|
||||||
try {
|
|
||||||
PrivilegeContext privilegeContext = this.ctx;
|
|
||||||
this.ctx = null;
|
|
||||||
privilegeHandler.invalidateSession(privilegeContext.getCertificate());
|
|
||||||
} catch (PrivilegeException e) {
|
|
||||||
String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!";
|
|
||||||
if (!e.getMessage().equals(msg))
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -258,8 +177,8 @@ public class PrivilegeTest {
|
||||||
@Test
|
@Test
|
||||||
public void testPerformSystemRestrictableFailPrivilege() throws Exception {
|
public void testPerformSystemRestrictableFailPrivilege() throws Exception {
|
||||||
this.exception.expect(PrivilegeException.class);
|
this.exception.expect(PrivilegeException.class);
|
||||||
this.exception
|
this.exception.expectMessage(
|
||||||
.expectMessage("User system_admin does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction");
|
"User system_admin does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction");
|
||||||
try {
|
try {
|
||||||
// create the action to be performed as a system user
|
// create the action to be performed as a system user
|
||||||
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
|
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
|
||||||
|
@ -277,8 +196,8 @@ public class PrivilegeTest {
|
||||||
@Test
|
@Test
|
||||||
public void testPerformSystemRestrictableFailNoAdditionalPrivilege() throws Exception {
|
public void testPerformSystemRestrictableFailNoAdditionalPrivilege() throws Exception {
|
||||||
this.exception.expect(PrivilegeException.class);
|
this.exception.expect(PrivilegeException.class);
|
||||||
this.exception
|
this.exception.expectMessage(
|
||||||
.expectMessage("User system_admin2 does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction needed for Restrictable ch.eitchnet.privilege.test.model.TestSystemUserActionDeny");
|
"User system_admin2 does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction needed for Restrictable ch.eitchnet.privilege.test.model.TestSystemUserActionDeny");
|
||||||
try {
|
try {
|
||||||
// create the action to be performed as a system user
|
// create the action to be performed as a system user
|
||||||
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
|
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
|
||||||
|
@ -398,8 +317,8 @@ public class PrivilegeTest {
|
||||||
|
|
||||||
Certificate certificate = this.ctx.getCertificate();
|
Certificate certificate = this.ctx.getCertificate();
|
||||||
|
|
||||||
UserRep selectorRep = new UserRep(null, null, null, null, null, new HashSet<>(
|
UserRep selectorRep = new UserRep(null, null, null, null, null,
|
||||||
Arrays.asList("PrivilegeAdmin")), null, null);
|
new HashSet<>(Arrays.asList("PrivilegeAdmin")), null, null);
|
||||||
List<UserRep> users = privilegeHandler.queryUsers(certificate, selectorRep);
|
List<UserRep> users = privilegeHandler.queryUsers(certificate, selectorRep);
|
||||||
assertEquals(1, users.size());
|
assertEquals(1, users.size());
|
||||||
assertEquals(ADMIN, users.get(0).getUsername());
|
assertEquals(ADMIN, users.get(0).getUsername());
|
||||||
|
@ -590,8 +509,8 @@ public class PrivilegeTest {
|
||||||
|
|
||||||
PrivilegeRep passwordRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_PASSWORD,
|
PrivilegeRep passwordRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_PASSWORD,
|
||||||
PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet());
|
PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet());
|
||||||
PrivilegeRep localeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_LOCALE,
|
PrivilegeRep localeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_LOCALE, PRIVILEGE_USER_ACCESS,
|
||||||
PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet());
|
false, Collections.emptySet(), Collections.emptySet());
|
||||||
|
|
||||||
RoleRep roleRep = new RoleRep(ROLE_CHANGE_PW, Arrays.asList(passwordRep, localeRep));
|
RoleRep roleRep = new RoleRep(ROLE_CHANGE_PW, Arrays.asList(passwordRep, localeRep));
|
||||||
|
|
||||||
|
@ -818,8 +737,8 @@ public class PrivilegeTest {
|
||||||
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
|
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
|
||||||
|
|
||||||
// let's add a new user bob
|
// let's add a new user bob
|
||||||
UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW, new HashSet<String>(
|
UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW,
|
||||||
Arrays.asList(ROLE_MY)), null, new HashMap<String, String>());
|
new HashSet<String>(Arrays.asList(ROLE_MY)), null, new HashMap<String, String>());
|
||||||
Certificate certificate = this.ctx.getCertificate();
|
Certificate certificate = this.ctx.getCertificate();
|
||||||
privilegeHandler.addUser(certificate, userRep, null);
|
privilegeHandler.addUser(certificate, userRep, null);
|
||||||
logger.info("Added user " + BOB);
|
logger.info("Added user " + BOB);
|
||||||
|
|
|
@ -120,7 +120,7 @@ public class XmlTest {
|
||||||
assertNotNull(containerModel.getPersistenceHandlerClassName());
|
assertNotNull(containerModel.getPersistenceHandlerClassName());
|
||||||
assertNotNull(containerModel.getPersistenceHandlerParameterMap());
|
assertNotNull(containerModel.getPersistenceHandlerParameterMap());
|
||||||
|
|
||||||
assertEquals(2, containerModel.getParameterMap().size());
|
assertEquals(6, containerModel.getParameterMap().size());
|
||||||
assertEquals(3, containerModel.getPolicies().size());
|
assertEquals(3, containerModel.getPolicies().size());
|
||||||
assertEquals(1, containerModel.getEncryptionHandlerParameterMap().size());
|
assertEquals(1, containerModel.getEncryptionHandlerParameterMap().size());
|
||||||
assertEquals(2, containerModel.getPersistenceHandlerParameterMap().size());
|
assertEquals(2, containerModel.getPersistenceHandlerParameterMap().size());
|
||||||
|
|
Loading…
Reference in New Issue