From 104fe6512dc7b611b6b1a26dd4d18f252620facd Mon Sep 17 00:00:00 2001 From: anhefti Date: Tue, 27 Aug 2019 16:35:23 +0200 Subject: [PATCH] prod SSL and added lmsType to RunningExamInfo --- .../selfsigned/application-prod.properties | 25 +++++++++++-------- .../standalone/selfsigned/docker-compose.yml | 3 +++ .../standalone/selfsigned/gencerts/Dockerfile | 4 +-- ...{RunningExam.java => RunningExamInfo.java} | 20 ++++++++++++--- .../weblayer/api/ExamAPI_V1_Controller.java | 22 ++++++++++++---- .../resources/config/application.properties | 2 +- src/main/resources/data-demo.sql | 2 +- .../ch/ethz/seb/sebserver/HTTPClientBot.java | 8 +++--- .../api/exam/SebConnectionTest.java | 6 +++-- .../client/ClientCredentialServiceTest.java | 4 +-- 10 files changed, 64 insertions(+), 32 deletions(-) rename src/main/java/ch/ethz/seb/sebserver/gbl/model/session/{RunningExam.java => RunningExamInfo.java} (69%) diff --git a/docker/prod/standalone/selfsigned/application-prod.properties b/docker/prod/standalone/selfsigned/application-prod.properties index af7f9fe4..0bee56e7 100644 --- a/docker/prod/standalone/selfsigned/application-prod.properties +++ b/docker/prod/standalone/selfsigned/application-prod.properties @@ -1,18 +1,21 @@ +spring.profiles.include=prod-ws,prod-gui + server.address=0.0.0.0 -server.port=80 +server.port=443 server.servlet.context-path=/ -#security.require-ssl=true -#server.ssl.key-store-type=PKCS12 -#server.ssl.key-store=file:/sebserver/seb-server-keystore.pkcs12 -#server.ssl.key-alias=1 +security.require-ssl=true +server.ssl.key-store-type=PKCS12 +server.ssl.key-store=file:/certs/seb-server-keystore.pkcs12 +server.ssl.key-store-password=[SET_PWD] +server.ssl.key-alias=1 file.encoding=UTF-8 -javax.net.ssl.keyStore=seb-server-keystore.pkcs12 +javax.net.ssl.keyStore=/certs/seb-server-keystore.pkcs12 javax.net.ssl.keyStorePassword=[SET_PWD] -javax.net.ssl.trustStore=seb-server-truststore.pkcs12 +javax.net.ssl.trustStore=/certs/seb-server-truststore.pkcs12 javax.net.ssl.trustStorePassword=[SET_PWD] @@ -33,10 +36,10 @@ datastore.mariadb.server.port=3306 # data source configuration spring.datasource.initialize=true spring.datasource.initialization-mode=always -spring.datasource.url=jdbc:mariadb://${datastore.mariadb.server.address}:${datastore.mariadb.server.port}/SEBServer?createDatabaseIfNotExist=true&verifyServerCertificate=true&useSSL=true&requireSSL=true +spring.datasource.url=jdbc:mariadb://${datastore.mariadb.server.address}:${datastore.mariadb.server.port}/SEBServer?createDatabaseIfNotExist=true&verifyServerCertificate=false&useSSL=true&requireSSL=true&trustServerCertificate=true spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.datasource.platform=prod -spring.datasource.hikari.initializationFailTimeout=30000 +spring.datasource.hikari.initializationFailTimeout=1 spring.datasource.hikari.connectionTimeout=30000 spring.datasource.hikari.idleTimeout=600000 spring.datasource.hikari.maxLifetime=1800000 @@ -45,8 +48,8 @@ spring.datasource.hikari.maxLifetime=1800000 sebserver.webservice.distributed=false sebserver.webservice.http.scheme=https sebserver.webservice.http.server.name=${server.address} - sebserver.webservice.http.redirect.gui=/gui +sebserver.webservice.api.admin.clientId=guiClient sebserver.webservice.api.admin.endpoint=/admin-api/v1 sebserver.webservice.api.admin.accessTokenValiditySeconds=3600 sebserver.webservice.api.admin.refreshTokenValiditySeconds=25200 @@ -73,7 +76,7 @@ server.servlet.session.tracking-modes=cookie sebserver.gui.entrypoint=/gui sebserver.gui.webservice.protocol=https -sebserver.gui.webservice.address=localhost +sebserver.gui.webservice.address=${server.address} sebserver.gui.webservice.port=80 sebserver.gui.webservice.apipath=/admin-api/v1 # defines the polling interval that is used to poll the webservice for client connection data on a monitored exam page diff --git a/docker/prod/standalone/selfsigned/docker-compose.yml b/docker/prod/standalone/selfsigned/docker-compose.yml index 0cf767d1..6d5bbffb 100644 --- a/docker/prod/standalone/selfsigned/docker-compose.yml +++ b/docker/prod/standalone/selfsigned/docker-compose.yml @@ -8,6 +8,8 @@ services: volumes: - ./certs:/certs environment: + - SERVER_CN=seb-server-mariadb + - CLIENT_CN=seb-server-mariadb - KEYSTORE_PWD=[SET_PWD] mariadb: @@ -35,6 +37,7 @@ services: container_name: seb-server volumes: - .:/config + - ./certs:/certs ports: - 80:80 networks: diff --git a/docker/prod/standalone/selfsigned/gencerts/Dockerfile b/docker/prod/standalone/selfsigned/gencerts/Dockerfile index a2ef1498..8de7584f 100644 --- a/docker/prod/standalone/selfsigned/gencerts/Dockerfile +++ b/docker/prod/standalone/selfsigned/gencerts/Dockerfile @@ -3,8 +3,8 @@ FROM openjdk:11-jre-stretch RUN apt-get update && apt-get install -y openssl ENV KEYSTORE_PWD= -ENV SERVER_CN="localhost" -ENV CLIENT_CN="localhost" +ENV SERVER_CN="seb-server-mariadb" +ENV CLIENT_CN="seb-server-mariadb" ENV OPENSSL_SUBJ="/C=CH/ST=Zuerich/L=Zuerich" ENV OPENSSL_CA="${OPENSSL_SUBJ}/CN=demo-CA" ENV OPENSSL_SERVER="${OPENSSL_SUBJ}/CN=${SERVER_CN}" diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExam.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExamInfo.java similarity index 69% rename from src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExam.java rename to src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExamInfo.java index 5ff163cc..ba3e034a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExam.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/RunningExamInfo.java @@ -12,8 +12,9 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; +import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; -public final class RunningExam { +public final class RunningExamInfo { @JsonProperty("examId") public final String examId; @@ -21,22 +22,27 @@ public final class RunningExam { public final String name; @JsonProperty("url") public final String url; + @JsonProperty("lmsType") + public final String lmsType; @JsonCreator - public RunningExam( + public RunningExamInfo( @JsonProperty("examId") final String examId, @JsonProperty("name") final String name, - @JsonProperty("url") final String url) { + @JsonProperty("url") final String url, + @JsonProperty("lmsType") final String lmsType) { this.examId = examId; this.name = name; this.url = url; + this.lmsType = lmsType; } - public RunningExam(final Exam exam) { + public RunningExamInfo(final Exam exam, final LmsType lmsType) { this.examId = exam.getModelId(); this.name = exam.name; this.url = exam.startURL; + this.lmsType = (lmsType == null) ? "" : lmsType.name(); } public String getExamId() { @@ -51,6 +57,10 @@ public final class RunningExam { return this.url; } + public String getLmsType() { + return this.lmsType; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -60,6 +70,8 @@ public final class RunningExam { builder.append(this.name); builder.append(", url="); builder.append(this.url); + builder.append(", lmsType="); + builder.append(this.lmsType); builder.append("]"); return builder.toString(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAPI_V1_Controller.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAPI_V1_Controller.java index 1cf3940e..a8a4f077 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAPI_V1_Controller.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamAPI_V1_Controller.java @@ -40,10 +40,11 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; import ch.ethz.seb.sebserver.gbl.model.session.PingResponse; -import ch.ethz.seb.sebserver.gbl.model.session.RunningExam; +import ch.ethz.seb.sebserver.gbl.model.session.RunningExamInfo; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.SebClientConfigDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SebClientConnectionService; @@ -56,6 +57,7 @@ public class ExamAPI_V1_Controller { private static final Logger log = LoggerFactory.getLogger(ExamAPI_V1_Controller.class); private final ExamDAO examDAO; + private final LmsSetupDAO lmsSetupDAO; private final ExamSessionService examSessionService; private final SebClientConnectionService sebClientConnectionService; private final SebClientConfigDAO sebClientConfigDAO; @@ -63,12 +65,14 @@ public class ExamAPI_V1_Controller { protected ExamAPI_V1_Controller( final ExamDAO examDAO, + final LmsSetupDAO lmsSetupDAO, final ExamSessionService examSessionService, final SebClientConnectionService sebClientConnectionService, final SebClientConfigDAO sebClientConfigDAO, final JSONMapper jsonMapper) { this.examDAO = examDAO; + this.lmsSetupDAO = lmsSetupDAO; this.examSessionService = examSessionService; this.sebClientConnectionService = sebClientConnectionService; this.sebClientConfigDAO = sebClientConfigDAO; @@ -80,7 +84,7 @@ public class ExamAPI_V1_Controller { method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) - public Collection handshakeCreate( + public Collection handshakeCreate( @RequestParam(name = API.PARAM_INSTITUTION_ID, required = false) final Long instIdRequestParam, @RequestParam(name = API.EXAM_API_PARAM_EXAM_ID, required = false) final Long examIdRequestParam, @RequestBody(required = false) final MultiValueMap formParams, @@ -116,18 +120,18 @@ public class ExamAPI_V1_Controller { remoteAddr); } - List result; + List result; if (examId == null) { result = this.examSessionService.getRunningExamsForInstitution(institutionId) .getOrThrow() .stream() - .map(exam -> new RunningExam(exam)) + .map(this::createRunningExamInfo) .collect(Collectors.toList()); } else { final Exam exam = this.examDAO.byPK(examId) .getOrThrow(); - result = Arrays.asList(new RunningExam(exam)); + result = Arrays.asList(createRunningExamInfo(exam)); } if (result.isEmpty()) { @@ -146,6 +150,14 @@ public class ExamAPI_V1_Controller { return result; } + private RunningExamInfo createRunningExamInfo(final Exam exam) { + return new RunningExamInfo( + exam, + this.lmsSetupDAO.byPK(exam.lmsSetupId) + .map(lms -> lms.lmsType) + .getOr(null)); + } + @RequestMapping( path = API.EXAM_API_HANDSHAKE_ENDPOINT, method = RequestMethod.PATCH, diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index d24325ce..8fe4b9bb 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -1,5 +1,5 @@ spring.application.name=SEB Server -spring.profiles.active=dev +spring.profiles.active=prod spring.mandatory-file-encoding=UTF-8 spring.http.encoding.charset=UTF-8 diff --git a/src/main/resources/data-demo.sql b/src/main/resources/data-demo.sql index fe7c6dd3..980dfcfe 100644 --- a/src/main/resources/data-demo.sql +++ b/src/main/resources/data-demo.sql @@ -14,7 +14,7 @@ INSERT IGNORE INTO user_role VALUES ; INSERT IGNORE INTO seb_client_configuration VALUES - (1, 1, 'test', '2019-07-02 09:22:50', 'test', '98ac3c953abf5948d9d13c81cab580819ee2624c76d6d4147d4896a5b79f49956d382c08c93cb3b9ae350b32', null, 1) + (1, 1, 'test', '2019-07-02 09:22:50', 'test', '20faa63098beb54053d228d078d9471a6b35bde8cf2e91a879789e721e54c6535660d8d69e4670484a87977a', null, 1) ; INSERT IGNORE INTO view VALUES diff --git a/src/test/java/ch/ethz/seb/sebserver/HTTPClientBot.java b/src/test/java/ch/ethz/seb/sebserver/HTTPClientBot.java index cf8f59ba..c7a93bb0 100644 --- a/src/test/java/ch/ethz/seb/sebserver/HTTPClientBot.java +++ b/src/test/java/ch/ethz/seb/sebserver/HTTPClientBot.java @@ -43,7 +43,7 @@ import org.springframework.util.MultiValueMap; import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.API; -import ch.ethz.seb.sebserver.gbl.model.session.RunningExam; +import ch.ethz.seb.sebserver.gbl.model.session.RunningExamInfo; import ch.ethz.seb.sebserver.gbl.util.Utils; public class HTTPClientBot { @@ -252,11 +252,11 @@ public class HTTPClientBot { log.info("ConnectionBot {} : init connection", this.name); try { - final ResponseEntity> exchange = this.restTemplate.exchange( + final ResponseEntity> exchange = this.restTemplate.exchange( this.handshakeURI, HttpMethod.POST, this.connectBody, - new ParameterizedTypeReference>() { + new ParameterizedTypeReference>() { }); final HttpStatus statusCode = exchange.getStatusCode(); @@ -264,7 +264,7 @@ public class HTTPClientBot { throw new RuntimeException("Webservice answered with error: " + exchange.getBody()); } - final Collection body = exchange.getBody(); + final Collection body = exchange.getBody(); final String token = exchange.getHeaders().getFirst(API.EXAM_API_SEB_CONNECTION_TOKEN); log.info("ConnectionBot {} : successfully created connection, token: {} body: {} ", this.name, token, diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java index b67cf98c..d4035045 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java @@ -62,7 +62,8 @@ public class SebConnectionTest extends ExamAPIIntegrationTester { // check correct response assertTrue(HttpStatus.OK.value() == createConnection.getStatus()); final String contentAsString = createConnection.getContentAsString(); - assertEquals("[{\"examId\":\"2\",\"name\":\"Demo Quiz 6\",\"url\":\"http://lms.mockup.com/api/\"}]", + assertEquals( + "[{\"examId\":\"2\",\"name\":\"Demo Quiz 6\",\"url\":\"http://lms.mockup.com/api/\",\"lmsType\":\"MOCKUP\"}]", contentAsString); // check connection token @@ -109,7 +110,8 @@ public class SebConnectionTest extends ExamAPIIntegrationTester { // check correct response assertTrue(HttpStatus.OK.value() == createConnection.getStatus()); final String contentAsString = createConnection.getContentAsString(); - assertEquals("[{\"examId\":\"2\",\"name\":\"Demo Quiz 6\",\"url\":\"http://lms.mockup.com/api/\"}]", + assertEquals( + "[{\"examId\":\"2\",\"name\":\"Demo Quiz 6\",\"url\":\"http://lms.mockup.com/api/\",\"lmsType\":\"MOCKUP\"}]", contentAsString); // check connection token diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceTest.java index 3d13861a..b07e06ae 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceTest.java @@ -20,8 +20,8 @@ public class ClientCredentialServiceTest { // @Test // public void testEncryptSimpleSecret() { // final Environment envMock = mock(Environment.class); -// when(envMock.getRequiredProperty(ClientCredentialServiceImpl.SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY)) -// .thenReturn("internalSecret"); +// when(envMock.getProperty(ClientCredentialServiceImpl.SEBSERVER_WEBSERVICE_INTERNAL_SECRET_KEY)) +// .thenReturn("somePW"); // // final ClientCredentialService service = new ClientCredentialServiceImpl(envMock); // final CharSequence encrypt = service.encrypt("test");