From dafc08304ddbdd7741a22c8a27f7b08ddc6b4a4f Mon Sep 17 00:00:00 2001 From: Florian BEZANNIER <48728684+flobz@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:04:23 +0200 Subject: [PATCH] Add portRequest url handler property (#1449) * Add portRequest url handler property The option server.forward-headers-strategy=NATIVE allow to dynamicly generate link based on X-Forwarded-Proto header. Unfortunately Hawkbit artifact use a custom url handler. This PR allow to serve artifacts on http and https in the same time. Signed-off-by: Florian Bezannier * docs: use server.forward-headers-strategy option --------- Signed-off-by: Florian Bezannier --- docs/content/concepts/authentication.md | 8 ++------ .../hawkbit-artifactdl-defaults.properties | 4 ++-- .../api/PropertyBasedArtifactUrlHandler.java | 11 +++++++++++ .../api/PropertyBasedArtifactUrlHandlerTest.java | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/docs/content/concepts/authentication.md b/docs/content/concepts/authentication.md index 2fc7bdae9..4a296c594 100644 --- a/docs/content/concepts/authentication.md +++ b/docs/content/concepts/authentication.md @@ -100,14 +100,10 @@ Nginx doesn't support obtaining the issuer hash without addons. Therefore, in th There are also some configurations that you need update when you deployed your hawkbit service. - You need to add the given download settings to your hawkBit configurations so that hawkBit can generate the URLs according to the https that the client will use to download. If you're deploying hawkBit as a Docker container, add these configurations as environmental values in the docker-compose.yml file. Don't forget to replace "hostname" with your actual hostname. + You need to add the given setting to your hawkBit configurations so that hawkBit can generate the URLs according to the https that the client will use to download. If you're deploying hawkBit as a Docker container, add these configurations as environmental values in the docker-compose.yml file. ``` -hawkbit.artifact.url.protocols.download-http.rel=download-http -hawkbit.artifact.url.protocols.download-http.hostname=hawkbit.dev.example -hawkbit.artifact.url.protocols.download-http.protocol=https -hawkbit.artifact.url.protocols.download-http.supports=DMF,DDI -hawkbit.artifact.url.protocols.download-http.ref={protocol}://{hostnameRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} +server.forward-headers-strategy=NATIVE ``` 2. In Hawkbit's UI section, under system configuration, make sure to select *Allow targets to authenticate via a certificate authenticated by a reverse proxy* and input the fixed issuer hash as "Hawkbit". This can be whetever you have configured in the nginx configuration in `proxy_set_header X-Ssl-Issuer-Hash-1` below. diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties index ec66debe5..06683b25b 100644 --- a/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties +++ b/hawkbit-autoconfigure/src/main/resources/hawkbit-artifactdl-defaults.properties @@ -15,7 +15,7 @@ hawkbit.artifact.url.protocols.download-http.ip=127.0.0.1 hawkbit.artifact.url.protocols.download-http.protocol=http hawkbit.artifact.url.protocols.download-http.port=8080 hawkbit.artifact.url.protocols.download-http.supports=DMF,DDI -hawkbit.artifact.url.protocols.download-http.ref={protocol}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} +hawkbit.artifact.url.protocols.download-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} hawkbit.artifact.url.protocols.md5sum-http.rel=md5sum-http hawkbit.artifact.url.protocols.md5sum-http.protocol=${hawkbit.artifact.url.protocols.download-http.protocol} hawkbit.artifact.url.protocols.md5sum-http.hostname=${hawkbit.artifact.url.protocols.download-http.hostname} @@ -29,4 +29,4 @@ hawkbit.artifact.url.protocols.download-cdn-http.ip=127.0.0.1 hawkbit.artifact.url.protocols.download-cdn-http.protocol=http hawkbit.artifact.url.protocols.download-cdn-http.port=8080 hawkbit.artifact.url.protocols.download-cdn-http.supports=MGMT -hawkbit.artifact.url.protocols.download-cdn-http.ref={protocol}://{hostnameRequest}:{portRequest}/rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} \ No newline at end of file +hawkbit.artifact.url.protocols.download-cdn-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/rest/v1/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} \ No newline at end of file diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java index 7f387a779..dc606a801 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java @@ -54,6 +54,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler { private static final String TARGET_ID_BASE62_PLACEHOLDER = "targetIdBase62"; private static final String HOSTNAME_REQUEST_PLACEHOLDER = "hostnameRequest"; private static final String PORT_REQUEST_PLACEHOLDER = "portRequest"; + private static final String PROTOCOL_REQUEST_PLACEHOLDER = "protocolRequest"; private static final String HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER = "domainRequest"; private static final String ARTIFACT_FILENAME_PLACEHOLDER = "artifactFileName"; private static final String ARTIFACT_SHA1_PLACEHOLDER = "artifactSHA1"; @@ -118,11 +119,13 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler { final URI requestUri) { final Map replaceMap = new HashMap<>(); replaceMap.put(IP_PLACEHOLDER, protocol.getIp()); + replaceMap.put(HOSTNAME_PLACEHOLDER, protocol.getHostname()); replaceMap.put(HOSTNAME_REQUEST_PLACEHOLDER, getRequestHost(protocol, requestUri)); replaceMap.put(PORT_REQUEST_PLACEHOLDER, getRequestPort(protocol, requestUri)); replaceMap.put(HOSTNAME_WITH_DOMAIN_REQUEST_PLACEHOLDER, computeHostWithRequestDomain(protocol, requestUri)); + replaceMap.put(PROTOCOL_REQUEST_PLACEHOLDER, getRequestProtocol(protocol, requestUri)); replaceMap.put(CONTEXT_PATH, contextPath); @@ -166,6 +169,14 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler { return Optional.ofNullable(requestUri.getHost()).orElse(protocol.getHostname()); } + private static String getRequestProtocol(final UrlProtocol protocol, final URI requestUri) { + if (requestUri == null) { + return protocol.getProtocol(); + } + + return Optional.ofNullable(requestUri.getScheme()).orElse(protocol.getProtocol()); + } + private static String getPort(final UrlProtocol protocol) { return ObjectUtils.isEmpty(protocol.getPort()) ? null : String.valueOf(protocol.getPort()); } diff --git a/hawkbit-core/src/test/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandlerTest.java b/hawkbit-core/src/test/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandlerTest.java index 771a5b78e..daffabbd4 100644 --- a/hawkbit-core/src/test/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandlerTest.java +++ b/hawkbit-core/src/test/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandlerTest.java @@ -142,6 +142,21 @@ public class PropertyBasedArtifactUrlHandlerTest { assertThat(urls).containsExactly(new ArtifactUrl(TEST_PROTO.toUpperCase(), TEST_REL, TEST_PROTO + "://" + testHost + ":5683/fws/" + TENANT + "/" + TARGETID_BASE62 + "/" + ARTIFACTID_BASE62)); } + @Test + @Description("Verfies that the protocol of the statically defined hostname is replaced with the protocol of the request.") + public void urlGenerationWithProtocolFromRequest() throws URISyntaxException { + final String testHost = "ddi.host.com"; + + final UrlProtocol proto = new UrlProtocol(); + proto.setRef("{protocolRequest}://{hostname}:{port}/fws/{tenant}/{targetIdBase62}/{artifactIdBase62}"); + properties.getProtocols().put("download-http", proto); + + final List urls = urlHandlerUnderTest.getUrls(placeholder, ApiType.DDI, + new URI("https://" + testHost)); + + assertThat(urls).containsExactly(new ArtifactUrl("http".toUpperCase(), "download-http", + "https://localhost:8080/fws/" + TENANT + "/" + TARGETID_BASE62 + "/" + ARTIFACTID_BASE62)); + } @Test @Description("Verfies that the port of the statically defined hostname is replaced with the port of the request.")