diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java index 762ce2345c..d726714dba 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java @@ -20,6 +20,7 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; import org.eclipse.hawkbit.cache.DownloadIdCache; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; @@ -81,9 +82,13 @@ import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import org.springframework.security.web.firewall.FirewalledRequest; +import org.springframework.security.web.firewall.HttpFirewall; +import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.security.web.session.SessionManagementFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; @@ -583,6 +588,51 @@ private CorsConfiguration corsConfiguration() { } } + + /** + * HttpFirewall which enables to define a list of allowed host names. + * + * @return the http firewall. + */ + @Bean + public HttpFirewall httpFirewall(final HawkbitSecurityProperties hawkbitSecurityProperties) { + final List allowedHostNames = hawkbitSecurityProperties.getAllowedHostNames(); + final IgnorePathsStrictHttpFirewall firewall = new IgnorePathsStrictHttpFirewall( + hawkbitSecurityProperties.getHttpFirewallIgnoredPaths()); + + if (!CollectionUtils.isEmpty(allowedHostNames)) { + firewall.setAllowedHostnames(hostName -> { + LOG.debug("Firewall check host: {}, allowed: {}", hostName, allowedHostNames.contains(hostName)); + return allowedHostNames.contains(hostName); + }); + } + return firewall; + } + + + private static class IgnorePathsStrictHttpFirewall extends StrictHttpFirewall { + + private final Collection pathsToIgnore; + + public IgnorePathsStrictHttpFirewall(final Collection pathsToIgnore) { + super(); + this.pathsToIgnore = pathsToIgnore; + } + + @Override + public FirewalledRequest getFirewalledRequest(final HttpServletRequest request) { + if (pathsToIgnore != null && pathsToIgnore.contains(request.getRequestURI())) { + return new FirewalledRequest(request) { + @Override + public void reset() { + // nothing to do + } + }; + } + return super.getFirewalledRequest(request); + } + } + private static AuthenticationManager setAuthenticationManager(final HttpSecurity http, final DdiSecurityProperties ddiSecurityConfiguration) throws Exception { // configure authentication manager final AuthenticationManager authenticationManager = diff --git a/hawkbit-runtime/.gitignore b/hawkbit-runtime/.gitignore new file mode 100644 index 0000000000..035c2989d8 --- /dev/null +++ b/hawkbit-runtime/.gitignore @@ -0,0 +1 @@ +**/artifactrepo/ diff --git a/hawkbit-runtime/docker/README.md b/hawkbit-runtime/docker/README.md index 3f18ab2e66..5ec99eb4fa 100644 --- a/hawkbit-runtime/docker/README.md +++ b/hawkbit-runtime/docker/README.md @@ -27,7 +27,7 @@ Start the hawkBit Update Server and Device Simulator together with an MySQL and ```bash $ docker swarm init -$ docker stack deploy -c docker-compose-stack.yml hawkbit +$ docker stack deploy -c docker-compose-deps-mysql.yml hawkbit ``` # Access diff --git a/hawkbit-runtime/docker/docker-compose-deps-mysql.yml b/hawkbit-runtime/docker/docker-compose-deps-mysql.yml new file mode 100644 index 0000000000..62c725813b --- /dev/null +++ b/hawkbit-runtime/docker/docker-compose-deps-mysql.yml @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +version: '3.7' + +services: + # --------------------- + # MySQL service + # --------------------- + mysql: + image: "mysql:8.0" + environment: + MYSQL_DATABASE: "hawkbit" + # MYSQL_USER: "root" is created by default in the container for mysql 8.0+ + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + restart: always + ports: + - "3306:3306" + labels: + NAME: "mysql" + + # --------------------- + # RabbitMQ service + # --------------------- + rabbitmq: + image: "rabbitmq:3-management-alpine" + hostname: "rabbitmq" + environment: + RABBITMQ_DEFAULT_VHOST: "/" + RABBITMQ_DEFAULT_USER: "guest" + RABBITMQ_DEFAULT_PASS: "guest" + ports: + - "15672:15672" + - "5672:5672" + deploy: + restart_policy: + condition: on-failure + diff --git a/hawkbit-runtime/docker/docker-compose-deps-postgres.yml b/hawkbit-runtime/docker/docker-compose-deps-postgres.yml new file mode 100644 index 0000000000..cc10d906d5 --- /dev/null +++ b/hawkbit-runtime/docker/docker-compose-deps-postgres.yml @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +version: '3.7' + +services: + # --------------------- + # Postgres service + # --------------------- + postgres: + image: "postgres:16.1" + ports: + - "5432:5432" + deploy: + restart_policy: + condition: on-failure + environment: + POSTGRES_USER: "postgres" + POSTGRES_PASSWORD: "admin" + POSTGRES_DB: "hawkbit" + + # --------------------- + # RabbitMQ service + # --------------------- + rabbitmq: + image: "rabbitmq:3-management-alpine" + hostname: "rabbitmq" + environment: + RABBITMQ_DEFAULT_VHOST: "/" + RABBITMQ_DEFAULT_USER: "guest" + RABBITMQ_DEFAULT_PASS: "guest" + ports: + - "15672:15672" + - "5672:5672" + deploy: + restart_policy: + condition: on-failure + diff --git a/hawkbit-runtime/docker/docker-compose-micro-services-mysql.yml b/hawkbit-runtime/docker/docker-compose-micro-services-mysql.yml new file mode 100644 index 0000000000..eaa5950158 --- /dev/null +++ b/hawkbit-runtime/docker/docker-compose-micro-services-mysql.yml @@ -0,0 +1,82 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +version: '3.7' + +include: + - docker-compose-deps-mysql.yml + +services: + + # --------------------- + # HawkBit DDI + # --------------------- + hawkbit-ddi: + image: "hawkbit/hawkbit-ddi-server:latest-mysql" + environment: + - 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit' + - 'SPRING_RABBITMQ_HOST=rabbitmq' + - 'SPRING_RABBITMQ_USERNAME=guest' + - 'SPRING_RABBITMQ_PASSWORD=guest' + - 'SPRING_DATASOURCE_USERNAME=root' + restart: always + ports: + - "8081:8081" + labels: + NAME: "hawkbit-ddi" + + # --------------------- + # HawkBit DMF + # --------------------- + hawkbit-dmf: + image: "hawkbit/hawkbit-dmf-server:latest-mysql" + environment: + - 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit' + - 'SPRING_RABBITMQ_HOST=rabbitmq' + - 'SPRING_RABBITMQ_USERNAME=guest' + - 'SPRING_RABBITMQ_PASSWORD=guest' + - 'SPRING_DATASOURCE_USERNAME=root' + restart: always + labels: + NAME: "hawkbit-dmf" + + # --------------------- + # HawkBit MGMT + # --------------------- + hawkbit-mgmt: + image: "hawkbit/hawkbit-mgmt-server:latest-mysql" + environment: + - 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit' + - 'SPRING_RABBITMQ_HOST=rabbitmq' + - 'SPRING_RABBITMQ_USERNAME=guest' + - 'SPRING_RABBITMQ_PASSWORD=guest' + - 'SPRING_DATASOURCE_USERNAME=root' + restart: always + ports: + - "8080:8080" + labels: + NAME: "hawkbit-mgmt" + + + # --------------------- + # HawkBit MGMT + # --------------------- + hawkbit-vv8ui: + image: "hawkbit/hawkbit-vv8-ui:latest-mysql" + environment: + - 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit' + - 'SPRING_RABBITMQ_HOST=rabbitmq' + - 'SPRING_RABBITMQ_USERNAME=guest' + - 'SPRING_RABBITMQ_PASSWORD=guest' + - 'SPRING_DATASOURCE_USERNAME=root' + restart: always + ports: + - "8082:8082" + labels: + NAME: "hawkbit-vv8-ui" \ No newline at end of file diff --git a/hawkbit-runtime/docker/docker-compose.yml b/hawkbit-runtime/docker/docker-compose-monolith-mysql.yml similarity index 100% rename from hawkbit-runtime/docker/docker-compose.yml rename to hawkbit-runtime/docker/docker-compose-monolith-mysql.yml diff --git a/hawkbit-runtime/docker/docker-compose-stack.yml b/hawkbit-runtime/docker/docker-compose-stack.yml deleted file mode 100644 index 48a0509188..0000000000 --- a/hawkbit-runtime/docker/docker-compose-stack.yml +++ /dev/null @@ -1,86 +0,0 @@ -# -# Copyright (c) 2018 Bosch Software Innovations GmbH and others -# -# This program and the accompanying materials are made -# available under the terms of the Eclipse Public License 2.0 -# which is available at https://www.eclipse.org/legal/epl-2.0/ -# -# SPDX-License-Identifier: EPL-2.0 -# -version: '3.7' - -services: - - # --------------------- - # MySQL service - # --------------------- - mysql: - image: "mysql:8.0" - networks: - - hawknet - ports: - - "3306:3306" - deploy: - restart_policy: - condition: on-failure - environment: - MYSQL_DATABASE: "hawkbit" - # MYSQL_USER: "root" is created by default in the container for mysql 8.0+ - MYSQL_ALLOW_EMPTY_PASSWORD: "true" - - # --------------------- - # RabbitMQ service - # --------------------- - rabbitmq: - image: "rabbitmq:3-management" - networks: - - hawknet - ports: - - "15672:15672" - - "5672:5672" - deploy: - restart_policy: - condition: on-failure - - # --------------------- - # hawkBit service - # --------------------- - hawkbit: - image: "hawkbit/hawkbit-update-server:latest-mysql" - networks: - - hawknet - ports: - - "8080:8080" - deploy: - restart_policy: - condition: on-failure - environment: - - 'SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/hawkbit' - - 'SPRING_DATASOURCE_USERNAME=root' - - 'SPRING_RABBITMQ_HOST=rabbitmq' - - 'SPRING_RABBITMQ_USERNAME=guest' - - 'SPRING_RABBITMQ_PASSWORD=guest' - - # --------------------- - # hawkBit simulator - # --------------------- - simulator: - image: "hawkbit/hawkbit-device-simulator:latest" - networks: - - hawknet - ports: - - "8083:8083" - deploy: - restart_policy: - condition: on-failure - environment: - - 'HAWKBIT_DEVICE_SIMULATOR_AUTOSTARTS_[0]_TENANT=DEFAULT' - - 'SPRING_RABBITMQ_VIRTUALHOST=/' - - 'SPRING_RABBITMQ_HOST=rabbitmq' - - 'SPRING_RABBITMQ_PORT=5672' - - 'SPRING_RABBITMQ_USERNAME=guest' - - 'SPRING_RABBITMQ_PASSWORD=guest' - -networks: - hawknet: - driver: overlay diff --git a/hawkbit-runtime/docker/docker_build/build_all_dev.sh b/hawkbit-runtime/docker/docker_build/build_all_dev.sh new file mode 100755 index 0000000000..161895ec68 --- /dev/null +++ b/hawkbit-runtime/docker/docker_build/build_all_dev.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# +# Copyright (c) 2023 Bosch.IO GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +set -xe + +VERSION=0.4.0-SNAPSHOT +FLAVOUR="standard" +MVN_REPO=~/.m2/repository + +while getopts v:f:r: option +do + case "${option}" + in + v)VERSION=${OPTARG};; + f)FLAVOUR=${OPTARG};; + r)MVN_REPO=${OPTARG};; + esac +done + +echo "hawkBit version : ${VERSION}" +echo "docker image flavour : ${FLAVOUR}" +echo "maven repository : ${MVN_REPO}" + +if [ ${FLAVOUR} == "mysql" ] +then + DOCKER_FILE="Dockerfile_dev-mysql" + TAG_SUFFIX="-mysql" +else + DOCKER_FILE="Dockerfile_dev" + TAG_SUFFIX="" +fi + +echo "docker file : ${DOCKER_FILE}" + +docker build -t hawkbit/hawkbit-ddi-server:${VERSION}${TAG_SUFFIX} -t hawkbit/hawkbit-ddi-server:latest${TAG_SUFFIX} --build-arg HAWKBIT_APP=hawkbit-ddi-server --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}" +docker build -t hawkbit/hawkbit-dmf-server:${VERSION}${TAG_SUFFIX} -t hawkbit/hawkbit-dmf-server:latest${TAG_SUFFIX} --build-arg HAWKBIT_APP=hawkbit-dmf-server --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}" +docker build -t hawkbit/hawkbit-mgmt-server:${VERSION}${TAG_SUFFIX} -t hawkbit/hawkbit-mgmt-server:latest${TAG_SUFFIX} --build-arg HAWKBIT_APP=hawkbit-mgmt-server --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}" +docker build -t hawkbit/hawkbit-vv8-ui:${VERSION}${TAG_SUFFIX} -t hawkbit/hawkbit-vv8-ui:latest${TAG_SUFFIX} --build-arg HAWKBIT_APP=hawkbit-vv8-ui --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}" diff --git a/hawkbit-runtime/hawkbit-ddi-server/README.md b/hawkbit-runtime/hawkbit-ddi-server/README.md new file mode 100644 index 0000000000..208da10710 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/README.md @@ -0,0 +1,50 @@ +# hawkBit DDI Server +The hawkBit DDI Server is a standalone spring-boot application with an embedded servlet container. It should be started with at least hawkbit-mgmt-server. + +## On your own workstation + +### Run + +```bash +java -jar hawkbit-runtime/hawkbit-ddi-server/target/hawkbit-ddi-server-*-SNAPSHOT.jar +``` + +_(Note: you have to add the JDBC driver also to your class path if you intend to use another database than H2.)_ + +Or: + +```bash +run org.eclipse.hawkbit.app.ddi.DDIStart +``` + +### Usage +The Management API can be accessed via http://localhost:8081/rest/v1 +The root url http://localhost:8081 will redirect directly to the Swagger Management UI + +### Clustering (Experimental!!!) +The micro-service instances are configured to communicate via Spring Cloud Bus. You could run multiple instances of any micro-service but hawkbit-mgmt-server. Management server run some schedulers which shall not run simultaneously - e.g. auto assignment checker and rollouts executor. To run multiple management server instances you shall do some extensions of hawkbit to ensure that they wont run schedulers simultaneously or you shall configure all instances but one to do not run schedulers! + +## Optional Protostuff for Sprign cloud bus +The micro-service instances are configured to communicate via Spring Cloud Bus. Optionally, you could use [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance. + +**Note**: If Protostuff is enabled it shall be enabled on all microservices! + +Add/Uncomment to/in your `application.properties` : + +```properties +spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff +``` + +Add to your `pom.xml` : + +```xml + + io.protostuff + protostuff-core + + + io.protostuff + protostuff-runtime + +``` \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-ddi-server/pom.xml b/hawkbit-runtime/hawkbit-ddi-server/pom.xml new file mode 100644 index 0000000000..c9462c8715 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-runtime-parent + ${revision} + + hawkbit-ddi-server + hawkBit :: Runtime :: DDI Server + + + org.eclipse.hawkbit.app.ddi.DDIStart + + + + + org.eclipse.hawkbit + hawkbit-boot-starter-ddi-api + ${project.version} + + + + org.springframework.cloud + spring-cloud-stream-binder-rabbit + + + diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java b/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java new file mode 100644 index 0000000000..eb1875ee68 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/java/org/eclipse/hawkbit/app/ddi/DDIStart.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.ddi; + +import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.view.RedirectView; + +/** + * A {@link SpringBootApplication} annotated class with a main method to start. + * The minimal configuration for the stand alone hawkBit DDI server. + */ +@SpringBootApplication +@EnableHawkbitManagedSecurityConfiguration +public class DDIStart { + + /** + * Main method to start the spring-boot application. + * + * @param args + * the VM arguments. + */ + public static void main(final String[] args) { + SpringApplication.run(DDIStart.class, args); + } + + @Controller + public static class RedirectController { + + @GetMapping("/") + public RedirectView redirectToSwagger( + RedirectAttributes attributes) { + attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectView"); + attributes.addAttribute("attribute", "redirectWithRedirectView"); + return new RedirectView("swagger-ui/index.html"); + } + } +} diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-db2.properties b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-db2.properties new file mode 100644 index 0000000000..16a0fa0b8c --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-db2.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a DB2 DB usage. +# Keep in mind that you need the DB2 driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=DB2 +spring.datasource.url=jdbc:db2://localhost:50000/hawkbit +spring.datasource.username=db2inst1 +spring.datasource.password=db2inst1-pwd +spring.datasource.driverClassName=com.ibm.db2.jcc.DB2Driver diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mssql.properties b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mssql.properties new file mode 100644 index 0000000000..a00c95aa8e --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mssql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a Microsoft SQL Server DB usage. +# Keep in mind that you need the SQL server driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=SQL_SERVER +spring.datasource.url=jdbc:sqlserver://localhost:1433;database=hawkbit +spring.datasource.username=SA +spring.datasource.password= +spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mysql.properties b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mysql.properties new file mode 100644 index 0000000000..979fec5630 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-mysql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a MySQL DB usage. +# Keep in mind that you need the MariaDB driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=MYSQL +spring.datasource.url=jdbc:mariadb://localhost:3306/hawkbit +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driverClassName=org.mariadb.jdbc.Driver diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-postgresql.properties b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-postgresql.properties new file mode 100644 index 0000000000..8b7a40af52 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application-postgresql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2020 Enapter Co.,Ltd +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a PostgreSQL usage. +# Keep in mind that you need the PostgreSQL driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=POSTGRESQL +spring.datasource.url=jdbc:postgresql://localhost:5432/hawkbit +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driverClassName=org.postgresql.Driver diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application.properties b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application.properties new file mode 100644 index 0000000000..6cf0e72fea --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/application.properties @@ -0,0 +1,76 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +spring.application.name=ddi-server +server.port=8081 + +# User Security +spring.security.user.name=admin +spring.security.user.password={noop}admin +spring.main.allow-bean-definition-overriding=true + +# Http Encoding +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.enabled=true +server.servlet.encoding.force=true + +# DDI authentication configuration +hawkbit.server.ddi.security.authentication.anonymous.enabled=false +hawkbit.server.ddi.security.authentication.targettoken.enabled=false +hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false + +# Optional events +hawkbit.server.repository.publish-target-poll-event=false + +## Configuration for DMF/RabbitMQ integration +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 + +# Enable CORS and specify the allowed origins: +#hawkbit.server.security.cors.enabled=true +#hawkbit.server.security.cors.allowedOrigins=http://localhost + +# Swagger Configuration +#springdoc.swagger-ui.path=/update-server-documentation +#springdoc.api-docs.path=/update-server-api-docs +springdoc.show-oauth2-endpoints=true +springdoc.api-docs.version=openapi_3_0 +springdoc.show-login-endpoint=true +springdoc.packages-to-scan=org.eclipse.hawkbit.ddi +springdoc.swagger-ui.oauth2RedirectUrl=/login/oauth2/code/suite +springdoc.paths-to-exclude=/system/** + +# Flyway disabled - US only +spring.flyway.enabled=false +## SQL Database Configuration - END + +## No Schedulers - START +hawkbit.autoassign.scheduler.enabled=false +hawkbit.rollout.scheduler.enabled=false +## No Schedulers - END + +# Disable discovery client of spring-cloud-commons +spring.cloud.discovery.enabled=false +# Enable communication between services +spring.cloud.bus.enabled=true +spring.cloud.bus.ack.enabled=false +spring.cloud.bus.refresh.enabled=false +spring.cloud.bus.env.enabled=false +endpoints.spring.cloud.bus.refresh.enabled=false +endpoints.spring.cloud.bus.env.enabled=false +spring.cloud.stream.bindings.springCloudBusInput.group=ddi-server + +# To use protostuff (for instance fot improved performance) you shall uncomment +# the following two lines and add io.protostuff:protostuff-core and io.protostuff:protostuff-runtime to dependencies +#spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +#spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/banner.txt b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/banner.txt new file mode 100644 index 0000000000..63097dd440 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/banner.txt @@ -0,0 +1,14 @@ +______ _ _ _ _ ____ _ _ _____ _____ _____ +| ____| | (_) | | | | | _ \(_) | | __ \| __ \_ _| +| |__ ___| |_ _ __ ___ ___ | |__ __ ___ _| | _| |_) |_| |_ | | | | | | || | +| __| / __| | | '_ \/ __|/ _ \ | '_ \ / _` \ \ /\ / / |/ / _ <| | __| | | | | | | || | +| |___| (__| | | |_) \__ \ __/ | | | | (_| |\ V V /| <| |_) | | |_ | |__| | |__| || |_ +|______\___|_|_| .__/|___/\___| |_| |_|\__,_| \_/\_/ |_|\_\____/|_|\__| |_____/|_____/_____| + | | + |_| + +Eclipse hawkBit DDI Server ${application.formatted-version} +using Spring Boot ${spring-boot.formatted-version} + +Go to https://www.eclipse.org/hawkbit for more information. + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/logback-spring.xml b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..cd0c5b2394 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/main/resources/logback-spring.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java new file mode 100644 index 0000000000..04b2934ef7 --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AbstractSecurityTest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2020 Bosch.IO GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.ddi; + +import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest(properties = { "hawkbit.dmf.rabbitmq.enabled=false" }) +@ExtendWith(SharedSqlTestDatabaseExtension.class) +public abstract class AbstractSecurityTest { + + @Autowired + private WebApplicationContext context; + + protected MockMvc mvc; + + @BeforeEach + public void setup() { + final DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true); + mvc = builder.build(); + } +} diff --git a/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AllowedHostNamesTest.java b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AllowedHostNamesTest.java new file mode 100644 index 0000000000..cb5c447fea --- /dev/null +++ b/hawkbit-runtime/hawkbit-ddi-server/src/test/java/org/eclipse/hawkbit/app/ddi/AllowedHostNamesTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.ddi; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import io.qameta.allure.Description; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.security.web.firewall.RequestRejectedException; + +import io.qameta.allure.Feature; +import io.qameta.allure.Story; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = { "hawkbit.server.security.allowedHostNames=localhost", + "hawkbit.server.security.httpFirewallIgnoredPaths=/index.html" }) +@Feature("Integration Test - Security") +@Story("Allowed Host Names") +public class AllowedHostNamesTest extends AbstractSecurityTest { + + @Test + @Description("Tests whether a RequestRejectedException is thrown when not allowed host is used") + public void allowedHostNameWithNotAllowedHost() { + assertThatExceptionOfType(RequestRejectedException.class).isThrownBy( + () -> mvc.perform(get("/").header(HttpHeaders.HOST, "www.google.com"))); + } + + @Test + @Description("Tests whether request is redirected when allowed host is used") + public void allowedHostNameWithAllowedHost() throws Exception { + mvc.perform(get("/").header(HttpHeaders.HOST, "localhost")).andExpect(status().is3xxRedirection()); + } + + @Test + @Description("Tests whether request without allowed host name and with ignored path end up with a client error") + public void notAllowedHostnameWithIgnoredPath() throws Exception { + mvc.perform(get("/index.html").header(HttpHeaders.HOST, "www.google.com")) + .andExpect(status().is4xxClientError()); + } +} \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-dmf-server/README.md b/hawkbit-runtime/hawkbit-dmf-server/README.md new file mode 100644 index 0000000000..cc546e90ac --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/README.md @@ -0,0 +1,46 @@ +# hawkBit DMF Server +The hawkBit DMF Server is a standalone spring-boot application with an embedded servlet container. It should be started with at least hawkbit-mgmt-server. + +## On your own workstation + +### Run + +```bash +java -jar hawkbit-runtime/hawkbit-dmf-server/target/hawkbit-dmf-server-*-SNAPSHOT.jar +``` + +_(Note: you have to add the JDBC driver also to your class path if you intend to use another database than H2.)_ + +Or: + +```bash +run org.eclipse.hawkbit.app.dmf.DMFStart +``` + +### Clustering (Experimental!!!) +The micro-service instances are configured to communicate via Spring Cloud Bus. You could run multiple instances of any micro-service but hawkbit-mgmt-server. Management server run some schedulers which shall not run simultaneously - e.g. auto assignment checker and rollouts executor. To run multiple management server instances you shall do some extensions of hawkbit to ensure that they wont run schedulers simultaneously or you shall configure all instances but one to do not run schedulers! + +## Optional Protostuff for Sprign cloud bus +The micro-service instances are configured to communicate via Spring Cloud Bus. Optionally, you could use [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance. + +**Note**: If Protostuff is enabled it shall be enabled on all microservices! + +Add/Uncomment to/in your `application.properties` : + +```properties +spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff +``` + +Add to your `pom.xml` : + +```xml + + io.protostuff + protostuff-core + + + io.protostuff + protostuff-runtime + +``` \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-dmf-server/pom.xml b/hawkbit-runtime/hawkbit-dmf-server/pom.xml new file mode 100644 index 0000000000..92f0e4aeac --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-runtime-parent + ${revision} + + hawkbit-dmf-server + hawkBit :: Runtime :: DMF Server + + + org.eclipse.hawkbit.app.ddi.DMFStart + + + + + org.eclipse.hawkbit + hawkbit-boot-starter-dmf-api + ${project.version} + + + + org.springframework.cloud + spring-cloud-stream-binder-rabbit + + + diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java b/hawkbit-runtime/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java new file mode 100644 index 0000000000..923f60bf07 --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/java/org/eclipse/hawkbit/app/dmf/DMFStart.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.dmf; + +import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * A {@link SpringBootApplication} annotated class with a main method to start. + * The minimal configuration for the stand alone hawkBit DMF server. + */ +@SpringBootApplication +@EnableHawkbitManagedSecurityConfiguration +public class DMFStart { + + /** + * Main method to start the spring-boot application. + * + * @param args the VM arguments. + */ + public static void main(final String[] args) { + SpringApplication.run(DMFStart.class, args); + } +} diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-db2.properties b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-db2.properties new file mode 100644 index 0000000000..16a0fa0b8c --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-db2.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a DB2 DB usage. +# Keep in mind that you need the DB2 driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=DB2 +spring.datasource.url=jdbc:db2://localhost:50000/hawkbit +spring.datasource.username=db2inst1 +spring.datasource.password=db2inst1-pwd +spring.datasource.driverClassName=com.ibm.db2.jcc.DB2Driver diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mssql.properties b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mssql.properties new file mode 100644 index 0000000000..a00c95aa8e --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mssql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a Microsoft SQL Server DB usage. +# Keep in mind that you need the SQL server driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=SQL_SERVER +spring.datasource.url=jdbc:sqlserver://localhost:1433;database=hawkbit +spring.datasource.username=SA +spring.datasource.password= +spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mysql.properties b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mysql.properties new file mode 100644 index 0000000000..979fec5630 --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-mysql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a MySQL DB usage. +# Keep in mind that you need the MariaDB driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=MYSQL +spring.datasource.url=jdbc:mariadb://localhost:3306/hawkbit +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driverClassName=org.mariadb.jdbc.Driver diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-postgresql.properties b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-postgresql.properties new file mode 100644 index 0000000000..8b7a40af52 --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application-postgresql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2020 Enapter Co.,Ltd +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a PostgreSQL usage. +# Keep in mind that you need the PostgreSQL driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=POSTGRESQL +spring.datasource.url=jdbc:postgresql://localhost:5432/hawkbit +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driverClassName=org.postgresql.Driver diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application.properties b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application.properties new file mode 100644 index 0000000000..7d0d0aa534 --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/application.properties @@ -0,0 +1,51 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +spring.application.name=dmf-server +spring.main.allow-bean-definition-overriding=true + +# Optional events +hawkbit.server.repository.publish-target-poll-event=false + +## Configuration for DMF/RabbitMQ integration +hawkbit.dmf.rabbitmq.enabled=true +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 + +spring.main.web-application-type=none +hawkbit.server.security.dos.filter.enabled=false + +# Flyway disabled - US only +spring.flyway.enabled=false +## SQL Database Configuration - END + +## No Schedulers - START +hawkbit.autoassign.scheduler.enabled=false +hawkbit.rollout.scheduler.enabled=false +## No Schedulers - END + +# Disable discovery client of spring-cloud-commons +spring.cloud.discovery.enabled=false +# Enable communication between services +spring.cloud.bus.enabled=true +spring.cloud.bus.ack.enabled=false +spring.cloud.bus.refresh.enabled=false +spring.cloud.bus.env.enabled=false +endpoints.spring.cloud.bus.refresh.enabled=false +endpoints.spring.cloud.bus.env.enabled=false +spring.cloud.stream.bindings.springCloudBusInput.group=dmf-server + +# To use protostuff (for instance fot improved performance) you shall uncomment +# the following two lines and add io.protostuff:protostuff-core and io.protostuff:protostuff-runtime to dependencies +#spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +#spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/banner.txt b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/banner.txt new file mode 100644 index 0000000000..f5591333ea --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/banner.txt @@ -0,0 +1,14 @@ +______ _ _ _ _ ____ _ _ _____ __ __ ______ +| ____| | (_) | | | | | _ \(_) | | __ \| \/ | ____| +| |__ ___| |_ _ __ ___ ___ | |__ __ ___ _| | _| |_) |_| |_ | | | | \ / | |__ +| __| / __| | | '_ \/ __|/ _ \ | '_ \ / _` \ \ /\ / / |/ / _ <| | __| | | | | |\/| | __| +| |___| (__| | | |_) \__ \ __/ | | | | (_| |\ V V /| <| |_) | | |_ | |__| | | | | | +|______\___|_|_| .__/|___/\___| |_| |_|\__,_| \_/\_/ |_|\_\____/|_|\__| |_____/|_| |_|_| + | | + |_| + +Eclipse hawkBit DMF Server ${application.formatted-version} +using Spring Boot ${spring-boot.formatted-version} + +Go to https://www.eclipse.org/hawkbit for more information. + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/logback-spring.xml b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..cd0c5b2394 --- /dev/null +++ b/hawkbit-runtime/hawkbit-dmf-server/src/main/resources/logback-spring.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/README.md b/hawkbit-runtime/hawkbit-mgmt-server/README.md new file mode 100644 index 0000000000..2fa863e98f --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/README.md @@ -0,0 +1,50 @@ +# hawkBit Management Server +The hawkBit Management Server is a standalone spring-boot application with an embedded servlet container. It should be started with at least one (or both) of the device interface servers - hawkbit-ddi-server or/and hawkbit-dmf-server. + +## On your own workstation + +### Run + +```bash +java -jar hawkbit-runtime/hawkbit-mgmt-server/target/hawkbit-mgmt-server-*-SNAPSHOT.jar +``` + +_(Note: you have to add the JDBC driver also to your class path if you intend to use another database than H2.)_ + +Or: + +```bash +run org.eclipse.hawkbit.app.mgmt.MgmtServerStart +``` + +### Usage +The Management API can be accessed via http://localhost:8080/rest/v1 +The root url http://localhost:8080 will redirect directly to the Swagger Management UI + +### Clustering (Experimental!!!) +The micro-service instances are configured to communicate via Spring Cloud Bus. You could run multiple instances of any micro-service but hawkbit-mgmt-server. Management server run some schedulers which shall not run simultaneously - e.g. auto assignment checker and rollouts executor. To run multiple management server instances you shall do some extensions of hawkbit to ensure that they wont run schedulers simultaneously or you shall configure all instances but one to do not run schedulers! + +## Optional Protostuff for Sprign cloud bus +The micro-service instances are configured to communicate via Spring Cloud Bus. Optionally, you could use [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance. + +**Note**: If Protostuff is enabled it shall be enabled on all microservices! + +Add/Uncomment to/in your `application.properties` : + +```properties +spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff +``` + +Add to your `pom.xml` : + +```xml + + io.protostuff + protostuff-core + + + io.protostuff + protostuff-runtime + +``` diff --git a/hawkbit-runtime/hawkbit-mgmt-server/pom.xml b/hawkbit-runtime/hawkbit-mgmt-server/pom.xml new file mode 100644 index 0000000000..0a2003232a --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-runtime-parent + ${revision} + + hawkbit-mgmt-server + hawkBit :: Runtime :: Management Server + + + org.eclipse.hawkbit.app.mgmt.UpdateServerStart + + + + + org.eclipse.hawkbit + hawkbit-boot-starter-mgmt-api + ${project.version} + + + + org.springframework.cloud + spring-cloud-stream-binder-rabbit + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/ErrorController.java b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/ErrorController.java new file mode 100644 index 0000000000..84389c60e7 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/ErrorController.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.mgmt; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Error page controller that ensures that ocet stream does not return text in + * case of an error. + */ +@Controller +// Exception squid:S3752 - errors need handling for all methods +@SuppressWarnings("squid:S3752") +public class ErrorController extends BasicErrorController { + + private static final String PATH = "path"; + + /** + * A new {@link ErrorController}. + * + * @param errorAttributes + * the error attributes + * @param serverProperties + * configuration properties + */ + public ErrorController(final ErrorAttributes errorAttributes, final ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + + @RequestMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public ResponseEntity errorStream(final HttpServletRequest request, final HttpServletResponse response) { + final HttpStatus status = getStatus(request); + return new ResponseEntity<>(status); + } + + @Override + @RequestMapping + public ResponseEntity> error(final HttpServletRequest request) { + final HttpStatus status = getStatus(request); + final Map body = getErrorAttributesWithoutPath(request); + return new ResponseEntity<>(body, status); + } + + private Map getErrorAttributesWithoutPath(final HttpServletRequest request) { + final Map body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); + if (body != null && body.containsKey(PATH)) { + body.remove(PATH); + } + return body; + } +} diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java new file mode 100644 index 0000000000..3881d1461a --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/java/org/eclipse/hawkbit/app/mgmt/MgmtServerStart.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.mgmt; + +import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.view.RedirectView; + +/** + * A {@link SpringBootApplication} annotated class with a main method to start. + * The minimal configuration for the stand alone hawkBit server. + * + */ +@SpringBootApplication +@EnableHawkbitManagedSecurityConfiguration +public class MgmtServerStart { + + /** + * Main method to start the spring-boot application. + * + * @param args the VM arguments. + */ + public static void main(final String[] args) { + SpringApplication.run(MgmtServerStart.class, args); + } + + @Controller + public static class RedirectController { + + @GetMapping("/") + public RedirectView redirectToSwagger( + RedirectAttributes attributes) { + attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectView"); + attributes.addAttribute("attribute", "redirectWithRedirectView"); + return new RedirectView("swagger-ui/index.html"); + } + } +} diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-db2.properties b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-db2.properties new file mode 100644 index 0000000000..16a0fa0b8c --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-db2.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a DB2 DB usage. +# Keep in mind that you need the DB2 driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=DB2 +spring.datasource.url=jdbc:db2://localhost:50000/hawkbit +spring.datasource.username=db2inst1 +spring.datasource.password=db2inst1-pwd +spring.datasource.driverClassName=com.ibm.db2.jcc.DB2Driver diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mssql.properties b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mssql.properties new file mode 100644 index 0000000000..a00c95aa8e --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mssql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a Microsoft SQL Server DB usage. +# Keep in mind that you need the SQL server driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=SQL_SERVER +spring.datasource.url=jdbc:sqlserver://localhost:1433;database=hawkbit +spring.datasource.username=SA +spring.datasource.password= +spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mysql.properties b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mysql.properties new file mode 100644 index 0000000000..979fec5630 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-mysql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a MySQL DB usage. +# Keep in mind that you need the MariaDB driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=MYSQL +spring.datasource.url=jdbc:mariadb://localhost:3306/hawkbit +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driverClassName=org.mariadb.jdbc.Driver diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-postgresql.properties b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-postgresql.properties new file mode 100644 index 0000000000..8b7a40af52 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application-postgresql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2020 Enapter Co.,Ltd +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a PostgreSQL usage. +# Keep in mind that you need the PostgreSQL driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=POSTGRESQL +spring.datasource.url=jdbc:postgresql://localhost:5432/hawkbit +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driverClassName=org.postgresql.Driver diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application.properties b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application.properties new file mode 100644 index 0000000000..d8db191468 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/application.properties @@ -0,0 +1,72 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +spring.application.name=mgmt-server +spring.port=8080 + +# User Security +spring.security.user.name=admin +spring.security.user.password={noop}admin +spring.main.allow-bean-definition-overriding=true + +# Http Encoding +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.enabled=true +server.servlet.encoding.force=true + +# Optional events +hawkbit.server.repository.publish-target-poll-event=false + +## Configuration for DMF/RabbitMQ integration +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 + +# Define own users instead of default "admin" user: +#hawkbit.server.im.users[0].username=hawkbit +#hawkbit.server.im.users[0].password={noop}isAwesome! +#hawkbit.server.im.users[0].firstname=Eclipse +#hawkbit.server.im.users[0].lastname=HawkBit +#hawkbit.server.im.users[0].permissions=ALL + +# Enable CORS and specify the allowed origins: +#hawkbit.server.security.cors.enabled=true +#hawkbit.server.security.cors.allowedOrigins=http://localhost + +hawkbit.server.swagger.mgmt.api.group.enabled=true +hawkbit.server.swagger.ddi.api.group.enabled=false + +# Swagger Configuration +#springdoc.swagger-ui.path=/update-server-documentation +#springdoc.api-docs.path=/update-server-api-docs +springdoc.show-oauth2-endpoints=true +springdoc.api-docs.version=openapi_3_0 +springdoc.show-login-endpoint=true +springdoc.packages-to-scan=org.eclipse.hawkbit.mgmt +springdoc.swagger-ui.oauth2RedirectUrl=/login/oauth2/code/suite +springdoc.paths-to-exclude=/system/** + +# Disable discovery client of spring-cloud-commons +spring.cloud.discovery.enabled=false +# Enable communication between services +spring.cloud.bus.enabled=true +spring.cloud.bus.ack.enabled=false +spring.cloud.bus.refresh.enabled=false +spring.cloud.bus.env.enabled=false +endpoints.spring.cloud.bus.refresh.enabled=false +endpoints.spring.cloud.bus.env.enabled=false +spring.cloud.stream.bindings.springCloudBusInput.group=mgmt-server + +# To use protostuff (for instance fot improved performance) you shall uncomment +# the following two lines and add io.protostuff:protostuff-core and io.protostuff:protostuff-runtime to dependencies +#spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +#spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/banner.txt b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/banner.txt new file mode 100644 index 0000000000..520ef399c7 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/banner.txt @@ -0,0 +1,14 @@ +______ _ _ _ _ ____ _ _ __ __ _ +| ____| | (_) | | | | | _ \(_) | | \/ | | | +| |__ ___| |_ _ __ ___ ___ | |__ __ ___ _| | _| |_) |_| |_ | \ / | __ _ _ __ ___ | |_ +| __| / __| | | '_ \/ __|/ _ \ | '_ \ / _` \ \ /\ / / |/ / _ <| | __| | |\/| |/ _` | '_ ` _ \| __| +| |___| (__| | | |_) \__ \ __/ | | | | (_| |\ V V /| <| |_) | | |_ | | | | (_| | | | | | | |_ +|______\___|_|_| .__/|___/\___| |_| |_|\__,_| \_/\_/ |_|\_\____/|_|\__| |_| |_|\__, |_| |_| |_|\__| + | | __/ | + |_| |___/ + +Eclipse hawkBit Management Server ${application.formatted-version} +using Spring Boot ${spring-boot.formatted-version} + +Go to https://www.eclipse.org/hawkbit for more information. + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/logback-spring.xml b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..cd0c5b2394 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/main/resources/logback-spring.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AbstractSecurityTest.java b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AbstractSecurityTest.java new file mode 100644 index 0000000000..c307d27b74 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AbstractSecurityTest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2020 Bosch.IO GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.mgmt; + +import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest(properties = { "hawkbit.dmf.rabbitmq.enabled=false" }) +@ExtendWith(SharedSqlTestDatabaseExtension.class) +public abstract class AbstractSecurityTest { + + @Autowired + private WebApplicationContext context; + + protected MockMvc mvc; + + @BeforeEach + public void setup() { + final DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true); + mvc = builder.build(); + } + +} diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AllowedHostNamesTest.java b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AllowedHostNamesTest.java new file mode 100644 index 0000000000..7cd3e184dd --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/AllowedHostNamesTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.mgmt; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import io.qameta.allure.Description; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.security.web.firewall.RequestRejectedException; + +import io.qameta.allure.Feature; +import io.qameta.allure.Story; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = { "hawkbit.server.security.allowedHostNames=localhost", + "hawkbit.server.security.httpFirewallIgnoredPaths=/index.html" }) +@Feature("Integration Test - Security") +@Story("Allowed Host Names") +public class AllowedHostNamesTest extends AbstractSecurityTest { + + @Test + @Description("Tests whether a RequestRejectedException is thrown when not allowed host is used") + public void allowedHostNameWithNotAllowedHost() { + assertThatExceptionOfType(RequestRejectedException.class).isThrownBy( + () -> mvc.perform(get("/").header(HttpHeaders.HOST, "www.google.com"))); + } + + @Test + @Description("Tests whether request is redirected when allowed host is used") + public void allowedHostNameWithAllowedHost() throws Exception { + mvc.perform(get("/").header(HttpHeaders.HOST, "localhost")).andExpect(status().is3xxRedirection()); + } + + @Test + @Description("Tests whether request without allowed host name and with ignored path end up with a client error") + public void notAllowedHostnameWithIgnoredPath() throws Exception { + mvc.perform(get("/index.html").header(HttpHeaders.HOST, "www.google.com")) + .andExpect(status().is4xxClientError()); + } +} \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/CorsTest.java b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/CorsTest.java new file mode 100644 index 0000000000..3c2d3244f0 --- /dev/null +++ b/hawkbit-runtime/hawkbit-mgmt-server/src/test/java/org/eclipse/hawkbit/app/mgmt/CorsTest.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.mgmt; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.web.servlet.ResultActions; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; + +@SpringBootTest(properties = { + "hawkbit.dmf.rabbitmq.enabled=false", + "hawkbit.server.security.cors.enabled=true", + "hawkbit.server.security.cors.allowedOrigins=" + + CorsTest.ALLOWED_ORIGIN_FIRST + "," + + CorsTest.ALLOWED_ORIGIN_SECOND, + "hawkbit.server.security.cors.exposedHeaders=" + + HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN}) +@Feature("Integration Test - Security") +@Story("CORS") +public class CorsTest extends AbstractSecurityTest { + + final static String ALLOWED_ORIGIN_FIRST = "http://test.first.origin"; + final static String ALLOWED_ORIGIN_SECOND = "http://test.second.origin"; + + private final static String INVALID_ORIGIN = "http://test.invalid.origin"; + private final static String INVALID_CORS_REQUEST = "Invalid CORS request"; + + @WithUserDetails("admin") + @Test + @Description("Ensures that Cors is working.") + public void validateCorsRequest() throws Exception { + performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_FIRST).andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_FIRST)); + performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_SECOND).andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_SECOND)); + + final String invalidOriginResponseBody = performOptionsRequestToRestWithOrigin(INVALID_ORIGIN) + .andExpect(status().isForbidden()) + .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).andReturn().getResponse() + .getContentAsString(); + assertThat(invalidOriginResponseBody).isEqualTo(INVALID_CORS_REQUEST); + + final String invalidCorsUrlResponseBody = performOptionsRequestToUrlWithOrigin( + MgmtRestConstants.BASE_SYSTEM_MAPPING, ALLOWED_ORIGIN_FIRST).andExpect(status().isForbidden()) + .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)).andReturn() + .getResponse().getContentAsString(); + assertThat(invalidCorsUrlResponseBody).isEqualTo(INVALID_CORS_REQUEST); + } + + private ResultActions performOptionsRequestToRestWithOrigin(final String origin) throws Exception { + return performOptionsRequestToUrlWithOrigin(MgmtRestConstants.BASE_V1_REQUEST_MAPPING, origin); + } + + private ResultActions performOptionsRequestToUrlWithOrigin(final String url, final String origin) throws Exception { + return mvc.perform(options(url).header("Access-Control-Request-Method", "GET").header("Origin", origin)); + } +} \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-update-server/.gitignore b/hawkbit-runtime/hawkbit-update-server/.gitignore deleted file mode 100644 index 5ea5939a39..0000000000 --- a/hawkbit-runtime/hawkbit-update-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/artifactrepo/ diff --git a/hawkbit-runtime/hawkbit-update-server/README.md b/hawkbit-runtime/hawkbit-update-server/README.md index e150f31c91..59fb7600c7 100644 --- a/hawkbit-runtime/hawkbit-update-server/README.md +++ b/hawkbit-runtime/hawkbit-update-server/README.md @@ -1,6 +1,6 @@ # hawkBit Update Server -The hawkBit Update Server is a standalone spring-boot application with an embedded servlet container . +The hawkBit Update Server (Monolith) is a standalone spring-boot application with an embedded servlet container . ## On your own workstation @@ -15,7 +15,7 @@ _(Note: you have to add the JDBC driver also to your class path if you intend to Or: ```bash -run org.eclipse.hawkbit.app.Start +run org.eclipse.hawkbit.doc.Start ``` ### Usage diff --git a/hawkbit-runtime/hawkbit-update-server/pom.xml b/hawkbit-runtime/hawkbit-update-server/pom.xml index b287815761..b6937dbc64 100644 --- a/hawkbit-runtime/hawkbit-update-server/pom.xml +++ b/hawkbit-runtime/hawkbit-update-server/pom.xml @@ -18,47 +18,11 @@ ${revision} hawkbit-update-server - hawkBit :: Runtime :: Update Server + hawkBit :: Runtime :: Update Server (Monolith) - - - docker - - - - io.fabric8 - docker-maven-plugin - - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - ${baseDir} - org.eclipse.hawkbit.app.Start - JAR - - - - - - - - - src/main/resources - - - + + org.eclipse.hawkbit.doc.Start + @@ -66,46 +30,5 @@ hawkbit-boot-starter ${project.version} - - com.h2database - h2 - - - com.microsoft.sqlserver - mssql-jdbc - - - org.postgresql - postgresql - - - - - io.qameta.allure - allure-junit5 - test - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - - - org.mariadb.jdbc - mariadb-java-client - test - - - org.eclipse.hawkbit - hawkbit-repository-test - ${project.version} - test - - diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-postgresql.properties b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-postgresql.properties index 89fb4468ee..8b7a40af52 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-postgresql.properties +++ b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-postgresql.properties @@ -15,5 +15,5 @@ spring.jpa.database=POSTGRESQL spring.datasource.url=jdbc:postgresql://localhost:5432/hawkbit spring.datasource.username=postgres -spring.datasource.password= +spring.datasource.password=admin spring.datasource.driverClassName=org.postgresql.Driver diff --git a/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/CorsTest.java b/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/CorsTest.java index 8ba879f351..925f3341d0 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/CorsTest.java +++ b/hawkbit-runtime/hawkbit-update-server/src/test/java/org/eclipse/hawkbit/app/CorsTest.java @@ -18,7 +18,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.PropertySource; import org.springframework.http.HttpHeaders; import org.springframework.security.test.context.support.WithUserDetails; import org.springframework.test.web.servlet.ResultActions; diff --git a/hawkbit-runtime/hawkbit-vv8-ui/README.md b/hawkbit-runtime/hawkbit-vv8-ui/README.md new file mode 100644 index 0000000000..2b56b0c7be --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/README.md @@ -0,0 +1,49 @@ +# hawkBit Vaadin 8 UI (Deprecated) +The hawkBit Vaadin v8 UI is a standalone spring-boot application with an embedded servlet container. It should be started with at least hawkbit-mgmt-server. + +## On your own workstation + +### Run + +```bash +java -jar hawkbit-runtime/hawkbit-vv8-ui/target/hawkbit-vv8-ui-*-SNAPSHOT.jar +``` + +_(Note: you have to add the JDBC driver also to your class path if you intend to use another database than H2.)_ + +Or: + +```bash +run org.eclipse.hawkbit.app.vv8ui.Vv8UIStart +``` + +### Usage +The Management UI can be accessed via http://localhost:8082/UI + +### Clustering (Experimental!!!) +The micro-service instances are configured to communicate via Spring Cloud Bus. You could run multiple instances of any micro-service but hawkbit-mgmt-server. Management server run some schedulers which shall not run simultaneously - e.g. auto assignment checker and rollouts executor. To run multiple management server instances you shall do some extensions of hawkbit to ensure that they wont run schedulers simultaneously or you shall configure all instances but one to do not run schedulers! + +## Optional Protostuff for Sprign cloud bus +The micro-service instances are configured to communicate via Spring Cloud Bus. Optionally, you could use [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance. + +**Note**: If Protostuff is enabled it shall be enabled on all microservices! + +Add/Uncomment to/in your `application.properties` : + +```properties +spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff +``` + +Add to your `pom.xml` : + +```xml + + io.protostuff + protostuff-core + + + io.protostuff + protostuff-runtime + +``` \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-vv8-ui/pom.xml b/hawkbit-runtime/hawkbit-vv8-ui/pom.xml new file mode 100644 index 0000000000..d1ab6f26eb --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.eclipse.hawkbit + hawkbit-runtime-parent + ${revision} + + hawkbit-vv8-ui + hawkBit :: Runtime :: Vaadin v8 UI + + + org.eclipse.hawkbit.app.vv8ui.Vaadin8UIStart + + + + + org.eclipse.hawkbit + hawkbit-boot-starter-mgmt-ui + ${project.version} + + + + org.springframework.cloud + spring-cloud-stream-binder-rabbit + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/ErrorController.java b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/ErrorController.java new file mode 100644 index 0000000000..4b2734b18c --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/ErrorController.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Error page controller that ensures that ocet stream does not return text in + * case of an error. + */ +@Controller +// Exception squid:S3752 - errors need handling for all methods +@SuppressWarnings("squid:S3752") +public class ErrorController extends BasicErrorController { + + private static final String PATH = "path"; + + /** + * A new {@link ErrorController}. + * + * @param errorAttributes + * the error attributes + * @param serverProperties + * configuration properties + */ + public ErrorController(final ErrorAttributes errorAttributes, final ServerProperties serverProperties) { + super(errorAttributes, serverProperties.getError()); + } + + @RequestMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) + public ResponseEntity errorStream(final HttpServletRequest request, final HttpServletResponse response) { + final HttpStatus status = getStatus(request); + return new ResponseEntity<>(status); + } + + @Override + @RequestMapping + public ResponseEntity> error(final HttpServletRequest request) { + final HttpStatus status = getStatus(request); + final Map body = getErrorAttributesWithoutPath(request); + return new ResponseEntity<>(body, status); + } + + private Map getErrorAttributesWithoutPath(final HttpServletRequest request) { + final Map body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); + if (body != null && body.containsKey(PATH)) { + body.remove(PATH); + } + return body; + } +} diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyLoginUI.java b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyLoginUI.java new file mode 100644 index 0000000000..217218342b --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyLoginUI.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator; +import org.eclipse.hawkbit.ui.UiProperties; +import org.eclipse.hawkbit.ui.login.AbstractHawkbitLoginUI; +import org.eclipse.hawkbit.ui.themes.HawkbitTheme; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.vaadin.spring.security.VaadinSecurity; + +import com.vaadin.spring.annotation.SpringUI; + +/** + * Example hawkBit login UI implementation. + * + * A {@link SpringUI} annotated class must be present in the classpath for the + * login path. The easiest way to get an hawkBit login UI running is to extend + * the {@link AbstractHawkbitLoginUI} and to annotated it with {@link SpringUI} + * as in this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}. + */ +@SpringUI(path = HawkbitTheme.LOGIN_UI_PATH) +// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from +// Vaadin. +@SuppressWarnings({ "squid:MaximumInheritanceDepth" }) +public class MyLoginUI extends AbstractHawkbitLoginUI { + private static final long serialVersionUID = 1L; + + @Autowired + MyLoginUI(final ApplicationContext context, final VaadinSecurity vaadinSecurity, final VaadinMessageSource i18n, + final UiProperties uiProperties, final MultitenancyIndicator multiTenancyIndicator) { + super(context, vaadinSecurity, i18n, uiProperties, multiTenancyIndicator); + } + +} diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyUI.java b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyUI.java new file mode 100644 index 0000000000..b677a33ec7 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/MyUI.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; +import org.eclipse.hawkbit.ui.UiProperties; +import org.eclipse.hawkbit.ui.components.NotificationUnreadButton; +import org.eclipse.hawkbit.ui.error.ErrorView; +import org.eclipse.hawkbit.ui.menu.DashboardMenu; +import org.eclipse.hawkbit.ui.push.EventPushStrategy; +import org.eclipse.hawkbit.ui.push.UIEventProvider; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.vaadin.spring.events.EventBus.UIEventBus; + +import com.vaadin.annotations.Push; +import com.vaadin.server.ErrorHandler; +import com.vaadin.shared.communication.PushMode; +import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.spring.navigator.SpringViewProvider; + +/** + * Example hawkBit UI implementation. + * + * A {@link SpringUI} annotated class must be present in the classpath. The + * easiest way to get an hawkBit UI running is to extend the + * {@link AbstractHawkbitUI} and to annotated it with {@link SpringUI} as in + * this example. WEBSOCKET_XHR transport is used instead of WEBSOCKET in order + * to preserve Spring Security Context, that does not work using websocket + * communication with Vaadin Shared Security. + * + */ +@SpringUI +@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET_XHR) +// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from +// Vaadin. +@SuppressWarnings({ "squid:MaximumInheritanceDepth" }) +public class MyUI extends AbstractHawkbitUI { + private static final long serialVersionUID = 1L; + + @Autowired + MyUI(final EventPushStrategy pushStrategy, final UIEventBus eventBus, final UIEventProvider eventProvider, + final SpringViewProvider viewProvider, final ApplicationContext context, final DashboardMenu dashboardMenu, + final ErrorView errorview, final NotificationUnreadButton notificationUnreadButton, + final UiProperties uiProperties, final VaadinMessageSource i18n, final ErrorHandler uiErrorHandler) { + super(pushStrategy, eventBus, eventProvider, viewProvider, context, dashboardMenu, errorview, + notificationUnreadButton, uiProperties, i18n, uiErrorHandler); + } + +} diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/Vaadin8UIStart.java b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/Vaadin8UIStart.java new file mode 100644 index 0000000000..3c98e5e2b6 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/java/org/eclipse/hawkbit/app/vv8ui/Vaadin8UIStart.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * A {@link SpringBootApplication} annotated class with a main method to start. + * The minimal configuration for the stand alone hawkBit server. + * + */ +@SpringBootApplication +@EnableHawkbitManagedSecurityConfiguration +public class Vaadin8UIStart { + + /** + * Main method to start the spring-boot application. + * + * @param args + * the VM arguments. + */ + public static void main(final String[] args) { + SpringApplication.run(Vaadin8UIStart.class, args); + } +} diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-db2.properties b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-db2.properties new file mode 100644 index 0000000000..16a0fa0b8c --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-db2.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a DB2 DB usage. +# Keep in mind that you need the DB2 driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=DB2 +spring.datasource.url=jdbc:db2://localhost:50000/hawkbit +spring.datasource.username=db2inst1 +spring.datasource.password=db2inst1-pwd +spring.datasource.driverClassName=com.ibm.db2.jcc.DB2Driver diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mssql.properties b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mssql.properties new file mode 100644 index 0000000000..a00c95aa8e --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mssql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a Microsoft SQL Server DB usage. +# Keep in mind that you need the SQL server driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=SQL_SERVER +spring.datasource.url=jdbc:sqlserver://localhost:1433;database=hawkbit +spring.datasource.username=SA +spring.datasource.password= +spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mysql.properties b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mysql.properties new file mode 100644 index 0000000000..979fec5630 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-mysql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a MySQL DB usage. +# Keep in mind that you need the MariaDB driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=MYSQL +spring.datasource.url=jdbc:mariadb://localhost:3306/hawkbit +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driverClassName=org.mariadb.jdbc.Driver diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-postgresql.properties b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-postgresql.properties new file mode 100644 index 0000000000..8b7a40af52 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application-postgresql.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2020 Enapter Co.,Ltd +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +# This profile adds basic configurations for a PostgreSQL usage. +# Keep in mind that you need the PostgreSQL driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/guides/runhawkbit/ + +spring.jpa.database=POSTGRESQL +spring.datasource.url=jdbc:postgresql://localhost:5432/hawkbit +spring.datasource.username=postgres +spring.datasource.password=admin +spring.datasource.driverClassName=org.postgresql.Driver diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application.properties b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application.properties new file mode 100644 index 0000000000..451eec3389 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/application.properties @@ -0,0 +1,77 @@ +# +# Copyright (c) 2015 Bosch Software Innovations GmbH and others +# +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +spring.application.name=vv8-ui-server +server.port=8082 + +# User Security +spring.security.user.name=admin +spring.security.user.password={noop}admin +spring.main.allow-bean-definition-overriding=true + +# Http Encoding +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.enabled=true +server.servlet.encoding.force=true + +# DDI authentication configuration +hawkbit.server.ddi.security.authentication.anonymous.enabled=false +hawkbit.server.ddi.security.authentication.targettoken.enabled=false +hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false + +# Optional events +hawkbit.server.repository.publish-target-poll-event=false + +## Configuration for DMF/RabbitMQ integration +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ +spring.rabbitmq.host=localhost +spring.rabbitmq.port=5672 + +# Define own users instead of default "admin" user: +#hawkbit.server.im.users[0].username=hawkbit +#hawkbit.server.im.users[0].password={noop}isAwesome! +#hawkbit.server.im.users[0].firstname=Eclipse +#hawkbit.server.im.users[0].lastname=HawkBit +#hawkbit.server.im.users[0].permissions=ALL + +# Enable CORS and specify the allowed origins: +#hawkbit.server.security.cors.enabled=true +#hawkbit.server.security.cors.allowedOrigins=http://localhost + +## Disable swagger +hawkbit.server.swagger.mgmt.api.group.enabled=false +hawkbit.server.swagger.ddi.api.group.enabled=false + +# Flyway disabled - US only +spring.flyway.enabled=false +## SQL Database Configuration - END + +## No Schedulers - START +hawkbit.autoassign.scheduler.enabled=false +hawkbit.rollout.scheduler.enabled=false +## No Schedulers - END + +# Disable discovery client of spring-cloud-commons +spring.cloud.discovery.enabled=false +# Enable communication between services +spring.cloud.bus.enabled=true +spring.cloud.bus.ack.enabled=false +spring.cloud.bus.refresh.enabled=false +spring.cloud.bus.env.enabled=false +endpoints.spring.cloud.bus.refresh.enabled=false +endpoints.spring.cloud.bus.env.enabled=false +spring.cloud.stream.bindings.springCloudBusInput.group=vv8-ui-server + +# To use protostuff (for instance fot improved performance) you shall uncomment +# the following two lines and add io.protostuff:protostuff-core and io.protostuff:protostuff-runtime to dependencies +#spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff +#spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/banner.txt b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/banner.txt new file mode 100644 index 0000000000..64f7e47a9f --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/banner.txt @@ -0,0 +1,18 @@ + ______ _ _ _ _ ____ _ _ + | ____| | (_) | | | | | _ \(_) | + | |__ ___| |_ _ __ ___ ___ | |__ __ ___ _| | _| |_) |_| |_ + | __| / __| | | '_ \/ __|/ _ \ | '_ \ / _` \ \ /\ / / |/ / _ <| | __| + | |___| (__| | | |_) \__ \ __/ | | | | (_| |\ V V /| <| |_) | | |_ + |______\___|_|_| .__/|___/\___| |_| |_|\__,_| \_/\_/ |_|\_\____/|_|\__| + __ __ | | _ _ ___ _ _ _____ + \ \ / / |_| | (_) / _ \ | | | |_ _| + \ \ / /_ _ __ _ __| |_ _ __ __ _| (_) | | | | | | | + \ \/ / _` |/ _` |/ _` | | '_ \ \ \ / /> _ < | | | | | | + \ / (_| | (_| | (_| | | | | | \ V /| (_) | | |__| |_| |_ + \/ \__,_|\__,_|\__,_|_|_| |_| \_/ \___/ \____/|_____| + +Eclipse hawkBit Vaadin v8 UI ${application.formatted-version} +using Spring Boot ${spring-boot.formatted-version} + +Go to https://www.eclipse.org/hawkbit for more information. + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/logback-spring.xml b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..b71e34118f --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/main/resources/logback-spring.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AbstractSecurityTest.java b/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AbstractSecurityTest.java new file mode 100644 index 0000000000..f99aa2465c --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AbstractSecurityTest.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2020 Bosch.IO GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@SpringBootTest(properties = { "hawkbit.dmf.rabbitmq.enabled=false" }) +@ExtendWith(SharedSqlTestDatabaseExtension.class) +public abstract class AbstractSecurityTest { + + @Autowired + private WebApplicationContext context; + + protected MockMvc mvc; + + @BeforeEach + public void setup() { + final DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true); + mvc = builder.build(); + } + +} diff --git a/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AllowedHostNamesTest.java b/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AllowedHostNamesTest.java new file mode 100644 index 0000000000..549f17a310 --- /dev/null +++ b/hawkbit-runtime/hawkbit-vv8-ui/src/test/java/org/eclipse/hawkbit/app/vv8ui/AllowedHostNamesTest.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2019 Bosch Software Innovations GmbH and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.hawkbit.app.vv8ui; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import io.qameta.allure.Description; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.security.web.firewall.RequestRejectedException; + +import io.qameta.allure.Feature; +import io.qameta.allure.Story; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(properties = { "hawkbit.server.security.allowedHostNames=localhost", + "hawkbit.server.security.httpFirewallIgnoredPaths=/index.html" }) +@Feature("Integration Test - Security") +@Story("Allowed Host Names") +public class AllowedHostNamesTest extends AbstractSecurityTest { + + @Test + @Description("Tests whether a RequestRejectedException is thrown when not allowed host is used") + public void allowedHostNameWithNotAllowedHost() { + assertThatExceptionOfType(RequestRejectedException.class).isThrownBy( + () -> mvc.perform(get("/").header(HttpHeaders.HOST, "www.google.com"))); + } + + @Test + @Description("Tests whether request is redirected when allowed host is used") + public void allowedHostNameWithAllowedHost() throws Exception { + mvc.perform(get("/").header(HttpHeaders.HOST, "localhost")).andExpect(status().is3xxRedirection()); + } + + @Test + @Description("Tests whether request without allowed host name and with ignored path end up with a client error") + public void notAllowedHostnameWithIgnoredPath() throws Exception { + mvc.perform(get("/index.html").header(HttpHeaders.HOST, "www.google.com")) + .andExpect(status().is4xxClientError()); + } +} \ No newline at end of file diff --git a/hawkbit-runtime/pom.xml b/hawkbit-runtime/pom.xml index f5887cb8f0..ba17c257eb 100644 --- a/hawkbit-runtime/pom.xml +++ b/hawkbit-runtime/pom.xml @@ -19,10 +19,100 @@ hawkbit-runtime-parent - hawkBit :: Runtime + hawkBit :: Runtime :: Parent pom + + + + com.h2database + h2 + + + com.microsoft.sqlserver + mssql-jdbc + + + org.postgresql + postgresql + + + + + io.qameta.allure + allure-junit5 + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + org.mariadb.jdbc + mariadb-java-client + test + + + org.eclipse.hawkbit + hawkbit-repository-test + ${project.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + ${baseDir} + ${spring.app.class} + JAR + + + + + + + + + src/main/resources + + + + + + + docker + + + + io.fabric8 + docker-maven-plugin + + + + + + + hawkbit-ddi-server + hawkbit-dmf-server + hawkbit-mgmt-server + hawkbit-vv8-ui + hawkbit-update-server diff --git a/hawkbit-test-report/pom.xml b/hawkbit-test-report/pom.xml index d090c95b93..331cf3719d 100644 --- a/hawkbit-test-report/pom.xml +++ b/hawkbit-test-report/pom.xml @@ -195,5 +195,4 @@ - diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/autoconfigure/UISecurityConfigurationAdapter.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/autoconfigure/UISecurityConfigurationAdapter.java index 953d281f28..3593658e06 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/autoconfigure/UISecurityConfigurationAdapter.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/autoconfigure/UISecurityConfigurationAdapter.java @@ -46,11 +46,7 @@ import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.security.web.firewall.FirewalledRequest; -import org.springframework.security.web.firewall.HttpFirewall; -import org.springframework.security.web.firewall.StrictHttpFirewall; import org.springframework.security.web.session.HttpSessionEventPublisher; -import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.vaadin.spring.http.HttpService; import org.vaadin.spring.security.annotation.EnableVaadinSharedSecurity; @@ -59,10 +55,7 @@ import org.vaadin.spring.security.shared.VaadinUrlAuthenticationSuccessHandler; import org.vaadin.spring.security.web.VaadinRedirectStrategy; -import javax.servlet.http.HttpServletRequest; import java.util.Arrays; -import java.util.Collection; -import java.util.List; /** * {@link WebSecurityConfigurer} for external (management) access. @@ -204,49 +197,6 @@ protected SecurityFilterChain filterChainUI( return httpSec.build(); } - /** - * HttpFirewall which enables to define a list of allowed host names. - * - * @return the http firewall. - */ - @Bean - public HttpFirewall httpFirewall() { - final List allowedHostNames = hawkbitSecurityProperties.getAllowedHostNames(); - final IgnorePathsStrictHttpFirewall firewall = new IgnorePathsStrictHttpFirewall( - hawkbitSecurityProperties.getHttpFirewallIgnoredPaths()); - - if (!CollectionUtils.isEmpty(allowedHostNames)) { - firewall.setAllowedHostnames(hostName -> { - LOG.debug("Firewall check host: {}, allowed: {}", hostName, allowedHostNames.contains(hostName)); - return allowedHostNames.contains(hostName); - }); - } - return firewall; - } - - private static class IgnorePathsStrictHttpFirewall extends StrictHttpFirewall { - - private final Collection pathsToIgnore; - - public IgnorePathsStrictHttpFirewall(final Collection pathsToIgnore) { - super(); - this.pathsToIgnore = pathsToIgnore; - } - - @Override - public FirewalledRequest getFirewalledRequest(final HttpServletRequest request) { - if (pathsToIgnore != null && pathsToIgnore.contains(request.getRequestURI())) { - return new FirewalledRequest(request) { - @Override - public void reset() { - // nothing to do - } - }; - } - return super.getFirewalledRequest(request); - } - } - @Bean public WebSecurityCustomizer webSecurityCustomizer() { // No security for static content