You will be provided with a partial code base and an issue statement explaining a problem to resolve.
<issue>
Open MinIO read access
## Current Implementation
Receiving files from local MinIO requires access key and secret key.

## Suggested Enhancement
Add a security policy to the MinIO configuration to only protect write access, but have open read access.

## Expected Benefits
Mobile colleagues can use local setup for end-to-end testing.

</issue>

<code>
[start of README.md]
1 <h1 align="center">
2     Corona-Warn-App Server
3 </h1>
4 
5 <p align="center">
6     <a href="https://github.com/corona-warn-app/cwa-server/commits/" title="Last Commit"><img src="https://img.shields.io/github/last-commit/corona-warn-app/cwa-server?style=flat"></a>
7     <a href="https://github.com/corona-warn-app/cwa-server/issues" title="Open Issues"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-server?style=flat"></a>
8     <a href="https://circleci.com/gh/corona-warn-app/cwa-server" title="Build Status"><img src="https://circleci.com/gh/corona-warn-app/cwa-server.svg?style=shield&circle-token=4ab059989d10709df19eb4b98ab7c121a25e981a"></a>
9         <a href="https://sonarcloud.io/dashboard?id=corona-warn-app_cwa-server" title="Quality Gate"><img src="https://sonarcloud.io/api/project_badges/measure?project=corona-warn-app_cwa-server&metric=alert_status"></a>    
10         <a href="https://sonarcloud.io/component_measures?id=corona-warn-app_cwa-server&metric=Coverage&view=list" title="Coverage"><img src="https://sonarcloud.io/api/project_badges/measure?project=corona-warn-app_cwa-server&metric=coverage"></a>
11     <a href="https://github.com/corona-warn-app/cwa-server/blob/master/LICENSE" title="License"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg?style=flat"></a>
12 </p>
13 
14 <p align="center">
15   <a href="#development">Development</a> •
16   <a href="#service-apis">Service APIs</a> •
17   <a href="#documentation">Documentation</a> •
18   <a href="#support-and-feedback">Support</a> •
19   <a href="#how-to-contribute">Contribute</a> •
20   <a href="#contributors">Contributors</a> •
21   <a href="#repositories">Repositories</a> •
22   <a href="#licensing">Licensing</a>
23 </p>
24 
25 The goal of this project is to develop the official Corona-Warn-App for Germany based on the exposure notification API from [Apple](https://www.apple.com/covid19/contacttracing/) and [Google](https://www.google.com/covid19/exposurenotifications/). The apps (for both iOS and Android) use Bluetooth technology to exchange anonymous encrypted data with other mobile phones (on which the app is also installed) in the vicinity of an app user's phone. The data is stored locally on each user's device, preventing authorities or other parties from accessing or controlling the data. This repository contains the **implementation of the server for encryption keys** for the Corona-Warn-App. This implementation is still a **work in progress**, and the code it contains is currently alpha-quality code.
26 
27 In this documentation, Corona-Warn-App services are also referred to as CWA services.
28 
29 ## Architecture Overview
30 
31 You can find the architecture overview [here](/docs/architecture-overview.md), which will give you
32 a good starting point in how the backend services interact with other services, and what purpose
33 they serve.
34 
35 ## Development
36 
37 After you've checked out this repository, you can run the application in one of the following ways:
38 
39 * As a [Docker](https://www.docker.com/)-based deployment on your local machine. You can run either:
40   * Single components using the respective Dockerfile or
41   * The full backend using the Docker Compose (which is considered the most convenient way)
42 * As a [Maven](https://maven.apache.org)-based build on your local machine.
43   If you want to develop something in a single component, this approach is preferable.
44 
45 ### Docker-Based Deployment
46 
47 If you want to use Docker-based deployment, you need to install Docker on your local machine. For more information about downloading and installing Docker, see the [official Docker documentation](https://docs.docker.com/get-docker/).
48 
49 #### Running the Full CWA Backend Using Docker Compose
50 
51 For your convenience, a full setup including the generation of test data has been prepared using [Docker Compose](https://docs.docker.com/compose/reference/overview/). To build the backend services, run ```docker-compose build``` in the repository's root directory. A default configuration file can be found under ```.env```in the root folder of the repository. The default values for the local Postgres and MinIO-build should be changed in this file before docker-compose is run.
52 
53 Once the services are built, you can start the whole backend using ```docker-compose up```.
54 The distribution service runs once and then finishes. If you want to trigger additional distribution runs, run ```docker-compose start distribution```.
55 
56 The docker-compose contains the following services:
57 
58 Service       | Description | Endpoint and Default Credentials
59 --------------|-------------|-----------
60 submission    | The Corona-Warn-App submission service                                            | http://localhost:8080 
61 distribution  | The Corona-Warn-App distribution service                                          | NO ENDPOINT
62 postgres      | A [postgres] database installation                                                | postgres:5432 <br> Username: postgres <br> Password: postgres
63 pgadmin       | A [pgadmin](https://www.pgadmin.org/) installation for the postgres database      | http://localhost:8081 <br> Username: user@domain.com <br> Password: password
64 minio         | [MinIO] is an S3-compliant object store                                           | http://localhost:8082/ <br> Access key: minioadmin <br> Secret key: minioadmin
65 
66 #### Running Single CWA Services Using Docker
67 
68 If you would like to build and run a single CWA service, it's considered easiest to run them in a Docker environment. You can do this using the script provided in the respective CWA service directory. The Docker script first builds the CWA service and then creates an image for the runtime, which means that there are no additional dependencies for you to install.
69 
70 To build and run the distribution service, run the following command:
71 
72 ```bash
73 ./services/distribution/build_and_run.sh
74 ```
75 
76 To build and run the submission service, run the following command:
77 
78 ```bash
79 ./services/submission/build_and_run.sh
80 ```
81 
82 The submission service is available on [localhost:8080](http://localhost:8080 ).
83 
84 ### Maven-Based Build
85 
86 If you want to actively develop in one of the CWA services, the Maven-based runtime is most suitable.
87 To prepare your machine to run the CWA project locally, we recommend that you first ensure that you've installed the following:
88 
89 * Minimum JDK Version 11: [OpenJDK](https://openjdk.java.net/) / [SapMachine](https://sap.github.io/SapMachine/)
90 * [Maven 3.6](https://maven.apache.org/)
91 * [Postgres]
92 * [MinIO]
93 
94 #### Configure
95 
96 After you made sure that the specified dependencies are running, configure them in the respective configuration files.
97 
98 * Configure the Postgres connection in the [submission config](./services/submission/src/main/resources/application.properties) and in the [distribution config](./services/distribution/src/main/resources/application.properties)
99 * Configure the S3 compatible object storage in the [distribution config](./services/distribution/src/main/resources/application.properties)
100 
101 #### Build
102 
103 After you've checked out the repository, to build the project, run ```mvn install``` in your base directory.
104 
105 #### Run
106 
107 Navigate to the service you want to start and run the spring-boot:run target. The configured Postgres and the configured S3 compliant object storage are used as default. When you start the submission service, the endpoint is available on your local port 8080.
108 
109 If you want to start the submission service, for example, you start it as follows:
110 
111 ```bash
112   cd services/submission/
113   mvn spring-boot:run
114 ```
115 
116 #### Debugging
117 
118 To enable the `DEBUG` log level, you can run the application using the Spring `dev` profile.
119 
120 ```bash
121 mvn spring-boot:run -Dspring-boot.run.profiles=dev
122 ```
123 
124 To be able to set breakpoints (e.g. in IntelliJ), it may be necessary to use the ```-Dspring-boot.run.fork=false``` parameter.
125 
126 ## Service APIs
127 
128 The API that is being exposed by the backend services is documented in an [OpenAPI](https://www.openapis.org/) specification. The specification files are available at the following locations:
129 
130 Service      | OpenAPI Specification
131 -------------|-------------
132 Submission Service        | https://github.com/corona-warn-app/cwa-server/raw/master/services/submission/api_v1.json
133 Distribution Service      | https://github.com/corona-warn-app/cwa-server/raw/master/services/distribution/api_v1.json
134 
135 ## Documentation
136 
137 The full documentation for the Corona-Warn-App can be found in the [cwa-documentation](https://github.com/corona-warn-app/cwa-documentation) repository. The documentation repository contains technical documents, architecture information, and whitepapers related to this implementation.
138 
139 ## Support and Feedback
140 
141 The following channels are available for discussions, feedback, and support requests:
142 
143 | Type                     | Channel                                                |
144 | ------------------------ | ------------------------------------------------------ |
145 | **General Discussion**   | <a href="https://github.com/corona-warn-app/cwa-documentation/issues/new/choose" title="General Discussion"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-documentation/question.svg?style=flat-square"></a> </a>   |
146 | **Concept Feedback**    | <a href="https://github.com/corona-warn-app/cwa-documentation/issues/new/choose" title="Open Concept Feedback"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-documentation/architecture.svg?style=flat-square"></a>  |
147 | **Backend Issue**    | <a href="https://github.com/corona-warn-app/cwa-server/issues/new/choose" title="Open Backend Issue"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-server?style=flat-square"></a>  |
148 | **Other Requests**    | <a href="mailto:corona-warn-app.opensource@sap.com" title="Email CWD Team"><img src="https://img.shields.io/badge/email-CWD%20team-green?logo=mail.ru&style=flat-square&logoColor=white"></a>   |
149 
150 ## How to Contribute
151 
152 Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](./CONTRIBUTING.md). By participating in this project, you agree to abide by its [Code of Conduct](./CODE_OF_CONDUCT.md) at all times.
153 
154 ## Contributors
155 
156 The German government has asked SAP and Deutsche Telekom to develop the Corona-Warn-App for Germany as open source software. Deutsche Telekom is providing the network and mobile technology and will operate and run the backend for the app in a safe, scalable and stable manner. SAP is responsible for the app development, its framework and the underlying platform. Therefore, development teams of SAP and Deutsche Telekom are contributing to this project. At the same time our commitment to open source means that we are enabling -in fact encouraging- all interested parties to contribute and become part of its developer community.
157 
158 ## Repositories
159 
160 The following public repositories are currently available for the Corona-Warn-App:
161 
162 | Repository          | Description                                                           |
163 | ------------------- | --------------------------------------------------------------------- |
164 | [cwa-documentation] | Project overview, general documentation, and white papers            |
165 | [cwa-server]        | Backend implementation for the Apple/Google exposure notification API|
166 
167 [cwa-documentation]: https://github.com/corona-warn-app/cwa-documentation
168 [cwa-server]: https://github.com/corona-warn-app/cwa-server
169 [Postgres]: https://www.postgresql.org/
170 [MinIO]: https://min.io/
171 [HSQLDB]: http://hsqldb.org/
172 
173 ## Licensing
174 
175 Copyright (c) 2020 SAP SE or an SAP affiliate company.
176 
177 Licensed under the **Apache License, Version 2.0** (the "License"); you may not use this file except in compliance with the License. 
178 
179 You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.
180 
181 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the [LICENSE](./LICENSE) for the specific language governing permissions and limitations under the License.
182 
[end of README.md]
[start of .env]
1 # This file contains simple default values for the deployment through Docker Compose
2 # Please change these default values before running docker-compose
3 
4 # Docker Compose Postgres settings
5 POSTGRES_DB=cwa
6 POSTGRES_USER=postgres
7 POSTGRES_PASSWORD=postgres
8 
9 # Docker Compose PgAdmin settings
10 PGADMIN_DEFAULT_EMAIL=user@domain.com
11 PGADMIN_DEFAULT_PASSWORD=password
12 
13 # Docker Compose MinIO settings
14 MINIO_ACCESS_KEY=minioadmin
15 MINIO_SECRET_KEY=minioadmin
16 
17 # Docker Compose Secrets settings
18 SECRET_PRIVATE=file:/secrets/private.pem
19 SECRET_CERTIFICATE=file:/secrets/certificate.crt
20 
[end of .env]
[start of /dev/null]
1 
[end of /dev/null]
[start of README.md]
1 <h1 align="center">
2     Corona-Warn-App Server
3 </h1>
4 
5 <p align="center">
6     <a href="https://github.com/corona-warn-app/cwa-server/commits/" title="Last Commit"><img src="https://img.shields.io/github/last-commit/corona-warn-app/cwa-server?style=flat"></a>
7     <a href="https://github.com/corona-warn-app/cwa-server/issues" title="Open Issues"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-server?style=flat"></a>
8     <a href="https://circleci.com/gh/corona-warn-app/cwa-server" title="Build Status"><img src="https://circleci.com/gh/corona-warn-app/cwa-server.svg?style=shield&circle-token=4ab059989d10709df19eb4b98ab7c121a25e981a"></a>
9         <a href="https://sonarcloud.io/dashboard?id=corona-warn-app_cwa-server" title="Quality Gate"><img src="https://sonarcloud.io/api/project_badges/measure?project=corona-warn-app_cwa-server&metric=alert_status"></a>    
10         <a href="https://sonarcloud.io/component_measures?id=corona-warn-app_cwa-server&metric=Coverage&view=list" title="Coverage"><img src="https://sonarcloud.io/api/project_badges/measure?project=corona-warn-app_cwa-server&metric=coverage"></a>
11     <a href="https://github.com/corona-warn-app/cwa-server/blob/master/LICENSE" title="License"><img src="https://img.shields.io/badge/License-Apache%202.0-green.svg?style=flat"></a>
12 </p>
13 
14 <p align="center">
15   <a href="#development">Development</a> •
16   <a href="#service-apis">Service APIs</a> •
17   <a href="#documentation">Documentation</a> •
18   <a href="#support-and-feedback">Support</a> •
19   <a href="#how-to-contribute">Contribute</a> •
20   <a href="#contributors">Contributors</a> •
21   <a href="#repositories">Repositories</a> •
22   <a href="#licensing">Licensing</a>
23 </p>
24 
25 The goal of this project is to develop the official Corona-Warn-App for Germany based on the exposure notification API from [Apple](https://www.apple.com/covid19/contacttracing/) and [Google](https://www.google.com/covid19/exposurenotifications/). The apps (for both iOS and Android) use Bluetooth technology to exchange anonymous encrypted data with other mobile phones (on which the app is also installed) in the vicinity of an app user's phone. The data is stored locally on each user's device, preventing authorities or other parties from accessing or controlling the data. This repository contains the **implementation of the server for encryption keys** for the Corona-Warn-App. This implementation is still a **work in progress**, and the code it contains is currently alpha-quality code.
26 
27 In this documentation, Corona-Warn-App services are also referred to as CWA services.
28 
29 ## Architecture Overview
30 
31 You can find the architecture overview [here](/docs/architecture-overview.md), which will give you
32 a good starting point in how the backend services interact with other services, and what purpose
33 they serve.
34 
35 ## Development
36 
37 After you've checked out this repository, you can run the application in one of the following ways:
38 
39 * As a [Docker](https://www.docker.com/)-based deployment on your local machine. You can run either:
40   * Single components using the respective Dockerfile or
41   * The full backend using the Docker Compose (which is considered the most convenient way)
42 * As a [Maven](https://maven.apache.org)-based build on your local machine.
43   If you want to develop something in a single component, this approach is preferable.
44 
45 ### Docker-Based Deployment
46 
47 If you want to use Docker-based deployment, you need to install Docker on your local machine. For more information about downloading and installing Docker, see the [official Docker documentation](https://docs.docker.com/get-docker/).
48 
49 #### Running the Full CWA Backend Using Docker Compose
50 
51 For your convenience, a full setup including the generation of test data has been prepared using [Docker Compose](https://docs.docker.com/compose/reference/overview/). To build the backend services, run ```docker-compose build``` in the repository's root directory. A default configuration file can be found under ```.env```in the root folder of the repository. The default values for the local Postgres and MinIO-build should be changed in this file before docker-compose is run.
52 
53 Once the services are built, you can start the whole backend using ```docker-compose up```.
54 The distribution service runs once and then finishes. If you want to trigger additional distribution runs, run ```docker-compose start distribution```.
55 
56 The docker-compose contains the following services:
57 
58 Service       | Description | Endpoint and Default Credentials
59 --------------|-------------|-----------
60 submission    | The Corona-Warn-App submission service                                            | http://localhost:8080 
61 distribution  | The Corona-Warn-App distribution service                                          | NO ENDPOINT
62 postgres      | A [postgres] database installation                                                | postgres:5432 <br> Username: postgres <br> Password: postgres
63 pgadmin       | A [pgadmin](https://www.pgadmin.org/) installation for the postgres database      | http://localhost:8081 <br> Username: user@domain.com <br> Password: password
64 minio         | [MinIO] is an S3-compliant object store                                           | http://localhost:8082/ <br> Access key: minioadmin <br> Secret key: minioadmin
65 
66 #### Running Single CWA Services Using Docker
67 
68 If you would like to build and run a single CWA service, it's considered easiest to run them in a Docker environment. You can do this using the script provided in the respective CWA service directory. The Docker script first builds the CWA service and then creates an image for the runtime, which means that there are no additional dependencies for you to install.
69 
70 To build and run the distribution service, run the following command:
71 
72 ```bash
73 ./services/distribution/build_and_run.sh
74 ```
75 
76 To build and run the submission service, run the following command:
77 
78 ```bash
79 ./services/submission/build_and_run.sh
80 ```
81 
82 The submission service is available on [localhost:8080](http://localhost:8080 ).
83 
84 ### Maven-Based Build
85 
86 If you want to actively develop in one of the CWA services, the Maven-based runtime is most suitable.
87 To prepare your machine to run the CWA project locally, we recommend that you first ensure that you've installed the following:
88 
89 * Minimum JDK Version 11: [OpenJDK](https://openjdk.java.net/) / [SapMachine](https://sap.github.io/SapMachine/)
90 * [Maven 3.6](https://maven.apache.org/)
91 * [Postgres]
92 * [MinIO]
93 
94 #### Configure
95 
96 After you made sure that the specified dependencies are running, configure them in the respective configuration files.
97 
98 * Configure the Postgres connection in the [submission config](./services/submission/src/main/resources/application.properties) and in the [distribution config](./services/distribution/src/main/resources/application.properties)
99 * Configure the S3 compatible object storage in the [distribution config](./services/distribution/src/main/resources/application.properties)
100 
101 #### Build
102 
103 After you've checked out the repository, to build the project, run ```mvn install``` in your base directory.
104 
105 #### Run
106 
107 Navigate to the service you want to start and run the spring-boot:run target. The configured Postgres and the configured S3 compliant object storage are used as default. When you start the submission service, the endpoint is available on your local port 8080.
108 
109 If you want to start the submission service, for example, you start it as follows:
110 
111 ```bash
112   cd services/submission/
113   mvn spring-boot:run
114 ```
115 
116 #### Debugging
117 
118 To enable the `DEBUG` log level, you can run the application using the Spring `dev` profile.
119 
120 ```bash
121 mvn spring-boot:run -Dspring-boot.run.profiles=dev
122 ```
123 
124 To be able to set breakpoints (e.g. in IntelliJ), it may be necessary to use the ```-Dspring-boot.run.fork=false``` parameter.
125 
126 ## Service APIs
127 
128 The API that is being exposed by the backend services is documented in an [OpenAPI](https://www.openapis.org/) specification. The specification files are available at the following locations:
129 
130 Service      | OpenAPI Specification
131 -------------|-------------
132 Submission Service        | https://github.com/corona-warn-app/cwa-server/raw/master/services/submission/api_v1.json
133 Distribution Service      | https://github.com/corona-warn-app/cwa-server/raw/master/services/distribution/api_v1.json
134 
135 ## Documentation
136 
137 The full documentation for the Corona-Warn-App can be found in the [cwa-documentation](https://github.com/corona-warn-app/cwa-documentation) repository. The documentation repository contains technical documents, architecture information, and whitepapers related to this implementation.
138 
139 ## Support and Feedback
140 
141 The following channels are available for discussions, feedback, and support requests:
142 
143 | Type                     | Channel                                                |
144 | ------------------------ | ------------------------------------------------------ |
145 | **General Discussion**   | <a href="https://github.com/corona-warn-app/cwa-documentation/issues/new/choose" title="General Discussion"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-documentation/question.svg?style=flat-square"></a> </a>   |
146 | **Concept Feedback**    | <a href="https://github.com/corona-warn-app/cwa-documentation/issues/new/choose" title="Open Concept Feedback"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-documentation/architecture.svg?style=flat-square"></a>  |
147 | **Backend Issue**    | <a href="https://github.com/corona-warn-app/cwa-server/issues/new/choose" title="Open Backend Issue"><img src="https://img.shields.io/github/issues/corona-warn-app/cwa-server?style=flat-square"></a>  |
148 | **Other Requests**    | <a href="mailto:corona-warn-app.opensource@sap.com" title="Email CWD Team"><img src="https://img.shields.io/badge/email-CWD%20team-green?logo=mail.ru&style=flat-square&logoColor=white"></a>   |
149 
150 ## How to Contribute
151 
152 Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](./CONTRIBUTING.md). By participating in this project, you agree to abide by its [Code of Conduct](./CODE_OF_CONDUCT.md) at all times.
153 
154 ## Contributors
155 
156 The German government has asked SAP and Deutsche Telekom to develop the Corona-Warn-App for Germany as open source software. Deutsche Telekom is providing the network and mobile technology and will operate and run the backend for the app in a safe, scalable and stable manner. SAP is responsible for the app development, its framework and the underlying platform. Therefore, development teams of SAP and Deutsche Telekom are contributing to this project. At the same time our commitment to open source means that we are enabling -in fact encouraging- all interested parties to contribute and become part of its developer community.
157 
158 ## Repositories
159 
160 The following public repositories are currently available for the Corona-Warn-App:
161 
162 | Repository          | Description                                                           |
163 | ------------------- | --------------------------------------------------------------------- |
164 | [cwa-documentation] | Project overview, general documentation, and white papers            |
165 | [cwa-server]        | Backend implementation for the Apple/Google exposure notification API|
166 
167 [cwa-documentation]: https://github.com/corona-warn-app/cwa-documentation
168 [cwa-server]: https://github.com/corona-warn-app/cwa-server
169 [Postgres]: https://www.postgresql.org/
170 [MinIO]: https://min.io/
171 [HSQLDB]: http://hsqldb.org/
172 
173 ## Licensing
174 
175 Copyright (c) 2020 SAP SE or an SAP affiliate company.
176 
177 Licensed under the **Apache License, Version 2.0** (the "License"); you may not use this file except in compliance with the License. 
178 
179 You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.
180 
181 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the [LICENSE](./LICENSE) for the specific language governing permissions and limitations under the License.
182 
[end of README.md]
[start of THIRD-PARTY-NOTICES]
1 ThirdPartyNotices
2 -----------------
3 corona-warn-app/cwa-server uses third-party software or other resources that
4 may be distributed under licenses different from corona-warn-app/cwa-server
5 software.
6 In the event that we overlooked to list a required notice, please bring this
7 to our attention by contacting us via this email:
8 corona-warn-app.opensource@sap.com
9 
10 
11 Components:
12 -----------
13 Component: Bouncy Castle
14 Licensor:  Legion of the Bouncy Castle Inc.
15 Website:   https://www.bouncycastle.org/
16 License:   MIT License
17 
18 Component: Commons IO
19 Licensor:  Apache Software Foundation
20 Website:   https://commons.apache.org/proper/commons-io/
21 License:   Apache License 2.0
22 
23 Component: Commons Math 3
24 Licensor:  Apache Software Foundation
25 Website:   https://commons.apache.org/proper/commons-math/
26 License:   Apache License 2.0
27 
28 Component: dom4j
29 Licensor:  dom4j
30 Website:   https://dom4j.github.io/
31 License:   BSD License
32 
33 Component: flyway
34 Licensor:  flyway
35 Website:   https://github.com/flyway/flyway
36 License:   Apache License 2.0
37 
38 Component: H2Database
39 Licensor:  H2
40 Website:   http://www.h2database.com/
41 License:   Mozilla Public License 2.0
42 
43 Component: JSON-Simple
44 Licensor:  Yidong Fang
45 Website:   https://github.com/fangyidong/json-simple
46 License:   Apache License 2.0
47 
48 Component: Maven
49 Licensor:  Apache Software Foundation
50 Website:   https://maven.apache.org/
51 License:   Apache License 2.0
52 
53 Component: MinIO Object Storage
54 Licensor:  MinIO Inc.
55 Website:   https://min.io/
56 License:   Apache License 2.0
57 
58 Component: PostgreSQL
59 Licensor:  PostgreSQL
60 Website:   https://www.postgresql.org/
61 License:   PostgreSQL License
62 
63 Component: Protocol Buffers
64 Licensor:  Google Inc.
65 Website:   https://developers.google.com/protocol-buffers/
66 License:   3-Clause BSD License
67 
68 Component: snakeyaml
69 Licensor:  snakeyaml
70 Website:   https://bitbucket.org/asomov/snakeyaml/
71 License:   Apache License 2.0
72 
73 Component: Spring Boot
74 Licensor:  VMWare Inc.
75 Website:   https://spring.io/
76 License:   Apache License 2.0
77 --------------------------------------------------------------------------------
78 Apache License 2.0 (Commons IO, Commons Math 3, flyway, JSON-Simple,
79 Maven, MinIO Object Storage, snakeyaml, Spring Boot)
80 
81                                  Apache License
82                            Version 2.0, January 2004
83                         https://www.apache.org/licenses/
84 
85    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
86 
87    1. Definitions.
88 
89       "License" shall mean the terms and conditions for use, reproduction,
90       and distribution as defined by Sections 1 through 9 of this document.
91 
92       "Licensor" shall mean the copyright owner or entity authorized by
93       the copyright owner that is granting the License.
94 
95       "Legal Entity" shall mean the union of the acting entity and all
96       other entities that control, are controlled by, or are under common
97       control with that entity. For the purposes of this definition,
98       "control" means (i) the power, direct or indirect, to cause the
99       direction or management of such entity, whether by contract or
100       otherwise, or (ii) ownership of fifty percent (50%) or more of the
101       outstanding shares, or (iii) beneficial ownership of such entity.
102 
103       "You" (or "Your") shall mean an individual or Legal Entity
104       exercising permissions granted by this License.
105 
106       "Source" form shall mean the preferred form for making modifications,
107       including but not limited to software source code, documentation
108       source, and configuration files.
109 
110       "Object" form shall mean any form resulting from mechanical
111       transformation or translation of a Source form, including but
112       not limited to compiled object code, generated documentation,
113       and conversions to other media types.
114 
115       "Work" shall mean the work of authorship, whether in Source or
116       Object form, made available under the License, as indicated by a
117       copyright notice that is included in or attached to the work
118       (an example is provided in the Appendix below).
119 
120       "Derivative Works" shall mean any work, whether in Source or Object
121       form, that is based on (or derived from) the Work and for which the
122       editorial revisions, annotations, elaborations, or other modifications
123       represent, as a whole, an original work of authorship. For the purposes
124       of this License, Derivative Works shall not include works that remain
125       separable from, or merely link (or bind by name) to the interfaces of,
126       the Work and Derivative Works thereof.
127 
128       "Contribution" shall mean any work of authorship, including
129       the original version of the Work and any modifications or additions
130       to that Work or Derivative Works thereof, that is intentionally
131       submitted to Licensor for inclusion in the Work by the copyright owner
132       or by an individual or Legal Entity authorized to submit on behalf of
133       the copyright owner. For the purposes of this definition, "submitted"
134       means any form of electronic, verbal, or written communication sent
135       to the Licensor or its representatives, including but not limited to
136       communication on electronic mailing lists, source code control systems,
137       and issue tracking systems that are managed by, or on behalf of, the
138       Licensor for the purpose of discussing and improving the Work, but
139       excluding communication that is conspicuously marked or otherwise
140       designated in writing by the copyright owner as "Not a Contribution."
141 
142       "Contributor" shall mean Licensor and any individual or Legal Entity
143       on behalf of whom a Contribution has been received by Licensor and
144       subsequently incorporated within the Work.
145 
146    2. Grant of Copyright License. Subject to the terms and conditions of
147       this License, each Contributor hereby grants to You a perpetual,
148       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
149       copyright license to reproduce, prepare Derivative Works of,
150       publicly display, publicly perform, sublicense, and distribute the
151       Work and such Derivative Works in Source or Object form.
152 
153    3. Grant of Patent License. Subject to the terms and conditions of
154       this License, each Contributor hereby grants to You a perpetual,
155       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
156       (except as stated in this section) patent license to make, have made,
157       use, offer to sell, sell, import, and otherwise transfer the Work,
158       where such license applies only to those patent claims licensable
159       by such Contributor that are necessarily infringed by their
160       Contribution(s) alone or by combination of their Contribution(s)
161       with the Work to which such Contribution(s) was submitted. If You
162       institute patent litigation against any entity (including a
163       cross-claim or counterclaim in a lawsuit) alleging that the Work
164       or a Contribution incorporated within the Work constitutes direct
165       or contributory patent infringement, then any patent licenses
166       granted to You under this License for that Work shall terminate
167       as of the date such litigation is filed.
168 
169    4. Redistribution. You may reproduce and distribute copies of the
170       Work or Derivative Works thereof in any medium, with or without
171       modifications, and in Source or Object form, provided that You
172       meet the following conditions:
173 
174       (a) You must give any other recipients of the Work or
175           Derivative Works a copy of this License; and
176 
177       (b) You must cause any modified files to carry prominent notices
178           stating that You changed the files; and
179 
180       (c) You must retain, in the Source form of any Derivative Works
181           that You distribute, all copyright, patent, trademark, and
182           attribution notices from the Source form of the Work,
183           excluding those notices that do not pertain to any part of
184           the Derivative Works; and
185 
186       (d) If the Work includes a "NOTICE" text file as part of its
187           distribution, then any Derivative Works that You distribute must
188           include a readable copy of the attribution notices contained
189           within such NOTICE file, excluding those notices that do not
190           pertain to any part of the Derivative Works, in at least one
191           of the following places: within a NOTICE text file distributed
192           as part of the Derivative Works; within the Source form or
193           documentation, if provided along with the Derivative Works; or,
194           within a display generated by the Derivative Works, if and
195           wherever such third-party notices normally appear. The contents
196           of the NOTICE file are for informational purposes only and
197           do not modify the License. You may add Your own attribution
198           notices within Derivative Works that You distribute, alongside
199           or as an addendum to the NOTICE text from the Work, provided
200           that such additional attribution notices cannot be construed
201           as modifying the License.
202 
203       You may add Your own copyright statement to Your modifications and
204       may provide additional or different license terms and conditions
205       for use, reproduction, or distribution of Your modifications, or
206       for any such Derivative Works as a whole, provided Your use,
207       reproduction, and distribution of the Work otherwise complies with
208       the conditions stated in this License.
209 
210    5. Submission of Contributions. Unless You explicitly state otherwise,
211       any Contribution intentionally submitted for inclusion in the Work
212       by You to the Licensor shall be under the terms and conditions of
213       this License, without any additional terms or conditions.
214       Notwithstanding the above, nothing herein shall supersede or modify
215       the terms of any separate license agreement you may have executed
216       with Licensor regarding such Contributions.
217 
218    6. Trademarks. This License does not grant permission to use the trade
219       names, trademarks, service marks, or product names of the Licensor,
220       except as required for reasonable and customary use in describing the
221       origin of the Work and reproducing the content of the NOTICE file.
222 
223    7. Disclaimer of Warranty. Unless required by applicable law or
224       agreed to in writing, Licensor provides the Work (and each
225       Contributor provides its Contributions) on an "AS IS" BASIS,
226       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
227       implied, including, without limitation, any warranties or conditions
228       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
229       PARTICULAR PURPOSE. You are solely responsible for determining the
230       appropriateness of using or redistributing the Work and assume any
231       risks associated with Your exercise of permissions under this License.
232 
233    8. Limitation of Liability. In no event and under no legal theory,
234       whether in tort (including negligence), contract, or otherwise,
235       unless required by applicable law (such as deliberate and grossly
236       negligent acts) or agreed to in writing, shall any Contributor be
237       liable to You for damages, including any direct, indirect, special,
238       incidental, or consequential damages of any character arising as a
239       result of this License or out of the use or inability to use the
240       Work (including but not limited to damages for loss of goodwill,
241       work stoppage, computer failure or malfunction, or any and all
242       other commercial damages or losses), even if such Contributor
243       has been advised of the possibility of such damages.
244 
245    9. Accepting Warranty or Additional Liability. While redistributing
246       the Work or Derivative Works thereof, You may choose to offer,
247       and charge a fee for, acceptance of support, warranty, indemnity,
248       or other liability obligations and/or rights consistent with this
249       License. However, in accepting such obligations, You may act only
250       on Your own behalf and on Your sole responsibility, not on behalf
251       of any other Contributor, and only if You agree to indemnify,
252       defend, and hold each Contributor harmless for any liability
253       incurred by, or claims asserted against, such Contributor by reason
254       of your accepting any such warranty or additional liability.
255 
256    END OF TERMS AND CONDITIONS
257 --------------------------------------------------------------------------------
258 BSD License (dom4j)
259 
260 Copyright 2001-2016 (C) MetaStuff, Ltd. and DOM4J contributors. All Rights Reserved.
261 
262 Redistribution and use of this software and associated documentation
263 ("Software"), with or without modification, are permitted provided
264 that the following conditions are met:
265 
266 1. Redistributions of source code must retain copyright
267    statements and notices.  Redistributions must also contain a
268    copy of this document.
269 
270 2. Redistributions in binary form must reproduce the
271    above copyright notice, this list of conditions and the
272    following disclaimer in the documentation and/or other
273    materials provided with the distribution.
274 
275 3. The name "DOM4J" must not be used to endorse or promote
276    products derived from this Software without prior written
277    permission of MetaStuff, Ltd.  For written permission,
278    please contact dom4j-info@metastuff.com.
279 
280 4. Products derived from this Software may not be called "DOM4J"
281    nor may "DOM4J" appear in their names without prior written
282    permission of MetaStuff, Ltd. DOM4J is a registered
283    trademark of MetaStuff, Ltd.
284 
285 5. Due credit should be given to the DOM4J Project - https://dom4j.github.io/
286 
287 THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
288 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
289 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
290 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
291 METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
292 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
293 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
294 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
295 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
296 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
297 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
298 OF THE POSSIBILITY OF SUCH DAMAGE.
299 --------------------------------------------------------------------------------
300 3-Clause BSD License (Protocol Buffers)
301 
302 Copyright 2008 Google Inc.  All rights reserved.
303 
304 Redistribution and use in source and binary forms, with or without
305 modification, are permitted provided that the following conditions are
306 met:
307 
308     * Redistributions of source code must retain the above copyright
309 notice, this list of conditions and the following disclaimer.
310     * Redistributions in binary form must reproduce the above
311 copyright notice, this list of conditions and the following disclaimer
312 in the documentation and/or other materials provided with the
313 distribution.
314     * Neither the name of Google Inc. nor the names of its
315 contributors may be used to endorse or promote products derived from
316 this software without specific prior written permission.
317 
318 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
319 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
320 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
321 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
323 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
324 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
325 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
326 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
327 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
328 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
329 
330 Code generated by the Protocol Buffer compiler is owned by the owner
331 of the input file used when generating it.  This code is not
332 standalone and requires a support library to be linked with it.  This
333 support library is itself covered by the above license.
334 --------------------------------------------------------------------------------
335 PostgreSQL License (PostgreSQL)
336 
337 PostgreSQL Database Management System
338 (formerly known as Postgres, then as Postgres95)
339 
340 Portions Copyright © 1996-2020, The PostgreSQL Global Development Group
341 
342 Portions Copyright © 1994, The Regents of the University of California
343 
344 Permission to use, copy, modify, and distribute this software and its
345 documentation for any purpose, without fee, and without a written agreement is
346 hereby granted, provided that the above copyright notice and this paragraph and
347 the following two paragraphs appear in all copies.
348 
349 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
350 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
351 PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
352 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
353 
354 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
355 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
356 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
357 THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
358 UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
359 --------------------------------------------------------------------------------
360 Mozilla Public License 2.0 (H2Database)
361 
362 Mozilla Public License
363 Version 2.0
364 1. Definitions
365 1.1. “Contributor”
366 means each individual or legal entity that creates, contributes to the creation
367 of, or owns Covered Software.
368 
369 1.2. “Contributor Version”
370 means the combination of the Contributions of others (if any) used by a
371 Contributor and that particular Contributor’s Contribution.
372 
373 1.3. “Contribution”
374 means Covered Software of a particular Contributor.
375 
376 1.4. “Covered Software”
377 means Source Code Form to which the initial Contributor has attached the notice
378 in Exhibit A, the Executable Form of such Source Code Form, and Modifications
379 of such Source Code Form, in each case including portions thereof.
380 
381 1.5. “Incompatible With Secondary Licenses”
382 means
383 
384 that the initial Contributor has attached the notice described in Exhibit B to
385 the Covered Software; or
386 
387 that the Covered Software was made available under the terms of version 1.1 or
388 earlier of the License, but not also under the terms of a Secondary License.
389 
390 1.6. “Executable Form”
391 means any form of the work other than Source Code Form.
392 
393 1.7. “Larger Work”
394 means a work that combines Covered Software with other material, in a separate
395 file or files, that is not Covered Software.
396 
397 1.8. “License”
398 means this document.
399 
400 1.9. “Licensable”
401 means having the right to grant, to the maximum extent possible, whether at the
402 time of the initial grant or subsequently, any and all of the rights conveyed
403 by this License.
404 
405 1.10. “Modifications”
406 means any of the following:
407 
408 any file in Source Code Form that results from an addition to, deletion from,
409 or modification of the contents of Covered Software; or
410 
411 any new file in Source Code Form that contains any Covered Software.
412 
413 1.11. “Patent Claims” of a Contributor
414 means any patent claim(s), including without limitation, method, process, and
415 apparatus claims, in any patent Licensable by such Contributor that would be
416 infringed, but for the grant of the License, by the making, using, selling,
417 offering for sale, having made, import, or transfer of either its Contributions
418 or its Contributor Version.
419 
420 1.12. “Secondary License”
421 means either the GNU General Public License, Version 2.0, the GNU Lesser
422 General Public License, Version 2.1, the GNU Affero General Public License,
423 Version 3.0, or any later versions of those licenses.
424 
425 1.13. “Source Code Form”
426 means the form of the work preferred for making modifications.
427 
428 1.14. “You” (or “Your”)
429 means an individual or a legal entity exercising rights under this License. For
430 legal entities, “You” includes any entity that controls, is controlled by, or
431 is under common control with You. For purposes of this definition, “control”
432 means (a) the power, direct or indirect, to cause the direction or management
433 of such entity, whether by contract or otherwise, or (b) ownership of more than
434 fifty percent (50%) of the outstanding shares or beneficial ownership of such
435 entity.
436 
437 2. License Grants and Conditions
438 2.1. Grants
439 Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive
440 license:
441 
442 under intellectual property rights (other than patent or trademark) Licensable
443 by such Contributor to use, reproduce, make available, modify, display,
444 perform, distribute, and otherwise exploit its Contributions, either on an
445 unmodified basis, with Modifications, or as part of a Larger Work; and
446 
447 under Patent Claims of such Contributor to make, use, sell, offer for sale,
448 have made, import, and otherwise transfer either its Contributions or its
449 Contributor Version.
450 
451 2.2. Effective Date
452 The licenses granted in Section 2.1 with respect to any Contribution become
453 effective for each Contribution on the date the Contributor first distributes
454 such Contribution.
455 
456 2.3. Limitations on Grant Scope
457 The licenses granted in this Section 2 are the only rights granted under this
458 License. No additional rights or licenses will be implied from the distribution
459 or licensing of Covered Software under this License. Notwithstanding Section
460 2.1(b) above, no patent license is granted by a Contributor:
461 
462 for any code that a Contributor has removed from Covered Software; or
463 
464 for infringements caused by: (i) Your and any other third party’s modifications
465 of Covered Software, or (ii) the combination of its Contributions with other
466 software (except as part of its Contributor Version); or
467 
468 under Patent Claims infringed by Covered Software in the absence of its
469 Contributions.
470 
471 This License does not grant any rights in the trademarks, service marks, or
472 logos of any Contributor (except as may be necessary to comply with the notice
473 requirements in Section 3.4).
474 
475 2.4. Subsequent Licenses
476 No Contributor makes additional grants as a result of Your choice to distribute
477 the Covered Software under a subsequent version of this License (see Section
478 10.2) or under the terms of a Secondary License (if permitted under the terms
479 of Section 3.3).
480 
481 2.5. Representation
482 Each Contributor represents that the Contributor believes its Contributions are
483 its original creation(s) or it has sufficient rights to grant the rights to its
484 Contributions conveyed by this License.
485 
486 2.6. Fair Use
487 This License is not intended to limit any rights You have under applicable
488 copyright doctrines of fair use, fair dealing, or other equivalents.
489 
490 2.7. Conditions
491 Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
492 Section 2.1.
493 
494 3. Responsibilities
495 3.1. Distribution of Source Form
496 All distribution of Covered Software in Source Code Form, including any
497 Modifications that You create or to which You contribute, must be under the
498 terms of this License. You must inform recipients that the Source Code Form of
499 the Covered Software is governed by the terms of this License, and how they can
500 obtain a copy of this License. You may not attempt to alter or restrict the
501 recipients’ rights in the Source Code Form.
502 
503 3.2. Distribution of Executable Form
504 If You distribute Covered Software in Executable Form then:
505 
506 such Covered Software must also be made available in Source Code Form, as
507 described in Section 3.1, and You must inform recipients of the Executable Form
508 how they can obtain a copy of such Source Code Form by reasonable means in a
509 timely manner, at a charge no more than the cost of distribution to the
510 recipient; and
511 
512 You may distribute such Executable Form under the terms of this License, or
513 sublicense it under different terms, provided that the license for the
514 Executable Form does not attempt to limit or alter the recipients’ rights in
515 the Source Code Form under this License.
516 
517 3.3. Distribution of a Larger Work
518 You may create and distribute a Larger Work under terms of Your choice,
519 provided that You also comply with the requirements of this License for the
520 Covered Software. If the Larger Work is a combination of Covered Software with
521 a work governed by one or more Secondary Licenses, and the Covered Software is
522 not Incompatible With Secondary Licenses, this License permits You to
523 additionally distribute such Covered Software under the terms of such Secondary
524 License(s), so that the recipient of the Larger Work may, at their option,
525 further distribute the Covered Software under the terms of either this License
526 or such Secondary License(s).
527 
528 3.4. Notices
529 You may not remove or alter the substance of any license notices (including
530 copyright notices, patent notices, disclaimers of warranty, or limitations of
531 liability) contained within the Source Code Form of the Covered Software,
532 except that You may alter any license notices to the extent required to remedy
533 known factual inaccuracies.
534 
535 3.5. Application of Additional Terms
536 You may choose to offer, and to charge a fee for, warranty, support, indemnity
537 or liability obligations to one or more recipients of Covered Software.
538 However, You may do so only on Your own behalf, and not on behalf of any
539 Contributor. You must make it absolutely clear that any such warranty, support,
540 indemnity, or liability obligation is offered by You alone, and You hereby
541 agree to indemnify every Contributor for any liability incurred by such
542 Contributor as a result of warranty, support, indemnity or liability terms You
543 offer. You may include additional disclaimers of warranty and limitations of
544 liability specific to any jurisdiction.
545 
546 4. Inability to Comply Due to Statute or Regulation
547 If it is impossible for You to comply with any of the terms of this License
548 with respect to some or all of the Covered Software due to statute, judicial
549 order, or regulation then You must: (a) comply with the terms of this License
550 to the maximum extent possible; and (b) describe the limitations and the code
551 they affect. Such description must be placed in a text file included with all
552 distributions of the Covered Software under this License. Except to the extent
553 prohibited by statute or regulation, such description must be sufficiently
554 detailed for a recipient of ordinary skill to be able to understand it.
555 
556 5. Termination
557 5.1. The rights granted under this License will terminate automatically if You
558 fail to comply with any of its terms. However, if You become compliant, then
559 the rights granted under this License from a particular Contributor are
560 reinstated (a) provisionally, unless and until such Contributor explicitly and
561 finally terminates Your grants, and (b) on an ongoing basis, if such
562 Contributor fails to notify You of the non-compliance by some reasonable means
563 prior to 60 days after You have come back into compliance. Moreover, Your
564 grants from a particular Contributor are reinstated on an ongoing basis if such
565 Contributor notifies You of the non-compliance by some reasonable means, this
566 is the first time You have received notice of non-compliance with this License
567 from such Contributor, and You become compliant prior to 30 days after Your
568 receipt of the notice.
569 
570 5.2. If You initiate litigation against any entity by asserting a patent
571 infringement claim (excluding declaratory judgment actions, counter-claims, and
572 cross-claims) alleging that a Contributor Version directly or indirectly
573 infringes any patent, then the rights granted to You by any and all
574 Contributors for the Covered Software under Section 2.1 of this License shall
575 terminate.
576 
577 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
578 license agreements (excluding distributors and resellers) which have been
579 validly granted by You or Your distributors under this License prior to
580 termination shall survive termination.
581 
582 6. Disclaimer of Warranty
583 Covered Software is provided under this License on an “as is” basis, without
584 warranty of any kind, either expressed, implied, or statutory, including,
585 without limitation, warranties that the Covered Software is free of defects,
586 merchantable, fit for a particular purpose or non-infringing. The entire risk
587 as to the quality and performance of the Covered Software is with You. Should
588 any Covered Software prove defective in any respect, You (not any Contributor)
589 assume the cost of any necessary servicing, repair, or correction. This
590 disclaimer of warranty constitutes an essential part of this License. No use of
591 any Covered Software is authorized under this License except under this
592 disclaimer.
593 
594 7. Limitation of Liability
595 Under no circumstances and under no legal theory, whether tort (including
596 negligence), contract, or otherwise, shall any Contributor, or anyone who
597 distributes Covered Software as permitted above, be liable to You for any
598 direct, indirect, special, incidental, or consequential damages of any
599 character including, without limitation, damages for lost profits, loss of
600 goodwill, work stoppage, computer failure or malfunction, or any and all other
601 commercial damages or losses, even if such party shall have been informed of
602 the possibility of such damages. This limitation of liability shall not apply
603 to liability for death or personal injury resulting from such party’s
604 negligence to the extent applicable law prohibits such limitation. Some
605 jurisdictions do not allow the exclusion or limitation of incidental or
606 consequential damages, so this exclusion and limitation may not apply to You.
607 
608 8. Litigation
609 Any litigation relating to this License may be brought only in the courts of a
610 jurisdiction where the defendant maintains its principal place of business and
611 such litigation shall be governed by laws of that jurisdiction, without
612 reference to its conflict-of-law provisions. Nothing in this Section shall
613 prevent a party’s ability to bring cross-claims or counter-claims.
614 
615 9. Miscellaneous
616 This License represents the complete agreement concerning the subject matter
617 hereof. If any provision of this License is held to be unenforceable, such
618 provision shall be reformed only to the extent necessary to make it
619 enforceable. Any law or regulation which provides that the language of a
620 contract shall be construed against the drafter shall not be used to construe
621 this License against a Contributor.
622 
623 10. Versions of the License
624 10.1. New Versions
625 Mozilla Foundation is the license steward. Except as provided in Section 10.3,
626 no one other than the license steward has the right to modify or publish new
627 versions of this License. Each version will be given a distinguishing version
628 number.
629 
630 10.2. Effect of New Versions
631 You may distribute the Covered Software under the terms of the version of the
632 License under which You originally received the Covered Software, or under the
633 terms of any subsequent version published by the license steward.
634 
635 10.3. Modified Versions
636 If you create software not governed by this License, and you want to create a
637 new license for such software, you may create and use a modified version of
638 this License if you rename the license and remove any references to the name of
639 the license steward (except to note that such modified license differs from
640 this License).
641 
642 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
643 If You choose to distribute Source Code Form that is Incompatible With
644 Secondary Licenses under the terms of this version of the License, the notice
645 described in Exhibit B of this License must be attached.
646 
647 Exhibit A - Source Code Form License Notice
648 This Source Code Form is subject to the terms of the Mozilla Public License, v.
649 2.0. If a copy of the MPL was not distributed with this file, You can obtain
650 one at https://mozilla.org/MPL/2.0/.
651 
652 If it is not possible or desirable to put the notice in a particular file, then
653 You may include the notice in a location (such as a LICENSE file in a relevant
654 directory) where a recipient would be likely to look for such a notice.
655 
656 You may add additional accurate notices of copyright ownership.
657 
658 Exhibit B - “Incompatible With Secondary Licenses” Notice
659 This Source Code Form is “Incompatible With Secondary Licenses”, as defined by
660 the Mozilla Public License, v. 2.0.
661 --------------------------------------------------------------------------------
662 MIT License (BouncyCastle)
663 
664 Copyright (c) 2000 - 2020 The Legion of the Bouncy Castle Inc.
665 (https://www.bouncycastle.org)
666 
667 Permission is hereby granted, free of charge, to any person obtaining a copy of
668 this software and associated documentation files (the "Software"), to deal in
669 the Software without restriction, including without limitation the rights to
670 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
671 of the Software, and to permit persons to whom the Software is furnished to do
672 so, subject to the following conditions:
673 
674 The above copyright notice and this permission notice shall be included in all
675 copies or substantial portions of the Software.
676 
677 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
678 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
679 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
680 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
681 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
682 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
683 SOFTWARE.
[end of THIRD-PARTY-NOTICES]
[start of docker-compose.yml]
1 version: '3'
2 services:
3   submission:
4     build:
5       context: ./
6       dockerfile: ./services/submission/Dockerfile
7     depends_on:
8       - postgres
9     ports:
10       - "8080:8080"
11     environment: 
12       SPRING_PROFILES_ACTIVE: cloud,dev
13       POSTGRESQL_SERVICE_PORT: '5432'
14       POSTGRESQL_SERVICE_HOST: postgres
15       POSTGRESQL_DATABASE: ${POSTGRES_DB}
16       POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD}
17       POSTGRESQL_USER: ${POSTGRES_USER}
18     networks:
19       - cwa
20   distribution:
21     build:
22       context: ./
23       dockerfile: ./services/distribution/Dockerfile
24     depends_on:
25      - postgres
26      - minio
27     environment:
28       SPRING_PROFILES_ACTIVE: cloud,dev,testdata
29       POSTGRESQL_SERVICE_PORT: '5432'
30       POSTGRESQL_SERVICE_HOST: postgres
31       POSTGRESQL_DATABASE: ${POSTGRES_DB}
32       POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD}
33       POSTGRESQL_USER: ${POSTGRES_USER}
34       # Settings for the S3 compatible MinIO object storage
35       CWA_OBJECTSTORE_ACCESSKEY: ${MINIO_ACCESS_KEY}
36       CWA_OBJECTSTORE_SECRETKEY: ${MINIO_SECRET_KEY}
37       CWA_OBJECTSTORE_ENDPOINT: http://minio
38       CWA_OBJECTSTORE_BUCKET: cwa
39       CWA_OBJECTSTORE_PORT: 9000
40       services.distribution.paths.output: /tmp/distribution
41       # Settings for cryptographic artefacts
42       VAULT_FILESIGNING_SECRET: ${SECRET_PRIVATE}
43       VAULT_FILESIGNING_CERT: ${SECRET_CERTIFICATE}
44     volumes:
45       - ./docker-compose-test-secrets:/secrets
46     networks:
47       - cwa
48   postgres:
49     image: postgres:9.6
50     restart: always
51     ports:
52       - "5432:5432"
53     environment:
54       PGDATA: /data/postgres
55       POSTGRES_DB: ${POSTGRES_DB}
56       POSTGRES_USER: ${POSTGRES_USER}
57       POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
58     volumes:
59        - postgres_volume:/data/postgres
60     networks:
61       - cwa
62   pgadmin:
63     container_name: pgadmin_container
64     image: dpage/pgadmin4
65     volumes:
66        - pgadmin_volume:/root/.pgadmin
67     ports:
68       - "8081:80"
69     restart: unless-stopped
70     networks:
71       - cwa
72     depends_on:
73       - postgres
74     environment:
75       PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
76       PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
77   minio:
78     image: "minio/minio"
79     volumes:
80       - minio_volume:/data
81     ports:
82       - "8082:9000"
83     environment:
84       MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
85       MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
86     entrypoint: sh
87     command: -c 'mkdir -p /data/cwa && minio server /data'
88     networks:
89       - cwa
90 volumes:
91   logvolume01: {}
92   minio_volume:
93   postgres_volume:
94   pgadmin_volume:
95 networks:
96   cwa:
97     driver: bridge
[end of docker-compose.yml]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore;
21 
22 import app.coronawarn.server.services.distribution.objectstore.publish.LocalFile;
23 import io.minio.MinioClient;
24 import io.minio.PutObjectOptions;
25 import io.minio.Result;
26 import io.minio.errors.InvalidEndpointException;
27 import io.minio.errors.InvalidPortException;
28 import io.minio.errors.MinioException;
29 import io.minio.messages.DeleteError;
30 import io.minio.messages.Item;
31 import java.io.IOException;
32 import java.security.GeneralSecurityException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.stream.Collectors;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.beans.factory.annotation.Autowired;
40 import org.springframework.stereotype.Component;
41 
42 /**
43  * <p>Grants access to the S3 compatible object storage hosted by Telekom in Germany, enabling
44  * basic functionality for working with files.</p>
45  * <br>
46  * Make sure the following properties are available on the env:
47  * <ul>
48  * <li>cwa.objectstore.endpoint</li>
49  * <li>cwa.objectstore.bucket</li>
50  * <li>cwa.objectstore.accessKey</li>
51  * <li>cwa.objectstore.secretKey</li>
52  * <li>cwa.objectstore.port</li>
53  * </ul>
54  */
55 @Component
56 public class ObjectStoreAccess {
57 
58   private static final Logger logger = LoggerFactory.getLogger(ObjectStoreAccess.class);
59 
60   private static final String DEFAULT_REGION = "eu-west-1";
61 
62   private final String bucket;
63 
64   private MinioClient client;
65 
66 
67   /**
68    * Constructs an {@link ObjectStoreAccess} instance for communication with the specified object
69    * store endpoint and bucket.
70    *
71    * @param configurationProperties The config properties
72    * @throws IOException When there were problems creating the S3 client
73    * @throws GeneralSecurityException When there were problems creating the S3 client
74    * @throws MinioException When there were problems creating the S3 client
75    */
76   @Autowired
77   public ObjectStoreAccess(ObjectStoreConfigurationProperties configurationProperties)
78       throws IOException, GeneralSecurityException, MinioException {
79     this.client = createClient(configurationProperties);
80 
81     this.bucket = configurationProperties.getBucket();
82 
83     if (!this.client.bucketExists(this.bucket)) {
84       throw new IllegalArgumentException("Supplied bucket does not exist " + bucket);
85     }
86   }
87 
88   private MinioClient createClient(ObjectStoreConfigurationProperties configurationProperties)
89       throws InvalidPortException, InvalidEndpointException {
90     if (isSsl(configurationProperties)) {
91       return new MinioClient(
92           configurationProperties.getEndpoint(),
93           configurationProperties.getPort(),
94           configurationProperties.getAccessKey(), configurationProperties.getSecretKey(),
95           DEFAULT_REGION,
96           true
97       );
98     } else {
99       return new MinioClient(
100           configurationProperties.getEndpoint(),
101           configurationProperties.getPort(),
102           configurationProperties.getAccessKey(), configurationProperties.getSecretKey()
103       );
104     }
105   }
106 
107   private boolean isSsl(ObjectStoreConfigurationProperties configurationProperties) {
108     return configurationProperties.getEndpoint().startsWith("https://");
109   }
110 
111   /**
112    * Stores the target file on the S3.
113    *
114    * @param localFile the file to be published
115    */
116   public void putObject(LocalFile localFile)
117       throws IOException, GeneralSecurityException, MinioException {
118     String s3Key = localFile.getS3Key();
119 
120 
121     var options = new PutObjectOptions(localFile.getFile().toFile().length(), -1);
122     options.setHeaders(createMetadataFor(localFile));
123 
124     logger.info("... uploading " + s3Key);
125     this.client.putObject(bucket, s3Key, localFile.getFile().toString(), options);
126   }
127 
128   /**
129    * Deletes objects in the object store, based on the given prefix (folder structure).
130    *
131    * @param prefix the prefix, e.g. my/folder/
132    */
133   public List<DeleteError> deleteObjectsWithPrefix(String prefix)
134       throws MinioException, GeneralSecurityException, IOException {
135     List<String> toDelete = getObjectsWithPrefix(prefix)
136         .stream()
137         .map(S3Object::getObjectName)
138         .collect(Collectors.toList());
139 
140     logger.info("Deleting " + toDelete.size() + " entries with prefix " + prefix);
141     var deletionResponse = this.client.removeObjects(bucket, toDelete);
142 
143     List<DeleteError> errors = new ArrayList<>();
144     for (Result<DeleteError> deleteErrorResult : deletionResponse) {
145       errors.add(deleteErrorResult.get());
146     }
147 
148     logger.info("Deletion result: " + errors.size());
149 
150     return errors;
151   }
152 
153   /**
154    * Fetches the list of objects in the store with the given prefix.
155    *
156    * @param prefix the prefix, e.g. my/folder/
157    * @return the list of objects
158    */
159   public List<S3Object> getObjectsWithPrefix(String prefix)
160       throws IOException, GeneralSecurityException, MinioException {
161     var objects = this.client.listObjects(bucket, prefix, true, true, false);
162 
163     var list = new ArrayList<S3Object>();
164     for (Result<Item> item : objects) {
165       list.add(S3Object.of(item.get()));
166     }
167 
168     return list;
169   }
170 
171   private Map<String, String> createMetadataFor(LocalFile file) {
172     return Map.of("cwa.hash", file.getHash());
173   }
174 }
175 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore;
21 
22 import org.springframework.boot.context.properties.ConfigurationProperties;
23 
24 @ConfigurationProperties(prefix = "cwa.objectstore")
25 public class ObjectStoreConfigurationProperties {
26 
27   private String accessKey;
28 
29   private String secretKey;
30 
31   private String endpoint;
32 
33   private int port;
34 
35   private String bucket;
36 
37   public int getPort() {
38     return port;
39   }
40 
41   public void setPort(int port) {
42     this.port = port;
43   }
44 
45   public String getSecretKey() {
46     return secretKey;
47   }
48 
49   public void setSecretKey(String secretKey) {
50     this.secretKey = secretKey;
51   }
52 
53   public String getEndpoint() {
54     return endpoint;
55   }
56 
57   public void setEndpoint(String endpoint) {
58     this.endpoint = endpoint;
59   }
60 
61   public String getBucket() {
62     return bucket;
63   }
64 
65   public void setBucket(String bucket) {
66     this.bucket = bucket;
67   }
68 
69   public String getAccessKey() {
70     return accessKey;
71   }
72 
73   public void setAccessKey(String accessKey) {
74     this.accessKey = accessKey;
75   }
76 }
77 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore;
21 
22 import io.minio.messages.Item;
23 import java.util.HashMap;
24 import java.util.Map;
25 
26 /**
27  * Represents an object as discovered on S3.
28  */
29 public class S3Object {
30 
31   /**
32    * the name of the object.
33    */
34   private final String objectName;
35 
36   /**
37    * the available meta information.
38    */
39   private Map<String, String> metadata = new HashMap<>();
40 
41   /**
42    * Constructs a new S3Object for the given object name.
43    *
44    * @param objectName the target object name
45    */
46   public S3Object(String objectName) {
47     this.objectName = objectName;
48   }
49 
50   public String getObjectName() {
51     return objectName;
52   }
53 
54   public Map<String, String> getMetadata() {
55     return metadata;
56   }
57 
58   /**
59    * Returns a new instance of an S3Object based on the given item.
60    *
61    * @param item the item (as provided by MinIO)
62    * @return the S3Object representation
63    */
64   public static S3Object of(Item item) {
65     S3Object s3Object = new S3Object(item.objectName());
66 
67     if (item.userMetadata() != null) {
68       s3Object.metadata = item.userMetadata();
69     }
70 
71     return s3Object;
72   }
73 }
74 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore.publish;
21 
22 import java.io.IOException;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.Base64;
28 
29 /**
30  * Represents a file, which is subject for publishing to S3.
31  */
32 public abstract class LocalFile {
33 
34   /** the path to the file to be represented. */
35   private final Path file;
36 
37   /** the assigned S3 key. */
38   private final String s3Key;
39 
40   /** the hash of this file. */
41   private final String hash;
42 
43   /**
44    * Constructs a new file representing a file on the disk.
45    *
46    * @param file the path to the file to be represented
47    * @param basePath the base path
48    */
49   public LocalFile(Path file, Path basePath) {
50     this.file = file;
51     this.hash = hash();
52     this.s3Key = createS3Key(file, basePath);
53   }
54 
55   public String getS3Key() {
56     return s3Key;
57   }
58 
59   public String getHash() {
60     return hash;
61   }
62 
63   public Path getFile() {
64     return file;
65   }
66 
67   private String hash() {
68     try {
69       MessageDigest digester = MessageDigest.getInstance("SHA-256");
70       digester.update(Files.readAllBytes(file));
71 
72       return Base64.getEncoder().encodeToString(digester.digest());
73     } catch (IOException | NoSuchAlgorithmException e) {
74       throw new RuntimeException("Unable to compute hashes due to ", e);
75     }
76   }
77 
78   protected String createS3Key(Path file, Path rootFolder) {
79     Path relativePath = rootFolder.relativize(file);
80     return relativePath.toString().replaceAll("\\\\", "/");
81   }
82 }
83 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore.publish;
21 
22 import java.nio.file.Path;
23 
24 /**
25  * Represents a file of a specific category: Index files.
26  * <br>
27  * Index files contain information about the available packages on the S3, which makes discovery of
28  * those files easier for the consumers. Index files are assembled with the name "index", but should
29  * be published on S3 w/o the index part, to makee.g.:
30  * <br>
31  * /diagnosis-keys/date/2020-12-12/index -> /diagnosis-keys/date/2020-12-12
32  */
33 public class LocalIndexFile extends LocalFile {
34 
35   /**
36    * the suffix for index files.
37    */
38   private static final String INDEX_FILE_SUFFIX = "/index";
39 
40   /**
41    * Constructs a new file, which is treated as an index file.
42    *
43    * @param file the file on the disk
44    * @param basePath the base path, from where the file was loaded. This will be used in order to
45    *                  determine the S3 key
46    */
47   public LocalIndexFile(Path file, Path basePath) {
48     super(file, basePath);
49   }
50 
51   @Override
52   protected String createS3Key(Path file, Path rootFolder) {
53     String s3Key = super.createS3Key(file, rootFolder);
54 
55     // Deactivate index mapping for now
56     // return s3Key.substring(0, s3Key.length() - INDEX_FILE_SUFFIX.length());
57     return s3Key;
58   }
59 }
60 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java]
[start of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java]
1 /*
2  * Corona-Warn-App
3  *
4  * SAP SE and all other contributors /
5  * copyright owners license this file to you under the Apache
6  * License, Version 2.0 (the "License"); you may not use this
7  * file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 package app.coronawarn.server.services.distribution.objectstore.publish;
21 
22 import app.coronawarn.server.services.distribution.objectstore.S3Object;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.stream.Collectors;
26 
27 /**
28  * Provides an overview about which files are currently available on S3.
29  */
30 public class PublishedFileSet {
31 
32   /** ta map of S3 objects with the S3 object name as the key component of the map. */
33   private Map<String, S3Object> s3Objects;
34 
35   /**
36    * Creates a new PublishedFileSet for the given S3 objects with the help of the metadata provider.
37    * The metadata provider helps to determine whether files have been changed, and are requiring
38    * re-upload.
39    *
40    * @param s3Objects the list of s3 objects.
41    */
42   public PublishedFileSet(List<S3Object> s3Objects) {
43     this.s3Objects = s3Objects.stream()
44         .collect(Collectors.toMap(S3Object::getObjectName, s3object -> s3object));
45   }
46 
47   /**
48    * Checks whether the given file, which is subject for publishing, is already available on the S3.
49    * Will return true, when:
50    * <ul>
51    *   <li>The S3 object key exists on S3</li>
52    *   <li>The checksum of the existing S3 object matches the hash of the given file</li>
53    * </ul>
54    *
55    * @param file the to-be-published file which should be checked
56    * @return true, if it exists & is identical
57    */
58   public boolean isNotYetPublished(LocalFile file) {
59     S3Object published = s3Objects.get(file.getS3Key());
60 
61     if (published == null) {
62       return true;
63     }
64 
65     return !hasSameHashAsPublishedFile(file);
66   }
67 
68   private boolean hasSameHashAsPublishedFile(LocalFile file) {
69     var metaData = s3Objects.get(file.getS3Key()).getMetadata();
70 
71     String s3FileHash = metaData.get("X-Amz-Meta-Cwa.hash");
72 
73     return file.getHash().equals(s3FileHash);
74   }
75 
76 }
77 
[end of services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java]
[start of services/distribution/src/main/resources/application-cloud.properties]
1 spring.flyway.enabled=true
2 spring.flyway.locations=classpath:db/migration/postgres
3 
4 spring.datasource.driver-class-name=org.postgresql.Driver
5 spring.datasource.url=jdbc:postgresql://${POSTGRESQL_SERVICE_HOST}:${POSTGRESQL_SERVICE_PORT}/${POSTGRESQL_DATABASE}
6 spring.datasource.username=${POSTGRESQL_USER}
7 spring.datasource.password=${POSTGRESQL_PASSWORD}
8 
9 services.distribution.paths.output=/tmp/distribution
10 
11 cwa.objectstore.accessKey=${CWA_OBJECTSTORE_ACCESSKEY}
12 cwa.objectstore.secretKey=${CWA_OBJECTSTORE_SECRETKEY}
13 cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT}
14 cwa.objectstore.bucket=${CWA_OBJECTSTORE_BUCKET}
15 cwa.objectstore.port=${CWA_OBJECTSTORE_PORT}
16 
[end of services/distribution/src/main/resources/application-cloud.properties]
[start of services/distribution/src/main/resources/application.properties]
1 logging.level.org.springframework.web=INFO
2 logging.level.app.coronawarn=INFO
3 spring.main.web-application-type=NONE
4 
5 services.distribution.retention-days=14
6 services.distribution.paths.output=out
7 services.distribution.paths.privatekey=${VAULT_FILESIGNING_SECRET}
8 services.distribution.paths.certificate=${VAULT_FILESIGNING_CERT}
9 
10 # Configuration for the S3 compatible object storage hosted by Telekom in Germany
11 cwa.objectstore.accessKey=${CWA_OBJECTSTORE_ACCESSKEY:minioadmin}
12 cwa.objectstore.secretKey=${CWA_OBJECTSTORE_SECRETKEY:minioadmin}
13 cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT:http\://localhost\:9000}
14 cwa.objectstore.bucket=${CWA_OBJECTSTORE_BUCKET:cwa}
15 cwa.objectstore.port=${CWA_OBJECTSTORE_PORT:9000}
16 
17 # Postgres configuration
18 spring.jpa.hibernate.ddl-auto=validate
19 
20 spring.flyway.enabled=true
21 spring.flyway.locations=classpath:db/migration/postgres
22 
23 spring.datasource.driver-class-name=org.postgresql.Driver
24 spring.datasource.url=jdbc:postgresql://${POSTGRESQL_SERVICE_HOST:localhost}:${POSTGRESQL_SERVICE_PORT:5432}/${POSTGRESQL_DATABASE:cwa}
25 spring.datasource.username=${POSTGRESQL_USER:postgres}
26 spring.datasource.password=${POSTGRESQL_PASSWORD:postgres}
27 
[end of services/distribution/src/main/resources/application.properties]
</code>

Here is an example of a patch file. It consists of changes to the code base. It specifies the file names, the line numbers of each change, and the removed and added lines. A single patch file can contain changes to multiple files.
<patch>
--- a/file.py
+++ b/file.py
@@ -1,27 +1,35 @@
 def euclidean(a, b):
-    while b:
-        a, b = b, a % b
-    return a
+    if b == 0:
+        return a
+    return euclidean(b, a % b)
 
 
 def bresenham(x0, y0, x1, y1):
     points = []
     dx = abs(x1 - x0)
     dy = abs(y1 - y0)
-    sx = 1 if x0 < x1 else -1
-    sy = 1 if y0 < y1 else -1
-    err = dx - dy
+    x, y = x0, y0
+    sx = -1 if x0 > x1 else 1
+    sy = -1 if y0 > y1 else 1
 
-    while True:
-        points.append((x0, y0))
-        if x0 == x1 and y0 == y1:
-            break
-        e2 = 2 * err
-        if e2 > -dy:
+    if dx > dy:
+        err = dx / 2.0
+        while x != x1:
+            points.append((x, y))
             err -= dy
-            x0 += sx
-        if e2 < dx:
-            err += dx
-            y0 += sy
+            if err < 0:
+                y += sy
+                err += dx
+            x += sx
+    else:
+        err = dy / 2.0
+        while y != y1:
+            points.append((x, y))
+            err -= dx
+            if err < 0:
+                x += sx
+                err += dy
+            y += sy
 
+    points.append((x, y))
     return points
</patch>

I need you to solve the provded issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the format shown above.
Respond below:


Open MinIO read access
## Current Implementation
Receiving files from local MinIO requires access key and secret key.

## Suggested Enhancement
Add a security policy to the MinIO configuration to only protect write access, but have open read access.

## Expected Benefits
Mobile colleagues can use local setup for end-to-end testing.

<patch>
diff --git a/.env b/.env
--- a/.env
+++ b/.env
@@ -10,9 +10,9 @@ POSTGRES_PASSWORD=postgres
 PGADMIN_DEFAULT_EMAIL=user@domain.com
 PGADMIN_DEFAULT_PASSWORD=password
 
-# Docker Compose MinIO settings
-MINIO_ACCESS_KEY=minioadmin
-MINIO_SECRET_KEY=minioadmin
+# Docker Compose objectstore settings
+OBJECTSTORE_ACCESSKEY=accessKey1
+OBJECTSTORE_SECRETKEY=verySecretKey1
 
 # Docker Compose Secrets settings
 SECRET_PRIVATE=file:/secrets/private.pem
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ If you want to use Docker-based deployment, you need to install Docker on your l
 
 #### Running the Full CWA Backend Using Docker Compose
 
-For your convenience, a full setup including the generation of test data has been prepared using [Docker Compose](https://docs.docker.com/compose/reference/overview/). To build the backend services, run ```docker-compose build``` in the repository's root directory. A default configuration file can be found under ```.env```in the root folder of the repository. The default values for the local Postgres and MinIO-build should be changed in this file before docker-compose is run.
+For your convenience, a full setup including the generation of test data has been prepared using [Docker Compose](https://docs.docker.com/compose/reference/overview/). To build the backend services, run ```docker-compose build``` in the repository's root directory. A default configuration file can be found under ```.env```in the root folder of the repository. The default values for the local Postgres and Zenko Cloudserver should be changed in this file before docker-compose is run.
 
 Once the services are built, you can start the whole backend using ```docker-compose up```.
 The distribution service runs once and then finishes. If you want to trigger additional distribution runs, run ```docker-compose start distribution```.
@@ -57,11 +57,11 @@ The docker-compose contains the following services:
 
 Service       | Description | Endpoint and Default Credentials
 --------------|-------------|-----------
-submission    | The Corona-Warn-App submission service                                            | http://localhost:8080 
-distribution  | The Corona-Warn-App distribution service                                          | NO ENDPOINT
-postgres      | A [postgres] database installation                                                | postgres:5432 <br> Username: postgres <br> Password: postgres
-pgadmin       | A [pgadmin](https://www.pgadmin.org/) installation for the postgres database      | http://localhost:8081 <br> Username: user@domain.com <br> Password: password
-minio         | [MinIO] is an S3-compliant object store                                           | http://localhost:8082/ <br> Access key: minioadmin <br> Secret key: minioadmin
+submission    | The Corona-Warn-App submission service                                                      | http://localhost:8000 
+distribution  | The Corona-Warn-App distribution service                                                    | NO ENDPOINT
+postgres      | A [postgres] database installation                                                          | postgres:8001 <br> Username: postgres <br> Password: postgres
+pgadmin       | A [pgadmin](https://www.pgadmin.org/) installation for the postgres database                | http://localhost:8002 <br> Username: user@domain.com <br> Password: password
+cloudserver   | [Zenko CloudServer] is a S3-compliant object store  | http://localhost:8003/ <br> Access key: accessKey1 <br> Secret key: verySecretKey1
 
 #### Running Single CWA Services Using Docker
 
@@ -89,7 +89,7 @@ To prepare your machine to run the CWA project locally, we recommend that you fi
 * Minimum JDK Version 11: [OpenJDK](https://openjdk.java.net/) / [SapMachine](https://sap.github.io/SapMachine/)
 * [Maven 3.6](https://maven.apache.org/)
 * [Postgres]
-* [MinIO]
+* [Zenko CloudServer]
 
 #### Configure
 
@@ -167,8 +167,8 @@ The following public repositories are currently available for the Corona-Warn-Ap
 [cwa-documentation]: https://github.com/corona-warn-app/cwa-documentation
 [cwa-server]: https://github.com/corona-warn-app/cwa-server
 [Postgres]: https://www.postgresql.org/
-[MinIO]: https://min.io/
 [HSQLDB]: http://hsqldb.org/
+[Zenko CloudServer]: https://github.com/scality/cloudserver
 
 ## Licensing
 
diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES
--- a/THIRD-PARTY-NOTICES
+++ b/THIRD-PARTY-NOTICES
@@ -74,9 +74,15 @@ Component: Spring Boot
 Licensor:  VMWare Inc.
 Website:   https://spring.io/
 License:   Apache License 2.0
+
+Component: Zenko CloudServer
+Licensor:  Zenko
+Website:   https://github.com/scality/cloudserver
+License:   Apache License 2.0
+
 --------------------------------------------------------------------------------
 Apache License 2.0 (Commons IO, Commons Math 3, flyway, JSON-Simple,
-Maven, MinIO Object Storage, snakeyaml, Spring Boot)
+Maven, MinIO Object Storage, snakeyaml, Spring Boot, Zenko CloudServer)
 
                                  Apache License
                            Version 2.0, January 2004
diff --git a/create-bucket.sh b/create-bucket.sh
new file mode 100755
--- /dev/null
+++ b/create-bucket.sh
@@ -0,0 +1,6 @@
+# Prerequisite - install aws cli
+
+export AWS_ACCESS_KEY_ID=accessKey1
+export AWS_SECRET_ACCESS_KEY=verySecretKey1
+
+aws s3api create-bucket --bucket cwa --endpoint-url http://localhost:8000 --acl public-read
diff --git a/docker-compose.yml b/docker-compose.yml
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,49 +7,46 @@ services:
     depends_on:
       - postgres
     ports:
-      - "8080:8080"
+      - "8000:8080"
     environment: 
-      SPRING_PROFILES_ACTIVE: cloud,dev
+      SPRING_PROFILES_ACTIVE: dev
       POSTGRESQL_SERVICE_PORT: '5432'
       POSTGRESQL_SERVICE_HOST: postgres
       POSTGRESQL_DATABASE: ${POSTGRES_DB}
       POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD}
       POSTGRESQL_USER: ${POSTGRES_USER}
-    networks:
-      - cwa
   distribution:
     build:
       context: ./
       dockerfile: ./services/distribution/Dockerfile
     depends_on:
      - postgres
-     - minio
+     - objectstore
+     - create-bucket
     environment:
-      SPRING_PROFILES_ACTIVE: cloud,dev,testdata
+      SPRING_PROFILES_ACTIVE: dev,testdata
       POSTGRESQL_SERVICE_PORT: '5432'
       POSTGRESQL_SERVICE_HOST: postgres
       POSTGRESQL_DATABASE: ${POSTGRES_DB}
       POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD}
       POSTGRESQL_USER: ${POSTGRES_USER}
-      # Settings for the S3 compatible MinIO object storage
-      CWA_OBJECTSTORE_ACCESSKEY: ${MINIO_ACCESS_KEY}
-      CWA_OBJECTSTORE_SECRETKEY: ${MINIO_SECRET_KEY}
-      CWA_OBJECTSTORE_ENDPOINT: http://minio
+      # Settings for the S3 compatible objectstore
+      CWA_OBJECTSTORE_ACCESSKEY: ${OBJECTSTORE_ACCESSKEY}
+      CWA_OBJECTSTORE_SECRETKEY: ${OBJECTSTORE_SECRETKEY}
+      CWA_OBJECTSTORE_ENDPOINT: http://objectstore
       CWA_OBJECTSTORE_BUCKET: cwa
-      CWA_OBJECTSTORE_PORT: 9000
+      CWA_OBJECTSTORE_PORT: 8000
       services.distribution.paths.output: /tmp/distribution
       # Settings for cryptographic artefacts
       VAULT_FILESIGNING_SECRET: ${SECRET_PRIVATE}
       VAULT_FILESIGNING_CERT: ${SECRET_CERTIFICATE}
     volumes:
       - ./docker-compose-test-secrets:/secrets
-    networks:
-      - cwa
   postgres:
     image: postgres:9.6
     restart: always
     ports:
-      - "5432:5432"
+      - "8001:5432"
     environment:
       PGDATA: /data/postgres
       POSTGRES_DB: ${POSTGRES_DB}
@@ -57,41 +54,39 @@ services:
       POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
     volumes:
        - postgres_volume:/data/postgres
-    networks:
-      - cwa
   pgadmin:
     container_name: pgadmin_container
     image: dpage/pgadmin4
     volumes:
        - pgadmin_volume:/root/.pgadmin
     ports:
-      - "8081:80"
+      - "8002:80"
     restart: unless-stopped
-    networks:
-      - cwa
     depends_on:
       - postgres
     environment:
       PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
       PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
-  minio:
-    image: "minio/minio"
+  objectstore:
+    image: "zenko/cloudserver"
     volumes:
-      - minio_volume:/data
+      - objectstore_volume:/data
     ports:
-      - "8082:9000"
+      - "8003:8000"
     environment:
-      MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
-      MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
-    entrypoint: sh
-    command: -c 'mkdir -p /data/cwa && minio server /data'
-    networks:
-      - cwa
+      ENDPOINT: objectstore
+      REMOTE_MANAGEMENT_DISABLE: 1
+      SCALITY_ACCESS_KEY_ID: ${OBJECTSTORE_ACCESSKEY}
+      SCALITY_SECRET_ACCESS_KEY: ${OBJECTSTORE_SECRETKEY}
+  create-bucket:
+    image: amazon/aws-cli
+    environment:
+      - AWS_ACCESS_KEY_ID=${OBJECTSTORE_ACCESSKEY}
+      - AWS_SECRET_ACCESS_KEY=${OBJECTSTORE_SECRETKEY}
+    command: s3api create-bucket --bucket cwa --endpoint-url http://objectstore:8000 --acl public-read
+    depends_on:
+      - objectstore
 volumes:
-  logvolume01: {}
-  minio_volume:
   postgres_volume:
   pgadmin_volume:
-networks:
-  cwa:
-    driver: bridge
\ No newline at end of file
+  objectstore_volume:
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreAccess.java
@@ -59,10 +59,11 @@ public class ObjectStoreAccess {
 
   private static final String DEFAULT_REGION = "eu-west-1";
 
-  private final String bucket;
+  private final boolean isSetPublicReadAclOnPutObject;
 
-  private MinioClient client;
+  private final String bucket;
 
+  private final MinioClient client;
 
   /**
    * Constructs an {@link ObjectStoreAccess} instance for communication with the specified object
@@ -79,6 +80,7 @@ public ObjectStoreAccess(ObjectStoreConfigurationProperties configurationPropert
     this.client = createClient(configurationProperties);
 
     this.bucket = configurationProperties.getBucket();
+    this.isSetPublicReadAclOnPutObject = configurationProperties.isSetPublicReadAclOnPutObject();
 
     if (!this.client.bucketExists(this.bucket)) {
       throw new IllegalArgumentException("Supplied bucket does not exist " + bucket);
@@ -116,10 +118,7 @@ private boolean isSsl(ObjectStoreConfigurationProperties configurationProperties
   public void putObject(LocalFile localFile)
       throws IOException, GeneralSecurityException, MinioException {
     String s3Key = localFile.getS3Key();
-
-
-    var options = new PutObjectOptions(localFile.getFile().toFile().length(), -1);
-    options.setHeaders(createMetadataFor(localFile));
+    PutObjectOptions options = createOptionsFor(localFile);
 
     logger.info("... uploading " + s3Key);
     this.client.putObject(bucket, s3Key, localFile.getFile().toString(), options);
@@ -158,7 +157,7 @@ public List<DeleteError> deleteObjectsWithPrefix(String prefix)
    */
   public List<S3Object> getObjectsWithPrefix(String prefix)
       throws IOException, GeneralSecurityException, MinioException {
-    var objects = this.client.listObjects(bucket, prefix, true, true, false);
+    var objects = this.client.listObjects(bucket, prefix, true);
 
     var list = new ArrayList<S3Object>();
     for (Result<Item> item : objects) {
@@ -168,7 +167,14 @@ public List<S3Object> getObjectsWithPrefix(String prefix)
     return list;
   }
 
-  private Map<String, String> createMetadataFor(LocalFile file) {
-    return Map.of("cwa.hash", file.getHash());
+  private PutObjectOptions createOptionsFor(LocalFile file) {
+    var options = new PutObjectOptions(file.getFile().toFile().length(), -1);
+
+    if (this.isSetPublicReadAclOnPutObject) {
+      options.setHeaders(Map.of("x-amz-acl", "public-read"));
+    }
+
+    return options;
   }
+
 }
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/ObjectStoreConfigurationProperties.java
@@ -34,6 +34,16 @@ public class ObjectStoreConfigurationProperties {
 
   private String bucket;
 
+  private boolean setPublicReadAclOnPutObject;
+
+  public boolean isSetPublicReadAclOnPutObject() {
+    return setPublicReadAclOnPutObject;
+  }
+
+  public void setSetPublicReadAclOnPutObject(boolean setPublicReadAclOnPutObject) {
+    this.setPublicReadAclOnPutObject = setPublicReadAclOnPutObject;
+  }
+
   public int getPort() {
     return port;
   }
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/S3Object.java
@@ -38,6 +38,9 @@ public class S3Object {
    */
   private Map<String, String> metadata = new HashMap<>();
 
+  /** The e-Tag of this S3 Object. */
+  private String etag;
+
   /**
    * Constructs a new S3Object for the given object name.
    *
@@ -55,6 +58,10 @@ public Map<String, String> getMetadata() {
     return metadata;
   }
 
+  public String getEtag() {
+    return etag;
+  }
+
   /**
    * Returns a new instance of an S3Object based on the given item.
    *
@@ -68,6 +75,8 @@ public static S3Object of(Item item) {
       s3Object.metadata = item.userMetadata();
     }
 
+    s3Object.etag = item.etag().replaceAll("\"","");
+
     return s3Object;
   }
 }
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalFile.java
@@ -19,26 +19,35 @@
 
 package app.coronawarn.server.services.distribution.objectstore.publish;
 
+import com.google.common.io.BaseEncoding;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.DigestUtils;
 
 /**
  * Represents a file, which is subject for publishing to S3.
  */
 public abstract class LocalFile {
 
-  /** the path to the file to be represented. */
+  private static final Logger logger = LoggerFactory.getLogger(LocalFile.class);
+
+  /**
+   * the path to the file to be represented.
+   */
   private final Path file;
 
-  /** the assigned S3 key. */
+  /**
+   * the assigned S3 key.
+   */
   private final String s3Key;
 
-  /** the hash of this file. */
-  private final String hash;
+  /**
+   * the etag of this file.
+   */
+  private final String etag;
 
   /**
    * Constructs a new file representing a file on the disk.
@@ -48,7 +57,7 @@ public abstract class LocalFile {
    */
   public LocalFile(Path file, Path basePath) {
     this.file = file;
-    this.hash = hash();
+    this.etag = computeS3ETag();
     this.s3Key = createS3Key(file, basePath);
   }
 
@@ -56,23 +65,25 @@ public String getS3Key() {
     return s3Key;
   }
 
-  public String getHash() {
-    return hash;
+  public String getEtag() {
+    return etag;
   }
 
   public Path getFile() {
     return file;
   }
 
-  private String hash() {
+  private String computeS3ETag() {
     try {
-      MessageDigest digester = MessageDigest.getInstance("SHA-256");
-      digester.update(Files.readAllBytes(file));
+      String md5 = DigestUtils.md5DigestAsHex(Files.readAllBytes(file));
+      byte[] raw = BaseEncoding.base16().decode(md5.toUpperCase());
 
-      return Base64.getEncoder().encodeToString(digester.digest());
-    } catch (IOException | NoSuchAlgorithmException e) {
-      throw new RuntimeException("Unable to compute hashes due to ", e);
+      return DigestUtils.md5DigestAsHex(raw) + "-1";
+    } catch (IOException e) {
+      logger.warn("Unable to compute E-Tag", e);
     }
+
+    return "";
   }
 
   protected String createS3Key(Path file, Path rootFolder) {
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/LocalIndexFile.java
@@ -51,9 +51,7 @@ public LocalIndexFile(Path file, Path basePath) {
   @Override
   protected String createS3Key(Path file, Path rootFolder) {
     String s3Key = super.createS3Key(file, rootFolder);
-
-    // Deactivate index mapping for now
-    // return s3Key.substring(0, s3Key.length() - INDEX_FILE_SUFFIX.length());
-    return s3Key;
+    
+    return s3Key.substring(0, s3Key.length() - INDEX_FILE_SUFFIX.length());
   }
 }
diff --git a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java
--- a/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java
+++ b/services/distribution/src/main/java/app/coronawarn/server/services/distribution/objectstore/publish/PublishedFileSet.java
@@ -62,15 +62,7 @@ public boolean isNotYetPublished(LocalFile file) {
       return true;
     }
 
-    return !hasSameHashAsPublishedFile(file);
-  }
-
-  private boolean hasSameHashAsPublishedFile(LocalFile file) {
-    var metaData = s3Objects.get(file.getS3Key()).getMetadata();
-
-    String s3FileHash = metaData.get("X-Amz-Meta-Cwa.hash");
-
-    return file.getHash().equals(s3FileHash);
+    return !file.getEtag().equals(published.getEtag());
   }
 
 }
diff --git a/services/distribution/src/main/java/io/minio/messages/Item.java b/services/distribution/src/main/java/io/minio/messages/Item.java
new file mode 100644
--- /dev/null
+++ b/services/distribution/src/main/java/io/minio/messages/Item.java
@@ -0,0 +1,132 @@
+/*
+ * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2015 MinIO, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.minio.messages;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.Root;
+
+/* ----------------------------------------------------------------
+ * Copied from MinIO due to patch not yet available.
+ * https://github.com/minio/minio-java/pull/921
+ * Waiting for new release version: 7.0.3
+ * ----------------------------------------------------------------
+ */
+
+/**
+ * Helper class to denote Object information in {@link ListBucketResult} and {@link
+ * ListBucketResultV1}.
+ */
+@Root(name = "Contents", strict = false)
+public class Item {
+
+  @Element(name = "Key")
+  private String objectName;
+
+  @Element(name = "LastModified")
+  private ResponseDate lastModified;
+
+  @Element(name = "ETag")
+  private String etag;
+
+  @Element(name = "Size")
+  private long size;
+
+  @Element(name = "StorageClass")
+  private String storageClass;
+
+  @Element(name = "Owner", required = false) /* Monkeypatch: Owner should be optional */
+  private Owner owner;
+
+  @Element(name = "UserMetadata", required = false)
+  private Metadata userMetadata;
+
+  private boolean isDir = false;
+
+  public Item() {
+
+  }
+
+  /**
+   * Constructs a new Item for prefix i.e. directory.
+   */
+  public Item(String prefix) {
+    this.objectName = prefix;
+    this.isDir = true;
+  }
+
+  /**
+   * Returns object name.
+   */
+  public String objectName() {
+    return objectName;
+  }
+
+  /**
+   * Returns last modified time of the object.
+   */
+  public ZonedDateTime lastModified() {
+    return lastModified.zonedDateTime();
+  }
+
+  /**
+   * Returns ETag of the object.
+   */
+  public String etag() {
+    return etag;
+  }
+
+  /**
+   * Returns object size.
+   */
+  public long size() {
+    return size;
+  }
+
+  /**
+   * Returns storage class of the object.
+   */
+  public String storageClass() {
+    return storageClass;
+  }
+
+  /**
+   * Returns owner object of given the object.
+   */
+  public Owner owner() {
+    return owner;
+  }
+
+  /**
+   * Returns user metadata. This is MinIO specific extension to ListObjectsV2.
+   */
+  public Map<String, String> userMetadata() {
+    if (userMetadata == null) {
+      return null;
+    }
+
+    return userMetadata.get();
+  }
+
+  /**
+   * Returns whether the object is a directory or not.
+   */
+  public boolean isDir() {
+    return isDir;
+  }
+}
diff --git a/services/distribution/src/main/resources/application-cloud.properties b/services/distribution/src/main/resources/application-cloud.properties
--- a/services/distribution/src/main/resources/application-cloud.properties
+++ b/services/distribution/src/main/resources/application-cloud.properties
@@ -13,3 +13,4 @@ cwa.objectstore.secretKey=${CWA_OBJECTSTORE_SECRETKEY}
 cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT}
 cwa.objectstore.bucket=${CWA_OBJECTSTORE_BUCKET}
 cwa.objectstore.port=${CWA_OBJECTSTORE_PORT}
+cwa.objectstore.set-public-read-acl-on-put-object=false
diff --git a/services/distribution/src/main/resources/application.properties b/services/distribution/src/main/resources/application.properties
--- a/services/distribution/src/main/resources/application.properties
+++ b/services/distribution/src/main/resources/application.properties
@@ -8,11 +8,12 @@ services.distribution.paths.privatekey=${VAULT_FILESIGNING_SECRET}
 services.distribution.paths.certificate=${VAULT_FILESIGNING_CERT}
 
 # Configuration for the S3 compatible object storage hosted by Telekom in Germany
-cwa.objectstore.accessKey=${CWA_OBJECTSTORE_ACCESSKEY:minioadmin}
-cwa.objectstore.secretKey=${CWA_OBJECTSTORE_SECRETKEY:minioadmin}
-cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT:http\://localhost\:9000}
+cwa.objectstore.access-key=${CWA_OBJECTSTORE_ACCESSKEY:accessKey1}
+cwa.objectstore.secret-key=${CWA_OBJECTSTORE_SECRETKEY:verySecretKey1}
+cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT:http\://localhost\:8003}
 cwa.objectstore.bucket=${CWA_OBJECTSTORE_BUCKET:cwa}
-cwa.objectstore.port=${CWA_OBJECTSTORE_PORT:9000}
+cwa.objectstore.port=${CWA_OBJECTSTORE_PORT:8003}
+cwa.objectstore.set-public-read-acl-on-put-object=true
 
 # Postgres configuration
 spring.jpa.hibernate.ddl-auto=validate

</patch>
diff --git a/services/distribution/src/test/resources/application.properties b/services/distribution/src/test/resources/application.properties
--- a/services/distribution/src/test/resources/application.properties
+++ b/services/distribution/src/test/resources/application.properties
@@ -14,9 +14,9 @@ spring.flyway.locations=classpath:db/migration/h2
 spring.jpa.hibernate.ddl-auto=validate
 
 # S3 object store configuration
-cwa.objectstore.accessKey=${CWA_OBJECTSTORE_ACCESSKEY:minioadmin}
-cwa.objectstore.secretKey=${CWA_OBJECTSTORE_SECRETKEY:minioadmin}
-cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT:http\://localhost\:9000}
+cwa.objectstore.access-key=${CWA_OBJECTSTORE_ACCESSKEY:accessKey1}
+cwa.objectstore.secret-key=${CWA_OBJECTSTORE_SECRETKEY:verySecretKey1}
+cwa.objectstore.endpoint=${CWA_OBJECTSTORE_ENDPOINT:http\://localhost\:8003}
 cwa.objectstore.bucket=${CWA_OBJECTSTORE_BUCKET:cwa}
-cwa.objectstore.port=${CWA_OBJECTSTORE_PORT:9000}
-
+cwa.objectstore.port=${CWA_OBJECTSTORE_PORT:8003}
+cwa.objectstore.set-public-read-acl-on-put-object=true
diff --git a/services/distribution/src/test/resources/objectstore/publisher/version/v1/indexfile b/services/distribution/src/test/resources/objectstore/publisher/version/v1/index
similarity index 100%
rename from services/distribution/src/test/resources/objectstore/publisher/version/v1/indexfile
rename to services/distribution/src/test/resources/objectstore/publisher/version/v1/index
