Compare commits

..
3 Commits
52 changed files with 1440 additions and 457 deletions

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-analytics</artifactId>
<!--
@@ -13,10 +13,6 @@ CONF_DIR=${BASE_DIR}/conf
. ${BIN_DIR}/timely-balancer-env.sh
HOST_IP=$(hostname -I | awk '{print $1}')
HOST=$(hostname -s)
HOST_FQDN=$(hostname -f)
for i in $(seq 1 $NUM_PROFILES); do
if [ "$NUM_PROFILES" -eq "1" ]; then
FILENAME=timely-balancer.yml
@@ -26,9 +22,6 @@ for i in $(seq 1 $NUM_PROFILES); do
echo "creating configuration file ${CONF_DIR}/${FILENAME}"
cp ${CONF_DIR}/timely-balancer-template.yml ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST}/${HOST}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_FQDN}/${HOST_FQDN}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_IP}/${HOST_IP}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${ZOOKEEPERS}/${ZOOKEEPERS}/g" ${CONF_DIR}/${FILENAME}
MULTIPLE=$(($i - 1))
TCP_PORT=$(($TCP_PORT_START + $MULTIPLE * $PORT_INCREMENT))
+13 -9
View File
@@ -8,13 +8,17 @@ WEBSOCKET_PORT_START=4244
UDP_PORT_START=4245
PORT_INCREMENT=100
SERVER_CERTIFICATE_FILE=
SERVER_KEY_FILE=
SERVER_KEY_PASSWORD=
SERVER_USE_GENERATED_KEYPAIR=true
CLIENT_KEY_FILE=
CLIENT_KEY_TYPE=pkcs12
CLIENT_KEY_PASSWORD=
TRUST_STORE_PEM=
TRUST_STORE_JKS=
HOST_IP=0.0.0.0
HOST=$(hostname -s)
HOST_FQDN=$(hostname -f)
GENERATE_KEYS=true
TRUST_STORE_TYPE=
TRUST_STORE_FILE=
TRUST_STORE_PASSWORD=
KEY_STORE_TYPE=
KEY_STORE_FILE=
KEY_STORE_PASSWORD=
AUTHORIZATION_URL=
AUTHORIZATION_CERTIFICATE_TYPE=
AUTHORIZATION_CERTIFICATE_FILE=
+4
View File
@@ -10,6 +10,10 @@ fi
THIS_DIR="${THIS_SCRIPT%/*}"
set -a
. ${THIS_DIR}/timely-balancer-env.sh
set +a
if [ -n "$1" ]; then
export PROFILE_NUM=$1
PROFILE_ARG="--spring.profiles.active=${PROFILE_NUM}"
+9
View File
@@ -0,0 +1,9 @@
trust.store.type=${TRUST_STORE_TYPE}
trust.store.file=${TRUST_STORE_FILE}
trust.store.password=${TRUST_STORE_PASSWORD}
key.store.type=${KEY_STORE_TYPE}
key.store.file=${KEY_STORE_FILE}
key.store.password=${KEY_STORE_PASSWORD}
authorization.url=${AUTHORIZATION_URL}
authorization.certificate.type=${AUTHORIZATION_CERTIFICATE_TYPE}
authorization.certificate.file=${AUTHORIZATION_CERTIFICATE_FILE}
+34 -41
View File
@@ -1,51 +1,44 @@
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<beans:bean id="x509PrincipalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor">
<beans:property name="subjectDnRegex" value="CN=(.*?)(?:,|$)"/>
http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:security.properties"/>
<beans:bean id="clientSsl" class="timely.configuration.ClientSsl">
<beans:property name="trustStoreType" value="${trust.store.type}"/>
<beans:property name="trustStoreFile" value="${trust.store.file}"/>
<beans:property name="trustStorePassword" value="${trust.store.password}"/>
<beans:property name="keyStoreType" value="${key.store.type}"/>
<beans:property name="keyStoreFile" value="${key.store.file}"/>
<beans:property name="keyStorePassword" value="${key.store.password}"/>
</beans:bean>
<beans:bean id="timelyUserDetailsService" class="timely.auth.UserDetailsService">
<beans:property name="users">
<util:list>
<beans:bean class="timely.auth.TimelyUser">
<beans:constructor-arg name="subjectDn">
<beans:value>CN=example.com</beans:value>
</beans:constructor-arg>
<beans:constructor-arg name="auths">
<util:list>
<beans:value>D</beans:value>
<beans:value>E</beans:value>
<beans:value>F</beans:value>
</util:list>
</beans:constructor-arg>
<beans:constructor-arg name="roles">
<util:list>
<beans:value>G</beans:value>
<beans:value>H</beans:value>
<beans:value>I</beans:value>
</util:list>
</beans:constructor-arg>
</beans:bean>
</util:list>
</beans:property>
<beans:bean id="authorizationProperties" class="timely.configuration.AuthorizationProperties">
<beans:property name="authorizationUrl" value="${authorization.url}"/>
<beans:property name="publicCertificateType" value="${authorization.certificate.type}"/>
<beans:property name="publicCertificateFile" value="${authorization.certificate.file}"/>
</beans:bean>
<beans:bean id="x509AuthorizationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="timelyUserDetailsService" />
</beans:bean>
<user-service id="usernamePasswordService">
<user name="test" password="test1" authorities="A,B,C" />
</user-service>
<beans:bean id="remoteUserDetailsService" class="timely.auth.RemoteUserDetailsService">
<beans:constructor-arg ref="clientSsl"/>
<beans:constructor-arg ref="authorizationProperties"/>
</beans:bean>
<beans:bean id="x509AuthorizationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="remoteUserDetailsService" />
</beans:bean>
<user-service id="usernamePasswordService">
<user name="test" password="test1" authorities="A,B,C" />
</user-service>
<beans:bean id="noOpPasswordEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder"/>
@@ -53,7 +46,7 @@
<beans:property name="userDetailsService" ref="usernamePasswordService"/>
<beans:property name="passwordEncoder" ref="noOpPasswordEncoder"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<!-- X509 PreAuthenticated authorization provider -->
<authentication-provider ref="x509AuthorizationProvider"/>
+18 -16
View File
@@ -13,23 +13,25 @@ timely-balancer:
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
serverSsl:
certificate-file: ${SERVER_CERTIFICATE_FILE}
key-file: ${SERVER_KEY_FILE}
key-password: ${SERVER_KEY_PASSWORD}
use-generated-keypair: ${SERVER_USE_GENERATED_KEYPAIR}
trust-store-file: ${TRUST_STORE_PEM}
use-openssl: true
#use-ciphers:
key-store-type: ${KEY_STORE_TYPE}
key-store-file: ${KEY_STORE_FILE}
key-store-password: ${KEY_STORE_PASSWORD}
use-generated-keypair: ${GENERATE_KEYS}
ignore-ssl-handshake-errors: true
trust-store-type: ${TRUST_STORE_TYPE}
trust-store-file: ${TRUST_STORE_FILE}
trust-store-password: ${TRUST_STORE_PASSWORD}
clientSsl:
keyFile: ${CLIENT_KEY_FILE}
keyType: ${CLIENT_KEY_TYPE}
keyPassword: ${CLIENT_KEY_PASSWORD}
trustStoreFile: ${TRUST_STORE_JKS}
trustStoreType: jks
trustStorePassword: ${TRUST_STORE_PASSWORD}
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
key-store-type: ${KEY_STORE_TYPE}
key-store-file: ${KEY_STORE_FILE}
key-store-password: ${KEY_STORE_PASSWORD}
trust-store-type: ${TRUST_STORE_TYPE}
trust-store-file: ${TRUST_STORE_FILE}
trust-store-password: ${TRUST_STORE_PASSWORD}
jwtSsl:
key-store-type: ${AUTHORIZATION_CERTIFICATE_TYPE}
key-store-file: ${AUTHORIZATION_CERTIFICATE_FILE}
key-store-password: ${AUTHORIZATION_CERTIFICATE_PASSWORD}
cache:
enabled: false
metric-age-off-hours:
+19 -17
View File
@@ -13,30 +13,32 @@ timely-balancer:
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
serverSsl:
certificate-file:
key-file:
#key-password:
key-store-type:
key-store-file:
key-store-password:
use-generated-keypair: true
ignore-ssl-handshake-errors: true
trust-store-type:
trust-store-file:
use-openssl: true
#use-ciphers:
trust-store-password:
clientSsl:
keyFile:
keyType: pkcs12
#keyPassword:
trustStoreFile:
trustStoreType: jks
#trustStorePassword:
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
key-store-type:
key-store-file:
key-store-password:
trust-store-type:
trust-store-file:
trust-store-password:
jwtSsl:
key-store-type:
key-store-file:
key-store-password:
cache:
enabled: false
metric-age-off-hours:
default: 26
nonCachedMetrics:
server:
ip: 127.0.0.1
ip: 0.0.0.0
tcpPort: 4242
numTcpPools: 1
tcpBufferSize: 100
@@ -77,7 +79,7 @@ timely-balancer:
testOnReturn: false
http:
host: localhost
ip: 127.0.0.1
ip: 0.0.0.0
port: 4243
redirect-path: /secure-me
strict-transport-max-age: 608400
@@ -106,7 +108,7 @@ timely-balancer:
testOnBorrow: false
testOnReturn: false
websocket:
ip: 127.0.0.1
ip: 0.0.0.0
port: 5244
timeout: 60
subscription-lag: 120
+1 -19
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-balancer</artifactId>
<dependencies>
@@ -51,12 +51,6 @@
<dependency>
<groupId>org.apache.accumulo</groupId>
<artifactId>accumulo-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.accumulo</groupId>
@@ -97,12 +91,6 @@
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<exclusions>
<exclusion>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
@@ -119,12 +107,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -5,7 +5,6 @@ import static timely.Server.SERVICE_DISCOVERY_PATH;
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS;
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS_LOCK_PATH;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -52,7 +51,6 @@ import io.netty.handler.ssl.OpenSslServerContext;
import io.netty.handler.ssl.OpenSslServerSessionContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
@@ -71,8 +69,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import timely.auth.AuthCache;
import timely.auth.JWTTokenHandler;
import timely.auth.util.SslHelper;
import timely.balancer.configuration.BalancerConfiguration;
import timely.balancer.configuration.ClientSsl;
import timely.balancer.configuration.SpringBootstrap;
import timely.balancer.connection.http.HttpClientPool;
import timely.balancer.connection.tcp.TcpClientPool;
@@ -86,6 +84,7 @@ import timely.balancer.netty.ws.WsRelayHandler;
import timely.balancer.resolver.BalancedMetricResolver;
import timely.balancer.resolver.MetricResolver;
import timely.client.http.HttpClient;
import timely.configuration.ClientSsl;
import timely.configuration.ServerSsl;
import timely.netty.http.HttpStaticFileServerHandler;
import timely.netty.http.NonSslRedirectHandler;
@@ -323,32 +322,13 @@ public class Balancer {
SelfSignedCertificate ssc = new SelfSignedCertificate("localhost", begin, end);
ssl = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey());
} else {
String cert = sslCfg.getCertificateFile();
String key = sslCfg.getKeyFile();
String keyPass = sslCfg.getKeyPassword();
if (null == cert || null == key) {
if (null == sslCfg.getKeyStoreFile()) {
throw new IllegalArgumentException("Check your SSL properties, something is wrong.");
}
ssl = SslContextBuilder.forServer(new File(cert), new File(key), keyPass);
ssl = SslHelper.getSslContextBuilder(sslCfg);
}
ssl.ciphers(sslCfg.getUseCiphers());
// Can't set to REQUIRE because the CORS pre-flight requests will fail.
ssl.clientAuth(ClientAuth.OPTIONAL);
Boolean useOpenSSL = sslCfg.isUseOpenssl();
if (useOpenSSL) {
ssl.sslProvider(SslProvider.OPENSSL);
} else {
ssl.sslProvider(SslProvider.JDK);
}
String trustStore = sslCfg.getTrustStoreFile();
if (null != trustStore) {
if (!trustStore.isEmpty()) {
ssl.trustManager(new File(trustStore));
}
}
return ssl.build();
}
@@ -356,7 +336,7 @@ public class Balancer {
ClientSsl ssl = config.getSecurity().getClientSsl();
return HttpClient.getSSLContext(ssl.getTrustStoreFile(), ssl.getTrustStoreType(), ssl.getTrustStorePassword(),
ssl.getKeyFile(), ssl.getKeyType(), ssl.getKeyPassword());
ssl.getKeyStoreFile(), ssl.getKeyStoreType(), ssl.getKeyStorePassword());
}
private void ensureZkPaths(CuratorFramework curatorFramework, String[] paths) {
@@ -385,7 +365,7 @@ public class Balancer {
ensureZkPaths(curatorFramework, zkPaths);
AuthCache.configure(balancerConfig.getSecurity());
JWTTokenHandler.init(balancerConfig.getSecurity(), null);
JWTTokenHandler.init(balancerConfig.getSecurity().getJwtSsl(), null);
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
Class<? extends Channel> datagramChannelClass;
@@ -536,12 +516,12 @@ public class Balancer {
ch.pipeline().addLast("queryDecoder", new timely.netty.http.HttpRequestDecoder(
balancerConfig.getSecurity(), balancerConfig.getHttp()));
ch.pipeline().addLast("fileServer", new HttpStaticFileServerHandler().setIgnoreSslHandshakeErrors(
balancerConfig.getSecurity().getServerSsl().isUseGeneratedKeypair()));
balancerConfig.getSecurity().getServerSsl().isIgnoreSslHandshakeErrors()));
ch.pipeline().addLast("login",
new X509LoginRequestHandler(balancerConfig.getSecurity(), balancerConfig.getHttp()));
ch.pipeline().addLast("httpRelay", new HttpRelayHandler(metricResolver, httpClientPool));
ch.pipeline().addLast("error", new TimelyExceptionHandler().setIgnoreSslHandshakeErrors(
balancerConfig.getSecurity().getServerSsl().isUseGeneratedKeypair()));
balancerConfig.getSecurity().getServerSsl().isIgnoreSslHandshakeErrors()));
}
};
}
@@ -3,6 +3,7 @@ package timely.balancer.configuration;
import javax.validation.Valid;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import timely.configuration.ClientSsl;
import timely.configuration.Security;
public class BalancerSecurity extends Security {
@@ -1,77 +0,0 @@
package timely.balancer.configuration;
public class ClientSsl {
private String keyFile;
private String keyType;
private String keyPassword;
private String trustStoreFile;
private String trustStoreType;
private String trustStorePassword;
private boolean useClientCert = true;
private boolean hostVerificationEnabled = true;
public String getKeyFile() {
return keyFile;
}
public void setKeyFile(String keyFile) {
this.keyFile = keyFile;
}
public String getKeyType() {
return keyType;
}
public void setKeyType(String keyType) {
this.keyType = keyType;
}
public String getKeyPassword() {
return keyPassword;
}
public void setKeyPassword(String keyPassword) {
this.keyPassword = keyPassword;
}
public String getTrustStoreFile() {
return trustStoreFile;
}
public void setTrustStoreFile(String trustStoreFile) {
this.trustStoreFile = trustStoreFile;
}
public String getTrustStoreType() {
return trustStoreType;
}
public void setTrustStoreType(String trustStoreType) {
this.trustStoreType = trustStoreType;
}
public String getTrustStorePassword() {
return trustStorePassword;
}
public void setTrustStorePassword(String trustStorePassword) {
this.trustStorePassword = trustStorePassword;
}
public void setUseClientCert(boolean useClientCert) {
this.useClientCert = useClientCert;
}
public boolean isUseClientCert() {
return useClientCert;
}
public void setHostVerificationEnabled(boolean hostVerificationEnabled) {
this.hostVerificationEnabled = hostVerificationEnabled;
}
public boolean isHostVerificationEnabled() {
return hostVerificationEnabled;
}
}
+2 -2
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-client</artifactId>
<properties>
<!-- PEP 440 compliant version gets substituted into src/main/python/template/setup.py -->
<!-- use .dev0 instead of -SNAPSHOT -->
<python.client.version>2.0.0</python.client.version>
<python.client.version>2.0.1</python.client.version>
</properties>
<dependencies>
<dependency>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>collectd-nsq-plugin</artifactId>
<dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>collectd-plugin-parent</artifactId>
<dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>collectd-timely-plugin</artifactId>
<dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-common</artifactId>
<dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-app</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -28,8 +28,8 @@
}
],
"screenshots": [],
"version": "2.0.0",
"updated": "2024-01-17"
"version": "2.0.1",
"updated": "2024-01-26"
},
"dependencies": {
"classnames": "2.2.6",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "timely-datasource",
"version": "2.0.0",
"version": "2.0.1",
"description": "Timely",
"backend": true,
"alerting": true,
+153 -13
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<packaging>pom</packaging>
<name>Timely</name>
<description>A secure and scalable time series database based on Apache Accumulo</description>
@@ -40,6 +40,7 @@
<os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<surefire.forkCount>1C</surefire.forkCount>
<version.accumulo>2.1.2</version.accumulo>
<version.buildnumber-maven>1.4</version.buildnumber-maven>
<version.caffeine>3.1.6</version.caffeine>
@@ -77,19 +78,22 @@
<version.maven-build-helper>3.0.0</version.maven-build-helper>
<version.maven-compiler>3.8.1</version.maven-compiler>
<version.maven-dependency>3.1.1</version.maven-dependency>
<version.maven-failsafe-plugin>3.2.5</version.maven-failsafe-plugin>
<version.maven-jar>3.1.2</version.maven-jar>
<version.maven-pmd>3.12.0</version.maven-pmd>
<version.maven-rpm>2.2.0</version.maven-rpm>
<version.maven-shade>3.2.1</version.maven-shade>
<version.maven-surefire>3.0.0-M3</version.maven-surefire>
<version.maven-surefire-plugin>3.2.5</version.maven-surefire-plugin>
<version.micrometer>1.11.1</version.micrometer>
<version.netty>4.1.45.Final</version.netty>
<version.netty-tcnative>2.0.29.Final</version.netty-tcnative>
<version.os-maven>1.5.0.Final</version.os-maven>
<version.powermock>1.6.4</version.powermock>
<version.reactor-netty>0.8.5.RELEASE</version.reactor-netty>
<version.slf4j>1.7.26</version.slf4j>
<version.spotbugs-maven>4.7.3.5</version.spotbugs-maven>
<version.spring-boot>2.1.3.RELEASE</version.spring-boot>
<version.spring-webflux>5.1.4.RELEASE</version.spring-webflux>
<version.tyrus>1.15</version.tyrus>
</properties>
<dependencyManagement>
@@ -256,6 +260,10 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@@ -317,22 +325,44 @@
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>${version.flink}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>${version.flink}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<version>${version.flink}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${version.hadoop}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
@@ -349,6 +379,10 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
@@ -364,10 +398,22 @@
<artifactId>hadoop-common</artifactId>
<version>${version.hadoop}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
@@ -387,6 +433,10 @@
<artifactId>hadoop-minicluster</artifactId>
<version>${version.hadoop}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
@@ -403,6 +453,10 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
@@ -453,6 +507,22 @@
<artifactId>slf4j-log4j12</artifactId>
<version>${version.slf4j}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>${version.spring-webflux}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${version.spring-boot}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>collectd-plugin-parent</artifactId>
@@ -570,23 +640,60 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${version.maven-compiler}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${version.maven-dependency}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<!-- do not use the following slf4j binders -->
<exclude>ch.qos.reload4j:reload4j</exclude>
<exclude>org.slf4j:slf4j-reload4j</exclude>
<!-- spring boot microservices do not use 1.x versions of log4j -->
<exclude>log4j:log4j</exclude>
<!-- spring boot microservices do not use 1.x versions of junit -->
<exclude>junit:junit</exclude>
</excludes>
<includes>
<!-- some spring boot microservices include test dependencies which use 1.x versions of junit -->
<include>junit:junit:*:*:test</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${version.maven-surefire}</version>
<version>${version.maven-failsafe-plugin}</version>
<configuration>
<argLine>${failsafeArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty_tcnative_linux_x86_64.so -Dzookeeper.sasl.client=false</argLine>
<argLine>${failsafeArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty_tcnative_linux_x86_64.so -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Dfile.encoding=UTF8 -Duser.timezone=GMT -Xmx1024m -Dapple.awt.UIElement=true -Djava.security.krb5.realm= -Djava.security.krb5.kdc= -Dzookeeper.sasl.client=false</argLine>
<includes>
<include>**/*.java</include>
<include>**/*IT.java</include>
</includes>
<groups>timely.test.IntegrationTest</groups>
<redirectTestOutputToFile>false</redirectTestOutputToFile>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
<executions>
<execution>
@@ -627,9 +734,16 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${version.maven-surefire}</version>
<version>${version.maven-surefire-plugin}</version>
<configuration>
<argLine>${sureFireArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty-tcnative_linux_x86_64.so -Dzookeeper.sasl.client=false</argLine>
<reuseForks>false</reuseForks>
<forkCount>${surefire.forkCount}</forkCount>
<threadCount>1</threadCount>
<threadCountClasses>1</threadCountClasses>
<threadCountMethods>0</threadCountMethods>
<threadCountSuites>0</threadCountSuites>
<argLine>${sureFireArgLine} -Djava.library.path=${project.build.directory}/native/META-INF/native/libnetty_tcnative_linux_x86_64.so -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Dfile.encoding=UTF8 -Duser.timezone=GMT -Xmx1024m -Dapple.awt.UIElement=true -Djava.security.krb5.realm= -Djava.security.krb5.kdc= -Dzookeeper.sasl.client=false</argLine>
<runOrder>random</runOrder>
<excludedGroups>timely.test.IntegrationTest</excludedGroups>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
@@ -799,6 +913,35 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<id>enforce-no-snapshots</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireReleaseDeps>
<message>Snapshot dependencies are prohibited on a release build.</message>
<onlyWhenRelease>true</onlyWhenRelease>
</requireReleaseDeps>
<requireJavaVersion>
<version>${java.version}</version>
</requireJavaVersion>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>
<reporting>
@@ -870,7 +1013,7 @@
</property>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.release>${maven.compiler.target}</maven.compiler.release>
</properties>
<build>
<pluginManagement>
@@ -933,10 +1076,7 @@
</build>
</profile>
<profile>
<id>jdk-release-flag</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<id>jdk8</id>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
-7
View File
@@ -13,10 +13,6 @@ CONF_DIR=${BASE_DIR}/conf
. ${BIN_DIR}/timely-env.sh
HOST_IP=$(hostname -I | awk '{print $1}')
HOST=$(hostname -s)
HOST_FQDN=$(hostname -f)
for i in $(seq 1 $NUM_PROFILES); do
if [ "$NUM_PROFILES" -eq "1" ]; then
FILENAME=timely.yml
@@ -26,9 +22,6 @@ for i in $(seq 1 $NUM_PROFILES); do
echo "creating configuration file ${CONF_DIR}/${FILENAME}"
cp ${CONF_DIR}/timely-template.yml ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST}/${HOST}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_FQDN}/${HOST_FQDN}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_IP}/${HOST_IP}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${ZOOKEEPERS}/${ZOOKEEPERS}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${AGE_OFF_DAYS}/${AGE_OFF_DAYS}/g" ${CONF_DIR}/${FILENAME}
MULTIPLE=$(($i - 1))
+16 -1
View File
@@ -9,4 +9,19 @@ UDP_PORT_START=4245
PORT_INCREMENT=100
AGE_OFF_DAYS=7
ACCUMULO_USER=root
ACCUMULO_PASSWORD=secret
ACCUMULO_PASSWORD=secret
HOST_IP=0.0.0.0
HOST=$(hostname -s)
HOST_FQDN=$(hostname -f)
GENERATE_KEYS=true
TRUST_STORE_TYPE=
TRUST_STORE_FILE=
TRUST_STORE_PASSWORD=
KEY_STORE_TYPE=
KEY_STORE_FILE=
KEY_STORE_PASSWORD=
AUTHORIZATION_URL=
AUTHORIZATION_CERTIFICATE_TYPE=
AUTHORIZATION_CERTIFICATE_FILE=
+6 -4
View File
@@ -10,6 +10,10 @@ fi
THIS_DIR="${THIS_SCRIPT%/*}"
set -a
. ${THIS_DIR}/timely-env.sh
set +a
if [ -n "$1" ]; then
export PROFILE_NUM=$1
PROFILE_ARG="--spring.profiles.active=${PROFILE_NUM}"
@@ -53,11 +57,9 @@ if [ "$PID" == "" ]; then
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
JVM_ARGS="${JVM_ARGS} -Xmx4G -Xms4G -XX:NewSize=1G -XX:MaxNewSize=1G -XX:+UnlockDiagnosticVMOptions"
JVM_ARGS="${JVM_ARGS} -XX:+UseConcMarkSweepGC -XX:+CMSScavengeBeforeRemark -XX:+ScavengeBeforeFullGC -XX:ReservedCodeCacheSize=384M -XX:+UseCodeCacheFlushing -XX:+UseParNewGC"
JVM_ARGS="${JVM_ARGS} -XX:SurvivorRatio=8 -XX:ParallelGCThreads=16 -XX:ConcGCThreads=8 -XX:+UseCondCardMark -XX:ParGCCardsPerStrideChunk=32768"
JVM_ARGS="${JVM_ARGS} -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSInitiatingOccupancyOnly"
JVM_ARGS="${JVM_ARGS} -Xmx4G -Xms4G -XX:NewSize=1G -XX:MaxNewSize=1G"
JVM_ARGS="${JVM_ARGS} -XX:+UseCompressedOops -XX:+UseNUMA -Djava.net.preferIPv4Stack=true"
JVM_ARGS="${JVM_ARGS} -XX:+UseG1GC -XX:MaxGCPauseMillis=4000 -XX:ParallelGCThreads=20 -XX:+UseStringDeduplication"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely ${PROFILE_ARG}"
nohup $JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely ${PROFILE_ARG} >> ${LOG_DIR}/timely-server${PROFILE_NUM}-startup.log 2>&1 &
Executable → Regular
View File
File mode changed.
+9
View File
@@ -0,0 +1,9 @@
trust.store.type=${TRUST_STORE_TYPE}
trust.store.file=${TRUST_STORE_FILE}
trust.store.password=${TRUST_STORE_PASSWORD}
key.store.type=${KEY_STORE_TYPE}
key.store.file=${KEY_STORE_FILE}
key.store.password=${KEY_STORE_PASSWORD}
authorization.url=${AUTHORIZATION_URL}
authorization.certificate.type=${AUTHORIZATION_CERTIFICATE_TYPE}
authorization.certificate.file=${AUTHORIZATION_CERTIFICATE_FILE}
+26 -33
View File
@@ -1,46 +1,39 @@
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans:bean id="x509PrincipalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor">
<beans:property name="subjectDnRegex" value="CN=(.*?)(?:,|$)"/>
</beans:bean>
<context:property-placeholder location="classpath:security.properties"/>
<beans:bean id="timelyUserDetailsService" class="timely.auth.UserDetailsService">
<beans:property name="users">
<util:list>
<beans:bean class="timely.auth.TimelyUser">
<beans:constructor-arg name="subjectDn">
<beans:value>CN=example.com</beans:value>
</beans:constructor-arg>
<beans:constructor-arg name="auths">
<util:list>
<beans:value>D</beans:value>
<beans:value>E</beans:value>
<beans:value>F</beans:value>
</util:list>
</beans:constructor-arg>
<beans:constructor-arg name="roles">
<util:list>
<beans:value>G</beans:value>
<beans:value>H</beans:value>
<beans:value>I</beans:value>
</util:list>
</beans:constructor-arg>
</beans:bean>
</util:list>
</beans:property>
<beans:bean id="clientSsl" class="timely.configuration.ClientSsl">
<beans:property name="trustStoreType" value="${trust.store.type}"/>
<beans:property name="trustStoreFile" value="${trust.store.file}"/>
<beans:property name="trustStorePassword" value="${trust.store.password}"/>
<beans:property name="keyStoreType" value="${key.store.type}"/>
<beans:property name="keyStoreFile" value="${key.store.file}"/>
<beans:property name="keyStorePassword" value="${key.store.password}"/>
</beans:bean>
<beans:bean id="authorizationProperties" class="timely.configuration.AuthorizationProperties">
<beans:property name="authorizationUrl" value="${authorization.url}"/>
<beans:property name="publicCertificateType" value="${authorization.certificate.type}"/>
<beans:property name="publicCertificateFile" value="${authorization.certificate.file}"/>
</beans:bean>
<beans:bean id="remoteUserDetailsService" class="timely.auth.RemoteUserDetailsService">
<beans:constructor-arg ref="clientSsl"/>
<beans:constructor-arg ref="authorizationProperties"/>
</beans:bean>
<beans:bean id="x509AuthorizationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="timelyUserDetailsService" />
<beans:property name="preAuthenticatedUserDetailsService" ref="remoteUserDetailsService" />
</beans:bean>
<user-service id="usernamePasswordService">
+11 -5
View File
@@ -24,13 +24,19 @@ timely:
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
server-ssl:
certificate-file:
key-file:
key-password: timely
serverSsl:
key-store-type:
key-store-file:
key-store-password:
use-generated-keypair: true
ignore-ssl-handshake-errors: true
trust-store-type:
trust-store-file:
use-openssl: false
trust-store-password:
jwtSsl:
key-store-type:
key-store-file:
key-store-password:
server:
ip: 0.0.0.0
tcp-port: 54321
+13 -11
View File
@@ -28,17 +28,19 @@ timely:
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
server-ssl:
certificate-file:
key-file:
key-password:
use-generated-keypair: true
trust-store-file:
use-openssl: true
#use-ciphers:
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
serverSsl:
key-store-type: ${KEY_STORE_TYPE}
key-store-file: ${KEY_STORE_FILE}
key-store-password: ${KEY_STORE_PASSWORD}
use-generated-keypair: ${GENERATE_KEYS}
ignore-ssl-handshake-errors: true
trust-store-type: ${TRUST_STORE_TYPE}
trust-store-file: ${TRUST_STORE_FILE}
trust-store-password: ${TRUST_STORE_PASSWORD}
jwtSsl:
key-store-type: ${AUTHORIZATION_CERTIFICATE_TYPE}
key-store-file: ${AUTHORIZATION_CERTIFICATE_FILE}
key-store-password: ${AUTHORIZATION_CERTIFICATE_PASSWORD}
server:
ip: ${HOST_IP}
tcp-port: ${TCP_PORT}
+11 -9
View File
@@ -27,17 +27,19 @@ timely:
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
server-ssl:
certificate-file:
key-file:
key-password:
serverSsl:
key-store-type:
key-store-file:
key-store-password:
use-generated-keypair: true
ignore-ssl-handshake-errors: true
trust-store-type:
trust-store-file:
use-openssl: true
#use-ciphers:
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
trust-store-password:
jwtSsl:
key-store-type:
key-store-file:
key-store-password:
server:
ip: 0.0.0.0
tcp-port: 4242
+17 -24
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
</parent>
<artifactId>timely-server</artifactId>
<dependencies>
@@ -68,6 +68,10 @@
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
</dependency>
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
@@ -75,12 +79,6 @@
<dependency>
<groupId>org.apache.accumulo</groupId>
<artifactId>accumulo-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.accumulo</groupId>
@@ -117,12 +115,6 @@
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<exclusions>
<exclusion>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
@@ -132,15 +124,13 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -182,11 +172,6 @@
<artifactId>log4j-core</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
@@ -303,6 +288,14 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
<extensions>
<!-- Use os-maven-plugin to initialize the "os.detected" properties -->
+6 -26
View File
@@ -4,7 +4,6 @@ import static org.apache.accumulo.core.conf.ConfigurationTypeHelper.getTimeInMil
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS;
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS_LOCK_PATH;
import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
@@ -56,7 +55,6 @@ import io.netty.handler.ssl.OpenSslServerContext;
import io.netty.handler.ssl.OpenSslServerSessionContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
@@ -84,6 +82,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import timely.auth.AuthCache;
import timely.auth.JWTTokenHandler;
import timely.auth.VisibilityCache;
import timely.auth.util.SslHelper;
import timely.configuration.Accumulo;
import timely.configuration.Configuration;
import timely.configuration.Cors;
@@ -513,7 +512,7 @@ public class Server {
MetaCacheFactory.getCache(config);
AuthCache.configure(config.getSecurity());
VisibilityCache.init(config);
JWTTokenHandler.init(config.getSecurity(), accumuloClient);
JWTTokenHandler.init(config.getSecurity().getJwtSsl(), accumuloClient);
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
Class<? extends Channel> datagramChannelClass;
@@ -622,32 +621,13 @@ public class Server {
SelfSignedCertificate ssc = new SelfSignedCertificate("localhost", begin, end);
ssl = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey());
} else {
String cert = sslCfg.getCertificateFile();
String key = sslCfg.getKeyFile();
String keyPass = sslCfg.getKeyPassword();
if (null == cert || null == key) {
if (null == sslCfg.getKeyStoreFile()) {
throw new IllegalArgumentException("Check your SSL properties, something is wrong.");
}
ssl = SslContextBuilder.forServer(new File(cert), new File(key), keyPass);
ssl = SslHelper.getSslContextBuilder(sslCfg);
}
ssl.ciphers(sslCfg.getUseCiphers());
// Can't set to REQUIRE because the CORS pre-flight requests will fail.
ssl.clientAuth(ClientAuth.OPTIONAL);
Boolean useOpenSSL = sslCfg.isUseOpenssl();
if (useOpenSSL) {
ssl.sslProvider(SslProvider.OPENSSL);
} else {
ssl.sslProvider(SslProvider.JDK);
}
String trustStore = sslCfg.getTrustStoreFile();
if (null != trustStore) {
if (!trustStore.isEmpty()) {
ssl.trustManager(new File(trustStore));
}
}
return ssl.build();
}
@@ -686,7 +666,7 @@ public class Server {
ch.pipeline().addLast("queryDecoder",
new timely.netty.http.HttpRequestDecoder(config.getSecurity(), config.getHttp()));
ch.pipeline().addLast("fileServer", new HttpStaticFileServerHandler()
.setIgnoreSslHandshakeErrors(config.getSecurity().getServerSsl().isUseGeneratedKeypair()));
.setIgnoreSslHandshakeErrors(config.getSecurity().getServerSsl().isIgnoreSslHandshakeErrors()));
ch.pipeline().addLast("strict", new StrictTransportHandler(config));
ch.pipeline().addLast("login", new X509LoginRequestHandler(config.getSecurity(), config.getHttp()));
ch.pipeline().addLast("doLogin",
@@ -700,7 +680,7 @@ public class Server {
ch.pipeline().addLast("cache", new HttpCacheRequestHandler(dataStoreCache));
ch.pipeline().addLast("put", new HttpMetricPutHandler(dataStore));
ch.pipeline().addLast("error", new TimelyExceptionHandler()
.setIgnoreSslHandshakeErrors(config.getSecurity().getServerSsl().isUseGeneratedKeypair()));
.setIgnoreSslHandshakeErrors(config.getSecurity().getServerSsl().isIgnoreSslHandshakeErrors()));
}
};
@@ -27,8 +27,8 @@ import timely.netty.http.auth.TimelyUserDetails;
public class AuthenticationService {
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationService.class);
private static ApplicationContext springContext = null;
private static AuthenticationManager authManager = null;
private static ApplicationContext springContext;
private static AuthenticationManager authManager;
private static ConcurrentHashMap<String, Object> fetchingEntity = new ConcurrentHashMap<>();
private static ConcurrentHashMap<String, Object> fetchingPrincipal = new ConcurrentHashMap<>();
private static Collection<String> requiredRoles;
@@ -161,9 +161,8 @@ public class AuthenticationService {
}
verifiedPrincipal = new TimelyPrincipal(authenticatedTimelyUsers);
AuthCache.put(verifiedPrincipal.getName(), verifiedPrincipal);
LOG.debug("Authenticated user {} for request {} with authorizations {}",
verifiedPrincipal.getName(), request.toString(),
verifiedPrincipal.getAuthorizationsString());
LOG.debug("Authenticated user {} with authorizations {}",
verifiedPrincipal.getName(), verifiedPrincipal.getAuthorizationsString());
} else {
LOG.trace("Verified principal {} in AuthCache on 2nd attempt", entity);
}
@@ -7,13 +7,13 @@ import java.util.List;
import java.util.Map;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import timely.netty.http.auth.TimelyUserDetails;
public class UserDetailsService implements
org.springframework.security.core.userdetails.AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
public class FileUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
private HashMap<String, TimelyUser> users;
@@ -7,19 +7,24 @@ import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import io.jsonwebtoken.*;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import timely.configuration.Security;
import timely.configuration.JwtSsl;
/**
* Converts between a String encoded JSON Web Token and a collection of
@@ -32,23 +37,23 @@ public class JWTTokenHandler {
private static ObjectMapper objectMapper;
private static Collection<String> accumuloAuths = new TreeSet<>();
public static void init(Security security, AccumuloClient accumuloClient) {
if (StringUtils.isNotBlank(security.getJwtCheckKeyStore())) {
public static void init(JwtSsl ssl, AccumuloClient accumuloClient) {
if (StringUtils.isNotBlank(ssl.getKeyStoreFile())) {
try {
String type = security.getJwtCheckKeyType();
String type = ssl.getKeyStoreType();
if (type != null && type.equals("X.509")) {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
InputStream is = ResourceUtils.getURL(security.getJwtCheckKeyStore()).openStream();
InputStream is = ResourceUtils.getURL(ssl.getKeyStoreFile()).openStream();
X509Certificate certificate = (X509Certificate) factory.generateCertificate(is);
JWTTokenHandler.signatureCheckKey = certificate.getPublicKey();
} else {
KeyStore keyStore = KeyStore.getInstance(type == null ? "JKS" : type);
char[] keyPassword = security.getJwtCheckKeyPassword() == null ? null
: security.getJwtCheckKeyPassword().toCharArray();
keyStore.load(ResourceUtils.getURL(security.getJwtCheckKeyStore()).openStream(), keyPassword);
char[] keyPassword = ssl.getKeyStorePassword() == null ? null
: ssl.getKeyStorePassword().toCharArray();
keyStore.load(ResourceUtils.getURL(ssl.getKeyStoreFile()).openStream(), keyPassword);
String alias = keyStore.aliases().nextElement();
Certificate cert = keyStore.getCertificate(alias);
JWTTokenHandler.signatureCheckKey = cert.getPublicKey();
Certificate certificate = keyStore.getCertificate(alias);
JWTTokenHandler.signatureCheckKey = certificate.getPublicKey();
}
} catch (Exception e) {
throw new IllegalStateException("Invalid SSL configuration.", e);
@@ -0,0 +1,152 @@
package timely.auth;
import static timely.auth.AuthenticationService.PRINCIPALS_CLAIM;
import java.util.ArrayList;
import java.util.Collection;
import io.netty.handler.ssl.SslContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import timely.auth.util.SslHelper;
import timely.configuration.AuthorizationProperties;
import timely.configuration.ClientSsl;
import timely.netty.http.auth.TimelyAuthenticationToken;
import timely.netty.http.auth.TimelyUserDetails;
public class RemoteUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
static private final Logger log = LoggerFactory.getLogger(RemoteUserDetailsService.class);
private WebClient webClient;
private ClientSsl clientSsl;
private AuthorizationProperties authorizationProperties;
public RemoteUserDetailsService() {
}
public RemoteUserDetailsService(ClientSsl clientSsl, AuthorizationProperties authorizationProperties)
throws Exception {
this.clientSsl = clientSsl;
this.authorizationProperties = authorizationProperties;
initialize();
}
public void initialize() throws Exception {
WebClient.Builder webClientBuilder = WebClient.builder();
SslContext sslContext = SslHelper.getSslContext(clientSsl);
HttpClient httpClient = HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient);
this.webClient = webClientBuilder.clientConnector(httpConnector)
.baseUrl(authorizationProperties.getAuthorizationUrl()).build();
}
public void setClientSsl(ClientSsl clientSsl) {
this.clientSsl = clientSsl;
}
public void setAuthorizationProperties(AuthorizationProperties authorizationProperties) {
this.authorizationProperties = authorizationProperties;
}
@Override
public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws UsernameNotFoundException {
TimelyUserDetails userDetails = null;
if (!(token instanceof TimelyAuthenticationToken)) {
log.error("Unexpected type for token: {}", token.getClass().getName());
}
TimelyAuthenticationToken timelyToken = (TimelyAuthenticationToken) token;
TimelyPrincipal principal = timelyToken.getTimelyPrincipal();
String subjectDN = principal.getPrimaryUser().getDn().subjectDN();
String issuerDN = principal.getPrimaryUser().getDn().issuerDN();
try {
log.trace("Authenticating {} via the authorization microservice", subjectDN);
// @formatter:off
String jwt = webClient.get()
.header(TimelyAuthenticationToken.PROXIED_ENTITIES_HEADER, subjectDN)
.header(TimelyAuthenticationToken.PROXIED_ISSUERS_HEADER, issuerDN)
.retrieve()
.bodyToMono(String.class)
.block();
// @formatter:on
log.trace("Authenticated {} via the authorization microservice with {} result", subjectDN,
jwt == null ? "null" : "non-null");
if (jwt != null) {
Collection<TimelyUser> timelyUsers = JWTTokenHandler.createUsersFromToken(jwt, PRINCIPALS_CLAIM);
if (timelyUsers.iterator().hasNext()) {
userDetails = getTimelyUserDetails(timelyUsers.iterator().next());
}
}
if (userDetails == null) {
throw new UsernameNotFoundException("No entities found for " + subjectDN);
}
} catch (Exception e) {
log.error("Failed performing lookup of {}: {}", subjectDN, e);
throw new UsernameNotFoundException(e.getMessage(), e);
}
return userDetails;
}
private TimelyUserDetails getTimelyUserDetails(TimelyUser timelyUser) {
return new TimelyUserDetails() {
private static final long serialVersionUID = 1L;
@Override
public Collection<SimpleGrantedAuthority> getAuthorities() {
final Collection<SimpleGrantedAuthority> auths = new ArrayList<>();
timelyUser.getAuths().forEach(a -> {
auths.add(new SimpleGrantedAuthority(a));
});
return auths;
}
@Override
public Collection<String> getRoles() {
final Collection<String> roles = new ArrayList<>();
roles.addAll(timelyUser.getRoles());
return roles;
}
@Override
public String getPassword() {
return "";
}
@Override
public String getUsername() {
return timelyUser.getName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
};
}
}
@@ -0,0 +1,504 @@
package timely.auth.util;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManagerFactorySpi;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
import com.google.common.base.Preconditions;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.util.concurrent.FastThreadLocal;
import org.springframework.util.ResourceUtils;
import timely.configuration.ServerSsl;
import timely.configuration.Ssl;
public class SslHelper {
public static SslContext getSslContext(Ssl ssl) throws Exception {
return getSslContextBuilder(ssl).build();
}
public static SslContextBuilder getSslContextBuilder(Ssl ssl) throws Exception {
KeyManagerFactory keyManagerFactory = getKeyManagerFactory(ssl);
SslContextBuilder builder = ssl instanceof ServerSsl ? SslContextBuilder.forServer(keyManagerFactory)
: SslContextBuilder.forClient().keyManager(keyManagerFactory);
boolean useOpenSSL = ssl.isUseOpenssl();
if (useOpenSSL) {
builder.sslProvider(SslProvider.OPENSSL);
} else {
builder.sslProvider(SslProvider.JDK);
}
if (ssl.getTrustStoreFile() != null) {
builder.trustManager(getTrustManagerFactory(ssl));
}
if (ssl.getCiphers() != null)
builder.ciphers(Arrays.asList(ssl.getCiphers()));
if (ssl.getEnabledProtocols() != null)
builder.protocols(ssl.getEnabledProtocols());
return builder;
}
public static KeyManager[] getKeyManagers(Ssl ssl) {
return getKeyManagerFactory(ssl).getKeyManagers();
}
public static KeyManagerFactory getKeyManagerFactory(Ssl ssl) {
try {
KeyStore keyStore = getKeyStore(ssl);
// Get key manager to provide client credentials.
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char[] keyStorePassword = ssl.getKeyStorePassword() == null ? null
: ssl.getKeyStorePassword().toCharArray();
keyManagerFactory.init(keyStore, keyStorePassword);
if (ssl.getKeyAlias() != null)
return new KeyAliasKeyManagerFactory(keyManagerFactory, ssl.getKeyAlias());
else
return keyManagerFactory;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public static KeyStore getKeyStore(Ssl ssl)
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
String keyStoreType = ssl.getKeyStoreType();
if (keyStoreType == null) {
keyStoreType = "PKCS12";
}
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
URL url = ResourceUtils.getURL(ssl.getKeyStoreFile());
char[] keyStorePassword = ssl.getKeyStorePassword() == null ? null : ssl.getKeyStorePassword().toCharArray();
keyStore.load(url.openStream(), keyStorePassword);
return keyStore;
}
public static TrustManager[] getTrustManagers(Ssl ssl) {
TrustManagerFactory tmf = getTrustManagerFactory(ssl);
return tmf.getTrustManagers();
}
public static TrustManagerFactory getTrustManagerFactory(Ssl ssl) {
try {
KeyStore trustStore = getTrustStore(ssl);
KeyStore keyStore = getKeyStore(ssl);
X509Certificate trustedCertificate = getTrustedCertificate(ssl.getKeyAlias(), keyStore);
TrustManagerFactory trustManagerFactory = new TimelyTrustMangerFactory(
TrustManagerFactory.getDefaultAlgorithm(), trustedCertificate);
trustManagerFactory.init(trustStore);
return trustManagerFactory;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public static KeyStore getTrustStore(Ssl ssl)
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
String trustStoreType = ssl.getTrustStoreType();
if (trustStoreType == null) {
trustStoreType = "JKS";
}
String trustStoreURL = ssl.getTrustStoreFile();
if (trustStoreURL == null) {
return null;
}
KeyStore trustStore = KeyStore.getInstance(trustStoreType);
URL url = ResourceUtils.getURL(trustStoreURL);
char[] trustStorePassword = ssl.getTrustStorePassword() == null ? null
: ssl.getTrustStorePassword().toCharArray();
trustStore.load(url.openStream(), trustStorePassword);
return trustStore;
}
public static X509Certificate getTrustedCertificate(String alias, KeyStore keyStore) throws KeyStoreException {
Certificate trustCandidate = null;
X509Certificate trustedCertificate = null;
if (alias != null) {
trustCandidate = keyStore.getCertificate(alias);
} else {
Enumeration<String> aliases = keyStore.aliases();
if (aliases.hasMoreElements()) {
trustCandidate = keyStore.getCertificate(aliases.nextElement());
}
}
if (trustCandidate instanceof X509Certificate) {
trustedCertificate = (X509Certificate) trustCandidate;
}
return trustedCertificate;
}
/**
* A custom {@link TrustManagerFactory} that wraps any returned
* {@link TrustManager}s in order to apply custom behavior for trusting a remote
* server.
*/
private static class TimelyTrustMangerFactory extends TrustManagerFactory {
private static final Provider PROVIDER = new Provider("", 0.0, "") {
private static final long serialVersionUID = -2680540247105807895L;
};
private static final FastThreadLocal<TimelyTrustManagerSpi> CURRENT_SPI = new FastThreadLocal<>() {
@Override
protected TimelyTrustManagerSpi initialValue() {
return new TimelyTrustManagerSpi();
}
};
public TimelyTrustMangerFactory(String algorithm, X509Certificate trustedCertificate)
throws NoSuchAlgorithmException {
super(CURRENT_SPI.get(), PROVIDER, algorithm);
CURRENT_SPI.get().init(TrustManagerFactory.getInstance(algorithm), trustedCertificate);
CURRENT_SPI.remove();
Preconditions.checkNotNull(algorithm);
}
}
/**
* The {@link TrustManagerFactorySpi} that is used by
* {@link TimelyTrustMangerFactory} in order to wrap any returned
* {@link TrustManager}s with a {@link TimelyTrustManager}.
*/
private static class TimelyTrustManagerSpi extends TrustManagerFactorySpi {
private TrustManagerFactory delegate;
private X509Certificate trustedCertificate;
private volatile TrustManager[] trustManagers;
public void init(TrustManagerFactory delegate, X509Certificate trustedCertificate) {
this.delegate = delegate;
this.trustedCertificate = trustedCertificate;
}
@Override
protected void engineInit(KeyStore keyStore) throws KeyStoreException {
delegate.init(keyStore);
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
throws InvalidAlgorithmParameterException {
delegate.init(managerFactoryParameters);
}
@Override
protected TrustManager[] engineGetTrustManagers() {
TrustManager[] trustManagers = this.trustManagers;
if (trustManagers == null) {
trustManagers = delegate.getTrustManagers();
for (int i = 0; i < trustManagers.length; i++) {
final TrustManager tm = trustManagers[i];
if (tm instanceof X509TrustManager) {
trustManagers[i] = new TimelyTrustManager((X509TrustManager) tm, trustedCertificate);
} else {
trustManagers[i] = tm;
}
}
this.trustManagers = trustManagers;
}
return trustManagers.clone();
}
}
/**
* An extension of {@link X509ExtendedTrustManager} that applies custom trust
* behavior for use with microservices. It is expected that these services will
* run on a cluster where DNS might be used for service discovery. However, the
* server certificate used by the microservices will not have the DNS names as
* Subject Alternative Name values, so normal trust for the certificate would
* fail. This trust manager trusts the remote server regardless of the host name
* used to access it, so long as the presented certificate is the one we expect.
* Otherwise, it falls back to the normal trust behavior.
*/
private static class TimelyTrustManager extends X509ExtendedTrustManager {
private X509Certificate trustedCertificate;
private X509TrustManager delegate;
private X509ExtendedTrustManager extendedDelegate;
public TimelyTrustManager(X509TrustManager delegate, X509Certificate trustedCertificate) {
this.trustedCertificate = trustedCertificate;
this.delegate = delegate;
if (delegate instanceof X509ExtendedTrustManager) {
extendedDelegate = (X509ExtendedTrustManager) delegate;
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return delegate.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
delegate.checkClientTrusted(x509Certificates, s);
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
delegate.checkServerTrusted(x509Certificates, s);
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
throws CertificateException {
Preconditions.checkNotNull(extendedDelegate, "Not wrapping an X509ExtendedTrustManager");
boolean certChainTrusted = certChainTrusted(x509Certificates);
if ((socket instanceof SSLSocket) && socket.isConnected() && certChainTrusted) {
SSLSocket sslSocket = (SSLSocket) socket;
SSLParameters origParameters = sslSocket.getSSLParameters();
String curIdentityAlgorithm = origParameters.getEndpointIdentificationAlgorithm();
try {
// Setting the identification algorithm to empty will prevent the hostname
// verification.
SSLParameters overrideParameters = sslSocket.getSSLParameters();
overrideParameters.setEndpointIdentificationAlgorithm("");
sslSocket.setSSLParameters(overrideParameters);
extendedDelegate.checkClientTrusted(x509Certificates, s, socket);
} finally {
origParameters.setEndpointIdentificationAlgorithm(curIdentityAlgorithm);
sslSocket.setSSLParameters(origParameters);
}
} else {
extendedDelegate.checkClientTrusted(x509Certificates, s, socket);
}
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket)
throws CertificateException {
Preconditions.checkNotNull(extendedDelegate, "Not wrapping an X509ExtendedTrustManager");
boolean certChainTrusted = certChainTrusted(x509Certificates);
if ((socket instanceof SSLSocket) && socket.isConnected() && certChainTrusted) {
SSLSocket sslSocket = (SSLSocket) socket;
SSLParameters origParameters = sslSocket.getSSLParameters();
String curIdentityAlgorithm = origParameters.getEndpointIdentificationAlgorithm();
try {
// Setting the identification algorithm to empty will prevent the hostname
// verification.
SSLParameters overrideParameters = sslSocket.getSSLParameters();
overrideParameters.setEndpointIdentificationAlgorithm("");
sslSocket.setSSLParameters(overrideParameters);
extendedDelegate.checkServerTrusted(x509Certificates, s, socket);
} finally {
origParameters.setEndpointIdentificationAlgorithm(curIdentityAlgorithm);
sslSocket.setSSLParameters(origParameters);
}
} else {
extendedDelegate.checkServerTrusted(x509Certificates, s, socket);
}
}
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine)
throws CertificateException {
Preconditions.checkNotNull(extendedDelegate, "Not wrapping an X509ExtendedTrustManager");
boolean certChainTrusted = certChainTrusted(x509Certificates);
SSLParameters origParameters = sslEngine.getSSLParameters();
String curIdentityAlgorithm = origParameters.getEndpointIdentificationAlgorithm();
try {
// Setting the identification algorithm to empty will prevent the hostname
// verification.
if (certChainTrusted) {
SSLParameters overrideParameters = sslEngine.getSSLParameters();
overrideParameters.setEndpointIdentificationAlgorithm("");
sslEngine.setSSLParameters(overrideParameters);
}
extendedDelegate.checkClientTrusted(x509Certificates, s, sslEngine);
} finally {
origParameters.setEndpointIdentificationAlgorithm(curIdentityAlgorithm);
sslEngine.setSSLParameters(origParameters);
}
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine)
throws CertificateException {
Preconditions.checkNotNull(extendedDelegate, "Not wrapping an X509ExtendedTrustManager");
boolean certChainTrusted = certChainTrusted(x509Certificates);
SSLParameters origParameters = sslEngine.getSSLParameters();
String curIdentityAlgorithm = origParameters.getEndpointIdentificationAlgorithm();
try {
// Setting the identification algorithm to empty will prevent the hostname
// verification.
if (certChainTrusted) {
SSLParameters overrideParameters = sslEngine.getSSLParameters();
overrideParameters.setEndpointIdentificationAlgorithm("");
sslEngine.setSSLParameters(overrideParameters);
}
extendedDelegate.checkServerTrusted(x509Certificates, s, sslEngine);
} finally {
origParameters.setEndpointIdentificationAlgorithm(curIdentityAlgorithm);
sslEngine.setSSLParameters(origParameters);
}
}
private boolean certChainTrusted(X509Certificate[] x509Certificates) {
// If there was no peer certificate available or none matched the trusted
// certificate, then return
// immediately so that we use the default trust verification instead of our
// custom verification.
boolean peerCertIsTrusted = false;
if (x509Certificates != null && trustedCertificate != null) {
for (X509Certificate cert : x509Certificates) {
if (cert.getSubjectDN().equals(trustedCertificate.getSubjectDN())
&& cert.getIssuerDN().equals(trustedCertificate.getIssuerDN())) {
peerCertIsTrusted = true;
break;
}
}
}
return peerCertIsTrusted;
}
}
private static class KeyAliasKeyManagerFactory extends KeyManagerFactory {
private static final Provider PROVIDER = new Provider("", 0.0, "") {
private static final long serialVersionUID = -2680540247105807895L;
};
private static final FastThreadLocal<KeyAliasKeyManagerSpi> CURRENT_SPI = new FastThreadLocal<KeyAliasKeyManagerSpi>() {
@Override
protected KeyAliasKeyManagerSpi initialValue() {
return new KeyAliasKeyManagerSpi();
}
};
public KeyAliasKeyManagerFactory(KeyManagerFactory delegate, String alias) {
super(CURRENT_SPI.get(), PROVIDER, delegate.getAlgorithm());
CURRENT_SPI.get().init(delegate, alias);
CURRENT_SPI.remove();
}
}
private static class KeyAliasKeyManagerSpi extends KeyManagerFactorySpi {
private KeyManagerFactory delegate;
private String alias;
private volatile KeyManager[] keyManagers;
public void init(KeyManagerFactory delegate, String alias) {
this.delegate = delegate;
this.alias = alias;
}
@Override
protected void engineInit(KeyStore keyStore, char[] chars)
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
delegate.init(keyStore, chars);
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
throws InvalidAlgorithmParameterException {
delegate.init(managerFactoryParameters);
}
@Override
protected KeyManager[] engineGetKeyManagers() {
KeyManager[] keyManagers = this.keyManagers;
if (keyManagers == null) {
keyManagers = delegate.getKeyManagers();
for (int i = 0; i < keyManagers.length; i++) {
final KeyManager km = keyManagers[i];
if (km instanceof X509ExtendedKeyManager) {
keyManagers[i] = new KeyAliasKeyManager((X509ExtendedKeyManager) km, alias);
} else {
keyManagers[i] = km;
}
}
this.keyManagers = keyManagers;
}
return keyManagers.clone();
}
}
private static class KeyAliasKeyManager extends X509ExtendedKeyManager {
private final X509ExtendedKeyManager delegate;
private final String alias;
public KeyAliasKeyManager(X509ExtendedKeyManager delegate, String alias) {
this.delegate = delegate;
this.alias = alias;
}
@Override
public String chooseEngineClientAlias(String[] strings, Principal[] principals, SSLEngine sslEngine) {
return delegate.chooseEngineClientAlias(strings, principals, sslEngine);
}
@Override
public String chooseEngineServerAlias(String s, Principal[] principals, SSLEngine sslEngine) {
return (alias != null) ? alias : delegate.chooseEngineServerAlias(s, principals, sslEngine);
}
@Override
public String[] getClientAliases(String s, Principal[] principals) {
return delegate.getClientAliases(s, principals);
}
@Override
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
return delegate.chooseClientAlias(strings, principals, socket);
}
@Override
public String[] getServerAliases(String s, Principal[] principals) {
return delegate.getServerAliases(s, principals);
}
@Override
public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
return delegate.chooseServerAlias(s, principals, socket);
}
@Override
public X509Certificate[] getCertificateChain(String s) {
return delegate.getCertificateChain(s);
}
@Override
public PrivateKey getPrivateKey(String s) {
return delegate.getPrivateKey(s);
}
}
}
@@ -0,0 +1,41 @@
package timely.configuration;
public class AuthorizationProperties {
private boolean enabled = false;
private String authorizationUrl;
private String publicCertificateFile;
private String publicCertificateType;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getAuthorizationUrl() {
return authorizationUrl;
}
public void setAuthorizationUrl(String authorizationUrl) {
this.authorizationUrl = authorizationUrl;
}
public String getPublicCertificateFile() {
return publicCertificateFile;
}
public void setPublicCertificateFile(String publicCertificateFile) {
this.publicCertificateFile = publicCertificateFile;
}
public String getPublicCertificateType() {
return publicCertificateType;
}
public void setPublicCertificateType(String publicCertificateType) {
this.publicCertificateType = publicCertificateType;
}
}
@@ -0,0 +1,113 @@
package timely.configuration;
public class ClientSsl implements Ssl {
private String[] ciphers;
private String[] enabledProtocols;
private String keyStoreFile;
private String keyStoreType;
private String keyStorePassword;
private String keyAlias;
private String trustStoreFile;
private String trustStoreType;
private String trustStorePassword;
private boolean useClientCert = true;
private boolean hostVerificationEnabled = true;
private boolean useOpenssl = true;
public String[] getCiphers() {
return ciphers;
}
public void setCiphers(String[] ciphers) {
this.ciphers = ciphers;
}
public String[] getEnabledProtocols() {
return enabledProtocols;
}
public void setEnabledProtocols(String[] enabledProtocols) {
this.enabledProtocols = enabledProtocols;
}
public String getKeyStoreFile() {
return keyStoreFile;
}
public void setKeyStoreFile(String keyStoreFile) {
this.keyStoreFile = keyStoreFile;
}
public String getKeyStoreType() {
return keyStoreType;
}
public void setKeyStoreType(String keyStoreType) {
this.keyStoreType = keyStoreType;
}
public String getKeyStorePassword() {
return keyStorePassword;
}
public void setKeyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
}
public String getKeyAlias() {
return keyAlias;
}
public void setKeyAlias(String keyAlias) {
this.keyAlias = keyAlias;
}
public String getTrustStoreFile() {
return trustStoreFile;
}
public void setTrustStoreFile(String trustStoreFile) {
this.trustStoreFile = trustStoreFile;
}
public String getTrustStoreType() {
return trustStoreType;
}
public void setTrustStoreType(String trustStoreType) {
this.trustStoreType = trustStoreType;
}
public String getTrustStorePassword() {
return trustStorePassword;
}
public void setTrustStorePassword(String trustStorePassword) {
this.trustStorePassword = trustStorePassword;
}
public void setUseClientCert(boolean useClientCert) {
this.useClientCert = useClientCert;
}
public boolean isUseClientCert() {
return useClientCert;
}
public void setHostVerificationEnabled(boolean hostVerificationEnabled) {
this.hostVerificationEnabled = hostVerificationEnabled;
}
public boolean isHostVerificationEnabled() {
return hostVerificationEnabled;
}
public boolean isUseOpenssl() {
return useOpenssl;
}
public void setUseOpenssl(boolean useOpenssl) {
this.useOpenssl = useOpenssl;
}
}
@@ -0,0 +1,32 @@
package timely.configuration;
public class JwtSsl {
private String keyStoreType;
private String keyStoreFile;
private String keyStorePassword;
public String getKeyStoreType() {
return keyStoreType;
}
public void setKeyStoreType(String keyStoreType) {
this.keyStoreType = keyStoreType;
}
public String getKeyStoreFile() {
return keyStoreFile;
}
public void setKeyStoreFile(String keyStoreFile) {
this.keyStoreFile = keyStoreFile;
}
public String getKeyStorePassword() {
return keyStorePassword;
}
public void setKeyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
}
}
@@ -11,10 +11,8 @@ public class Security {
private int sessionMaxAge = 86400;
private int cacheExpirationMinutes = 60;
private int cacheRefreshMinutes = 5;
private String jwtCheckKeyStore;
private String jwtCheckKeyType;
private String jwtCheckKeyPassword;
@NestedConfigurationProperty
private JwtSsl jwtSsl = new JwtSsl();
@Valid
@NestedConfigurationProperty
private ServerSsl serverSsl = new ServerSsl();
@@ -63,27 +61,7 @@ public class Security {
return serverSsl;
}
public String getJwtCheckKeyStore() {
return jwtCheckKeyStore;
}
public void setJwtCheckKeyStore(String jwtCheckKeyStore) {
this.jwtCheckKeyStore = jwtCheckKeyStore;
}
public String getJwtCheckKeyType() {
return jwtCheckKeyType;
}
public void setJwtCheckKeyType(String jwtCheckKeyType) {
this.jwtCheckKeyType = jwtCheckKeyType;
}
public String getJwtCheckKeyPassword() {
return jwtCheckKeyPassword;
}
public void setJwtCheckKeyPassword(String jwtCheckKeyPassword) {
this.jwtCheckKeyPassword = jwtCheckKeyPassword;
public JwtSsl getJwtSsl() {
return jwtSsl;
}
}
@@ -2,47 +2,82 @@ package timely.configuration;
import java.util.List;
import com.google.common.collect.Lists;
import timely.validator.NotEmptyIfFieldSet;
@NotEmptyIfFieldSet.List({
@NotEmptyIfFieldSet(fieldName = "useGeneratedKeypair", fieldValue = "false", notNullFieldName = "certificateFile", message = "must be set if timely.security.ssl.use-generated-keypair is false"),
@NotEmptyIfFieldSet(fieldName = "useGeneratedKeypair", fieldValue = "false", notNullFieldName = "keyFile", message = "must be set if timely.security.ssl.use-generated-keypair is false") })
@NotEmptyIfFieldSet(fieldName = "useGeneratedKeypair", fieldValue = "false", notNullFieldName = "keyStoreFile", message = "must be set if timely.security.ssl.use-generated-keypair is false") })
public class ServerSsl {
public class ServerSsl implements Ssl {
private String certificateFile;
private String keyFile;
private String keyPassword;
private String trustStoreFile;
private boolean useGeneratedKeypair = false;
private boolean useOpenssl = true;
private List<String> useCiphers = Lists.newArrayList("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
private String[] ciphers = new String[] { "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA");
"SSL_RSA_WITH_3DES_EDE_CBC_SHA" };
private String[] enabledProtocols;
private String keyStoreType;
private String keyStoreFile;
private String keyStorePassword;
private String keyAlias;
private String trustStoreType;
private String trustStoreFile;
private String trustStorePassword;
private boolean useGeneratedKeypair = false;
private boolean ignoreSslHandshakeErrors = false;
private boolean useOpenssl = true;
public String getCertificateFile() {
return certificateFile;
public String[] getCiphers() {
return ciphers;
}
public void setCertificateFile(String certificateFile) {
this.certificateFile = certificateFile;
public void setCiphers(String[] ciphers) {
this.ciphers = ciphers;
}
public String getKeyFile() {
return keyFile;
public String[] getEnabledProtocols() {
return enabledProtocols;
}
public void setKeyFile(String keyFile) {
this.keyFile = keyFile;
public void setEnabledProtocols(String[] enabledProtocols) {
this.enabledProtocols = enabledProtocols;
}
public String getKeyPassword() {
return keyPassword;
public String getKeyStoreType() {
return keyStoreType;
}
public void setKeyPassword(String keyPassword) {
this.keyPassword = keyPassword;
public void setKeyStoreType(String keyStoreType) {
this.keyStoreType = keyStoreType;
}
public String getKeyStoreFile() {
return keyStoreFile;
}
public void setKeyStoreFile(String keyStoreFile) {
this.keyStoreFile = keyStoreFile;
}
public String getKeyStorePassword() {
return keyStorePassword;
}
public void setKeyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
}
public String getKeyAlias() {
return keyAlias;
}
public void setKeyAlias(String keyAlias) {
this.keyAlias = keyAlias;
}
public String getTrustStoreType() {
return trustStoreType;
}
public void setTrustStoreType(String trustStoreType) {
this.trustStoreType = trustStoreType;
}
public String getTrustStoreFile() {
@@ -53,6 +88,14 @@ public class ServerSsl {
this.trustStoreFile = trustStoreFile;
}
public String getTrustStorePassword() {
return trustStorePassword;
}
public void setTrustStorePassword(String trustStorePassword) {
this.trustStorePassword = trustStorePassword;
}
public boolean isUseGeneratedKeypair() {
return useGeneratedKeypair;
}
@@ -61,6 +104,14 @@ public class ServerSsl {
this.useGeneratedKeypair = useGeneratedKeypair;
}
public boolean isIgnoreSslHandshakeErrors() {
return ignoreSslHandshakeErrors;
}
public void setIgnoreSslHandshakeErrors(boolean ignoreSslHandshakeErrors) {
this.ignoreSslHandshakeErrors = ignoreSslHandshakeErrors;
}
public boolean isUseOpenssl() {
return useOpenssl;
}
@@ -68,12 +119,4 @@ public class ServerSsl {
public void setUseOpenssl(boolean useOpenssl) {
this.useOpenssl = useOpenssl;
}
public List<String> getUseCiphers() {
return useCiphers;
}
public void setUseCiphers(List<String> useCiphers) {
this.useCiphers = useCiphers;
}
}
@@ -0,0 +1,45 @@
package timely.configuration;
public interface Ssl {
String getKeyStoreType();
void setKeyStoreType(String keyStoreType);
String getKeyStoreFile();
void setKeyStoreFile(String keyStoreFile);
String getKeyStorePassword();
void setKeyStorePassword(String keyStorePassword);
String getKeyAlias();
void setKeyAlias(String keyAlias);
String getTrustStoreType();
void setTrustStoreType(String trustStoreType);
String getTrustStoreFile();
void setTrustStoreFile(String trustStoreFile);
String getTrustStorePassword();
void setTrustStorePassword(String trustStorePassword);
String[] getCiphers();
void setCiphers(String[] ciphers);
String[] getEnabledProtocols();
void setEnabledProtocols(String[] enabledProtocols);
boolean isUseOpenssl();
void setUseOpenssl(boolean useOpenssl);
}
@@ -102,8 +102,8 @@ public class ConfigurationTest {
"timely.accumulo.username:root",
"timely.accumulo.password:secret",
"timely.http.host:localhost",
"timely.security.serverSsl.certificate-file:/tmp/foo",
"timely.security.serverSsl.key-file:/tmp/bar").applyTo(this.context);
"timely.security.serverSsl.key-store-file:/tmp/foo",
"timely.security.serverSsl.key-store-password:password").applyTo(this.context);
// @formatter:on
context.refresh();
}
@@ -31,7 +31,7 @@ public class MetricAdapterTest {
}
@Test
public void testToMutation() throws Exception {
public void testToMutation() {
long ts = System.currentTimeMillis();
List<Tag> tags = new ArrayList<>();
tags.add(new Tag("tag1", "value1"));
@@ -72,7 +72,7 @@ public class MetricAdapterTest {
}
@Test
public void testToMutationWithViz() throws Exception {
public void testToMutationWithViz() {
long ts = System.currentTimeMillis();
List<Tag> tags = new ArrayList<>();
tags.add(new Tag("tag1", "value1"));
@@ -10,16 +10,16 @@ import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserDetailsServiceTest {
public class FileUserDetailsServiceTest {
private static ApplicationContext springContext = null;
private static UserDetailsService userDetailsService = null;
private static FileUserDetailsService fileUserDetailsService = null;
@BeforeClass
public static void setupClass() {
try {
springContext = new ClassPathXmlApplicationContext("security.xml");
userDetailsService = (UserDetailsService) springContext.getBean("timelyUserDetailsService");
fileUserDetailsService = (FileUserDetailsService) springContext.getBean("timelyUserDetailsService");
} catch (BeansException e) {
throw new ServiceConfigurationError("Error initializing from spring: " + e.getMessage(), e.getRootCause());
}
@@ -27,7 +27,7 @@ public class UserDetailsServiceTest {
@Test
public void testAuths() {
TimelyUser u = userDetailsService.getUsers().get("CN=example.com");
TimelyUser u = fileUserDetailsService.getUsers().get("CN=example.com");
Assert.assertNotNull("TimelyUser not found", u);
Assert.assertEquals("3 auths expected", 3, u.getAuths().size());
Assert.assertTrue("Unexpected auths found " + u.getAuths(),
@@ -36,7 +36,7 @@ public class UserDetailsServiceTest {
@Test
public void testRoles() {
TimelyUser u = userDetailsService.getUsers().get("CN=example.com");
TimelyUser u = fileUserDetailsService.getUsers().get("CN=example.com");
Assert.assertNotNull("TimelyUser not found", u);
Assert.assertEquals("3 roles expected", 3, u.getRoles().size());
Assert.assertTrue("Unexpected roles found " + u.getRoles(),
@@ -36,7 +36,6 @@ public class InMemoryITBase {
private static final Logger LOG = LoggerFactory.getLogger(InMemoryITBase.class);
protected static final String ROOT_USER = "root";
protected static final String ROOT_PASSWORD = "secret";
protected Configuration conf = null;
protected AccumuloClient accumuloClient;
protected Server s;
@@ -100,7 +99,7 @@ public class InMemoryITBase {
}
@After
public void shutdownInMemoryBase() {
public void shutdownInMemoryBase() throws Exception {
if (zookeeper != null) {
zookeeper.close();
}
@@ -1,14 +1,18 @@
package timely.test.integration;
import static java.util.Objects.requireNonNull;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.minicluster.MiniAccumuloCluster;
import org.apache.accumulo.minicluster.MiniAccumuloConfig;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -51,12 +55,28 @@ public class MacITBase {
if (null == mac) {
final MiniAccumuloConfig macConfig = new MiniAccumuloConfig(tempDir, MAC_ROOT_PASSWORD);
mac = new MiniAccumuloCluster(macConfig);
// this is needed if the timely server is run against MiniAccumulo
File libExt = new File(macConfig.getDir(), "/lib/ext");
copyJarsToMacLibExt(libExt, "target", "timely-server.*.jar");
copyJarsToMacLibExt(libExt, "target/lib", ".*.jar");
mac.start();
} else {
LOG.info("Mini Accumulo already running.");
}
}
private static void copyJarsToMacLibExt(File macLibExt, String searchDirStr, String jarRegex) {
File searchDir = new File(Paths.get(searchDirStr).toUri());
File[] jarFiles = searchDir.listFiles((dir, name) -> name.matches(jarRegex));
for (File f : jarFiles) {
try {
FileUtils.copyURLToFile(requireNonNull(f.toURI().toURL()), new File(macLibExt, f.getName()));
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
}
@Before
public void setupMacITBase() {
AuthCache.clear();
@@ -67,7 +67,6 @@ public class MetricCompactionIT extends MacITBase {
accumuloClient.tableOperations().setProperty(conf.getMetricsTable(), Property.TABLE_SPLIT_THRESHOLD.getKey(),
"50K");
adapter.resetState();
startServer();
}
@After
@@ -75,7 +74,6 @@ public class MetricCompactionIT extends MacITBase {
accumuloClient.instanceOperations().setProperty(Property.TSERV_MAJC_DELAY.getKey(), "30s");
adapter.resetState();
AuthCache.resetConfiguration();
stopServer();
}
@Test
@@ -116,7 +114,7 @@ public class MetricCompactionIT extends MacITBase {
@Test
public void tabletsCompactedUntilAgeOff() throws Exception {
// test will replicated problem in time-series tablets where data is
// test will replicate problem in time-series tablets where data is
// split automatically and the resulting tablets will not be cleaned up
// by the default compaction strategy
//
@@ -131,7 +129,7 @@ public class MetricCompactionIT extends MacITBase {
// check to make sure the table has only one iterator
Map<String, EnumSet<IteratorUtil.IteratorScope>> itrs = accumuloClient.tableOperations()
.listIterators(metricsTable);
assertEquals(2, itrs.size());
assertEquals(1, itrs.size());
assertTrue(itrs.containsKey("vers"));
long timestampMax = System.currentTimeMillis();
@@ -51,9 +51,8 @@ public class OneWaySSLBase extends QueryBase {
protected static void setupSSL(Configuration config) throws Exception {
SelfSignedCertificate serverCert = new SelfSignedCertificate();
config.getSecurity().getServerSsl().setCertificateFile(serverCert.certificate().getAbsolutePath());
clientTrustStoreFile = serverCert.certificate().getAbsoluteFile();
config.getSecurity().getServerSsl().setKeyFile(serverCert.privateKey().getAbsolutePath());
config.getSecurity().getServerSsl().setKeyStoreFile(serverCert.privateKey().getAbsolutePath());
config.getSecurity().getServerSsl().setUseOpenssl(false);
config.getSecurity().getServerSsl().setUseGeneratedKeypair(false);
config.getSecurity().setAllowAnonymousHttpAccess(true);
@@ -1,7 +1,10 @@
package timely.test.integration;
import java.io.File;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
@@ -17,6 +20,7 @@ import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Before;
import timely.configuration.Configuration;
@@ -69,14 +73,37 @@ public class TwoWaySSLBase extends QueryBase {
return jdkSslContext.getSocketFactory();
}
protected void setupSSL(Configuration config) {
protected void setupSSL(Configuration config) throws Exception {
SelfSignedCertificate serverCert = getServerCert();
config.getSecurity().getServerSsl().setCertificateFile(serverCert.certificate().getAbsolutePath());
config.getSecurity().getServerSsl().setKeyFile(serverCert.privateKey().getAbsolutePath());
String password = "password";
// write the keyStore with server certificate into a P12 trustStore
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
keyStore.setCertificateEntry("cert", serverCert.cert());
File trustStoreP12File = File.createTempFile("trustStore_", ".p12");
try (OutputStream out = FileUtils.newOutputStream(trustStoreP12File, false)) {
keyStore.store(out, password.toCharArray());
}
// write the keyStore with private key and server certificate into a P12
// keyStore
keyStore.setKeyEntry("key", serverCert.key(), password.toCharArray(), new Certificate[] { serverCert.cert() });
File keyStoreP12File = File.createTempFile("keyStore_", ".p12");
try (OutputStream out = FileUtils.newOutputStream(keyStoreP12File, false)) {
keyStore.store(out, password.toCharArray());
}
config.getSecurity().getServerSsl().setKeyStoreType("PKCS12");
config.getSecurity().getServerSsl().setKeyStoreFile(keyStoreP12File.getAbsolutePath());
config.getSecurity().getServerSsl().setKeyStorePassword(password);
// Needed for 2way SSL
config.getSecurity().getServerSsl().setTrustStoreFile(serverCert.certificate().getAbsolutePath());
config.getSecurity().getServerSsl().setTrustStoreType("PKCS12");
config.getSecurity().getServerSsl().setTrustStoreFile(trustStoreP12File.getAbsolutePath());
config.getSecurity().getServerSsl().setTrustStorePassword(password);
config.getSecurity().getServerSsl().setUseOpenssl(false);
config.getSecurity().getServerSsl().setUseGeneratedKeypair(false);
config.getSecurity().getServerSsl().setIgnoreSslHandshakeErrors(true);
config.getSecurity().setAllowAnonymousHttpAccess(false);
}
+1 -1
View File
@@ -13,7 +13,7 @@
<beans:property name="subjectDnRegex" value="CN=(.*?)(?:,|$)"/>
</beans:bean>
<beans:bean id="timelyUserDetailsService" class="timely.auth.UserDetailsService">
<beans:bean id="timelyUserDetailsService" class="timely.auth.FileUserDetailsService">
<beans:property name="users">
<util:list>
<beans:bean class="timely.auth.TimelyUser">