
eu.clarussecure.proxy.Proxy Maven / Gradle / Ivy
The newest version!
package eu.clarussecure.proxy;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import eu.clarussecure.proxy.protection.ProtectionModuleLoader;
import eu.clarussecure.proxy.protection.mongodb.EmbeddedMongoDB;
import eu.clarussecure.proxy.protocol.ProtocolLoader;
import eu.clarussecure.proxy.protocol.ProtocolServiceDelegate;
import eu.clarussecure.proxy.spi.Mode;
import eu.clarussecure.proxy.spi.Operation;
import eu.clarussecure.proxy.spi.protection.ProtectionModule;
import eu.clarussecure.proxy.spi.protection.ProtectionModuleCapabilities;
import eu.clarussecure.proxy.spi.protocol.Configuration;
import eu.clarussecure.proxy.spi.protocol.Protocol;
import eu.clarussecure.proxy.spi.protocol.ProtocolCapabilities;
import eu.clarussecure.proxy.spi.protocol.ProtocolService;
import eu.clarussecure.proxy.spi.protocol.ProtocolServiceNoop;
import eu.clarussecure.proxy.spi.security.policy.SecurityPolicy;
public class Proxy {
protected static final Logger LOGGER = LoggerFactory.getLogger(Proxy.class);
private final String securityPolicyPath;
private final List serverAddresses;
private final Integer maxFrameLen;
private final Integer nbListenThreads;
private final Integer nbSessionThreads;
private final Integer nbParserThreads;
private SecurityPolicy securityPolicy;
private Protocol protocol;
private Proxy(String securityPolicyPath, List serverAddresses, Integer maxFrameLen, Integer nbListenThreads,
Integer nbSessionThreads, Integer nbParserThreads) {
this.securityPolicyPath = securityPolicyPath;
this.serverAddresses = serverAddresses;
this.maxFrameLen = maxFrameLen;
this.nbListenThreads = nbListenThreads;
this.nbSessionThreads = nbSessionThreads;
this.nbParserThreads = nbParserThreads;
}
public void initialize() throws ParserConfigurationException, SAXException, IOException {
LOGGER.trace("Loading security policy from file: {} ...", securityPolicyPath);
// Load security policy
securityPolicy = SecurityPolicy.load(new File(securityPolicyPath));
LOGGER.debug("Security policy loaded from file: {}", securityPolicyPath);
// Load protection module
String protectionModuleName = securityPolicy.getProtectionModuleName();
ProtectionModule protectionModule = null;
if (protectionModuleName == null) {
LOGGER.debug("No protection module");
} else {
LOGGER.trace("Loading protection module '{}' ...", protectionModuleName);
protectionModule = ProtectionModuleLoader.getInstance().getProtectionModule(protectionModuleName);
LOGGER.debug("Protection module '{}' loaded", protectionModuleName);
}
// Load protocol plugin
String pluginName = securityPolicy.getProtocolPluginName();
LOGGER.trace("Loading protocol plugin '{}' ...", pluginName);
protocol = ProtocolLoader.getInstance().getProtocol(pluginName);
LOGGER.debug("Protocol plugin '{}' loaded", pluginName);
// Configure processing modes
LOGGER.trace("Configuring processing modes...");
ProtectionModuleCapabilities protectionModuleCapabilities = null;
if (protectionModule != null) {
protectionModuleCapabilities = protectionModule.getCapabilities();
}
ProtocolCapabilities protocolCapabilities = protocol.getCapabilities();
Configuration protocolConfiguration = protocol.getConfiguration();
// Configure dataset processing mode
configureProcessingModes(true, protectionModuleCapabilities, protocolCapabilities, protocolConfiguration);
// Configure records processing mode
configureProcessingModes(false, protectionModuleCapabilities, protocolCapabilities, protocolConfiguration);
LOGGER.debug("Processing modes configured");
LOGGER.trace("Configuring internal and external endpoints...");
// Configure listen port
Integer listenPort = securityPolicy.getProtocolListenPort();
if (listenPort != null) {
protocolConfiguration.setListenPort(listenPort);
}
// Configure server addresses
List serverEndpoints = serverAddresses.stream().map(serverAddress -> {
String[] tokens = serverAddress.split(":");
String hostname = tokens[0];
int port = tokens.length == 1 ? protocolConfiguration.getListenPort() : Integer.parseInt(tokens[1]);
return new InetSocketAddress(hostname, port);
}).collect(Collectors.toList());
protocolConfiguration.setServerEndpoints(serverEndpoints);
LOGGER.debug("Internal and external endpoints configured");
// Configure protocol parameters
protocolConfiguration.setParameters(securityPolicy);
// Configure the frame length
if (maxFrameLen != null) {
protocolConfiguration.setFramePartMaxLength(maxFrameLen);
}
// Configure the event executor groups (pools of threads)
if (nbListenThreads != null) {
protocolConfiguration.setNbListenThreads(nbListenThreads);
}
if (nbSessionThreads != null) {
protocolConfiguration.setNbSessionThreads(nbSessionThreads);
}
if (nbParserThreads != null) {
protocolConfiguration.setNbParserThreads(nbParserThreads);
}
// Adapt data identifiers
String[] dataIds = protocol.adaptDataIds(securityPolicy.getDataIds());
securityPolicy.setDataIds(dataIds);
// Initialize the protection module
if (protectionModule != null) {
LOGGER.trace("Initializing the protection module...");
protectionModule.initialize(securityPolicy.getDocument());
LOGGER.debug("Protection module initialized");
}
// Register the protocol service
ProtocolService protocolService;
if (protectionModule != null) {
protocolService = new ProtocolServiceDelegate(protectionModule);
} else {
protocolService = new ProtocolServiceNoop();
}
protocolConfiguration.register(protocolService);
LOGGER.debug("Protocol service registered");
LOGGER.info("The CLARUS proxy is ready to intercept {} protocol and to protect data with {}",
protocolConfiguration.getProtocolName(), protectionModuleName);
}
private void configureProcessingModes(boolean wholedataset,
ProtectionModuleCapabilities protectionModuleCapabilities, ProtocolCapabilities protocolCapabilities,
Configuration protocolConfiguration) {
LOGGER.trace("Configuring processing modes for access to {}...", wholedataset ? "wholedataset" : "records");
Set protectionOps;
if (protectionModuleCapabilities != null) {
protectionOps = protectionModuleCapabilities.getSupportedCRUDOperations(wholedataset);
LOGGER.trace("Protection module supports the following operations for access to {}: {}",
wholedataset ? "wholedataset" : "records", protectionOps);
} else {
protectionOps = Arrays.stream(Operation.values()).collect(Collectors.toSet());
}
Set protocolOps = protocolCapabilities.getSupportedCRUDOperations(wholedataset);
LOGGER.trace("Protocol plugin supports the following operations for access to {}: {}",
wholedataset ? "wholedataset" : "records", protocolOps);
Set operations = EnumSet.copyOf(protocolOps);
operations.retainAll(protectionOps);
LOGGER.debug("Supported operations by both the protection module and the protocol plugin for access to {}: {}",
wholedataset ? "wholedataset" : "records", operations);
for (Operation operation : operations) {
Mode protectionProcessingMode;
if (protectionModuleCapabilities != null) {
protectionProcessingMode = protectionModuleCapabilities.getPreferredProcessingMode(wholedataset,
operation, securityPolicy);
LOGGER.trace(
"Preferred processing mode of the protection module (according to the security policy) for {} operation on {}: {}",
operation, wholedataset ? "wholedataset" : "records", protectionProcessingMode);
} else {
protectionProcessingMode = Mode.AS_IT_IS;
}
Set protocolProcessingModes = protocolCapabilities.getSupportedProcessingModes(wholedataset,
operation);
LOGGER.trace("Supported processing modes by the protocol module for {} operation on {}: {}", operation,
wholedataset ? "wholedataset" : "records", protocolProcessingModes);
Set processingModes = EnumSet.copyOf(protocolProcessingModes);
processingModes.retainAll(Collections.singleton(protectionProcessingMode));
Mode processingMode = processingModes.isEmpty() ? null : processingModes.iterator().next();
protocolConfiguration.setProcessingMode(wholedataset, operation, processingMode);
LOGGER.debug("Processing mode to use for {} operation on {}: {}", operation,
wholedataset ? "wholedataset" : "records", processingMode);
}
}
public void start() {
protocol.start();
}
public void sync() throws InterruptedException, ExecutionException {
protocol.sync();
}
public void waitForServerIsReady() throws InterruptedException {
protocol.waitForServerIsReady();
}
public void stop() {
protocol.stop();
}
public static void main(String[] args) throws Exception {
EmbeddedMongoDB mongoDBServer = null;
try {
String url = System.getProperty("EMBEDDED_MONGO_DB");
if (url != null) {
mongoDBServer = new EmbeddedMongoDB(url);
mongoDBServer.start();
}
Proxy proxy = builder(args);
if (proxy != null) {
proxy.initialize();
proxy.start();
proxy.sync();
}
} finally {
if (mongoDBServer != null) {
mongoDBServer.stop();
}
}
}
public static Proxy builder(String[] args) throws Exception {
if (args.length < 1) {
usage();
return null;
}
String securityPolicyPath = null;
List serverAddresses = new ArrayList<>();
Integer maxFrameLen = null;
Integer nbListenThreads = null;
Integer nbSessionThreads = null;
Integer nbParserThreads = null;
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if ("-sp".equals(arg) || "--security-policy".equals(arg)) {
if (++i < args.length) {
securityPolicyPath = args[i];
}
} else if ("-mf".equals(arg) || "--max-frame-len".equals(arg)) {
if (++i < args.length) {
maxFrameLen = Integer.parseInt(args[i]);
if (maxFrameLen <= 0) {
System.out.println("Maximum frame length must be a positive number");
usage();
return null;
}
}
} else if ("-lt".equals(arg) || "--nb-listen-threads".equals(arg)) {
if (++i < args.length) {
if ("cores".equals(args[i])) {
nbListenThreads = Runtime.getRuntime().availableProcessors();
} else {
nbListenThreads = Integer.parseInt(args[i]);
}
if (nbListenThreads <= 0) {
System.out.println(
"Number of listen threads must be a positive number or the special value 'cores' (number of cores)");
usage();
return null;
}
}
} else if ("-st".equals(arg) || "--nb-session-threads".equals(arg)) {
if (++i < args.length) {
if ("cores".equals(args[i])) {
nbSessionThreads = Runtime.getRuntime().availableProcessors();
} else {
nbSessionThreads = Integer.parseInt(args[i]);
}
if (nbSessionThreads <= 0) {
System.out.println(
"Number of session threads must be a positive number or the special value 'cores' (number of cores)");
usage();
return null;
}
}
} else if ("-pt".equals(arg) || "--nb-parser-threads".equals(arg)) {
if (++i < args.length) {
if ("cores".equals(args[i])) {
nbParserThreads = Runtime.getRuntime().availableProcessors();
} else {
nbParserThreads = Integer.parseInt(args[i]);
}
if (nbParserThreads < 0) {
System.out.println(
"Number of parser threads must be a positive number or 0 or the special value 'cores' (number of cores)");
usage();
return null;
}
}
} else {
serverAddresses.add(arg);
}
}
if (securityPolicyPath == null || serverAddresses.isEmpty()) {
if (securityPolicyPath == null) {
System.out.println("The security policy is mandatory");
}
if (serverAddresses.isEmpty()) {
System.out.println("At least one server address is mandatory");
}
usage();
return null;
}
Proxy proxy = new Proxy(securityPolicyPath, serverAddresses, maxFrameLen, nbListenThreads, nbSessionThreads,
nbParserThreads);
return proxy;
}
private static void usage() {
System.out.println(
"usage: java -Djava.ext.dirs= [PROTOCOL OPTIONS] -jar proxy-1.0.1.jar [OPTION]... [SERVER_ADDRESS]...");
System.out.println("CLARUS extensions:");
System.out.println(
" list the extensions directories that contain protection modules and protocol plugins");
System.out.println("Security policy options:");
System.out.println(" -sp, --security-policy ");
System.out.println(" the security policy to apply");
System.out.println("Resource consumption options:");
System.out.println(" [-mf, --max-frame-len ]");
System.out.println(" maximum frame length to process");
System.out.println(" [-lt, --nb-listen-threads ]");
System.out.println(
" number of listen threads (default: 1). Must be a positive number or the special value 'cores' (number of cores)");
System.out.println(" [-st, --nb-session-threads ]");
System.out.println(
" number of session threads (default: number of cores). Must be a positive number or the special value 'cores' (number of cores)");
System.out.println(" [-pt, --nb-parser-threads ]");
System.out.println(
" number of parser threads (default: 0). Must be a positive number or 0 or the special value 'cores' (number of cores)");
System.out.println("Protocol options:");
System.out.println(" [-D=]");
System.out.println(
" define options specific to the protocol plugin. Muliple options can be specified");
System.out.println("Server addresses:");
System.out.println(
" [:] server host and optional port. Muliple server addresses can be specified");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy