strolch/agent/src/main/java/li/strolch/runtime/privilege/DefaultStrolchPrivilegeHand...

287 lines
11 KiB
Java

/*
* 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 li.strolch.runtime.privilege;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.agent.api.StrolchRealm;
import li.strolch.model.audit.AccessType;
import li.strolch.model.audit.Audit;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.*;
import li.strolch.privilege.helper.PrivilegeInitializer;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Usage;
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
import li.strolch.privilege.xml.PrivilegeConfigSaxReader;
import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.configuration.RuntimeConfiguration;
import li.strolch.utils.helper.XmlHelper;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Map;
import static java.lang.Boolean.parseBoolean;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static li.strolch.persistence.api.TransactionThreadLocal.getTx;
import static li.strolch.persistence.api.TransactionThreadLocal.hasTx;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS_PATH;
import static li.strolch.privilege.helper.XmlConstants.PARAM_BASE_PATH;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.*;
public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements PrivilegeHandler {
public static final String PROP_PRIVILEGE_CONFIG_FILE = "privilegeConfigFile";
public static final String PRIVILEGE_CONFIG_XML = "PrivilegeConfig.xml";
private li.strolch.privilege.handler.PrivilegeHandler privilegeHandler;
public DefaultStrolchPrivilegeHandler(ComponentContainer container, String componentName) {
super(container, componentName);
}
@Override
public void initialize(ComponentConfiguration configuration) throws Exception {
super.initialize(configuration);
// initialize privilege
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
File privilegeConfigFile = configuration.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML,
runtimeConfiguration);
this.privilegeHandler = initializeFromXml(configuration, privilegeConfigFile);
}
@Override
public void reloadConfiguration() {
try {
runAsAgent(ctx -> this.privilegeHandler.persistSessions(ctx.getCertificate(), getClass().getName()));
} catch (Exception e) {
logger.error("Failed to persist sessions", e);
}
ComponentConfiguration configuration = getConfiguration();
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
File privilegeConfigFile = configuration.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML,
runtimeConfiguration);
this.privilegeHandler = initializeFromXml(configuration, privilegeConfigFile);
}
/**
* Initializes the {@link DefaultPrivilegeHandler} from the configuration file
*
* @param privilegeXmlFile a {@link File} reference to the XML file containing the configuration for Privilege
*
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and
* {@link PersistenceHandler} are set and initialized as well
*/
private li.strolch.privilege.handler.PrivilegeHandler initializeFromXml(ComponentConfiguration configuration,
File privilegeXmlFile) {
// make sure file exists
if (!privilegeXmlFile.exists()) {
String msg = "Privilege file does not exist at path {0}";
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
throw new PrivilegeException(msg);
}
try (InputStream inputStream = Files.newInputStream(privilegeXmlFile.toPath())) {
// parse configuration file
PrivilegeContainerModel containerModel = new PrivilegeContainerModel();
PrivilegeConfigSaxReader xmlHandler = new PrivilegeConfigSaxReader(containerModel);
XmlHelper.parseDocument(inputStream, xmlHandler);
Map<String, String> parameterMap = containerModel.getParameterMap();
RuntimeConfiguration runtimeConfig = configuration.getRuntimeConfiguration();
// set sessions data path
if (parseBoolean(parameterMap.get(PARAM_PERSIST_SESSIONS))) {
File dataPath = runtimeConfig.getTempPath();
String sessionsPath = new File(dataPath, "sessions.dat").getAbsolutePath();
parameterMap.put(PARAM_PERSIST_SESSIONS_PATH, sessionsPath);
}
// set base path
if (containerModel.getPersistenceHandlerClassName().equals(XmlPersistenceHandler.class.getName())) {
Map<String, String> xmlParams = containerModel.getPersistenceHandlerParameterMap();
File configPath = runtimeConfig.getConfigPath();
xmlParams.put(PARAM_BASE_PATH, configPath.getPath());
}
return new PrivilegeInitializer(getScheduledExecutor(getName())).initializeFromXml(containerModel);
} catch (Exception e) {
String msg = "Failed to load Privilege configuration from {0}";
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
throw new PrivilegeException(msg, e);
}
}
@Override
public Certificate authenticate(String username, char[] password) {
assertContainerStarted();
Certificate certificate = this.privilegeHandler.authenticate(username, password, false);
writeAudit(certificate, LOGIN, AccessType.CREATE, username);
return certificate;
}
@Override
public Certificate authenticate(String username, char[] password, String source, Usage usage, boolean keepAlive) {
assertContainerStarted();
Certificate certificate = this.privilegeHandler.authenticate(username, password, source, usage, keepAlive);
writeAudit(certificate, LOGIN, AccessType.CREATE, username);
return certificate;
}
@Override
public Certificate authenticateSingleSignOn(Object data) {
assertContainerStarted();
Certificate certificate = this.privilegeHandler.authenticateSingleSignOn(data, false);
writeAudit(certificate, LOGIN, AccessType.CREATE, certificate.getUsername());
return certificate;
}
@Override
public Certificate authenticateSingleSignOn(Object data, String source) {
assertContainerStarted();
Certificate certificate = this.privilegeHandler.authenticateSingleSignOn(data, source, false);
writeAudit(certificate, LOGIN, AccessType.CREATE, certificate.getUsername());
return certificate;
}
@Override
public Certificate refreshSession(Certificate certificate, String source) {
assertContainerStarted();
Certificate refreshedCert = this.privilegeHandler.refresh(certificate, source);
writeAudit(refreshedCert, LOGIN, AccessType.CREATE, refreshedCert.getUsername());
return refreshedCert;
}
@Override
public boolean isRefreshAllowed() {
return this.privilegeHandler.isRefreshAllowed();
}
private void writeAudit(Certificate certificate, String login, AccessType accessType, String username) {
StrolchRealm realm = getContainer().getRealm(certificate);
try (StrolchTransaction tx = hasTx() ? getTx() : openTx(certificate, login, realm)) {
tx.setSuppressAudits(true);
Audit audit = tx.auditFrom(accessType, PRIVILEGE, CERTIFICATE, username);
tx.getAuditTrail().add(tx, audit);
}
}
private static StrolchTransaction openTx(Certificate certificate, String login, StrolchRealm realm) {
return realm.openTx(certificate, login, false).silentThreshold(1, NANOSECONDS);
}
@Override
public PrivilegeContext validate(Certificate certificate) throws PrivilegeException {
return this.privilegeHandler.validate(certificate);
}
@Override
public PrivilegeContext validate(Certificate certificate, String source) throws PrivilegeException {
return this.privilegeHandler.validate(certificate, source);
}
@Override
public void validateSystemSession(PrivilegeContext ctx) throws PrivilegeException {
this.privilegeHandler.validateSystemSession(ctx);
}
@Override
public boolean invalidate(Certificate certificate) {
boolean invalidateSession = this.privilegeHandler.invalidate(certificate);
writeAudit(certificate, StrolchPrivilegeConstants.LOGOUT, AccessType.DELETE, certificate.getUsername());
return invalidateSession;
}
@Override
public boolean sessionTimeout(Certificate certificate) {
assertStarted();
boolean invalidateSession = this.privilegeHandler.invalidate(certificate);
writeAudit(certificate, StrolchPrivilegeConstants.SESSION_TIME_OUT, AccessType.DELETE,
certificate.getUsername());
return invalidateSession;
}
@Override
public void runAs(String username, SystemAction action) throws Exception {
this.privilegeHandler.runAs(username, action);
}
@Override
public <T> T runWithResult(String username, SystemActionWithResult<T> action) throws Exception {
return this.privilegeHandler.runWithResult(username, action);
}
@Override
public void runAs(String username, PrivilegedRunnable runnable) throws Exception {
this.privilegeHandler.runAs(username, new StrolchSystemAction(runnable));
}
@Override
public <T> T runWithResult(String username, PrivilegedRunnableWithResult<T> runnable) throws Exception {
return this.privilegeHandler.runWithResult(username, new StrolchSystemActionWithResult<>(runnable));
}
@Override
public void runAsAgent(SystemAction action) throws Exception {
this.privilegeHandler.runAs(StrolchConstants.SYSTEM_USER_AGENT, action);
}
@Override
public <T> T runAsAgentWithResult(SystemActionWithResult<T> action) throws Exception {
return this.privilegeHandler.runWithResult(StrolchConstants.SYSTEM_USER_AGENT, action);
}
@Override
public void runAsAgent(PrivilegedRunnable runnable) throws Exception {
this.privilegeHandler.runAs(StrolchConstants.SYSTEM_USER_AGENT, new StrolchSystemAction(runnable));
}
@Override
public <T> T runAsAgentWithResult(PrivilegedRunnableWithResult<T> runnable) throws Exception {
return this.privilegeHandler.runWithResult(StrolchConstants.SYSTEM_USER_AGENT,
new StrolchSystemActionWithResult<>(runnable));
}
@Override
public <T> T runAsWithResult(String username, PrivilegedRunnableWithResult<T> runnable) throws Exception {
return this.privilegeHandler.runWithResult(username, new StrolchSystemActionWithResult<>(runnable));
}
@Override
public PrivilegeContext openAgentSystemUserContext() throws PrivilegeException {
return this.privilegeHandler.openSystemUserContext(StrolchConstants.SYSTEM_USER_AGENT);
}
@Override
public li.strolch.privilege.handler.PrivilegeHandler getPrivilegeHandler() {
return this.privilegeHandler;
}
}