Skip to content

Commit

Permalink
Merge pull request #1 from DP-3T/feature/splunk-integration
Browse files Browse the repository at this point in the history
Feature/splunk integration
  • Loading branch information
martinalig authored Sep 24, 2020
2 parents a85761b + ec6eb0d commit c4a46bc
Show file tree
Hide file tree
Showing 22 changed files with 1,081 additions and 458 deletions.
524 changes: 261 additions & 263 deletions dpppt-additionalinfo-backend/pom.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.dpppt.additionalinfo.backend.ws.config;

import java.util.TimeZone;

import org.dpppt.additionalinfo.backend.ws.controller.DppptAdditionalInfoController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {

@Autowired
DppptAdditionalInfoController dppptAdditionalInfoController;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// refresh the statistics every full hour.
taskRegistrar.addCronTask(new CronTask(new Runnable() {

@Override
public void run() {
dppptAdditionalInfoController.reloadStats();
}

}, new CronTrigger("0 0 * * * ?", TimeZone.getTimeZone("Europe/Zurich"))));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package org.dpppt.additionalinfo.backend.ws.config;

import io.jsonwebtoken.SignatureAlgorithm;
import java.io.ByteArrayInputStream;
import java.io.Reader;
import java.io.StringReader;
Expand All @@ -21,101 +20,140 @@
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Duration;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.dpppt.additionalinfo.backend.ws.controller.DppptAdditionalInfoController;
import org.dpppt.additionalinfo.backend.ws.statistics.MockStatisticClient;
import org.dpppt.additionalinfo.backend.ws.statistics.SplunkStatisticClient;
import org.dpppt.additionalinfo.backend.ws.statistics.StatisticClient;
import org.dpppt.backend.shared.interceptor.HeaderInjector;
import org.dpppt.backend.shared.security.filter.ResponseWrapperFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import io.jsonwebtoken.SignatureAlgorithm;

@Configuration
@EnableScheduling
public abstract class WSBaseConfig implements SchedulingConfigurer, WebMvcConfigurer {

protected final Logger logger = LoggerFactory.getLogger(getClass());
final SignatureAlgorithm algorithm = SignatureAlgorithm.ES256;

@Value("${ws.headers.protected:}")
List<String> protectedHeaders;

int retentionDays = 0; // TODO remove

@Value(
"#{${ws.security.headers: {'X-Content-Type-Options':'nosniff', 'X-Frame-Options':'DENY','X-Xss-Protection':'1; mode=block'}}}")
Map<String, String> additionalHeaders;

abstract String getPublicKey();

abstract String getPrivateKey();

@Bean
public DppptAdditionalInfoController dppptAdditionalInfoController(
StatisticClient statisticClient) {
return new DppptAdditionalInfoController(statisticClient);
}

@Bean
public StatisticClient statisticsClient() {
return new MockStatisticClient();
}

@Bean
public ResponseWrapperFilter hashFilter() {
return new ResponseWrapperFilter(getKeyPair(algorithm), retentionDays, protectedHeaders);
}

@Bean
public HeaderInjector securityHeaderInjector() {
return new HeaderInjector(additionalHeaders);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(securityHeaderInjector());
}

public KeyPair getKeyPair(SignatureAlgorithm algorithm) {
Security.addProvider(new BouncyCastleProvider());
Security.setProperty("crypto.policy", "unlimited");
return new KeyPair(loadPublicKeyFromString(), loadPrivateKeyFromString());
}

private PrivateKey loadPrivateKeyFromString() {
try {
String privateKey = getPrivateKey();
Reader reader = new StringReader(privateKey);
PemReader readerPem = new PemReader(reader);
PemObject obj = readerPem.readPemObject();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(obj.getContent());
KeyFactory kf = KeyFactory.getInstance("ECDSA", "BC");
return (PrivateKey) kf.generatePrivate(pkcs8KeySpec);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException();
}
}

private PublicKey loadPublicKeyFromString() {
try {
return CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(getPublicKey().getBytes()))
.getPublicKey();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException();
}
}
public abstract class WSBaseConfig implements WebMvcConfigurer {

protected final Logger logger = LoggerFactory.getLogger(getClass());
final SignatureAlgorithm algorithm = SignatureAlgorithm.ES256;

@Value("${ws.headers.protected:}")
List<String> protectedHeaders;

// used for jwt token validity
int retentionDays = 1;

@Value("#{${ws.security.headers: {'X-Content-Type-Options':'nosniff', 'X-Frame-Options':'DENY','X-Xss-Protection':'1; mode=block'}}}")
Map<String, String> additionalHeaders;

@Value("${ws.statistics.splunk.url:}")
String splunkUrl;

@Value("${ws.statistics.splunk.activeapps.query:}")
String activeAppsQuery;

@Value("${ws.statistics.splunk.usedauthcodecount.query:}")
String usedAuthCodeCountQuery;

@Value("${ws.statistics.splunk.positivetestcount.query:}")
String positiveTestCountQuery;

@Value("#{T(java.time.LocalDate).parse('${ws.statistics.splunk.startdate:2020-06-01}')}")
LocalDate queryStartDate;

@Value("${ws.statistics.splunk.enddaysback:0}")
Integer queryEndDaysBack;

@Value("${ws.statistics.cachecontrol:PT1H}")
Duration cacheControl;

abstract String getPublicKey();

abstract String getPrivateKey();

abstract String getSplunkUsername();

abstract String getSplunkpassword();

@Bean
@ConditionalOnProperty(prefix = "ws.statistics.splunk", name = { "url", "activeapps.query",
"usedauthcodecount.query", "positivetestcount.query" })
public SplunkStatisticClient splunkStatisticsClient() {
logger.info("Creating Splunk statistics client");
return new SplunkStatisticClient(splunkUrl, getSplunkUsername(), getSplunkpassword(), activeAppsQuery,
usedAuthCodeCountQuery, positiveTestCountQuery, queryStartDate, queryEndDaysBack);
}

@Bean
@ConditionalOnMissingBean
public StatisticClient mockStatisticsClient() {
logger.info("Creating Mock statistics client");
return new MockStatisticClient();
}

@Bean
public DppptAdditionalInfoController dppptAdditionalInfoController(StatisticClient statisticClient) {
return new DppptAdditionalInfoController(statisticClient, cacheControl);
}

@Bean
public ResponseWrapperFilter hashFilter() {
return new ResponseWrapperFilter(getKeyPair(algorithm), retentionDays, protectedHeaders);
}

@Bean
public HeaderInjector securityHeaderInjector() {
return new HeaderInjector(additionalHeaders);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(securityHeaderInjector());
}

public KeyPair getKeyPair(SignatureAlgorithm algorithm) {
Security.addProvider(new BouncyCastleProvider());
Security.setProperty("crypto.policy", "unlimited");
return new KeyPair(loadPublicKeyFromString(), loadPrivateKeyFromString());
}

private PrivateKey loadPrivateKeyFromString() {
try {
String privateKey = getPrivateKey();
Reader reader = new StringReader(privateKey);
PemReader readerPem = new PemReader(reader);
PemObject obj = readerPem.readPemObject();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(obj.getContent());
KeyFactory kf = KeyFactory.getInstance("ECDSA", "BC");
return (PrivateKey) kf.generatePrivate(pkcs8KeySpec);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException();
}
}

private PublicKey loadPublicKeyFromString() {
try {
return CertificateFactory.getInstance("X.509")
.generateCertificate(new ByteArrayInputStream(getPublicKey().getBytes())).getPublicKey();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,26 @@
package org.dpppt.additionalinfo.backend.ws.config;

import java.util.Base64;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
@Profile("cloud-abn")
public class WSAbnConfig extends WSBaseConfig {
public class WSCloudAbnConfig extends WSBaseConfig {

@Value("${vcap.services.ecdsa_cs_abn.credentials.privateKey}")
private String privateKey;

@Value("${vcap.services.ecdsa_cs_abn.credentials.publicKey}")
public String publicKey;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {}

@Value("${vcap.services.splunk_api_abn.credentials.username}")
private String splunkUsername;

@Value("${vcap.services.splunk_api_abn.credentials.password}")
private String splunkPassword;

@Override
String getPrivateKey() {
Expand All @@ -37,4 +41,14 @@ String getPrivateKey() {
String getPublicKey() {
return new String(Base64.getDecoder().decode(publicKey));
}

@Override
String getSplunkUsername() {
return splunkUsername;
}

@Override
String getSplunkpassword() {
return splunkPassword;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,27 @@
package org.dpppt.additionalinfo.backend.ws.config;

import java.util.Base64;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
@Profile("cloud-test")
public class WSTestConfig extends WSBaseConfig {
@Value("${vcap.services.ecdsa_cs_test.credentials.privateKey}")
@Profile("cloud-dev")
public class WSCloudDevConfig extends WSBaseConfig {

@Value("${vcap.services.ecdsa_cs_dev.credentials.privateKey}")
private String privateKey;

@Value("${vcap.services.ecdsa_cs_test.credentials.publicKey}")
@Value("${vcap.services.ecdsa_cs_dev.credentials.publicKey}")
public String publicKey;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {}
@Value("${vcap.services.splunk_api_dev.credentials.username}")
private String splunkUsername;

@Value("${vcap.services.splunk_api_dev.credentials.password}")
private String splunkPassword;


@Override
String getPrivateKey() {
Expand All @@ -37,4 +42,14 @@ String getPrivateKey() {
String getPublicKey() {
return new String(Base64.getDecoder().decode(publicKey));
}

@Override
String getSplunkUsername() {
return splunkUsername;
}

@Override
String getSplunkpassword() {
return splunkPassword;
}
}
Loading

0 comments on commit c4a46bc

Please sign in to comment.