From 68f6eda318e2f90d060de44147ccdd0b498fee98 Mon Sep 17 00:00:00 2001 From: Claudio Bianucci Date: Wed, 26 May 2021 13:20:31 +0200 Subject: [PATCH] feat: migrate to new eps + proxy-services based architecture Migrate to new eps + proxy-services based architecture. Highlights: - the location-service now uses json-rpc / eps instead of REST - the deployment config in the infrastructure directory was adjusted accordingly - demo-checkin-app now receives data requests via json-rpc / eps - demo-checkin-app now submits data via json-rpc / eps Notes for developers: - iris-client-eps directory contains all files / information to set up a local development environment Co-authored-by: Claudio Bianucci Co-authored-by: lucky-lusa Refs iris-backlog/issues/81 , /iris-backlog/issues/92 BREAKING CHANGES --- .../workflows/location-service_develop.yml | 37 --- .github/workflows/public-server_develop.yml | 37 --- .github/workflows/push-to-develop.yml | 60 +++++ demo-checkin-app/pom.xml | 220 ++++++++++-------- .../IrisDemoCheckinAppApplication.java | 26 ++- .../config/EPSClientProperties.java | 21 ++ .../checkin_app/config/RPCClientConfig.java | 79 +++++++ .../datarequest/jsonrpc/DataRequestRPC.java | 17 ++ .../jsonrpc/DataRequestRPCImpl.java | 34 +++ .../datarequest/jsonrpc/JsonRpcClientDto.java | 14 ++ .../model/dto/LocationDataRequestDto.java | 39 ++-- .../datasubmission/encryption/Decryptor.java | 5 - .../datasubmission/encryption/Encryptor.java | 7 - .../encryption/GuestListDecryptor.java | 92 -------- .../encryption/GuestListEncryptor.java | 96 -------- .../eps/EPSDataSubmissionClient.java | 31 +++ .../eps/dto/DataSubmissionDto.java | 18 ++ .../IRISDataSubmissionException.java | 8 + .../service/DataSubmissionService.java | 54 ++--- .../web/client/DataSubmissionClient.java | 41 ---- .../searchindex/SearchIndexClient.java | 18 ++ .../searchindex/eps/EPSSearchIndexClient.java | 55 +++++ .../eps/dto/DeleteLocationDTO.java | 13 ++ .../eps/dto/JsonRPCStringResult.java | 16 ++ .../eps/dto/UpdateLocationsDTO.java | 16 ++ .../web/client/SearchIndexClient.java | 67 ------ .../checkin_app/startup/LocationUpdater.java | 15 +- .../src/main/resources/application.properties | 14 +- .../src/main/resources/keystore.p12 | Bin 2627 -> 0 bytes .../IrisAppApiDemoApplicationTests.java | 8 - .../bootstrap/GuestLoaderTest.java | 60 ++--- .../service/DataSubmissionTest.java | 164 ------------- .../web/client/SearchIndexClientTest.java | 47 ---- infrastructure/DEPLOYMENT.adoc | 13 -- infrastructure/docker-compose-all.dev.yml | 134 +++++++++++ infrastructure/docker-compose-all.staging.yml | 6 +- infrastructure/docker-compose.staging.yml | 136 ++++++----- .../docker/nginx/config-dev/nginx.conf | 73 ++++++ .../sites-enabled-sormas/sormas.conf | 33 +++ .../nginx/config-dev/sites-enabled/api.conf | 104 +++++++++ .../nginx/config-dev/sites-enabled/iris.conf | 32 +++ .../docker/nginx/with-sormas-dev.Dockerfile | 4 + .../eps/settings/dev/directory/.gitignore | 1 + .../dev/roles/demo-app/001_default.yml | 44 ++++ .../settings/dev/roles/hd-1/001_default.yml | 40 ++++ .../settings/dev/roles/ls-1/001_default.yml | 35 +++ .../dev/roles/private-proxy-1/001_default.yml | 19 ++ .../roles/private-proxy-eps-1/001_default.yml | 43 ++++ .../dev/roles/public-proxy-1/001_default.yml | 20 ++ .../roles/public-proxy-eps-1/001_default.yml | 48 ++++ .../settings/dev/roles/sd-1/001_default.yml | 9 + .../iris-gateway/templates/_helpers.tpl | 24 +- .../templates/location/service.yaml | 16 -- .../templates/locations-eps/configmap.yaml | 44 ++++ .../templates/locations-eps/deployment.yaml | 46 ++++ .../templates/locations-eps/service.yaml | 16 ++ .../{location => locations}/deployment.yaml | 12 +- .../templates/locations/service.yaml | 14 ++ .../templates/postgres/deployment.yaml | 43 ---- .../iris-gateway/templates/postgres/pvc.yaml | 15 -- .../templates/postgres/secret.yaml | 11 - .../templates/postgres/service.yaml | 16 -- .../templates/public-server/deployment.yaml | 31 --- .../templates/public-server/service.yaml | 16 -- infrastructure/iris-gateway/values.yaml | 27 ++- iris-client-eps/README.md | 78 +++++++ iris-client-eps/docker-compose.yml | 101 ++++++++ iris-client-eps/private-proxy-db/.gitignore | 1 + iris-client-eps/pub-proxy-db/.gitignore | 1 + .../settings/dev/directory/.gitignore | 3 + .../settings/dev/directory/services.json | 150 ++++++++++++ .../dev/roles/demo-app/001_default.yml | 41 ++++ .../settings/dev/roles/hd-1/001_default.yml | 37 +++ .../settings/dev/roles/ls-1/001_default.yml | 29 +++ .../dev/roles/private-proxy-1/001_default.yml | 16 ++ .../roles/private-proxy-eps-1/001_default.yml | 38 +++ .../dev/roles/public-proxy-1/001_default.yml | 21 ++ .../roles/public-proxy-eps-1/001_default.yml | 48 ++++ .../.mvn/wrapper/MavenWrapperDownloader.java | 174 +++++++------- iris-location-service/pom.xml | 65 +++--- .../jsonrpc/JsonRpcClientDto.java | 14 ++ .../location_service/jsonrpc/LocationRPC.java | 14 +- .../jsonrpc/LocationRPCImpl.java | 21 +- .../security/AllowedProviders.java | 39 ---- .../security/ProviderIdAuthFilter.java | 25 -- .../security/ProviderIdConfig.java | 57 ----- .../service/LocationService.java | 11 +- .../ConstraintViolationExceptionHandler.java | 21 -- .../web/LocationIndexController.java | 92 -------- .../src/main/resources/application.properties | 10 +- .../LocationRepositoryTest.java | 40 ++-- .../web/LocationIndexControllerTest.java | 65 ------ 92 files changed, 2220 insertions(+), 1546 deletions(-) delete mode 100644 .github/workflows/location-service_develop.yml delete mode 100644 .github/workflows/public-server_develop.yml create mode 100644 .github/workflows/push-to-develop.yml create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/config/EPSClientProperties.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/config/RPCClientConfig.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPC.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPCImpl.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/JsonRpcClientDto.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Decryptor.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Encryptor.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListDecryptor.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListEncryptor.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/EPSDataSubmissionClient.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/dto/DataSubmissionDto.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/exceptions/IRISDataSubmissionException.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/web/client/DataSubmissionClient.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/SearchIndexClient.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/EPSSearchIndexClient.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/DeleteLocationDTO.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/JsonRPCStringResult.java create mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/UpdateLocationsDTO.java delete mode 100644 demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClient.java delete mode 100644 demo-checkin-app/src/main/resources/keystore.p12 delete mode 100644 demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionTest.java delete mode 100644 demo-checkin-app/src/test/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClientTest.java delete mode 100644 infrastructure/DEPLOYMENT.adoc create mode 100644 infrastructure/docker-compose-all.dev.yml create mode 100644 infrastructure/docker/nginx/config-dev/nginx.conf create mode 100644 infrastructure/docker/nginx/config-dev/sites-enabled-sormas/sormas.conf create mode 100644 infrastructure/docker/nginx/config-dev/sites-enabled/api.conf create mode 100644 infrastructure/docker/nginx/config-dev/sites-enabled/iris.conf create mode 100644 infrastructure/docker/nginx/with-sormas-dev.Dockerfile create mode 100644 infrastructure/eps/settings/dev/directory/.gitignore create mode 100644 infrastructure/eps/settings/dev/roles/demo-app/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/hd-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/ls-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/private-proxy-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/private-proxy-eps-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/public-proxy-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/public-proxy-eps-1/001_default.yml create mode 100644 infrastructure/eps/settings/dev/roles/sd-1/001_default.yml delete mode 100644 infrastructure/iris-gateway/templates/location/service.yaml create mode 100644 infrastructure/iris-gateway/templates/locations-eps/configmap.yaml create mode 100644 infrastructure/iris-gateway/templates/locations-eps/deployment.yaml create mode 100644 infrastructure/iris-gateway/templates/locations-eps/service.yaml rename infrastructure/iris-gateway/templates/{location => locations}/deployment.yaml (52%) create mode 100644 infrastructure/iris-gateway/templates/locations/service.yaml delete mode 100644 infrastructure/iris-gateway/templates/postgres/deployment.yaml delete mode 100644 infrastructure/iris-gateway/templates/postgres/pvc.yaml delete mode 100644 infrastructure/iris-gateway/templates/postgres/secret.yaml delete mode 100644 infrastructure/iris-gateway/templates/postgres/service.yaml delete mode 100644 infrastructure/iris-gateway/templates/public-server/deployment.yaml delete mode 100644 infrastructure/iris-gateway/templates/public-server/service.yaml create mode 100644 iris-client-eps/README.md create mode 100644 iris-client-eps/docker-compose.yml create mode 100644 iris-client-eps/private-proxy-db/.gitignore create mode 100644 iris-client-eps/pub-proxy-db/.gitignore create mode 100644 iris-client-eps/settings/dev/directory/.gitignore create mode 100644 iris-client-eps/settings/dev/directory/services.json create mode 100644 iris-client-eps/settings/dev/roles/demo-app/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/hd-1/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/ls-1/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/private-proxy-1/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/private-proxy-eps-1/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/public-proxy-1/001_default.yml create mode 100644 iris-client-eps/settings/dev/roles/public-proxy-eps-1/001_default.yml create mode 100644 iris-location-service/src/main/java/iris/location_service/jsonrpc/JsonRpcClientDto.java delete mode 100644 iris-location-service/src/main/java/iris/location_service/security/AllowedProviders.java delete mode 100644 iris-location-service/src/main/java/iris/location_service/security/ProviderIdAuthFilter.java delete mode 100644 iris-location-service/src/main/java/iris/location_service/security/ProviderIdConfig.java delete mode 100644 iris-location-service/src/main/java/iris/location_service/web/ConstraintViolationExceptionHandler.java delete mode 100644 iris-location-service/src/main/java/iris/location_service/web/LocationIndexController.java delete mode 100644 iris-location-service/src/test/java/iris/location_service/web/LocationIndexControllerTest.java diff --git a/.github/workflows/location-service_develop.yml b/.github/workflows/location-service_develop.yml deleted file mode 100644 index a892a0ce..00000000 --- a/.github/workflows/location-service_develop.yml +++ /dev/null @@ -1,37 +0,0 @@ -# https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image - -name: Build and package image for iris-location-service and deploy it to docker.io - -on: - push: - branches: - - main - paths: - - iris-location-service/** - - .github/workflows/location-service_develop.yml - -defaults: - run: - shell: bash - -jobs: - build: - runs-on: ubuntu-20.04 - - steps: - - name: Checkout code - uses: actions/checkout@v2.3.4 - - - name: Cache local Maven repository - uses: actions/cache@v2.1.5 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: build, package and publish the image - run: mvn -B spring-boot:build-image -am -pl iris-location-service -Dspring-boot.build-image.publish=true - env: - DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} - DOCKER_HUB_PW: ${{ secrets.DOCKER_HUB_PW }} diff --git a/.github/workflows/public-server_develop.yml b/.github/workflows/public-server_develop.yml deleted file mode 100644 index 466fa6e3..00000000 --- a/.github/workflows/public-server_develop.yml +++ /dev/null @@ -1,37 +0,0 @@ -# https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image - -name: Build and package image for iris-public-server and deploy it to docker.io - -on: - push: - branches: - - main - paths: - - iris-public-server/** - - .github/workflows/public-server_develop.yml - -defaults: - run: - shell: bash - -jobs: - build: - runs-on: ubuntu-20.04 - - steps: - - name: Checkout code - uses: actions/checkout@v2.3.4 - - - name: Cache local Maven repository - uses: actions/cache@v2.1.5 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: build, package and publish the image - run: mvn -B spring-boot:build-image -am -pl iris-public-server -Dspring-boot.build-image.publish=true - env: - DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} - DOCKER_HUB_PW: ${{ secrets.DOCKER_HUB_PW }} diff --git a/.github/workflows/push-to-develop.yml b/.github/workflows/push-to-develop.yml new file mode 100644 index 00000000..ee8230b5 --- /dev/null +++ b/.github/workflows/push-to-develop.yml @@ -0,0 +1,60 @@ +name: Build, package and deploy (to test) all services on push to develop branch + +on: + push: + branches: + - develop + paths: + - iris-location-service/** + - .github/workflows/push-to-develop.yml + +jobs: + # https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image + build-location-service: + runs-on: ubuntu-20.04 + defaults: + run: + shell: bash + + steps: + - name: Checkout code + uses: actions/checkout@v2.3.4 + + - name: Cache local Maven repository + uses: actions/cache@v2.1.5 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: build, package and publish the image + run: > + mvn -B spring-boot:build-image -am -pl iris-location-service + -Dspring-boot.build-image.publish=true + -Dversion.tag="${{ github.sha }}" + env: + DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} + DOCKER_HUB_PW: ${{ secrets.DOCKER_HUB_PW }} + + deployment: + needs: build-location-service + runs-on: self-hosted + container: alpine/helm:3.5.4 + + steps: + - uses: actions/checkout@v1 + + - name: Prepare k8s config + run: > + rm -rf ~/.kube && + mkdir ~/.kube && + echo "${{ secrets.KUBECONFIG_TEST }}" > ~/.kube/config + + - name: Run helm deployment + run: > + helm upgrade --install + --namespace iris-gateway + --set environment=test + --set locations.tag="${{ github.sha }}" + iris-gateway ./infrastructure/iris-gateway diff --git a/demo-checkin-app/pom.xml b/demo-checkin-app/pom.xml index 0c685520..8b44dea7 100644 --- a/demo-checkin-app/pom.xml +++ b/demo-checkin-app/pom.xml @@ -1,106 +1,124 @@ - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.4.4 - - - iris-gateway - demo-checkin-app - 0.0.1-SNAPSHOT - Demo for Checkin Apps - - 11 - inoeg - ${project.version} - - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-devtools - runtime - true - - - org.projectlombok - lombok - true - - - org.apache.httpcomponents - httpclient - 4.5.12 - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-validation - - - org.bouncycastle - bcpkix-jdk15on - 1.58 - - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner - 2.2.7.RELEASE - test - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.4 + + + iris-gateway + demo-checkin-app + 0.0.1-SNAPSHOT + Demo for Checkin Apps + + 11 + inoeg + ${project.version} + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.projectlombok + lombok + true + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-validation + + + org.bouncycastle + bcpkix-jdk15on + 1.58 + + + org.springframework.cloud + spring-cloud-starter-contract-stub-runner + 2.2.7.RELEASE + test + - - ${project.artifactId}-${version.tag} - - - src/main/resources - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - ${docker.image.prefix}/${project.artifactId}:${version.tag} - - - docker - - - - - - ${env.DOCKER_HUB_USER} - ${env.DOCKER_HUB_PW} - - - - - - - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + com.github.briandilley.jsonrpc4j + jsonrpc4j + 1.6 + + + com.sun.xml.ws + jaxws-ri + 2.3.3 + pom + + + + + ${project.artifactId}-${version.tag} + + + src/main/resources + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + ${docker.image.prefix}/${project.artifactId}:${version.tag} + + + docker + + + + + + ${env.DOCKER_HUB_USER} + ${env.DOCKER_HUB_PW} + + + + + + + diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/IrisDemoCheckinAppApplication.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/IrisDemoCheckinAppApplication.java index 3562d8af..8bb54244 100644 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/IrisDemoCheckinAppApplication.java +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/IrisDemoCheckinAppApplication.java @@ -1,21 +1,23 @@ package iris.demo.checkin_app; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.ssl.SSLContextBuilder; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; +import iris.demo.checkin_app.datarequest.jsonrpc.DataRequestRPCImpl; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.Security; -@SpringBootApplication -public class IrisDemoCheckinAppApplication { +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.context.annotation.Bean; +import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplExporter; +@SpringBootApplication +@ConfigurationPropertiesScan +public class IrisDemoCheckinAppApplication { public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { Security.setProperty("crypto.policy", "unlimited"); @@ -23,4 +25,12 @@ public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithm } + @Bean + public static AutoJsonRpcServiceImplExporter autoJsonRpcServiceImplExporter() { + return new AutoJsonRpcServiceImplExporter(); + } + + @Autowired + public DataRequestRPCImpl locationRPC; + } diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/EPSClientProperties.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/EPSClientProperties.java new file mode 100644 index 00000000..bc905543 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/EPSClientProperties.java @@ -0,0 +1,21 @@ +package iris.demo.checkin_app.config; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; +import org.springframework.context.annotation.Configuration; + +import javax.validation.constraints.NotNull; + +@ConstructorBinding +@AllArgsConstructor +@ConfigurationProperties("iris") +@Getter +public class EPSClientProperties { + + private final @NotNull String locationServiceEndpoint; + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/RPCClientConfig.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/RPCClientConfig.java new file mode 100644 index 00000000..ef56d96a --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/config/RPCClientConfig.java @@ -0,0 +1,79 @@ +package iris.demo.checkin_app.config; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import java.net.MalformedURLException; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; +import org.springframework.context.annotation.Bean; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.googlecode.jsonrpc4j.JsonRpcHttpClient; + +@ConstructorBinding +@RequiredArgsConstructor +@ConfigurationProperties("eps-client") +@Getter +public class RPCClientConfig { + + private final @NonNull String clientUrl; + + @Bean + public JsonRpcHttpClient rpcClient() throws MalformedURLException, NoSuchAlgorithmException, KeyManagementException { + + ObjectMapper jacksonObjectMapper = new ObjectMapper(); + jacksonObjectMapper.registerModule(new JavaTimeModule()); + + JsonRpcHttpClient client = new JsonRpcHttpClient( + jacksonObjectMapper, + new URL(clientUrl), + new HashMap<>()); + + // Can be removed when we include the root certs + SSLContext sc = getAllCertsTrustedSSLContext(); + client.setSslContext(sc); + client.setHostNameVerifier(new NoopHostnameVerifier()); + + // This is SO! important + client.setContentType("application/json"); + + return client; + } + + private SSLContext getAllCertsTrustedSSLContext() throws NoSuchAlgorithmException, KeyManagementException { + TrustManager[] trustAllCerts = new TrustManager[] { + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted( + X509Certificate[] certs, String authType) {} + + public void checkServerTrusted( + X509Certificate[] certs, String authType) {} + } + }; + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + return sc; + } +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPC.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPC.java new file mode 100644 index 00000000..d0e6be32 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPC.java @@ -0,0 +1,17 @@ +package iris.demo.checkin_app.datarequest.jsonrpc; + +import iris.demo.checkin_app.datarequest.model.dto.LocationDataRequestDto; + +import javax.validation.Valid; + +import com.googlecode.jsonrpc4j.JsonRpcParam; +import com.googlecode.jsonrpc4j.JsonRpcService; + +@JsonRpcService("/data-request-rpc") +public interface DataRequestRPC { + + String createDataRequest( + @Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client, + @JsonRpcParam(value = "dataRequest") LocationDataRequestDto locationDataRequestDto); + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPCImpl.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPCImpl.java new file mode 100644 index 00000000..6535b699 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/DataRequestRPCImpl.java @@ -0,0 +1,34 @@ +package iris.demo.checkin_app.datarequest.jsonrpc; + +import iris.demo.checkin_app.datarequest.model.dto.LocationDataRequestDto; +import iris.demo.checkin_app.datasubmission.service.DataSubmissionService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.validation.constraints.NotNull; + +import org.springframework.stereotype.Service; + +import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl; + +@AutoJsonRpcServiceImpl +@AllArgsConstructor +@Slf4j +@Service +public class DataRequestRPCImpl implements DataRequestRPC { + + private final @NotNull DataSubmissionService dataSubmissionService; + + @Override + public String createDataRequest(JsonRpcClientDto client, LocationDataRequestDto locationDataRequestDto) { + try { + log.info("Setting HD endpoint to " + client.getName()); + locationDataRequestDto.setHdEndpoint(client.getName()); + dataSubmissionService.sendDataForRequest(locationDataRequestDto); + return "OK"; + } catch (Exception e) { + e.printStackTrace(); + return "ERROR: " + e.getMessage(); + } + } +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/JsonRpcClientDto.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/JsonRpcClientDto.java new file mode 100644 index 00000000..fe35086d --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/jsonrpc/JsonRpcClientDto.java @@ -0,0 +1,14 @@ +package iris.demo.checkin_app.datarequest.jsonrpc; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@RequiredArgsConstructor +public class JsonRpcClientDto { + + private @NotNull String name; + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/model/dto/LocationDataRequestDto.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/model/dto/LocationDataRequestDto.java index 39980966..c8e268ee 100644 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/model/dto/LocationDataRequestDto.java +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datarequest/model/dto/LocationDataRequestDto.java @@ -5,8 +5,12 @@ import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.UUID; + +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonFormat; @Data @NoArgsConstructor @@ -14,31 +18,22 @@ @Builder public class LocationDataRequestDto { - @NotNull - private String healthDepartment; - - @NotNull - private String keyOfHealthDepartment; - - @NotNull - private Instant start; + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") + private Instant start; - @NotNull - private Instant end; + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") + private Instant end; - private String requestDetails; + private String requestDetails; - @NotNull - private String submissionUri; + @NotNull + private UUID dataAuthorizationToken; - @NotNull - private String locationId; + @NotNull + private String locationId; - /** - * Reference id of the given key. - * This reference must be included in the submission in order to identify the - * correct private key for decryption at the health department. - */ - private String keyReference; + private String hdEndpoint; } diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Decryptor.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Decryptor.java deleted file mode 100644 index 9d43d7d2..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Decryptor.java +++ /dev/null @@ -1,5 +0,0 @@ -package iris.demo.checkin_app.datasubmission.encryption; - -public interface Decryptor { - public String decrypt(); -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Encryptor.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Encryptor.java deleted file mode 100644 index 069f568b..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/Encryptor.java +++ /dev/null @@ -1,7 +0,0 @@ -package iris.demo.checkin_app.datasubmission.encryption; - -public interface Encryptor { - - String encrypt(); - -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListDecryptor.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListDecryptor.java deleted file mode 100644 index e3045f61..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListDecryptor.java +++ /dev/null @@ -1,92 +0,0 @@ -package iris.demo.checkin_app.datasubmission.encryption; - -import lombok.extern.slf4j.Slf4j; - -import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Arrays; -import java.util.Base64; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -@Slf4j -public class GuestListDecryptor implements Decryptor { - - private final String encryptedSecretKeyB64; - - private SecretKey secretKey; - - private byte[] iv; - - private final String cipherText; - - private String clearText; - - private String privateKey; - - public GuestListDecryptor(String encryptedSecretKeyB64, String privateKey, String cipherText) { - this.encryptedSecretKeyB64 = encryptedSecretKeyB64; - this.cipherText = cipherText; - this.privateKey = privateKey.replaceAll(System.lineSeparator(), ""); - this.privateKey = privateKey.replaceAll("\\n", ""); - } - - public String decrypt() { - - log.info("Decrypting..."); - try { - decryptEncryptedSecretKeyB64(); - - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - - byte[] cipherBytes = Base64.getDecoder().decode(cipherText); - - iv = Arrays.copyOfRange(cipherBytes, 0, 16); - - cipherBytes = Arrays.copyOfRange(cipherBytes, 16, cipherBytes.length); - - IvParameterSpec ivSpec = new IvParameterSpec(iv); - cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec); - clearText = new String(cipher.doFinal(cipherBytes), StandardCharsets.UTF_8); - - return clearText; - - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - private void decryptEncryptedSecretKeyB64() { - try { - PrivateKey key = getPrivateKey(); - Cipher decoder = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); - decoder.init(Cipher.DECRYPT_MODE, key); - byte[] decodedKey = decoder.doFinal(Base64.getDecoder().decode(encryptedSecretKeyB64)); - secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private PrivateKey getPrivateKey() { - try { - byte[] encoded = Base64.getDecoder().decode(privateKey); - - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); - return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); - - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListEncryptor.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListEncryptor.java deleted file mode 100644 index a2a2e2cf..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/encryption/GuestListEncryptor.java +++ /dev/null @@ -1,96 +0,0 @@ -package iris.demo.checkin_app.datasubmission.encryption; - -import iris.demo.checkin_app.datasubmission.model.dto.GuestListDto; -import lombok.*; -import lombok.extern.slf4j.Slf4j; - -import javax.crypto.*; -import javax.crypto.spec.IvParameterSpec; - -import java.nio.charset.StandardCharsets; -import java.security.*; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; - -@Builder -@Slf4j -public class GuestListEncryptor implements Encryptor { - - private final GuestListDto guestList; - - private final String givenPublicKey; - - private SecretKey secretKey; - - private SecretKey getAESKey() throws NoSuchAlgorithmException { - KeyGenerator keyGen = KeyGenerator.getInstance("AES"); - keyGen.init(256, SecureRandom.getInstanceStrong()); - return keyGen.generateKey(); - } - - private byte[] generateIv() { - byte[] iv = new byte[16]; - new SecureRandom().nextBytes(iv); - return iv; - } - - private PublicKey getPublicKey(String givenPublicKey) { - try { - KeyFactory kf = KeyFactory.getInstance("RSA"); - - X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(givenPublicKey.replaceAll("\\n", ""))); - - return (RSAPublicKey) kf.generatePublic(keySpecX509); - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - @Override - public String encrypt() { - - log.info("Encrypting..."); - try { - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - - secretKey = getAESKey(); - - byte[] iv = generateIv(); - IvParameterSpec ivSpec = new IvParameterSpec(iv); - - cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); - byte[] cipherText = cipher.doFinal(guestList.asJson().getBytes(StandardCharsets.UTF_8)); - - return Base64.getEncoder() - .encodeToString(combineIVAndData(iv, cipherText)); - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - public String getSecretKeyBase64() { - - try { - PublicKey key = getPublicKey(givenPublicKey); - Cipher encoder = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); - encoder.init(Cipher.ENCRYPT_MODE, key); - byte[] cipherText = encoder.doFinal(secretKey.getEncoded()); - return Base64.getEncoder().encodeToString(cipherText); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - private byte[] combineIVAndData(byte[] iv, byte[] encryptedData) { - byte[] destination = new byte[iv.length + encryptedData.length]; - System.arraycopy(iv, 0, destination, 0, iv.length); - System.arraycopy(encryptedData, 0, destination, iv.length, encryptedData.length); - return destination; - } -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/EPSDataSubmissionClient.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/EPSDataSubmissionClient.java new file mode 100644 index 00000000..aa8e8277 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/EPSDataSubmissionClient.java @@ -0,0 +1,31 @@ +package iris.demo.checkin_app.datasubmission.eps; + +import iris.demo.checkin_app.datasubmission.eps.dto.DataSubmissionDto; +import iris.demo.checkin_app.datasubmission.exceptions.IRISDataSubmissionException; +import iris.demo.checkin_app.searchindex.eps.dto.JsonRPCStringResult; +import lombok.AllArgsConstructor; + +import org.springframework.stereotype.Service; + +import com.googlecode.jsonrpc4j.JsonRpcHttpClient; + +@Service +@AllArgsConstructor +public class EPSDataSubmissionClient { + + private final JsonRpcHttpClient rpcClient; + + private final static String TEMPORARY_PROVIDER_ID = "demo-app"; + + public void postDataSubmissionGuests(DataSubmissionDto dataSubmissionDto, String hdEndpoint) + throws IRISDataSubmissionException { + + try { + var methodName = hdEndpoint + ".submitGuestList"; + rpcClient.invoke(methodName, dataSubmissionDto, JsonRPCStringResult.class); + } catch (Throwable t) { + throw new IRISDataSubmissionException(t); + } + + } +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/dto/DataSubmissionDto.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/dto/DataSubmissionDto.java new file mode 100644 index 00000000..6c7385c6 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/eps/dto/DataSubmissionDto.java @@ -0,0 +1,18 @@ +package iris.demo.checkin_app.datasubmission.eps.dto; + +import iris.demo.checkin_app.datasubmission.model.dto.GuestListDto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.UUID; + +@Data +@AllArgsConstructor +@Builder +public class DataSubmissionDto { + + private UUID dataAuthorizationToken; + private GuestListDto guestList; + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/exceptions/IRISDataSubmissionException.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/exceptions/IRISDataSubmissionException.java new file mode 100644 index 00000000..7bc20bf8 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/exceptions/IRISDataSubmissionException.java @@ -0,0 +1,8 @@ +package iris.demo.checkin_app.datasubmission.exceptions; + +public class IRISDataSubmissionException extends Exception { + + public IRISDataSubmissionException(Throwable cause) { + super(cause); + } +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionService.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionService.java index f1fac47a..3a3139ea 100644 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionService.java +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionService.java @@ -1,14 +1,15 @@ package iris.demo.checkin_app.datasubmission.service; +import iris.demo.checkin_app.config.EPSClientProperties; import iris.demo.checkin_app.datarequest.model.dto.LocationDataRequestDto; import iris.demo.checkin_app.datasubmission.bootstrap.DataProviderLoader; import iris.demo.checkin_app.datasubmission.bootstrap.GuestLoader; -import iris.demo.checkin_app.datasubmission.encryption.GuestListEncryptor; +import iris.demo.checkin_app.datasubmission.eps.EPSDataSubmissionClient; +import iris.demo.checkin_app.datasubmission.eps.dto.DataSubmissionDto; import iris.demo.checkin_app.datasubmission.model.dto.DataProviderDto; import iris.demo.checkin_app.datasubmission.model.dto.GuestDto; import iris.demo.checkin_app.datasubmission.model.dto.GuestListDto; -import iris.demo.checkin_app.datasubmission.model.dto.GuestSubmissionDto; -import iris.demo.checkin_app.datasubmission.web.client.DataSubmissionClient; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.time.Instant; @@ -17,25 +18,26 @@ import java.util.Optional; import java.util.Random; -import org.springframework.beans.factory.annotation.Autowired; +import javax.validation.constraints.NotNull; + import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @Slf4j @Service @Component +@RequiredArgsConstructor public class DataSubmissionService { - @Autowired - private GuestLoader guestLoader; + private final @NotNull GuestLoader guestLoader; + + private final @NotNull DataProviderLoader dataProviderLoader; - @Autowired - private DataProviderLoader dataProviderLoader; + private final @NotNull EPSClientProperties epsClientProperties; - @Autowired - private DataSubmissionClient dataSubmissionClient; + private final @NotNull EPSDataSubmissionClient dataSubmissionClient; - private Random random = new Random(); + private final Random random = new Random(); public void sendDataForRequest(LocationDataRequestDto locationDataRequest) throws Exception { @@ -44,7 +46,7 @@ public void sendDataForRequest(LocationDataRequestDto locationDataRequest) throw var start = Optional.ofNullable(locationDataRequest.getStart()) .map(it -> it.minus(random.nextInt(100), ChronoUnit.MINUTES)); var end = Optional.ofNullable(locationDataRequest.getEnd()) - .map(it->it.plus(random.nextInt(100), ChronoUnit.MINUTES)); + .map(it -> it.plus(random.nextInt(100), ChronoUnit.MINUTES)); // 2 of 3 should have plausible values for (int i = 0; i < 2; i++) { @@ -54,24 +56,14 @@ public void sendDataForRequest(LocationDataRequestDto locationDataRequest) throw } DataProviderDto dataProvider = dataProviderLoader.getDataProvider(); - GuestListDto guestList = GuestListDto.builder(). - guests(guests). - additionalInformation(""). - startDate(Instant.now()). - endDate(Instant.now().plus(6, ChronoUnit.HOURS)). - dataProvider(dataProvider). - build(); - GuestListEncryptor encryptor = GuestListEncryptor.builder(). - guestList(guestList). - givenPublicKey(locationDataRequest.getKeyOfHealthDepartment()). - build(); - - GuestSubmissionDto guestSubmission = GuestSubmissionDto.builder(). - encryptedData(encryptor.encrypt()). - keyReference(locationDataRequest.getKeyReference()). - secret(encryptor.getSecretKeyBase64()). - build(); - - dataSubmissionClient.postDataSubmissionGuests(guestSubmission, locationDataRequest.getSubmissionUri()); + + GuestListDto guestList = GuestListDto.builder().guests(guests).additionalInformation("").startDate(Instant.now()) + .endDate(Instant.now().plus(6, ChronoUnit.HOURS)).dataProvider(dataProvider).build(); + + DataSubmissionDto dataSubmissionDto = DataSubmissionDto.builder() + .dataAuthorizationToken(locationDataRequest.getDataAuthorizationToken()) + .guestList(guestList).build(); + + dataSubmissionClient.postDataSubmissionGuests(dataSubmissionDto, locationDataRequest.getHdEndpoint()); } } diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/web/client/DataSubmissionClient.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/web/client/DataSubmissionClient.java deleted file mode 100644 index fb59dc90..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/datasubmission/web/client/DataSubmissionClient.java +++ /dev/null @@ -1,41 +0,0 @@ -package iris.demo.checkin_app.datasubmission.web.client; - -import iris.demo.checkin_app.datasubmission.model.dto.GuestSubmissionDto; -import iris.demo.checkin_app.searchindex.model.LocationsDto; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; - -@Component -@Slf4j -public class DataSubmissionClient { - - private final RestTemplate restTemplate; - - public DataSubmissionClient(RestTemplateBuilder restTemplateBuilder) { - this.restTemplate = restTemplateBuilder.build(); - } - - public void postDataSubmissionGuests(GuestSubmissionDto guestSubmission, String submissionUrl) throws Exception { - HttpHeaders headers = new HttpHeaders(); - headers.set(HttpHeaders.CONTENT_TYPE, "application/json"); - try { - HttpEntity request = - new HttpEntity(guestSubmission, headers); - - String personResultAsJsonStr = - restTemplate.postForObject(submissionUrl, request, String.class); - } catch (HttpClientErrorException e) { - log.error("Request failed. Status code: " + e.getStatusCode().toString()); - log.error("Response: "+e.getResponseBodyAsString()); - throw new Exception("Request to Public API failed"); - } - - } -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/SearchIndexClient.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/SearchIndexClient.java new file mode 100644 index 00000000..62b9f2fb --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/SearchIndexClient.java @@ -0,0 +1,18 @@ +package iris.demo.checkin_app.searchindex; + +import iris.demo.checkin_app.datasubmission.exceptions.IRISDataSubmissionException; +import iris.demo.checkin_app.searchindex.model.LocationDto; +import iris.demo.checkin_app.searchindex.model.LocationsDto; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; + +public interface SearchIndexClient { + + public void updateLocations(LocationsDto locationsDto) throws IRISDataSubmissionException; + + public void deleteLocation(LocationDto locationDto) throws IRISDataSubmissionException; + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/EPSSearchIndexClient.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/EPSSearchIndexClient.java new file mode 100644 index 00000000..f8a4a0f1 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/EPSSearchIndexClient.java @@ -0,0 +1,55 @@ +package iris.demo.checkin_app.searchindex.eps; + +import iris.demo.checkin_app.config.EPSClientProperties; +import iris.demo.checkin_app.datasubmission.exceptions.IRISDataSubmissionException; +import iris.demo.checkin_app.searchindex.SearchIndexClient; +import iris.demo.checkin_app.searchindex.eps.dto.DeleteLocationDTO; +import iris.demo.checkin_app.searchindex.eps.dto.JsonRPCStringResult; +import iris.demo.checkin_app.searchindex.eps.dto.UpdateLocationsDTO; +import iris.demo.checkin_app.searchindex.model.LocationDto; +import iris.demo.checkin_app.searchindex.model.LocationsDto; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +import com.googlecode.jsonrpc4j.JsonRpcHttpClient; + +@Service +@AllArgsConstructor +@Primary +@Slf4j +public class EPSSearchIndexClient implements SearchIndexClient { + + private final JsonRpcHttpClient rpcClient; + private final EPSClientProperties epsClientProperties; + + @Override + public void updateLocations(LocationsDto locationsDto) throws IRISDataSubmissionException { + UpdateLocationsDTO updateLocationsDTO = UpdateLocationsDTO.builder() + .locations(locationsDto.getLocations()) + .build(); + var methodName = epsClientProperties.getLocationServiceEndpoint() + ".postLocationsToSearchIndex"; + try { + log.info( + "Sent request with response " + rpcClient.invoke(methodName, updateLocationsDTO, JsonRPCStringResult.class)); + } catch (Throwable t) { + throw new IRISDataSubmissionException(t); + } + } + + @Override + public void deleteLocation(LocationDto locationDto) throws IRISDataSubmissionException { + DeleteLocationDTO deleteLocationDTO = DeleteLocationDTO.builder() + .locationId(locationDto.getId().toString()) + .build(); + var methodName = epsClientProperties.getLocationServiceEndpoint() + ".deleteLocationFromSearchIndex"; + try { + log.info( + "Sent request with response " + rpcClient.invoke(methodName, deleteLocationDTO, JsonRPCStringResult.class)); + } catch (Throwable t) { + throw new IRISDataSubmissionException(t); + } + } +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/DeleteLocationDTO.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/DeleteLocationDTO.java new file mode 100644 index 00000000..e3dc7f7c --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/DeleteLocationDTO.java @@ -0,0 +1,13 @@ +package iris.demo.checkin_app.searchindex.eps.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@AllArgsConstructor +@Builder +public class DeleteLocationDTO { + + private String locationId; +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/JsonRPCStringResult.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/JsonRPCStringResult.java new file mode 100644 index 00000000..10ccd1a6 --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/JsonRPCStringResult.java @@ -0,0 +1,16 @@ +package iris.demo.checkin_app.searchindex.eps.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; + +@Data +@AllArgsConstructor +@RequiredArgsConstructor +public class JsonRPCStringResult { + + @JsonProperty("_") + private String status; + +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/UpdateLocationsDTO.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/UpdateLocationsDTO.java new file mode 100644 index 00000000..7656fc4d --- /dev/null +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/eps/dto/UpdateLocationsDTO.java @@ -0,0 +1,16 @@ +package iris.demo.checkin_app.searchindex.eps.dto; + +import iris.demo.checkin_app.searchindex.model.LocationDto; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +@Builder +public class UpdateLocationsDTO { + + private List locations; +} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClient.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClient.java deleted file mode 100644 index f3fffeae..00000000 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClient.java +++ /dev/null @@ -1,67 +0,0 @@ -package iris.demo.checkin_app.searchindex.web.client; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; - -import java.util.List; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.springframework.http.MediaType.APPLICATION_JSON; - -import iris.demo.checkin_app.searchindex.model.LocationDto; -import iris.demo.checkin_app.searchindex.model.LocationsDto; - -@ConfigurationProperties(prefix = "iris.public-api", ignoreUnknownFields = false) -@Component -@Slf4j -public class SearchIndexClient { - - private final static String TEMPORARY_PROVIDER_ID = "f002f370-bd54-4325-ad91-1aff3bf730a5"; - - public final String LOCATIONS_PATH = "/search-index/locations"; - private final RestTemplate restTemplate; - private String apihost; - - public SearchIndexClient(RestTemplateBuilder restTemplateBuilder) { - this.restTemplate = restTemplateBuilder.build(); - } - - public void updateLocations(LocationsDto locationsDto) { - var headers = new HttpHeaders(); - headers.add("x-provider-id", TEMPORARY_PROVIDER_ID); - HttpEntity requestUpdate = new HttpEntity(locationsDto, headers); - try { - ResponseEntity response = restTemplate.exchange(apihost + LOCATIONS_PATH, HttpMethod.PUT, requestUpdate, String.class); - log.info(response.toString()); - } catch (HttpClientErrorException e) { - log.error("Request failed. Status code: " + e.getStatusCode().toString()); - log.error("Response: "+e.getResponseBodyAsString()); - } - - } - - public void deleteLocation(LocationDto locationDto) { - var headers = new HttpHeaders(); - headers.add("x-provider-id", TEMPORARY_PROVIDER_ID); - HttpEntity requestDelete = new HttpEntity(null, headers); - try { - ResponseEntity response = restTemplate.exchange(apihost + LOCATIONS_PATH + '/' + locationDto.getId(), HttpMethod.DELETE, requestDelete, String.class); - log.info(response.toString()); - } catch (HttpClientErrorException e) { - log.error("Request failed. Status code: " + e.getStatusCode().toString()); - } - } - - public void setApihost(String apihost) { - this.apihost = apihost; - } -} diff --git a/demo-checkin-app/src/main/java/iris/demo/checkin_app/startup/LocationUpdater.java b/demo-checkin-app/src/main/java/iris/demo/checkin_app/startup/LocationUpdater.java index b5a89a8a..91477549 100644 --- a/demo-checkin-app/src/main/java/iris/demo/checkin_app/startup/LocationUpdater.java +++ b/demo-checkin-app/src/main/java/iris/demo/checkin_app/startup/LocationUpdater.java @@ -1,8 +1,9 @@ package iris.demo.checkin_app.startup; +import iris.demo.checkin_app.datasubmission.exceptions.IRISDataSubmissionException; +import iris.demo.checkin_app.searchindex.SearchIndexClient; import iris.demo.checkin_app.searchindex.bootstrap.LocationsLoader; import iris.demo.checkin_app.searchindex.model.LocationsDto; -import iris.demo.checkin_app.searchindex.web.client.SearchIndexClient; import lombok.extern.slf4j.Slf4j; import javax.annotation.PostConstruct; @@ -28,9 +29,17 @@ public void init() { LocationsDto locations = locationsLoader.getDemoLocations(); log.info(String.format("Updating %d locations", locations.getCount())); - searchIndexClient.updateLocations(locations); + try { + searchIndexClient.updateLocations(locations); + } catch (IRISDataSubmissionException e) { + e.printStackTrace(); + } log.info(String.format("Delete location %s", locations.getLocationByIndex(1).getName())); - searchIndexClient.deleteLocation(locations.getLocationByIndex(1)); + try { + searchIndexClient.deleteLocation(locations.getLocationByIndex(1)); + } catch (IRISDataSubmissionException e) { + e.printStackTrace(); + } } } diff --git a/demo-checkin-app/src/main/resources/application.properties b/demo-checkin-app/src/main/resources/application.properties index 38163c35..175d8675 100644 --- a/demo-checkin-app/src/main/resources/application.properties +++ b/demo-checkin-app/src/main/resources/application.properties @@ -1,14 +1,6 @@ -iris.public-api.apihost = http://localhost:8080 - +iris.public-api.apihost=http://localhost:8080 server.port=8091 - -server.ssl.key-store-type=PKCS12 -server.ssl.key-store=classpath:keystore.p12 -server.ssl.key-store-password=irisapp -server.ssl.key-alias=demo-checkin-app - logging.level.org.apache.http=INFO -spring.output.ansi.enabled=ALWAYS - spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false - +eps-client.client-url=https://localhost:5554/jsonrpc +iris.location-service-endpoint=ls-1 diff --git a/demo-checkin-app/src/main/resources/keystore.p12 b/demo-checkin-app/src/main/resources/keystore.p12 deleted file mode 100644 index 7fd243e84e321e07d70383169af9a3df1727d2d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2627 zcmY+Eby(Al7RP@qfDIYlmj)@3O5vdd3{gVF8JByXd*AnY|2WS%=leb1^XCUihND3&U?ds#jTNRGV;Xb7$->5x zPll~S$gtHTc?n5|hW^8X-hz;!UPrRqQ8}}6{4aG3&H~COLzqZ1P-C?S5Y;3+GDVw?Be$%Ne~$5yaXXbdI#RLsAw5J7THPTucDq8=TO@z6t}tP ziTblFqde*jT`+U7Me&fKPjTrpw6pYJ_Th?Ou(6@VC?6=7V(-&{E4EA15?S=d%~STYx2& z6&&G;vxg|N*<+1Muyt!{Po$qpp`i%Ak9@-?$nseZb-KsBL$bZJ-*xAP0s$Ci()d`w{4dp(e zYUyH<=cnHXTvi<*TPCy0)17(-{Lh_07ynCaQ7_^FMee0h2p$Gz$go*;0dT+;q4O=< zE{*1YGW5aR@*`Rl@v_sFwzo59R$ZPDvBN26DqFB`=S9}DMwo20p$zks=$80RR)q$v zLHX;&rXjai-qQO?&7elQmo*3fD@-cIWqHC__e;#xP)>0!wl3o4%N7He`wK^xq!yWQ8boZe}s zZRG6h7}<>o*nPtxY-Um?VVTTlzA^R&qu>(?tWtt^ZLyi2d#@uY?uu_R+7247ZVydg z~FGM$G+i8|Tgu0#Q8DnzB8v+VyAawSn%yH`3g#f%_%n05w8RCbY zXNF66Xkr2|#mqSI1(W`ucNnL z<6~@r@BU&PR`S+&yFdOCeH%w0_q#2U zBc_7rV1ekQ@B6pVTG1+${k>O;=S^Qc+b}Mn!}moLBCvrhX~=_j{3}1XeJwuivd5~g zot`O0W`v&}*7(?&`M%N6^-!b!SsBw*N!bb$-$8gq)R+jj(S{ntOnU^*uhH!=uH;qx zo&X+|uvF`kRCR{w9w^qmVgR|yt_zYZOl%*y!gYVrFm-g-p24$$zglFPMR0~VVwD(G zj3z*F>k}<1pXfBsCZ~8I`^$N;cZE^j&|)(oTK4m^Ypy&AADY?|W8m=kn?h5Y<&s-j zl@+?^Isb*rspFd}r#u+Hv}zJ>N>9#8HpdMnsM13oA;5 zw)*2=T~&N_#!B>G68x<7MWmYe9GDy8qWSDOHZdv2_G5QWYjzERntA=1x`&VQwl@RN zBQ2DwjA7ft7Fg-eN1ji**v*211Ua=O<3jNtM%NTq7tbp`T(ixQ)co41zkAId)$xK= zn<(@(K9v!&F_k;PuZTB74yzAvvhduAviEiiOvJtj$&nNMq|i;HMekrkFUZC@2mdb8 zYeZQg)&4>yj2|T@luVeCi=kF3w0KGilr8dJ`Le0C%!IZ`SdH z%!BQjG15&odTz%qC1A~>MIM*C;a=yFIWcBK(i@H<1oe^x9=n|ExupEBAMpOXv_{0Z zSe-Ac>gXR?jZdu>cfa6be7oIkT^syTY-u1&5r+DkXXyNB!f+(%RBD)copRZMvhi<; zur@UF_v9P1F_Ck67$-&BaT~h3?OJUL-i51E$?C4qKbFum2 zS@hsdkBPw=ObV$)b*d6GR?9z++8K0Qu*^vrkjiDGPGU7*JP^BeIh5ir?57@Q;SLm0 zaDq?bD=DX@Xzk#+op*<#{yGj`SWQtFrn%LgZz%lw_upGq0&tPdNWx0$)JeqE`KQ{| zborYyA`X#WpD|Z9Y(LVP7CD!UI2F|}w!rXD(Rii~-_9%%w4DMctUE4!urZ^`=KJUI zQREg6w-CL2;;6(GF^cyJOeRO6K+F9}qZ}e|Teo%hYZ~nv2jka`rHT4_Vic9U7yDAa z!)pm)>s&35LCw-q+EyNBeDKhmPP;cf6|V84IYC7|vuquLj7ywxycY{9l4&MR5u=Pg z)bzxw3iscwCowgP)pj|AaMzsbg-UNX?5Kucc-~q6^@-=BFQ#w=N)RuR!0r zE+>30x&QWt$vwfrgjJ(j4Px)xLiXN=`~pKw0MA`Zm*at-2)IiNz$>HtGU%68+?k1I$8IWwd3T7=rNtuXXuGNkB z(^P^qwKUH)Z>Zq5L;5+TyVXRTnnRAj9yO{`p^s{jJC#N_`Qt0mG~ diff --git a/demo-checkin-app/src/test/java/iris/demo/checkin_app/IrisAppApiDemoApplicationTests.java b/demo-checkin-app/src/test/java/iris/demo/checkin_app/IrisAppApiDemoApplicationTests.java index 2fab1e24..0da8c9ea 100644 --- a/demo-checkin-app/src/test/java/iris/demo/checkin_app/IrisAppApiDemoApplicationTests.java +++ b/demo-checkin-app/src/test/java/iris/demo/checkin_app/IrisAppApiDemoApplicationTests.java @@ -7,12 +7,4 @@ @IrisWireMockTest class IrisAppApiDemoApplicationTests { - public final String LOCATIONS_PATH = "/search-index/locations"; - - @Test - void contextLoads() { - stubFor(put(urlEqualTo(LOCATIONS_PATH)).willReturn(aResponse().withStatus(204))); - - stubFor(delete(urlEqualTo(LOCATIONS_PATH)).willReturn(aResponse().withStatus(200))); - } } diff --git a/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/bootstrap/GuestLoaderTest.java b/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/bootstrap/GuestLoaderTest.java index faa26235..60d50473 100644 --- a/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/bootstrap/GuestLoaderTest.java +++ b/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/bootstrap/GuestLoaderTest.java @@ -1,17 +1,10 @@ package iris.demo.checkin_app.datasubmission.bootstrap; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.fail; import iris.demo.checkin_app.IrisWebIntegrationTest; -import iris.demo.checkin_app.datasubmission.bootstrap.DataProviderLoader; -import iris.demo.checkin_app.datasubmission.bootstrap.GuestLoader; -import iris.demo.checkin_app.datasubmission.encryption.GuestListEncryptor; -import iris.demo.checkin_app.datasubmission.model.dto.DataProviderDto; import iris.demo.checkin_app.datasubmission.model.dto.GuestDto; -import iris.demo.checkin_app.datasubmission.model.dto.GuestListDto; -import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.List; import org.junit.jupiter.api.Test; @@ -21,46 +14,27 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - @IrisWebIntegrationTest class GuestLoaderTest { - @Autowired - private GuestLoader guestLoader; + @Autowired + private GuestLoader guestLoader; + + @Autowired + private DataProviderLoader dataProviderLoader; - @Autowired - private DataProviderLoader dataProviderLoader; + @Test + List getGuests() { - @Test - List getGuests() { - - List guests = guestLoader.getGuests(); + List guests = guestLoader.getGuests(); - ObjectMapper objectMapper = new ObjectMapper(); - try { - objectMapper.registerModule(new JavaTimeModule()).writeValueAsString(guests); - } catch (JsonProcessingException e) { - fail(e); - } - return guests; - } + ObjectMapper objectMapper = new ObjectMapper(); + try { + objectMapper.registerModule(new JavaTimeModule()).writeValueAsString(guests); + } catch (JsonProcessingException e) { + fail(e); + } + return guests; + } - @Test - void encryptGuestList() { - List guests = getGuests(); - DataProviderDto dataProvider = dataProviderLoader.getDataProvider(); - GuestListDto guestList = GuestListDto.builder().guests(guests).additionalInformation("").startDate(Instant.now()).endDate(Instant.now().plus(6,ChronoUnit.HOURS)).dataProvider(dataProvider).build(); - GuestListEncryptor encryptor = GuestListEncryptor.builder().guestList(guestList).givenPublicKey("MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtcEUFlnEZfDkPO/mxXwC\n" + - "NmNTjwlndnp4fk521W+lPqhQ5f8lipp6A2tnIhPeLtvwVN6q68hzASaWxbhAypp2\n" + - "Bv77YRjoDacqx4gaq2eLGepb01CHNudGGvQGwhTYbfa8k13d2+z9+uN0/SrmofGc\n" + - "ZvhjZWnxALGcdZRUn3Trk3O6uYrBODVk6HmpFMZKqL9tKtrCxLG17Yr9ek53sFJI\n" + - "7YuEKxFbvF/20w5rcPYsmGgkoNjGhq2ajdGwe5UfcsGOEE/4tGScF2GMZM/Tjsh9\n" + - "W9wISn6/e1v/Hhj9I19UfgasbQrE9lC1D01i1kTCjpYQ+dWcnA1Ulj2evymPpq9H\n" + - "XVoKl8LmsfQ7n9w0vAfY2sPNW3H3wN/NlcuZslUTeTopZxtt4j7b7i+7Ik62t7Yr\n" + - "CrioWQOlsWYME2YChzDCp6IlBOjeZtA9IDh6V3hbnDlV4AZygoMWWUWb1WS3oFNf\n" + - "vaJfolxZRZXDUrsrQYpJPUZ8BexE0OPEdNNS8KCa9ANbhgO3xvSTSsPpbE7P346k\n" + - "zyTCQxyJM66FLGu7vmGyt1sGiUBXFQCVYbSFNT3opke70f9/rYyzZoVA4ZBbAK7F\n" + - "azMTNzUZzt9EICWupkdrDEcyuFQ3Q/9a8Bp14zAciIAujpWNMaeO9zi57W9V0Vd4\n" + - "LyPpQIplL03J5EtG6FLHRWECAwEAAQ==").build(); - } } diff --git a/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionTest.java b/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionTest.java deleted file mode 100644 index 498ab47f..00000000 --- a/demo-checkin-app/src/test/java/iris/demo/checkin_app/datasubmission/service/DataSubmissionTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package iris.demo.checkin_app.datasubmission.service; - - -import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static org.junit.jupiter.api.Assertions.*; - -import iris.demo.checkin_app.IrisWireMockTest; -import iris.demo.checkin_app.datarequest.model.dto.LocationDataRequestDto; -import iris.demo.checkin_app.datasubmission.bootstrap.DataProviderLoader; -import iris.demo.checkin_app.datasubmission.bootstrap.GuestLoader; -import iris.demo.checkin_app.datasubmission.encryption.GuestListDecryptor; -import iris.demo.checkin_app.datasubmission.encryption.GuestListEncryptor; -import iris.demo.checkin_app.datasubmission.model.dto.DataProviderDto; -import iris.demo.checkin_app.datasubmission.model.dto.GuestDto; -import iris.demo.checkin_app.datasubmission.model.dto.GuestListDto; -import iris.demo.checkin_app.datasubmission.service.DataSubmissionService; -import lombok.extern.slf4j.Slf4j; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; - -@IrisWireMockTest -@Slf4j -class DataSubmissionTest { - - @Autowired - private DataSubmissionService dataSubmissionService; - - @Autowired - private GuestLoader guestLoader; - - @Autowired - private DataProviderLoader dataProviderLoader; - - @Value("${wiremock.server.https-port}") - private String port; - - final String publicKey = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtcEUFlnEZfDkPO/mxXwC\n" + - "NmNTjwlndnp4fk521W+lPqhQ5f8lipp6A2tnIhPeLtvwVN6q68hzASaWxbhAypp2\n" + - "Bv77YRjoDacqx4gaq2eLGepb01CHNudGGvQGwhTYbfa8k13d2+z9+uN0/SrmofGc\n" + - "ZvhjZWnxALGcdZRUn3Trk3O6uYrBODVk6HmpFMZKqL9tKtrCxLG17Yr9ek53sFJI\n" + - "7YuEKxFbvF/20w5rcPYsmGgkoNjGhq2ajdGwe5UfcsGOEE/4tGScF2GMZM/Tjsh9\n" + - "W9wISn6/e1v/Hhj9I19UfgasbQrE9lC1D01i1kTCjpYQ+dWcnA1Ulj2evymPpq9H\n" + - "XVoKl8LmsfQ7n9w0vAfY2sPNW3H3wN/NlcuZslUTeTopZxtt4j7b7i+7Ik62t7Yr\n" + - "CrioWQOlsWYME2YChzDCp6IlBOjeZtA9IDh6V3hbnDlV4AZygoMWWUWb1WS3oFNf\n" + - "vaJfolxZRZXDUrsrQYpJPUZ8BexE0OPEdNNS8KCa9ANbhgO3xvSTSsPpbE7P346k\n" + - "zyTCQxyJM66FLGu7vmGyt1sGiUBXFQCVYbSFNT3opke70f9/rYyzZoVA4ZBbAK7F\n" + - "azMTNzUZzt9EICWupkdrDEcyuFQ3Q/9a8Bp14zAciIAujpWNMaeO9zi57W9V0Vd4\n" + - "LyPpQIplL03J5EtG6FLHRWECAwEAAQ=="; - - final String privateKey = - "MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC1wRQWWcRl8OQ8\n" + - "7+bFfAI2Y1OPCWd2enh+TnbVb6U+qFDl/yWKmnoDa2ciE94u2/BU3qrryHMBJpbF\n" + - "uEDKmnYG/vthGOgNpyrHiBqrZ4sZ6lvTUIc250Ya9AbCFNht9ryTXd3b7P3643T9\n" + - "Kuah8Zxm+GNlafEAsZx1lFSfdOuTc7q5isE4NWToeakUxkqov20q2sLEsbXtiv16\n" + - "TnewUkjti4QrEVu8X/bTDmtw9iyYaCSg2MaGrZqN0bB7lR9ywY4QT/i0ZJwXYYxk\n" + - "z9OOyH1b3AhKfr97W/8eGP0jX1R+BqxtCsT2ULUPTWLWRMKOlhD51ZycDVSWPZ6/\n" + - "KY+mr0ddWgqXwuax9Duf3DS8B9jaw81bcffA382Vy5myVRN5OilnG23iPtvuL7si\n" + - "Tra3tisKuKhZA6WxZgwTZgKHMMKnoiUE6N5m0D0gOHpXeFucOVXgBnKCgxZZRZvV\n" + - "ZLegU1+9ol+iXFlFlcNSuytBikk9RnwF7ETQ48R001LwoJr0A1uGA7fG9JNKw+ls\n" + - "Ts/fjqTPJMJDHIkzroUsa7u+YbK3WwaJQFcVAJVhtIU1PeimR7vR/3+tjLNmhUDh\n" + - "kFsArsVrMxM3NRnO30QgJa6mR2sMRzK4VDdD/1rwGnXjMByIgC6OlY0xp473OLnt\n" + - "b1XRV3gvI+lAimUvTcnkS0boUsdFYQIDAQABAoICAD+KwPsPZxo8nY6wUH26XQum\n" + - "rg/Tudgx+O4vgFweLCc7sQy3puhOGVoYsnW3fHXlbqA9OIQ2D/7W/t8hC4XJenn3\n" + - "qurHSll7l/kqHCjQilEFHhVCkgMf1+KUbchsgT3whP0AVBAPSrvryXq5BOiZD5Tw\n" + - "Qc+yug8ECS8SLIOS3MkwLJexatu7zwt3fSVGLdPRGNliobUia/ggH34i8LU0D0r8\n" + - "+7gS2X+CDUi8QdO8PNsLjcKuBroO93mdVZXfDJ+SC5ioXMq0Yd3KvMqB3fSNI0Z6\n" + - "Jmvk5Ay8nPRoyBcVvPRSYPW+Th3PGX3AEE3YvCwdStINXDMydeAQqu8qGI6tuMTS\n" + - "2rq1tYMcy8z1GqNrUrV2F5U6VHDM1CsvMum+9hABOONqNbGlrtSuVFVpBhxRQMqB\n" + - "KsLIo9Z/gQxiHH2mDzqZF156EiHQn8Swa59oE/v0oabdCP8dcXxRe5e8FuXGM3Op\n" + - "K+8edav17ICSthz7g5E5hrBjO6RZc+8TT4d9z/zgvBlEtKlvspY8m6gRTQEKrCkE\n" + - "6e024Q4Z7gBYUBsc/op0iK4YEpMfrwp4uX29nfIs+w388/ByTCSeCq3/JgDootb7\n" + - "Lg+QGLRoZ1Jl+Js3+Q1aYbjz5i7WRR0g9o1Zd6SSRtxSvY6MWzSMVRdkF1ESzVSC\n" + - "ev+Gj4LpnPCHYjl6C74BAoIBAQDqkfRn7BV9I5C/J5xCdQ/C2bnC5guT1EW9lsB7\n" + - "o8aI3XYBpDuXiLx0ZHzXN6VwQaSP2v+eYDDphZXgo4ES03bwigsLU//EvRoKS+36\n" + - "3HXGFMs2Y09hdNO6MgPtosesZKu9OKSkyHa3twsBZYfLlcwpJNtCxbyCB29KP7e0\n" + - "AYhDdw2yVblZ46oRPfm7KBqeoPcLbW6DoWqdiBQBxGserv5xObB2Sqg7WsBlFAv0\n" + - "qjQX9rdAsGZ8zqYgTWA6UIJZ2DhOQLy1DFYdC7yVYWO7yRj5+F9bHLxUpd9oqC3A\n" + - "5FFDW1TtltYI5c3BfxN8kVEPddLmJSQi+DTsIk7x9W2STiajAoIBAQDGW+IZXhaK\n" + - "PA/RhmoSuqq6AzyoKvgklrhrWef++vjeP2BC+2VGbQAQsLSDWGWtRgzAhRTjaOh+\n" + - "aFLwLVQIVoMxZ5WPDaqW7HqO5JTj5QEraj+7gJViKRmIpLWregKEX/ceAYkK0cOn\n" + - "baND4znnz+ciy0HKnQdGSzpe5pZzfOB6m5kz6LA8smv4MMIp8e7c6vQna9497ipf\n" + - "sQC+4JVCulfOacdC4+XF63/432QFt3nuMSNqaINqv0+no/8UvrGnehMYQHs8YoQw\n" + - "CIlQiVBN6K8mzXBUSVZdnOSmJG52UIzv02ttCUsP5ID6spYXbhjWr6+6u4HtsYUv\n" + - "PiyKcxQt0pgrAoIBAFFNM1QNvMj52cKXfQ5/um3DvyHxUBP14BI9PQvdkQOBFtSs\n" + - "0sbL6t3AspB5xgqphdsigbSoDGv0FCWfJi6bQr9OaVOM0rqi/HKTLLHlVaDJNkHs\n" + - "m+fgcT449amY4PI8llXoWxCONq+obtUWFsIWcoPUNXboSFUdNJKckRR/73XKvuGP\n" + - "2sVwJlMBkxwuY0OV8OpyDHrtKKHfN2gBZ0tkReaCo0nsyHCCHOsrzpUHpTSlG5D9\n" + - "UxhxG51YlEDCBNwVGDbvMzjhRLuehMeV0NaWdeS2FH7k79W7BDsnB2yy9gONlVsg\n" + - "C6Fb3TvyypNDXsAoC2gfeW3xb45kuc4dTdQG6FcCggEBAISQrbeUaO3znALEmSlx\n" + - "NV5hgW1GYlZZoGCmUmTXJ/GoW1YImzOI7004Ozu4nSNDOIyFpGMjHpY0dJFtScbU\n" + - "wpMHDi3vzT1WR8Ytv8/aoYB5XqSaF7vlidoHch5qyTncxNN55TOk4uSHYmChgHaL\n" + - "PIbFXm/hqBXzeswnwQ7nu0JVsPq/HOFDwOK6+1h7Bs7/+zJJZdrvy8PuEHiAsWBK\n" + - "FxqtGO18T3iJnhoeecNUTpnAn1GjDYkO2FZKRNSBaUtrS02e8n11vbA4VETNsCyR\n" + - "QFVnYRYDeUPQ8gKTQHuz86zoF9hkKJUzenuRVLvN6a249nGOlRPc2wyquavBow/I\n" + - "uccCggEAI2Uac9KhvWtjrBo4s3A9IHdWnHN5oWRN2/WWHV3Sorwh2IJGmfv7c5lm\n" + - "Ui3BDtmGpd4zWNXHiQdSdvfQtuTK8Shgdpcs3ieY4sV72DnivV8wH7qElm9U7BW8\n" + - "4V94JZsu0ZVBoH8u8QEh1+XSrgVepIO6TKUaIZGrexP0A5d78ZnntLfOL7LN7nx/\n" + - "mWno//TNFHG0mzJncRhM1uGt38SpnEP7jqtQXCUeJ7cpfI+3nFP6dFYHm5PQPL59\n" + - "6yXy5jU1rEbkrAt5O4xxRZ9E7MJNyLWGfLRjY6xg9pyYhIaKIN3jqOQtvWx+jj0a\n" + - "s/u9sTZGcpOwd3Zdsmd/Fg+4MR8WTQ=="; - - - @Test - void sendDataForRequest() { - - String path = "/data-submissions/423576f4-9202-11eb-b5b7-00155da17da6/guests"; - var submissionUri = "https://localhost:" + port + path; - - stubFor(post(urlEqualTo(path)).willReturn(aResponse().withStatus(202))); - - try { - - LocationDataRequestDto locationDataRequest = LocationDataRequestDto.builder(). - keyOfHealthDepartment(publicKey). - keyReference("2470b56c-90b7-11eb-a8b3-0242ac130003"). - submissionUri(submissionUri). - start(Instant.now()). - build(); - - dataSubmissionService.sendDataForRequest(locationDataRequest); - - } catch (Exception e) { - fail(e); - } - } - - @Test - void testDecryption() { - - LocationDataRequestDto locationDataRequest = LocationDataRequestDto.builder(). - keyOfHealthDepartment(publicKey). - keyReference("2470b56c-90b7-11eb-a8b3-0242ac130003"). - submissionUri("https://localhost:" + port + "/data-submissions/423576f4-9202-11eb-b5b7-00155da17da6/guests"). - build(); - - List guests = guestLoader.getGuests(); - DataProviderDto dataProvider = dataProviderLoader.getDataProvider(); - GuestListDto guestList = GuestListDto.builder(). - guests(guests). - additionalInformation(""). - startDate(Instant.now()). - endDate(Instant.now().plus(6,ChronoUnit.HOURS)). - dataProvider(dataProvider). - build(); - GuestListEncryptor encryptor = GuestListEncryptor.builder(). - guestList(guestList). - givenPublicKey(locationDataRequest.getKeyOfHealthDepartment()). - build(); - - String encryptedData = encryptor.encrypt(); - - GuestListDecryptor decryptor = new GuestListDecryptor(encryptor.getSecretKeyBase64(), privateKey, encryptedData); - - log.info("json: "+guestList.asJson()); - assertEquals(guestList.asJson(), decryptor.decrypt()); - - } -} diff --git a/demo-checkin-app/src/test/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClientTest.java b/demo-checkin-app/src/test/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClientTest.java deleted file mode 100644 index d04aa7e1..00000000 --- a/demo-checkin-app/src/test/java/iris/demo/checkin_app/searchindex/web/client/SearchIndexClientTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package iris.demo.checkin_app.searchindex.web.client; - -import static com.github.tomakehurst.wiremock.client.WireMock.*; - -import iris.demo.checkin_app.IrisWireMockTest; -import iris.demo.checkin_app.searchindex.bootstrap.LocationsLoader; -import iris.demo.checkin_app.searchindex.model.LocationsDto; -import iris.demo.checkin_app.searchindex.web.client.SearchIndexClient; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -@IrisWireMockTest -class SearchIndexClientTest { - - @Autowired - SearchIndexClient client; - - @Autowired - LocationsLoader locationsLoader; - - public final String LOCATIONS_PATH = "/search-index/locations"; - - @Test - void testUpdateLocations() { - stubFor(put(urlEqualTo(LOCATIONS_PATH)).willReturn(aResponse().withStatus(204))); - - stubFor(delete(urlEqualTo(LOCATIONS_PATH)).willReturn(aResponse().withStatus(200))); - - LocationsDto locations = locationsLoader.getDemoLocations(); - - client.updateLocations(locations); - } - - @Test - void testDeleteLocation() { - stubFor(put(urlEqualTo(LOCATIONS_PATH + "/0d4b783a-59fa-4687-9bf8-d1f7e15d040d")) - .willReturn(aResponse().withStatus(204))); - - stubFor(delete(urlEqualTo(LOCATIONS_PATH + "/0d4b783a-59fa-4687-9bf8-d1f7e15d040d")) - .willReturn(aResponse().withStatus(200))); - - LocationsDto locations = locationsLoader.getDemoLocations(); - - client.deleteLocation(locations.getLocations().get(1)); - } -} diff --git a/infrastructure/DEPLOYMENT.adoc b/infrastructure/DEPLOYMENT.adoc deleted file mode 100644 index 6641dcca..00000000 --- a/infrastructure/DEPLOYMENT.adoc +++ /dev/null @@ -1,13 +0,0 @@ -= Deployment - -== Staging Environment - -iris-gateway.de - -```bash -sudo su - iris -cd ./infrastructure -docker-compose -f docker-compose.staging.yml pull -docker-compose -f docker-compose.staging.yml up -d -``` -Frontend: https://iris.staging.iris-gateway.de diff --git a/infrastructure/docker-compose-all.dev.yml b/infrastructure/docker-compose-all.dev.yml new file mode 100644 index 00000000..f665dbde --- /dev/null +++ b/infrastructure/docker-compose-all.dev.yml @@ -0,0 +1,134 @@ +######################################################## +# Intended for the all in one staging environment on the VM +# +# provides a NGINX server with certificates and configuration for staging.iris-gateway.de +# togehter with the IRIS applications and with a Postgresql database and SORMAS +# DB: look at docker-compose-postgres.yml +# SORMAS: port = /; look at docker-compose-sormas.base.yml +# IRIS public: port = / +# IRIS location: port = / +# IRIS client: port = /; look at docker-compose-hd-client.base.yml +# IRIS frontend: port = /; look at docker-compose-hd-client.base.yml +# NGINX: port = 443 +######################################################## +version: '3' +services: + postgres: + extends: + file: docker-compose-postgres.yml + service: postgres + + sormas: + extends: + file: docker-compose-sormas.base.yml + service: sormas + depends_on: + postgres: + condition: service_healthy + + iris-public: + image: inoeg/iris-public-server:${IRIS_VERSION} + depends_on: + postgres: + condition: service_healthy + expose: + - 8443 + env_file: + - iris-gateway.env + # do not work on Strato machine + # mem_limit: ${IRIS_PUBLIC_MEM} + # mem_reservation: ${IRIS_PUBLIC_MEM_RESERVED} + restart: unless-stopped + + iris-location: + image: inoeg/iris-location-service:${IRIS_VERSION} + restart: unless-stopped + + ls-1: + image: inoeg/eps-server + depends_on: + iris-client: + condition: service_started + volumes: + - "/home/iris/infrastructure/eps/settings/dev/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/ls-1 + command: [ "--level debug server run" ] + + iris-client: + extends: + file: docker-compose-hd-client.base.yml + service: iris-client + depends_on: + postgres: + condition: service_healthy + sormas: + condition: service_healthy + iris-public: + condition: service_started + iris-location: + condition: service_started + environment: + - EPS-CLIENT_CLIENTURL=https://ls-1:5556/jsonrpc + + hd-1: + image: inoeg/eps-server + depends_on: + iris-client: + condition: service_started + volumes: + - "/home/iris/infrastructure/eps/settings/dev/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/hd-1 + command: [ "--level debug server run" ] + + iris-frontend: + extends: + file: docker-compose-hd-client.base.yml + service: iris-frontend + depends_on: + - iris-client + + nginx: + build: + context: ./docker/nginx + dockerfile: with-sormas-dev.Dockerfile + ports: + - 9443:443 + volumes: + - "/etc/letsencrypt:/etc/letsencrypt" + depends_on: + iris-location: + condition: service_started + iris-public: + condition: service_started + sormas: + condition: service_healthy + iris-client: + condition: service_started + + iris-app-api-demo: + image: inoeg/iris-app-api-demo:${IRIS_VERSION} + depends_on: + iris-location: + condition: service_started + nginx: + condition: service_started + expose: + - 8091 + restart: unless-stopped + + iris-app-api-demo-eps: + image: inoeg/eps-server + depends_on: + iris-app-api-demo: + condition: service_started + volumes: + - "/home/iris/infrastructure/eps/settings/dev/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/demo-app + command: [ "--level debug server run" ] + + +volumes: + psqldata_iris: diff --git a/infrastructure/docker-compose-all.staging.yml b/infrastructure/docker-compose-all.staging.yml index 5b15d958..7778a8b8 100644 --- a/infrastructure/docker-compose-all.staging.yml +++ b/infrastructure/docker-compose-all.staging.yml @@ -55,11 +55,11 @@ services: condition: service_healthy sormas: condition: service_healthy - iris-public: + iris-public: condition: service_started - iris-location: + iris-location: condition: service_started - + iris-frontend: extends: file: docker-compose-hd-client.base.yml diff --git a/infrastructure/docker-compose.staging.yml b/infrastructure/docker-compose.staging.yml index b88a1fef..2e3f497d 100644 --- a/infrastructure/docker-compose.staging.yml +++ b/infrastructure/docker-compose.staging.yml @@ -2,8 +2,9 @@ # Intended for the all in one staging environment on the VM # # provides a NGINX server with certificates and configuration for staging.iris-gateway.de -# togehter with the IRIS applications and with a Postgresql database without SORMAS +# togehter with the IRIS applications and with a Postgresql database and SORMAS # DB: look at docker-compose-postgres.yml +# SORMAS: port = /; look at docker-compose-sormas.base.yml # IRIS public: port = / # IRIS location: port = / # IRIS client: port = /; look at docker-compose-hd-client.base.yml @@ -12,75 +13,102 @@ ######################################################## version: '3' services: - postgres: - extends: - file: docker-compose-postgres.yml - service: postgres - - iris-public: - image: inoeg/iris-public-server:${IRIS_VERSION} - depends_on: - postgres: - condition: service_healthy - expose: - - 8443 - env_file: - - iris-gateway.env -# do not work on Strato machine -# mem_limit: ${IRIS_PUBLIC_MEM} -# mem_reservation: ${IRIS_PUBLIC_MEM_RESERVED} - restart: unless-stopped iris-location: - image: inoeg/iris-location-service:${IRIS_VERSION} + image: inoeg/iris-location-service:v1.0.2-alpha + restart: unless-stopped + depends_on: + - ls-1 expose: - 8080 - restart: unless-stopped - iris-client: - extends: - file: docker-compose-hd-client.base.yml - service: iris-client + ls-1: + image: inoeg/eps:v0.0.4 depends_on: - postgres: - condition: service_healthy - iris-public: + sd-1: condition: service_started - iris-location: - condition: service_started - - iris-frontend: - extends: - file: docker-compose-hd-client.base.yml - service: iris-frontend - depends_on: - - iris-client - - nginx: - build: - ./docker/nginx + expose: + - 4445 ports: - - 443:443 + - 4445:4445 volumes: - - "/etc/letsencrypt:/etc/letsencrypt" + - "/home/iris/iris-eps/iris-gateway/infrastructure/eps/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/ls-1 + command: [ "--level", "debug", "server", "run" ] + + iris-app-api-demo: + image: inoeg/demo-checkin-app:v1.0.2-alpha + environment: + - EPS_CLIENT_CLIENT_URL=https://iris-app-api-demo-eps:5554/jsonrpc depends_on: iris-location: condition: service_started - iris-public: - condition: service_started - iris-client: + iris-app-api-demo-eps: condition: service_started + ports: + - 8091:8091 + restart: unless-stopped - demo-checkin-app: - image: inoeg/demo-checkin-app:${IRIS_VERSION} + iris-app-api-demo-eps: + image: inoeg/eps:v0.0.4 depends_on: - iris-location: + sd-1: condition: service_started - nginx: + expose: + - 4444 + ports: + - 4444:4444 + volumes: + - "/home/iris/iris-eps/iris-gateway/infrastructure/eps/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/demo-app + command: [ "--level", "trace", "server", "run" ] + + public-proxy: + image: inoeg/proxy:v0.0.4 + expose: + - 4433 + - 9999 + - 6655 + ports: + - 4433:4433 + - 9999:9999 + volumes: + - "/home/iris/iris-eps/iris-gateway/infrastructure/eps/settings:/app/settings" + - /home/iris/pub-proxy-db:/tmp + environment: + - PROXY_SETTINGS=settings/dev/roles/public-proxy-1 + command: [ "--level", "trace", "run", "public" ] + + public-proxy-eps: + image: inoeg/eps:v0.0.4 + depends_on: + sd-1: condition: service_started expose: - - 8091 - restart: unless-stopped + - 5559 + - 5544 + ports: + - 5559:5559 + volumes: + - "/home/iris/iris-eps/iris-gateway/infrastructure/eps/settings:/app/settings" + environment: + - EPS_SETTINGS=settings/dev/roles/public-proxy-eps-1 + command: [ "--level", "trace", "server", "run" ] + + sd-1: + image: inoeg/sd:v0.0.4 + expose: + - 3322 + ports: + - 3322:3322 + volumes: + - "/home/iris/iris-eps/iris-gateway/infrastructure/eps/settings:/app/settings" + - /home/iris/service-directory:/tmp + environment: + - SD_SETTINGS=settings/dev/roles/sd-1 + entrypoint: ./sd + command: [ "--level", "trace", "run" ] + -volumes: - psqldata_iris: diff --git a/infrastructure/docker/nginx/config-dev/nginx.conf b/infrastructure/docker/nginx/config-dev/nginx.conf new file mode 100644 index 00000000..6fdee7ef --- /dev/null +++ b/infrastructure/docker/nginx/config-dev/nginx.conf @@ -0,0 +1,73 @@ +user nginx; +worker_processes auto; +pid /var/run/nginx.pid; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ### BEGIN Basic Settings ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + charset utf-8; + # max upload size + client_max_body_size 75M; # adjust to taste + # server_tokens off; + + server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ### END Basic Settings ## + + ### BEGIN SSL Settings ### + + #include /etc/letsencrypt/options-ssl-nginx.conf; + + # SSL + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + + # Diffie-Hellman parameter for DHE ciphersuites + ssl_dhparam /etc/nginx/dhparam.pem; + + # Mozilla Intermediate configuration + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + + # OCSP Stapling + ssl_stapling on; + ssl_stapling_verify on; + resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s; + resolver_timeout 2s; + + ### END SSL Settings ### + + ### Logging Settings ### + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ### Gzip Settings ### + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + ### Virtual Host Configs ### + include /etc/nginx/sites-enabled/*; +} diff --git a/infrastructure/docker/nginx/config-dev/sites-enabled-sormas/sormas.conf b/infrastructure/docker/nginx/config-dev/sites-enabled-sormas/sormas.conf new file mode 100644 index 00000000..238ca13d --- /dev/null +++ b/infrastructure/docker/nginx/config-dev/sites-enabled-sormas/sormas.conf @@ -0,0 +1,33 @@ +server { + server_name sormas.dev.iris-gateway.de; + listen 443 ssl; + + ssl_certificate /etc/letsencrypt/live/dev.iris-gateway.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dev.iris-gateway.de/privkey.pem; + ssl_dhparam /etc/letsencrypt/dhparams.pem; + + + if ($host != sormas.dev.iris-gateway.de) { + return 404; + } + + location / { + proxy_pass http://sormas:6080; + proxy_http_version 1.1; + proxy_cache_bypass $http_upgrade; + + # Proxy headers + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # Proxy timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } +} diff --git a/infrastructure/docker/nginx/config-dev/sites-enabled/api.conf b/infrastructure/docker/nginx/config-dev/sites-enabled/api.conf new file mode 100644 index 00000000..d82f74e5 --- /dev/null +++ b/infrastructure/docker/nginx/config-dev/sites-enabled/api.conf @@ -0,0 +1,104 @@ +# configuration of the server +server { + server_name api.staging.iris-gateway.de; + listen 443 ssl; + + ssl_certificate /etc/letsencrypt/live/staging.iris-gateway.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/staging.iris-gateway.de/privkey.pem; + ssl_dhparam /etc/letsencrypt/dhparams.pem; + + + if ($host != api.staging.iris-gateway.de) { + return 404; + } + + proxy_http_version 1.1; + proxy_cache_bypass $http_upgrade; + + # Proxy headers + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # Proxy timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + + ### BEGIN CORS ### + + # This is necessary here, because https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/ + # and also, can't have add_headers in an if block.. also can't overwrite the add_headers, only + # by repetition in the location blocks + + set $cors_origin ""; + set $cors_cred ""; + set $cors_header ""; + set $cors_method ""; + set $cors_maxage ""; + if ( $http_origin ~* ((https:\/\/iris.staging.iris-gateway\.de|http:\/\/localhost:8080)$)) { + set $cors_origin $http_origin; + set $cors_cred true; + set $cors_header "*"; + set $cors_method "*"; + set $cors_maxage "86400"; + } + + # "always" keyword is required to also set access-control headers in case of error responses. + # Otherwise errors like 403 will not be forwarded by nginx and instead + add_header Access-Control-Allow-Origin $cors_origin always; + add_header Access-Control-Allow-Credentials $cors_cred always; + add_header Access-Control-Allow-Headers $cors_header always; + add_header Access-Control-Allow-Methods $cors_method always; + add_header Access-Control-Max-Age $cors_maxage always; + add_header Vary origin always; + + # preflight requests + if ($request_method = OPTIONS) { + return 204; + } + + # here we reset the unnecessary headers + + location /data-requests-client/ { + proxy_pass http://iris-client:8092; + } + + location /search { + # only for staging, so that calls from external clients do not go through the internal client. + proxy_pass http://iris-location:8080; + } + + location /login { + proxy_pass http://iris-client:8092; + } + + location /users { + proxy_pass http://iris-client:8092; + } + + location /user-profile { + proxy_pass http://iris-client:8092; + } + + location /search-index/ { + proxy_pass http://iris-location:8080; + } + + location / { + # todo ssl + proxy_ssl_verify off; + + proxy_pass https://iris-public:8443; + + proxy_ssl_certificate /etc/letsencrypt/live/staging.iris-gateway.de/fullchain.pem; + proxy_ssl_certificate_key /etc/letsencrypt/live/staging.iris-gateway.de/privkey.pem; + proxy_ssl_protocols TLSv1.2 TLSv1.3; + proxy_ssl_ciphers HIGH:!aNULL:!MD5; + } +} diff --git a/infrastructure/docker/nginx/config-dev/sites-enabled/iris.conf b/infrastructure/docker/nginx/config-dev/sites-enabled/iris.conf new file mode 100644 index 00000000..c8b9500f --- /dev/null +++ b/infrastructure/docker/nginx/config-dev/sites-enabled/iris.conf @@ -0,0 +1,32 @@ +server { + server_name iris.dev.iris-gateway.de; + listen 443 ssl; + + ssl_certificate /etc/letsencrypt/live/dev.iris-gateway.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dev.iris-gateway.de/privkey.pem; + ssl_dhparam /etc/letsencrypt/dhparams.pem; + + if ($host != iris.dev.iris-gateway.de) { + return 404; + } + + location / { + proxy_pass http://iris-frontend:28080; + proxy_http_version 1.1; + proxy_cache_bypass $http_upgrade; + + # Proxy headers + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # Proxy timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } +} diff --git a/infrastructure/docker/nginx/with-sormas-dev.Dockerfile b/infrastructure/docker/nginx/with-sormas-dev.Dockerfile new file mode 100644 index 00000000..d92ced85 --- /dev/null +++ b/infrastructure/docker/nginx/with-sormas-dev.Dockerfile @@ -0,0 +1,4 @@ +FROM nginx +COPY config-dev/nginx.conf /etc/nginx/ +COPY config-dev/sites-enabled/ /etc/nginx/sites-enabled/ +COPY config-dev/sites-enabled-sormas/ /etc/nginx/sites-enabled/ diff --git a/infrastructure/eps/settings/dev/directory/.gitignore b/infrastructure/eps/settings/dev/directory/.gitignore new file mode 100644 index 00000000..72e8ffc0 --- /dev/null +++ b/infrastructure/eps/settings/dev/directory/.gitignore @@ -0,0 +1 @@ +* diff --git a/infrastructure/eps/settings/dev/roles/demo-app/001_default.yml b/infrastructure/eps/settings/dev/roles/demo-app/001_default.yml new file mode 100644 index 00000000..79198a31 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/demo-app/001_default.yml @@ -0,0 +1,44 @@ +name: demo-app +directory: + type: api + settings: + jsonrpc_client: + tls: + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + endpoints: [ "https://iris.staging.iris-gateway.de:3322/jsonrpc" ] + server_names: [ "sd-1" ] +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:4444" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://iris-app-api-demo:8091/data-request-rpc + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5554" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + verify_client: false diff --git a/infrastructure/eps/settings/dev/roles/hd-1/001_default.yml b/infrastructure/eps/settings/dev/roles/hd-1/001_default.yml new file mode 100644 index 00000000..63add849 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/hd-1/001_default.yml @@ -0,0 +1,40 @@ +name: hd-1 +directory: + type: api + settings: + jsonrpc_client: + tls: + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + endpoints: [ "https://iris.staging.iris-gateway.de:3322/jsonrpc" ] + server_names: [ "sd-1" ] +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://iris-client:8092/data-submission-rpc + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5556" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + verify_client: false +signing: + certificate_file: "$DIR/../../certs/hd-1-sign.crt" + key_file: "$DIR/../../certs/hd-1-sign.key" + ca_certificate_file: "$DIR/../../certs/root.crt" diff --git a/infrastructure/eps/settings/dev/roles/ls-1/001_default.yml b/infrastructure/eps/settings/dev/roles/ls-1/001_default.yml new file mode 100644 index 00000000..b7342eae --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/ls-1/001_default.yml @@ -0,0 +1,35 @@ +name: ls-1 +directory: + type: api + settings: + jsonrpc_client: + tls: + certificate_file: "$DIR/../../certs/ls-1.crt" + key_file: "$DIR/../../certs/ls-1.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + endpoints: [ "https://iris.staging.iris-gateway.de:3322/jsonrpc" ] + server_names: [ "sd-1" ] +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:4445" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/ls-1.crt" + key_file: "$DIR/../../certs/ls-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://iris-location:8080/location-rpc + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/ls-1.crt" + key_file: "$DIR/../../certs/ls-1.key" diff --git a/infrastructure/eps/settings/dev/roles/private-proxy-1/001_default.yml b/infrastructure/eps/settings/dev/roles/private-proxy-1/001_default.yml new file mode 100644 index 00000000..3a6ef9da --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/private-proxy-1/001_default.yml @@ -0,0 +1,19 @@ +private: + name: private-proxy-1 + database_file: /tmp/private-proxy-announcements.db + bind_address: 0.0.0.0:5545 + internal_endpoint: internal-server:8888 + jsonrpc_client: + endpoint: https://private-proxy-1:7766/jsonrpc + server_name: private-proxy-1 + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + jsonrpc_server: # the JSON-RPC server that the EPS server uses for communication + bind_address: 0.0.0.0:8877 + + #tls: + # ca_certificate_files: ["$DIR/../../certs/root.crt"] + # certificate_file: "$DIR/../../certs/private-proxy-1.crt" + # key_file: "$DIR/../../certs/private-proxy-1.key" diff --git a/infrastructure/eps/settings/dev/roles/private-proxy-eps-1/001_default.yml b/infrastructure/eps/settings/dev/roles/private-proxy-eps-1/001_default.yml new file mode 100644 index 00000000..2dc5fa67 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/private-proxy-eps-1/001_default.yml @@ -0,0 +1,43 @@ +name: private-proxy-1 +directory: + type: api + settings: + jsonrpc_client: + tls: + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + endpoints: [ "https://iris.staging.iris-gateway.de:3322/jsonrpc" ] + server_names: [ "sd-1" ] +channels: # defines all the channels that we want to open when starting the server + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:7776" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://private-proxy:8877/jsonrpc + #tls: + # ca_certificate_files: ["$DIR/../../certs/root.crt"] + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:7766" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + diff --git a/infrastructure/eps/settings/dev/roles/public-proxy-1/001_default.yml b/infrastructure/eps/settings/dev/roles/public-proxy-1/001_default.yml new file mode 100644 index 00000000..39f4e1f8 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/public-proxy-1/001_default.yml @@ -0,0 +1,20 @@ +public: + name: public-proxy-1 + database_file: /tmp/public-proxy-announcements.db + tls_bind_address: 0.0.0.0:4433 + internal_bind_address: 0.0.0.0:9999 + internal_endpoint: iris.staging.iris-gateway.de:9999 + jsonrpc_client: + endpoint: https://public-proxy-eps:5544/jsonrpc + server_name: public-proxy-1 + tls: + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + jsonrpc_server: # the JSON-RPC server that the EPS server uses for communication + bind_address: "0.0.0.0:6655" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + validate_client: false diff --git a/infrastructure/eps/settings/dev/roles/public-proxy-eps-1/001_default.yml b/infrastructure/eps/settings/dev/roles/public-proxy-eps-1/001_default.yml new file mode 100644 index 00000000..27a4c516 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/public-proxy-eps-1/001_default.yml @@ -0,0 +1,48 @@ +name: public-proxy-1 +directory: + type: api + settings: + jsonrpc_client: + tls: + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + endpoints: [ "https://iris.staging.iris-gateway.de:3322/jsonrpc" ] + server_names: [ "sd-1" ] +channels: # defines all the channels that we want to open when starting the server + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:5559" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: https://public-proxy:6655/jsonrpc + server_name: public-proxy-1 + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5544" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + + + diff --git a/infrastructure/eps/settings/dev/roles/sd-1/001_default.yml b/infrastructure/eps/settings/dev/roles/sd-1/001_default.yml new file mode 100644 index 00000000..0e60d911 --- /dev/null +++ b/infrastructure/eps/settings/dev/roles/sd-1/001_default.yml @@ -0,0 +1,9 @@ +jsonrpc_server: # the JSON-RPC server that the EPS server uses for communication + bind_address: "0.0.0.0:3322" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/sd-1.crt" + key_file: "$DIR/../../certs/sd-1.key" +directory: + database_file: /tmp/service-directory.records + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] diff --git a/infrastructure/iris-gateway/templates/_helpers.tpl b/infrastructure/iris-gateway/templates/_helpers.tpl index d68bfe94..78aea3eb 100644 --- a/infrastructure/iris-gateway/templates/_helpers.tpl +++ b/infrastructure/iris-gateway/templates/_helpers.tpl @@ -19,28 +19,20 @@ If release name contains chart name it will be used as a full name. {{- end }} {{- end }} -{{- define "iris-gateway.public" -}} -{{- include "iris-gateway.fullname" . }}-public +{{- define "iris-gateway.locations" -}} +{{- include "iris-gateway.fullname" . }}-locations {{- end }} -{{- define "iris-gateway.public-labels" -}} -app.kubernetes.io/name: {{ include "iris-gateway.public" . }} +{{- define "iris-gateway.locations-eps" -}} +{{- include "iris-gateway.fullname" . }}-locations-eps {{- end }} -{{- define "iris-gateway.location" -}} -{{- include "iris-gateway.fullname" . }}-location +{{- define "iris-gateway.locations-labels" -}} +app.kubernetes.io/name: {{ include "iris-gateway.locations" . }} {{- end }} -{{- define "iris-gateway.location-labels" -}} -app.kubernetes.io/name: {{ include "iris-gateway.location" . }} -{{- end }} - -{{- define "iris-gateway.postgres" -}} -{{ include "iris-gateway.fullname" . }}-postgres -{{- end }} - -{{- define "iris-gateway.postgres-labels" -}} -app.kubernetes.io/name: {{ include "iris-gateway.postgres" . }} +{{- define "iris-gateway.locations-eps-labels" -}} +app.kubernetes.io/name: {{ include "iris-gateway.locations-eps" . }} {{- end }} {{/* diff --git a/infrastructure/iris-gateway/templates/location/service.yaml b/infrastructure/iris-gateway/templates/location/service.yaml deleted file mode 100644 index 15ee5f6f..00000000 --- a/infrastructure/iris-gateway/templates/location/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "iris-gateway.location" . }} - labels: - {{- include "iris-gateway.location-labels" . | nindent 4 }} -spec: - type: NodePort - ports: - - nodePort: {{ add .Values.location.nodePort .Values.nodePortOffsets }} - port: {{ add .Values.location.nodePort .Values.nodePortOffsets }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "iris-gateway.location-labels" . | nindent 4 }} diff --git a/infrastructure/iris-gateway/templates/locations-eps/configmap.yaml b/infrastructure/iris-gateway/templates/locations-eps/configmap.yaml new file mode 100644 index 00000000..ed25d2d0 --- /dev/null +++ b/infrastructure/iris-gateway/templates/locations-eps/configmap.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "iris-gateway.locations-eps" . }} +data: + settings.yml: | + name: ls-1 + directory: + type: json + settings: + path: "{{ .Values.eps.configMountPath }}/services.json" + channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: {} + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:{{ .Values.locations.nodePort }}" + tls: + ca_certificate_file: "{{ .Values.tls.mountPath }}/root.crt" + certificate_file: "{{ .Values.tls.mountPath }}/ls-1.crt" + key_file: "{{ .Values.tls.mountPath }}/ls-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + # needs to match the endpoint configuration in the spring boot app + endpoint: http://{{ include "iris-gateway.locations" . }}:{{ .Values.locations.port }}/location-rpc + services.json: | + { + "entries": [ + { + "name": "ls-1", + "channels": [ + { + "type": "grpc_server", + "settings": { + "address": "locations.{{ index .Values.domains .Values.environment }}" + } + } + ] + } + ] + } diff --git a/infrastructure/iris-gateway/templates/locations-eps/deployment.yaml b/infrastructure/iris-gateway/templates/locations-eps/deployment.yaml new file mode 100644 index 00000000..de0ec74b --- /dev/null +++ b/infrastructure/iris-gateway/templates/locations-eps/deployment.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "iris-gateway.locations-eps" . }} + labels: + {{- include "iris-gateway.locations-labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "iris-gateway.locations-eps-labels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "iris-gateway.locations-eps-labels" . | nindent 8 }} + spec: + containers: + - name: location + image: {{ .Values.eps.image }}:{{ .Values.eps.tag }} + {{- if eq .Values.environment "local" }} + imagePullPolicy: Never + {{- else }} + imagePullPolicy: Always + {{- end }} + args: [--level, debug, server, run] + ports: + - name: grpc + containerPort: {{ .Values.locations.nodePort }} + protocol: TCP + volumeMounts: + - mountPath: {{ .Values.tls.mountPath }} + name: tls + readOnly: true + - mountPath: /config + name: config + readOnly: true + env: + - name: EPS_SETTINGS + value: {{ .Values.eps.configMountPath }}/settings.yml + volumes: + - name: tls + secret: + secretName: {{ include "iris-gateway.locations-eps" . }}-tls + - name: config + configMap: + name: {{ include "iris-gateway.locations-eps" . }} diff --git a/infrastructure/iris-gateway/templates/locations-eps/service.yaml b/infrastructure/iris-gateway/templates/locations-eps/service.yaml new file mode 100644 index 00000000..b19656c8 --- /dev/null +++ b/infrastructure/iris-gateway/templates/locations-eps/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "iris-gateway.locations-eps" . }} + labels: + {{- include "iris-gateway.locations-eps-labels" . | nindent 4 }} +spec: + type: NodePort + ports: + - port: {{ .Values.locations.nodePort }} + targetPort: grpc + nodePort: {{ .Values.locations.nodePort }} + protocol: TCP + name: grpc + selector: + {{- include "iris-gateway.locations-eps-labels" . | nindent 4 }} diff --git a/infrastructure/iris-gateway/templates/location/deployment.yaml b/infrastructure/iris-gateway/templates/locations/deployment.yaml similarity index 52% rename from infrastructure/iris-gateway/templates/location/deployment.yaml rename to infrastructure/iris-gateway/templates/locations/deployment.yaml index 6fad593b..1abc5187 100644 --- a/infrastructure/iris-gateway/templates/location/deployment.yaml +++ b/infrastructure/iris-gateway/templates/locations/deployment.yaml @@ -1,22 +1,22 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "iris-gateway.location" . }} + name: {{ include "iris-gateway.locations" . }} labels: - {{- include "iris-gateway.location-labels" . | nindent 4 }} + {{- include "iris-gateway.locations-labels" . | nindent 4 }} spec: replicas: 1 selector: matchLabels: - {{- include "iris-gateway.location-labels" . | nindent 6 }} + {{- include "iris-gateway.locations-labels" . | nindent 6 }} template: metadata: labels: - {{- include "iris-gateway.location-labels" . | nindent 8 }} + {{- include "iris-gateway.locations-labels" . | nindent 8 }} spec: containers: - name: location - image: {{ .Values.location.image }} + image: {{ .Values.locations.image }}:{{ .Values.locations.tag }} {{- if eq .Values.environment "local" }} imagePullPolicy: Never {{- else }} @@ -24,5 +24,5 @@ spec: {{- end }} ports: - name: http - containerPort: 8080 + containerPort: {{ .Values.locations.port }} protocol: TCP diff --git a/infrastructure/iris-gateway/templates/locations/service.yaml b/infrastructure/iris-gateway/templates/locations/service.yaml new file mode 100644 index 00000000..bfb5adb5 --- /dev/null +++ b/infrastructure/iris-gateway/templates/locations/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "iris-gateway.locations" . }} + labels: + {{- include "iris-gateway.locations-labels" . | nindent 4 }} +spec: + ports: + - port: {{ .Values.locations.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "iris-gateway.locations-labels" . | nindent 4 }} diff --git a/infrastructure/iris-gateway/templates/postgres/deployment.yaml b/infrastructure/iris-gateway/templates/postgres/deployment.yaml deleted file mode 100644 index 450b3e42..00000000 --- a/infrastructure/iris-gateway/templates/postgres/deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if not (eq .Values.environment "production") }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "iris-gateway.postgres" . }} - labels: - {{- include "iris-gateway.postgres-labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - {{- include "iris-gateway.postgres-labels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "iris-gateway.postgres-labels" . | nindent 8 }} - spec: - containers: - - name: postgres - image: postgres - imagePullPolicy: Always - ports: - - name: tcp - containerPort: 5432 - protocol: TCP - env: - - name: POSTGRES_DB - value: iris_public - - name: PGDATA - value: {{ .Values.postgres.storageDir }} - envFrom: - - secretRef: - name: {{ include "iris-gateway.postgres" . }} - {{- if eq .Values.environment "test" }} - volumeMounts: - - mountPath: {{ .Values.postgres.storageDir }} - name: persistent-storage - volumes: - - name: persistent-storage - persistentVolumeClaim: - claimName: {{ include "iris-gateway.postgres" . }} - {{- end }} -{{- end }} diff --git a/infrastructure/iris-gateway/templates/postgres/pvc.yaml b/infrastructure/iris-gateway/templates/postgres/pvc.yaml deleted file mode 100644 index 93f38c4a..00000000 --- a/infrastructure/iris-gateway/templates/postgres/pvc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if eq .Values.environment "test" }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "iris-gateway.postgres" . }} - labels: - {{- include "iris-gateway.postgres-labels" . | nindent 4 }} -spec: - accessModes: - - ReadWriteOnce - storageClassName: managed-nfs-storage - resources: - requests: - storage: 10Gi -{{- end }} diff --git a/infrastructure/iris-gateway/templates/postgres/secret.yaml b/infrastructure/iris-gateway/templates/postgres/secret.yaml deleted file mode 100644 index a03d9534..00000000 --- a/infrastructure/iris-gateway/templates/postgres/secret.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- if eq .Values.environment "local" }} -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - name: {{ include "iris-gateway.postgres" . }} -data: - POSTGRES_USER: {{ "postgres" | b64enc }} - POSTGRES_PASSWORD: {{ "postgres" | b64enc }} - POSTGRES_HOST: {{ include "iris-gateway.postgres" . | b64enc }} -{{- end }} diff --git a/infrastructure/iris-gateway/templates/postgres/service.yaml b/infrastructure/iris-gateway/templates/postgres/service.yaml deleted file mode 100644 index d997bbec..00000000 --- a/infrastructure/iris-gateway/templates/postgres/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if not (eq .Values.environment "production") }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "iris-gateway.postgres" . }} - labels: - {{- include "iris-gateway.postgres-labels" . | nindent 4 }} -spec: - ports: - - port: 5432 - targetPort: tcp - protocol: TCP - name: tcp - selector: - {{- include "iris-gateway.postgres-labels" . | nindent 4 }} - {{- end }} diff --git a/infrastructure/iris-gateway/templates/public-server/deployment.yaml b/infrastructure/iris-gateway/templates/public-server/deployment.yaml deleted file mode 100644 index a1e1bc4b..00000000 --- a/infrastructure/iris-gateway/templates/public-server/deployment.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "iris-gateway.public" . }} - labels: - {{- include "iris-gateway.public-labels" . | nindent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - {{- include "iris-gateway.public-labels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "iris-gateway.public-labels" . | nindent 8 }} - spec: - containers: - - name: public - image: {{ .Values.public.image }} - {{- if eq .Values.environment "local" }} - imagePullPolicy: Never - {{- else }} - imagePullPolicy: Always - {{- end }} - ports: - - name: http - containerPort: 8443 - protocol: TCP - envFrom: - - secretRef: - name: {{ include "iris-gateway.postgres" . }} diff --git a/infrastructure/iris-gateway/templates/public-server/service.yaml b/infrastructure/iris-gateway/templates/public-server/service.yaml deleted file mode 100644 index 64ecf1cf..00000000 --- a/infrastructure/iris-gateway/templates/public-server/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "iris-gateway.public" . }} - labels: - {{- include "iris-gateway.public-labels" . | nindent 4 }} -spec: - type: NodePort - ports: - - nodePort: {{ add .Values.public.nodePort .Values.nodePortOffsets }} - port: {{ add .Values.public.nodePort .Values.nodePortOffsets }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "iris-gateway.public-labels" . | nindent 4 }} diff --git a/infrastructure/iris-gateway/values.yaml b/infrastructure/iris-gateway/values.yaml index 60162803..26705f7c 100644 --- a/infrastructure/iris-gateway/values.yaml +++ b/infrastructure/iris-gateway/values.yaml @@ -3,17 +3,22 @@ # production: --set environment=production environment: undefined -public: - image: inoeg/iris-public-server:0.0.1-SNAPSHOT - nodePort: 30001 +tls: + keystoreSecretName: tls-keystore + keystoreCredentialsSecretName: tls-keystore-credentials + mountPath: /tls -location: - image: inoeg/iris-location-service:0.0.1-SNAPSHOT - nodePort: 30002 +eps: + image: luckylusa/iris-eps-server # TODO: use inoeg/eps + tag: latest # optional overwrite via CLI: --set eps.tag= + configMountPath: /config -postgres: - storageDir: /var/lib/postgresql/data/pgdata +locations: + image: inoeg/iris-location-service + tag: 0.0.1-SNAPSHOT # optional overwrite via CLI: --set locations.tag= + port: 8080 + nodePort: 32323 -# needed only if multiple deployments are needed in the same environment. -# nodePorts need to be unique globally, for all deployments in the same environment. -nodePortOffsets: 0 +domains: + test: test.iris-gateway.de + production: iris-gateway.de diff --git a/iris-client-eps/README.md b/iris-client-eps/README.md new file mode 100644 index 00000000..fc541ea1 --- /dev/null +++ b/iris-client-eps/README.md @@ -0,0 +1,78 @@ +#IRIS EPS + +To communicate with the distributed services, IRIS uses its own EPS (endpoint server). The following describes how to install and configure the EPS. + +## Local development setup +### Install EPS +The following steps are necessary: +* In `iris-client-eps` directory run `docker run -v ./settings:/app/settings luckylusa/iris-eps-scripts certs` to generate certificates for development +* Run demo-eps config with `docker-compose up -d` +* `eps-client.clientUrl=https://localhost:5556/jsonrpc` should be set in iris-client-bff +* Please make sure `host.docker.internal` points to `172.17.0.1` on linux +* iris-app-api-demo will push a location to location service and will deliver data for any date + +### Create and change locations in location server + +Create demo location by POST to https://localhost:5554/jsonrpc + + { + "method": "ls-1.postLocationsToSearchIndex", + "id": "1", + "params": { + "providerId": "6b3f5dee-acb0-11eb-8529-0242ac130003", + "locations": [ + { + "id": "5eddd61036d39a0ff8b11fdb", + "name": "Restaurant Alberts", + "contact": { + "officialName": "Darfichrein GmbH", + "representative": "Silke ", + "address": { + "street": "Türkenstr. 7", + "city": "München", + "zip": "80333" + }, + "email": "covid2@restaurant.de", + "phone": "die bleibt privat :-)" + } + } + ] + }, + "jsonrpc": "2.0" + } + + That emulates how the operator would use his eps on port 5554. + + Delete location + + { + "method": "deleteLocationFromSearchIndex", + "id": "1", + "params": { + "providerId": "6b3f5dee-acb0-11eb-8529-0242ac130003", + "locationId": "5eddd61036d39a0ff8b11fdb" + }, + "jsonrpc": "2.0" + } + + Get provider locations + + { + "method": "ls-1.getLocationDetails", + "id": "1", + "params": { + "providerId": "6b3f5dee-acb0-11eb-8529-0242ac130003", + "locationId": "5eddd61036d39a0ff8b11fdb" + }, + "jsonrpc": "2.0" + } + + ### Note + Currently providerId is used to identify the provider. That will change soon and the provider will be identified by eps via certificate. + + +## Staging +Todo: +* Create binary for linux / eps docker image +* Integrate staging config and certificates to docker image +* Deployment to staging diff --git a/iris-client-eps/docker-compose.yml b/iris-client-eps/docker-compose.yml new file mode 100644 index 00000000..388ff1ca --- /dev/null +++ b/iris-client-eps/docker-compose.yml @@ -0,0 +1,101 @@ +######################################################## +# Intended for local development eps servers # +######################################################## + +version: '3' +services: + + ls-1: + image: inoeg/eps:v0.0.4 + expose: + - 4445 + - 5555 + ports: + - 4445:4445 + - 5555:5555 + volumes: + - ./settings:/app/settings + environment: + - EPS_SETTINGS=settings/dev/roles/ls-1 + command: [ "--level", "debug", "server", "run" ] + + demo-app: + image: inoeg/eps:v0.0.4 + expose: + - 4444 + - 5554 + ports: + - 4444:4444 + - 5554:5554 + volumes: + - ./settings:/app/settings + environment: + - EPS_SETTINGS=settings/dev/roles/demo-app + command: [ "--level", "trace", "server", "run" ] + + hd-1: + image: inoeg/eps:v0.0.4 + expose: + - 4446 + - 5556 + ports: + - 4446:4446 + - 5556:5556 + volumes: + - ./settings:/app/settings + environment: + - EPS_SETTINGS=settings/dev/roles/hd-1 + command: [ "--level", "trace", "server", "run" ] + + public-proxy: + image: inoeg/proxy:v0.0.4 + expose: + - 4433 + - 9999 + - 6655 + ports: + - 4433:4433 + - 9999:9999 + volumes: + - ./settings:/app/settings + - ./pub-proxy-db:/tmp + environment: + - PROXY_SETTINGS=settings/dev/roles/public-proxy-1 + command: [ "--level", "trace", "run", "public" ] + + public-proxy-eps: + image: inoeg/eps:v0.0.4 + expose: + - 5559 + - 5544 + ports: + - 5559:5559 + volumes: + - ./settings:/app/settings + environment: + - EPS_SETTINGS=settings/dev/roles/public-proxy-eps-1 + command: [ "--level", "trace", "server", "run" ] + + private-proxy: + image: inoeg/proxy:v0.0.4 + expose: + - 5544 + - 8877 + volumes: + - ./settings:/app/settings + - ./private-proxy-db:/tmp + environment: + - PROXY_SETTINGS=settings/dev/roles/private-proxy-1 + command: [ "--level", "trace", "run", "private" ] + + private-proxy-1: + image: inoeg/eps:v0.0.4 + expose: + - 7766 + - 7776 + volumes: + - ./settings:/app/settings + environment: + - EPS_SETTINGS=settings/dev/roles/private-proxy-eps-1 + command: [ "--level", "trace", "server", "run" ] + diff --git a/iris-client-eps/private-proxy-db/.gitignore b/iris-client-eps/private-proxy-db/.gitignore new file mode 100644 index 00000000..3997bead --- /dev/null +++ b/iris-client-eps/private-proxy-db/.gitignore @@ -0,0 +1 @@ +*.db \ No newline at end of file diff --git a/iris-client-eps/pub-proxy-db/.gitignore b/iris-client-eps/pub-proxy-db/.gitignore new file mode 100644 index 00000000..3997bead --- /dev/null +++ b/iris-client-eps/pub-proxy-db/.gitignore @@ -0,0 +1 @@ +*.db \ No newline at end of file diff --git a/iris-client-eps/settings/dev/directory/.gitignore b/iris-client-eps/settings/dev/directory/.gitignore new file mode 100644 index 00000000..86462410 --- /dev/null +++ b/iris-client-eps/settings/dev/directory/.gitignore @@ -0,0 +1,3 @@ +# generated + +*certificates.json \ No newline at end of file diff --git a/iris-client-eps/settings/dev/directory/services.json b/iris-client-eps/settings/dev/directory/services.json new file mode 100644 index 00000000..40d005e0 --- /dev/null +++ b/iris-client-eps/settings/dev/directory/services.json @@ -0,0 +1,150 @@ +{ + "records": [ + { + "created_at": "2021-05-21T09:11:27+00:00", + "section": "channels", + "name": "demo-app", + "data": [ + { + "type": "grpc_server", + "settings": { + "address": "demo-app:4444" + } + } + ] + }, + { + "created_at": "2021-05-21T09:11:27+00:00", + "section": "channels", + "name": "ls-1", + "data": [ + { + "type": "grpc_server", + "settings": { + "address": "ls-1:4445" + } + } + ] + }, + { + "created_at": "2021-05-21T09:11:27+00:00", + "section": "channels", + "name": "hd-1", + "data": [ + { + "type": "grpc_client" + } + ] + }, + { + "created_at": "2021-05-22T20:18:01Z", + "section": "channels", + "name": "private-proxy-1", + "data": [ + { + "type": "grpc_server", + "settings": { + "address": "private-proxy-1:7776" + } + }, + { + "type": "grpc_client" + } + ] + }, + { + "created_at": "2021-05-22T08:50:00Z", + "section": "groups", + "name": "public-proxy-1", + "data": [ + "proxy-providers" + ] + }, + { + "created_at": "2021-05-22T08:50:00Z", + "section": "services", + "name": "public-proxy-1", + "data": [ + { + "name": "proxy", + "permissions": [ + { + "group": "proxy-users", + "rights": [ + "call" + ] + } + ], + "methods": [ + { + "name": "announceConnection" + } + ] + } + ] + }, + { + "created_at": "2021-05-24T06:38:00Z", + "section": "settings", + "name": "hd-1", + "data": [ + { + "service": "proxy", + "environment": "production", + "settings": { + "allowed_domains": [ + ".proxy.test-gesundheitsamt.de" + ] + } + } + ] + }, + { + "created_at": "2021-05-24T06:38:00Z", + "section": "settings", + "name": "private-proxy-1", + "data": [ + { + "service": "proxy", + "environment": "production", + "settings": { + "allowed_domains": [ + ".proxy.test-gesundheitsamt.de" + ] + } + } + ] + }, + { + "created_at": "2021-05-22T08:50:00Z", + "section": "services", + "name": "private-proxy-1", + "data": [ + { + "name": "proxy-client", + "permissions": [ + { + "group": "proxy-providers", + "rights": [ + "call" + ] + } + ], + "methods": [ + { + "name": "incomingConnection" + } + ] + } + ] + }, + { + "created_at": "2021-05-22T08:50:00Z", + "section": "groups", + "name": "private-proxy-1", + "data": [ + "proxy-users" + ] + } + ] +} diff --git a/iris-client-eps/settings/dev/roles/demo-app/001_default.yml b/iris-client-eps/settings/dev/roles/demo-app/001_default.yml new file mode 100644 index 00000000..1d13f99b --- /dev/null +++ b/iris-client-eps/settings/dev/roles/demo-app/001_default.yml @@ -0,0 +1,41 @@ +name: demo-app +directory: + type: json + settings: + path: "$DIR/../../directory" +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:4444" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://host.docker.internal:8091/data-request-rpc + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5554" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/demo-app.crt" + key_file: "$DIR/../../certs/demo-app.key" + verify_client: false diff --git a/iris-client-eps/settings/dev/roles/hd-1/001_default.yml b/iris-client-eps/settings/dev/roles/hd-1/001_default.yml new file mode 100644 index 00000000..398c771b --- /dev/null +++ b/iris-client-eps/settings/dev/roles/hd-1/001_default.yml @@ -0,0 +1,37 @@ +name: hd-1 +directory: + type: json + settings: + path: "$DIR/../../directory" +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:4446" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://host.docker.internal:8092/data-submission-rpc + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5556" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/hd-1.crt" + key_file: "$DIR/../../certs/hd-1.key" + verify_client: false diff --git a/iris-client-eps/settings/dev/roles/ls-1/001_default.yml b/iris-client-eps/settings/dev/roles/ls-1/001_default.yml new file mode 100644 index 00000000..0c341e1d --- /dev/null +++ b/iris-client-eps/settings/dev/roles/ls-1/001_default.yml @@ -0,0 +1,29 @@ +name: ls-1 +directory: + type: json + settings: + path: "$DIR/../../directory" +channels: # defines all the channels that we want to open when starting the server + - name: Stdout channel + type: stdout + settings: { } + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:4445" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/ls-1.crt" + key_file: "$DIR/../../certs/ls-1.key" + + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://host.docker.internal:8080/location-rpc + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/ls-1.crt" + key_file: "$DIR/../../certs/ls-1.key" diff --git a/iris-client-eps/settings/dev/roles/private-proxy-1/001_default.yml b/iris-client-eps/settings/dev/roles/private-proxy-1/001_default.yml new file mode 100644 index 00000000..33a04851 --- /dev/null +++ b/iris-client-eps/settings/dev/roles/private-proxy-1/001_default.yml @@ -0,0 +1,16 @@ +private: + name: private-proxy-1 + database_file: /tmp/private-proxy-announcements.db + jsonrpc_client: + endpoint: https://private-proxy:7766/jsonrpc + server_name: private-proxy-1 + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + jsonrpc_server: # the JSON-RPC server that the EPS server uses for communication + bind_address: 0.0.0.0:8877 +# tls: +# ca_certificate_files: [ "$DIR/../../certs/root.crt" ] +# certificate_file: "$DIR/../../certs/private-proxy-1.crt" +# key_file: "$DIR/../../certs/private-proxy-1.key" diff --git a/iris-client-eps/settings/dev/roles/private-proxy-eps-1/001_default.yml b/iris-client-eps/settings/dev/roles/private-proxy-eps-1/001_default.yml new file mode 100644 index 00000000..a5d58310 --- /dev/null +++ b/iris-client-eps/settings/dev/roles/private-proxy-eps-1/001_default.yml @@ -0,0 +1,38 @@ +name: private-proxy-1 +directory: + # to use the JSON directory, uncomment this and comment everything below... + type: json + settings: + path: "$DIR/../../directory" +channels: # defines all the channels that we want to open when starting the server + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:7776" + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:7766" + cors: + allowed_hosts: [ "^http(?:s)?://localhost\\:\\d+$" ] + tls: + ca_certificate_files: [ "$DIR/../../certs/root.crt" ] + certificate_file: "$DIR/../../certs/private-proxy-1.crt" + key_file: "$DIR/../../certs/private-proxy-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: http://private-proxy:8877/jsonrpc + #tls: + # ca_certificate_files: ["$DIR/../../certs/root.crt"] diff --git a/iris-client-eps/settings/dev/roles/public-proxy-1/001_default.yml b/iris-client-eps/settings/dev/roles/public-proxy-1/001_default.yml new file mode 100644 index 00000000..050f7c4c --- /dev/null +++ b/iris-client-eps/settings/dev/roles/public-proxy-1/001_default.yml @@ -0,0 +1,21 @@ +public: + name: public-proxy-1 + database_file: /tmp/public-proxy-announcements.db + tls_bind_address: localhost:4433 + internal_bind_address: localhost:9999 + jsonrpc_client: + endpoint: https://localhost:5544/jsonrpc + server_name: public-proxy-1 + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + jsonrpc_server: # the JSON-RPC server that the EPS server uses for communication + bind_address: "0.0.0.0:6655" + cors: + allowed_hosts: ["^http(?:s)?://localhost\\:\\d+$"] + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + validate_client: false \ No newline at end of file diff --git a/iris-client-eps/settings/dev/roles/public-proxy-eps-1/001_default.yml b/iris-client-eps/settings/dev/roles/public-proxy-eps-1/001_default.yml new file mode 100644 index 00000000..a78b9492 --- /dev/null +++ b/iris-client-eps/settings/dev/roles/public-proxy-eps-1/001_default.yml @@ -0,0 +1,48 @@ +name: public-proxy-1 +directory: + type: json + settings: + path: "$DIR/../../directory" +# type: api +# settings: +# jsonrpc_client: +# tls: +# certificate_file: "$DIR/../../certs/hd-1.crt" +# key_file: "$DIR/../../certs/hd-1.key" +# ca_certificate_files: ["$DIR/../../certs/root.crt"] +# ca_certificate_files: ["$DIR/../../certs/root.crt"] +# endpoints: ["https://localhost:3322/jsonrpc"] +# server_names: ["sd-1"] +channels: # defines all the channels that we want to open when starting the server + - name: main gRPC server # accepts incoming gRPC connections to deliver and receive messages + type: grpc_server + settings: + bind_address: "0.0.0.0:5559" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main gRPC client # creates outgoing gRPC connections to deliver and receive messages + type: grpc_client + settings: + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main JSON-RPC server # accepts incoming JSONRPC connections to deliver and receive messages + type: jsonrpc_server + settings: + bind_address: "0.0.0.0:5544" + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" + - name: main JSON-RPC client # creates outgoing JSONRPC connections to deliver and receive messages + type: jsonrpc_client + settings: + endpoint: https://0.0.0.0:6655/jsonrpc + server_name: public-proxy-1 + tls: + ca_certificate_files: ["$DIR/../../certs/root.crt"] + certificate_file: "$DIR/../../certs/public-proxy-1.crt" + key_file: "$DIR/../../certs/public-proxy-1.key" diff --git a/iris-location-service/.mvn/wrapper/MavenWrapperDownloader.java b/iris-location-service/.mvn/wrapper/MavenWrapperDownloader.java index e76d1f32..8e98712c 100644 --- a/iris-location-service/.mvn/wrapper/MavenWrapperDownloader.java +++ b/iris-location-service/.mvn/wrapper/MavenWrapperDownloader.java @@ -13,105 +13,101 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; + import java.util.Properties; public class MavenWrapperDownloader { - private static final String WRAPPER_VERSION = "0.5.6"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to use instead of the default + * one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = ".mvn/wrapper/maven-wrapper.properties"; - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = ".mvn/wrapper/maven-wrapper.jar"; - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } } diff --git a/iris-location-service/pom.xml b/iris-location-service/pom.xml index d9a2d8b7..5c887f63 100644 --- a/iris-location-service/pom.xml +++ b/iris-location-service/pom.xml @@ -27,15 +27,6 @@ org.springframework.boot spring-boot-starter-data-jpa - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.security - spring-security-test - test - org.projectlombok lombok @@ -66,11 +57,11 @@ compile - org.springframework.boot - spring-boot-devtools - runtime - true - + org.springframework.boot + spring-boot-devtools + runtime + true + @@ -91,16 +82,16 @@ pom - - - org.springdoc - springdoc-openapi-ui - 1.5.7 - + + + org.springdoc + springdoc-openapi-ui + 1.5.7 + - ${project.artifactId}-${version.tag} + ${project.artifactId}-${version.tag} org.springframework.boot @@ -123,25 +114,25 @@ - - - ${env.DOCKER_HUB_USER} - ${env.DOCKER_HUB_PW} - - - + + + ${env.DOCKER_HUB_USER} + ${env.DOCKER_HUB_PW} + + + - - pl.project13.maven - git-commit-id-plugin - - true - - + + pl.project13.maven + git-commit-id-plugin + + true + + diff --git a/iris-location-service/src/main/java/iris/location_service/jsonrpc/JsonRpcClientDto.java b/iris-location-service/src/main/java/iris/location_service/jsonrpc/JsonRpcClientDto.java new file mode 100644 index 00000000..12d708e1 --- /dev/null +++ b/iris-location-service/src/main/java/iris/location_service/jsonrpc/JsonRpcClientDto.java @@ -0,0 +1,14 @@ +package iris.location_service.jsonrpc; + +import lombok.Data; +import lombok.RequiredArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@RequiredArgsConstructor +public class JsonRpcClientDto { + + private @NotNull String name; + +} diff --git a/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPC.java b/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPC.java index a10f09e5..735330b7 100644 --- a/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPC.java +++ b/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPC.java @@ -5,7 +5,8 @@ import iris.location_service.dto.LocationOverviewDto; import java.util.List; -import java.util.UUID; + +import javax.validation.Valid; import com.googlecode.jsonrpc4j.JsonRpcParam; import com.googlecode.jsonrpc4j.JsonRpcService; @@ -13,18 +14,21 @@ @JsonRpcService("/location-rpc") public interface LocationRPC { String postLocationsToSearchIndex( - @JsonRpcParam(value = "providerId") UUID providerId, + @Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client, @JsonRpcParam(value = "locations") List locationList); - List getProviderLocations(@JsonRpcParam(value = "providerId") UUID providerId); + List getProviderLocations(@Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client); String deleteLocationFromSearchIndex( - @JsonRpcParam(value = "providerId") UUID providerId, + @Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client, @JsonRpcParam(value = "locationId") String locationId); - LocationList searchForLocation(@JsonRpcParam(value = "searchKeyword") String searchKeyword); + LocationList searchForLocation( + @Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client, + @JsonRpcParam(value = "searchKeyword") String searchKeyword); Object getLocationDetails( + @Valid @JsonRpcParam(value = "_client") JsonRpcClientDto client, @JsonRpcParam(value = "providerId") String providerId, @JsonRpcParam(value = "locationId") String locationId); } diff --git a/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPCImpl.java b/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPCImpl.java index e145a4f2..fd304e2b 100644 --- a/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPCImpl.java +++ b/iris-location-service/src/main/java/iris/location_service/jsonrpc/LocationRPCImpl.java @@ -8,13 +8,11 @@ import java.util.List; import java.util.Optional; -import java.util.UUID; import javax.validation.constraints.NotNull; import org.springframework.stereotype.Service; -import com.googlecode.jsonrpc4j.JsonRpcParam; import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl; @AutoJsonRpcServiceImpl @@ -24,32 +22,33 @@ public class LocationRPCImpl implements LocationRPC { private final @NotNull LocationService locationService; - public String postLocationsToSearchIndex(UUID providerId, List locationList) { - locationService.addLocations(providerId, locationList); + public String postLocationsToSearchIndex(JsonRpcClientDto client, List locationList) { + locationService.addLocations(client.getName(), locationList); return "OK"; } @Override - public List getProviderLocations(UUID providerId) { - return locationService.getProviderLocations(providerId); + public List getProviderLocations(JsonRpcClientDto client) { + return locationService.getProviderLocations(client.getName()); } @Override - public String deleteLocationFromSearchIndex(UUID providerId, String locationId) { - if (locationService.deleteLocation(providerId, locationId)) + public String deleteLocationFromSearchIndex(JsonRpcClientDto client, String locationId) { + if (locationService.deleteLocation(client.getName(), locationId)) return "OK"; return "NOT FOUND"; } @Override - public LocationList searchForLocation(String searchKeyword) { + public LocationList searchForLocation(JsonRpcClientDto client, String searchKeyword) { return new LocationList(locationService.search(searchKeyword)); } @Override public Object getLocationDetails( - @JsonRpcParam(value = "providerId") String providerId, - @JsonRpcParam(value = "locationId") String locationId) { + JsonRpcClientDto client, + String providerId, + String locationId) { Optional locationInformation = locationService.getLocationByProviderIdAndLocationId(providerId, locationId); diff --git a/iris-location-service/src/main/java/iris/location_service/security/AllowedProviders.java b/iris-location-service/src/main/java/iris/location_service/security/AllowedProviders.java deleted file mode 100644 index e8ae4537..00000000 --- a/iris-location-service/src/main/java/iris/location_service/security/AllowedProviders.java +++ /dev/null @@ -1,39 +0,0 @@ -package iris.location_service.security; - -import lombok.Data; -import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.ConstructorBinding; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; - -import java.util.List; -import java.util.stream.Collectors; - - -@ConstructorBinding -@RequiredArgsConstructor -@ConfigurationProperties(prefix = "iris.allowed-providers") -public class AllowedProviders { - - private final List providers; - - public Provider findByProviderId(String providerId) { - var configurationList = providers.stream() - .filter(it -> StringUtils.equals(it.getId(), providerId)) - .collect(Collectors.toList()); - var listSize = configurationList.size(); - if (listSize != 1) { - return null; - } - return configurationList.get(0); - } - - @Data - public static class Provider { - String id; - String name; - } -} diff --git a/iris-location-service/src/main/java/iris/location_service/security/ProviderIdAuthFilter.java b/iris-location-service/src/main/java/iris/location_service/security/ProviderIdAuthFilter.java deleted file mode 100644 index 9e104e02..00000000 --- a/iris-location-service/src/main/java/iris/location_service/security/ProviderIdAuthFilter.java +++ /dev/null @@ -1,25 +0,0 @@ -package iris.location_service.security; - -import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; - -import javax.servlet.http.HttpServletRequest; - -public class ProviderIdAuthFilter extends AbstractPreAuthenticatedProcessingFilter { - - private String principalRequestHeader; - - public ProviderIdAuthFilter(String principalRequestHeader) { - this.principalRequestHeader = principalRequestHeader; - } - - @Override - protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { - return request.getHeader(principalRequestHeader); - } - - @Override - protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { - return "N/A"; - } - -} diff --git a/iris-location-service/src/main/java/iris/location_service/security/ProviderIdConfig.java b/iris-location-service/src/main/java/iris/location_service/security/ProviderIdConfig.java deleted file mode 100644 index e9838221..00000000 --- a/iris-location-service/src/main/java/iris/location_service/security/ProviderIdConfig.java +++ /dev/null @@ -1,57 +0,0 @@ -package iris.location_service.security; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; -import org.springframework.core.annotation.Order; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; - -import javax.validation.constraints.NotNull; - -@AllArgsConstructor -@Configuration -@EnableWebSecurity -@Slf4j -public class ProviderIdConfig extends WebSecurityConfigurerAdapter { - - private static final String requestHeaderName = "x-provider-id"; - - private final @NotNull AllowedProviders allowedProviders; - - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - ProviderIdAuthFilter filter = new ProviderIdAuthFilter(requestHeaderName); - filter.setAuthenticationManager(new AuthenticationManager() { - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - String principal = (String) authentication.getPrincipal(); - AllowedProviders.Provider provider = allowedProviders.findByProviderId(principal); - if (provider == null) - { - throw new BadCredentialsException("ProviderId was not found in header."); - } - log.info("Request from "+provider.name); - authentication.setAuthenticated(true); - return authentication; - } - }); - httpSecurity. - antMatcher("/search-index/**"). - csrf().disable(). - sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS). - and().addFilter(filter).authorizeRequests().anyRequest().authenticated(); - } - -} diff --git a/iris-location-service/src/main/java/iris/location_service/service/LocationService.java b/iris-location-service/src/main/java/iris/location_service/service/LocationService.java index e3a229a1..94c92bca 100644 --- a/iris-location-service/src/main/java/iris/location_service/service/LocationService.java +++ b/iris-location-service/src/main/java/iris/location_service/service/LocationService.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Optional; -import java.util.UUID; import java.util.stream.Collectors; import javax.validation.constraints.NotNull; @@ -30,7 +29,7 @@ public class LocationService { private final @NotNull DBSearchIndex index; - public void addLocations(UUID providerId, List locations) { + public void addLocations(String providerId, List locations) { // TODO: Authenticate API Access // TODO: Define sensible limits for this API @@ -42,7 +41,7 @@ public void addLocations(UUID providerId, List locations) { locationRepository.saveAll(data); } - private Location getLocationFromLocationInformation(UUID providerId, LocationInformation entry) { + private Location getLocationFromLocationInformation(String providerId, LocationInformation entry) { // Reset possibly sent provider id. We need to ensure this comes from // the authentication system and isn't user-provided! @@ -51,12 +50,12 @@ private Location getLocationFromLocationInformation(UUID providerId, LocationInf // For the search index, we are only interested in a subset of the data structure for location information // Can be replaced - location.setId(new LocationIdentifier(providerId.toString(), entry.getId())); + location.setId(new LocationIdentifier(providerId, entry.getId())); return location; } - public List getProviderLocations(UUID providerId) { + public List getProviderLocations(String providerId) { List providerLocations = locationRepository.findByIdProviderId(providerId.toString()); @@ -66,7 +65,7 @@ public List getProviderLocations(UUID providerId) { } - public boolean deleteLocation(UUID providerId, String locationId) { + public boolean deleteLocation(String providerId, String locationId) { // Construct a new ID to match the (provider, id) pair key LocationIdentifier ident = new LocationIdentifier(providerId.toString(), locationId); diff --git a/iris-location-service/src/main/java/iris/location_service/web/ConstraintViolationExceptionHandler.java b/iris-location-service/src/main/java/iris/location_service/web/ConstraintViolationExceptionHandler.java deleted file mode 100644 index e3bf3f41..00000000 --- a/iris-location-service/src/main/java/iris/location_service/web/ConstraintViolationExceptionHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package iris.location_service.web; - -import javax.validation.ConstraintViolationException; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@ControllerAdvice -public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler { - - @ExceptionHandler(value = { ConstraintViolationException.class }) - protected ResponseEntity handleConstraintViolation(ConstraintViolationException e, WebRequest request) { - - return handleExceptionInternal(e, e.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } -} diff --git a/iris-location-service/src/main/java/iris/location_service/web/LocationIndexController.java b/iris-location-service/src/main/java/iris/location_service/web/LocationIndexController.java deleted file mode 100644 index 13f9365d..00000000 --- a/iris-location-service/src/main/java/iris/location_service/web/LocationIndexController.java +++ /dev/null @@ -1,92 +0,0 @@ -package iris.location_service.web; -/* - * Controller of the location index. Handles adding/removing entries from the index as well as search - * - * @author Kai Greshake - */ - -import iris.location_service.dto.LocationInformation; -import iris.location_service.dto.LocationList; -import iris.location_service.search.db.DBSearchIndex; -import iris.location_service.search.db.LocationRepository; -import iris.location_service.service.LocationService; -import lombok.AllArgsConstructor; - -import java.util.Optional; -import java.util.UUID; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import org.modelmapper.ModelMapper; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@Validated -@AllArgsConstructor -public class LocationIndexController { - - /* - TODO: This placeholder is for information we will get from authenticating the API requests- - i.e. which provider sent the request. Mocked to be constant 0 for now. - */ - - private final @NotNull LocationService locationService; - private final ModelMapper mapper; - private final LocationRepository locationRepository; - private final DBSearchIndex index; - - @DeleteMapping("/search-index/locations/{id}") - @ResponseStatus(code = HttpStatus.OK) - public ResponseEntity deleteLocationFromSearchIndex( - @RequestHeader(value = "x-provider-id", required = true) UUID providerId, @PathVariable("id") String id) { - // TODO: Authenticate API Access - - if (locationService.deleteLocation(providerId, id)) - return new ResponseEntity(HttpStatus.OK); - - return new ResponseEntity(HttpStatus.NOT_FOUND); - } - - @PutMapping("/search-index/locations") - @ResponseStatus(HttpStatus.NO_CONTENT) - public ResponseEntity postLocationsToSearchIndex( - @RequestHeader(value = "x-provider-id", required = true) UUID providerId, @Valid @RequestBody LocationList body) { - locationService.addLocations(providerId, body.getLocations()); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - - @GetMapping("/search/{search_keyword}") - @ResponseStatus(HttpStatus.OK) - public ResponseEntity searchSearchKeywordGet( - @Size(min = 4) @PathVariable("search_keyword") String searchKeyword) { - // TODO: Authenticate API Access - - return new ResponseEntity(new LocationList(index.search(searchKeyword)), HttpStatus.OK); - } - - @GetMapping("/search/{providerId}/{locationId}") - @ResponseStatus(HttpStatus.OK) - public ResponseEntity getLocation(@PathVariable("providerId") String providerId, - @PathVariable("locationId") String locationId) { - // TODO: Authenticate API Access - Optional locationInformation = locationService.getLocationByProviderIdAndLocationId(providerId, - locationId); - - return locationInformation.map(ResponseEntity::ok) - .orElseGet(ResponseEntity.notFound()::build); - - } - -} diff --git a/iris-location-service/src/main/resources/application.properties b/iris-location-service/src/main/resources/application.properties index 161ec55d..9ec4d3be 100644 --- a/iris-location-service/src/main/resources/application.properties +++ b/iris-location-service/src/main/resources/application.properties @@ -1,26 +1,20 @@ spring.application.name=IRIS Location Service - spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect - # JSON Marshalling spring.jackson.generator.escape-non-ascii=true spring.jackson.mapper.accept-case-insensitive-enums=true -spring.jackson.default-property-inclusion: NON_ABSENT - +spring.jackson.default-property-inclusion:NON_ABSENT springdoc.api-docs.enabled=false - # Loglevel logging.level.iris=INFO - iris.allowed-providers.providers.[0].id=f002f370-bd54-4325-ad91-1aff3bf730a5 iris.allowed-providers.providers.[0].name=app-api-demo - iris.allowed-providers.providers.[1].id=bcf054fd-c904-484a-acdb-798e151c5142 iris.allowed-providers.providers.[1].name=SmartMeeting - iris.allowed-providers.providers.[2].id=f26f1ab5-6cfe-4e00-81ad-1a59ecc2998d iris.allowed-providers.providers.[2].name=eGuest +logging.level.com.googlecode.jsonrpc4j=TRACE diff --git a/iris-location-service/src/test/java/iris/location_service/LocationRepositoryTest.java b/iris-location-service/src/test/java/iris/location_service/LocationRepositoryTest.java index 0b993498..6227769a 100644 --- a/iris-location-service/src/test/java/iris/location_service/LocationRepositoryTest.java +++ b/iris-location-service/src/test/java/iris/location_service/LocationRepositoryTest.java @@ -1,36 +1,36 @@ package iris.location_service; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import iris.location_service.search.db.LocationRepository; import iris.location_service.search.db.model.Location; import iris.location_service.search.db.model.LocationIdentifier; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + @SpringBootTest class LocationRepositoryTest { - @Autowired - private LocationRepository repo; + @Autowired + private LocationRepository repo; - @Test - public void demoForUsingTheRepo(){ + @Test + public void demoForUsingTheRepo() { - // when - var id = new LocationIdentifier("provider", "location"); - var location = new Location(); - location.setId(id); - repo.save(location); + // when + var id = new LocationIdentifier("provider", "location"); + var location = new Location(); + location.setId(id); + repo.save(location); - // then - var res = repo.findById(new LocationIdentifier( "provider", "location")); + // then + var res = repo.findById(new LocationIdentifier("provider", "location")); - // assert - assertEquals("location", res.get().getId().getLocationId()); + // assert + assertEquals("location", res.get().getId().getLocationId()); - } + } -} \ No newline at end of file +} diff --git a/iris-location-service/src/test/java/iris/location_service/web/LocationIndexControllerTest.java b/iris-location-service/src/test/java/iris/location_service/web/LocationIndexControllerTest.java deleted file mode 100644 index 573ee6b2..00000000 --- a/iris-location-service/src/test/java/iris/location_service/web/LocationIndexControllerTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package iris.location_service.web; - -import static org.junit.jupiter.api.Assertions.*; - -import iris.location_service.dto.LocationList; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; - -import com.fasterxml.jackson.databind.ObjectMapper; - -@SpringBootTest -@WebAppConfiguration -@AutoConfigureMockMvc -class LocationIndexControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper om; - - @Test - public void testPost() throws Exception { - // when, then, assert - postLocations(); - } - - @Test - public void testSearch() throws Exception { - postLocations(); - var res = mockMvc.perform(MockMvcRequestBuilders.get("/search/Restaurant") - .header("x-provider-id", "f002f370-bd54-4325-ad91-1aff3bf730a5")) - .andExpect(MockMvcResultMatchers.status().isOk()).andReturn(); - - var json = om.readValue(res.getResponse().getContentAsString(), LocationList.class); - - assertEquals(1, json.getLocations().size()); - } - - @Test - public void testDelete() throws Exception { - postLocations(); - - mockMvc.perform(MockMvcRequestBuilders.delete("/search-index/locations/5eddd61036d39a0ff8b11fdb") - .header("x-provider-id", "f002f370-bd54-4325-ad91-1aff3bf730a5")) - .andExpect(MockMvcResultMatchers.status().isOk()); - } - - private void postLocations() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.put("/search-index/locations") - .contentType(MediaType.APPLICATION_JSON) - .content(TestData.LOCATIONS) - .header("x-provider-id", "f002f370-bd54-4325-ad91-1aff3bf730a5")) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()); - } - -}