eclipse / hawkbit

Eclipse hawkBit™
https://projects.eclipse.org/projects/iot.hawkbit
Eclipse Public License 2.0
445 stars 184 forks source link

No matter what I do DDI root resource query returns a http instead of https href #1696

Open KubaFYI opened 3 months ago

KubaFYI commented 3 months ago

I'm running hawkbit spun with docker compose from the docker-compose-monolith-mysql.yml config file. Then my SWUpdate-based clients access it through a nginx reverse proxy for mTLS auth. The clients are configured to hit a https url. Initial plug-and-play registration of clients works fine, and I can see them polling the server fine. But once it comes to an artifact being available for download, and clients getting an answer containing "deploymentBase" to the root resource query, the link provided there by hawkbit is http instead of https (which then fails).

I've tried changing the relevant property (i.e. server.forward-headers-strategy=NATIVE) by adding it to the docker-compose file with other JAVA_OPTS, by adding it to application-mysql.properties, as well as by introducing the SERVER_FORWARD-HEADERS-STRATEGY=NATIVE environmental variable. None of them resolves my problem.

The nginx configuration is pretty much identical to the one in Hawkbit documentation obviously except for my specific hostname, certificate issuer hash etc.

Is this a bug or have I not configured the thing correctly?

KubaFYI commented 3 months ago

I found the culprit. Turns out that the nginx configuration given in Hawkbit documentation is incomplete and needs to contain proxy_set_header X-Forwarded-Proto https; in order for the server to correctly recognise incoming traffic as using https and respond accordingly

mwiesenbauer commented 3 months ago

Setting server.forward-headers-strategy=NATIVE did not work in my setup, it caused infinite redirects to the same URL. Instead I used the following configuration:

hawkbit.server.security.require-ssl=true
server.forward-headers-strategy=FRAMEWORK

I tried setting server.tomcat.redirect-context-root=true as well, but it did not change anything. The reverse proxy (traefik) sets the following headers:

X-Forwarded-For: 1.1.1.1
X-Forwarded-Host: hawkbit.example.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: hawkbit.example.com
X-Real-Ip: 1.1.1.1

My setup is hawkbit 0.4.1 in docker compose with mysql 8.3 behind a traefik 2.11.0 reverse proxy running on Ubuntu 20.04.6 LTS with docker 26.1.0, build 9714adc.

---
version: "3"

services:
  mysql:
    image: "mysql:8.3"
    environment:
      MYSQL_DATABASE: "hawkbit"
      MYSQL_USER: "hawkbit"
    restart: unless-stopped
    ports:
      - "3306:3306"
    labels:
      NAME: "mysql"
    networks:
      default:

hawkbit:
  image: "hawkbit/hawkbit-update-server:0.4.1-mysql"
  expose:
    - "8080"
  labels:
    - 'NAME: "hawkbit"'
    - "traefik.enable=true"
    - "traefik.http.routers.hawkbit.entrypoints=websecure,web"
    - "traefik.http.routers.hawkbit.priority=400"
    - "traefik.http.services.hawkbit.loadbalancer.passHostHeader=true"
    - "traefik.http.routers.hawkbit.rule=Host(`hawkbit.example.com`)"
  environment:
    - "SPRING_CONFIG_LOCATION=/etc/hawkbit/application.properties"
  volumes:
    - "./application.properties:/etc/hawkbit/application.properties:ro"
  restart: unless-stopped
  networks:
    default:
    traefik_proxy:

networks:
  traefik_proxy:
    external: true

and the traefik configuration

global:
  checkNewVersion: false
  sendAnonymousUsage: false

log:
  level: ERROR
  format: "json"

api:
  dashboard: False

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          scheme: https
          to: websecure
  websecure:
    address: :443
    http:
      tls:
        certResolver: le

certificatesResolvers:
  le:
    acme:
      email: "admin@example.com"
      storage: /var/lib/traefik/acme.json
      tlsChallenge: {}

providers:
  docker:
    watch: true
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: "traefik_proxy"
  file:
    directory: "/etc/traefik/conf.d"
    watch: true

accessLog: {}