diff --git a/.gitignore b/.gitignore
index 46cdc0f81..def6421af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,40 +22,19 @@
### VS Code ###
.vscode/
wrapper
-/authorization/target
-/core-common/target
-/eventhandler/target
-/gatekeeper/target
-/gateway/target
+/target
+/**/target
/mvnw
/mvnw.cmd
-/orchestrator/target
-/serviceregistry/target
/.settings
-/authorization/.settings
-/core-common/.settings
-/eventhandler/.settings/*.prefs
-/eventhandler/.settings
+/**/.settings
*.prefs
-/gatekeeper/.settings
-/gateway/.settings
-/orchestrator/.settings
-/serviceregistry/.settings
+/*.log
+/**/*.log
-/serviceregistry/*.log
-/authorization/*.log
/.metadata/
-gatekeeper/gatekeeper\.log
-/eventhandler/*.log
-/orchestrator/*.log
-/choreographer/*.log
-choreographer.log
-serviceregistry.log
-authorization.log
-/choreographer/target
-
-*.log
-/target
/deb-installer/.classpath
/deb-installer/.project
/deb-installer/.settings
+/qos-monitor/.settings
+/qos-monitor/target
diff --git a/README.md b/README.md
index ba608b505..b5634e984 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+
# Arrowhead Framework 4.1.3
[Arrowhead](http://www.arrowhead.eu/) (and its continuation, [Productive4.0](https://productive40.eu/)) is an ambitious holistic innovation project,
@@ -10,7 +11,10 @@ Please be aware, that 4.1.3 is __NOT__ backwards compatible with 4.1.2. If you h
## Table of Contents
1. [Quick Start Guide](#quickstart)
1. [Docker](#quickstart_docker)
- * [Handy Docker Commands](#quickstart_dockercommands)
+ * [System Requirements](#quickstart_dockersysreqs)
+ * [Examples](#quickstart_examples)
+ * [Guide](#quickstart_dockerguide)
+ * [Cheat-Sheet](#quickstart_dockercommands)
* [Troubleshooting](#quickstart_dockertroubleshooting)
2. [Debian Installer](#quickstart_debian)
3. [Compile Code](#quickstart_compile)
@@ -70,6 +74,41 @@ Please be aware, that 4.1.3 is __NOT__ backwards compatible with 4.1.2. If you h
* [Client](#gateway_endpoints_client)
* [Private](#gateway_endpoints_private)
* [Management](#gateway_endpoints_mgmt)
+ 7. [Certificate Authority](#ca)
+ * [System Design Description Overview](#ca_sdd)
+ * [Services and Use Cases](#ca_usecases)
+ * [Endpoints](#ca_endpoints)
+ * [Client](#ca_endpoints_client)
+ * [Private](#ca_endpoints_private)
+ * [Management](#ca_endpoints_mgmt)
+ 8. [QoS Monitor (Quality of Service Monitor)](#qos_monitor)
+ * [System Design Description Overview](#qos_monitor_sdd)
+ * [Services and Use Cases](#qos_monitor_usecases)
+ * [Endpoints](#qos_monitor_endpoints)
+ * [Client](#qos_monitor_endpoints_client)
+ * [Private](#qos_monitor_endpoints_private)
+ * [Management](#qos_monitor_endpoints_mgmt)
+ 9. [Onboarding Controller](#onboardingcontroller)
+ * [System Design Description Overview](#onboardingcontroller_sdd)
+ * [Services and Use Cases](#onboardingcontroller_usecases)
+ * [Security](#onboardingcontroller_security)
+ * [Endpoints](#onboardingcontroller_endpoints)
+ * [Onboarding](#onboardingcontroller_endpoints_onboarding)
+ 9. [Device Registry](#deviceregistry)
+ * [System Design Description Overview](#deviceregistry_sdd)
+ * [Services and Use Cases](#deviceregistry_usecases)
+ * [Security](#deviceregistry_security)
+ * [Endpoints](#deviceregistry_endpoints)
+ * [Onboarding](#deviceregistry_endpoints_onboarding)
+ * [Client](#deviceregistry_endpoints_client)
+ 9. [System Registry](#systemregistry)
+ * [System Design Description Overview](#systemregistry_sdd)
+ * [Services and Use Cases](#systemregistry_usecases)
+ * [Security](#systemregistry_security)
+ * [Endpoints](#systemregistry_endpoints)
+ * [Onboarding](#systemregistry_endpoints_onboarding)
+ * [Client](#systemregistry_endpoints_client)
+
@@ -79,7 +118,13 @@ Please be aware, that 4.1.3 is __NOT__ backwards compatible with 4.1.2. If you h
### Docker
-#### Requirements
+[Docker](https://docs.docker.com/) is a container platform that can be used to package and deploy applications in server environments, among other.
+In particular, the [`docker-compose`](https://docs.docker.com/compose/) utility may with advantage be used during application development to test integration with the Arrowhead Core systems.
+Here, we provide brief instructions on how to install and run both Docker and container images for the Arrowhead Core systems.
+
+
+
+#### System Requirements
> **Note:** A system with 4GB of RAM is advised.
@@ -90,6 +135,8 @@ Please be aware, that 4.1.3 is __NOT__ backwards compatible with 4.1.2. If you h
* [Windows](https://docs.docker.com/docker-for-windows/install/)
* [Docker Compose](https://docs.docker.com/compose/install/)
+
+
Don't forget to create a volume for mysql: `docker volume create --name=mysql`
Don't forget to copy the `initSQL.sh` script next to the docker-compose file and execute it! On the first run it initializes the Database!
Example copy command which does this for you, execute from the project root directory.
@@ -99,17 +146,21 @@ cd docker
./initSQL.sh
```
-Inside the `docker` folder an example is provided.
+#### Examples
-##### Core System Config
+We provide two examples of how Docker containers can be used to host Arrowhead Core systems in this repository.
+The first one is located in the [`docker`](docker) folder and the second one in the [`docker-all`](docker-all) folder.
+The former example shows how some prebuilt Docker images can be used to bring up networks, while the second describes how a Docker image can be constructed that contains all Arrowhead Core systems.
+Please refer to those folders for more information.
+In particular, each folder contains its own `README.md` file with more instructions.
-Example Core System Configuration files are available in this folder.
+
-> **Note:** Don't forget to set `domain.name` and `domain.port` properties!
+#### Docker Guide
-##### Docker Compose
+> **Note:** Don't forget to set `domain.name` and `domain.port` properties!
-Example Docker Compose file is located here. The interesting part is the volumes section.
+Example Docker Compose file is located [here](docker/docker-compose.yml). The interesting part is the volumes section.
Format is /path/on/your/local/machine:/path/inside/docker/container
You may want to copy the config files elsewhere with the compose file too. If you copy them, please don't forget to change the volume mounting point, but DON'T change the volume mounting point inside the container, otherwise it will start up with default config.
@@ -129,9 +180,9 @@ If you change your config you have to restart the appropriate container
`docker restart `
-`
+
-##### Handy Docker Commands
+#### Docker Cheat-Sheet
| Command | Description |
| ------- | ----------- |
@@ -139,6 +190,7 @@ If you change your config you have to restart the appropriate container
| `docker images` | List all images |
| `docker-compose up -d` | Starts the Docker containers |
| `docker-compose down` | Destroys the Docker containers |
+| `docker restart ` | Restarts a container, making it re-read its configuration files |
| `docker logs ` | Shows logs for the container |
| `docker volume create --name=` | Creates a named volume |
| `docker volume rm ` | Removes the specified named volume |
@@ -150,7 +202,6 @@ If you change your config you have to restart the appropriate container
Q: MySQL won't start. What did went wrong?
A: Probably you missed to copy the init SQL script next to the compose file, or you have a typo in its name. Solution: [https://github.com/arrowhead-f/core-java-spring/issues/105](https://github.com/arrowhead-f/core-java-spring/issues/105)
-
### Debian Installers
@@ -400,7 +451,7 @@ Arrowhead Framework's security is relying on SSL Certificate Trust Chains. The A
1) Master certificate: `arrowhead.eu`
2) Cloud certificate: `my_cloud.my_company.arrowhead.eu`
3) Client certificate: `my_client.my_cloud.my_company.arrowhead.eu`
-The certificate naming convetion have strict rules:
+The certificate naming convention have strict rules:
* The different parts are delimited by dots, therefore parts are not allowed to contain any of them.
* A cloud certificate name has to consist of four part and the last two part have to be 'arrowhead' and 'eu'.
* A client certificate name has to consist of five part and the last two part have to be 'arrowhead' and 'eu'.
@@ -423,6 +474,14 @@ Currently Arrowhead community have the possibility to create only "self signed"
* [Create Arrowhead Client Self Signed Certificate](documentation/certificates/create_client_certificate.pdf)
* [Create Trust Store](documentation/certificates/create_trust_store.pdf)
+If you wish to generate all Certificates by a script, you can use the scripts in the [scripts/certificate_generation](scripts/certificate_generation) folder.
+
+> **Note:** Basic scripting knowledge is required!
+
+* lib_certs.sh - Certificate generation code
+* mk_certs.sh - Usage example
+* rm_certs.sh - Delete generated certs
+
### System Operator Certificate
The System Operator Certificate is a special client certificate with the naming convention of `sysop.my_cloud.my_company.arrowhead.eu`.
@@ -431,6 +490,14 @@ SysOp certificate allows the client to use the management endpoints of the Arrow
* [Import SysOp Certificate (macOS)](documentation/certificates/import_sysop_certificate_macos.pdf)
* [Import SysOp Certificate (Linux)](documentation/certificates/import_sysop_certificate_linux.pdf)
+### Include certificate in Docker container
+
+The following guide describes step by step, how to include your own certificates into a Docker container.
+
+* [How to include certificate in Docker](documentation/certificates/docker_certificate_guide.md)
+
+
+
## Gatekeeper and Gateway Setup with ActiveMQ Relay
@@ -3322,7 +3389,7 @@ __ServiceRequestForm__ is the input
"string"
],
"securityRequirements": [
- "NOT_SECURE", "CEERTIFICATE", "TOKEN"
+ "NOT_SECURE", "CERTIFICATE", "TOKEN"
],
"metadataRequirements": {
"additionalProp1": "string",
@@ -6234,3 +6301,1176 @@ __ActiveSession__ is the output.
| `responseControlQueue` | control queue of response messaging through the the Relay |
| `sessionStartedAt` | Time stamp of session start |
+
+
+# Certificate Authority
+
+
+
+## System Design Description Overview
+
+The purpose of the Certificate Authority supporting core system is issuing signed certificates to be used in the local cloud.
+
+
+
+## Provided services
+
+The Certificate Authority provides the following services:
+* [Echo](#ca_endpoints_get_echo)
+* [Certificate signing](#ca_endpoints_sign)
+
+
+
+## Use cases
+
+The main use case of the Certificate Authority is to issue signed certificates to new consumers coming via the Onboarding Controller.
+
+
+
+## Endpoints
+
+
+
+### Client endpoint description
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Echo](#ca_endpoints_get_echo) | /echo | GET | - | OK |
+
+
+
+### Private endpoint description
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Sign CSR with the Cloud Certificate](#ca_endpoints_sign) | /sign | POST | CertificateSigningRequest | [CertificateSigningResponse](#ca_certificate_signing_response) |
+
+
+
+### Echo
+```
+GET /certificate-authority/echo
+```
+
+Returns a "Got it" message with the purpose of testing the core service availability.
+
+
+
+### Sign CSR with the Cloud Certificate
+
+```
+POST /certificate-authority/sign
+```
+
+Returns the whole certificate chain beginning with the newly generated leaf certificate and ending with the root certificate.
+
+Each certificate's issuer is the same as the subject of the following one. The issuer of the root certificate is the same as the subject.
+
+__Sign CSR with the Cloud Certificate__ inputs:
+
+`https://ca_ip:ca_port/certificate-authority/sign`
+
+| __Sign CSR with the Cloud Certificate__ query parameters |
+| ------------------------------------------------------- |
+
+| Parameter | Description | Necessity | Format/Limitations |
+| --------- | ----------- | --------- | ----------- |
+| `encodedCSR` | PKCS #10 Certificate Signing Request | mandatory | Base64 encoded CSR |
+
+
+
+__Sign CSR with the Cloud Certificate__ output :
+
+```json
+{
+ "certificateChain": [
+ "",
+ "",
+ ""
+ ]
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificateChain` | The whole certificate chain in an array of PEM encoded strings |
+
+
+
+### Management endpoint description
+
+The Certificate Authority does not have management endpoints.
+
+
+
+# QOS MONITOR (QUALITY OF SERVICE MONITOR)
+
+
+
+## System Design Description Overview
+
+The purpose of QoS Monitor supporting core system is providing QoS (Quality of Service) measurements to the QoS Manager (which is part of the Orchestrator core system).
+
+ `AH Service Registry`
+ `AH Authorization`
+ `AH Orchestrator / QoS Manager`
+ `AH QoS Monitor`
+
+
+
+
+## System Design Overview
+
+
+
+
+## Provided services
+
+The QoS Monitor provides the following services:
+* [Echo](#qos_monitor_endpoints_get_echo)
+* [Ping Measurement](#qos_monitor_endpoints_ping_measurement_by_system_id)
+
+
+
+## Consumed services
+
+The QoS Monitor consumes the following service:
+* QueryAll private service from the ServiceRegistry core system
+
+
+
+## Use cases
+
+The QoS Monitor has the following use cases:
+* [Ping Measurement](documentation/qos_monitor/use_cases/QoSMonitor_use_case_1.md)
+
+* [Reset Counter](documentation/qos_monitor/use_cases/QoSMonitor_use_case_2.md)
+
+* [Get Measurements](documentation/qos_monitor/use_cases/QoSMonitor_use_case_3.md)
+
+
+
+
+## Endpoints
+
+
+
+### Client endpoint description
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Echo](#qos_monitor_endpoints_get_echo) | /echo | GET | - | OK |
+
+
+
+### Management endpoint description
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Get ping measurements mgmt](#qos_monitor_endpoints_get_ping_measurements_list) | /mgmt/ping/measurements | GET | direction && item_per_page && page && sort_field | [PingMeasurement list response](#qos_monitor_ping_measurement_list_response) |
+| [Get ping measurements by system id mgmt](#qos_monitor_mgmt_endpoints_get_ping_measurement_by_system_id) | /mgmt/ping/measurements/{id} | GET | id | [Ping Measurment response](#qos_monitor_ping_measurement_response) |
+
+
+
+### Private endpoint description
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Get ping measurements by system id](#qos_monitor_endpoints_get_ping_measurement_by_system_id) | /ping/measurements/{id} | GET | id | [Ping Measurment response](#qos_monitor_ping_measurement_response) |
+
+
+
+### Echo
+```
+GET /qos_monitor/echo
+```
+
+Returns a "Got it" message with the purpose of testing the core service availability.
+
+### Get ping measurements mgmt
+
+```
+GET /mgmt/ping/measurements
+```
+
+__Get subscriptions query parameters__ the input :
+
+`https://qos_monitor_ip:qos_monitor_port/qos_monitor/mgmt/ping/measurements?dirction=`ASC`&item_per_page=`100`&page=`0`&sort_field=`id
+
+| __Get ping measurements mgmt__ query parameters |
+| ------------------------------------------------------- |
+
+| Parameter | Description | Necessity | Format/Limitations |
+| --------- | ----------- | --------- | ----------- |
+| `direction` | Direction of sorting. | optional | valid values: "ASC", "DESC" - default: "ASC"|
+| `item_per_page` | Maximum number of items returned. | optional (mandatory, if page is defined)| integer |
+| `page` | Zero based page index. | optional (mandatory, if item_per_page is defined)| integer |
+| `sort_field` | The field to sort the results by. | optional | valid values: "id", "updatedAt", "createdAt" - default: "id" |
+
+
+
+__PingMeasurement list response__ the output :
+
+```json
+{
+ "data": [
+ {
+ "id": 1,
+ "measurement": {
+ "id": 1,
+ "system": {
+ "id": 5,
+ "systemName": "testsystem",
+ "address": "testsystem.ai",
+ "port": 12345,
+ "createdAt": "2020-02-04 09:38:56",
+ "updatedAt": "2020-02-04 09:38:56"
+ },
+ "measurementType": "PING",
+ "lastMeasurementAt": "2020-02-14T10:48:10+01:00",
+ "createdAt": "2020-02-04T10:42:04+01:00",
+ "updatedAt": "2020-02-14T10:48:47+01:00"
+ },
+ "available": true,
+ "lastAccessAt": "2020-02-14T10:48:10+01:00",
+ "minResponseTime": 15,
+ "maxResponseTime": 26,
+ "meanResponseTimeWithTimeout": 18,
+ "meanResponseTimeWithoutTimeout": 18,
+ "jitterWithTimeout": 3,
+ "jitterWithoutTimeout": 3,
+ "lostPerMeasurementPercent": 0,
+ "sent": 12075,
+ "received": 12070,
+ "countStartedAt": "2020-02-07T00:00:00+01:00",
+ "sentAll": 63175,
+ "receivedAll": 56721,
+ "createdAt": "2020-02-14T10:48:47+01:00",
+ "updatedAt": "2020-02-14T10:48:47+01:00"
+ }
+ ],
+ "count": 1
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `count` | Number of record found |
+| `data` | Array of data |
+| `id` | ID of the ping measurement |
+| `measurement.id` | ID of the measurement |
+| `measurement.system.id` | ID of the measured system |
+| `measurement.system.systemName` | Name of the measured system |
+| `measurement.system.address` | Address of the measured system |
+| `measurement.system.port` | Port of the measured system |
+| `measurement.system.createdAt` | Date of creation of the measured system |
+| `measurement.system.updatedAt` | Date of update of the measured system |
+| `measurement.measurementType` | Type of the measurement |
+| `measurement.lastMeasurementAt` | Time of the last measurement |
+| `measurement.createdAt` | Date of creation of the measurement |
+| `measurement.updatedAt` | Date of update of the measurement |
+| `available` | Boolean value of the systems calculated availability|
+| `lastAccessAt` | TimeStamp value of the systems last known availability|
+| `minResponseTime` | Integer value of milliseconds of the fastest returned ping|
+| `maxResponseTime` | Integer value of milliseconds of the slowest returned ping|
+| `meanResponseTimeWithTimeout` | Integer value of milliseconds of the calculated average of pings including timeouts|
+| `meanResponseTimeWithoutTimeout` | Integer value of milliseconds of the calculated average of pings not including timeouts|
+| `jitterWithTimeout` | Integer value of milliseconds of the calculated standard deviation of pings including timeouts|
+| `jitterWithoutTimeout` | Integer value of milliseconds of the calculated standard deviation of pings not including timeouts|
+| `lostPerMeasurementPercent` | Integer value of calculated lost ping percentage|
+| `sent` | Integer value of sent pings in measurement|
+| `received` | Integer value of received pings in measurement|
+| `countStartedAt` | TimeSatmp value of the last reset of sent and received fields|
+| `sentAll` | Integer value of sent pings since ping measurement created|
+| `receivedAll` | Integer value of received pings since ping measurement created|
+| `createdAt` | Date of creation of the ping measurement |
+| `updatedAt` | Date of update of the ping measurement |
+
+
+
+### Get ping measurements by system id mgmt
+
+```
+GET /mgmt/ping/measurements/{id}
+```
+
+__Get ping measurements by system id mgmt path parameter__ the input :
+
+`https://qos_monitor_ip:qos_monitor_port/qos_monitor/mgmt/ping/measurements/`1
+
+| __Get ping measurement by system id__ path parameter |
+| ------------------------------------------------------- |
+
+| Parameter | Description | Necessity | Format/Limitations |
+| --------- | ----------- | --------- | ----------- |
+| `id` | Id of measured system | mandatory | integer |
+
+
+
+__Ping Measurment response by system id__ the output :
+
+```json
+{
+ "id": 1,
+ "measurement": {
+ "id": 1,
+ "system": {
+ "id": 5,
+ "systemName": "testsystem",
+ "address": "testsystem.ai",
+ "port": 12345,
+ "createdAt": "2020-02-04 09:38:56",
+ "updatedAt": "2020-02-04 09:38:56"
+ },
+ "measurementType": "PING",
+ "lastMeasurementAt": "2020-02-14T10:48:10+01:00",
+ "createdAt": "2020-02-04T10:42:04+01:00",
+ "updatedAt": "2020-02-14T10:48:47+01:00"
+ },
+ "available": true,
+ "lastAccessAt": "2020-02-14T10:48:10+01:00",
+ "minResponseTime": 15,
+ "maxResponseTime": 26,
+ "meanResponseTimeWithTimeout": 18,
+ "meanResponseTimeWithoutTimeout": 18,
+ "jitterWithTimeout": 3,
+ "jitterWithoutTimeout": 3,
+ "lostPerMeasurementPercent": 0,
+ "sent": 12075,
+ "received": 12070,
+ "countStartedAt": "2020-02-07T00:00:00+01:00",
+ "sentAll": 63175,
+ "receivedAll": 56721,
+ "createdAt": "2020-02-14T10:48:47+01:00",
+ "updatedAt": "2020-02-14T10:48:47+01:00"
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `id` | ID of the ping measurement |
+| `measurement.id` | ID of the measurement |
+| `measurement.system.id` | ID of the measured system |
+| `measurement.system.systemName` | Name of the measured system |
+| `measurement.system.address` | Address of the measured system |
+| `measurement.system.port` | Port of the measured system |
+| `measurement.system.createdAt` | Date of creation of the measured system |
+| `measurement.system.updatedAt` | Date of update of the measured system |
+| `measurement.measurementType` | Type of the measurement |
+| `measurement.lastMeasurementAt` | Time of the last measurement |
+| `measurement.createdAt` | Date of creation of the measurement |
+| `measurement.updatedAt` | Date of update of the measurement |
+| `available` | Boolean value of the systems calculated availability|
+| `lastAccessAt` | TimeStamp value of the systems last known availability|
+| `minResponseTime` | Integer value of milliseconds of the fastest returned ping|
+| `maxResponseTime` | Integer value of milliseconds of the slowest returned ping|
+| `meanResponseTimeWithTimeout` | Integer value of milliseconds of the calculated average of pings including timeouts|
+| `meanResponseTimeWithoutTimeout` | Integer value of milliseconds of the calculated average of pings not including timeouts|
+| `jitterWithTimeout` | Integer value of milliseconds of the calculated standard deviation of pings including timeouts|
+| `jitterWithoutTimeout` | Integer value of milliseconds of the calculated standard deviation of pings not including timeouts|
+| `lostPerMeasurementPercent` | Integer value of calculated lost ping percentage|
+| `sent` | Integer value of sent pings in measurement|
+| `received` | Integer value of received pings in measurement|
+| `countStartedAt` | TimeSatmp value of the last reset of sent and received fields|
+| `sentAll` | Integer value of sent pings since ping measurement created|
+| `receivedAll` | Integer value of received pings since ping measurement created|
+| `createdAt` | Date of creation of the ping measurement |
+| `updatedAt` | Date of update of the ping measurement |
+
+
+
+### Get ping measurements by system id
+
+For private endpoints no detailed description available.
+
+
+# Onboarding Controller
+
+
+The purpose of this System is to be the entry board for the onboarding procedure. The onboarding controller sits at the edge of the Arrowhead local cloud.
+It is not only reachable from within the cloud by authorized systems, but also from the public through its "accept all" interfaces.
+Any client may authenticate itself through an Arrowhead certificate, through an authorized manufacturer certificate, or simply through a shared secret.
+
+
+
+## Services and Use Cases
+
+
+The only use case is the onboarding procedure.
+
+The onboarding procedure is needed when a new device produced by any vendor (e.g. Siemens, Infineon, Bosch, etc.), containing a security controller (e.g. TPM),
+wants to interact with the Arrowhead local cloud. To assure that the cloud is not compromised upon the arrival of this new device, it is important to establish
+a chain of trust from the new hardware device, to its hosted application systems and their services. Thus, the onboarding procedure makes possible that
+the device, systems and services are authenticated and authorized to connect to the Arrowhead local cloud.
+
+The use cases in which the external actor interacts with the Arrowhead local cloud during onboarding include:
+* Initialize Device Onboarding (via the Onboarding Controller system)
+* Register a Device in the DeviceRegistry (via the DeviceRegistry system)
+* Register a System in the SystemRegistry (via the SystemRegistry system)
+* Register a Service in the ServiceRegistry (via the ServiceRegistry system)
+* Start normal operation (e.g., service lookup, service consumption, etc.)
+
+The onboarding controller can either relay a  or generate one on behalf of the client.
+
+
+## Security
+
+
+This System can be secured via the HTTPS protocol. If it is started in secure mode, it verifies whether the Application System
+- possesses a proper X.509 identity certificate and whether that certificate is Arrowhead compliant
+- possesses a proper X.509 identity certificate and whether that certificate is trusted by the CA
+- provides a shared secret through 
+
+## Endpoints
+
+
+The Onboarding Controller offers two types of authentication (certificate or HTTP Basic) and two types operation (provide CSR or generate CSR), thus having four different endpoint.
+No management or private endpoint exists.
+
+Swagger API documentation is available on: `https://:`
+The base URL for the requests: `https://:/onboarding`
+
+The general scheme of the URLs is `https://:/onboarding//`
+
+### Client endpoint description
+
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Echo](#onboardingcontroller_endpoints_get_echo) | /echo | GET | - | OK |
+| [Onboard with Name](#onboardingcontroller_endpoints_name) | /certificate/name | POST | [OnboardingWithNameRequest](#datastructures_onboarding_name_request) | [OnboardingWithNameResponse](#datastructures_onboarding_name_response) |
+| [Onboard with Name](#onboardingcontroller_endpoints_name) | /sharedsecret/name | POST | [OnboardingWithNameRequest](#datastructures_onboarding_name_request) | [OnboardingWithNameResponse](#datastructures_onboarding_name_response) |
+| [Onboard with CSR](#onboardingcontroller_endpoints_csr) | /certificate/csr | POST | [OnboardingWithCsrRequest](#datastructures_onboarding_csr_request) | [OnboardingWithCsrResponse](#datastructures_onboarding_csr_response) |
+| [Onboard with CSR](#onboardingcontroller_endpoints_csr) | /sharedsecret/csr | POST | [OnboardingWithCsrRequest](#datastructures_onboarding_csr_request) | [OnboardingWithCsrResponse](#datastructures_onboarding_csr_response) |
+
+
+### Onboard with Name
+
+
+```
+POST /certificate/name
+POST /sharedsecret/name
+```
+
+Creates a CSR on behalf of the client and eventually returns an onboarding certificate which may be used in the next step of the onboarding controller.
+
+#### Request
+
+
+```json
+{
+ "creationRequestDTO": {
+ "commonName": "string",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ }
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `commonName` | The common name field for the new certificate |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+
+#### Response
+
+
+```json
+{
+ "rootCertificate": "string",
+ "intermediateCertificate": "string",
+ "onboardingCertificate": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_ONBOARDING",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "deviceRegistry": {
+ "service": "DEVICE_REGISTRY_ONBOARDING_WITH_NAME_SERVICE",
+ "uri": "string"
+ },
+ "systemRegistry": {
+ "service": "SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_SERVICE",
+ "uri": "string"
+ },
+ "serviceRegistry": {
+ "service": "SERVICE_REGISTRY_REGISTER_SERVICE",
+ "uri": "string"
+ },
+ "orchestrationService": {
+ "service": "ORCHESTRATION_SERVICE",
+ "uri": "string"
+ }
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `rootCertificate` | The Arrowhead master certificate |
+| `intermediateCertificate` | The Arrowhead local cloud certificate |
+| `onboardingCertificate` | The onboarding certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_ONBOARDING for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+| `service` | The service which is reachable under `uri` |
+| `uri` | The uri under which the depicted `service` is reachable |
+
+
+### Onboard with CSR
+
+
+```
+POST /certificate/csr
+POST /sharedsecret/csr
+```
+
+Creates a CSR on behalf of the client and eventually returns an onboarding certificate which may be used in the next step of the onboarding controller.
+
+#### Request
+
+
+```json
+{
+ "certificateSigningRequest": "string"
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificateSigningRequest` | Base64 encoded certificate signing request |
+
+#### Response
+
+
+```json
+{
+ "rootCertificate": "string",
+ "intermediateCertificate": "string",
+ "onboardingCertificate": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_ONBOARDING",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "deviceRegistry": {
+ "service": "DEVICE_REGISTRY_ONBOARDING_WITH_CSR_SERVICE",
+ "uri": "string"
+ },
+ "systemRegistry": {
+ "service": "SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_SERVICE",
+ "uri": "string"
+ },
+ "serviceRegistry": {
+ "service": "SERVICE_REGISTRY_REGISTER_SERVICE",
+ "uri": "string"
+ },
+ "orchestrationService": {
+ "service": "ORCHESTRATION_SERVICE",
+ "uri": "string"
+ }
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `rootCertificate` | The Arrowhead master certificate |
+| `intermediateCertificate` | The Arrowhead local cloud certificate |
+| `onboardingCertificate` | The onboarding certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_ONBOARDING for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key. Always empty for this operation |
+| `publicKey` | Base64 encoded public key |
+| `service` | The service which is reachable under `uri` |
+| `uri` | The uri under which the depicted `service` is reachable |
+
+
+# Device Registry
+
+
+## System Design Description Overview
+
+
+This System provides the database, which stores information related to the Devices within the Local Cloud.
+
+The purpose of this System is therefore to allow:
+- Devices to register themselves, making this announcement available to other Application Systems on the network.
+- They are also allowed to remove or update their entries when it is necessary.
+- Generate a client certificate which can be used by the Device to register its Systems
+
+## Services and Use Cases
+
+
+This System provides two Core Service: the __device registration__ and __de-registration__.
+Further it provides two Onboarding Services: the __onboarding with name__ and __onboarding with CSR__.
+
+The __register__ method is used to register a device. The device will contain various metadata as well as a physical endpoint.
+The various parameters are representing the endpoint information that should be registered.
+
+The __unregister__ method is used to unregister device instances that were previously registered in the Registry.
+The instance parameter is representing the endpoint information that should be removed.
+
+The __onboarding__ methods are used to register a device and to retrieve a device certificate which must be used on the next step of the onboarding procedure.
+
+## Security
+
+
+This System can be secured via the HTTPS protocol. If it is started in secure mode, it verifies whether the Application System possesses a proper X.509 identity certificate and whether that certificate is Arrowhead compliant in its making. This certificate structure and creation guidelines ensure:
+- Application System is properly bootstrapped into the Local Cloud
+- The Application System indeed belongs to this Local Cloud
+- The Application System then automatically has the right to register its Systems in the Registry.
+
+If these criteria are met, the Application System’s registration or removal message is processed. An Application System can only delete or alter entries that contain the Device as the System Provider in the entry.
+
+
+## Endpoints
+
+
+The System Registry offers four types of endpoints. Onboarding, Client, Management and Private.
+
+Swagger API documentation is available on: `https://:`
+The base URL for the requests: `http://:/deviceregistry`
+
+### Onboarding endpoint description
+
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Onboard with Name](#deviceregistry_endpoints_onboarding_name) | /onboarding/name | POST | [DeviceOnboardingWithNameRequest](#datastructures_deviceregistry_onboarding_with_name_request) | [DeviceOnboardingWithNameResponse](#datastructures_deviceregistry_onboarding_with_name_response) |
+| [Onboard with CSR](#deviceregistry_endpoints_onboarding_csr) | /onboarding/csr | POST | [DeviceOnboardingWithCsrRequest](#datastructures_deviceregistry_onboarding_with_csr_request) | [DeviceOnboardingWithCsrResponse](#datastructures_deviceregistry_onboarding_with_csr_response) |
+
+
+### Client endpoint description
+
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Echo](#deviceregistry_endpoints_get_echo) | /echo | GET | - | OK |
+| [Query](#deviceregistry_endpoints_post_query) | /query | POST | [DeviceQueryForm](#datastructures_systemqueryform) | [DeviceQueryList](#datastructures_devicequerylist) |
+| [Register](#deviceregistry_endpoints_post_register) | /register | POST | [DeviceRegistryEntry](#datastructures_deviceregistryentry) | [DeviceRegistryEntry](#datastructures_deviceregistryentry) |
+| [Unregister](#deviceregistry_delete_unregister) | /unregister | DELETE | Device Name and Mac Address in query parameters| OK |
+
+### Detailed description
+
+A detailed description of management and private endpoints is available in the release notes.
+
+### Onboard with Name
+
+
+```
+POST /onboarding/name
+```
+
+Creates a CSR on behalf of the client, registers the device and eventually returns a device certificate which may be used in the next step of the onboarding controller.
+
+#### Request
+
+
+```json
+{
+ "certificateCreationRequest": {
+ "commonName": "string",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "device": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "deviceName": "string",
+ "macAddress": "string"
+ },
+ "endOfValidity": "string",
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `commonName` | The common name field for the new certificate |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+| `address` | The optional IP address of the device |
+| `authenticationInfo` | Base64 encoded public key of the certificate this device |
+| `deviceName` | The device name |
+| `macAddress` | The MAC address of the device |
+| `endOfValidity` | The validity of this entry |
+| `metadata` | Various meta information as map |
+| `version` | The version of this entry |
+
+#### Response
+
+
+```json
+{
+ "certificateResponse": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_DEVICE",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "createdAt": "string",
+ "device": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "deviceName": "string",
+ "id": 0,
+ "macAddress": "string",
+ "updatedAt": "string"
+ },
+ "endOfValidity": "string",
+ "id": 0,
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "updatedAt": "string",
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificate` | The Base64 device certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_DEVICE for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+
+Additionally all fields from [DeviceRegistryEntry](#datastructures_deviceregistryentry) are returned.
+
+### Onboard with CSR
+
+
+```
+POST /onboarding/csr
+```
+
+Signs the CSR, registers the device and eventually returns a device certificate which may be used in the next step of the onboarding controller.
+
+#### Request
+
+
+```json
+{
+ "certificateSigningRequest": "string",
+ "device": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "deviceName": "string",
+ "macAddress": "string"
+ },
+ "endOfValidity": "string",
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificateSigningRequest` | Base64 encoded certificate signing request |
+| `address` | The optional IP address of the device |
+| `authenticationInfo` | Base64 encoded public key of the certificate this device |
+| `deviceName` | The device name |
+| `macAddress` | The MAC address of the device |
+| `endOfValidity` | The validity of this entry |
+| `metadata` | Various meta information as map |
+| `version` | The version of this entry |
+
+#### Response
+
+
+```json
+{
+ "certificateResponse": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_DEVICE",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "createdAt": "string",
+ "device": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "deviceName": "string",
+ "id": 0,
+ "macAddress": "string",
+ "updatedAt": "string"
+ },
+ "endOfValidity": "string",
+ "id": 0,
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "updatedAt": "string",
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificate` | The Base64 device certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_DEVICE for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key. Always empty for this operation |
+| `publicKey` | Base64 encoded public key |
+
+Additionally all fields from [DeviceRegistryEntry](#datastructures_deviceregistryentry) are returned.
+
+
+# System Registry
+
+
+
+## System Design Description Overview
+
+
+This System provides the database, which stores information related to the System of the currently actively offered Services within the Local Cloud.
+
+The purpose of this System is therefore to allow:
+- Devices to register which Systems they offer at the moment, making this announcement available to other Application Systems on the network.
+- They are also allowed to remove or update their entries when it is necessary.
+- Generate a client certificate which can be used by the System to offer Services
+
+
+## Services and Use Cases
+
+
+This System provides two Core Service the __system registration__ and __de-registration__
+
+The __register__ method is used to register a system. The system will contain various metadata as well as a physical endpoint.
+The various parameters are representing the endpoint information that should be registered.
+
+The __unregister__ method is used to unregister system instances that were previously registered in the Registry.
+The instance parameter is representing the endpoint information that should be removed.
+
+
+## Security
+
+
+This System can be secured via the HTTPS protocol. If it is started in secure mode, it verifies whether the Application System possesses a proper X.509 identity certificate and whether that certificate is Arrowhead compliant in its making. This certificate structure and creation guidelines ensure:
+- Application System is properly bootstrapped into the Local Cloud
+- The Application System indeed belongs to this Local Cloud
+- The Application System then automatically has the right to register its Services in the Registry.
+
+If these criteria are met, the Application System’s registration or removal message is processed. An Application System can only delete or alter entries that contain the Device as the System Provider in the entry.
+
+
+## Endpoints
+
+
+The System Registry offers three types of endpoints. Client, Management and Private.
+
+Swagger API documentation is available on: `https://:`
+The base URL for the requests: `http://:/systemregistry`
+
+### Onboarding endpoint description
+
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Onboard with Name](#systemregistry_endpoints_onboarding_name) | /onboarding/name | POST | [SystemOnboardingWithNameRequest](#datastructures_systemregistry_onboarding_with_name_request) | [SystemOnboardingWithNameResponse](#datastructures_systemregistry_onboarding_with_name_response) |
+| [Onboard with CSR](#systemregistry_endpoints_onboarding_csr) | /onboarding/csr | POST | [SystemOnboardingWithCsrRequest](#datastructures_systemregistry_onboarding_with_csr_request) | [SystemOnboardingWithCsrResponse](#datastructures_systemregistry_onboarding_with_csr_response) |
+
+
+### Client endpoint description
+
+
+| Function | URL subpath | Method | Input | Output |
+| -------- | ----------- | ------ | ----- | ------ |
+| [Echo](#systemregistry_endpoints_get_echo) | /echo | GET | - | OK |
+| [Query](#systemregistry_endpoints_post_query) | /query | POST | [SystemQueryForm](#datastructures_systemqueryform) | [SystemQueryList](#datastructures_systemquerylist) |
+| [Register](#systemregistry_endpoints_post_register) | /register | POST | [SystenRegistryEntry](#datastructures_systemregistryentry) | [SystenRegistryEntry](#datastructures_systemregistryentry) |
+| [Unregister](#systemregistry_delete_unregister) | /unregister | DELETE | System Name, Address and Port in query parameters| OK |
+
+### Detailed description
+
+A detailed description of public, management and private endpoints is available in the release notes.
+
+### Onboard with Name
+
+
+```
+POST /onboarding/name
+```
+
+Creates a CSR on behalf of the client, registers the system and eventually returns a system certificate which is valid in the Arrowhead local cloud.
+
+#### Request
+
+
+```json
+{
+ "certificateCreationRequest": {
+ "commonName": "string",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "provider": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "deviceName": "string",
+ "macAddress": "string"
+ },
+ "system": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "port": 0,
+ "systemName": "string"
+ },
+ "endOfValidity": "string",
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `commonName` | The common name field for the new certificate |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+| `address` | The IP address of the device/system |
+| `authenticationInfo` | Base64 encoded public key of the certificate this device/system |
+| `deviceName` | The device name |
+| `macAddress` | The MAC address of the device |
+| `systemName` | The system name |
+| `port` | The port under which this system's services are available |
+| `endOfValidity` | The validity of this entry |
+| `metadata` | Various meta information as map |
+| `version` | The version of this entry |
+
+#### Response
+
+
+```json
+{
+ "certificateResponse": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_SYSTEM",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "createdAt": "string",
+ "provider": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "deviceName": "string",
+ "id": 0,
+ "macAddress": "string",
+ "updatedAt": "string"
+ },
+ "system": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "id": 0,
+ "port": 0,
+ "systemName": "string",
+ "updatedAt": "string"
+ },
+ "endOfValidity": "string",
+ "id": 0,
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "updatedAt": "string",
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificate` | The Base64 device certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_SYSTEM for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key |
+| `publicKey` | Base64 encoded public key |
+
+Additionally all fields from [SystemRegistryEntry](#datastructures_systemregistryentry) are returned.
+
+### Onboard with CSR
+
+
+```
+POST /onboarding/csr
+```
+
+Signs the CSR, registers the device and eventually returns a device certificate which may be used in the next step of the onboarding controller.
+
+#### Request
+
+
+```json
+{
+ "certificateSigningRequest": "string",
+ "provider": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "deviceName": "string",
+ "macAddress": "string"
+ },
+ "system": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "port": 0,
+ "systemName": "string"
+ },
+ "endOfValidity": "string",
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificateSigningRequest` | Base64 encoded certificate signing request |
+| `address` | The IP address of the device/system |
+| `authenticationInfo` | Base64 encoded public key of the certificate this device/system |
+| `deviceName` | The device name |
+| `macAddress` | The MAC address of the device |
+| `systemName` | The system name |
+| `port` | The port under which this system's services are available |
+| `endOfValidity` | The validity of this entry |
+| `metadata` | Various meta information as map |
+| `version` | The version of this entry |
+
+#### Response
+
+
+```json
+{
+ "certificateResponse": {
+ "certificate": "string",
+ "certificateFormat": "string",
+ "certificateType": "AH_SYSTEM",
+ "keyPairDTO": {
+ "keyAlgorithm": "string",
+ "keyFormat": "string",
+ "privateKey": "string",
+ "publicKey": "string"
+ }
+ },
+ "createdAt": "string",
+ "provider": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "deviceName": "string",
+ "id": 0,
+ "macAddress": "string",
+ "updatedAt": "string"
+ },
+ "system": {
+ "address": "string",
+ "authenticationInfo": "string",
+ "createdAt": "string",
+ "id": 0,
+ "port": 0,
+ "systemName": "string",
+ "updatedAt": "string"
+ },
+ "endOfValidity": "string",
+ "id": 0,
+ "metadata": {
+ "additionalProp1": "string",
+ "additionalProp2": "string",
+ "additionalProp3": "string"
+ },
+ "updatedAt": "string",
+ "version": 0
+}
+```
+
+| Field | Description |
+| ----- | ----------- |
+| `certificate` | The Base64 device certificate for the next step |
+| `certificateFormat` | The certificate format (usually X.509) |
+| `certificateType` | The certificate type. Always AH_DEVICE for this operation |
+| `keyAlgorithm` | The key algorithm of the provided keys |
+| `keyFormat` | The key format of the provided keys |
+| `privateKey` | Base64 encoded private key. Always empty for this operation |
+| `publicKey` | Base64 encoded public key |
+
+Additionally all fields from [SystemRegistryEntry](#datastructures_systemregistryentry) are returned.
+
diff --git a/authorization/.classpath b/authorization/.classpath
index 01997bb0d..e210343c4 100644
--- a/authorization/.classpath
+++ b/authorization/.classpath
@@ -45,5 +45,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/authorization/src/main/java/eu/arrowhead/core/authorization/AuthorizationController.java b/authorization/src/main/java/eu/arrowhead/core/authorization/AuthorizationController.java
index f38c0adec..9d4b49e5e 100644
--- a/authorization/src/main/java/eu/arrowhead/core/authorization/AuthorizationController.java
+++ b/authorization/src/main/java/eu/arrowhead/core/authorization/AuthorizationController.java
@@ -597,10 +597,6 @@ public void removeAuthorizationInterCloudById(@PathVariable(value = PATH_VARIABL
logger.debug("New token generation request received");
checkTokenGenerationRequest(request);
- if (request.getDuration() != null && request.getDuration().intValue() <= 0) {
- request.setDuration(null);
- }
-
final TokenGenerationResponseDTO response = tokenGenerationService.generateTokensResponse(request);
logger.debug("{} token(s) are generated for {}", calculateNumberOfTokens(response.getTokenData()), request.getConsumer().getSystemName());
@@ -669,6 +665,10 @@ private void checkTokenGenerationProviderDTO(final TokenGenerationProviderDTO pr
throw new BadPayloadException("Specified interface name is not valid: " + intf, HttpStatus.SC_BAD_REQUEST, origin);
}
}
+
+ if (provider.getTokenDuration() <= 0) {
+ provider.setTokenDuration(-1);
+ }
}
//-------------------------------------------------------------------------------------------------
diff --git a/authorization/src/main/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBService.java b/authorization/src/main/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBService.java
index 81ea655b3..85ccbcd41 100644
--- a/authorization/src/main/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBService.java
+++ b/authorization/src/main/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBService.java
@@ -629,7 +629,7 @@ private List createBulkAuthorizationIntraCloudWithOnePr
checkConstraintsOfAuthorizationIntraCloudTable(consumer, provider, service);
toBeSaved.add(new AuthorizationIntraCloud(consumer, provider, service));
} catch (final InvalidParameterException ex) {
- //not throwing towards as in this bulk operation case should be only a warning
+ // not throwing towards as in this bulk operation case should be only a warning
logger.debug(ex.getMessage());
}
} else {
@@ -784,7 +784,7 @@ private List createBulkAuthorizationInterCloudWithOneSe
checkConstraintsOfAuthorizationInterCloudTable(cloud, provider, service);
toBeSaved.add(new AuthorizationInterCloud(cloud, provider, service));
} catch (final InvalidParameterException ex) {
- //not throwing towards as in this bulk operation case should be only a warning
+ // not throwing towards as in this bulk operation case should be only a warning
logger.debug(ex.getMessage());
}
} else {
diff --git a/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthAccessControlFilter.java b/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthAccessControlFilter.java
index ecb04cbbc..2714c3ab5 100644
--- a/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthAccessControlFilter.java
+++ b/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthAccessControlFilter.java
@@ -16,10 +16,11 @@ public class AuthAccessControlFilter extends CoreSystemAccessControlFilter {
//=================================================================================================
// members
-
+ private static final String AUTHORIZATION_INTRA_CLOUD_MGMT_URI = CoreCommonConstants.MGMT_URI + "/intracloud";
private static final CoreSystem[] allowedCoreSystemsForChecks = { CoreSystem.ORCHESTRATOR, CoreSystem.GATEKEEPER };
private static final CoreSystem[] allowedCoreSystemsForSubscriptionChecks = { CoreSystem.EVENT_HANDLER };
-
+ private static final CoreSystem[] allowedCoreSystemsForRuleMgmt = { CoreSystem.ONBOARDING_CONTROLLER };
+
//=================================================================================================
// assistant methods
@@ -31,6 +32,11 @@ protected void checkClientAuthorized(final String clientCN, final String method,
final String cloudCN = getServerCloudCN();
if (requestTarget.endsWith(CommonConstants.OP_AUTH_KEY_URI) || requestTarget.endsWith(CommonConstants.ECHO_URI)) {
// Everybody in the local cloud can get the Authorization public key (because it is PUBLIC) or test the server => no further check is necessary
+ } else if (requestTarget.endsWith(AUTHORIZATION_INTRA_CLOUD_MGMT_URI)) {
+ // onboarding controller may use this method
+ if(!checkIfClientIsAnAllowedCoreSystemNoException(clientCN, cloudCN, allowedCoreSystemsForRuleMgmt, requestTarget)) {
+ checkIfLocalSystemOperator(clientCN, cloudCN, requestTarget);
+ }
} else if (requestTarget.contains(CoreCommonConstants.MGMT_URI)) {
// Only the local System Operator can use these methods
checkIfLocalSystemOperator(clientCN, cloudCN, requestTarget);
diff --git a/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthSecurityConfig.java b/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthSecurityConfig.java
index 9cfe85970..a82654572 100644
--- a/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthSecurityConfig.java
+++ b/authorization/src/main/java/eu/arrowhead/core/authorization/security/AuthSecurityConfig.java
@@ -8,5 +8,4 @@
@Configuration
@EnableWebSecurity
public class AuthSecurityConfig extends DefaultSecurityConfig {
-
}
\ No newline at end of file
diff --git a/authorization/src/main/java/eu/arrowhead/core/authorization/token/TokenGenerationService.java b/authorization/src/main/java/eu/arrowhead/core/authorization/token/TokenGenerationService.java
index 86da3e05c..5a510b81a 100644
--- a/authorization/src/main/java/eu/arrowhead/core/authorization/token/TokenGenerationService.java
+++ b/authorization/src/main/java/eu/arrowhead/core/authorization/token/TokenGenerationService.java
@@ -44,6 +44,7 @@ public class TokenGenerationService {
private final Logger logger = LogManager.getLogger(TokenGenerationService.class);
+ private static final String DOT = ".";
private static final String JWT_CONTENT_TYPE = "JWT";
@Value(CommonConstants.$SERVER_SSL_ENABLED_WD)
@@ -78,21 +79,17 @@ public Map> generateTokens(final TokenGenera
final Map publicKeys = getProviderPublicKeys(request.getProviders());
final Map> result = new HashMap<>(publicKeys.size());
final String consumerInfo = generateConsumerInfo(request.getConsumer(), request.getConsumerCloud());
- final Map signedJWTs = new HashMap<>();
for (final TokenGenerationProviderDTO provider : request.getProviders()) {
final SystemRequestDTO providerSystem = provider.getProvider();
if (publicKeys.containsKey(providerSystem)) {
for (final String intf : provider.getServiceInterfaces()) {
- String signedJWT = signedJWTs.get(intf);
- if (signedJWT == null) {
- try {
- signedJWT = generateSignedJWT(consumerInfo, request.getService(), intf, request.getDuration());
- signedJWTs.put(intf, signedJWT);
- } catch (final JoseException ex) {
- logger.error("Problem occured when trying to sign JWT token", ex);
- throw new ArrowheadException("Token generation failed"); // if there is a problem here, all calling cause the same problem
- }
+ String signedJWT;
+ try {
+ signedJWT = generateSignedJWT(consumerInfo, request.getService(), intf, provider.getTokenDuration() < 0 ? null: provider.getTokenDuration());
+ } catch (final JoseException ex) {
+ logger.error("Problem occured when trying to sign JWT token", ex);
+ throw new ArrowheadException("Token generation failed"); // if there is a problem here, all calling cause the same problem
}
try {
@@ -174,7 +171,7 @@ private void checkTokenGeneratorionProviderDTO(final TokenGenerationProviderDTO
for (final String intf : provider.getServiceInterfaces()) {
if (!interfaceNameVerifier.isValid(intf)) {
- throw new InvalidParameterException("Specified interface name is not valid: " + intf + ".");
+ throw new InvalidParameterException("Specified interface name is not valid: " + intf + DOT);
}
}
}
@@ -194,14 +191,14 @@ private String generateConsumerInfo(final SystemRequestDTO consumer, final Cloud
final StringBuilder sb = new StringBuilder(consumer.getSystemName());
if (consumerCloud != null) {
- sb.append(".").append(consumerCloud.getName().trim()).append(".").append(consumerCloud.getOperator().trim());
+ sb.append(DOT).append(consumerCloud.getName().trim()).append(DOT).append(consumerCloud.getOperator().trim());
} else {
// need to use own cloud information
if (Utilities.isEmpty(ownCloudName)) {
initOwnCloudInfo();
}
- sb.append(".").append(ownCloudName).append(".").append(ownCloudOperator);
+ sb.append(DOT).append(ownCloudName).append(DOT).append(ownCloudOperator);
}
return sb.toString().toLowerCase();
@@ -284,7 +281,7 @@ private JwtClaims generateTokenPayload(final String consumerInfo, final String s
claims.setIssuedAtToNow();
claims.setNotBeforeMinutesInThePast(1);
if (duration != null) {
- claims.setExpirationTimeMinutesInTheFuture(duration.floatValue());
+ claims.setExpirationTimeMinutesInTheFuture(duration.floatValue() / CommonConstants.CONVERSION_SECOND_TO_MINUTE);
}
claims.setStringClaim(CommonConstants.JWT_CLAIM_CONSUMER_ID, consumerInfo);
claims.setStringClaim(CommonConstants.JWT_CLAIM_SERVICE_ID, service.toLowerCase());
diff --git a/authorization/src/main/resources/application.properties b/authorization/src/main/resources/application.properties
index e5921426f..ae4c9157c 100644
--- a/authorization/src/main/resources/application.properties
+++ b/authorization/src/main/resources/application.properties
@@ -61,6 +61,6 @@ server.ssl.trust-store-type=PKCS12
server.ssl.trust-store=classpath:certificates/truststore.p12
server.ssl.trust-store-password=123456
-#If true, http client does not check whether the hostname is match one of the server's SAN in its certificate
-#Just for testing, DO NOT USE this feature in production environment
+# If true, http client does not check whether the hostname is match one of the server's SAN in its certificate
+# Just for testing, DO NOT USE this feature in production environment
disable.hostname.verifier=false
\ No newline at end of file
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerInterCloudTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerInterCloudTest.java
index 41ac703e7..18e58e886 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerInterCloudTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerInterCloudTest.java
@@ -435,7 +435,7 @@ public void testCheckAuthorizationInterCloudRequestDBCall() throws Exception {
//-------------------------------------------------------------------------------------------------
private List createIdList(final int firstNum, final int lastNum) {
- final List idList = new ArrayList<>(lastNum);
+ final List idList = new ArrayList<>(lastNum - firstNum + 1);
for (int i = firstNum; i <= lastNum; ++i) {
idList.add((long) i);
}
@@ -449,7 +449,7 @@ private Page createPageForMockingAuthorizationDBService
final Cloud cloud = getValidTestCloud();
final System provider = new System("testSystem", "testAddr", 2000, "TOKEN");
for (int i = 1; i <= numberOfRequestedEntry; ++i) {
- final ServiceDefinition serviceDefinition = new ServiceDefinition("testService"+i);
+ final ServiceDefinition serviceDefinition = new ServiceDefinition("testService" + i);
serviceDefinition.setId(i);
serviceDefinition.setCreatedAt(zdTime);
serviceDefinition.setUpdatedAt(zdTime);
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerIntraCloudTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerIntraCloudTest.java
index e4fe7b858..cc36f6f22 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerIntraCloudTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerIntraCloudTest.java
@@ -511,7 +511,7 @@ private Page createPageForMockingAuthorizationDBService
//-------------------------------------------------------------------------------------------------
private List createIdList(final int firstNum, final int lastNum) {
- final List idList = new ArrayList<>(lastNum);
+ final List idList = new ArrayList<>(lastNum - firstNum + 1);
for (int i = firstNum; i <= lastNum; ++i) {
idList.add((long) i);
}
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerTokenTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerTokenTest.java
index 2b0593fec..33a528f24 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerTokenTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/AuthorizationControllerTokenTest.java
@@ -529,8 +529,8 @@ private TokenGenerationRequestDTO getRequest() {
provider.setPort(18765);
provider.setAuthenticationInfo("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1aaeuv1I4bF5dxMIvUvLMxjRn309kdJewIIH08DfL17/LSssD70ZaLz0yxNfbPPQpFK8LMK+HQHDiGZH5yp4qJDuEgfmUrqWibnBIBc/K3Ob45lQy0zdFVtFsVJYBFVymQwgxJT6th0hI3RGLbCJMzbmpDzT7g0IDsN+64tMyi08ZCPrqk99uzYgioSSWNb9bhG2Z9646b3oiY5utQWRhP/2z/t6vVJHtRYeyaXPl6Z2M/5KnjpSvpSeZQhNrw+Is1DEE5DHiEjfQFWrLwDOqPKDrvmFyIlJ7P7OCMax6dIlSB7GEQSSP+j4eIxDWgjm+Pv/c02UVDc0x3xX/UGtNwIDAQAB");
- final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO(provider, List.of("HTTP-SECURE-JSON"));
+ final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO(provider, 6000, List.of("HTTP-SECURE-JSON"));
- return new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(providerDTO), "aservice", null);
+ return new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(providerDTO), "aservice");
}
}
\ No newline at end of file
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/StandaloneModeInAuthorizationTests.java b/authorization/src/test/java/eu/arrowhead/core/authorization/StandaloneModeInAuthorizationTests.java
index 3f9dfa70e..6b0cdf6ff 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/StandaloneModeInAuthorizationTests.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/StandaloneModeInAuthorizationTests.java
@@ -6,5 +6,4 @@
@Component
public class StandaloneModeInAuthorizationTests extends StandaloneModeInTests {
-
}
\ No newline at end of file
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceInterCloudTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceInterCloudTest.java
index 31a889dad..08f953943 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceInterCloudTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceInterCloudTest.java
@@ -73,7 +73,7 @@ public class AuthorizationDBServiceInterCloudTest {
// methods
//=================================================================================================
- //Tests of getAuthorizationInterCloudEntries
+ // Tests of getAuthorizationInterCloudEntries
//-------------------------------------------------------------------------------------------------
@Test
@@ -90,7 +90,7 @@ public void testGetAuthorizationInterCloudEntriesWithNotValidSortField() {
}
//=================================================================================================
- //Tests of getAuthorizationInterCloudEntryById
+ // Tests of getAuthorizationInterCloudEntryById
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
@@ -100,7 +100,7 @@ public void testGetAuthorizationInterCloudEntryByIdWithNotExistingId() {
}
//=================================================================================================
- //Tests of removeAuthorizationInterCloudEntryById
+ // Tests of removeAuthorizationInterCloudEntryById
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
@@ -110,7 +110,7 @@ public void testRemoveAuthorizationInterCloudEntryByIdWithNotExistingId() {
}
//=================================================================================================
- //Tests of createBulkAuthorizationInterCloud
+ // Tests of createBulkAuthorizationInterCloud
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
@@ -224,7 +224,7 @@ public void testCreateBulkAuthorizationInterCloudDBCall() {
}
//=================================================================================================
- //Tests of checkAuthorizationInterCloudResponse
+ // Tests of checkAuthorizationInterCloudResponse
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceIntraCloudTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceIntraCloudTest.java
index ce14de33c..71760a404 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceIntraCloudTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/database/service/AuthorizationDBServiceIntraCloudTest.java
@@ -65,7 +65,7 @@ public class AuthorizationDBServiceIntraCloudTest {
// methods
//=================================================================================================
- //Tests of getAuthorizationIntraCloudEntries
+ // Tests of getAuthorizationIntraCloudEntries
//-------------------------------------------------------------------------------------------------
@Test
@@ -82,7 +82,7 @@ public void testGetAuthorizationIntraCloudEntriesWithNotValidSortField() {
}
//=================================================================================================
- //Tests of getAuthorizationIntraCloudEntryById
+ // Tests of getAuthorizationIntraCloudEntryById
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
@@ -92,7 +92,7 @@ public void testGetAuthorizationIntraCloudEntryByIdWithNotExistingId() {
}
//=================================================================================================
- //Tests of removeAuthorizationIntraCloudEntryById
+ // Tests of removeAuthorizationIntraCloudEntryById
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
@@ -102,7 +102,7 @@ public void testRemoveAuthorizationIntraCloudEntryByIdWithNotExistingId() {
}
//=================================================================================================
- //Tests of createBulkAuthorizationIntraCloud
+ // Tests of createBulkAuthorizationIntraCloud
//-------------------------------------------------------------------------------------------------
@Test(expected = InvalidParameterException.class)
diff --git a/authorization/src/test/java/eu/arrowhead/core/authorization/token/TokenGenerationServiceTest.java b/authorization/src/test/java/eu/arrowhead/core/authorization/token/TokenGenerationServiceTest.java
index 948994922..2f910d121 100644
--- a/authorization/src/test/java/eu/arrowhead/core/authorization/token/TokenGenerationServiceTest.java
+++ b/authorization/src/test/java/eu/arrowhead/core/authorization/token/TokenGenerationServiceTest.java
@@ -91,7 +91,7 @@ public void testGenerateTokenNullConsumer() {
@Test(expected = InvalidParameterException.class)
public void testGenerateTokenConsumerNameNull() {
final SystemRequestDTO consumer = new SystemRequestDTO();
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -100,7 +100,7 @@ public void testGenerateTokenConsumerNameNull() {
public void testGenerateTokenConsumerNameEmpty() {
final SystemRequestDTO consumer = new SystemRequestDTO();
consumer.setSystemName(" ");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -109,7 +109,7 @@ public void testGenerateTokenConsumerNameEmpty() {
public void testGenerateTokenConsumerCloudOperatorNull() {
final SystemRequestDTO consumer = new SystemRequestDTO();
consumer.setSystemName("consumer");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, new CloudRequestDTO(), List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, new CloudRequestDTO(), List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -120,7 +120,7 @@ public void testGenerateTokenConsumerCloudOperatorEmpty() {
consumer.setSystemName("consumer");
final CloudRequestDTO consumerCloud = new CloudRequestDTO();
consumerCloud.setOperator(" ");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -131,7 +131,7 @@ public void testGenerateTokenConsumerCloudNameNull() {
consumer.setSystemName("consumer");
final CloudRequestDTO consumerCloud = new CloudRequestDTO();
consumerCloud.setOperator("aitia");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -143,7 +143,7 @@ public void testGenerateTokenConsumerCloudNameEmpty() {
final CloudRequestDTO consumerCloud = new CloudRequestDTO();
consumerCloud.setOperator("aitia");
consumerCloud.setName(" ");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, consumerCloud, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -152,7 +152,7 @@ public void testGenerateTokenConsumerCloudNameEmpty() {
public void testGenerateTokenProvidersListNull() {
final SystemRequestDTO consumer = new SystemRequestDTO();
consumer.setSystemName("consumer");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService");
request.setProviders(null);
tokenGenerationService.generateTokens(request);
}
@@ -162,7 +162,7 @@ public void testGenerateTokenProvidersListNull() {
public void testGenerateTokenProvidersListEmpty() {
final SystemRequestDTO consumer = new SystemRequestDTO();
consumer.setSystemName("consumer");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService");
request.setProviders(List.of());
tokenGenerationService.generateTokens(request);
}
@@ -172,7 +172,7 @@ public void testGenerateTokenProvidersListEmpty() {
public void testGenerateTokenProviderNull() {
final SystemRequestDTO consumer = new SystemRequestDTO();
consumer.setSystemName("consumer");
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(new TokenGenerationProviderDTO()), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -183,7 +183,7 @@ public void testGenerateTokenProviderNameNull() {
consumer.setSystemName("consumer");
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(new SystemRequestDTO());
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -196,7 +196,7 @@ public void testGenerateTokenProviderNameEmpty() {
provider.setSystemName(" ");
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -209,7 +209,7 @@ public void testGenerateTokenServiceInterfacesNull() {
provider.setSystemName("provider");
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -223,7 +223,7 @@ public void testGenerateTokenServiceInterfacesEmpty() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of());
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -237,7 +237,7 @@ public void testGenerateTokenServiceInterfaceInvalid() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("INVALID"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -251,7 +251,7 @@ public void testGenerateTokenServiceNull() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
request.setService(null);
tokenGenerationService.generateTokens(request);
}
@@ -266,7 +266,7 @@ public void testGenerateTokenServiceEmpty() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
request.setService(" \t");
tokenGenerationService.generateTokens(request);
}
@@ -281,7 +281,7 @@ public void testGenerateTokenProviderHasNoKey() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -296,7 +296,7 @@ public void testGenerateTokenProviderHasNotValidKey() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -313,7 +313,7 @@ public void testGenerateTokenProviderInitOwnCloudFromCertificateNoCommonName() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, null, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -331,7 +331,7 @@ public void testGenerateTokenProviderNoServerPrivateKey() {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -351,7 +351,7 @@ public void testGenerateTokenProviderErrorWhileSigning() throws Exception {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testService", null);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testService");
tokenGenerationService.generateTokens(request);
}
@@ -375,7 +375,8 @@ public void testTokenGenerationOk() throws Exception {
final TokenGenerationProviderDTO providerDTO = new TokenGenerationProviderDTO();
providerDTO.setProvider(provider);
providerDTO.setServiceInterfaces(List.of("HTTP-SECURE-JSON"));
- final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testservice", 10);
+ providerDTO.setTokenDuration(600);
+ final TokenGenerationRequestDTO request = new TokenGenerationRequestDTO(consumer, cloud, List.of(providerDTO), "testservice");
final Map> result = tokenGenerationService.generateTokens(request);
Assert.assertTrue(!result.isEmpty());
Assert.assertTrue(result.containsKey(provider));
diff --git a/certificate-authority/.classpath b/certificate-authority/.classpath
new file mode 100644
index 000000000..6e0021feb
--- /dev/null
+++ b/certificate-authority/.classpath
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/certificate-authority/.project b/certificate-authority/.project
new file mode 100644
index 000000000..9b4a8b591
--- /dev/null
+++ b/certificate-authority/.project
@@ -0,0 +1,23 @@
+
+
+ arrowhead-certificate-authority
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/certificate-authority/pom.xml b/certificate-authority/pom.xml
new file mode 100644
index 000000000..257563a28
--- /dev/null
+++ b/certificate-authority/pom.xml
@@ -0,0 +1,153 @@
+
+ 4.0.0
+
+ eu.arrowhead
+ core
+ ${revision}
+
+
+ arrowhead-certificate-authority
+ jar
+ Arrowhead Certificate Authority
+ Certificate Authority core service
+
+
+
+ eu.arrowhead
+ arrowhead-core-common
+ ${revision}
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+ ${bouncy.castle.version}
+
+
+
+ org.bouncycastle
+ bcpkix-jdk15on
+ ${bouncy.castle.version}
+
+
+ org.jetbrains
+ annotations
+ 18.0.0
+ compile
+
+
+
+
+
+
+ maven-resources-plugin
+ ${mvn.resources.version}
+
+
+ copy-resources
+
+ validate
+
+ copy-resources
+
+
+ ${basedir}/target
+
+
+ src/main/resources
+
+ application.properties
+ log4j2.xml
+
+
+
+
+
+
+
+
+
+ jdeb
+ org.vafer
+ 1.8
+
+
+ package
+
+ jdeb
+
+
+ true
+ [YYMMddHHmm].${git.commit.id.abbrev}
+ target/${project.artifactId}_${revision}.deb
+ true
+ ${basedir}/src/deb/control
+
+
+ file
+ ${project.build.directory}/${project.build.finalName}.jar
+
+ perm
+ /usr/share/arrowhead/certificate_authority
+ 755
+
+
+
+
+ link
+ /usr/share/arrowhead/certificate_authority/${project.artifactId}.jar
+ /usr/share/arrowhead/certificate_authority/${project.build.finalName}.jar
+
+
+
+ file
+ ${project.build.directory}/log4j2.xml
+
+ perm
+ /etc/arrowhead/systems/certificate_authority
+ 644
+
+
+
+
+ file
+ ${project.build.directory}/application.properties
+
+ perm
+ /etc/arrowhead/systems/certificate_authority
+ 644
+
+
+
+
+ link
+ /usr/share/arrowhead/certificate_authority/application.properties
+ /etc/arrowhead/systems/certificate_authority/application.properties
+
+
+
+ file
+ ${project.basedir}/src/deb/arrowhead-certificate-authority.service
+
+ perm
+ /etc/systemd/system
+ 644
+
+
+
+
+ file
+ ${project.basedir}/../scripts/certificate_authority_privileges.sql
+
+ perm
+ /usr/share/arrowhead/conf
+
+
+
+
+
+
+
+
+
+
diff --git a/certificate-authority/src/deb/arrowhead-certificate-authority.service b/certificate-authority/src/deb/arrowhead-certificate-authority.service
new file mode 100644
index 000000000..31d62af19
--- /dev/null
+++ b/certificate-authority/src/deb/arrowhead-certificate-authority.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=arrowhead-certificate-authority
+After=network.target mysql.target
+
+[Service]
+WorkingDirectory=/etc/arrowhead/systems/certificate_authority
+ExecStart=/usr/bin/java -Dlog4j.configurationFile=file:/etc/arrowhead/systems/certificate_authority/log4j2.xml -jar /usr/share/arrowhead/certificate_authority/arrowhead-certificate-authority.jar
+ExecStartPost=/bin/bash -c 'sleep 10'
+TimeoutStopSec=5
+Type=simple
+User=arrowhead
+Group=arrowhead
+
+[Install]
+WantedBy=default.target
diff --git a/certificate-authority/src/deb/control/config b/certificate-authority/src/deb/control/config
new file mode 100644
index 000000000..1c83ed2f4
--- /dev/null
+++ b/certificate-authority/src/deb/control/config
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+
+. /usr/share/debconf/confmodule
+
+if logname 2>/dev/null; then
+ USER=$(logname)
+ HOME=$(eval echo "~$USER")
+else
+ USER="root"
+ HOME="/root"
+fi
+
+# Get installation type
+db_input high arrowhead-core-common/db_host || true
+db_input high arrowhead-core-common/mysql_password_ca || true
+db_input high arrowhead-core-common/sr_host || true
+
+# Run dialogs
+db_go || true
+
diff --git a/certificate-authority/src/deb/control/control b/certificate-authority/src/deb/control/control
new file mode 100644
index 000000000..1b7ccbf25
--- /dev/null
+++ b/certificate-authority/src/deb/control/control
@@ -0,0 +1,10 @@
+Package: arrowhead-certificate-authority
+Version: [[version]]
+Section: contrib/java
+Priority: optional
+Architecture: all
+Maintainer: Rajmund Bocsi
+Homepage: http://www.arrowhead.eu
+Description: Arrowhead Certificate Authority
+Distribution: development
+Depends: java-runtime-headless, openssl, virtual-mysql-server, arrowhead-core-common
diff --git a/certificate-authority/src/deb/control/postinst b/certificate-authority/src/deb/control/postinst
new file mode 100644
index 000000000..a47d9de5a
--- /dev/null
+++ b/certificate-authority/src/deb/control/postinst
@@ -0,0 +1,82 @@
+#!/bin/sh
+# postinst script for arrowhead-certificate-authority
+#
+# see: dh_installdeb(1)
+
+set -e
+
+. /usr/share/debconf/confmodule
+
+SYSTEM_NAME="certificate_authority"
+PKG_NAME="arrowhead-certificate-authority"
+
+# summary of how this script can be called:
+# * `configure'
+# * `abort-upgrade'
+# * `abort-remove' `in-favour'
+#
+# * `abort-remove'
+# * `abort-deconfigure' `in-favour'
+# `removing'
+#
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+ configure)
+ . /usr/share/arrowhead/conf/ahconf.sh
+ SYSTEM_DIR="${AH_SYSTEMS_DIR}/${SYSTEM_NAME}"
+
+ db_get arrowhead-core-common/mysql_password_ca; system_passwd=$RET || true
+ db_unregister arrowhead-core-common/mysql_password_ca
+
+ # Generate password (if required)
+ if [ -z "${system_passwd}" ]; then
+ system_passwd="$(openssl rand -base64 12)"
+ fi
+
+ echo "Configuring MySQL database..." >&2
+ ah_db_tables_and_user ${SYSTEM_NAME} ${SYSTEM_NAME}_privileges.sql ${system_passwd}
+
+ if [ ! -d "${SYSTEM_DIR}" ]; then
+ mkdir -p ${SYSTEM_DIR}
+ fi
+
+ ah_ca_keystore ${SYSTEM_NAME}
+
+ mv ${SYSTEM_DIR}/application.properties ${SYSTEM_DIR}/application.properties.orig
+ cat ${SYSTEM_DIR}/application.properties.orig | \
+ sed -r -e "\#^.*spring\.datasource\.url=#s#.*\$#spring.datasource.url=jdbc:mysql://"${db_host}":3306/arrowhead?serverTimezone=Europe/Budapest#" \
+ -e "\#^.*spring\.datasource\.password=#s#.*\$#spring.datasource.password=${system_passwd}#" \
+ -e "\#^.*server\.address=#s#.*\$#server.address=${OWN_IP}#" \
+ -e "\#^.*server\.ssl\.key-store=#s#.*\$#server.ssl.key-store=file:${SYSTEM_DIR}/${SYSTEM_NAME}.p12#" \
+ -e "\#^.*server\.ssl\.key-store-password=#s#.*\$#server.ssl.key-store-password=${AH_PASS_CERT}#" \
+ -e "\#^.*server\.ssl\.key-password=#s#.*\$#server.ssl.key-password=${AH_PASS_CERT}#" \
+ -e "\#^.*server\.ssl\.trust-store=#s#.*\$#server.ssl.trust-store=file:${AH_CONF_DIR}/truststore.p12#" \
+ -e "\#^.*server\.ssl\.trust-store-password=#s#.*\$#server.ssl.trust-store-password=${AH_PASS_CERT}#" > ${SYSTEM_DIR}/application.properties
+
+ rm ${SYSTEM_DIR}/application.properties.orig
+ chown arrowhead:arrowhead ${SYSTEM_DIR}/application.properties
+ chmod 640 ${SYSTEM_DIR}/application.properties
+
+ echo "Starting ${PKG_NAME}..." >&2
+ systemctl daemon-reload
+ systemctl enable ${PKG_NAME}.service
+ systemctl start ${PKG_NAME}.service
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/certificate-authority/src/deb/control/postrm b/certificate-authority/src/deb/control/postrm
new file mode 100644
index 000000000..5ec593529
--- /dev/null
+++ b/certificate-authority/src/deb/control/postrm
@@ -0,0 +1,54 @@
+#!/bin/sh
+# postrm script for arrowhead-certificate-authority
+#
+# see: dh_installdeb(1)
+
+set -e
+
+. /usr/share/debconf/confmodule
+
+SYSTEM_NAME="certificate_authority"
+
+# summary of how this script can be called:
+# * `remove'
+# * `purge'
+# * `upgrade'
+# * `failed-upgrade'
+# * `abort-install'
+# * `abort-install'
+# * `abort-upgrade'
+# * `disappear'
+#
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ purge)
+ AH_CONF_DIR="/etc/arrowhead"
+ AH_SYSTEMS_DIR="${AH_CONF_DIR}/systems"
+ SYSTEM_DIR="${AH_SYSTEMS_DIR}/${SYSTEM_NAME}"
+
+ rm -f \
+ /var/log/arrowhead/${SYSTEM_NAME}*.log \
+ ${SYSTEM_DIR}/log4j2.xml \
+ ${SYSTEM_DIR}/application.properties \
+ ${SYSTEM_DIR}/${SYSTEM_NAME}.p12 \
+ rmdir ${SYSTEM_DIR} 2>/dev/null || true
+ db_purge
+ ;;
+ remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/certificate-authority/src/deb/control/preinst b/certificate-authority/src/deb/control/preinst
new file mode 100644
index 000000000..a0a30f7d9
--- /dev/null
+++ b/certificate-authority/src/deb/control/preinst
@@ -0,0 +1,35 @@
+#!/bin/sh
+# preinst script for arrowhead-certificate-authority
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `install'
+# * `install'
+# * `upgrade'
+# * `abort-upgrade'
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ install|upgrade)
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/certificate-authority/src/deb/control/prerm b/certificate-authority/src/deb/control/prerm
new file mode 100644
index 000000000..4c2d565a7
--- /dev/null
+++ b/certificate-authority/src/deb/control/prerm
@@ -0,0 +1,45 @@
+#!/bin/sh
+# prerm script for arrowhead-certificate-authority
+#
+# see: dh_installdeb(1)
+
+set -e
+
+PKG_NAME="arrowhead-certificate-authority"
+
+# summary of how this script can be called:
+# * `remove'
+# * `upgrade'
+# * `failed-upgrade'
+# * `remove' `in-favour'
+# * `deconfigure' `in-favour'
+# `removing'
+#
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove)
+ systemctl stop ${PKG_NAME}.service
+ systemctl disable ${PKG_NAME}.service
+ ;;
+
+ upgrade|deconfigure)
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CAProperties.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CAProperties.java
new file mode 100644
index 000000000..d4120006a
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CAProperties.java
@@ -0,0 +1,24 @@
+package eu.arrowhead.core.certificate_authority;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import eu.arrowhead.common.CommonConstants;
+
+@Component
+public class CAProperties {
+
+ @Value(CommonConstants.$CA_CERT_VALIDITY_NEG_OFFSET_MILLIS)
+ private long certValidityNegativeOffsetMinutes;
+
+ @Value(CommonConstants.$CA_CERT_VALIDITY_POS_OFFSET_MILLIS)
+ private long certValidityPositiveOffsetMinutes;
+
+ public long getCertValidityNegativeOffsetMinutes() {
+ return certValidityNegativeOffsetMinutes;
+ }
+
+ public long getCertValidityPositiveOffsetMinutes() {
+ return certValidityPositiveOffsetMinutes;
+ }
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityApplicationInitListener.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityApplicationInitListener.java
new file mode 100644
index 000000000..aa3e97061
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityApplicationInitListener.java
@@ -0,0 +1,20 @@
+package eu.arrowhead.core.certificate_authority;
+
+import java.security.Security;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+import eu.arrowhead.common.ApplicationInitListener;
+
+@Component
+public class CertificateAuthorityApplicationInitListener extends ApplicationInitListener {
+
+ @Override
+ protected void customInit(ContextRefreshedEvent event) {
+ logger.debug("customInit started...");
+
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityController.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityController.java
new file mode 100644
index 000000000..75608ddb3
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityController.java
@@ -0,0 +1,106 @@
+package eu.arrowhead.core.certificate_authority;
+
+import java.util.List;
+
+import javax.validation.Valid;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.CoreCommonConstants;
+import eu.arrowhead.common.Defaults;
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+import eu.arrowhead.common.dto.internal.CertificateSigningResponseDTO;
+import eu.arrowhead.common.exception.BadPayloadException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.http.HttpStatus;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.ObjectError;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = { CoreCommonConstants.SWAGGER_TAG_ALL })
+@CrossOrigin(maxAge = Defaults.CORS_MAX_AGE, allowCredentials = Defaults.CORS_ALLOW_CREDENTIALS,
+ allowedHeaders = { HttpHeaders.ORIGIN, HttpHeaders.CONTENT_TYPE, HttpHeaders.ACCEPT, HttpHeaders.AUTHORIZATION }
+)
+@RestController
+@RequestMapping(CommonConstants.CERTIFICATE_AUTHRORITY_URI)
+public class CertificateAuthorityController {
+
+ //=================================================================================================
+ // members
+ //
+ private static final String GET_CLOUD_COMMON_NAME_HTTP_200_MESSAGE = "Cloud Common Name returned";
+ private static final String SIGN_CERTIFICATE_HTTP_200_MESSAGE = "Successful certificate signing";
+ private static final String SIGN_CERTIFICATE_HTTP_400_MESSAGE = "Invalid Certificate Signing Request";
+
+ private final Logger logger = LogManager.getLogger(CertificateAuthorityController.class);
+
+ @Autowired
+ private CertificateAuthorityService certificateAuthorityService;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ @ApiOperation(value = "Return an echo message with the purpose of testing the core service availability", response = String.class, tags = { CoreCommonConstants.SWAGGER_TAG_CLIENT })
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_OK, message = CoreCommonConstants.SWAGGER_HTTP_200_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = CoreCommonConstants.SWAGGER_HTTP_401_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = CoreCommonConstants.SWAGGER_HTTP_500_MESSAGE)
+ })
+ @GetMapping(path = CommonConstants.ECHO_URI)
+ public String echoService() {
+ return "Got it!";
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @ApiOperation(value = "Return the cloud's Common Name", response = String.class, tags = { CoreCommonConstants.SWAGGER_TAG_CLIENT })
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_OK, message = GET_CLOUD_COMMON_NAME_HTTP_200_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = CoreCommonConstants.SWAGGER_HTTP_401_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = CoreCommonConstants.SWAGGER_HTTP_500_MESSAGE)
+ })
+ @GetMapping(path = CommonConstants.OP_CA_CLOUD_COMMON_NAME_URI)
+ public String getCloudCommonName() {
+ logger.debug("getCloudCommonName started ...");
+
+ return certificateAuthorityService.getCloudCommonName();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @ApiOperation(value = "Return a signed certificate", response = CertificateSigningResponseDTO.class, tags = { CoreCommonConstants.SWAGGER_TAG_CLIENT })
+ @ApiResponses(value = {
+ @ApiResponse(code = HttpStatus.SC_OK, message = SIGN_CERTIFICATE_HTTP_200_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = SIGN_CERTIFICATE_HTTP_400_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = CoreCommonConstants.SWAGGER_HTTP_401_MESSAGE),
+ @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = CoreCommonConstants.SWAGGER_HTTP_500_MESSAGE)
+ })
+ @PostMapping(path = CommonConstants.OP_CA_SIGN_CERTIFICATE_URI, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseBody
+ public CertificateSigningResponseDTO signCertificate(@Valid @RequestBody final CertificateSigningRequestDTO request, BindingResult bindingResult) {
+ handleBindingResult(bindingResult);
+ return certificateAuthorityService.signCertificate(request);
+ }
+
+ private void handleBindingResult(BindingResult bindingResult) {
+ if (bindingResult.hasErrors()) {
+ final List allErrors = bindingResult.getAllErrors();
+ for (ObjectError error : allErrors) {
+ logger.debug(error.toString());
+ }
+ throw new BadPayloadException(allErrors.get(0).getDefaultMessage());
+ }
+ }
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityMain.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityMain.java
new file mode 100644
index 000000000..a984109d5
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityMain.java
@@ -0,0 +1,28 @@
+package eu.arrowhead.core.certificate_authority;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.CoreCommonConstants;
+import eu.arrowhead.common.database.repository.RefreshableRepositoryImpl;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@SpringBootApplication
+@ComponentScan(CommonConstants.BASE_PACKAGE)
+@EntityScan(CoreCommonConstants.DATABASE_ENTITY_PACKAGE)
+@EnableJpaRepositories(basePackages = CoreCommonConstants.DATABASE_REPOSITORY_PACKAGE, repositoryBaseClass = RefreshableRepositoryImpl.class)
+@EnableSwagger2
+public class CertificateAuthorityMain {
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public static void main(final String[] args) {
+ SpringApplication.run(CertificateAuthorityMain.class, args);
+ }
+}
\ No newline at end of file
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityService.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityService.java
new file mode 100644
index 000000000..4c4e71d5a
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityService.java
@@ -0,0 +1,126 @@
+package eu.arrowhead.core.certificate_authority;
+
+import eu.arrowhead.common.SSLProperties;
+import eu.arrowhead.common.Utilities;
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+import eu.arrowhead.common.dto.internal.CertificateSigningResponseDTO;
+import eu.arrowhead.common.exception.InvalidParameterException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.ServiceConfigurationError;
+
+@Service
+public class CertificateAuthorityService {
+
+ private static final Logger logger = LogManager.getLogger(CertificateAuthorityService.class);
+
+ @Autowired
+ private SSLProperties sslProperties;
+
+ @Autowired
+ private CAProperties caProperties;
+
+ private SecureRandom random;
+ private KeyStore keyStore;
+
+ private X509Certificate rootCertificate;
+ private X509Certificate cloudCertificate;
+ private String cloudCommonName;
+
+ @PostConstruct
+ private void init() {
+ random = new SecureRandom();
+ //random.reseed();
+ keyStore = getKeyStore();
+
+ rootCertificate = Utilities.getRootCertFromKeyStore(keyStore);
+ cloudCertificate = Utilities.getCloudCertFromKeyStore(keyStore);
+ cloudCommonName = CertificateAuthorityUtils.getCloudCommonName(cloudCertificate);
+ }
+
+ public String getCloudCommonName() {
+ return cloudCommonName;
+ }
+
+ public CertificateSigningResponseDTO signCertificate(CertificateSigningRequestDTO request) {
+ verifyCertificateSigningRequest(request);
+
+ final JcaPKCS10CertificationRequest csr = CertificateAuthorityUtils.decodePKCS10CSR(request);
+ CertificateAuthorityUtils.checkCommonName(csr, cloudCommonName);
+ CertificateAuthorityUtils.checkCsrSignature(csr);
+
+ logger.info("Signing certificate for " + csr.getSubject().toString() + "...");
+
+ final PrivateKey cloudPrivateKey = Utilities.getCloudPrivateKey(keyStore, cloudCommonName,
+ sslProperties.getKeyPassword());
+
+ final X509Certificate clientCertificate = buildCertificate(csr, cloudPrivateKey, cloudCertificate);
+ final List encodedCertificateChain = buildEncodedCertificateChain(clientCertificate);
+
+ return new CertificateSigningResponseDTO(encodedCertificateChain);
+ }
+
+ private KeyStore getKeyStore() {
+ try {
+ final KeyStore keystore = KeyStore.getInstance(sslProperties.getKeyStoreType());
+ keystore.load(sslProperties.getKeyStore().getInputStream(),
+ sslProperties.getKeyStorePassword().toCharArray());
+ return keystore;
+ } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException e) {
+ throw new ServiceConfigurationError("Cannot open keystore: " + e.getMessage());
+ }
+ }
+
+ private static void verifyCertificateSigningRequest(CertificateSigningRequestDTO request) {
+ if (request == null) {
+ logger.error("CertificateSigningRequest cannot be null");
+ throw new InvalidParameterException("CertificateSigningRequest cannot be null");
+ }
+
+ final String encodedCSR = request.getEncodedCSR();
+
+ if (encodedCSR == null || encodedCSR.isEmpty()) {
+ logger.error("CertificateSigningRequest cannot be empty");
+ throw new InvalidParameterException("CertificateSigningRequest cannot be empty");
+ }
+ }
+
+ private List buildEncodedCertificateChain(X509Certificate clientCertificate) {
+ final ArrayList encodedCertificateChain = new ArrayList<>();
+ encodedCertificateChain.add(CertificateAuthorityUtils.encodeCertificate(clientCertificate));
+ encodedCertificateChain.add(CertificateAuthorityUtils.encodeCertificate(cloudCertificate));
+ encodedCertificateChain.add(CertificateAuthorityUtils.encodeCertificate(rootCertificate));
+ return encodedCertificateChain;
+ }
+
+ private X509Certificate buildCertificate(JcaPKCS10CertificationRequest csr, PrivateKey cloudPrivateKey,
+ X509Certificate cloudCertificate) {
+ final ZonedDateTime now = ZonedDateTime.now();
+ final Date validFrom = Date.from(
+ now.minusMinutes(caProperties.getCertValidityNegativeOffsetMinutes()).toInstant());
+ final Date validUntil = Date.from(
+ now.plusMinutes(caProperties.getCertValidityPositiveOffsetMinutes()).toInstant());
+
+ logger.debug("Setting validity from='{}' to='{}'", validFrom, validUntil);
+ return CertificateAuthorityUtils.buildCertificate(csr, cloudPrivateKey, cloudCertificate, validFrom, validUntil,
+ random);
+ }
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtils.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtils.java
new file mode 100644
index 000000000..3e6528319
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtils.java
@@ -0,0 +1,211 @@
+package eu.arrowhead.core.certificate_authority;
+
+import eu.arrowhead.common.Utilities;
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+import eu.arrowhead.common.exception.AuthException;
+import eu.arrowhead.common.exception.BadPayloadException;
+import eu.arrowhead.common.exception.DataNotFoundException;
+import eu.arrowhead.common.exception.InvalidParameterException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.bouncycastle.asn1.pkcs.Attribute;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x500.RDN;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.bouncycastle.asn1.x500.style.IETFUtils;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.cert.CertIOException;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.operator.ContentVerifierProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
+import org.bouncycastle.pkcs.PKCSException;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.ServiceConfigurationError;
+
+class CertificateAuthorityUtils {
+
+ private static final Logger logger = LogManager.getLogger(CertificateAuthorityService.class);
+
+ private static final String PROVIDER = "BC";
+ private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
+
+ private CertificateAuthorityUtils() {
+ }
+
+ static JcaPKCS10CertificationRequest decodePKCS10CSR(CertificateSigningRequestDTO csr) {
+ try {
+ final byte[] csrBytes = Base64.getDecoder().decode(csr.getEncodedCSR());
+ return new JcaPKCS10CertificationRequest(csrBytes);
+ } catch (Exception e) {
+ logger.error("Failed to parse request as a PKCS10 CSR, because: " + e.getMessage());
+ throw new BadPayloadException("Failed to parse request as a PKCS10 CSR", e);
+ }
+ }
+
+ static String encodeCertificate(X509Certificate certificate) {
+ try {
+ return Base64.getEncoder().encodeToString(certificate.getEncoded());
+ } catch (CertificateEncodingException | NullPointerException e) {
+ throw new AuthException("Certificate encoding failed! (" + e.getMessage() + ")", e);
+ }
+ }
+
+ static String getCloudCommonName(X509Certificate cloudCertificate) {
+ try {
+ final X500Name subject = new JcaX509CertificateHolder(cloudCertificate).getSubject();
+ final RDN cn = subject.getRDNs(BCStyle.CN)[0];
+ return IETFUtils.valueToString(cn.getFirst().getValue());
+ } catch (CertificateEncodingException | NullPointerException e) {
+ logger.error("Cannot get common name from cloud cert, because: " + e.getMessage());
+ throw new ServiceConfigurationError("Cannot get common name from cloud cert.", e);
+ }
+ }
+
+ static void checkCommonName(JcaPKCS10CertificationRequest csr, String cloudCN) {
+ if (csr == null) {
+ throw new BadPayloadException("CSR cannot be null");
+ }
+ if (cloudCN == null || cloudCN.isEmpty()) {
+ throw new BadPayloadException("CloudCN cannot be null");
+ }
+ final String clientCN = Objects.requireNonNull(Utilities.getCertCNFromSubject(csr.getSubject().toString()));
+
+ if (!clientCN.endsWith(cloudCN) || clientCN.split("\\.").length > 6) {
+ throw new BadPayloadException(
+ "Certificate request does not have a valid common name! Valid common name: {systemName}."
+ + cloudCN);
+ }
+ }
+
+ static void checkCsrSignature(JcaPKCS10CertificationRequest csr) {
+ try {
+ final ContentVerifierProvider verifierProvider = new JcaContentVerifierProviderBuilder()
+ .setProvider(PROVIDER)
+ .build(csr.getSubjectPublicKeyInfo());
+ if (!csr.isSignatureValid(verifierProvider)) {
+ throw new BadPayloadException("Certificate request has invalid signature! (key pair does not match)");
+ }
+ } catch (OperatorCreationException | PKCSException | NullPointerException e) {
+ throw new BadPayloadException("Encapsulated " + e.getClass().getCanonicalName() + ": " + e.getMessage(), e);
+ }
+ }
+
+ static PublicKey getClientKey(JcaPKCS10CertificationRequest csr) {
+ try {
+ return csr.getPublicKey();
+ } catch (InvalidKeyException | NoSuchAlgorithmException | NullPointerException e) {
+ // This should not be possible after a successful signature verification
+ throw new DataNotFoundException("Extracting the public key from the CSR failed (" + e.getMessage() + ")",
+ e);
+ }
+ }
+
+ static X509Certificate buildCertificate(JcaPKCS10CertificationRequest csr, PrivateKey cloudPrivateKey,
+ X509Certificate cloudCertificate, Date validFrom, Date validUntil, SecureRandom random) {
+
+ final BigInteger serial = new BigInteger(32, random);
+
+ final PublicKey clientKey = getClientKey(csr);
+
+ X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(cloudCertificate, serial, validFrom,
+ validUntil, csr.getSubject(), clientKey);
+
+ addCertificateExtensions(builder, csr, clientKey, cloudCertificate);
+
+ JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider(PROVIDER);
+ try {
+ return new JcaX509CertificateConverter().setProvider(PROVIDER)
+ .getCertificate(builder.build(signerBuilder.build(cloudPrivateKey)));
+ } catch (CertificateException e) {
+ throw new BadPayloadException("Certificate encoding failed! (" + e.getMessage() + ")", e);
+ } catch (OperatorCreationException e) {
+ throw new BadPayloadException("Certificate signing failed! (" + e.getMessage() + ")", e);
+ }
+ }
+
+ /**
+ * Adding the following extensions to the new certificate:
+ *
+ *
The subject alternative name makes possible to use the certificate for
+ * accessing a host via IP address or hostname
+ *
+ *
The subject key identifier provides a hashed value that should uniquely
+ * identify the public key
+ *
+ *
The authority key identifier provides a hashed value that should uniquely
+ * identify the issuer of the certificate
+ *
+ *
And this basic constraint is for forbidding issuing other certificates
+ * under this certificate
+ *
+ */
+ static void addCertificateExtensions(X509v3CertificateBuilder builder, JcaPKCS10CertificationRequest csr,
+ PublicKey clientKey, X509Certificate cloudCertificate) {
+ try {
+ JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+
+ final List subjectAlternativeNames = getSubjectAlternativeNames(csr);
+ builder.addExtension(Extension.subjectAlternativeName, false,
+ new GeneralNames(subjectAlternativeNames.toArray(new GeneralName[]{})));
+ builder.addExtension(Extension.subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(clientKey));
+ builder.addExtension(Extension.authorityKeyIdentifier, false,
+ extUtils.createAuthorityKeyIdentifier(cloudCertificate));
+ builder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
+ } catch (NoSuchAlgorithmException | CertIOException | CertificateEncodingException | NullPointerException e) {
+ throw new InvalidParameterException("Appending extensions to the certificate failed! (" + e.getMessage() + ")", e);
+ }
+ }
+
+ static List getSubjectAlternativeNames(JcaPKCS10CertificationRequest csr) {
+ if (csr == null) {
+ throw new InvalidParameterException("CSR cannot be null");
+ }
+
+ List alternativeNames = new ArrayList<>();
+ for (final Attribute attribute : csr.getAttributes()) {
+ if (attribute == null) {
+ continue;
+ }
+ if (attribute.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest)) {
+ final Extensions extensions = Extensions.getInstance(attribute.getAttrValues().getObjectAt(0));
+ final GeneralNames generalNames = GeneralNames.fromExtensions(extensions,
+ Extension.subjectAlternativeName);
+ if (generalNames != null && generalNames.getNames() != null && generalNames.getNames().length > 0) {
+ for (final GeneralName name : generalNames.getNames()) {
+ if (name.getTagNo() == GeneralName.dNSName || name.getTagNo() == GeneralName.iPAddress) {
+ alternativeNames.add(name);
+ }
+ }
+ }
+ }
+ }
+
+ return alternativeNames;
+ }
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CAAccessControlFilter.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CAAccessControlFilter.java
new file mode 100644
index 000000000..0af563874
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CAAccessControlFilter.java
@@ -0,0 +1,34 @@
+package eu.arrowhead.core.certificate_authority.security;
+
+import java.util.Map;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.CoreCommonConstants;
+import eu.arrowhead.common.security.CoreSystemAccessControlFilter;
+
+@Component
+@ConditionalOnProperty(name = CommonConstants.SERVER_SSL_ENABLED, matchIfMissing = true)
+public class CAAccessControlFilter extends CoreSystemAccessControlFilter {
+
+ //=================================================================================================
+ // members
+
+ //=================================================================================================
+ // assistant methods
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ protected void checkClientAuthorized(final String clientCN, final String method, final String requestTarget, final String requestJSON, final Map queryParams) {
+ super.checkClientAuthorized(clientCN, method, requestTarget, requestJSON, queryParams);
+
+ final String cloudCN = getServerCloudCN();
+
+ if (requestTarget.contains(CoreCommonConstants.MGMT_URI)) {
+ // Only the local System Operator can use these methods
+ checkIfLocalSystemOperator(clientCN, cloudCN, requestTarget);
+ }
+ }
+}
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CASecurityConfig.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CASecurityConfig.java
new file mode 100644
index 000000000..5f129c51d
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/security/CASecurityConfig.java
@@ -0,0 +1,12 @@
+package eu.arrowhead.core.certificate_authority.security;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
+import eu.arrowhead.common.security.DefaultSecurityConfig;
+
+@Configuration
+@EnableWebSecurity
+public class CASecurityConfig extends DefaultSecurityConfig {
+
+}
\ No newline at end of file
diff --git a/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/swagger/CASwaggerConfig.java b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/swagger/CASwaggerConfig.java
new file mode 100644
index 000000000..ae0b4321e
--- /dev/null
+++ b/certificate-authority/src/main/java/eu/arrowhead/core/certificate_authority/swagger/CASwaggerConfig.java
@@ -0,0 +1,28 @@
+package eu.arrowhead.core.certificate_authority.swagger;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.swagger.DefaultSwaggerConfig;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@EnableSwagger2
+@Configuration
+public class CASwaggerConfig extends DefaultSwaggerConfig {
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public CASwaggerConfig() {
+ super(CommonConstants.CORE_SYSTEM_CERTIFICATE_AUTHORITY);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Bean
+ public Docket customizeSwagger() {
+ return configureSwaggerForCoreSystem(this.getClass().getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/certificate-authority/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/certificate-authority/src/main/resources/META-INF/additional-spring-configuration-metadata.json
new file mode 100644
index 000000000..af4455de4
--- /dev/null
+++ b/certificate-authority/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -0,0 +1,47 @@
+{"properties": [
+ {
+ "name": "ping_scheduled",
+ "type": "java.lang.Boolean",
+ "description": "A description for 'ping_scheduled'"
+ },
+ {
+ "name": "ping_timeout",
+ "type": "java.lang.Long",
+ "description": "A description for 'ping_timeout'"
+ },
+ {
+ "name": "ping_interval",
+ "type": "java.lang.Long",
+ "description": "A description for 'ping_interval'"
+ },
+ {
+ "name": "ttl_scheduled",
+ "type": "java.lang.Boolean",
+ "description": "A description for 'ttl_scheduled'"
+ },
+ {
+ "name": "ttl_interval",
+ "type": "java.lang.Long",
+ "description": "A description for 'ttl_interval'"
+ },
+ {
+ "name": "disable.hostname.verifier",
+ "type": "java.lang.Boolean",
+ "description": "A description for 'disable.hostname.verifier'"
+ },
+ {
+ "name": "log_all_request_and_response",
+ "type": "java.lang.Boolean",
+ "description": "A description for 'log_all_request_and_response'"
+ },
+ {
+ "name": "use_strict_service_intf_name_verifier",
+ "type": "java.lang.Boolean",
+ "description": "A description for 'use_strict_service_intf_name_verifier'"
+ },
+ {
+ "name": "core_system_name",
+ "type": "java.lang.String",
+ "description": "A description for 'core_system_name'"
+ }
+]}
\ No newline at end of file
diff --git a/certificate-authority/src/main/resources/application.properties b/certificate-authority/src/main/resources/application.properties
new file mode 100644
index 000000000..93f325bd4
--- /dev/null
+++ b/certificate-authority/src/main/resources/application.properties
@@ -0,0 +1,59 @@
+############################################
+### APPLICATION PARAMETERS ###
+############################################
+
+# Database connection (mandatory)
+# Change the server timezone if neccessary
+spring.datasource.url=jdbc:mysql://127.0.0.1:3306/arrowhead?serverTimezone=Europe/Budapest
+spring.datasource.username=certificate_authority
+spring.datasource.password=FsdG6Kgf9QpPfv2
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+
+spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
+# use true only for debugging
+spring.jpa.show-sql=false
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.hibernate.ddl-auto=none
+
+# Certificate Authority web-server parameters
+server.address=127.0.0.1
+server.port=8448
+domain.name=127.0.0.1
+domain.port=8448
+
+############################################
+### CUSTOM PARAMETERS ###
+############################################
+
+# Name of the core system
+core_system_name=certificate_authority
+
+# Show all request/response in debug log
+log_all_request_and_response=false
+
+# Service Registry web-server parameters (to register the Certificate-Authority services)
+sr_address=127.0.0.1
+sr_port=8443
+
+############################################
+### SECURE MODE ###
+############################################
+
+# configure secure mode
+
+# Set this to false to disable https mode
+server.ssl.enabled=true
+
+server.ssl.key-store-type=PKCS12
+server.ssl.key-store=classpath:certificates/certificate_authority.p12
+server.ssl.key-store-password=123456
+server.ssl.key-alias=certificate_authority
+server.ssl.key-password=123456
+server.ssl.client-auth=need
+server.ssl.trust-store-type=PKCS12
+server.ssl.trust-store=classpath:certificates/truststore.p12
+server.ssl.trust-store-password=123456
+
+#If true, http client does not check whether the hostname is match one of the server's SAN in its certificate
+#Just for testing, DO NOT USE this feature in production environment
+disable.hostname.verifier=false
diff --git a/certificate-authority/src/main/resources/certificates/certificate_authority.p12 b/certificate-authority/src/main/resources/certificates/certificate_authority.p12
new file mode 100644
index 000000000..57fba65b4
Binary files /dev/null and b/certificate-authority/src/main/resources/certificates/certificate_authority.p12 differ
diff --git a/certificate-authority/src/main/resources/certificates/truststore.p12 b/certificate-authority/src/main/resources/certificates/truststore.p12
new file mode 100644
index 000000000..57c1c5f43
Binary files /dev/null and b/certificate-authority/src/main/resources/certificates/truststore.p12 differ
diff --git a/certificate-authority/src/main/resources/log4j2.xml b/certificate-authority/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..fcce0981a
--- /dev/null
+++ b/certificate-authority/src/main/resources/log4j2.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${hostName} --- [%15.15t] %-40.40c{1.} : %m%n%ex
+
+ INFO
+ INFO
+ .
+
+
+
+
+
+
+
+ ${LOG_PATTERN}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/certificate-authority/src/main/resources/swagger/swagger-ui.html b/certificate-authority/src/main/resources/swagger/swagger-ui.html
new file mode 100644
index 000000000..4dec726e9
--- /dev/null
+++ b/certificate-authority/src/main/resources/swagger/swagger-ui.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+ Certificate Authority
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityControllerTest.java b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityControllerTest.java
new file mode 100644
index 000000000..dda6e9b0b
--- /dev/null
+++ b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityControllerTest.java
@@ -0,0 +1,207 @@
+package eu.arrowhead.core.certificate_authority;
+
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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.core.io.ClassPathResource;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CertificateAuthorityMain.class)
+@AutoConfigureMockMvc
+public class CertificateAuthorityControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void testEchoWithoutCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/echo")
+ .secure(true))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testEchoWithInvalidCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/echo")
+ .secure(true)
+ .with(x509("certificates/notvalid.pem")))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testEchoWithValidCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/echo")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void testGetCloudCommonNameWithoutCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/name")
+ .secure(true))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testGetCloudCommonNameWithInvalidCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/name")
+ .secure(true)
+ .with(x509("certificates/notvalid.pem")))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testGetCloudCommonNameWithValidCert() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/name")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isOk())
+ .andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN))
+ .andExpect(content().string("testcloud2.aitia.arrowhead.eu"));
+ }
+
+ @Test
+ public void testSignWithoutCert() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testSignWithInvalidCert() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/notvalid.pem")))
+ .andExpect(status().isUnauthorized());
+ }
+
+ @Test
+ public void testSignGet() throws Exception {
+ mockMvc.perform(get("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isMethodNotAllowed());
+ }
+
+ @Test
+ public void testSignPut() throws Exception {
+ mockMvc.perform(put("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isMethodNotAllowed());
+ }
+
+ @Test
+ public void testSignPatch() throws Exception {
+ mockMvc.perform(patch("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isMethodNotAllowed());
+ }
+
+ @Test
+ public void testSignDelete() throws Exception {
+ mockMvc.perform(delete("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isMethodNotAllowed());
+ }
+
+ @Test
+ public void testSignHead() throws Exception {
+ mockMvc.perform(head("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isMethodNotAllowed());
+ }
+
+ @Test
+ public void testSignOptions() throws Exception {
+ mockMvc.perform(options("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void testSignPostInvalidContentType() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem")))
+ .andExpect(status().isUnsupportedMediaType());
+ }
+
+ @Test
+ public void testSignPostWithNullCSR() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON)
+ .content(asJsonString(new CertificateSigningRequestDTO(null))))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ public void testSignPostWithInvalidCSR() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON)
+ .content(asJsonString(new CertificateSigningRequestDTO("INVALID"))))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ public void testSignPostWithValidCSR() throws Exception {
+ mockMvc.perform(post("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/certificate-authority/sign")
+ .secure(true)
+ .with(x509("certificates/valid.pem"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON)
+ .content(asJsonString(new CertificateSigningRequestDTO(getResourceContent("certificates/valid.csr")))))
+ .andExpect(status().isOk())
+ .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+ .andExpect(jsonPath("$.certificateChain").isArray());
+ }
+
+ private static String asJsonString(final Object obj) {
+ try {
+ return new ObjectMapper().writeValueAsString(obj);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String getResourceContent(String resourcePath) throws IOException {
+ File resource = new ClassPathResource(resourcePath).getFile();
+ return new String(Files.readAllBytes(resource.toPath())).trim();
+ }
+}
diff --git a/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtilsTest.java b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtilsTest.java
new file mode 100644
index 000000000..a11fe32a8
--- /dev/null
+++ b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/CertificateAuthorityUtilsTest.java
@@ -0,0 +1,94 @@
+package eu.arrowhead.core.certificate_authority;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Base64;
+import java.util.ServiceConfigurationError;
+
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
+import org.hamcrest.core.IsInstanceOf;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+import eu.arrowhead.common.exception.AuthException;
+import eu.arrowhead.common.exception.BadPayloadException;
+import eu.arrowhead.common.exception.DataNotFoundException;
+
+@RunWith(SpringRunner.class)
+public class CertificateAuthorityUtilsTest {
+
+ @Rule
+ public ExpectedException thrownException = ExpectedException.none();
+
+ @Test(expected = BadPayloadException.class)
+ public void testDecodePKCS10CSRNull() {
+ CertificateAuthorityUtils.decodePKCS10CSR(null);
+ }
+
+ @Test(expected = BadPayloadException.class)
+ public void testDecodePKCS10CSREmpty() {
+ CertificateAuthorityUtils.decodePKCS10CSR(new CertificateSigningRequestDTO());
+ }
+
+ @Test(expected = BadPayloadException.class)
+ public void testDecodePKCS10CSRInvalidString() {
+ CertificateAuthorityUtils.decodePKCS10CSR(new CertificateSigningRequestDTO("Invalid CSR String"));
+ }
+
+ @Test
+ public void testEncodeCertificateNull() {
+ thrownException.expect(IsInstanceOf.instanceOf(AuthException.class));
+ thrownException.expectCause(IsInstanceOf.instanceOf(NullPointerException.class));
+ CertificateAuthorityUtils.encodeCertificate(null);
+ }
+
+ @Test(expected = ServiceConfigurationError.class)
+ public void testGetCloudCommonNameNullCert() {
+ CertificateAuthorityUtils.getCloudCommonName(null);
+ }
+
+ @Test(expected = BadPayloadException.class)
+ public void testCheckCommonNameNullCSR() {
+ CertificateAuthorityUtils.checkCommonName(null, "cloudCN");
+ }
+
+ @Test(expected = BadPayloadException.class)
+ public void testCheckCommonNameNullCloudCN() throws NullPointerException, IOException {
+ final JcaPKCS10CertificationRequest csr = getResourceCSR("certificates/valid.csr");
+ assertNotNull(csr);
+ CertificateAuthorityUtils.checkCommonName(csr, null);
+ }
+
+ @Test(expected = BadPayloadException.class)
+ public void testCheckCsrSignatureNull() {
+ CertificateAuthorityUtils.checkCsrSignature(null);
+ }
+
+ @Test
+ public void testGetClientKeyNull() {
+ thrownException.expect(DataNotFoundException.class);
+ thrownException.expectCause(IsInstanceOf.instanceOf(NullPointerException.class));
+ CertificateAuthorityUtils.getClientKey(null);
+ }
+
+ private static String getResourceContentAsString(final String resourcePath) throws IOException {
+ final File resource = new ClassPathResource(resourcePath).getFile();
+ return new String(Files.readAllBytes(resource.toPath())).trim();
+ }
+
+ private static JcaPKCS10CertificationRequest getResourceCSR(
+ final String resourcePath)
+ throws IOException, NullPointerException {
+ final String resourceBytes = getResourceContentAsString(resourcePath);
+ final byte[] csrBytes = Base64.getDecoder().decode(resourceBytes);
+ return new JcaPKCS10CertificationRequest(csrBytes);
+ }
+}
diff --git a/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/StandaloneModeInCertificateAuthorityTests.java b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/StandaloneModeInCertificateAuthorityTests.java
new file mode 100644
index 000000000..552432eb5
--- /dev/null
+++ b/certificate-authority/src/test/java/eu/arrowhead/core/certificate_authority/StandaloneModeInCertificateAuthorityTests.java
@@ -0,0 +1,10 @@
+package eu.arrowhead.core.certificate_authority;
+
+import org.springframework.stereotype.Component;
+
+import eu.arrowhead.common.testhelper.StandaloneModeInTests;
+
+@Component
+public class StandaloneModeInCertificateAuthorityTests extends StandaloneModeInTests {
+
+}
\ No newline at end of file
diff --git a/certificate-authority/src/test/resources/banner.txt b/certificate-authority/src/test/resources/banner.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/certificate-authority/src/test/resources/certificates/notvalid.pem b/certificate-authority/src/test/resources/certificates/notvalid.pem
new file mode 100644
index 000000000..a70c46837
--- /dev/null
+++ b/certificate-authority/src/test/resources/certificates/notvalid.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAhugAwIBAgIEXNlw3zANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxh
+cnJvd2hlYWQuZXUwHhcNMTkwNTEzMTMyNzU5WhcNMjkwNTEzMTMyNzU5WjAoMSYw
+JAYDVQQDDB10ZXN0Y2xvdWQxLmFpdGlhLmFycm93aGVhZC5ldTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANTIWrd0mcvxx6LfPG6RvviN5VY1n9uphoYm
+CoRA47scc0duc6kIWsIydEsKD9xEd2WdClbQXVazLSF+OWGocxBuyPaAjgu4DdVY
+pJLgAaeSzbcjqS+A6bB3B6i8A9RxCWwtDJ5EJsUuIOa9yqcfkmdXVOHpNlwycPeH
+FEOIUdUcd+RAL0Fw4h39a3HmTDf4nb2Px/3CWvZk89woxDXURJfyDl2fJyB3kLbp
+4HWBht9YZNw2ZuIT1fO5rfm2XGEaPiUseI4KEwDyhW36HWOxv3oP9lMWjCaeWFg1
+A4q6sbjm+fsEsZJavgPWANINCTxKyy/IclwmxKimS6aDBHHyW6UCAwEAAaN2MHQw
+DwYDVR0TBAgwBgEB/wIBAjBCBgNVHSMEOzA5gBSaipkeMUwesuYttprtxx4xyt07
+/qEbpBkwFzEVMBMGA1UEAwwMYXJyb3doZWFkLmV1ggRc1T6tMB0GA1UdDgQWBBT0
+jA9ICBgevPSr86oEvVJ8uDamJTANBgkqhkiG9w0BAQsFAAOCAQEAiy1OVJulFL2V
+HOYlERD2MJCgIaVKoN6GGxGXQ7mBAjGE+am+dKvbGZ9l5ADRKxKgd1T0hklfTZJU
+j7CHBp1JJ7cj7OkFyountQcdTJ3WVLDMxfRRictRwuEUaKMry4nmcU2WpDTJ+DSV
+H6qW3VlXxJKnGe1M3u14wUx5k0iXr4S2oYkq/WZ9TUkLWKmzVPDlU3x6iSsyZj/5
+1a5o2qNceezzpGhcvoiHwQ0MFm9OLDYrh61Zb4M7jhn2AocHV4f3Y0P0IfdLlXq5
+MIgOK1ds2BekemekJ3VnW/TDj8fY6sxWl8aWFYJ1RhmVWTODiN9xu9XPyzAO5ryk
+zG4AOQa5rQ==
+-----END CERTIFICATE-----
diff --git a/certificate-authority/src/test/resources/certificates/valid.csr b/certificate-authority/src/test/resources/certificates/valid.csr
new file mode 100644
index 000000000..d1d8fc393
--- /dev/null
+++ b/certificate-authority/src/test/resources/certificates/valid.csr
@@ -0,0 +1 @@
+MIIDKTCCAhECAQAwTDEPMA0GA1UECgwGZWlsYWJzMQswCQYDVQQGEwJodTEsMCoGA1UEAwwjc3lzb3AudGVzdGNsb3VkMi5haXRpYS5hcnJvd2hlYWQuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgKgJZOMH5QiLxYLz6bKcDAOkLvh13EIVG3W6CdNJpbYcYljnuZlGZ+38A+HLsL4fJfLOPvsrpMKSv2NfEDKSuQaHJt0nchM26WiVkiYfZXPxYduZy9wqi1069V7E2i7vYsqJEytugjEhEk+1O1rtFuGZXIitNUSUBUNYWNkc/sr3wCGgZrcAOnTFuHSorUGm4Kc8qbrgNtjnbPCvnyZJp7IvsyAT51bBYfH2vhf9Yjv/apAiKjwNO/Hfo8cYq6u3CnFpXSj6BD5DVhwPWZ9IenfG1hACdldEsiNoN3ssZYwbuPcduq6SSNOHIqtQIp+spdAUi0FQnnw8kmryxPGgvAgMBAAGggZcwFAYJKoZIhvcNAQkHMQcMBTI0NTM0MBUGCSqGSIb3DQEJAjEIDAZlaWxhYnMwaAYJKoZIhvcNAQkOMVswWTAPBgNVHREECDAGhwR/AAABMCcGA1UdIwQgMB6AFAQwTQgjkz3eZj0WWqfRyV4jppdPoQCCBFzZYhkwHQYDVR0OBBYEFAVG6MVZFFyHQXW6qlQWA4EfXWSIMA0GCSqGSIb3DQEBCwUAA4IBAQAkRvc+/O/GWx3dg6CgnpWSCFZKnaaD1l+1Rls93qZZ3jP1tukK+7xh+1AcRNnB5h5tNW0Zaa7KrYIS/RX2wsqGRIil4iTmGaa2/MPFY3GAm65891JuF4t0dk/5GcOJjZOAEV603ils9qxZ1np3asQRGiFAXbvL1tr+2iaQR2olfsn00qSw+zYICKPtBAJhUcmxavMrlZPoiCiJzWqQZMNOlYzJitim8N8rMwKZnwmDdgqgjkVrIQXKVh3Q2xw2mGlqPIRToLSgnGtLQ5caNVhBeF1OnfBxziP8SVckazTSlJ8uVm8an6Jt2R6VQf1avuclAxWAwS8CyAn5TpJNzVjL
diff --git a/certificate-authority/src/test/resources/certificates/valid.pem b/certificate-authority/src/test/resources/certificates/valid.pem
new file mode 100644
index 000000000..56eae293d
--- /dev/null
+++ b/certificate-authority/src/test/resources/certificates/valid.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLzCCAhegAwIBAgIEXPYrATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB10
+ZXN0Y2xvdWQyLmFpdGlhLmFycm93aGVhZC5ldTAeFw0xOTA2MDQwODI1MzdaFw0y
+MDA2MDMwODI1MzdaMC4xLDAqBgNVBAMMI3N5c29wLnRlc3RjbG91ZDIuYWl0aWEu
+YXJyb3doZWFkLmV1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoCoC
+WTjB+UIi8WC8+mynAwDpC74ddxCFRt1ugnTSaW2HGJY57mZRmft/APhy7C+HyXyz
+j77K6TCkr9jXxAykrkGhybdJ3ITNulolZImH2Vz8WHbmcvcKotdOvVexNou72LKi
+RMrboIxIRJPtTta7RbhmVyIrTVElAVDWFjZHP7K98AhoGa3ADp0xbh0qK1BpuCnP
+Km64DbY52zwr58mSaeyL7MgE+dWwWHx9r4X/WI7/2qQIio8DTvx36PHGKurtwpxa
+V0o+gQ+Q1YcD1mfSHp3xtYQAnZXRLIjaDd7LGWMG7j3HbqukkjThyKrUCKfrKXQF
+ItBUJ58PJJq8sTxoLwIDAQABo1swWTAPBgNVHREECDAGhwR/AAABMCcGA1UdIwQg
+MB6AFAQwTQgjkz3eZj0WWqfRyV4jppdPoQCCBFzZYhkwHQYDVR0OBBYEFAVG6MVZ
+FFyHQXW6qlQWA4EfXWSIMA0GCSqGSIb3DQEBCwUAA4IBAQBUEExzkf2bH4fF/tyP
+r7DxO94aqQOySGJq/25DzfZQOpuK5Ud3MPpXSlxYw+MB5rRDJu0NzGUX+ha4mG3T
+dXxd3X2QaDFR0SYUD4J0hTtmYp9TzgCXnU+J7t6sku/LYFJrCl5m4o124ShZXBgR
+Dj/gDVd4C6InTPhpIPHaD6D97wKyObbC3V1dGiVs5Z5/+wUJdUFUmnfAb1rbX0nV
+0TTKluWTtRT4cjBeIFs7MZiThMx8bgSE4mZIC1ry4PikjAap/oEIQVxbBTbl+5q8
+xhPbPn+JhZwQp39a1oPMEQog0wQhtKvZrYx//H1o3mzRo1ZFzL+R/LCKKElMPMXx
+UHKC
+-----END CERTIFICATE-----
diff --git a/certificate-authority/src/test/resources/log4j2.xml b/certificate-authority/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..931cbfebb
--- /dev/null
+++ b/certificate-authority/src/test/resources/log4j2.xml
@@ -0,0 +1,49 @@
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${hostName} --- [%15.15t] %-40.40c{1.} : %m%n%ex
+
+ OFF
+ OFF
+
+
+
+
+
+
+
+ ${LOG_PATTERN}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/certificates/testcloud2/device_registry.p12 b/certificates/testcloud2/device_registry.p12
new file mode 100644
index 000000000..dcd55a150
Binary files /dev/null and b/certificates/testcloud2/device_registry.p12 differ
diff --git a/certificates/testcloud2/onboarding_controller.p12 b/certificates/testcloud2/onboarding_controller.p12
new file mode 100644
index 000000000..cbfcb32b1
Binary files /dev/null and b/certificates/testcloud2/onboarding_controller.p12 differ
diff --git a/certificates/testcloud2/qos_monitor.p12 b/certificates/testcloud2/qos_monitor.p12
new file mode 100644
index 000000000..86c68f35b
Binary files /dev/null and b/certificates/testcloud2/qos_monitor.p12 differ
diff --git a/certificates/testcloud2/system_registry.p12 b/certificates/testcloud2/system_registry.p12
new file mode 100644
index 000000000..1e913c7ae
Binary files /dev/null and b/certificates/testcloud2/system_registry.p12 differ
diff --git a/choreographer/.classpath b/choreographer/.classpath
index 01997bb0d..e210343c4 100644
--- a/choreographer/.classpath
+++ b/choreographer/.classpath
@@ -45,5 +45,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/choreographer/src/main/java/eu/arrowhead/core/choreographer/ChoreographerController.java b/choreographer/src/main/java/eu/arrowhead/core/choreographer/ChoreographerController.java
index 0bc785e7b..6882f14e3 100644
--- a/choreographer/src/main/java/eu/arrowhead/core/choreographer/ChoreographerController.java
+++ b/choreographer/src/main/java/eu/arrowhead/core/choreographer/ChoreographerController.java
@@ -162,7 +162,7 @@ public void removeActionPlanById(@PathVariable(value = PATH_VARIABLE_ID) final l
final ValidatedPageParams validatedPageParams = CoreUtilities.validatePageParameters(page, size, direction, sortField);
final List choreographerActionPlanEntriesResponse = choreographerDBService.getChoreographerActionPlanEntriesResponse(validatedPageParams.getValidatedPage(),
validatedPageParams.getValidatedSize(),
- validatedPageParams.getValidatedDirecion(),
+ validatedPageParams.getValidatedDirection(),
sortField);
logger.debug("ChoreographerActionPlans with page: {} and item_per page: {} retrieved successfully", page, size);
diff --git a/core-common/.classpath b/core-common/.classpath
index 779e9464e..660114540 100644
--- a/core-common/.classpath
+++ b/core-common/.classpath
@@ -40,5 +40,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core-common/pom.xml b/core-common/pom.xml
index 1e5d966f4..ec10307f3 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -1,6 +1,6 @@
4.0.0
-
+ eu.arrowheadcore${revision}
@@ -14,8 +14,17 @@
core-client-skeleton
-
-
+
+
+
+ org.bouncycastle
+ bcpkix-jdk15on
+ 1.64
+ compile
+
+
+
+ src/main/java
diff --git a/core-common/src/deb/ahconf.sh b/core-common/src/deb/ahconf.sh
index 1242632b7..0b2ea2cb3 100644
--- a/core-common/src/deb/ahconf.sh
+++ b/core-common/src/deb/ahconf.sh
@@ -190,6 +190,23 @@ ah_ip_valid () {
fi
}
+ah_subject_alternative_names() {
+ host=${1}
+ ip=${2}
+
+ san="IP:127.0.0.1,DNS:localhost,DNS:${host},IP:${ip}"
+
+ if [ ! -z ${AH_DOMAIN_NAME} ]; then
+ if ah_ip_valid ${AH_DOMAIN_NAME}; then
+ san=${san},IP:${AH_DOMAIN_NAME}
+ else
+ san=${san},DNS:${AH_DOMAIN_NAME}
+ fi
+ fi
+
+ return san
+}
+
ah_cert_signed_system () {
name=${1}
passwd=${2}
@@ -218,15 +235,7 @@ ah_cert_signed_system () {
src_file="${AH_CLOUDS_DIR}/${AH_CLOUD_NAME}.p12"
if [ ! -f "${file}" ]; then
- san="IP:127.0.0.1,DNS:localhost,DNS:${host},IP:${ip}"
-
- if [ ! -z ${AH_DOMAIN_NAME} ]; then
- if ah_ip_valid ${AH_DOMAIN_NAME}; then
- san=${san},IP:${AH_DOMAIN_NAME}
- else
- san=${san},DNS:${AH_DOMAIN_NAME}
- fi
- fi
+ san=ah_subject_alternative_names ${host} ${ip}
ah_cert ${path} ${name} "${name}.${AH_CLOUD_NAME}.${AH_OPERATOR}.arrowhead.eu" ${passwd}
@@ -266,6 +275,94 @@ ah_cert_signed_system () {
fi
}
+# Create the keystore for the CA system
+# Apart from being a regular Arrowhead compliant system keystore,
+# it also has to contain the private key of the cloud
+ah_ca_keystore () {
+ ca_sys_name=${1} # name of the CA system
+ host=${2} # hostname of the CA system (default: `hostname`)
+ ip=${3} # IP address of the CA system (default: $OWN_IP)
+ cloud_keystore=${4} # path of the cloud keystore (default: "${AH_CLOUDS_DIR}/${AH_CLOUD_NAME}.p12")
+ ca_password=${5} # password used in the CA keystore (default: $AH_PASS_CERT)
+ cloud_password=${6} # password used in the cloud keystore (default: $AH_PASS_CERT)
+ cloud_alias_src=${7} # cloud cert alias in the cloud keystore (default: $AH_CLOUD_NAME)
+ cloud_alias_dst=${8} # cloud cert alias in the CA keystore (default: $AH_CLOUD_NAME)
+
+ if [ -z ${host} ]; then
+ host=`hostname`
+ fi
+
+ if [ -z ${ip} ]; then
+ ip=${OWN_IP}
+ fi
+
+ if [ -z ${cloud_keystore} ]; then
+ cloud_keystore="${AH_CLOUDS_DIR}/${AH_CLOUD_NAME}.p12"
+ fi
+
+ if [ -z ${ca_password} ]; then
+ ca_password=${AH_PASS_CERT}
+ fi
+
+ if [ -z ${cloud_password} ]; then
+ cloud_password=${ca_password}
+ fi
+
+ if [ -z ${cloud_alias_src} ]; then
+ cloud_alias_src=${AH_CLOUD_NAME}
+ fi
+
+ if [ -z ${cloud_alias_dst} ]; then
+ cloud_alias_dst=${cloud_alias_src}
+ fi
+
+ ca_sys_dir="${AH_SYSTEMS_DIR}/${ca_sys_name}"
+ ca_keystore="${ca_sys_dir}/${ca_sys_name}.p12"
+
+ if [ ! -f "${ca_keystore}" ]; then
+ san=ah_subject_alternative_names ${host} ${ip}
+
+ # generate CA system keypair
+ ah_cert ${ca_sys_dir} ${ca_sys_name} "${ca_sys_name}.${AH_CLOUD_NAME}.${AH_OPERATOR}.arrowhead.eu" ${ca_password}
+
+ # import cloud keypair
+ # this is necessary, because CA signs system certificates with the cloud cert
+ keytool -importkeystore \
+ -srckeypass ${cloud_password} \
+ -srcstorepass ${cloud_password} \
+ -destkeypass ${ca_password} \
+ -deststorepass ${ca_password} \
+ -srcalias ${cloud_alias_src} \
+ -destalias ${cloud_alias_dst} \
+ -srckeystore "${cloud_keystore}" \
+ -destkeystore "${ca_keystore}" \
+ -deststoretype PKCS12
+
+ # sign CA system cert with the cloud cert
+ keytool -certreq \
+ -alias ${ca_sys_name} \
+ -keypass ${ca_password} \
+ -keystore "${ca_keystore}" \
+ -storepass ${ca_password} \
+ | keytool -gencert \
+ -alias ${cloud_alias_dst} \
+ -keypass ${ca_password} \
+ -keystore "${ca_keystore}" \
+ -storepass ${ca_password} \
+ -validity 3650 \
+ -ext SubjectAlternativeName=${san} \
+ | keytool -importcert \
+ -alias ${ca_sys_name} \
+ -keypass ${ca_password} \
+ -keystore "${ca_keystore}" \
+ -storepass ${ca_password} \
+ -noprompt
+
+ # import root certificate
+ ah_cert_import "${AH_CONF_DIR}" "master" "${ca_sys_dir}" ${ca_sys_name} ${ca_password}
+ fi
+}
+
ah_cert_trust () {
dst_path=${1}
src_path=${2}
@@ -359,4 +456,4 @@ ah_transform_log_file () {
rm ${log_path}/log4j2.xml.orig
chown :arrowhead ${log_path}/log4j2.xml
chmod 640 ${log_path}/log4j2.xml
-}
\ No newline at end of file
+}
diff --git a/core-common/src/deb/control/templates b/core-common/src/deb/control/templates
index 83b24eab3..a7b3ab39e 100644
--- a/core-common/src/deb/control/templates
+++ b/core-common/src/deb/control/templates
@@ -76,6 +76,11 @@ Type: password
Default:
Description: MySQL password for Event Handler system (leave empty for random).
+Template: arrowhead-core-common/mysql_password_qos
+Type: password
+Default:
+Description: MySQL password for Qos Monitor system (leave empty for random).
+
Template: arrowhead-core-common/mysql_password_gk
Type: password
Default:
@@ -96,6 +101,26 @@ Type: password
Default:
Description: MySQL password for Service Registry system (leave empty for random).
+Template: arrowhead-core-common/mysql_password_sysr
+Type: password
+Default:
+Description: MySQL password for System Registry system (leave empty for random).
+
+Template: arrowhead-core-common/mysql_password_dr
+Type: password
+Default:
+Description: MySQL password for Device Registry system (leave empty for random).
+
+Template: arrowhead-core-common/mysql_password_onboarding
+Type: password
+Default:
+Description: MySQL password for Onboarding Controller system (leave empty for random).
+
+Template: arrowhead-core-common/mysql_password_ca
+Type: password
+Default:
+Description: MySQL password for Certificate Authority system (leave empty for random).
+
Template: arrowhead-core-common/sr_host
Type: string
Description: Enter the hostname or IP address of the Service Registry (leave empty if the SR on the same computer than the system)
diff --git a/core-common/src/main/java/eu/arrowhead/common/ApplicationConfiguration.java b/core-common/src/main/java/eu/arrowhead/common/ApplicationConfiguration.java
new file mode 100644
index 000000000..0c1afb1a6
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/ApplicationConfiguration.java
@@ -0,0 +1,18 @@
+package eu.arrowhead.common;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Configuration
+public class ApplicationConfiguration {
+
+ //-------------------------------------------------------------------------------------------------
+ @Bean(CommonConstants.ARROWHEAD_CONTEXT)
+ public Map getArrowheadContext() {
+ return new ConcurrentHashMap<>();
+ }
+
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/ApplicationInitListener.java b/core-common/src/main/java/eu/arrowhead/common/ApplicationInitListener.java
index be8b61a76..470313077 100644
--- a/core-common/src/main/java/eu/arrowhead/common/ApplicationInitListener.java
+++ b/core-common/src/main/java/eu/arrowhead/common/ApplicationInitListener.java
@@ -125,12 +125,6 @@ public void destroy() throws InterruptedException {
customDestroy();
}
- //-------------------------------------------------------------------------------------------------
- @Bean(CommonConstants.ARROWHEAD_CONTEXT)
- public Map getArrowheadContext() {
- return new ConcurrentHashMap<>();
- }
-
//=================================================================================================
// assistant methods
@@ -187,12 +181,15 @@ private void obtainKeys(final KeyStore keyStore, final ApplicationContext appCon
logger.debug("obtainKeys started...");
@SuppressWarnings("unchecked")
final Map context = appContext.getBean(CommonConstants.ARROWHEAD_CONTEXT, Map.class);
-
- publicKey = Utilities.getFirstCertFromKeyStore(keyStore).getPublicKey();
+
+ final X509Certificate serverCertificate = Utilities.getFirstCertFromKeyStore(keyStore);
+ publicKey = serverCertificate.getPublicKey();
context.put(CommonConstants.SERVER_PUBLIC_KEY, publicKey);
-
+
final PrivateKey privateKey = Utilities.getPrivateKey(keyStore, sslProperties.getKeyPassword());
context.put(CommonConstants.SERVER_PRIVATE_KEY, privateKey);
+
+ context.put(CommonConstants.SERVER_CERTIFICATE, serverCertificate);
}
//-------------------------------------------------------------------------------------------------
@@ -219,7 +216,7 @@ private void registerCoreSystemServicesToServiceRegistry(final ApplicationContex
final ServiceQueryFormDTO queryForm = new ServiceQueryFormDTO.Builder(coreService.getServiceDefinition()).build();
final ResponseEntity queryResponse = httpService.sendRequest(queryUri, HttpMethod.POST, ServiceQueryResultDTO.class, queryForm);
- for (final ServiceRegistryResponseDTO result : queryResponse.getBody().getServiceQueryData()) { // stucked entries
+ for (final ServiceRegistryResponseDTO result : queryResponse.getBody().getServiceQueryData()) { // old, possibly obsolete entries
final UriComponents unregisterUri = createUnregisterUri(scheme, coreService, result.getProvider().getAddress(), result.getProvider().getPort());
httpService.sendRequest(unregisterUri, HttpMethod.DELETE, Void.class);
}
diff --git a/core-common/src/main/java/eu/arrowhead/common/CommonConstants.java b/core-common/src/main/java/eu/arrowhead/common/CommonConstants.java
index 7ef651842..dd591fab9 100644
--- a/core-common/src/main/java/eu/arrowhead/common/CommonConstants.java
+++ b/core-common/src/main/java/eu/arrowhead/common/CommonConstants.java
@@ -1,12 +1,11 @@
package eu.arrowhead.common;
-import java.util.List;
-
+import eu.arrowhead.common.core.CoreSystemService;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
import org.jose4j.jws.AlgorithmIdentifiers;
-import eu.arrowhead.common.core.CoreSystemService;
+import java.util.List;
public class CommonConstants {
@@ -14,15 +13,21 @@ public class CommonConstants {
// members
public static final String BASE_PACKAGE = "eu.arrowhead";
-
+
public static final String CORE_SYSTEM_AUTHORIZATION = "Authorization";
+ public static final String CORE_SYSTEM_CERTIFICATE_AUTHORITY = "Certificate Authority";
public static final String CORE_SYSTEM_CHOREOGRAPHER = "Choreographer";
public static final String CORE_SYSTEM_EVENT_HANDLER = "Event Handler";
public static final String CORE_SYSTEM_GATEKEEPER = "Gatekeeper";
public static final String CORE_SYSTEM_GATEWAY = "Gateway";
public static final String CORE_SYSTEM_ORCHESTRATOR = "Orchestrator";
public static final String CORE_SYSTEM_SERVICE_REGISTRY = "Service Registry";
-
+ public static final String CORE_SYSTEM_QOS_MONITOR = "Quality of Service Monitor";
+
+ public static final String CORE_SYSTEM_SYSTEM_REGISTRY = "System Registry";
+ public static final String CORE_SYSTEM_DEVICE_REGISTRY = "Device Registry";
+ public static final String CORE_SYSTEM_ONBOARDING = "Onboarding Controller";
+
public static final String CORE_SERVICE_AUTH_TOKEN_GENERATION = "token-generation";
public static final String CORE_SERVICE_AUTH_PUBLIC_KEY = "auth-public-key";
public static final String CORE_SERVICE_AUTH_CONTROL_INTRA = "authorization-control-intra";
@@ -41,14 +46,39 @@ public class CommonConstants {
public static final String CORE_SERVICE_EVENT_HANDLER_SUBSCRIBE = "event-subscribe";
public static final String CORE_SERVICE_EVENT_HANDLER_UNSUBSCRIBE = "event-unsubscribe";
public static final String CORE_SERVICE_EVENT_HANDLER_PUBLISH_AUTH_UPDATE = "event-publish-auth-update";
-
+
+
+ public static final String CORE_SERVICE_CERTIFICATE_AUTHORITY_SIGN = "ca-sign";
+
+ public static final String CORE_SERVICE_QOS_MONITOR_PING_MEASUREMENT = "qos-monitor-ping-measurement";
+
+
+ public static final String CORE_SERVICE_SERVICE_REGISTRY_REGISTER = "service-register";
+ public static final String CORE_SERVICE_SERVICE_REGISTRY_UNREGISTER = "service-unregister";
+
+ public static final String CORE_SERVICE_SYSTEM_REGISTRY_REGISTER = "system-register";
+ public static final String CORE_SERVICE_SYSTEM_REGISTRY_UNREGISTER = "system-unregister";
+ public static final String CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME = "system-onboarding-with-name";
+ public static final String CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR = "system-onboarding-with-csr";
+
+ public static final String CORE_SERVICE_DEVICE_REGISTRY_REGISTER = "device-register";
+ public static final String CORE_SERVICE_DEVICE_REGISTRY_UNREGISTER = "device-unregister";
+ public static final String CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_NAME = "device-onboarding-with-name";
+ public static final String CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_CSR = "device-onboarding-with-csr";
+
+ public static final String CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_NAME = "onboarding-with-certificate-and-name";
+ public static final String CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_CSR = "onboarding-with-certificate-and-csr";
+ public static final String CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_NAME = "onboarding-with-shared-secret-and-name";
+ public static final String CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_CSR = "onboarding-with-shared-secret-and-csr";
+
public static final String COMMON_FIELD_NAME_ID = "id";
public static final String ARROWHEAD_CONTEXT = "arrowheadContext";
public static final String SERVER_COMMON_NAME = "server.common.name";
public static final String SERVER_PUBLIC_KEY = "server.public.key";
public static final String SERVER_PRIVATE_KEY = "server.private.key";
-
+ public static final String SERVER_CERTIFICATE = "server.certificate";
+
public static final String HTTPS = "https";
public static final String HTTP = "http";
public static final String JSON = "JSON";
@@ -62,6 +92,16 @@ public class CommonConstants {
public static final String SERVICE_REGISTRY_PORT = "sr_port";
public static final String $SERVICE_REGISTRY_PORT_WD = "${" + SERVICE_REGISTRY_PORT + ":" + Defaults.DEFAULT_SERVICE_REGISTRY_PORT + "}";
+ public static final String ONBOARDING_URI = "/onboarding";
+ public static final String ONBOARDING_AUTH_WITH_CERTIFICATE_URI = "/certificate";
+ public static final String ONBOARDING_AUTH_WITH_SHARED_SECRET_URI = "/sharedsecret";
+ public static final String ONBOARDING_WITH_NAME_URI = "/name";
+ public static final String ONBOARDING_WITH_CSR_URI = "/csr";
+ public static final String OP_ONBOARDING_WITH_CERTIFICATE_AND_NAME = ONBOARDING_AUTH_WITH_CERTIFICATE_URI + ONBOARDING_WITH_NAME_URI;
+ public static final String OP_ONBOARDING_WITH_CERTIFICATE_AND_CSR = ONBOARDING_AUTH_WITH_CERTIFICATE_URI + ONBOARDING_WITH_CSR_URI;
+ public static final String OP_ONBOARDING_WITH_SHARED_SECRET_AND_NAME = ONBOARDING_AUTH_WITH_SHARED_SECRET_URI + ONBOARDING_WITH_NAME_URI;
+ public static final String OP_ONBOARDING_WITH_SHARED_SECRET_AND_CSR = ONBOARDING_AUTH_WITH_SHARED_SECRET_URI + ONBOARDING_WITH_CSR_URI;
+
public static final String SERVICE_REGISTRY_URI = "/serviceregistry";
public static final String OP_SERVICE_REGISTRY_REGISTER_URI = "/register";
public static final String OP_SERVICE_REGISTRY_UNREGISTER_URI = "/unregister";
@@ -70,25 +110,48 @@ public class CommonConstants {
public static final String OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_ADDRESS = "address";
public static final String OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_PORT = "port";
public static final String OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_SERVICE_DEFINITION = "service_definition";
-
+
+ public static final String SYSTEM_REGISTRY_URI = "/systemregistry";
+ public static final String OP_SYSTEM_REGISTRY_REGISTER_URI = "/register";
+ public static final String OP_SYSTEM_REGISTRY_UNREGISTER_URI = "/unregister";
+ public static final String OP_SYSTEM_REGISTRY_QUERY_URI = "/query";
+ public static final String OP_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_URI = ONBOARDING_WITH_NAME_URI;
+ public static final String OP_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_URI = ONBOARDING_WITH_CSR_URI;
+ public static final String OP_SYSTEM_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_SYSTEM_NAME = "system_name";
+ public static final String OP_SYSTEM_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_ADDRESS = "address";
+ public static final String OP_SYSTEM_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_PORT = "port";
+
+ public static final String DEVICE_REGISTRY_URI = "/deviceregistry";
+ public static final String OP_DEVICE_REGISTRY_REGISTER_URI = "/register";
+ public static final String OP_DEVICE_REGISTRY_UNREGISTER_URI = "/unregister";
+ public static final String OP_DEVICE_REGISTRY_QUERY_URI = "/query";
+ public static final String OP_DEVICE_REGISTRY_ONBOARDING_WITH_NAME_URI = ONBOARDING_WITH_NAME_URI;
+ public static final String OP_DEVICE_REGISTRY_ONBOARDING_WITH_CSR_URI = ONBOARDING_WITH_CSR_URI;
+ public static final String OP_DEVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_DEVICE_NAME = "device_name";
+ public static final String OP_DEVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_MAC_ADDRESS = "mac_address";
+
public static final String AUTHORIZATION_URI = "/authorization";
public static final String OP_AUTH_TOKEN_URI = "/token";
public static final String OP_AUTH_KEY_URI = "/publickey";
public static final String OP_AUTH_INTRA_CHECK_URI = "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/intracloud/check";
public static final String OP_AUTH_INTER_CHECK_URI = "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/intercloud/check";
public static final String OP_AUTH_SUBSCRIPTION_CHECK_URI = "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/subscription/check";
-
+
+ public static final String CERTIFICATE_AUTHRORITY_URI = "/certificate-authority";
+ public static final String OP_CA_CLOUD_COMMON_NAME_URI = "/name";
+ public static final String OP_CA_SIGN_CERTIFICATE_URI = "/sign";
+
public static final String ORCHESTRATOR_URI = "/orchestrator";
public static final String OP_ORCH_PROCESS = "/orchestration";
- public static final String ORCHESTRATON_FLAG_MATCHMAKING = "matchmaking";
- public static final String ORCHESTRATON_FLAG_METADATA_SEARCH = "metadataSearch";
- public static final String ORCHESTRATON_FLAG_ONLY_PREFERRED = "onlyPreferred";
- public static final String ORCHESTRATON_FLAG_PING_PROVIDERS = "pingProviders";
- public static final String ORCHESTRATON_FLAG_OVERRIDE_STORE = "overrideStore";
- public static final String ORCHESTRATON_FLAG_TRIGGER_INTER_CLOUD = "triggerInterCloud";
- public static final String ORCHESTRATON_FLAG_EXTERNAL_SERVICE_REQUEST = "externalServiceRequest";
- public static final String ORCHESTRATON_FLAG_ENABLE_INTER_CLOUD = "enableInterCloud";
- public static final String ORCHESTRATON_FLAG_ENABLE_QOS = "enableQoS";
+ public static final String ORCHESTRATION_FLAG_MATCHMAKING = "matchmaking";
+ public static final String ORCHESTRATION_FLAG_METADATA_SEARCH = "metadataSearch";
+ public static final String ORCHESTRATION_FLAG_ONLY_PREFERRED = "onlyPreferred";
+ public static final String ORCHESTRATION_FLAG_PING_PROVIDERS = "pingProviders";
+ public static final String ORCHESTRATION_FLAG_OVERRIDE_STORE = "overrideStore";
+ public static final String ORCHESTRATION_FLAG_TRIGGER_INTER_CLOUD = "triggerInterCloud";
+ public static final String ORCHESTRATION_FLAG_EXTERNAL_SERVICE_REQUEST = "externalServiceRequest";
+ public static final String ORCHESTRATION_FLAG_ENABLE_INTER_CLOUD = "enableInterCloud";
+ public static final String ORCHESTRATION_FLAG_ENABLE_QOS = "enableQoS";
public static final String GATEKEEPER_URI = "/gatekeeper";
public static final String OP_GATEKEEPER_GSD_SERVICE = "/init_gsd";
@@ -108,6 +171,10 @@ public class CommonConstants {
public static final String OP_EVENT_HANDLER_UNSUBSCRIBE = "/unsubscribe";
public static final String OP_EVENT_HANDLER_PUBLISH_AUTH_UPDATE = "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/publish/authupdate";
+ public static final String QOS_MONITOR_URI = "/qosmonitor";
+ public static final String OP_QOS_MONITOR_PING_MEASUREMENT = "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/ping/measurement";
+ public static final String OP_QOS_MONITOR_PING_MEASUREMENT_SUFFIX = "/{" + COMMON_FIELD_NAME_ID + "}";
+
public static final String SWAGGER_COMMON_PACKAGE = "eu.arrowhead.common.swagger";
public static final String SWAGGER_UI_URI = "/swagger-ui.html";
public static final String SWAGGER_HTTP_200_MESSAGE = "Core service is available";
@@ -149,6 +216,11 @@ public class CommonConstants {
public static final String DISABLE_HOSTNAME_VERIFIER = "disable.hostname.verifier";
public static final String $DISABLE_HOSTNAME_VERIFIER_WD = "${" + DISABLE_HOSTNAME_VERIFIER + ":" + Defaults.DEFAULT_DISABLE_HOSTNAME_VERIFIER + "}";
+ public static final String CA_CERT_VALIDITY_NEG_OFFSET_MILLIS = "ca.validity.negative-offest-millis";
+ public static final String $CA_CERT_VALIDITY_NEG_OFFSET_MILLIS = "${" + CA_CERT_VALIDITY_NEG_OFFSET_MILLIS + ":" + Defaults.DEFAULT_CA_CERT_VALIDITY_NEG_OFFSET_MILLIS + "}";
+ public static final String CA_CERT_VALIDITY_POS_OFFSET_MILLIS = "ca.validity.positive-offest-millis";
+ public static final String $CA_CERT_VALIDITY_POS_OFFSET_MILLIS = "${" + CA_CERT_VALIDITY_POS_OFFSET_MILLIS + ":" + Defaults.DEFAULT_CA_CERT_VALIDITY_POS_OFFSET_MILLIS + "}";
+
public static final String JWT_CLAIM_CONSUMER_ID = "cid";
public static final String JWT_CLAIM_SERVICE_ID = "sid";
public static final String JWT_CLAIM_INTERFACE_ID = "iid";
@@ -164,6 +236,7 @@ public class CommonConstants {
public static final long CONVERSION_MILLISECOND_TO_SECOND = 1000;
public static final long CONVERSION_MILLISECOND_TO_MINUTE = 60000;
+ public static final long CONVERSION_SECOND_TO_MINUTE = 60;
public static final String SORT_ORDER_ASCENDING = "ASC";
public static final String SORT_ORDER_DESCENDING = "DESC";
diff --git a/core-common/src/main/java/eu/arrowhead/common/CoreCommonConstants.java b/core-common/src/main/java/eu/arrowhead/common/CoreCommonConstants.java
index 02bd3b73d..6a5e76e22 100644
--- a/core-common/src/main/java/eu/arrowhead/common/CoreCommonConstants.java
+++ b/core-common/src/main/java/eu/arrowhead/common/CoreCommonConstants.java
@@ -21,6 +21,7 @@ public class CoreCommonConstants {
public static final String SR_QUERY_URI = "service.registry.query.uri";
public static final String SR_QUERY_BY_SYSTEM_ID_URI = "service.registry.query.by.system.id.uri";
public static final String SR_QUERY_BY_SYSTEM_DTO_URI = "service.registry.query.by.system.dto.uri";
+ public static final String SR_QUERY_ALL = "service.registry.query.all.uri";
public static final String REQUIRED_URI_LIST = "required.uri.list";
public static final String URI_SUFFIX = "-uri";
@@ -33,9 +34,16 @@ public class CoreCommonConstants {
public static final String SERVER_ERROR_URI = "/error";
public static final String MGMT_URI = "/mgmt";
-
+
+ public static final String OP_DEVICE_REGISTRY_QUERY_BY_DEVICE_ID_URI = "/query/device/{" + COMMON_FIELD_NAME_ID + "}";
+ public static final String OP_DEVICE_REGISTRY_QUERY_BY_DEVICE_DTO_URI = "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/query/device";
+
+ public static final String OP_SYSTEM_REGISTRY_QUERY_BY_SYSTEM_ID_URI = "/query/system/{" + COMMON_FIELD_NAME_ID + "}";
+ public static final String OP_SYSTEM_REGISTRY_QUERY_BY_SYSTEM_DTO_URI = "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/query/system";
+
public static final String OP_SERVICE_REGISTRY_QUERY_BY_SYSTEM_ID_URI = "/query/system/{" + COMMON_FIELD_NAME_ID + "}";
public static final String OP_SERVICE_REGISTRY_QUERY_BY_SYSTEM_DTO_URI = "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/query/system";
+ public static final String OP_SERVICE_REGISTRY_QUERY_ALL_URI = "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/query/all";
public static final String ORCHESTRATOR_STORE_MGMT_URI = "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/mgmt/store";
@@ -48,6 +56,7 @@ public class CoreCommonConstants {
public static final String SWAGGER_TAG_MGMT = "Management";
public static final String SWAGGER_TAG_CLIENT = "Client";
public static final String SWAGGER_TAG_PRIVATE = "Private";
+ public static final String SWAGGER_TAG_ONBOARDING = "Onboarding";
public static final String SWAGGER_TAG_ALL = "All";
public static final String SERVER_ADDRESS = "server.address";
@@ -88,14 +97,18 @@ public class CoreCommonConstants {
public static final String SERVICE_REGISTRY_PING_INTERVAL = "ping_interval";
public static final String $SERVICE_REGISTRY_PING_INTERVAL_WD = "${" + SERVICE_REGISTRY_PING_INTERVAL + ":" + CoreDefaults.DEFAULT_SERVICE_REGISTRY_PING_INTERVAL_MINUTES + "}";
public static final String SERVICE_REGISTRY_PING_TIMEOUT = "ping_timeout";
- public static final String $SERVICE_REGISTRY_PING_TIMEOUT_WD = "${" + SERVICE_REGISTRY_PING_TIMEOUT + ":" + CoreDefaults.DEFAULT_SERVICE_REGISTRY_PING_TIMEOUT_MILISECONDS + "}";
+ public static final String $SERVICE_REGISTRY_PING_TIMEOUT_WD = "${" + SERVICE_REGISTRY_PING_TIMEOUT + ":" + CoreDefaults.DEFAULT_SERVICE_REGISTRY_PING_TIMEOUT_MILLISECONDS + "}";
public static final String SERVICE_REGISTRY_TTL_SCHEDULED = "ttl_scheduled";
public static final String $SERVICE_REGISTRY_TTL_SCHEDULED_WD = "${" + SERVICE_REGISTRY_TTL_SCHEDULED + ":" + CoreDefaults.DEFAULT_SERVICE_REGISTRY_TTL_SCHEDULED + "}";
public static final String SERVICE_REGISTRY_TTL_INTERVAL = "ttl_interval";
public static final String $SERVICE_REGISTRY_TTL_INTERVAL_WD = "${" + SERVICE_REGISTRY_TTL_INTERVAL + ":" + CoreDefaults.DEFAULT_SERVICE_REGISTRY_TTL_INTERVAL_MINUTES + "}";
-
+
+ public static final String SYSTEM_REGISTRY_PING_TIMEOUT = "ping_timeout";
+ public static final String $SYSTEM_REGISTRY_PING_TIMEOUT_WD =
+ "${" + SYSTEM_REGISTRY_PING_TIMEOUT + ":" + CoreDefaults.DEFAULT_SYSTEM_REGISTRY_PING_TIMEOUT_MILLISECONDS + "}";
+
public static final String AUTHORIZATION_IS_EVENTHANDLER_PRESENT = "eventhandler_is_present";
- public static final String $AUTHORIZATION_IS_EVENTHANDLER_PRESENT_WD = "${" + AUTHORIZATION_IS_EVENTHANDLER_PRESENT + ":" +CoreDefaults.DEFAULT_AUTHORIZATION_IS_EVENTHANDLER_PRESENT + "}";
+ public static final String $AUTHORIZATION_IS_EVENTHANDLER_PRESENT_WD = "${" + AUTHORIZATION_IS_EVENTHANDLER_PRESENT + ":" + CoreDefaults.DEFAULT_AUTHORIZATION_IS_EVENTHANDLER_PRESENT + "}";
public static final String ORCHESTRATOR_IS_GATEKEEPER_PRESENT = "gatekeeper_is_present";
public static final String $ORCHESTRATOR_IS_GATEKEEPER_PRESENT_WD = "${" + ORCHESTRATOR_IS_GATEKEEPER_PRESENT + ":" + CoreDefaults.DEFAULT_ORCHESTRATOR_IS_GATEKEEPER_PRESENT + "}";
@@ -116,6 +129,20 @@ public class CoreCommonConstants {
public static final int TOP_PRIORITY = 1;
+ public static final String QOS_MANAGER = "qosManager";
+ public static final String QOS_ENABLED = "enable_qos";
+ public static final String $QOS_ENABLED_WD = "${" + QOS_ENABLED + ":" + CoreDefaults.DEFAULT_QOS_ENABLED + "}";
+ public static final String QOS_RESERVATION_CHECK_INTERVAL = "qos_reservation_check_interval"; // in seconds
+ public static final String $QOS_RESERVATION_CHECK_INTERVAL_WD = "${" + QOS_RESERVATION_CHECK_INTERVAL + ":" + CoreDefaults.DEFAULT_QOS_RESERVATION_CHECK_INTERVAL + "}";
+ public static final String QOS_RESERVATION_TEMP_LOCK_DURATION = "qos_reservation_temp_lock_duration"; // in seconds
+ public static final String $QOS_RESERVATION_TEMP_LOCK_DURATION_WD = "${" + QOS_RESERVATION_TEMP_LOCK_DURATION + ":" + CoreDefaults.DEFAULT_QOS_TEMPORARY_LOCK_DURATION + "}";
+ public static final String QOS_MAX_RESERVATION_DURATION = "qos_maximum_reservation_duration"; // in seconds
+ public static final String $QOS_MAX_RESERVATION_DURATION_WD = "${" + QOS_MAX_RESERVATION_DURATION + ":" + CoreDefaults.DEFAULT_QOS_MAX_RESERVATION_DURATION + "}";
+ public static final String QOS_PING_MEASUREMENT_CACHE_THRESHOLD = "qos_ping_measurement_cache_threshold"; // in seconds
+ public static final String $QOS_PING_MEASUREMENT_CACHE_THRESHOLD_WD = "${" + QOS_PING_MEASUREMENT_CACHE_THRESHOLD + ":" + CoreDefaults.DEFAULT_QOS_PING_MEASUREMENT_CACHE_THRESHOLD + "}";
+ public static final String QOS_NOT_MEASURED_SYSTEM_VERIFY_RESULT = "qos_not_measured_system_verify_result"; // result of verify if a system has no measurement records
+ public static final String $QOS_NOT_MEASURED_SYSTEM_VERIFY_RESULT = "${" + QOS_NOT_MEASURED_SYSTEM_VERIFY_RESULT + ":" + CoreDefaults.DEFAULT_QOS_NOT_MEASURED_SYSTEM_VERIFY_RESULT + "}";
+
public static final String NO_GATEKEEPER_RELAY_REQUEST_HANDLER_WORKERS = "no_gatekeeper_relay_request_handler_workers";
public static final String $NO_GATEKEEPER_RELAY_REQUEST_HANDLER_WORKERS_WD = "${" + NO_GATEKEEPER_RELAY_REQUEST_HANDLER_WORKERS + ":" +
CoreDefaults.DEFAULT_NO_GATEKEEPER_RELAY_REQUEST_HANDLER_WORKERS + "}";
@@ -145,7 +172,14 @@ public class CoreCommonConstants {
public static final String $EVENT_HANDLER_MAX_EXPRESS_SUBSCRIBERS_WD = "${" + EVENT_HANDLER_MAX_EXPRESS_SUBSCRIBERS + ":" + CoreDefaults.DEFAULT_EVENT_HANDLER_MAX_EXPRESS_SUBSCRIBERS + "}";
public static final String EVENT_PUBLISHING_EXPRESS_EXECUTOR = "eventPublishingExpressExecutor";
- //=================================================================================================
+ public static final String PING_TTL_INTERVAL = "ping_ttl_interval_minutes";
+ public static final String $PING_TTL_INTERVAL_WD = "${" + PING_TTL_INTERVAL + ":" + CoreDefaults.DEFAULT_PING_TTL_INTERVAL_MINUTES + "}";
+
+ public static final String CLOUD_PING_TTL_INTERVAL = "cloud_ping_ttl_interval_minutes";
+ public static final String $CLOUD_PING_TTL_INTERVAL_WD = "${" + CLOUD_PING_TTL_INTERVAL + ":" + CoreDefaults.DEFAULT_CLOUD_PING_TTL_INTERVAL_MINUTES + "}";
+ public static final String CERTIFICATE_FORMAT = "X.509";
+
+ //=================================================================================================
// assistant methods
//-------------------------------------------------------------------------------------------------
diff --git a/core-common/src/main/java/eu/arrowhead/common/CoreDefaults.java b/core-common/src/main/java/eu/arrowhead/common/CoreDefaults.java
index 8ffc12b5c..c53c885fc 100644
--- a/core-common/src/main/java/eu/arrowhead/common/CoreDefaults.java
+++ b/core-common/src/main/java/eu/arrowhead/common/CoreDefaults.java
@@ -13,13 +13,17 @@ public class CoreDefaults {
public static final boolean DEFAULT_USE_STRICT_SERVICE_INTF_NAME_VERIFIER = false;
public static final int DEFAULT_URI_CRAWLER_INTERVAL = 30;
public static final int DEFAULT_AUTH_TOKEN_TTL_IN_MINUTES = -1; // never expires
+ public static final int DEFAULT_AUTH_TOKEN_TTL_IN_MINUTES_WITH_QOS_ENABLED = 60; // when QoS enabled, we want to make sure that tokens expires eventually
public static final boolean DEFAULT_SERVICE_REGISTRY_PING_SCHEDULED = false;
public static final int DEFAULT_SERVICE_REGISTRY_PING_INTERVAL_MINUTES = 60;
- public static final int DEFAULT_SERVICE_REGISTRY_PING_TIMEOUT_MILISECONDS = 5000;
+ public static final int DEFAULT_SERVICE_REGISTRY_PING_TIMEOUT_MILLISECONDS = 5000;
public static final boolean DEFAULT_SERVICE_REGISTRY_TTL_SCHEDULED = false;
public static final int DEFAULT_SERVICE_REGISTRY_TTL_INTERVAL_MINUTES = 13;
-
+
+ public static final int DEFAULT_SYSTEM_REGISTRY_PING_INTERVAL_MINUTES = 60;
+ public static final int DEFAULT_SYSTEM_REGISTRY_PING_TIMEOUT_MILLISECONDS = 5000;
+
public static final String DEFAULT_OWN_CLOUD_OPERATOR = "default_operator";
public static final String DEFAULT_OWN_CLOUD_NAME = "default_insecure_cloud";
@@ -45,6 +49,17 @@ public class CoreDefaults {
public static final long DEFAULT_TIME_STAMP_TOLERANCE_SECONDS = 120;
public static final int DEFAULT_EVENT_HANDLER_MAX_EXPRESS_SUBSCRIBERS = 10;
+ public static final int DEFAULT_PING_TTL_INTERVAL_MINUTES = 10;
+
+ public static final int DEFAULT_CLOUD_PING_TTL_INTERVAL_MINUTES = 10;
+
+ public static final boolean DEFAULT_QOS_ENABLED = false;
+ public static final int DEFAULT_QOS_RESERVATION_CHECK_INTERVAL = 60; // in seconds
+ public static final int DEFAULT_QOS_TEMPORARY_LOCK_DURATION = 60; // in seconds
+ public static final int DEFAULT_QOS_MAX_RESERVATION_DURATION = 3600; // in seconds
+ public static final int DEFAULT_QOS_PING_MEASUREMENT_CACHE_THRESHOLD = 600; // in seconds
+ public static final boolean DEFAULT_QOS_NOT_MEASURED_SYSTEM_VERIFY_RESULT = true;
+
//=================================================================================================
// assistant methods
diff --git a/core-common/src/main/java/eu/arrowhead/common/CoreUtilities.java b/core-common/src/main/java/eu/arrowhead/common/CoreUtilities.java
index fd20c8d76..e669c98cb 100644
--- a/core-common/src/main/java/eu/arrowhead/common/CoreUtilities.java
+++ b/core-common/src/main/java/eu/arrowhead/common/CoreUtilities.java
@@ -73,24 +73,25 @@ public static class ValidatedPageParams {
//=================================================================================================
// members
-
+ private static final int MAX_BATCH_SIZE = Integer.MAX_VALUE;
+
private final int validatedPage;
private final int validatedSize;
- private final Direction validatedDirecion;
+ private final Direction validatedDirection;
//=================================================================================================
// methods
//-------------------------------------------------------------------------------------------------
public ValidatedPageParams(final int validatedPage, final int validatedSize, final Direction validatedDirection) {
- this.validatedPage = validatedPage;
- this.validatedSize = validatedSize;
- this.validatedDirecion = validatedDirection;
+ this.validatedPage = Math.max(validatedPage, 0);
+ this.validatedSize = validatedSize < 1 ? MAX_BATCH_SIZE : validatedSize;
+ this.validatedDirection = validatedDirection;
}
//-------------------------------------------------------------------------------------------------
public int getValidatedPage() { return validatedPage; }
public int getValidatedSize() { return validatedSize; }
- public Direction getValidatedDirecion() { return validatedDirecion; }
+ public Direction getValidatedDirection() { return validatedDirection; }
}
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/Defaults.java b/core-common/src/main/java/eu/arrowhead/common/Defaults.java
index e5db9ed31..5460b30fd 100644
--- a/core-common/src/main/java/eu/arrowhead/common/Defaults.java
+++ b/core-common/src/main/java/eu/arrowhead/common/Defaults.java
@@ -11,27 +11,34 @@ public class Defaults {
public static final int DEFAULT_URI_CRAWLER_INTERVAL = 30;
public static final int DEFAULT_AUTH_TOKEN_TTL_IN_MINUTES = -1; // never expires
- public static final String DEFAULT_SERVICE_REGISTRY_ADDRESS = CommonConstants.LOCALHOST;
+ public static final String DEFAULT_SERVICE_REGISTRY_ADDRESS = CommonConstants.LOCALHOST;
+ public static final int DEFAULT_ONBOARDING_PORT = 8435;
+ public static final int DEFAULT_SYSTEM_REGISTRY_PORT = 8437;
+ public static final int DEFAULT_DEVICE_REGISTRY_PORT = 8439;
+ public static final int DEFAULT_ORCHESTRATOR_PORT = 8441;
public static final int DEFAULT_SERVICE_REGISTRY_PORT = 8443;
public static final int DEFAULT_AUTHORIZATION_PORT = 8445;
- public static final int DEFAULT_ORCHESTRATOR_PORT = 8441;
- public static final int DEFAULT_GATEKEEPER_PORT = 8449;
+ public static final int DEFAULT_GATEKEEPER_PORT = 8449;
+ public static final int DEFAULT_QOS_MONITOR_PORT = 8451;
public static final int DEFAULT_GATEWAY_PORT = 8453;
public static final int DEFAULT_EVENT_HANDLER_PORT = 8455;
public static final int DEFAULT_CHOREOGRAPHER_PORT = 8457;
- public static final int DEFAULT_CERTIFICATE_AUTHORITY_PORT = 8459;
-
- // HTTP client defaults
- public static final int DEFAULT_CONNECTION_TIMEOUT = 30000;
- public static final int DEFAULT_SOCKET_TIMEOUT = 30000;
- public static final int DEFAULT_CONNECTION_MANAGER_TIMEOUT = 10000;
-
- // CORS defaults
- public static final long CORS_MAX_AGE = 600;
- public static final String CORS_ALLOW_CREDENTIALS = "true";
-
- //-------------------------------------------------------------------------------------------------
- private Defaults() {
- throw new UnsupportedOperationException();
- }
+ public static final int DEFAULT_CERTIFICATE_AUTHORITY_PORT = 8448;
+
+ // HTTP client defaults
+ public static final int DEFAULT_CONNECTION_TIMEOUT = 30000;
+ public static final int DEFAULT_SOCKET_TIMEOUT = 30000;
+ public static final int DEFAULT_CONNECTION_MANAGER_TIMEOUT = 10000;
+
+ // CORS defaults
+ public static final long CORS_MAX_AGE = 600;
+ public static final String CORS_ALLOW_CREDENTIALS = "true";
+
+ // CA defaults
+ public static final long DEFAULT_CA_CERT_VALIDITY_NEG_OFFSET_MILLIS = 5000;
+ public static final long DEFAULT_CA_CERT_VALIDITY_POS_OFFSET_MILLIS = 1000L * 3600 * 24 * 365;
+ //-------------------------------------------------------------------------------------------------
+ private Defaults() {
+ throw new UnsupportedOperationException();
+ }
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/SecurityUtilities.java b/core-common/src/main/java/eu/arrowhead/common/SecurityUtilities.java
new file mode 100644
index 000000000..3c371fe8a
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/SecurityUtilities.java
@@ -0,0 +1,340 @@
+package eu.arrowhead.common;
+
+import eu.arrowhead.common.dto.shared.CertificateCreationRequestDTO;
+import eu.arrowhead.common.dto.shared.CertificateCreationResponseDTO;
+import eu.arrowhead.common.dto.shared.CertificateType;
+import eu.arrowhead.common.dto.shared.KeyPairDTO;
+import eu.arrowhead.common.exception.ArrowheadException;
+import eu.arrowhead.common.exception.AuthException;
+import org.apache.http.HttpStatus;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNamesBuilder;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Objects;
+
+@Component
+public class SecurityUtilities {
+
+ //=================================================================================================
+ // members
+ private final static String SIGNATURE_ALGORITHM = "SHA256WithRSA";
+
+ private final Logger logger = LogManager.getLogger(SecurityUtilities.class);
+
+ private final KeyFactory keyFactory;
+ private final KeyPairGenerator keyPairGenerator;
+ private final SSLProperties sslProperties;
+
+ //=================================================================================================
+ // constructors
+ @Autowired
+ public SecurityUtilities(@Value("${security.key.algorithm:RSA}") final String keyFactoryAlgorithm,
+ @Value("${security.key.size:2048}") final Integer keySize,
+ final SSLProperties sslProperties) throws NoSuchAlgorithmException {
+ Assert.hasText(keyFactoryAlgorithm,"keyFactoryAlgorithm must not be null");
+ Assert.notNull(keySize,"keyFactoryAlgorithm keySize not be null");
+ Assert.notNull(sslProperties,"sslProperties must not be null");
+ this.sslProperties = sslProperties;
+ keyFactory = KeyFactory.getInstance(keyFactoryAlgorithm);
+ keyPairGenerator = KeyPairGenerator.getInstance(keyFactoryAlgorithm);
+ keyPairGenerator.initialize(keySize);
+ }
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public static String getCertificateCNFromRequest(final HttpServletRequest request) {
+ Assert.notNull(request,"request must not be null");
+ final X509Certificate[] certificates = (X509Certificate[]) request.getAttribute(CommonConstants.ATTR_JAVAX_SERVLET_REQUEST_X509_CERTIFICATE);
+ if (certificates != null && certificates.length != 0) {
+ final X509Certificate cert = certificates[0];
+ return Utilities.getCertCNFromSubject(cert.getSubjectDN().getName());
+ }
+
+ return null;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private static String getCommonNameFromCloudCertificate(final Principal principal) {
+ Assert.notNull(principal, "Principal must not be null");
+ return Utilities.getCertCNFromSubject(principal.getName());
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private static String getOperatorNameFromCloudCertificate(final Principal principal) {
+ return extractCNPart(principal, 2);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private static String getOrganizationFromCloudCertificate(final Principal principal) {
+ return extractCNPart(principal, 1);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private static String getCountryFromCloudCertificate(final Principal principal) {
+ return extractCNPart(principal, 0);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private static String extractCNPart(final Principal principal, final int tailIndex) {
+ Assert.notNull(principal, "Principal must not be null");
+ Assert.isTrue(tailIndex >= 0, "tailIndex must not be negative");
+ final String fullCN = principal.getName();
+ Assert.hasText(fullCN, "Empty common name is not allowed");
+
+ final String[] strings = fullCN.split("\\.");
+
+ if (tailIndex >= strings.length) {
+ throw new IllegalArgumentException("Internal error: Unable to extract information from cloud certificate");
+ }
+
+ return strings[strings.length - (tailIndex + 1)];
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public void authenticateCertificate(final HttpServletRequest httpServletRequest, final CertificateType minimumStrength) {
+ Assert.notNull(httpServletRequest,"httpServletRequest must not be null");
+ Assert.notNull(minimumStrength,"minimumStrength must not be null");
+
+ final X509Certificate[] certificates = (X509Certificate[]) httpServletRequest.getAttribute(CommonConstants.ATTR_JAVAX_SERVLET_REQUEST_X509_CERTIFICATE);
+
+ if (sslProperties.isSslEnabled()) {
+ if (Objects.nonNull(certificates) && certificates.length > 0) {
+
+ final X509Certificate cert = certificates[0];
+ final String clientCN = Utilities.getCertCNFromSubject(cert.getSubjectDN().getName());
+ final String requestTarget = Utilities.stripEndSlash(httpServletRequest.getRequestURL().toString());
+
+ authenticateCertificate(clientCN, requestTarget, minimumStrength);
+ } else {
+ logger.debug("No client certificate given!");
+ throw new AuthException("Client certificate in needed!");
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public void authenticateCertificate(final String clientCN, final String requestTarget, final CertificateType minimumStrength) {
+ Assert.notNull(clientCN,"clientCN must not be null");
+ Assert.notNull(requestTarget,"requestTarget must not be null");
+ Assert.notNull(minimumStrength,"minimumStrength must not be null");
+
+ if (sslProperties.isSslEnabled()) {
+
+ final CertificateType type = CertificateType.getTypeFromCN(clientCN);
+ if (!type.hasMinimumStrength(minimumStrength)) {
+ logger.debug("{} is not a valid common name, access denied!", clientCN);
+ throw new AuthException(clientCN + " is unauthorized to access " + requestTarget);
+ }
+ }
+ }
+
+ //=================================================================================================
+ // assistant methods
+
+ //-------------------------------------------------------------------------------------------------
+ public String createCertificateSigningRequest(final String baseCommonName, final KeyPair keyPair, final CertificateType type,
+ final String host, final String address)
+ throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, OperatorCreationException {
+ Assert.hasText(baseCommonName, "baseCommonName must not be null or empty!");
+ Assert.notNull(keyPair, "keyPair must not be null");
+ Assert.notNull(sslProperties.getKeyStore(), "KeyStore property must not be null!");
+ Assert.hasText(sslProperties.getKeyStorePassword(), "KeyStore password property must not be null or empty!");
+ Assert.notNull(type, "type must not be null");
+ // host and address are optional
+
+ logger.debug("Preparing Certificate Signing Request ...");
+ // get cloud certificate for cloudName and operator
+ final KeyStore keyStore = KeyStore.getInstance(sslProperties.getKeyStore().getFile(), sslProperties.getKeyStorePassword().toCharArray());
+ final X509Certificate cloudCertFromKeyStore = Utilities.getCloudCertFromKeyStore(keyStore);
+
+ // "CN=....arrowhead.eu, OU=, O=arrowhead, C=eu"
+ final String cloudName = getCommonNameFromCloudCertificate(cloudCertFromKeyStore.getSubjectDN());
+ final String operator = getOperatorNameFromCloudCertificate(cloudCertFromKeyStore.getSubjectDN());
+ final String organization = getOrganizationFromCloudCertificate(cloudCertFromKeyStore.getSubjectDN());
+ final String country = getCountryFromCloudCertificate(cloudCertFromKeyStore.getSubjectDN());
+ final String commonName = String.format("CN=%s.%s, OU=%s, O=%s, C=%s", type.appendTypeToCN(baseCommonName), cloudName,
+ operator, organization, country);
+ final X500Name x500Name = new X500Name(commonName);
+
+ logger.debug("Building and Signing Certificate Signing Request for {}", x500Name);
+ // create certificate signing request
+ final JcaPKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(x500Name, keyPair.getPublic());
+ final GeneralNamesBuilder namesBuilder = new GeneralNamesBuilder();
+
+ namesBuilder.addName(new GeneralName(GeneralName.dNSName, "localhost"));
+ namesBuilder.addName(new GeneralName(GeneralName.dNSName, baseCommonName));
+ namesBuilder.addName(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
+
+ if (StringUtils.hasText(host)) {
+ namesBuilder.addName(new GeneralName(GeneralName.dNSName, host));
+ }
+ if (StringUtils.hasText(address)) {
+ namesBuilder.addName(new GeneralName(GeneralName.iPAddress, address));
+ }
+
+ final Extension extAlternativeNames = new Extension(Extension.subjectAlternativeName, false, new DEROctetString(namesBuilder.build()));
+ builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, new Extensions(extAlternativeNames));
+
+ final JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM);
+ final ContentSigner contentSigner = contentSignerBuilder.build(keyPair.getPrivate());
+ final PKCS10CertificationRequest csr = builder.build(contentSigner);
+
+ return Base64.getEncoder().encodeToString(csr.getEncoded());
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public void extractAndSetPublicKey(final CertificateCreationResponseDTO creationResponseDTO) {
+ Assert.notNull(creationResponseDTO, "creationResponseDTO must not be null");
+
+ try {
+ final byte[] certificateBytes = Base64Utils.decodeFromString(creationResponseDTO.getCertificate());
+
+ final Certificate certificate;
+
+ try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(certificateBytes)) {
+ final CertificateFactory certificateFactory = CertificateFactory.getInstance(creationResponseDTO.getCertificateFormat());
+ certificate = certificateFactory.generateCertificate(byteArrayInputStream);
+ } catch (final CertificateException e) {
+ logger.error("Unable to generate certificate from Base64: {}", creationResponseDTO.getCertificate());
+ throw new ArrowheadException("Unable to decode signed certificate", HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ }
+
+ final PublicKey publicKey = certificate.getPublicKey();
+ creationResponseDTO.setKeyPairDTO(encodePublicKey(publicKey));
+
+ } catch (final IOException e) {
+ logger.fatal("ByteArrayInputStream should never throw an IOException, but it just did : {}", e.getMessage());
+ throw new ArrowheadException(e.getMessage());
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public KeyPair extractOrGenerateKeyPair(final CertificateCreationRequestDTO creationRequestDTO) {
+ Assert.notNull(creationRequestDTO, "creationRequestDTO must not be null");
+
+ final String commonName = creationRequestDTO.getCommonName();
+ Assert.isTrue(Utilities.notEmpty(commonName), "CommonName is null or blank");
+
+ final KeyPairDTO keyPairDTO = creationRequestDTO.getKeyPairDTO();
+ final KeyPair keyPair;
+
+ if (Objects.nonNull(keyPairDTO) &&
+ Objects.nonNull(keyPairDTO.getPublicKey()) &&
+ Objects.nonNull(keyPairDTO.getPrivateKey())) {
+
+ final String encodedPublicKey = keyPairDTO.getPublicKey();
+ final String encodedPrivateKey = keyPairDTO.getPrivateKey();
+
+ keyPair = getKeyPairFromBase64EncodedStrings(encodedPublicKey, encodedPrivateKey);
+ } else {
+ keyPair = generateKeyPair();
+ }
+
+ return keyPair;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public KeyPairDTO encodePublicKey(final PublicKey publicKey) {
+ Assert.notNull(publicKey, "PublicKey must not be null");
+ final String encodedPublicKey = Base64.getEncoder().encodeToString(publicKey.getEncoded());
+ return new KeyPairDTO(publicKey.getAlgorithm(), publicKey.getFormat(), encodedPublicKey, null);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public KeyPairDTO encodeKeyPair(final KeyPair keyPair) {
+ Assert.notNull(keyPair, "KeyPair must not be null");
+ final KeyPairDTO dto = encodePublicKey(keyPair.getPublic());
+ if (Objects.nonNull(keyPair.getPrivate())) { dto.setPrivateKey(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded())); }
+ return dto;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private PublicKey getPublicKeyFromBase64EncodedString(final String encodedKey) {
+ Assert.isTrue(Utilities.notEmpty(encodedKey), "Encoded key is null or blank");
+
+ final byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
+ return generatePublicKeyFromByteArray(keyBytes);
+ }
+
+
+ //-------------------------------------------------------------------------------------------------
+ private KeyPair generateKeyPair() {
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private KeyPair getKeyPairFromBase64EncodedStrings(final String encodedPublicKey,
+ final String encodedPrivateKey) {
+ final PublicKey publicKey = getPublicKeyFromBase64EncodedString(encodedPublicKey);
+ final PrivateKey privateKey = getPrivateKeyFromBase64EncodedString(encodedPrivateKey);
+ return new KeyPair(publicKey, privateKey);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private PrivateKey getPrivateKeyFromBase64EncodedString(final String encodedKey) {
+ Assert.isTrue(Utilities.notEmpty(encodedKey), "Encoded key is null or blank");
+
+ final byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
+ return generatePrivateKeyFromByteArray(keyBytes);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private PublicKey generatePublicKeyFromByteArray(final byte[] keyBytes) {
+ try {
+ return keyFactory.generatePublic(new X509EncodedKeySpec(keyBytes));
+ } catch (final InvalidKeySpecException ex) {
+ logger.error("getPublicKey: X509 keySpec could not be created from the decoded bytes.");
+ throw new AuthException("Public key decoding failed due wrong input key", ex);
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private PrivateKey generatePrivateKeyFromByteArray(final byte[] keyBytes) {
+ try {
+ return keyFactory.generatePrivate(new X509EncodedKeySpec(keyBytes));
+ } catch (final InvalidKeySpecException ex) {
+ logger.error("getPublicKey: X509 keySpec could not be created from the decoded bytes.");
+ throw new AuthException("Public key decoding failed due wrong input key", ex);
+ }
+ }
+
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/Utilities.java b/core-common/src/main/java/eu/arrowhead/common/Utilities.java
index 790ea5832..632f7a0a4 100644
--- a/core-common/src/main/java/eu/arrowhead/common/Utilities.java
+++ b/core-common/src/main/java/eu/arrowhead/common/Utilities.java
@@ -1,5 +1,31 @@
package eu.arrowhead.common;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import eu.arrowhead.common.dto.internal.RelayType;
+import eu.arrowhead.common.dto.shared.ErrorMessageDTO;
+import eu.arrowhead.common.exception.ArrowheadException;
+import eu.arrowhead.common.exception.AuthException;
+import eu.arrowhead.common.exception.BadPayloadException;
+import eu.arrowhead.common.exception.DataNotFoundException;
+import eu.arrowhead.common.exception.InvalidParameterException;
+import eu.arrowhead.common.exception.TimeoutException;
+import eu.arrowhead.common.exception.UnavailableServerException;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.http.HttpStatus;
+import org.springframework.lang.Nullable;
+import org.springframework.util.Assert;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -13,6 +39,7 @@
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
@@ -31,60 +58,37 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.ServiceConfigurationError;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.springframework.http.HttpStatus;
-import org.springframework.lang.Nullable;
-import org.springframework.util.Assert;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.util.UriComponents;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-
-import eu.arrowhead.common.dto.internal.RelayType;
-import eu.arrowhead.common.dto.shared.ErrorMessageDTO;
-import eu.arrowhead.common.exception.ArrowheadException;
-import eu.arrowhead.common.exception.AuthException;
-import eu.arrowhead.common.exception.BadPayloadException;
-import eu.arrowhead.common.exception.DataNotFoundException;
-import eu.arrowhead.common.exception.InvalidParameterException;
-import eu.arrowhead.common.exception.TimeoutException;
-import eu.arrowhead.common.exception.UnavailableServerException;
-
public class Utilities {
-
+
//=================================================================================================
// members
-
+
private static final int SERVICE_CN_NAME_LENGTH = 5;
@SuppressWarnings("unused")
private static final int CLOUD_CN_NAME_LENGTH = 4;
@SuppressWarnings("unused")
private static final int AH_MASTER_CN_NAME_LENGTH = 2;
-
+
private static final String AH_MASTER_SUFFIX = "eu";
private static final String AH_MASTER_NAME = "arrowhead";
-
+
private static final String KEY_FACTORY_ALGORHITM_NAME = "RSA";
private static final KeyFactory keyFactory;
private static final Pattern PEM_PATTERN = Pattern.compile("(?m)(?s)^---*BEGIN.*---*$(.*)^---*END.*---*$.*");
-
+
+ private static final String MAC_ADDRESS_PATTERN_STRING = "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$";
+ public static final Pattern MAC_ADDRESS_PATTERN = Pattern.compile(MAC_ADDRESS_PATTERN_STRING);
+
private static final Logger logger = LogManager.getLogger(Utilities.class);
private static final ObjectMapper mapper = new ObjectMapper();
private static final String dateTimePattern = "yyyy-MM-dd HH:mm:ss";
static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern);
-
+
static {
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
try {
@@ -94,7 +98,7 @@ public class Utilities {
throw new ServiceConfigurationError("KeyFactory.getInstance(String) throws NoSuchAlgorithmException, code needs to be changed!", ex);
}
}
-
+
//=================================================================================================
// methods
@@ -102,34 +106,39 @@ public class Utilities {
public static boolean isEmpty(final String str) {
return str == null || str.isBlank();
}
-
+
+ //-------------------------------------------------------------------------------------------------
+ public static boolean notEmpty(final String str) {
+ return StringUtils.hasText(str);
+ }
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static String stripEndSlash(final String uri) {
if (uri != null && uri.endsWith("/")) {
return uri.substring(0, uri.length() - 1);
}
-
+
return uri;
}
-
+
//-------------------------------------------------------------------------------------------------
public static String convertZonedDateTimeToUTCString(final ZonedDateTime time) {
if (time == null) {
return null;
}
-
+
final LocalDateTime localDateTime = LocalDateTime.ofInstant(time.toInstant(), ZoneOffset.UTC);
return dateTimeFormatter.format(localDateTime);
}
-
+
//-------------------------------------------------------------------------------------------------
@SuppressWarnings("squid:RedundantThrowsDeclarationCheck")
public static ZonedDateTime parseUTCStringToLocalZonedDateTime(final String timeStr) throws DateTimeParseException {
if (isEmpty(timeStr)) {
return null;
}
-
+
final TemporalAccessor tempAcc = dateTimeFormatter.parse(timeStr);
final ZonedDateTime parsedDateTime = ZonedDateTime.of(tempAcc.get(ChronoField.YEAR),
tempAcc.get(ChronoField.MONTH_OF_YEAR),
@@ -139,11 +148,11 @@ public static ZonedDateTime parseUTCStringToLocalZonedDateTime(final String time
tempAcc.get(ChronoField.SECOND_OF_MINUTE),
0,
ZoneOffset.UTC);
-
+
final ZoneOffset offset = OffsetDateTime.now().getOffset();
return ZonedDateTime.ofInstant(parsedDateTime.toInstant(), offset);
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static String toPrettyJson(final String jsonString) {
@@ -161,45 +170,45 @@ public static String toPrettyJson(final String jsonString) {
} catch (final IOException ex) {
// it seems it is not a JSON string, so we just return untouched
}
-
+
return jsonString;
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static String toJson(final Object object) {
if (object == null) {
return null;
}
-
+
try {
return mapper.writeValueAsString(object);
} catch (final JsonProcessingException ex) {
throw new ArrowheadException("The specified object cannot be converted to text.", ex);
}
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static T fromJson(final String json, final Class parsedClass) {
if (json == null || parsedClass == null) {
return null;
}
-
+
try {
return mapper.readValue(json, parsedClass);
} catch (final IOException ex) {
throw new ArrowheadException("The specified string cannot be converted to a(n) " + parsedClass.getSimpleName() + " object.", ex);
}
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static Map text2Map(final String text) {
if (text == null) {
return null;
}
-
+
final Map result = new HashMap<>();
if (!isEmpty(text.trim())) {
final String[] parts = text.split(",");
@@ -208,30 +217,30 @@ public static Map text2Map(final String text) {
result.put(URLDecoder.decode(pair[0].trim(), StandardCharsets.UTF_8), pair.length == 1 ? "" : URLDecoder.decode(pair[1].trim(), StandardCharsets.UTF_8));
}
}
-
+
return result;
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static String map2Text(final Map map) {
if (map == null) {
return null;
}
-
+
final StringBuilder sb = new StringBuilder();
for (final Entry entry : map.entrySet()) {
final String key = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8);
final String value = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8);
sb.append(key).append("=").append(value).append(", ");
}
-
+
return map.isEmpty() ? "" : sb.substring(0, sb.length() - 2);
}
-
+
//-------------------------------------------------------------------------------------------------
+
/**
- *
* @param scheme default: http
* @param host default: 127.0.0.1
* @param port default: 80
@@ -244,54 +253,54 @@ public static UriComponents createURI(final String scheme, final String host, fi
builder.scheme(scheme == null ? CommonConstants.HTTP : scheme)
.host(host == null ? CommonConstants.LOCALHOST : host)
.port(port <= 0 ? CommonConstants.HTTP_PORT : port);
-
+
if (queryParams != null) {
builder.queryParams(queryParams);
}
-
+
if (pathSegments != null && pathSegments.length > 0) {
builder.pathSegment(pathSegments);
}
-
+
if (!Utilities.isEmpty(path)) {
builder.path(path);
}
-
+
return builder.build();
}
-
+
//-------------------------------------------------------------------------------------------------
public static UriComponents createURI(final String scheme, final String host, final int port, final String path) {
return createURI(scheme, host, port, null, path, (String[]) null);
}
-
+
//-------------------------------------------------------------------------------------------------
public static UriComponents createURI(final String scheme, final String host, final int port, final String path, final String... queryParams) {
if (queryParams.length % 2 != 0) {
throw new InvalidParameterException("queryParams variable arguments conatins a key without value");
}
-
- final LinkedMultiValueMap query = new LinkedMultiValueMap<>();
-
+
+ final LinkedMultiValueMap query = new LinkedMultiValueMap<>();
+
int count = 1;
String key = "";
for (final String vararg : queryParams) {
if (count % 2 != 0) {
- query.putIfAbsent(vararg, new ArrayList<>());
+ query.putIfAbsent(vararg, new ArrayList<>());
key = vararg;
} else {
- query.get(key).add(vararg);
+ query.get(key).add(vararg);
}
count++;
}
-
+
return createURI(scheme, host, port, query, path);
}
-
+
//-------------------------------------------------------------------------------------------------
public static HttpStatus calculateHttpStatusFromArrowheadException(final ArrowheadException ex) {
Assert.notNull(ex, "Exception is null.");
-
+
HttpStatus status = HttpStatus.resolve(ex.getErrorCode());
if (status == null) {
switch (ex.getExceptionType()) {
@@ -313,30 +322,30 @@ public static HttpStatus calculateHttpStatusFromArrowheadException(final Arrowhe
status = HttpStatus.INTERNAL_SERVER_ERROR;
}
}
-
+
return status;
}
-
+
//-------------------------------------------------------------------------------------------------
public static RelayType convertStringToRelayType(final String str) {
if (isEmpty(str)) {
return RelayType.GENERAL_RELAY;
}
-
+
try {
- return RelayType.valueOf(str.toUpperCase().trim());
+ return RelayType.valueOf(str.toUpperCase().trim());
} catch (final IllegalArgumentException ex) {
return null;
}
}
-
+
//-------------------------------------------------------------------------------------------------
@Nullable
public static String getCertCNFromSubject(final String subjectName) {
if (subjectName == null) {
return null;
}
-
+
try {
// Subject is in LDAP format, we can use the LdapName object for parsing
final LdapName ldapname = new LdapName(subjectName);
@@ -353,92 +362,206 @@ public static String getCertCNFromSubject(final String subjectName) {
return null;
}
-
+
//-------------------------------------------------------------------------------------------------
public static String getCloudCommonName(final String cloudOperator, final String cloudName) {
Assert.isTrue(!isEmpty(cloudOperator), "Cloud operator is null or blank.");
Assert.isTrue(!isEmpty(cloudName), "Cloud name is null or blank.");
-
- return (cloudName.trim() + "." + cloudOperator.trim() + ".arrowhead.eu").toLowerCase();
+
+ return (cloudName.trim() + "." + cloudOperator.trim() + ".arrowhead.eu").toLowerCase();
}
-
+
//-------------------------------------------------------------------------------------------------
public static X509Certificate getFirstCertFromKeyStore(final KeyStore keystore) {
Assert.notNull(keystore, "Key store is not defined.");
-
+
try {
+ // the first certificate is not always the end certificate. java does not guarantee the order
final Enumeration enumeration = keystore.aliases();
- final String alias = enumeration.nextElement();
- return (X509Certificate) keystore.getCertificate(alias);
+ while (enumeration.hasMoreElements()) {
+ final Certificate[] chain = keystore.getCertificateChain(enumeration.nextElement());
+
+ if(Objects.nonNull(chain) && chain.length >= 3) {
+ return (X509Certificate) chain[0];
+ }
+ }
+ throw new ServiceConfigurationError("Getting the first cert from keystore failed...");
} catch (final KeyStoreException | NoSuchElementException ex) {
logger.error("Getting the first cert from key store failed...", ex);
throw new ServiceConfigurationError("Getting the first cert from keystore failed...", ex);
}
}
-
- //-------------------------------------------------------------------------------------------------
- public static PrivateKey getPrivateKey(final KeyStore keystore, final String keyPass) {
+
+//-------------------------------------------------------------------------------------------------
+ public static X509Certificate getCloudCertFromKeyStore(final KeyStore keystore) {
Assert.notNull(keystore, "Key store is not defined.");
- Assert.notNull(keyPass, "Password is not defined.");
-
- PrivateKey privateKey = null;
- String element;
- try {
- final Enumeration enumeration = keystore.aliases();
- while (enumeration.hasMoreElements()) {
- element = enumeration.nextElement();
- privateKey = (PrivateKey) keystore.getKey(element, keyPass.toCharArray());
- if (privateKey != null) {
- break;
- }
- }
- } catch (final KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException ex) {
- logger.error("Getting the private key from key store failed...", ex);
- throw new ServiceConfigurationError("Getting the private key from key store failed...", ex);
- }
- if (privateKey == null) {
- throw new ServiceConfigurationError("Getting the private key failed, key store aliases do not identify a key.");
- }
-
- return privateKey;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static PublicKey getPublicKeyFromBase64EncodedString(final String encodedKey) {
- Assert.isTrue(!isEmpty(encodedKey), "Encoded key is null or blank");
-
- final byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
- return generatePublicKeyFromByteArray(keyBytes);
+ try {
+ // debian installation with new certificates have a different alias
+ // i.e. the format is {cloudname}." + AH_MASTER_NAME + "." + AH_MASTER_SUFFIX
+ final Enumeration enumeration = keystore.aliases();
+ while (enumeration.hasMoreElements()) {
+ final String alias = enumeration.nextElement();
+ final X509Certificate certificate = (X509Certificate) keystore.getCertificate(alias);
+
+ if(isCloudCertificate(certificate))
+ {
+ return certificate;
+ }
+ }
+
+ final String errorMsg = "Getting the cloud cert from keystore failed. " +
+ "Cannot find alias in the following format: {cloudname}.{cloudoperator}." + AH_MASTER_NAME + "." + AH_MASTER_SUFFIX;
+ logger.error(errorMsg);
+ throw new ServiceConfigurationError(errorMsg);
+ } catch (final KeyStoreException | NoSuchElementException ex) {
+ logger.error("Getting the cloud cert from keystore failed...", ex);
+ throw new ServiceConfigurationError("Getting the cloud cert from keystore failed...", ex);
+ }
}
//-------------------------------------------------------------------------------------------------
- public static PublicKey getPublicKeyFromPEMFile(final InputStream is) {
- Assert.notNull(is, "Input stream is null");
+ public static X509Certificate getRootCertFromKeyStore(final KeyStore keystore) {
+ Assert.notNull(keystore, "Key store is not defined.");
+
try {
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final byte[] buf = new byte[1024];
- for (int read = 0; read != -1; read = is.read(buf)) {
- baos.write(buf, 0, read);
+ // debian installation with new certificates have a different alias
+ Enumeration enumeration = keystore.aliases();
+ while (enumeration.hasMoreElements()) {
+ final String alias = enumeration.nextElement();
+ final X509Certificate certificate = (X509Certificate) keystore.getCertificate(alias);
+ final String commonName = getCertCNFromSubject(certificate.getSubjectDN().getName());
+ Assert.notNull(commonName, "Certificate without commonName is not allowed");
+ final String[] cnParts = commonName.split("\\.");
+ if (cnParts.length == 2 && cnParts[0].equals(AH_MASTER_NAME) && cnParts[1].equals(AH_MASTER_SUFFIX)) {
+ return (X509Certificate) keystore.getCertificate(alias);
+ }
}
-
- final String pem = new String(baos.toByteArray(), StandardCharsets.ISO_8859_1);
- baos.close();
- final String encoded = PEM_PATTERN.matcher(pem).replaceFirst("$1");
- final byte[] keyBytes = Base64.getMimeDecoder().decode(encoded);
-
- return generatePublicKeyFromByteArray(keyBytes);
- } catch (final IOException ex) {
- throw new ArrowheadException("IOException occurred during PEM file loading from input stream.", ex);
- }
- }
-
- //-------------------------------------------------------------------------------------------------
- public static boolean isKeyStoreCNArrowheadValid(final String commonName) {
- if (isEmpty(commonName)) {
- return false;
+
+ final String errorMsg = "Getting the root cert from keystore failed. " +
+ "Cannot find alias in the following format: " + AH_MASTER_NAME + "." + AH_MASTER_SUFFIX;
+ logger.error(errorMsg);
+ throw new ServiceConfigurationError(errorMsg);
+ } catch (final KeyStoreException | NoSuchElementException ex) {
+ logger.error("Getting the root cert from keystore failed...", ex);
+ throw new ServiceConfigurationError("Getting the root cert from keystore failed...", ex);
}
-
+ }
+ //-------------------------------------------------------------------------------------------------
+ public static PrivateKey getCloudPrivateKey(final KeyStore keystore, final String keyPass) {
+ Assert.notNull(keystore, "Key store is not defined.");
+ Assert.notNull(keyPass, "Password is not defined.");
+
+ PrivateKey privateKey = null;
+ String element;
+ try {
+ final Enumeration enumeration = keystore.aliases();
+ while (enumeration.hasMoreElements()) {
+ element = enumeration.nextElement();
+
+ final X509Certificate certificate = (X509Certificate) keystore.getCertificate(element);
+ if(isCloudCertificate(certificate))
+ {
+ privateKey = (PrivateKey) keystore.getKey(element, keyPass.toCharArray());
+ if (privateKey != null) {
+ break;
+ }
+ }
+ }
+ } catch (final KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException ex) {
+ logger.error("Getting the private key from key store failed...", ex);
+ throw new ServiceConfigurationError("Getting the private key from key store failed...", ex);
+ }
+
+ if (privateKey == null) {
+ throw new ServiceConfigurationError("Getting the private key failed, key store aliases do not identify a key.");
+ }
+
+ return privateKey;
+ }
+ //-------------------------------------------------------------------------------------------------
+ public static PrivateKey getPrivateKey(final KeyStore keystore, final String keyPass) {
+ Assert.notNull(keystore, "Key store is not defined.");
+ Assert.notNull(keyPass, "Password is not defined.");
+
+ PrivateKey privateKey = null;
+ String element;
+ try {
+ final Enumeration enumeration = keystore.aliases();
+ while (enumeration.hasMoreElements()) {
+ element = enumeration.nextElement();
+
+ privateKey = (PrivateKey) keystore.getKey(element, keyPass.toCharArray());
+ if (privateKey != null) {
+ break;
+ }
+ }
+ } catch (final KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException ex) {
+ logger.error("Getting the private key from key store failed...", ex);
+ throw new ServiceConfigurationError("Getting the private key from key store failed...", ex);
+ }
+
+ if (privateKey == null) {
+ throw new ServiceConfigurationError("Getting the private key failed, key store aliases do not identify a key.");
+ }
+
+ return privateKey;
+ }
+ //-------------------------------------------------------------------------------------------------
+ public static PrivateKey getCloudPrivateKey(final KeyStore keystore, final String alias, final String keyPass) {
+ Assert.notNull(keystore, "Key store is not defined.");
+ Assert.notNull(keyPass, "Password is not defined.");
+
+ try {
+ // TODO issue: the cloud common name is not the alias in debian installation with own certificates
+ PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, keyPass.toCharArray());
+ if (privateKey != null) {
+ return privateKey;
+ } else {
+ return getCloudPrivateKey(keystore, keyPass);
+ // throw new ServiceConfigurationError("Getting the private key failed, key store aliases do not identify a key.");
+ }
+ } catch (final KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException ex) {
+ logger.error("Getting the private key from key store failed...", ex);
+ throw new ServiceConfigurationError("Getting the private key from key store failed...", ex);
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static PublicKey getPublicKeyFromBase64EncodedString(final String encodedKey) {
+ Assert.isTrue(!isEmpty(encodedKey), "Encoded key is null or blank");
+
+ final byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
+ return generatePublicKeyFromByteArray(keyBytes);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static PublicKey getPublicKeyFromPEMFile(final InputStream is) {
+ Assert.notNull(is, "Input stream is null");
+ try {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final byte[] buf = new byte[1024];
+ for (int read = 0; read != -1; read = is.read(buf)) {
+ baos.write(buf, 0, read);
+ }
+
+ final String pem = new String(baos.toByteArray(), StandardCharsets.ISO_8859_1);
+ baos.close();
+ final String encoded = PEM_PATTERN.matcher(pem).replaceFirst("$1");
+ final byte[] keyBytes = Base64.getMimeDecoder().decode(encoded);
+
+ return generatePublicKeyFromByteArray(keyBytes);
+ } catch (final IOException ex) {
+ throw new ArrowheadException("IOException occurred during PEM file loading from input stream.", ex);
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static boolean isKeyStoreCNArrowheadValid(final String commonName) {
+ if (isEmpty(commonName)) {
+ return false;
+ }
+
final String[] cnFields = commonName.split("\\.", 0);
return cnFields.length == SERVICE_CN_NAME_LENGTH && cnFields[cnFields.length - 1].equals(AH_MASTER_SUFFIX) && cnFields[cnFields.length - 2].equals(AH_MASTER_NAME);
}
@@ -483,8 +606,42 @@ public static void createExceptionFromErrorMessageDTO(final ErrorMessageDTO dto)
logger.error("Unknown exception type: {}", dto.getExceptionType());
throw new ArrowheadException(dto.getErrorMessage(), dto.getErrorCode(), dto.getOrigin());
}
- }
-
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static String lowerCaseTrim(final String text) {
+ if (isEmpty(text)) {
+ return text;
+ }
+
+ return text.toLowerCase().trim();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static String firstNotNullIfExists(final String first, final String second) {
+ return Utilities.notEmpty(first) ? first : second;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @SuppressWarnings("unchecked")
+ public static T firstNotNullIfExists(final T first, final T second) {
+ if (first instanceof String && second instanceof String) {
+ return (T) firstNotNullIfExists((String) first, (String) second);
+ }
+ return Objects.nonNull(first) ? first : second;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public static String firstNotNullIfExists(final String... args) {
+ for (final String candidate : args) {
+ if (Utilities.notEmpty(candidate)) {
+ return candidate;
+ }
+ }
+
+ return null;
+ }
+
//=================================================================================================
// assistant methods
@@ -502,4 +659,18 @@ private static PublicKey generatePublicKeyFromByteArray(final byte[] keyBytes) {
throw new AuthException("Public key decoding failed due wrong input key", ex);
}
}
-}
\ No newline at end of file
+
+ private static boolean isCloudCertificate(final X509Certificate certificate)
+ {
+ final String commonName = getCertCNFromSubject(certificate.getSubjectDN().getName());
+ Assert.notNull(commonName, "Certificate without commonName is not allowed");
+ final String[] cnParts = commonName.split("\\.");
+ return (cnParts.length == 4 && cnParts[2].equals(AH_MASTER_NAME) && cnParts[3].equals(AH_MASTER_SUFFIX));
+ }
+
+ public static boolean isValidMacAddress(final String macAddress) {
+ Assert.notNull(macAddress, "MAC address must not be null");
+ final Matcher matcher = MAC_ADDRESS_PATTERN.matcher(macAddress);
+ return matcher.matches();
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/core/CoreSystem.java b/core-common/src/main/java/eu/arrowhead/common/core/CoreSystem.java
index 4e39afa2a..70401cc84 100644
--- a/core-common/src/main/java/eu/arrowhead/common/core/CoreSystem.java
+++ b/core-common/src/main/java/eu/arrowhead/common/core/CoreSystem.java
@@ -1,40 +1,63 @@
package eu.arrowhead.common.core;
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.Defaults;
+import org.springframework.util.Assert;
+
import java.util.Collections;
import java.util.List;
-import org.springframework.util.Assert;
-
-import eu.arrowhead.common.CommonConstants;
-import eu.arrowhead.common.Defaults;
+import static eu.arrowhead.common.core.CoreSystemService.DEVICE_REGISTRY_ONBOARDING_WITH_NAME_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.DEVICE_REGISTRY_REGISTER_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.DEVICE_REGISTRY_ONBOARDING_WITH_CSR_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.DEVICE_REGISTRY_UNREGISTER_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.ONBOARDING_WITH_CERTIFICATE_AND_CSR_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.ONBOARDING_WITH_CERTIFICATE_AND_NAME_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.ONBOARDING_WITH_SHARED_SECRET_AND_CSR_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.ONBOARDING_WITH_SHARED_SECRET_AND_NAME_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SERVICE_REGISTRY_REGISTER_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SERVICE_REGISTRY_UNREGISTER_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SYSTEM_REGISTRY_REGISTER_SERVICE;
+import static eu.arrowhead.common.core.CoreSystemService.SYSTEM_REGISTRY_UNREGISTER_SERVICE;
public enum CoreSystem {
-
- //=================================================================================================
- // elements
-
- SERVICE_REGISTRY(Defaults.DEFAULT_SERVICE_REGISTRY_PORT, null),
- AUTHORIZATION(Defaults.DEFAULT_AUTHORIZATION_PORT, List.of(CoreSystemService.AUTH_CONTROL_INTRA_SERVICE, CoreSystemService.AUTH_CONTROL_INTER_SERVICE,
- CoreSystemService.AUTH_TOKEN_GENERATION_SERVICE, CoreSystemService.AUTH_PUBLIC_KEY_SERVICE,
- CoreSystemService.AUTH_CONTROL_SUBSCRIPTION_SERVICE)),
- ORCHESTRATOR(Defaults.DEFAULT_ORCHESTRATOR_PORT, List.of(CoreSystemService.ORCHESTRATION_SERVICE)),
- GATEKEEPER(Defaults.DEFAULT_GATEKEEPER_PORT, List.of(CoreSystemService.GATEKEEPER_GLOBAL_SERVICE_DISCOVERY, CoreSystemService.GATEKEEPER_INTER_CLOUD_NEGOTIATION)),
- EVENT_HANDLER(Defaults.DEFAULT_EVENT_HANDLER_PORT, List.of(CoreSystemService.EVENT_PUBLISH_SERVICE, CoreSystemService.EVENT_SUBSCRIBE_SERVICE
- , CoreSystemService.EVENT_UNSUBSCRIBE_SERVICE, CoreSystemService.EVENT_PUBLISH_AUTH_UPDATE_SERVICE)),
- GATEWAY(Defaults.DEFAULT_GATEWAY_PORT, List.of(CoreSystemService.GATEWAY_PUBLIC_KEY_SERVICE, CoreSystemService.GATEWAY_PROVIDER_SERVICE,CoreSystemService.GATEWAY_CONSUMER_SERVICE)),
- CHOREOGRAPHER(Defaults.DEFAULT_CHOREOGRAPHER_PORT, List.of()), // TODO: add services
- CERTIFICATE_AUTHORITY(Defaults.DEFAULT_CERTIFICATE_AUTHORITY_PORT, List.of()); // TODO: add services
-
- //=================================================================================================
- // members
-
- private final int defaultPort;
- private final List services;
-
- //=================================================================================================
- // methods
-
- //-------------------------------------------------------------------------------------------------
+
+ //=================================================================================================
+ // elements
+
+ SERVICE_REGISTRY(Defaults.DEFAULT_SERVICE_REGISTRY_PORT, List.of(SERVICE_REGISTRY_REGISTER_SERVICE, SERVICE_REGISTRY_UNREGISTER_SERVICE)),
+ SYSTEM_REGISTRY(Defaults.DEFAULT_SYSTEM_REGISTRY_PORT, List.of(SYSTEM_REGISTRY_REGISTER_SERVICE, SYSTEM_REGISTRY_UNREGISTER_SERVICE,
+ SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_SERVICE, SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_SERVICE)),
+ DEVICE_REGISTRY(Defaults.DEFAULT_DEVICE_REGISTRY_PORT, List.of(DEVICE_REGISTRY_REGISTER_SERVICE, DEVICE_REGISTRY_UNREGISTER_SERVICE,
+ DEVICE_REGISTRY_ONBOARDING_WITH_NAME_SERVICE, DEVICE_REGISTRY_ONBOARDING_WITH_CSR_SERVICE)),
+ ONBOARDING_CONTROLLER(Defaults.DEFAULT_ONBOARDING_PORT, List.of(ONBOARDING_WITH_CERTIFICATE_AND_NAME_SERVICE,
+ ONBOARDING_WITH_SHARED_SECRET_AND_NAME_SERVICE,
+ ONBOARDING_WITH_CERTIFICATE_AND_CSR_SERVICE,
+ ONBOARDING_WITH_SHARED_SECRET_AND_CSR_SERVICE)),
+ AUTHORIZATION(Defaults.DEFAULT_AUTHORIZATION_PORT, List.of(CoreSystemService.AUTH_CONTROL_INTRA_SERVICE, CoreSystemService.AUTH_CONTROL_INTER_SERVICE,
+ CoreSystemService.AUTH_TOKEN_GENERATION_SERVICE, CoreSystemService.AUTH_PUBLIC_KEY_SERVICE,
+ CoreSystemService.AUTH_CONTROL_SUBSCRIPTION_SERVICE)),
+ ORCHESTRATOR(Defaults.DEFAULT_ORCHESTRATOR_PORT, List.of(CoreSystemService.ORCHESTRATION_SERVICE)),
+ GATEKEEPER(Defaults.DEFAULT_GATEKEEPER_PORT, List.of(CoreSystemService.GATEKEEPER_GLOBAL_SERVICE_DISCOVERY, CoreSystemService.GATEKEEPER_INTER_CLOUD_NEGOTIATION)),
+ EVENT_HANDLER(Defaults.DEFAULT_EVENT_HANDLER_PORT, List.of(CoreSystemService.EVENT_PUBLISH_SERVICE, CoreSystemService.EVENT_SUBSCRIBE_SERVICE
+ , CoreSystemService.EVENT_UNSUBSCRIBE_SERVICE, CoreSystemService.EVENT_PUBLISH_AUTH_UPDATE_SERVICE)),
+ GATEWAY(Defaults.DEFAULT_GATEWAY_PORT, List.of(CoreSystemService.GATEWAY_PUBLIC_KEY_SERVICE, CoreSystemService.GATEWAY_PROVIDER_SERVICE, CoreSystemService.GATEWAY_CONSUMER_SERVICE)),
+ CHOREOGRAPHER(Defaults.DEFAULT_CHOREOGRAPHER_PORT, List.of()), // TODO: add services
+ QOS_MONITOR(Defaults.DEFAULT_QOS_MONITOR_PORT, List.of(CoreSystemService.QOS_MONITOR_PING_MEASUREMENT_SERVICE)),
+ CERTIFICATE_AUTHORITY(Defaults.DEFAULT_CERTIFICATE_AUTHORITY_PORT, List.of(CoreSystemService.CERTIFICATE_AUTHORITY_SIGN_SERVICE));
+
+ //=================================================================================================
+ // members
+
+ private final int defaultPort;
+ private final List services;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
public int getDefaultPort() { return defaultPort; }
public List getServices() { return services; }
@@ -47,4 +70,4 @@ private CoreSystem(final int defaultPort, final List services
this.services = services != null ? Collections.unmodifiableList(services) : List.of();
this.defaultPort = defaultPort;
}
-}
\ No newline at end of file
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/core/CoreSystemService.java b/core-common/src/main/java/eu/arrowhead/common/core/CoreSystemService.java
index 39f6db738..182bec23a 100644
--- a/core-common/src/main/java/eu/arrowhead/common/core/CoreSystemService.java
+++ b/core-common/src/main/java/eu/arrowhead/common/core/CoreSystemService.java
@@ -1,62 +1,174 @@
package eu.arrowhead.common.core;
+import eu.arrowhead.common.Utilities;
import org.springframework.util.Assert;
-import eu.arrowhead.common.CommonConstants;
-import eu.arrowhead.common.Utilities;
+import static eu.arrowhead.common.CommonConstants.AUTHORIZATION_URI;
+import static eu.arrowhead.common.CommonConstants.CERTIFICATE_AUTHRORITY_URI;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_AUTH_CONTROL_INTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_AUTH_CONTROL_INTRA;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_AUTH_CONTROL_SUBSCRIPTION;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_AUTH_PUBLIC_KEY;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_AUTH_TOKEN_GENERATION;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_CERTIFICATE_AUTHORITY_SIGN;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_CSR;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_NAME;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_DEVICE_REGISTRY_REGISTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_DEVICE_REGISTRY_UNREGISTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_EVENT_HANDLER_PUBLISH;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_EVENT_HANDLER_PUBLISH_AUTH_UPDATE;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_EVENT_HANDLER_SUBSCRIBE;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_EVENT_HANDLER_UNSUBSCRIBE;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_GATEKEEPER_GSD;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_GATEKEEPER_ICN;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_GATEWAY_CONNECT_CONSUMER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_GATEWAY_CONNECT_PROVIDER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_GATEWAY_PUBLIC_KEY;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_CSR;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_NAME;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_CSR;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_NAME;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_ORCH_PROCESS;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_QOS_MONITOR_PING_MEASUREMENT;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SERVICE_REGISTRY_REGISTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SERVICE_REGISTRY_UNREGISTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SYSTEM_REGISTRY_REGISTER;
+import static eu.arrowhead.common.CommonConstants.CORE_SERVICE_SYSTEM_REGISTRY_UNREGISTER;
+import static eu.arrowhead.common.CommonConstants.DEVICE_REGISTRY_URI;
+import static eu.arrowhead.common.CommonConstants.EVENT_HANDLER_URI;
+import static eu.arrowhead.common.CommonConstants.GATEKEEPER_URI;
+import static eu.arrowhead.common.CommonConstants.GATEWAY_URI;
+import static eu.arrowhead.common.CommonConstants.ONBOARDING_URI;
+import static eu.arrowhead.common.CommonConstants.OP_AUTH_INTER_CHECK_URI;
+import static eu.arrowhead.common.CommonConstants.OP_AUTH_INTRA_CHECK_URI;
+import static eu.arrowhead.common.CommonConstants.OP_AUTH_KEY_URI;
+import static eu.arrowhead.common.CommonConstants.OP_AUTH_SUBSCRIPTION_CHECK_URI;
+import static eu.arrowhead.common.CommonConstants.OP_AUTH_TOKEN_URI;
+import static eu.arrowhead.common.CommonConstants.OP_CA_SIGN_CERTIFICATE_URI;
+import static eu.arrowhead.common.CommonConstants.OP_DEVICE_REGISTRY_ONBOARDING_WITH_CSR_URI;
+import static eu.arrowhead.common.CommonConstants.OP_DEVICE_REGISTRY_ONBOARDING_WITH_NAME_URI;
+import static eu.arrowhead.common.CommonConstants.OP_DEVICE_REGISTRY_REGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_DEVICE_REGISTRY_UNREGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_EVENT_HANDLER_PUBLISH;
+import static eu.arrowhead.common.CommonConstants.OP_EVENT_HANDLER_PUBLISH_AUTH_UPDATE;
+import static eu.arrowhead.common.CommonConstants.OP_EVENT_HANDLER_SUBSCRIBE;
+import static eu.arrowhead.common.CommonConstants.OP_EVENT_HANDLER_UNSUBSCRIBE;
+import static eu.arrowhead.common.CommonConstants.OP_GATEKEEPER_GSD_SERVICE;
+import static eu.arrowhead.common.CommonConstants.OP_GATEKEEPER_ICN_SERVICE;
+import static eu.arrowhead.common.CommonConstants.OP_GATEWAY_CONNECT_CONSUMER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_GATEWAY_CONNECT_PROVIDER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_GATEWAY_KEY_URI;
+import static eu.arrowhead.common.CommonConstants.OP_ONBOARDING_WITH_CERTIFICATE_AND_CSR;
+import static eu.arrowhead.common.CommonConstants.OP_ONBOARDING_WITH_CERTIFICATE_AND_NAME;
+import static eu.arrowhead.common.CommonConstants.OP_ONBOARDING_WITH_SHARED_SECRET_AND_CSR;
+import static eu.arrowhead.common.CommonConstants.OP_ONBOARDING_WITH_SHARED_SECRET_AND_NAME;
+import static eu.arrowhead.common.CommonConstants.OP_ORCH_PROCESS;
+import static eu.arrowhead.common.CommonConstants.OP_QOS_MONITOR_PING_MEASUREMENT;
+import static eu.arrowhead.common.CommonConstants.OP_QOS_MONITOR_PING_MEASUREMENT_SUFFIX;
+import static eu.arrowhead.common.CommonConstants.OP_SERVICE_REGISTRY_REGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_SERVICE_REGISTRY_UNREGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_URI;
+import static eu.arrowhead.common.CommonConstants.OP_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_URI;
+import static eu.arrowhead.common.CommonConstants.OP_SYSTEM_REGISTRY_REGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.OP_SYSTEM_REGISTRY_UNREGISTER_URI;
+import static eu.arrowhead.common.CommonConstants.ORCHESTRATOR_URI;
+import static eu.arrowhead.common.CommonConstants.QOS_MONITOR_URI;
+import static eu.arrowhead.common.CommonConstants.SERVICE_REGISTRY_URI;
+import static eu.arrowhead.common.CommonConstants.SYSTEM_REGISTRY_URI;
public enum CoreSystemService {
- //=================================================================================================
- // elements
-
- // Authorization services
- AUTH_CONTROL_INTRA_SERVICE(CommonConstants.CORE_SERVICE_AUTH_CONTROL_INTRA, CommonConstants.AUTHORIZATION_URI + CommonConstants.OP_AUTH_INTRA_CHECK_URI),
- AUTH_CONTROL_INTER_SERVICE(CommonConstants.CORE_SERVICE_AUTH_CONTROL_INTER, CommonConstants.AUTHORIZATION_URI + CommonConstants.OP_AUTH_INTER_CHECK_URI),
- AUTH_TOKEN_GENERATION_SERVICE(CommonConstants.CORE_SERVICE_AUTH_TOKEN_GENERATION, CommonConstants.AUTHORIZATION_URI + CommonConstants.OP_AUTH_TOKEN_URI),
- AUTH_PUBLIC_KEY_SERVICE(CommonConstants.CORE_SERVICE_AUTH_PUBLIC_KEY, CommonConstants.AUTHORIZATION_URI + CommonConstants.OP_AUTH_KEY_URI),
- AUTH_CONTROL_SUBSCRIPTION_SERVICE(CommonConstants.CORE_SERVICE_AUTH_CONTROL_SUBSCRIPTION, CommonConstants.AUTHORIZATION_URI + CommonConstants.OP_AUTH_SUBSCRIPTION_CHECK_URI),
-
- // Orchestrator services
- ORCHESTRATION_SERVICE(CommonConstants.CORE_SERVICE_ORCH_PROCESS, CommonConstants.ORCHESTRATOR_URI + CommonConstants.OP_ORCH_PROCESS),
-
- // Gatekeeper services
- GATEKEEPER_GLOBAL_SERVICE_DISCOVERY(CommonConstants.CORE_SERVICE_GATEKEEPER_GSD, CommonConstants.GATEKEEPER_URI + CommonConstants.OP_GATEKEEPER_GSD_SERVICE),
- GATEKEEPER_INTER_CLOUD_NEGOTIATION(CommonConstants.CORE_SERVICE_GATEKEEPER_ICN, CommonConstants.GATEKEEPER_URI + CommonConstants.OP_GATEKEEPER_ICN_SERVICE),
-
- // Gateway services
- GATEWAY_PUBLIC_KEY_SERVICE(CommonConstants.CORE_SERVICE_GATEWAY_PUBLIC_KEY, CommonConstants.GATEWAY_URI + CommonConstants.OP_GATEWAY_KEY_URI),
- GATEWAY_PROVIDER_SERVICE(CommonConstants.CORE_SERVICE_GATEWAY_CONNECT_PROVIDER, CommonConstants.GATEWAY_URI + CommonConstants.OP_GATEWAY_CONNECT_PROVIDER_URI),
- GATEWAY_CONSUMER_SERVICE(CommonConstants.CORE_SERVICE_GATEWAY_CONNECT_CONSUMER, CommonConstants.GATEWAY_URI + CommonConstants.OP_GATEWAY_CONNECT_CONSUMER_URI),
-
- //Eventhandler services
- EVENT_PUBLISH_SERVICE(CommonConstants.CORE_SERVICE_EVENT_HANDLER_PUBLISH, CommonConstants.EVENT_HANDLER_URI + CommonConstants.OP_EVENT_HANDLER_PUBLISH),
- EVENT_SUBSCRIBE_SERVICE(CommonConstants.CORE_SERVICE_EVENT_HANDLER_SUBSCRIBE, CommonConstants.EVENT_HANDLER_URI + CommonConstants.OP_EVENT_HANDLER_SUBSCRIBE),
- EVENT_UNSUBSCRIBE_SERVICE(CommonConstants.CORE_SERVICE_EVENT_HANDLER_UNSUBSCRIBE, CommonConstants.EVENT_HANDLER_URI + CommonConstants.OP_EVENT_HANDLER_UNSUBSCRIBE),
- EVENT_PUBLISH_AUTH_UPDATE_SERVICE(CommonConstants.CORE_SERVICE_EVENT_HANDLER_PUBLISH_AUTH_UPDATE, CommonConstants.EVENT_HANDLER_URI + CommonConstants.OP_EVENT_HANDLER_PUBLISH_AUTH_UPDATE);
-
- //TODO: additional services
-
- //=================================================================================================
- // members
-
- private final String serviceDefinition;
- private final String serviceUri;
-
- //=================================================================================================
- // methods
-
- //-------------------------------------------------------------------------------------------------
- public String getServiceDefinition() { return serviceDefinition; }
- public String getServiceUri() { return serviceUri; }
-
-
- //=================================================================================================
- // assistant methods
+ //=================================================================================================
+ // elements
+
+ // Authorization services
+ AUTH_CONTROL_INTRA_SERVICE(CORE_SERVICE_AUTH_CONTROL_INTRA, AUTHORIZATION_URI + OP_AUTH_INTRA_CHECK_URI),
+ AUTH_CONTROL_INTER_SERVICE(CORE_SERVICE_AUTH_CONTROL_INTER, AUTHORIZATION_URI + OP_AUTH_INTER_CHECK_URI),
+ AUTH_TOKEN_GENERATION_SERVICE(CORE_SERVICE_AUTH_TOKEN_GENERATION, AUTHORIZATION_URI + OP_AUTH_TOKEN_URI),
+ AUTH_PUBLIC_KEY_SERVICE(CORE_SERVICE_AUTH_PUBLIC_KEY, AUTHORIZATION_URI + OP_AUTH_KEY_URI),
+ AUTH_CONTROL_SUBSCRIPTION_SERVICE(CORE_SERVICE_AUTH_CONTROL_SUBSCRIPTION, AUTHORIZATION_URI + OP_AUTH_SUBSCRIPTION_CHECK_URI),
+
+ // Orchestrator services
+ ORCHESTRATION_SERVICE(CORE_SERVICE_ORCH_PROCESS,
+ ORCHESTRATOR_URI + OP_ORCH_PROCESS),
+
+ // Gatekeeper services
+ GATEKEEPER_GLOBAL_SERVICE_DISCOVERY(CORE_SERVICE_GATEKEEPER_GSD, GATEKEEPER_URI + OP_GATEKEEPER_GSD_SERVICE),
+ GATEKEEPER_INTER_CLOUD_NEGOTIATION(CORE_SERVICE_GATEKEEPER_ICN, GATEKEEPER_URI + OP_GATEKEEPER_ICN_SERVICE),
+
+ // Gateway services
+ GATEWAY_PUBLIC_KEY_SERVICE(CORE_SERVICE_GATEWAY_PUBLIC_KEY, GATEWAY_URI + OP_GATEWAY_KEY_URI),
+ GATEWAY_PROVIDER_SERVICE(CORE_SERVICE_GATEWAY_CONNECT_PROVIDER, GATEWAY_URI + OP_GATEWAY_CONNECT_PROVIDER_URI),
+ GATEWAY_CONSUMER_SERVICE(CORE_SERVICE_GATEWAY_CONNECT_CONSUMER, GATEWAY_URI + OP_GATEWAY_CONNECT_CONSUMER_URI),
+
+ // Eventhandler services
+ EVENT_PUBLISH_SERVICE(CORE_SERVICE_EVENT_HANDLER_PUBLISH, EVENT_HANDLER_URI + OP_EVENT_HANDLER_PUBLISH),
+ EVENT_SUBSCRIBE_SERVICE(CORE_SERVICE_EVENT_HANDLER_SUBSCRIBE, EVENT_HANDLER_URI + OP_EVENT_HANDLER_SUBSCRIBE),
+ EVENT_UNSUBSCRIBE_SERVICE(CORE_SERVICE_EVENT_HANDLER_UNSUBSCRIBE, EVENT_HANDLER_URI + OP_EVENT_HANDLER_UNSUBSCRIBE),
+ EVENT_PUBLISH_AUTH_UPDATE_SERVICE(CORE_SERVICE_EVENT_HANDLER_PUBLISH_AUTH_UPDATE, EVENT_HANDLER_URI + OP_EVENT_HANDLER_PUBLISH_AUTH_UPDATE),
+
+ // CA services
+ CERTIFICATE_AUTHORITY_SIGN_SERVICE(CORE_SERVICE_CERTIFICATE_AUTHORITY_SIGN, CERTIFICATE_AUTHRORITY_URI + OP_CA_SIGN_CERTIFICATE_URI),
+ // QoS Monitor services
+ QOS_MONITOR_PING_MEASUREMENT_SERVICE(CORE_SERVICE_QOS_MONITOR_PING_MEASUREMENT,
+ QOS_MONITOR_URI + OP_QOS_MONITOR_PING_MEASUREMENT + OP_QOS_MONITOR_PING_MEASUREMENT_SUFFIX),
+
+ // Onboarding services
+ ONBOARDING_WITH_CERTIFICATE_AND_NAME_SERVICE(CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_NAME, ONBOARDING_URI + OP_ONBOARDING_WITH_CERTIFICATE_AND_NAME),
+ ONBOARDING_WITH_CERTIFICATE_AND_CSR_SERVICE(CORE_SERVICE_ONBOARDING_WITH_CERTIFICATE_AND_CSR, ONBOARDING_URI + OP_ONBOARDING_WITH_CERTIFICATE_AND_CSR),
+ ONBOARDING_WITH_SHARED_SECRET_AND_NAME_SERVICE(CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_NAME, ONBOARDING_URI + OP_ONBOARDING_WITH_SHARED_SECRET_AND_NAME),
+ ONBOARDING_WITH_SHARED_SECRET_AND_CSR_SERVICE(CORE_SERVICE_ONBOARDING_WITH_SHARED_SECRET_AND_CSR, ONBOARDING_URI + OP_ONBOARDING_WITH_SHARED_SECRET_AND_CSR),
+
+ // Device Registry services
+ DEVICE_REGISTRY_REGISTER_SERVICE(CORE_SERVICE_DEVICE_REGISTRY_REGISTER, DEVICE_REGISTRY_URI + OP_DEVICE_REGISTRY_REGISTER_URI),
+ DEVICE_REGISTRY_UNREGISTER_SERVICE(CORE_SERVICE_DEVICE_REGISTRY_UNREGISTER, DEVICE_REGISTRY_URI + OP_DEVICE_REGISTRY_UNREGISTER_URI),
+ DEVICE_REGISTRY_ONBOARDING_WITH_NAME_SERVICE(CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_NAME,
+ DEVICE_REGISTRY_URI + ONBOARDING_URI + OP_DEVICE_REGISTRY_ONBOARDING_WITH_NAME_URI),
+ DEVICE_REGISTRY_ONBOARDING_WITH_CSR_SERVICE(CORE_SERVICE_DEVICE_REGISTRY_ONBOARDING_WITH_CSR,
+ DEVICE_REGISTRY_URI + ONBOARDING_URI + OP_DEVICE_REGISTRY_ONBOARDING_WITH_CSR_URI),
+
+ // System Registry services
+ SYSTEM_REGISTRY_REGISTER_SERVICE(CORE_SERVICE_SYSTEM_REGISTRY_REGISTER, SYSTEM_REGISTRY_URI + OP_SYSTEM_REGISTRY_REGISTER_URI),
+ SYSTEM_REGISTRY_UNREGISTER_SERVICE(CORE_SERVICE_SYSTEM_REGISTRY_UNREGISTER, SYSTEM_REGISTRY_URI + OP_SYSTEM_REGISTRY_UNREGISTER_URI),
+ SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_SERVICE(CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME,
+ SYSTEM_REGISTRY_URI + ONBOARDING_URI + OP_SYSTEM_REGISTRY_ONBOARDING_WITH_NAME_URI),
+ SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_SERVICE(CORE_SERVICE_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR,
+ SYSTEM_REGISTRY_URI + ONBOARDING_URI + OP_SYSTEM_REGISTRY_ONBOARDING_WITH_CSR_URI),
+
+ // Service Registry services
+ SERVICE_REGISTRY_REGISTER_SERVICE(CORE_SERVICE_SERVICE_REGISTRY_REGISTER, SERVICE_REGISTRY_URI + OP_SERVICE_REGISTRY_REGISTER_URI),
+ SERVICE_REGISTRY_UNREGISTER_SERVICE(CORE_SERVICE_SERVICE_REGISTRY_UNREGISTER, SERVICE_REGISTRY_URI + OP_SERVICE_REGISTRY_UNREGISTER_URI);
+
+ //TODO: additional services
+
+ //=================================================================================================
+ // members
+
+ private final String serviceDefinition;
+ private final String serviceUri;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public String getServiceDefinition() {
+ return serviceDefinition;
+ }
+
+ public String getServiceUri() {
+ return serviceUri;
+ }
+
+
+ //=================================================================================================
+ // constructors
//-------------------------------------------------------------------------------------------------
private CoreSystemService(final String serviceDefinition, final String serviceUri) {
- Assert.isTrue(!Utilities.isEmpty(serviceDefinition), serviceUri);
+ Assert.isTrue(!Utilities.isEmpty(serviceDefinition), "Service definition is null or blank");
+ Assert.isTrue(!Utilities.isEmpty(serviceUri), "Service URI is null or blank");
this.serviceDefinition = serviceDefinition;
this.serviceUri = serviceUri;
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/AuthorizationInterCloud.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/AuthorizationInterCloud.java
index c54e1dbc1..b448cff6c 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/entity/AuthorizationInterCloud.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/AuthorizationInterCloud.java
@@ -25,12 +25,12 @@
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"consumerCloudId", "providerSystemId", "serviceId"}))
public class AuthorizationInterCloud {
-
- public static final List SORTABLE_FIELDS_BY = List.of("id", "updatedAt", "createdAt"); //NOSONAR
//=================================================================================================
// members
+ public static final List SORTABLE_FIELDS_BY = List.of("id", "updatedAt", "createdAt"); //NOSONAR
+
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/Device.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/Device.java
new file mode 100644
index 000000000..c1ecf6bc6
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/Device.java
@@ -0,0 +1,131 @@
+package eu.arrowhead.common.database.entity;
+
+import eu.arrowhead.common.CoreDefaults;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedAttributeNode;
+import javax.persistence.NamedEntityGraph;
+import javax.persistence.OneToMany;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.time.ZonedDateTime;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Entity
+@Table(name = "device", uniqueConstraints = @UniqueConstraint(columnNames = { "deviceName", "macAddress" }))
+@NamedEntityGraph(name = "deviceWithSystemRegistryEntries",
+ attributeNodes = {
+ @NamedAttributeNode(value = "systemRegistryEntries")
+})
+public class Device
+{
+
+ //=================================================================================================
+ // members
+
+ public static final List SORTABLE_FIELDS_BY = List.of("id", "updatedAt", "createdAt", "deviceName", "address"); //NOSONAR
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @Column(nullable = false, length = CoreDefaults.VARCHAR_BASIC)
+ private String deviceName;
+
+ @Column(nullable = false, length = CoreDefaults.VARCHAR_BASIC)
+ private String address;
+
+ @Column(nullable = false, unique = true, length = CoreDefaults.VARCHAR_BASIC)
+ private String macAddress;
+
+ @Column(nullable = true, length = CoreDefaults.VARCHAR_EXTENDED)
+ private String authenticationInfo;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ @OneToMany(mappedBy = "device", fetch = FetchType.LAZY, orphanRemoval = true)
+ @OnDelete(action = OnDeleteAction.CASCADE)
+ private Set systemRegistryEntries = new HashSet<>();
+
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public Device() {}
+
+ //-------------------------------------------------------------------------------------------------
+ public Device(final String deviceName, final String address, final String macAddress, final String authenticationInfo) {
+ this.deviceName = deviceName;
+ this.address = address;
+ this.macAddress = macAddress;
+ this.authenticationInfo = authenticationInfo;
+ }
+
+ public Device(final long id, final String deviceName, final String address, final String macAddress, final String authenticationInfo,
+ final ZonedDateTime createdAt, final ZonedDateTime updatedAt, final Set systemRegistryEntries) {
+ this.id = id;
+ this.deviceName = deviceName;
+ this.address = address;
+ this.macAddress = macAddress;
+ this.authenticationInfo = authenticationInfo;
+ this.createdAt = createdAt;
+ this.updatedAt = updatedAt;
+ this.systemRegistryEntries = systemRegistryEntries;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() { return id; }
+ public String getDeviceName() { return deviceName; }
+ public String getAddress() { return address; }
+ public String getMacAddress() {return macAddress; }
+
+ public String getAuthenticationInfo() { return authenticationInfo; }
+ public ZonedDateTime getCreatedAt() { return createdAt; }
+ public ZonedDateTime getUpdatedAt() { return updatedAt; }
+ public Set getSystemRegistryEntries() { return systemRegistryEntries; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) { this.id = id; }
+ public void setDeviceName(final String systemName) { this.deviceName = systemName; }
+ public void setAddress(final String address) { this.address = address; }
+ public void setMacAddress(final String macAddress) { this.macAddress = macAddress; }
+ public void setAuthenticationInfo(final String authenticationInfo) { this.authenticationInfo = authenticationInfo; }
+ public void setCreatedAt(final ZonedDateTime createdAt) { this.createdAt = createdAt; }
+ public void setUpdatedAt(final ZonedDateTime updatedAt) { this.updatedAt = updatedAt; }
+ public void setSystemRegistryEntries(final Set systemRegistryEntries) { this.systemRegistryEntries = systemRegistryEntries; }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public String toString() {
+ return "System [id = " + id + ", systemName = " + deviceName + ", address = " + address + ", macAddress = " + macAddress + "]";
+ }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/DeviceRegistry.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/DeviceRegistry.java
new file mode 100644
index 000000000..bc11e3ef8
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/DeviceRegistry.java
@@ -0,0 +1,168 @@
+package eu.arrowhead.common.database.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"deviceId"}))
+public class DeviceRegistry {
+
+ //=================================================================================================
+ // members
+ public static final List SORTABLE_FIELDS_BY = List.of("id", "updatedAt", "createdAt"); //NOSONAR
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "deviceId", referencedColumnName = "id", nullable = false)
+ private Device device;
+
+ @Column(nullable = true)
+ private ZonedDateTime endOfValidity;
+
+ @Column(nullable = true, columnDefinition = "TEXT")
+ private String metadata;
+
+ @Column(nullable = true)
+ private Integer version = 1;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public DeviceRegistry() {
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public DeviceRegistry(final Device device, final ZonedDateTime endOfValidity,
+ final String metadata, final Integer version) {
+ this.device = device;
+ this.endOfValidity = endOfValidity;
+ this.metadata = metadata;
+ this.version = version;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() {
+ return id;
+ }
+
+ public Device getDevice() {
+ return device;
+ }
+
+ public ZonedDateTime getEndOfValidity() {
+ return endOfValidity;
+ }
+
+ public String getMetadata() {
+ return metadata;
+ }
+
+ public Integer getVersion() {
+ return version;
+ }
+
+ public ZonedDateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ public ZonedDateTime getUpdatedAt() {
+ return updatedAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public void setDevice(final Device device) {
+ this.device = device;
+ }
+
+ public void setEndOfValidity(final ZonedDateTime endOfValidity) {
+ this.endOfValidity = endOfValidity;
+ }
+
+ public void setMetadata(final String metadata) {
+ this.metadata = metadata;
+ }
+
+ public void setVersion(final Integer version) {
+ this.version = version;
+ }
+
+ public void setCreatedAt(final ZonedDateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public void setUpdatedAt(final ZonedDateTime updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public String toString() {
+ return "ServiceRegistry [id = " + id + ", device = " + device + ", endOfValidity = " + endOfValidity + ", version = " + version + "]";
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final DeviceRegistry other = (DeviceRegistry) obj;
+
+ return id == other.id;
+ }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraMeasurement.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraMeasurement.java
new file mode 100644
index 000000000..a6b3e40d3
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraMeasurement.java
@@ -0,0 +1,92 @@
+package eu.arrowhead.common.database.entity;
+
+import java.time.ZonedDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import eu.arrowhead.common.CoreDefaults;
+import eu.arrowhead.common.dto.shared.QoSMeasurementType;
+
+@Entity
+@Table(name = "qos_intra_measurement", uniqueConstraints = @UniqueConstraint(columnNames = {"systemId", "measurementType"}))
+public class QoSIntraMeasurement {
+
+ //=================================================================================================
+ // members
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "systemId", referencedColumnName = "id", nullable = false)
+ private System system;
+
+ @Column(nullable = false, columnDefinition = "varchar(" + CoreDefaults.VARCHAR_BASIC + ")")
+ @Enumerated(EnumType.STRING)
+ private QoSMeasurementType measurementType;
+
+ @Column(nullable = false)
+ private ZonedDateTime lastMeasurementAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraMeasurement() {}
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraMeasurement(final System system, final QoSMeasurementType measurementType, final ZonedDateTime lastMeasurementAt) {
+ this.system = system;
+ this.measurementType = measurementType;
+ this.lastMeasurementAt = lastMeasurementAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() { return id; }
+ public System getSystem() { return system; }
+ public QoSMeasurementType getMeasurementType() { return measurementType; }
+ public ZonedDateTime getLastMeasurementAt() { return lastMeasurementAt; }
+ public ZonedDateTime getCreatedAt() { return createdAt; }
+ public ZonedDateTime getUpdatedAt() { return updatedAt; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) { this.id = id; }
+ public void setSystem(final System system) { this.system = system; }
+ public void setMeasurementType(final QoSMeasurementType measurementType) { this.measurementType = measurementType; }
+ public void setLastMeasurementAt(final ZonedDateTime lastMeasurementAt) { this.lastMeasurementAt = lastMeasurementAt; }
+ public void setCreatedAt(final ZonedDateTime createdAt) { this.createdAt = createdAt; }
+ public void setUpdatedAt(final ZonedDateTime updatedAt) { this.updatedAt = updatedAt; }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurement.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurement.java
new file mode 100644
index 000000000..f22cefd02
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurement.java
@@ -0,0 +1,141 @@
+package eu.arrowhead.common.database.entity;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "qos_intra_ping_measurement")
+public class QoSIntraPingMeasurement {
+
+ //=================================================================================================
+ // members
+
+ public static final List SORTABLE_FIELDS_BY = List.of( "id", "updatedAt", "createdAt"); //NOSONAR
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "measurementId", referencedColumnName = "id", nullable = false, unique = true)
+ private QoSIntraMeasurement measurement;
+
+ @Column(name = "available", nullable = false)
+ private boolean available = false;
+
+ @Column(name = "last_access_at", nullable = true)
+ private ZonedDateTime lastAccessAt;
+
+ @Column(name = "min_response_time", nullable = true)
+ private Integer minResponseTime;
+
+ @Column(name = "max_response_time", nullable = true)
+ private Integer maxResponseTime;
+
+ @Column(name = "mean_response_time_with_timeout", nullable = true)
+ private Integer meanResponseTimeWithTimeout;
+
+ @Column(name = "mean_response_time_without_timeout", nullable = true)
+ private Integer meanResponseTimeWithoutTimeout;
+
+ @Column(name = "jitter_with_timeout", nullable = true)
+ private Integer jitterWithTimeout;
+
+ @Column(name = "jitter_without_timeout", nullable = true)
+ private Integer jitterWithoutTimeout;
+
+ @Column(name = "lost_per_measurement_percent", nullable = false)
+ private Integer lostPerMeasurementPercent;
+
+ @Column(name = "sent", nullable = false)
+ private long sent;
+
+ @Column(name = "received", nullable = false)
+ private long received;
+
+ @Column(name = "count_started_at", nullable = true)
+ private ZonedDateTime countStartedAt;
+
+ @Column(name = "sent_all", nullable = false)
+ private long sentAll;
+
+ @Column(name = "received_all", nullable = false)
+ private long receivedAll;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraPingMeasurement() {}
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() { return id; }
+ public QoSIntraMeasurement getMeasurement() { return measurement; }
+ public boolean isAvailable() { return available; }
+ public ZonedDateTime getLastAccessAt() { return lastAccessAt; }
+ public Integer getMinResponseTime() { return minResponseTime; }
+ public Integer getMaxResponseTime() { return maxResponseTime; }
+ public Integer getMeanResponseTimeWithTimeout() { return meanResponseTimeWithTimeout; }
+ public Integer getMeanResponseTimeWithoutTimeout() { return meanResponseTimeWithoutTimeout; }
+ public Integer getJitterWithTimeout() {return jitterWithTimeout;}
+ public Integer getJitterWithoutTimeout() { return jitterWithoutTimeout; }
+ public Integer getLostPerMeasurementPercent() { return lostPerMeasurementPercent; }
+ public long getSent() { return sent; }
+ public long getReceived() { return received; }
+ public ZonedDateTime getCountStartedAt() { return countStartedAt; }
+ public long getSentAll() { return sentAll; }
+ public long getReceivedAll() { return receivedAll; }
+ public ZonedDateTime getCreatedAt() { return createdAt; }
+ public ZonedDateTime getUpdatedAt() { return updatedAt; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) { this.id = id; }
+ public void setMeasurement(final QoSIntraMeasurement measurement) { this.measurement = measurement; }
+ public void setAvailable(final boolean available) { this.available = available; }
+ public void setLastAccessAt(final ZonedDateTime lastAccessAt) { this.lastAccessAt = lastAccessAt; }
+ public void setMinResponseTime(final Integer minResponseTime) { this.minResponseTime = minResponseTime; }
+ public void setMaxResponseTime(final Integer maxResponseTime) { this.maxResponseTime = maxResponseTime; }
+ public void setMeanResponseTimeWithoutTimeout(final Integer meanResponseTimeWithoutTimeout) { this.meanResponseTimeWithoutTimeout = meanResponseTimeWithoutTimeout; }
+ public void setMeanResponseTimeWithTimeout(final Integer meanResponseTimeWithTimeout) { this.meanResponseTimeWithTimeout = meanResponseTimeWithTimeout; }
+ public void setJitterWithTimeout(final Integer jitterWithTimeout) { this.jitterWithTimeout = jitterWithTimeout; }
+ public void setJitterWithoutTimeout(final Integer jitterWithoutTimeout) { this.jitterWithoutTimeout = jitterWithoutTimeout; }
+ public void setLostPerMeasurementPercent(final Integer lostPerMeasurementPercent) { this.lostPerMeasurementPercent = lostPerMeasurementPercent; }
+ public void setSent(final long sent) { this.sent = sent; }
+ public void setReceived(final long received) { this.received = received; }
+ public void setCountStartedAt(final ZonedDateTime countStartedAt) { this.countStartedAt = countStartedAt; }
+ public void setSentAll(final long sentAll) { this.sentAll = sentAll; }
+ public void setReceivedAll(final long receivedAll) { this.receivedAll = receivedAll; }
+ public void setCreatedAt(final ZonedDateTime createdAt) { this.createdAt = createdAt; }
+ public void setUpdatedAt(final ZonedDateTime updatedAt) { this.updatedAt = updatedAt; }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLog.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLog.java
new file mode 100644
index 000000000..d8a306891
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLog.java
@@ -0,0 +1,114 @@
+package eu.arrowhead.common.database.entity;
+
+import java.time.ZonedDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "qos_intra_ping_measurement_log")
+public class QoSIntraPingMeasurementLog {
+
+ //=================================================================================================
+ // members
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @Column(name = "measured_system_address", nullable = false)
+ private String measuredSystemAddress;
+
+ @Column(name = "available", nullable = false)
+ private boolean available = false;
+
+ @Column(name = "min_response_time", nullable = true)
+ private Integer minResponseTime;
+
+ @Column(name = "max_response_time", nullable = true)
+ private Integer maxResponseTime;
+
+ @Column(name = "mean_response_time_with_timeout", nullable = true)
+ private Integer meanResponseTimeWithTimeout;
+
+ @Column(name = "mean_response_time_without_timeout", nullable = true)
+ private Integer meanResponseTimeWithoutTimeout;
+
+ @Column(name = "jitter_with_timeout", nullable = true)
+ private Integer jitterWithTimeout;
+
+ @Column(name = "jitter_without_timeout", nullable = true)
+ private Integer jitterWithoutTimeout;
+
+ @Column(name = "lost_per_measurement_percent", nullable = false)
+ private Integer lostPerMeasurementPercent;
+
+ @Column(name = "sent", nullable = false)
+ private long sent;
+
+ @Column(name = "received", nullable = false)
+ private long received;
+
+ @Column(name = "measured_at",nullable = false)
+ private ZonedDateTime measuredAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraPingMeasurementLog() {}
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public String getMeasuredSystemAddress() { return measuredSystemAddress; }
+ public boolean isAvailable() { return available; }
+ public Integer getMinResponseTime() { return minResponseTime; }
+ public Integer getMaxResponseTime() { return maxResponseTime; }
+ public Integer getMeanResponseTimeWithTimeout() { return meanResponseTimeWithTimeout; }
+ public Integer getMeanResponseTimeWithoutTimeout() { return meanResponseTimeWithoutTimeout; }
+ public Integer getJitterWithTimeout() { return jitterWithTimeout; }
+ public Integer getJitterWithoutTimeout() { return jitterWithoutTimeout; }
+ public Integer getLostPerMeasurementPercent() { return lostPerMeasurementPercent; }
+ public long getSent() { return sent; }
+ public long getReceived() { return received; }
+ public ZonedDateTime getMeasuredAt() { return measuredAt; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setMeasuredSystemAddress(final String measuredSystemAddress) { this.measuredSystemAddress = measuredSystemAddress; }
+ public void setAvailable(final boolean available) { this.available = available; }
+ public void setMinResponseTime(final Integer minResponseTime) { this.minResponseTime = minResponseTime; }
+ public void setMaxResponseTime(final Integer maxResponseTime) { this.maxResponseTime = maxResponseTime; }
+ public void setMeanResponseTimeWithTimeout(final Integer meanResponseTimeWithTimeout) { this.meanResponseTimeWithTimeout = meanResponseTimeWithTimeout; }
+ public void setMeanResponseTimeWithoutTimeout(final Integer meanResponseTimeWithoutTimeout) { this.meanResponseTimeWithoutTimeout = meanResponseTimeWithoutTimeout; }
+ public void setJitterWithTimeout(final Integer jitterWithTimeout) { this.jitterWithTimeout = jitterWithTimeout; }
+ public void setJitterWithoutTimeout(final Integer jitterWithoutTimeout) { this.jitterWithoutTimeout = jitterWithoutTimeout; }
+ public void setLostPerMeasurementPercent(final Integer lostPerMeasurementPercent) { this.lostPerMeasurementPercent = lostPerMeasurementPercent; }
+ public void setSent(final long sent) { this.sent = sent; }
+ public void setReceived(final long received) { this.received = received; }
+ public void setMeasuredAt(final ZonedDateTime measuredAt) { this.measuredAt = measuredAt; }
+
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLogDetails.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLogDetails.java
new file mode 100644
index 000000000..f19de5443
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSIntraPingMeasurementLogDetails.java
@@ -0,0 +1,113 @@
+package eu.arrowhead.common.database.entity;
+
+import java.time.ZonedDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "qos_intra_ping_measurement_log_details")
+public class QoSIntraPingMeasurementLogDetails {
+
+ //=================================================================================================
+ // members
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "measurement_log_id", referencedColumnName = "id", nullable = false, unique = true)
+ private QoSIntraPingMeasurementLog measurementLog;
+
+ @Column(name = "measurement_sequenece_number", nullable = false)
+ private int measurementSequeneceNumber;
+
+ @Column(name = "success_flag", nullable = false)
+ private boolean successFlag = false;
+
+ @Column(name = "timeout_flag", nullable = false)
+ private boolean timeoutFlag = false;
+
+ @Column(name = "error_message", nullable = true)
+ private String errorMessage;
+
+ @Column(name = "throwable", nullable = true)
+ private String throwable;
+
+ @Column(name = "size_", nullable = true)
+ private Integer size;
+
+ @Column(name = "rtt", nullable = true)
+ private Integer rtt;
+
+ @Column(name = "ttl", nullable = true)
+ private Integer ttl;
+
+ @Column(name = "duration", nullable = true)
+ private Integer duration;
+
+ @Column(name = "measured_at", nullable = false)
+ private ZonedDateTime measuredAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraPingMeasurementLogDetails() {}
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSIntraPingMeasurementLog getMeasurementLog() { return measurementLog; }
+ public int getMeasurementSequeneceNumber() { return measurementSequeneceNumber; }
+ public boolean isSuccessFlag() { return successFlag; }
+ public boolean isTimeoutFlag() { return timeoutFlag; }
+ public String getErrorMessage() { return errorMessage; }
+ public String getThrowable() { return throwable; }
+ public Integer getSize() { return size; }
+ public Integer getRtt() { return rtt; }
+ public Integer getTtl() { return ttl; }
+ public Integer getDuration() { return duration; }
+ public ZonedDateTime getMeasuredAt() { return measuredAt; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setMeasurementLog(final QoSIntraPingMeasurementLog measurementLog) { this.measurementLog = measurementLog; }
+ public void setMeasurementSequeneceNumber(final int measurementSequeneceNumber) { this.measurementSequeneceNumber = measurementSequeneceNumber; }
+ public void setSuccessFlag(final boolean successFlag) { this.successFlag = successFlag; }
+ public void setTimeoutFlag(final boolean timeoutFlag) { this.timeoutFlag = timeoutFlag; }
+ public void setErrorMessage(final String errorMessage) { this.errorMessage = errorMessage; }
+ public void setThrowable(final String throwable) { this.throwable = throwable; }
+ public void setSize(final Integer size) { this.size = size; }
+ public void setRtt(final Integer rtt) { this.rtt = rtt; }
+ public void setTtl(final Integer ttl) { this.ttl = ttl; }
+ public void setDuration(final Integer duration) { this.duration = duration; }
+ public void setMeasuredAt(final ZonedDateTime measuredAt) { this.measuredAt = measuredAt; }
+
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSReservation.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSReservation.java
new file mode 100644
index 000000000..4c2df2ea8
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/QoSReservation.java
@@ -0,0 +1,97 @@
+package eu.arrowhead.common.database.entity;
+
+import java.time.ZonedDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+@Entity
+@Table(name = "qos_reservation", uniqueConstraints = @UniqueConstraint(columnNames = { "reservedProviderId", "reservedServiceId" }) )
+public class QoSReservation {
+
+ //=================================================================================================
+ // members
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ private long reservedProviderId;
+ private long reservedServiceId;
+
+ private String consumerSystemName;
+ private String consumerAddress;
+ private int consumerPort;
+
+ private ZonedDateTime reservedTo;
+
+ private boolean temporaryLock = false;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSReservation() {}
+
+ //-------------------------------------------------------------------------------------------------
+ public QoSReservation(final long reservedProviderId, final long reservedServiceId, final String consumerSystemName, final String consumerAddress, final int consumerPort,
+ final ZonedDateTime reservedTo, final boolean temporaryLock) {
+ this.reservedProviderId = reservedProviderId;
+ this.reservedServiceId = reservedServiceId;
+ this.consumerSystemName = consumerSystemName;
+ this.consumerAddress = consumerAddress;
+ this.consumerPort = consumerPort;
+ this.reservedTo = reservedTo;
+ this.temporaryLock = temporaryLock;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() { return id; }
+ public long getReservedProviderId() { return reservedProviderId; }
+ public long getReservedServiceId() { return reservedServiceId; }
+ public String getConsumerSystemName() { return consumerSystemName; }
+ public String getConsumerAddress() { return consumerAddress; }
+ public int getConsumerPort() { return consumerPort; }
+ public ZonedDateTime getReservedTo() { return reservedTo; }
+ public boolean isTemporaryLock() { return temporaryLock; }
+ public ZonedDateTime getCreatedAt() { return createdAt; }
+ public ZonedDateTime getUpdatedAt() { return updatedAt; }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) { this.id = id; }
+ public void setReservedProviderId(final long reservedProviderId) { this.reservedProviderId = reservedProviderId; }
+ public void setReservedServiceId(final int reservedServiceId) { this.reservedServiceId = reservedServiceId; }
+ public void setConsumerSystemName(final String consumerSystemName) { this.consumerSystemName = consumerSystemName; }
+ public void setConsumerAddress(final String consumerAddress) { this.consumerAddress = consumerAddress; }
+ public void setConsumerPort(final int consumerPort) { this.consumerPort = consumerPort; }
+ public void setReservedTo(final ZonedDateTime reservedTo) { this.reservedTo = reservedTo; }
+ public void setTemporaryLock(final boolean temporaryLock) { this.temporaryLock = temporaryLock; }
+ public void setCreatedAt(final ZonedDateTime createdAt) { this.createdAt = createdAt; }
+ public void setUpdatedAt(final ZonedDateTime updatedAt) { this.updatedAt = updatedAt; }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/Subscription.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/Subscription.java
index 36c80d176..2f1e53ff1 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/entity/Subscription.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/Subscription.java
@@ -71,7 +71,6 @@ public class Subscription {
@OneToMany(mappedBy = "subscriptionEntry", fetch = FetchType.EAGER, orphanRemoval = true)
@OnDelete(action = OnDeleteAction.CASCADE)
private Set publisherConnections = new HashSet<>();
-
//=================================================================================================
// methods
@@ -126,7 +125,7 @@ public void onUpdate() {
public void setFilterMetaData(final String filterMetaData) { this.filterMetaData = filterMetaData; }
public void setNotifyUri(final String notifyUri) { this.notifyUri = notifyUri; }
public void setMatchMetaData(final boolean matchMetaData) { this.matchMetaData = matchMetaData; }
- public void setOnlyPredefinedPublishers( final boolean onlyPredefinedPublishers) { this.onlyPredefinedPublishers = onlyPredefinedPublishers; }
+ public void setOnlyPredefinedPublishers(final boolean onlyPredefinedPublishers) { this.onlyPredefinedPublishers = onlyPredefinedPublishers; }
public void setStartDate(final ZonedDateTime startDate) { this.startDate = startDate; }
public void setEndDate(final ZonedDateTime endDate) { this.endDate = endDate; }
public void setCreatedAt(final ZonedDateTime createdAt) { this.createdAt = createdAt; }
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/SubscriptionPublisherConnection.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/SubscriptionPublisherConnection.java
index 0ed4d6a45..a980828e8 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/entity/SubscriptionPublisherConnection.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/SubscriptionPublisherConnection.java
@@ -18,6 +18,7 @@
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "subscriptionId", "systemId" }))
public class SubscriptionPublisherConnection {
+
//=================================================================================================
// members
@@ -33,7 +34,7 @@ public class SubscriptionPublisherConnection {
@JoinColumn(name = "systemId", referencedColumnName = "id", nullable = false)
private System system;
- @Column(nullable = false )
+ @Column(nullable = false)
private boolean authorized = false;
@Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/entity/SystemRegistry.java b/core-common/src/main/java/eu/arrowhead/common/database/entity/SystemRegistry.java
new file mode 100644
index 000000000..43bda3ce6
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/entity/SystemRegistry.java
@@ -0,0 +1,181 @@
+package eu.arrowhead.common.database.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"systemId", "deviceId"}))
+public class SystemRegistry {
+
+ //=================================================================================================
+ // members
+ public static final List SORTABLE_FIELDS_BY = List.of("id", "updatedAt", "createdAt"); //NOSONAR
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "systemId", referencedColumnName = "id", nullable = false)
+ private System system;
+
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "deviceId", referencedColumnName = "id", nullable = false)
+ private Device device;
+
+ @Column(nullable = true)
+ private ZonedDateTime endOfValidity;
+
+ @Column(nullable = true, columnDefinition = "TEXT")
+ private String metadata;
+
+ @Column(nullable = true)
+ private Integer version = 1;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private ZonedDateTime createdAt;
+
+ @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
+ private ZonedDateTime updatedAt;
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public SystemRegistry() {
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public SystemRegistry(final System system, final Device device, final ZonedDateTime endOfValidity,
+ final String metadata, final Integer version) {
+ this.system = system;
+ this.device = device;
+ this.endOfValidity = endOfValidity;
+ this.metadata = metadata;
+ this.version = version;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PrePersist
+ public void onCreate() {
+ this.createdAt = ZonedDateTime.now();
+ this.updatedAt = this.createdAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @PreUpdate
+ public void onUpdate() {
+ this.updatedAt = ZonedDateTime.now();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public long getId() {
+ return id;
+ }
+
+ public System getSystem() {
+ return system;
+ }
+
+ public Device getDevice() {
+ return device;
+ }
+
+ public ZonedDateTime getEndOfValidity() {
+ return endOfValidity;
+ }
+
+ public String getMetadata() {
+ return metadata;
+ }
+
+ public Integer getVersion() {
+ return version;
+ }
+
+ public ZonedDateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ public ZonedDateTime getUpdatedAt() {
+ return updatedAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public void setSystem(final System system) {
+ this.system = system;
+ }
+
+ public void setDevice(final Device device) {
+ this.device = device;
+ }
+
+ public void setEndOfValidity(final ZonedDateTime endOfValidity) {
+ this.endOfValidity = endOfValidity;
+ }
+
+ public void setMetadata(final String metadata) {
+ this.metadata = metadata;
+ }
+
+ public void setVersion(final Integer version) {
+ this.version = version;
+ }
+
+ public void setCreatedAt(final ZonedDateTime createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public void setUpdatedAt(final ZonedDateTime updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public String toString() {
+ return "ServiceRegistry [id = " + id + ", system = " + system + ", device = " + device + ", endOfValidity = " + endOfValidity + ", version = " + version + "]";
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final SystemRegistry other = (SystemRegistry) obj;
+
+ return id == other.id;
+ }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationInterCloudInterfaceConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationInterCloudInterfaceConnectionRepository.java
index 8f411aebb..eb201a31d 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationInterCloudInterfaceConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationInterCloudInterfaceConnectionRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface AuthorizationInterCloudInterfaceConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudInterfaceConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudInterfaceConnectionRepository.java
index baa3155ab..39042da56 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudInterfaceConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudInterfaceConnectionRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface AuthorizationIntraCloudInterfaceConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudRepository.java
index 35f9832c6..b18b93326 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/AuthorizationIntraCloudRepository.java
@@ -22,7 +22,5 @@ public interface AuthorizationIntraCloudRepository extends RefreshableRepository
//-------------------------------------------------------------------------------------------------
public Optional findByConsumerSystemAndProviderSystemAndServiceDefinition(final System consumer, final System provider, final ServiceDefinition serviceDefinition);
-
- //-------------------------------------------------------------------------------------------------
public List findAllByConsumerSystem(final System consumer);
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionActionStepConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionActionStepConnectionRepository.java
index 71e03f334..8b4f9b20b 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionActionStepConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionActionStepConnectionRepository.java
@@ -5,5 +5,4 @@
@Repository
public interface ChoreographerActionActionStepConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionPlanActionConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionPlanActionConnectionRepository.java
index bc26c4406..85047832d 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionPlanActionConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionPlanActionConnectionRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface ChoreographerActionPlanActionConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionStepServiceDefinitionConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionStepServiceDefinitionConnectionRepository.java
index 34309477d..6710b9825 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionStepServiceDefinitionConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerActionStepServiceDefinitionConnectionRepository.java
@@ -5,5 +5,4 @@
@Repository
public interface ChoreographerActionStepServiceDefinitionConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerNextActionStepRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerNextActionStepRepository.java
index 8c6ae64df..4ff71485d 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerNextActionStepRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/ChoreographerNextActionStepRepository.java
@@ -5,5 +5,4 @@
@Repository
public interface ChoreographerNextActionStepRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatekeeperRelayRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatekeeperRelayRepository.java
index 9143b59fa..e4636f140 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatekeeperRelayRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatekeeperRelayRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface CloudGatekeeperRelayRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatewayRelayRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatewayRelayRepository.java
index b9bf21e08..b1f980798 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatewayRelayRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/CloudGatewayRelayRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface CloudGatewayRelayRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRegistryRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRegistryRepository.java
new file mode 100644
index 000000000..95480eec6
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRegistryRepository.java
@@ -0,0 +1,23 @@
+package eu.arrowhead.common.database.repository;
+
+import eu.arrowhead.common.database.entity.Device;
+import eu.arrowhead.common.database.entity.DeviceRegistry;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface DeviceRegistryRepository extends RefreshableRepository
+{
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ Optional findByDevice(final Device device);
+ Page findAllByDeviceIsIn(final List devices, final PageRequest pageRequest);
+ List findAllByDeviceIsIn(final List devices);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRepository.java
new file mode 100644
index 000000000..bfe573e7b
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/DeviceRepository.java
@@ -0,0 +1,19 @@
+package eu.arrowhead.common.database.repository;
+
+import eu.arrowhead.common.database.entity.Device;
+import eu.arrowhead.common.database.entity.System;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface DeviceRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public Optional findByDeviceNameAndMacAddress(final String deviceName, final String address);
+ public List findByDeviceName(final String deviceName);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/EventTypeRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/EventTypeRepository.java
index 4c6455222..7fb619237 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/EventTypeRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/EventTypeRepository.java
@@ -14,4 +14,4 @@ public interface EventTypeRepository extends RefreshableRepository findByEventTypeName(final String eventTypeName);
-}
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementPingRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementPingRepository.java
new file mode 100644
index 000000000..9dfb91be5
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementPingRepository.java
@@ -0,0 +1,15 @@
+package eu.arrowhead.common.database.repository;
+
+import java.util.Optional;
+
+import org.springframework.stereotype.Repository;
+
+import eu.arrowhead.common.database.entity.QoSIntraMeasurement;
+import eu.arrowhead.common.database.entity.QoSIntraPingMeasurement;
+
+@Repository
+public interface QoSIntraMeasurementPingRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ public Optional findByMeasurement(final QoSIntraMeasurement measurement);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementRepository.java
new file mode 100644
index 000000000..a17d5b359
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraMeasurementRepository.java
@@ -0,0 +1,17 @@
+package eu.arrowhead.common.database.repository;
+
+import java.util.Optional;
+
+import org.springframework.stereotype.Repository;
+
+import eu.arrowhead.common.database.entity.QoSIntraMeasurement;
+import eu.arrowhead.common.database.entity.System;
+import eu.arrowhead.common.dto.shared.QoSMeasurementType;
+
+@Repository
+public interface QoSIntraMeasurementRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ // methods
+ public Optional findBySystemAndMeasurementType(final System systemToCheck,final QoSMeasurementType type);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogDetailsRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogDetailsRepository.java
new file mode 100644
index 000000000..e72f6e59b
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogDetailsRepository.java
@@ -0,0 +1,11 @@
+package eu.arrowhead.common.database.repository;
+
+import org.springframework.stereotype.Repository;
+
+import eu.arrowhead.common.database.entity.QoSIntraPingMeasurementLogDetails;
+
+@Repository
+public interface QoSIntraPingMeasurementLogDetailsRepository extends RefreshableRepository {
+ //=================================================================================================
+ // methods
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogRepository.java
new file mode 100644
index 000000000..5b8702099
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSIntraPingMeasurementLogRepository.java
@@ -0,0 +1,15 @@
+package eu.arrowhead.common.database.repository;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+import org.springframework.stereotype.Repository;
+import eu.arrowhead.common.database.entity.QoSIntraPingMeasurementLog;
+
+@Repository
+public interface QoSIntraPingMeasurementLogRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ // methods
+ public Optional findByMeasuredAt(final ZonedDateTime timeStamp);
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSReservationRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSReservationRepository.java
new file mode 100644
index 000000000..ad3ce72c3
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/QoSReservationRepository.java
@@ -0,0 +1,22 @@
+package eu.arrowhead.common.database.repository;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.stereotype.Repository;
+
+import eu.arrowhead.common.database.entity.QoSReservation;
+
+@Repository
+public interface QoSReservationRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ public List findAllByReservedToLessThanEqual(final ZonedDateTime threshold);
+ public List findAllByConsumerSystemNameNotOrConsumerAddressNotOrConsumerPortNot(final String consumerSystemName, final String consumerAddress, final int consumerPort);
+ public Optional findByReservedProviderIdAndReservedServiceId(final long reservedProviderId, final long reservedServiceId);
+ public Optional findByReservedProviderIdAndReservedServiceIdAndTemporaryLockTrue(final long reservedProviderId, final long reservedServiceId);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/ServiceRegistryInterfaceConnectionRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/ServiceRegistryInterfaceConnectionRepository.java
index 0876b9051..f7382af49 100644
--- a/core-common/src/main/java/eu/arrowhead/common/database/repository/ServiceRegistryInterfaceConnectionRepository.java
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/ServiceRegistryInterfaceConnectionRepository.java
@@ -6,5 +6,4 @@
@Repository
public interface ServiceRegistryInterfaceConnectionRepository extends RefreshableRepository {
-
}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/database/repository/SystemRegistryRepository.java b/core-common/src/main/java/eu/arrowhead/common/database/repository/SystemRegistryRepository.java
new file mode 100644
index 000000000..f8ef9378f
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/database/repository/SystemRegistryRepository.java
@@ -0,0 +1,29 @@
+package eu.arrowhead.common.database.repository;
+
+import eu.arrowhead.common.database.entity.Device;
+import eu.arrowhead.common.database.entity.System;
+import eu.arrowhead.common.database.entity.SystemRegistry;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface SystemRegistryRepository extends RefreshableRepository {
+
+ //=================================================================================================
+ // methods
+
+ //-------------------------------------------------------------------------------------------------
+ List findBySystem(final System system);
+
+ List findByDevice(final Device device);
+
+ Optional findBySystemAndDevice(final System systemDb, final Device deviceDb);
+
+ List findAllBySystemIsIn(final List systems);
+
+ Page findAllBySystemIsIn(final List systemList, final PageRequest pageRequest);
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/eu/arrowhead/common/drivers/CertificateAuthorityDriver.java b/core-common/src/main/java/eu/arrowhead/common/drivers/CertificateAuthorityDriver.java
new file mode 100644
index 000000000..20a4ea20b
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/drivers/CertificateAuthorityDriver.java
@@ -0,0 +1,40 @@
+package eu.arrowhead.common.drivers;
+
+import eu.arrowhead.common.core.CoreSystemService;
+import eu.arrowhead.common.dto.internal.CertificateSigningRequestDTO;
+import eu.arrowhead.common.dto.internal.CertificateSigningResponseDTO;
+import eu.arrowhead.common.http.HttpService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.web.util.UriComponents;
+
+@Service
+public class CertificateAuthorityDriver {
+
+ //=================================================================================================
+ // members
+ private final Logger logger = LogManager.getLogger(CertificateAuthorityDriver.class);
+ private final DriverUtilities driverUtilities;
+ private final HttpService httpService;
+
+ @Autowired
+ public CertificateAuthorityDriver(final DriverUtilities driverUtilities, final HttpService httpService) {
+ this.driverUtilities = driverUtilities;
+ this.httpService = httpService;
+ }
+
+ public CertificateSigningResponseDTO signCertificate(final CertificateSigningRequestDTO request) throws DriverUtilities.DriverException {
+ logger.traceEntry("signCertificate: {}", request);
+ Assert.notNull(request,"CertificateSigningRequestDTO must not be null");
+ final UriComponents uri = driverUtilities.findUriByOrchestrator(CoreSystemService.CERTIFICATE_AUTHORITY_SIGN_SERVICE);
+ final ResponseEntity httpResponse = httpService
+ .sendRequest(uri, HttpMethod.POST, CertificateSigningResponseDTO.class, request);
+ final CertificateSigningResponseDTO result = httpResponse.getBody();
+ return logger.traceExit(result);
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/drivers/DriverUtilities.java b/core-common/src/main/java/eu/arrowhead/common/drivers/DriverUtilities.java
new file mode 100644
index 000000000..1f4ebcf98
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/drivers/DriverUtilities.java
@@ -0,0 +1,329 @@
+package eu.arrowhead.common.drivers;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.CoreCommonConstants;
+import eu.arrowhead.common.CoreSystemRegistrationProperties;
+import eu.arrowhead.common.SSLProperties;
+import eu.arrowhead.common.Utilities;
+import eu.arrowhead.common.core.CoreSystemService;
+import eu.arrowhead.common.dto.shared.OrchestrationFlags;
+import eu.arrowhead.common.dto.shared.OrchestrationFormRequestDTO;
+import eu.arrowhead.common.dto.shared.OrchestrationResponseDTO;
+import eu.arrowhead.common.dto.shared.OrchestrationResultDTO;
+import eu.arrowhead.common.dto.shared.ServiceQueryFormDTO;
+import eu.arrowhead.common.dto.shared.ServiceQueryResultDTO;
+import eu.arrowhead.common.dto.shared.ServiceRegistryResponseDTO;
+import eu.arrowhead.common.dto.shared.ServiceSecurityType;
+import eu.arrowhead.common.dto.shared.SystemRequestDTO;
+import eu.arrowhead.common.dto.shared.SystemResponseDTO;
+import eu.arrowhead.common.exception.UnavailableServerException;
+import eu.arrowhead.common.http.HttpService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@Component
+public class DriverUtilities {
+
+ private final Logger logger = LogManager.getLogger(DriverUtilities.class);
+ private final CoreSystemRegistrationProperties coreSystemProps;
+ private final HttpService httpService;
+ private final SSLProperties sslProperties;
+
+ @Resource(name = CommonConstants.ARROWHEAD_CONTEXT)
+ private Map arrowheadContext;
+
+ @Autowired
+ public DriverUtilities(final CoreSystemRegistrationProperties coreSystemProps,
+ final HttpService httpService,
+ final SSLProperties sslProperties) {
+ super();
+ this.coreSystemProps = coreSystemProps;
+ this.httpService = httpService;
+ this.sslProperties = sslProperties;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public T getContext(final String key) {
+ return (T) arrowheadContext.get(key);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public T getContext(final String key, final T defaultValue) {
+ return (T) arrowheadContext.getOrDefault(key, defaultValue);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public boolean containsContext(final String key) {
+ return arrowheadContext.containsKey(key);
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public boolean pingService(final UriComponents echoUri) {
+ try {
+ httpService.sendRequest(echoUri, HttpMethod.GET, String.class);
+ logger.debug("Service at {} is accessible...", echoUri);
+ return true;
+ } catch (final Exception e) {
+ logger.debug("Service at {} is not accessible: {}: {}", echoUri, e.getClass().getSimpleName(), e.getMessage());
+ return false;
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public boolean pingService(final ServiceSecurityType securityType, final SystemResponseDTO system, final String systemUri) {
+ final UriComponents echoUri = createUri(securityType, system, systemUri + CommonConstants.ECHO_URI);
+ return pingService(echoUri);
+ }
+
+ public UriComponents findUriByContext(final CoreSystemService service) throws DriverException {
+ Assert.notNull(service, "CoreSystemService must not be null");
+ logger.debug("Searching for '{}' uri in context ...", service.getServiceDefinition());
+ final String key = getCoreSystemServiceKey(service);
+ if (containsContext(key)) {
+ final UriComponents serviceUri = getContext(key);
+ final UriComponents echoUri = createEchoUri(serviceUri);
+ if (pingService(echoUri)) {
+ return serviceUri;
+ }
+ }
+
+ throw DriverException.notFoundByArrowheadContext(service);
+ }
+
+ public ServiceRegistryResponseDTO findByServiceRegistry(final CoreSystemService service, final boolean pingTarget) throws DriverException {
+ Assert.notNull(service, "CoreSystemService must not be null");
+ logger.debug("findByServiceRegistry started...");
+ final UriComponents queryUri = getServiceRegistryQueryUri();
+ final ServiceQueryFormDTO form = new ServiceQueryFormDTO.Builder(service.getServiceDefinition())
+ .interfaces(getInterface())
+ .build();
+ final ResponseEntity response = httpService.sendRequest(queryUri, HttpMethod.POST, ServiceQueryResultDTO.class, form);
+ final ServiceQueryResultDTO result = response.getBody();
+
+ if (Objects.isNull(result) || Objects.isNull(result.getServiceQueryData()) || result.getServiceQueryData().isEmpty()) {
+ throw DriverException.notFoundByServiceRegistry(service);
+ }
+
+ final List serviceQueryData = result.getServiceQueryData();
+
+ for (int reverseIndex = serviceQueryData.size() - 1; reverseIndex >= 0; reverseIndex--) {
+ final ServiceRegistryResponseDTO entry = serviceQueryData.get(reverseIndex);
+ final UriComponents uri = createUri(entry);
+ if (!pingTarget) {
+ arrowheadContext.putIfAbsent(getCoreSystemServiceKey(service), uri);
+ return entry;
+ } else if (pingService(createEchoUri(uri))) {
+ arrowheadContext.putIfAbsent(getCoreSystemServiceKey(service), uri);
+ return entry;
+ }
+ }
+
+ throw DriverException.notFoundByServiceRegistry(service);
+ }
+
+ public UriComponents findUriByServiceRegistry(final CoreSystemService service) throws DriverException {
+
+ try {
+ return findUriByContext(service);
+ } catch (final DriverException e) {
+ logger.debug(e.getMessage());
+ }
+
+ logger.debug("findUriByServiceRegistry started...");
+ final ServiceRegistryResponseDTO entry = findByServiceRegistry(service, true);
+ return createUri(entry);
+ }
+
+ public UriComponents findUriByOrchestrator(final CoreSystemService service) throws DriverException {
+ Assert.notNull(service, "CoreSystemService must not be null");
+
+ try {
+ return findUriByContext(service);
+ } catch (final DriverException e) {
+ logger.debug(e.getMessage());
+ }
+
+ logger.debug("findUriByOrchestrator started...");
+
+ final UriComponents queryUri = getOrchestrationQueryUri();
+ final SystemRequestDTO requester = new SystemRequestDTO();
+ requester.setAddress(coreSystemProps.getCoreSystemDomainName());
+ requester.setPort(coreSystemProps.getCoreSystemDomainPort());
+ requester.setSystemName(coreSystemProps.getCoreSystemName());
+
+ final ServiceQueryFormDTO serviceQueryForm = new ServiceQueryFormDTO.Builder(service.getServiceDefinition())
+ .interfaces(getInterface())
+ .build();
+
+ final OrchestrationFormRequestDTO orchestrationForm = new OrchestrationFormRequestDTO
+ .Builder(requester)
+ .requestedService(serviceQueryForm)
+ .flag(OrchestrationFlags.Flag.OVERRIDE_STORE, true)
+ .build();
+
+ final ResponseEntity httpResponse = httpService
+ .sendRequest(queryUri, HttpMethod.POST, OrchestrationResponseDTO.class, orchestrationForm);
+ final OrchestrationResponseDTO response = httpResponse.getBody();
+
+ if (Objects.isNull(response) || Objects.isNull(response.getResponse()) || response.getResponse().isEmpty()) {
+ throw DriverException.notFoundByOrchestrator(service);
+ }
+
+ final List result = response.getResponse();
+
+ for (int reverseIndex = result.size() - 1; reverseIndex >= 0; reverseIndex--) {
+ final OrchestrationResultDTO entry = result.get(reverseIndex);
+ final UriComponents uri = createUri(entry);
+ if (pingService(createEchoUri(uri))) {
+ arrowheadContext.put(getCoreSystemServiceKey(service), uri);
+ return uri;
+ }
+ }
+
+ throw DriverException.notFoundByOrchestrator(service);
+ }
+
+ public UriComponents createUri(final ServiceRegistryResponseDTO entry) {
+ Assert.notNull(entry, "ServiceRegistryResponseDTO must not be null");
+ return createUri(entry.getSecure(), entry.getProvider(), entry.getServiceUri());
+ }
+
+ public UriComponents createUri(final OrchestrationResultDTO entry) {
+ Assert.notNull(entry, "OrchestrationResultDTO must not be null");
+ return createUri(entry.getSecure(), entry.getProvider(), entry.getServiceUri());
+ }
+
+ public UriComponents createUri(final ServiceSecurityType securityType, final SystemResponseDTO system, final String serviceUri) {
+ Assert.notNull(system, "SystemResponseDTO must not be null");
+ return Utilities.createURI(getScheme(securityType),
+ system.getAddress(),
+ system.getPort(),
+ serviceUri);
+ }
+
+ public UriComponents createEchoUri(final UriComponents serviceUri) {
+ Assert.notNull(serviceUri, "UriComponents must not be null");
+ return UriComponentsBuilder.newInstance()
+ .scheme(serviceUri.getScheme())
+ .host(serviceUri.getHost())
+ .port(serviceUri.getPort())
+ .path(extractSystemUriPath(serviceUri))
+ .path(CommonConstants.ECHO_URI)
+ .build();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public UriComponents createCustomUri(final UriComponents serviceUri, final String systemUri, final String postfix) {
+ Assert.notNull(serviceUri, "UriComponents must not be null");
+ return UriComponentsBuilder.newInstance()
+ .uriComponents(serviceUri)
+ .replacePath(systemUri)
+ .path(postfix)
+ .build();
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ public UriComponents createCustomUri(final UriComponents serviceUri, final String postfix) {
+ Assert.notNull(serviceUri, "UriComponents must not be null");
+ return UriComponentsBuilder.newInstance()
+ .uriComponents(serviceUri)
+ .path(extractSystemUriPath(serviceUri))
+ .path(postfix)
+ .build();
+ }
+
+ public String getCoreSystemServiceKey(final CoreSystemService service) {
+ Assert.notNull(service, "CoreSystemService must not be null");
+ return service.getServiceDefinition() + CoreCommonConstants.URI_SUFFIX;
+ }
+
+ protected UriComponents getServiceRegistryQueryUri() {
+ logger.debug("getServiceRegistryQueryUri started...");
+
+ if (arrowheadContext.containsKey(CoreCommonConstants.SR_QUERY_URI)) {
+ return (UriComponents) arrowheadContext.get(CoreCommonConstants.SR_QUERY_URI);
+ } else {
+ final String scheme = sslProperties.isSslEnabled() ? CommonConstants.HTTPS : CommonConstants.HTTP;
+ final String registerUriStr = CommonConstants.SERVICE_REGISTRY_URI + CommonConstants.OP_SERVICE_REGISTRY_QUERY_URI;
+ final UriComponents uri = Utilities.createURI(scheme, coreSystemProps.getServiceRegistryAddress(),
+ coreSystemProps.getServiceRegistryPort(), registerUriStr);
+ arrowheadContext.putIfAbsent(CoreCommonConstants.SR_QUERY_URI, uri);
+ return uri;
+ }
+ }
+
+ protected UriComponents getOrchestrationQueryUri() throws DriverException {
+ logger.debug("getOrchestrationQueryUri started...");
+ return findUriByServiceRegistry(CoreSystemService.ORCHESTRATION_SERVICE);
+ }
+
+ protected String getScheme() {
+ return sslProperties.isSslEnabled() ? CommonConstants.HTTPS : CommonConstants.HTTP;
+ }
+
+ protected String getScheme(final ServiceSecurityType securityType) {
+ return securityType == ServiceSecurityType.NOT_SECURE ? CommonConstants.HTTP : CommonConstants.HTTPS;
+ }
+
+ protected String getInterface() {
+ return sslProperties.isSslEnabled() ? CommonConstants.HTTP_SECURE_JSON : CommonConstants.HTTP_INSECURE_JSON;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ private String extractSystemUriPath(final UriComponents components) {
+ final List pathSegments = components.getPathSegments();
+ return pathSegments.isEmpty() ? components.getPath() : pathSegments.get(0);
+ }
+
+ public static class DriverException extends UnavailableServerException {
+
+ protected DriverException(final String message) {
+ super(message);
+ }
+
+ protected DriverException(final String message, final HttpStatus httpStatus) {
+ super(message, httpStatus.value());
+ }
+
+ protected DriverException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ protected DriverException(final String msg, final int errorCode, final String origin, final Throwable cause) {
+ super(msg, errorCode, origin, cause);
+ }
+
+ private static DriverException notFoundByArrowheadContext(final CoreSystemService service) {
+ return new DriverException("Unable to find " + service.getServiceDefinition() + " via ArrowheadContext", HttpStatus.SERVICE_UNAVAILABLE);
+ }
+
+ private static DriverException notFoundByServiceRegistry(final CoreSystemService service) {
+ return new DriverException("Unable to find " + service.getServiceDefinition() + " via ServiceRegistry", HttpStatus.SERVICE_UNAVAILABLE);
+ }
+
+ private static DriverException notFoundByOrchestrator(final CoreSystemService service) {
+ return new DriverException("Unable to find " + service.getServiceDefinition() + " via Orchestrator", HttpStatus.SERVICE_UNAVAILABLE);
+ }
+
+ public DriverException createExceptionWith(final HttpStatus errorCode, final String origin) {
+ return new DriverException(getMessage(), errorCode.value(), origin, getCause());
+ }
+
+ public DriverException createExceptionWith(final int errorCode, final String origin) {
+ return new DriverException(getMessage(), errorCode, origin, getCause());
+ }
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/drivers/OrchestrationDriver.java b/core-common/src/main/java/eu/arrowhead/common/drivers/OrchestrationDriver.java
new file mode 100644
index 000000000..e5c3ebdbd
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/drivers/OrchestrationDriver.java
@@ -0,0 +1,46 @@
+package eu.arrowhead.common.drivers;
+
+import eu.arrowhead.common.core.CoreSystemService;
+import eu.arrowhead.common.dto.shared.OrchestrationFormRequestDTO;
+import eu.arrowhead.common.dto.shared.OrchestrationResponseDTO;
+import eu.arrowhead.common.http.HttpService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.web.util.UriComponents;
+
+@Service
+public class OrchestrationDriver {
+
+ //=================================================================================================
+ // members
+ private final Logger logger = LogManager.getLogger(OrchestrationDriver.class);
+ private final DriverUtilities driverUtilities;
+ private final HttpService httpService;
+
+ @Autowired
+ public OrchestrationDriver(final DriverUtilities driverUtilities, final HttpService httpService) {
+ this.driverUtilities = driverUtilities;
+ this.httpService = httpService;
+ }
+
+ public UriComponents findCoreSystemService(final CoreSystemService service) throws DriverUtilities.DriverException {
+ logger.traceEntry("findCoreSystemService: {}", service);
+ Assert.notNull(service, "CoreSystemService must not be null");
+ return logger.traceExit(driverUtilities.findUriByOrchestrator(service));
+ }
+
+ public OrchestrationResponseDTO orchestrate(final OrchestrationFormRequestDTO request) throws DriverUtilities.DriverException {
+ logger.traceEntry("orchestrate: {}", request);
+ Assert.notNull(request, "OrchestrationFormRequestDTO must not be null");
+ final UriComponents uri = driverUtilities.getOrchestrationQueryUri();
+ final ResponseEntity httpResponse = httpService
+ .sendRequest(uri, HttpMethod.POST, OrchestrationResponseDTO.class, request);
+ final OrchestrationResponseDTO result = httpResponse.getBody();
+ return logger.traceExit(result);
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/drivers/ServiceRegistryDriver.java b/core-common/src/main/java/eu/arrowhead/common/drivers/ServiceRegistryDriver.java
new file mode 100644
index 000000000..a5ea526be
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/drivers/ServiceRegistryDriver.java
@@ -0,0 +1,80 @@
+package eu.arrowhead.common.drivers;
+
+import eu.arrowhead.common.CommonConstants;
+import eu.arrowhead.common.core.CoreSystemService;
+import eu.arrowhead.common.dto.shared.ServiceQueryFormDTO;
+import eu.arrowhead.common.dto.shared.ServiceQueryResultDTO;
+import eu.arrowhead.common.dto.shared.ServiceRegistryRequestDTO;
+import eu.arrowhead.common.dto.shared.ServiceRegistryResponseDTO;
+import eu.arrowhead.common.http.HttpService;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.List;
+
+@Service
+public class ServiceRegistryDriver {
+
+ private final Logger logger = LogManager.getLogger(ServiceRegistryDriver.class);
+ private final DriverUtilities driverUtilities;
+ private final HttpService httpService;
+
+ @Autowired
+ public ServiceRegistryDriver(final DriverUtilities driverUtilities, final HttpService httpService) {
+ this.driverUtilities = driverUtilities;
+ this.httpService = httpService;
+ }
+
+ public UriComponents findCoreSystemService(final CoreSystemService service) throws DriverUtilities.DriverException {
+ logger.traceEntry("findCoreSystemService:{}", service);
+ Assert.notNull(service, "CoreSystemService must not be null");
+ return logger.traceExit(driverUtilities.findUriByServiceRegistry(service));
+ }
+
+ public ServiceQueryResultDTO queryRegistry(final ServiceQueryFormDTO form) {
+ logger.traceEntry("queryRegistry: {}", form);
+ Assert.notNull(form, "ServiceQueryFormDTO must not be null");
+
+ final UriComponents uri = driverUtilities.getServiceRegistryQueryUri();
+ final ResponseEntity httpEntity = httpService
+ .sendRequest(uri, HttpMethod.POST, ServiceQueryResultDTO.class, form);
+ return logger.traceExit(httpEntity.getBody());
+ }
+
+ public ServiceRegistryResponseDTO registerService(final ServiceRegistryRequestDTO request) throws DriverUtilities.DriverException {
+ logger.traceEntry("registerService: {}", request);
+ Assert.notNull(request, "ServiceRegistryRequestDTO must not be null");
+
+ final UriComponents uri = driverUtilities.findUriByOrchestrator(CoreSystemService.SERVICE_REGISTRY_REGISTER_SERVICE);
+ final ResponseEntity httpEntity = httpService
+ .sendRequest(uri, HttpMethod.POST, ServiceRegistryResponseDTO.class, request);
+ return logger.traceExit(httpEntity.getBody());
+ }
+
+ public void unregisterService(final String serviceDefinition, final String providerName,
+ final String providerAddress, final int providerPort)
+ throws DriverUtilities.DriverException {
+
+ logger.traceEntry("unregisterService: {}, {}, {}, {}", serviceDefinition, providerName, providerAddress, providerPort);
+ final UriComponents uri = driverUtilities.findUriByOrchestrator(CoreSystemService.SERVICE_REGISTRY_UNREGISTER_SERVICE);
+ final MultiValueMap queryMap = new LinkedMultiValueMap<>(4);
+ queryMap.put(CommonConstants.OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_SERVICE_DEFINITION, List.of(serviceDefinition));
+ queryMap.put(CommonConstants.OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_SYSTEM_NAME, List.of(providerName));
+ queryMap.put(CommonConstants.OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_ADDRESS, List.of(providerAddress));
+ queryMap.put(CommonConstants.OP_SERVICE_REGISTRY_UNREGISTER_REQUEST_PARAM_PROVIDER_PORT, List.of(String.valueOf(providerPort)));
+
+ final UriComponents unregisterUri = UriComponentsBuilder.newInstance().uriComponents(uri)
+ .queryParams(queryMap).build();
+ httpService.sendRequest(unregisterUri, HttpMethod.POST, Void.class);
+ logger.traceExit();
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningRequestDTO.java b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningRequestDTO.java
new file mode 100644
index 000000000..780c30e81
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningRequestDTO.java
@@ -0,0 +1,27 @@
+package eu.arrowhead.common.dto.internal;
+
+import java.io.Serializable;
+
+import javax.validation.constraints.NotBlank;
+
+public class CertificateSigningRequestDTO implements Serializable {
+
+ private static final long serialVersionUID = -6810780579000655432L;
+
+ @NotBlank(message = "The encodedCSR is mandatory")
+ private String encodedCSR;
+
+ public CertificateSigningRequestDTO() {}
+
+ public CertificateSigningRequestDTO(String encodedCSR) {
+ this.encodedCSR = encodedCSR;
+ }
+
+ public String getEncodedCSR() {
+ return encodedCSR;
+ }
+
+ public void setEncodedCSR(String encodedCSR) {
+ this.encodedCSR = encodedCSR;
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningResponseDTO.java b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningResponseDTO.java
new file mode 100644
index 000000000..cb8726244
--- /dev/null
+++ b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CertificateSigningResponseDTO.java
@@ -0,0 +1,26 @@
+package eu.arrowhead.common.dto.internal;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class CertificateSigningResponseDTO implements Serializable {
+
+ private static final long serialVersionUID = -6810780579000655432L;
+
+ private List certificateChain;
+
+ public CertificateSigningResponseDTO() {
+ }
+
+ public CertificateSigningResponseDTO(List certificateChain) {
+ this.certificateChain = certificateChain;
+ }
+
+ public List getCertificateChain() {
+ return certificateChain;
+ }
+
+ public void setCertificateChain(List certificateChain) {
+ this.certificateChain = certificateChain;
+ }
+}
diff --git a/core-common/src/main/java/eu/arrowhead/common/dto/internal/CloudResponseDTO.java b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CloudResponseDTO.java
index 6d966922a..d8e1baa66 100644
--- a/core-common/src/main/java/eu/arrowhead/common/dto/internal/CloudResponseDTO.java
+++ b/core-common/src/main/java/eu/arrowhead/common/dto/internal/CloudResponseDTO.java
@@ -74,12 +74,15 @@ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
+
if (obj == null) {
return false;
}
+
if (getClass() != obj.getClass()) {
return false;
}
+
final CloudResponseDTO other = (CloudResponseDTO) obj;
return id == other.id;
diff --git a/core-common/src/main/java/eu/arrowhead/common/dto/internal/DTOConverter.java b/core-common/src/main/java/eu/arrowhead/common/dto/internal/DTOConverter.java
index d2cc2b0cf..fbc688cb6 100644
--- a/core-common/src/main/java/eu/arrowhead/common/dto/internal/DTOConverter.java
+++ b/core-common/src/main/java/eu/arrowhead/common/dto/internal/DTOConverter.java
@@ -1,18 +1,5 @@
package eu.arrowhead.common.dto.internal;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import eu.arrowhead.common.database.entity.System;
-import org.springframework.data.domain.Page;
-import org.springframework.util.Assert;
-
import eu.arrowhead.common.Utilities;
import eu.arrowhead.common.database.entity.AuthorizationInterCloud;
import eu.arrowhead.common.database.entity.AuthorizationInterCloudInterfaceConnection;
@@ -28,9 +15,13 @@
import eu.arrowhead.common.database.entity.Cloud;
import eu.arrowhead.common.database.entity.CloudGatekeeperRelay;
import eu.arrowhead.common.database.entity.CloudGatewayRelay;
+import eu.arrowhead.common.database.entity.Device;
+import eu.arrowhead.common.database.entity.DeviceRegistry;
import eu.arrowhead.common.database.entity.EventType;
import eu.arrowhead.common.database.entity.ForeignSystem;
import eu.arrowhead.common.database.entity.OrchestratorStore;
+import eu.arrowhead.common.database.entity.QoSIntraMeasurement;
+import eu.arrowhead.common.database.entity.QoSIntraPingMeasurement;
import eu.arrowhead.common.database.entity.Relay;
import eu.arrowhead.common.database.entity.ServiceDefinition;
import eu.arrowhead.common.database.entity.ServiceInterface;
@@ -38,11 +29,16 @@
import eu.arrowhead.common.database.entity.ServiceRegistryInterfaceConnection;
import eu.arrowhead.common.database.entity.Subscription;
import eu.arrowhead.common.database.entity.SubscriptionPublisherConnection;
+import eu.arrowhead.common.database.entity.System;
+import eu.arrowhead.common.database.entity.SystemRegistry;
import eu.arrowhead.common.dto.shared.ChoreographerActionPlanResponseDTO;
import eu.arrowhead.common.dto.shared.ChoreographerActionResponseDTO;
import eu.arrowhead.common.dto.shared.ChoreographerActionStepResponseDTO;
import eu.arrowhead.common.dto.shared.ChoreographerNextActionStepResponseDTO;
import eu.arrowhead.common.dto.shared.CloudRequestDTO;
+import eu.arrowhead.common.dto.shared.DeviceQueryResultDTO;
+import eu.arrowhead.common.dto.shared.DeviceRegistryResponseDTO;
+import eu.arrowhead.common.dto.shared.DeviceResponseDTO;
import eu.arrowhead.common.dto.shared.EventDTO;
import eu.arrowhead.common.dto.shared.EventPublishRequestDTO;
import eu.arrowhead.common.dto.shared.EventTypeResponseDTO;
@@ -53,705 +49,964 @@
import eu.arrowhead.common.dto.shared.ServiceRegistryResponseDTO;
import eu.arrowhead.common.dto.shared.SubscriptionListResponseDTO;
import eu.arrowhead.common.dto.shared.SubscriptionResponseDTO;
+import eu.arrowhead.common.dto.shared.SystemQueryResultDTO;
+import eu.arrowhead.common.dto.shared.SystemRegistryResponseDTO;
import eu.arrowhead.common.dto.shared.SystemRequestDTO;
import eu.arrowhead.common.dto.shared.SystemResponseDTO;
+import org.springframework.data.domain.Page;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
public class DTOConverter {
-
- //=================================================================================================
- // methods
-
- //-------------------------------------------------------------------------------------------------
- public static SystemResponseDTO convertSystemToSystemResponseDTO(final System system) {
- Assert.notNull(system, "System is null");
-
- return new SystemResponseDTO(system.getId(), system.getSystemName(), system.getAddress(), system.getPort(), system.getAuthenticationInfo(),
- Utilities.convertZonedDateTimeToUTCString(system.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(system.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SystemListResponseDTO convertSystemEntryListToSystemListResponseDTO(final Page systemEntryList) {
- Assert.notNull(systemEntryList, "systemEntryList is null");
-
- final long count = systemEntryList.getTotalElements();
- final SystemListResponseDTO systemListResponseDTO = new SystemListResponseDTO();
- systemListResponseDTO.setCount(count);
- systemListResponseDTO.setData(systemEntryListToSystemResponseDTOList(systemEntryList.getContent()));
-
- return systemListResponseDTO;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceDefinitionResponseDTO convertServiceDefinitionToServiceDefinitionResponseDTO(final ServiceDefinition serviceDefinition) {
- Assert.notNull(serviceDefinition, "ServiceDefinition is null");
-
- return new ServiceDefinitionResponseDTO(serviceDefinition.getId(), serviceDefinition.getServiceDefinition(), Utilities.convertZonedDateTimeToUTCString(serviceDefinition.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(serviceDefinition.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceDefinitionsListResponseDTO convertServiceDefinitionsListToServiceDefinitionListResponseDTO(final Page serviceDefinitions) {
- Assert.notNull(serviceDefinitions, "List of ServiceDefinition is null");
-
- final List serviceDefinitionDTOs = new ArrayList<>(serviceDefinitions.getNumberOfElements());
- for (final ServiceDefinition definition : serviceDefinitions) {
- serviceDefinitionDTOs.add(convertServiceDefinitionToServiceDefinitionResponseDTO(definition));
- }
-
- return new ServiceDefinitionsListResponseDTO(serviceDefinitionDTOs, serviceDefinitions.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceRegistryResponseDTO convertServiceRegistryToServiceRegistryResponseDTO(final ServiceRegistry entry) {
- Assert.notNull(entry, "SR entry is null.");
- Assert.notNull(entry.getServiceDefinition(), "Related service definition is null.");
- Assert.notNull(entry.getSystem(), "Related system is null.");
- Assert.notNull(entry.getInterfaceConnections(), "Related interface connection set is null.");
- Assert.isTrue(!entry.getInterfaceConnections().isEmpty(), "Related interface connection set is empty.");
-
- final ServiceDefinitionResponseDTO serviceDefinitionDTO = convertServiceDefinitionToServiceDefinitionResponseDTO(entry.getServiceDefinition());
- final SystemResponseDTO systemDTO = convertSystemToSystemResponseDTO(entry.getSystem());
-
- final ServiceRegistryResponseDTO dto = new ServiceRegistryResponseDTO();
- dto.setId(entry.getId());
- dto.setServiceDefinition(serviceDefinitionDTO);
- dto.setProvider(systemDTO);
- dto.setServiceUri(entry.getServiceUri());
- dto.setEndOfValidity(Utilities.convertZonedDateTimeToUTCString(entry.getEndOfValidity()));
- dto.setSecure(entry.getSecure());
- dto.setMetadata(Utilities.text2Map(entry.getMetadata()));
- dto.setVersion(entry.getVersion());
- dto.setInterfaces(collectInterfacesFromServiceRegistry(entry.getInterfaceConnections()));
- dto.setCreatedAt(Utilities.convertZonedDateTimeToUTCString(entry.getCreatedAt()));
- dto.setUpdatedAt(Utilities.convertZonedDateTimeToUTCString(entry.getUpdatedAt()));
-
- return dto;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceRegistryListResponseDTO convertServiceRegistryListToServiceRegistryListResponseDTO(final Page serviceRegistryEntries) {
- Assert.notNull(serviceRegistryEntries, "List of serviceRegistryEntries is null");
-
- final List serviceRegistryEntryDTOs = new ArrayList<>(serviceRegistryEntries.getNumberOfElements());
- for (final ServiceRegistry srEntry: serviceRegistryEntries) {
- serviceRegistryEntryDTOs.add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- }
-
- return new ServiceRegistryListResponseDTO(serviceRegistryEntryDTOs, serviceRegistryEntries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- @SuppressWarnings("squid:S3776")
- public static ServiceRegistryGroupedResponseDTO convertServiceRegistryDataToServiceRegistryGroupedResponseDTO(final Iterable serviceDefinitionEntries,
- final Iterable systemEntries,
- final Iterable interfaceEntries,
- final Iterable serviceRegistryEntries) {
- Assert.notNull(serviceDefinitionEntries, "List of serviceDefinitionEntries is null");
- Assert.notNull(systemEntries, "List of systemEntries is null");
- Assert.notNull(interfaceEntries, "List of interfaceEntries is null");
- Assert.notNull(serviceRegistryEntries, "List of serviceRegistryEntries is null");
-
- final Map servicesBySystemId = new HashMap<>();
- final Map servicesByServiceDefinition = new HashMap<>();
- final List servicesForAutoComplete = new ArrayList<>();
- final List systemsForAutoComplete = new ArrayList<>();
- final List interfacesForAutoComplete = new ArrayList<>();
-
- for (final ServiceRegistry srEntry: serviceRegistryEntries) {
- final long systemId = srEntry.getSystem().getId();
- final String systemName = srEntry.getSystem().getSystemName();
- final String systemAddress = srEntry.getSystem().getAddress();
- final int systemPort = srEntry.getSystem().getPort();
- final long serviceDefinitionId = srEntry.getServiceDefinition().getId();
- final String serviceDefinition = srEntry.getServiceDefinition().getServiceDefinition();
-
- // Creating ServicesGroupedBySystemsResponseDTO
- if (servicesBySystemId.containsKey(systemId)) {
- servicesBySystemId.get(systemId).getServices().add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- } else {
- final ServicesGroupedBySystemsResponseDTO dto = new ServicesGroupedBySystemsResponseDTO(systemId, systemName, systemAddress, systemPort, new ArrayList<>());
- dto.getServices().add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- servicesBySystemId.put(systemId, dto);
- }
-
- // Creating ServicesGroupedByServiceDefinitionResponseDTO
- if (servicesByServiceDefinition.containsKey(serviceDefinitionId)) {
- servicesByServiceDefinition.get(serviceDefinitionId).getProviderServices().add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- } else {
- final ServicesGroupedByServiceDefinitionResponseDTO dto = new ServicesGroupedByServiceDefinitionResponseDTO(serviceDefinitionId, serviceDefinition, new ArrayList<>());
- dto.getProviderServices().add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- servicesByServiceDefinition.put(serviceDefinitionId, dto);
- }
- }
-
- // Creating AutoCompleteDataResponseDTO
- for (final ServiceDefinition serviceDefinition : serviceDefinitionEntries) {
- servicesForAutoComplete.add(new IdValueDTO(serviceDefinition.getId(), serviceDefinition.getServiceDefinition()));
- }
- for (final System system : systemEntries) {
- systemsForAutoComplete.add(DTOConverter.convertSystemToSystemResponseDTO(system));
- }
- for (final ServiceInterface serviceInterface : interfaceEntries) {
- interfacesForAutoComplete.add(new IdValueDTO(serviceInterface.getId(), serviceInterface.getInterfaceName()));
- }
-
- final List servicesGroupedBySystemsResponseDTOList = new ArrayList<>();
- servicesGroupedBySystemsResponseDTOList.addAll(servicesBySystemId.values());
- final List servicesGroupedByServiceDefinitionResponseDTOList = new ArrayList<>();
- servicesGroupedByServiceDefinitionResponseDTOList.addAll(servicesByServiceDefinition.values());
- final AutoCompleteDataResponseDTO autoCompleteDataResponseDTO = new AutoCompleteDataResponseDTO(servicesForAutoComplete, systemsForAutoComplete, interfacesForAutoComplete);
-
- return new ServiceRegistryGroupedResponseDTO(servicesGroupedBySystemsResponseDTOList, servicesGroupedByServiceDefinitionResponseDTOList, autoCompleteDataResponseDTO);
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceInterfaceResponseDTO convertServiceInterfaceToServiceInterfaceResponseDTO(final ServiceInterface intf) {
- Assert.notNull(intf, "Interface entry is null.");
-
- return new ServiceInterfaceResponseDTO(intf.getId(), intf.getInterfaceName(), Utilities.convertZonedDateTimeToUTCString(intf.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(intf.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ServiceQueryResultDTO convertListOfServiceRegistryEntriesToServiceQueryResultDTO(final List entries, final int unfilteredHits) {
- final ServiceQueryResultDTO result = new ServiceQueryResultDTO();
-
- if (entries != null) {
- Assert.isTrue(unfilteredHits >= entries.size(), "Invalid value of unfiltered hits: " + unfilteredHits);
- result.setUnfilteredHits(unfilteredHits);
- for (final ServiceRegistry srEntry : entries) {
- result.getServiceQueryData().add(convertServiceRegistryToServiceRegistryResponseDTO(srEntry));
- }
- }
-
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static AuthorizationIntraCloudResponseDTO convertAuthorizationIntraCloudToAuthorizationIntraCloudResponseDTO(final AuthorizationIntraCloud entry) {
- Assert.notNull(entry, "AuthorizationIntraCloud is null");
- Assert.notNull(entry.getConsumerSystem(), "Consumer is null");
- Assert.notNull(entry.getProviderSystem(), "Provider is null");
- Assert.notNull(entry.getServiceDefinition(), "ServiceDefintion is null");
- Assert.notNull(entry.getInterfaceConnections(), "InterfaceConnections is null");
-
- return new AuthorizationIntraCloudResponseDTO(entry.getId(), convertSystemToSystemResponseDTO(entry.getConsumerSystem()), convertSystemToSystemResponseDTO(entry.getProviderSystem()),
- convertServiceDefinitionToServiceDefinitionResponseDTO(entry.getServiceDefinition()),
- collectInterfacesFromAuthorizationIntraCloud(entry.getInterfaceConnections()),
- Utilities.convertZonedDateTimeToUTCString(entry.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(entry.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static AuthorizationIntraCloudListResponseDTO convertAuthorizationIntraCloudListToAuthorizationIntraCloudListResponseDTO(final Page entries) {
- Assert.notNull(entries, "AuthorizationIntraCloudList is null");
-
- final List authorizationIntraCloudEntries = new ArrayList<>(entries.getNumberOfElements());
- for (final AuthorizationIntraCloud entry : entries) {
- authorizationIntraCloudEntries.add(convertAuthorizationIntraCloudToAuthorizationIntraCloudResponseDTO(entry));
- }
-
- return new AuthorizationIntraCloudListResponseDTO(authorizationIntraCloudEntries, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static TokenGenerationResponseDTO convertTokenMapToTokenGenerationResponseDTO(final Map> tokenMap) {
- Assert.notNull(tokenMap, "Token map is null.");
-
- final TokenGenerationResponseDTO result = new TokenGenerationResponseDTO();
- for (final Entry> entry : tokenMap.entrySet()) {
- result.getTokenData().add(new TokenDataDTO(entry.getKey(), entry.getValue()));
- }
-
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static CloudListResponseDTO convertCloudToCloudResponseDTO(final Page entries) {
- Assert.notNull(entries, "Cloud list is null" );
-
- final List cloudEntries = new ArrayList<>(entries.getNumberOfElements());
- for (final Cloud entry : entries) {
- cloudEntries.add(convertCloudToCloudResponseDTO(entry));
- }
-
- return new CloudListResponseDTO(cloudEntries, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static CloudResponseDTO convertCloudToCloudResponseDTO(final Cloud entity) {
- Assert.notNull(entity, "Cloud is null" );
- Assert.notNull(entity.getOperator(), "Cloud.operator is null" );
- Assert.notNull(entity.getName(), "Cloud.name is null" );
- Assert.notNull(entity.getCreatedAt(), "Cloud.createdAt is null" );
- Assert.notNull(entity.getUpdatedAt(), "Cloud.cpdatedAt is null" );
-
- return new CloudResponseDTO(entity.getId(), entity.getOperator(), entity.getName(), entity.getSecure(), entity.getNeighbor(), entity.getOwnCloud(), entity.getAuthenticationInfo(),
- Utilities.convertZonedDateTimeToUTCString(entity.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(entity.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static RelayListResponseDTO convertRelayListToRelayResponseListDTO(final Page entries) {
- Assert.notNull(entries, "Relay list is null" );
-
- final List relayEntries = new ArrayList<>(entries.getNumberOfElements());
- for (final Relay entry : entries) {
- relayEntries.add(convertRelayToRelayResponseDTO(entry));
- }
-
- return new RelayListResponseDTO(relayEntries, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static RelayResponseDTO convertRelayToRelayResponseDTO(final Relay entry) {
- Assert.notNull(entry, "Relay is null");
- Assert.notNull(entry.getAddress(), "Relay.address is null");
- Assert.notNull(entry.getType(), "Relay.type is null");
- Assert.notNull(entry.getCreatedAt(), "Relay.createdAt is null");
- Assert.notNull(entry.getCreatedAt(), "Relay.updatedAt is null");
-
- return new RelayResponseDTO(entry.getId(), entry.getAddress(), entry.getPort(), entry.getSecure(), entry.getExclusive(), entry.getType(),
- Utilities.convertZonedDateTimeToUTCString(entry.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(entry.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static List convertRelayListToRelayRequestDTOList(final List relays) {
- Assert.notNull(relays, "Relay list is null.");
-
- final List result = new ArrayList<>(relays.size());
- for (final Relay relay : relays) {
- result.add(convertRelayToRelayRequestDTO(relay));
- }
-
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static RelayRequestDTO convertRelayToRelayRequestDTO(final Relay relay) {
- Assert.notNull(relay, "relay is null.");
-
- return new RelayRequestDTO(relay.getAddress(), relay.getPort(), relay.getSecure(), relay.getExclusive(), relay.getType().name());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static CloudWithRelaysListResponseDTO convertCloudToCloudWithRelaysListResponseDTO(final Page entries) {
- Assert.notNull(entries, "Cloud list is null" );
-
- final List cloudWithRelaysResponseDTOList = new ArrayList<>(entries.getNumberOfElements());
- for (final Cloud cloud : entries) {
- Assert.notNull(cloud.getGatekeeperRelays(), "CloudGatekeeperRelay set is null");
- Assert.notNull(cloud.getGatewayRelays(), "CloudGatewayRelay set is null");
-
- cloudWithRelaysResponseDTOList.add(convertCloudToCloudWithRelaysResponseDTO(cloud));
- }
-
- return new CloudWithRelaysListResponseDTO(cloudWithRelaysResponseDTOList, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static CloudWithRelaysResponseDTO convertCloudToCloudWithRelaysResponseDTO(final Cloud cloud) {
- Assert.notNull(cloud, "Cloud is null");
- Assert.notNull(cloud.getGatekeeperRelays(), "Gatekeeper relays set is null");
- Assert.notNull(cloud.getGatewayRelays(), "Gateway relays set is null");
-
- final CloudResponseDTO cloudResponseDTO = convertCloudToCloudResponseDTO(cloud);
-
- final Set gatekeeperRelays = new HashSet<>();
- for (final CloudGatekeeperRelay conn : cloud.getGatekeeperRelays()) {
- gatekeeperRelays.add(conn.getRelay());
- }
-
- final Set gatewayRelays = new HashSet<>();
- for (final CloudGatewayRelay conn : cloud.getGatewayRelays()) {
- gatewayRelays.add(conn.getRelay());
- }
-
- final List gatekeeperRelayListDTO = new ArrayList<>(gatekeeperRelays.size());
- for (final Relay gatekeeperRelay : gatekeeperRelays) {
- gatekeeperRelayListDTO.add(convertRelayToRelayResponseDTO(gatekeeperRelay));
- }
-
- final List gatewayRelayListDTO = new ArrayList<>(gatewayRelays.size());
- for (final Relay gatewayRelay : gatewayRelays) {
- gatewayRelayListDTO.add(convertRelayToRelayResponseDTO(gatewayRelay));
- }
-
- return new CloudWithRelaysResponseDTO(cloudResponseDTO.getId(), cloudResponseDTO.getOperator(), cloudResponseDTO.getName(), cloudResponseDTO.getSecure(),
- cloudResponseDTO.getNeighbor(), cloudResponseDTO.getOwnCloud(), cloudResponseDTO.getAuthenticationInfo(),
- cloudResponseDTO.getCreatedAt(), cloudResponseDTO.getUpdatedAt(), gatekeeperRelayListDTO, gatewayRelayListDTO);
- }
-
- //-------------------------------------------------------------------------------------------------
- public static AuthorizationInterCloudListResponseDTO convertAuthorizationInterCloudListToAuthorizationInterCloudListResponseDTO(final Page entries) {
- Assert.notNull(entries, "AuthorizationInterCloudList is null");
-
- final List authorizationInterCloudEntries = new ArrayList<>(entries.getNumberOfElements());
- for (final AuthorizationInterCloud entry : entries) {
- authorizationInterCloudEntries.add(convertAuthorizationInterCloudToAuthorizationInterCloudResponseDTO(entry));
- }
-
- return new AuthorizationInterCloudListResponseDTO(authorizationInterCloudEntries, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static AuthorizationInterCloudResponseDTO convertAuthorizationInterCloudToAuthorizationInterCloudResponseDTO(final AuthorizationInterCloud entity) {
- Assert.notNull(entity, "AuthorizationInterCloud is null" );
- Assert.notNull(entity.getCloud(), "AuthorizationInterCloud.Cloud is null" );
- Assert.notNull(entity.getProvider(), "AuthorizationInterCloud.Provider is null");
- Assert.notNull(entity.getServiceDefinition(), "AuthorizationInterCloud.ServiceDefinition is null" );
- Assert.notNull(entity.getInterfaceConnections(), "AuthorizationInterCloud.InterfaceConnections is null");
- Assert.notNull(entity.getCreatedAt(), "AuthorizationInterCloud.CreatedAt is null" );
- Assert.notNull(entity.getUpdatedAt(), "AuthorizationInterCloud.UpdatedAt is null" );
-
- return new AuthorizationInterCloudResponseDTO(entity.getId(), convertCloudToCloudResponseDTO(entity.getCloud()), convertSystemToSystemResponseDTO(entity.getProvider()),
- convertServiceDefinitionToServiceDefinitionResponseDTO(entity.getServiceDefinition()),
- collectInterfacesFromAuthorizationInterCloud(entity.getInterfaceConnections()),
- Utilities.convertZonedDateTimeToUTCString(entity.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(entity.getUpdatedAt()));
-
- }
-
- //-------------------------------------------------------------------------------------------------
- public static OrchestratorStoreResponseDTO convertOrchestratorStoreToOrchestratorStoreResponseDTO(final OrchestratorStore entity, final SystemResponseDTO providerSystem,
- final CloudResponseDTO providerCloud) {
- Assert.notNull(entity, "OrchestratorStore is null");
- Assert.notNull(providerSystem, "OrchestratorStore.ProviderSystem is null");
- Assert.notNull(entity.getCreatedAt(), "OrchestratorStore.CreatedAt is null");
- Assert.notNull(entity.getUpdatedAt(), "OrchestratorStore.UpdatedAt is null");
-
- return new OrchestratorStoreResponseDTO(entity.getId(), convertServiceDefinitionToServiceDefinitionResponseDTO(entity.getServiceDefinition()),
- convertSystemToSystemResponseDTO(entity.getConsumerSystem()), entity.isForeign(), providerSystem, providerCloud,
- convertServiceInterfaceToServiceInterfaceResponseDTO(entity.getServiceInterface()), entity.getPriority(), Utilities.text2Map(entity.getAttribute()),
- Utilities.convertZonedDateTimeToUTCString(entity.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(entity.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static OrchestratorStoreListResponseDTO convertOrchestratorStoreEntryListToOrchestratorStoreListResponseDTO(final List entries) {
- Assert.notNull(entries, "OrchestratorStoreList is null");
-
- return new OrchestratorStoreListResponseDTO(entries, entries.size());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static OrchestratorStoreListResponseDTO convertOrchestratorStoreEntryListToOrchestratorStoreListResponseDTO(final List entries, final long totalElements) {
- Assert.notNull(entries, "OrchestratorStoreList is null");
-
- return new OrchestratorStoreListResponseDTO(entries, totalElements);
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SystemRequestDTO convertSystemToSystemRequestDTO(final System system) {
- Assert.notNull(system, "System is null");
-
- final SystemRequestDTO systemRequestDTO = new SystemRequestDTO();
- systemRequestDTO.setAddress(system.getAddress());
- systemRequestDTO.setSystemName(system.getSystemName());
- systemRequestDTO.setPort(system.getPort());
- systemRequestDTO.setAuthenticationInfo(systemRequestDTO.getAuthenticationInfo());
-
- return systemRequestDTO;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SystemRequestDTO convertSystemResponseDTOToSystemRequestDTO(final SystemResponseDTO response) {
- Assert.notNull(response, "response is null");
-
- final SystemRequestDTO result = new SystemRequestDTO();
- result.setSystemName(response.getSystemName());
- result.setAddress(response.getAddress());
- result.setPort(response.getPort());
- result.setAuthenticationInfo(response.getAuthenticationInfo());
-
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static PreferredProviderDataDTO convertForeignOrchestratorStoreResponseDTOToPreferredProviderDataDTO(final OrchestratorStoreResponseDTO orchestratorStoreResponseDTO) {
- Assert.notNull(orchestratorStoreResponseDTO, "orchestratorStoreResponseDTO is null");
- Assert.isTrue(orchestratorStoreResponseDTO.getForeign(), "orchestratorStoreResponseDTO is not foreign");
- Assert.notNull(orchestratorStoreResponseDTO.getProviderSystem(), "orchestratorStoreResponseDTO.ProviderSystem is null");
- Assert.notNull(orchestratorStoreResponseDTO.getProviderCloud(), "orchestratorStoreResponseDTO.ProviderCloud is null");
-
- final PreferredProviderDataDTO preferredProviderDataDTO = new PreferredProviderDataDTO();
-
- final SystemRequestDTO providerSystemRequestDTO = DTOConverter.convertSystemResponseDTOToSystemRequestDTO(orchestratorStoreResponseDTO.getProviderSystem());
- preferredProviderDataDTO.setProviderSystem(providerSystemRequestDTO);
-
- final CloudRequestDTO cloudRequestDTO = convertCloudResponseDTOToCloudRequestDTO(orchestratorStoreResponseDTO.getProviderCloud());
- preferredProviderDataDTO.setProviderCloud(cloudRequestDTO);
-
- return preferredProviderDataDTO;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static CloudRequestDTO convertCloudResponseDTOToCloudRequestDTO(final CloudResponseDTO cloudResponseDTO) {
- Assert.notNull(cloudResponseDTO, "cloudResponseDTO is null");
- Assert.notNull(cloudResponseDTO.getOperator(), "cloudResponseDTO.Operator is null");
- Assert.notNull(cloudResponseDTO.getName(), "cloudResponseDTO.Name is null");
-
- final CloudRequestDTO cloudRequestDTO = new CloudRequestDTO();
-
- cloudRequestDTO.setOperator(cloudResponseDTO.getOperator());
- cloudRequestDTO.setName(cloudResponseDTO.getName());
- cloudRequestDTO.setSecure(cloudResponseDTO.getSecure());
- cloudRequestDTO.setNeighbor(cloudResponseDTO.getNeighbor());
- cloudRequestDTO.setAuthenticationInfo(cloudResponseDTO.getAuthenticationInfo());
-
- return cloudRequestDTO;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SubscriptionResponseDTO convertSubscriptionToSubscriptionResponseDTO(final Subscription subscription) {
- Assert.notNull(subscription, "subscription is null");
- Assert.notNull(subscription.getSubscriberSystem(), "subscription.ConsumerSystem is null");
- Assert.notNull(subscription.getEventType(), "subscription.EventType is null");
- Assert.notNull(subscription.getNotifyUri(), "subscription.NotifyUri is null");
- Assert.notNull(subscription.getCreatedAt(), "subscription.CreatedAt is null");
- Assert.notNull(subscription.getUpdatedAt(), "subscription.UpdatedAt is null");
-
- final String startDate = subscription.getStartDate() == null ? null : Utilities.convertZonedDateTimeToUTCString(subscription.getStartDate());
- final String endDate = subscription.getEndDate() == null ? null : Utilities.convertZonedDateTimeToUTCString(subscription.getEndDate());
-
- final Set sources = collectPublishersFromSubscription(subscription.getPublisherConnections());
-
- return new SubscriptionResponseDTO(subscription.getId(), convertEventTypeToEventTypeResponseDTO(subscription.getEventType()),
- convertSystemToSystemResponseDTO(subscription.getSubscriberSystem()), Utilities.text2Map(subscription.getFilterMetaData()), subscription.getNotifyUri(),
- subscription.isMatchMetaData(), startDate, endDate, sources, Utilities.convertZonedDateTimeToUTCString(subscription.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(subscription.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SubscriptionResponseDTO convertSubscriptionToOnlyAuthorizedSourcesSubscriptionResponseDTO(final Subscription subscription) {
- Assert.notNull(subscription, "subscription is null");
- Assert.notNull(subscription.getSubscriberSystem(), "subscription.ConsumerSystem is null");
- Assert.notNull(subscription.getEventType(), "subscription.EventType is null");
- Assert.notNull(subscription.getNotifyUri(), "subscription.NotifyUri is null");
- Assert.notNull(subscription.getCreatedAt(), "subscription.CreatedAt is null");
- Assert.notNull(subscription.getUpdatedAt(), "subscription.UpdatedAt is null");
-
- final String startDate = subscription.getStartDate() == null ? null : Utilities.convertZonedDateTimeToUTCString(subscription.getStartDate());
- final String endDate = subscription.getEndDate() == null ? null : Utilities.convertZonedDateTimeToUTCString(subscription.getEndDate());
-
- final Set sources = collectAuthorizedPublishersFromSubscription(subscription.getPublisherConnections());
-
- return new SubscriptionResponseDTO(subscription.getId(), convertEventTypeToEventTypeResponseDTO(subscription.getEventType()),
- convertSystemToSystemResponseDTO(subscription.getSubscriberSystem()), Utilities.text2Map(subscription.getFilterMetaData()), subscription.getNotifyUri(),
- subscription.isMatchMetaData(), startDate, endDate, sources, Utilities.convertZonedDateTimeToUTCString(subscription.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(subscription.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static EventTypeResponseDTO convertEventTypeToEventTypeResponseDTO(final EventType eventType) {
- Assert.notNull(eventType, "eventType is null");
- Assert.notNull(eventType.getEventTypeName(), "eventType.EvenTypeName is null");
-
- return new EventTypeResponseDTO(eventType.getId(), eventType.getEventTypeName(), Utilities.convertZonedDateTimeToUTCString(eventType.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(eventType.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static EventDTO convertEventPublishRequestDTOToEventDTO(final EventPublishRequestDTO eventPublishRequestDTO) {
- Assert.notNull(eventPublishRequestDTO, "eventPublishRequestDTO is null");
- Assert.notNull(eventPublishRequestDTO.getEventType(), "eventPublishRequestDTO.EvenType is null");
- Assert.notNull(eventPublishRequestDTO.getPayload(), "eventPublishRequestDTO.Payload is null");
- Assert.notNull(eventPublishRequestDTO.getTimeStamp(), "eventPublishRequestDTO.TimeStamp is null");
-
- return new EventDTO(eventPublishRequestDTO.getEventType(), eventPublishRequestDTO.getMetaData(), eventPublishRequestDTO.getPayload(), eventPublishRequestDTO.getTimeStamp());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SubscriptionListResponseDTO convertSubscriptionPageToSubscriptionListResponseDTO(final Page entries) {
- Assert.notNull(entries, "SubscriptionPage is null" );
-
- final List subscriptionEntries = new ArrayList<>(entries.getNumberOfElements());
- for (final Subscription entry : entries) {
- subscriptionEntries.add(convertSubscriptionToSubscriptionResponseDTO(entry));
- }
-
- return new SubscriptionListResponseDTO(subscriptionEntries, entries.getTotalElements());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static RelayRequestDTO convertRelayResponseDTOToRelayRequestDTO(final RelayResponseDTO response) {
- Assert.notNull(response, "Relay response is null.");
-
- return new RelayRequestDTO(response.getAddress(), response.getPort(), response.isSecure(), response.isExclusive(), response.getType().name());
- }
-
- //-------------------------------------------------------------------------------------------------
- public static SystemResponseDTO convertForeignSystemToSystemResponseDTO(final ForeignSystem foreignSystem) {
- Assert.notNull(foreignSystem, "ForeignSystem is null");
-
- return new SystemResponseDTO(foreignSystem.getId(), foreignSystem.getSystemName(), foreignSystem.getAddress(), foreignSystem.getPort(), foreignSystem.getAuthenticationInfo(),
- Utilities.convertZonedDateTimeToUTCString(foreignSystem.getCreatedAt()), Utilities.convertZonedDateTimeToUTCString(foreignSystem.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ChoreographerActionStepResponseDTO convertChoreographerActionStepToChoreographerActionStepResponseDTO(final ChoreographerActionStep actionStep) {
- Assert.notNull(actionStep, "ChoreographerActionStep is null.");
-
- return new ChoreographerActionStepResponseDTO(actionStep.getId(), actionStep.getName(),
- collectServiceDefinitionsFromChoreographerActionStep(actionStep.getActionStepServiceDefinitionConnections()),
- collectChoreographerNextActionStepsFromChoreographerActionStep(actionStep.getNextActionSteps()),
- Utilities.convertZonedDateTimeToUTCString(actionStep.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(actionStep.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static List collectChoreographerActionStepsFromChoreographerAction(final Set actionStepConnections) {
- Assert.notNull(actionStepConnections, "ActionStepConnectionSet is null.");
-
- final List result = new ArrayList<>(actionStepConnections.size());
- for (final ChoreographerActionActionStepConnection conn : actionStepConnections) {
- result.add(convertChoreographerActionStepToChoreographerActionStepResponseDTO(conn.getActionStepEntry()));
- }
-
- result.sort(Comparator.comparing(ChoreographerActionStepResponseDTO::getId));
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static String collectChoreographerNextActionNameFromChoreographerAction(final ChoreographerAction nextAction) {
- if (nextAction != null) {
- return nextAction.getActionName();
- }
-
- return null;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ChoreographerActionResponseDTO convertChoreographerActionToChoreographerActionResponseDTO(final ChoreographerAction actionEntry) {
- Assert.notNull(actionEntry, "ChoreographerAction entry is null.");
-
- return new ChoreographerActionResponseDTO(actionEntry.getId(), actionEntry.getActionName(),
- collectChoreographerNextActionNameFromChoreographerAction(actionEntry.getNextAction()),
- collectChoreographerActionStepsFromChoreographerAction(actionEntry.getActionActionStepConnections()),
- Utilities.convertZonedDateTimeToUTCString(actionEntry.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(actionEntry.getUpdatedAt()));
- }
-
- //-------------------------------------------------------------------------------------------------
- public static List collectChoreographerActionsFromChoreographerActionPlan(final Set actionConnections) {
- Assert.notNull(actionConnections, "ActionConnectionsSet is null.");
-
- final List result = new ArrayList<>(actionConnections.size());
- for (final ChoreographerActionPlanActionConnection conn : actionConnections) {
- result.add(convertChoreographerActionToChoreographerActionResponseDTO(conn.getActionEntry()));
- }
-
- result.sort(Comparator.comparing(ChoreographerActionResponseDTO::getId));
- return result;
- }
-
- //-------------------------------------------------------------------------------------------------
- public static ChoreographerActionPlanResponseDTO convertChoreographerActionPlanToChoreographerActionPlanResponseDTO(final ChoreographerActionPlan actionPlanEntry) {
- Assert.notNull(actionPlanEntry, "ChoreographerActionPlan entry is null.");
-
- return new ChoreographerActionPlanResponseDTO(actionPlanEntry.getId(), actionPlanEntry.getActionPlanName(),
- collectChoreographerActionsFromChoreographerActionPlan(actionPlanEntry.getActionPlanActionConnections()),
- Utilities.convertZonedDateTimeToUTCString(actionPlanEntry.getCreatedAt()),
- Utilities.convertZonedDateTimeToUTCString(actionPlanEntry.getUpdatedAt()));
- }
-
- //=================================================================================================
- // assistant methods
-
- //-------------------------------------------------------------------------------------------------
- private DTOConverter() {
- throw new UnsupportedOperationException();
- }
-
- //-------------------------------------------------------------------------------------------------
- private static List systemEntryListToSystemResponseDTOList(final List systemList) {
- final List systemResponseDTOs = new ArrayList<>(systemList.size());
-
- for (final System system : systemList) {
- systemResponseDTOs.add(convertSystemToSystemResponseDTO(system));
- }
-
- return systemResponseDTOs;
- }
-
- //-------------------------------------------------------------------------------------------------
- private static List collectInterfacesFromServiceRegistry(final Set interfaceConnections) {
- final List