This is an automated email from the ASF dual-hosted git repository.
pvillard31 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new fda655bc333 NIFI-16018: Handle port number in header validator
fda655bc333 is described below
commit fda655bc333640b2e9b8d8a0adefc40f05992f44
Author: Zoltan Kornel Torok <[email protected]>
AuthorDate: Sat Jun 13 00:59:33 2026 +0200
NIFI-16018: Handle port number in header validator
Signed-off-by: Pierre Villard <[email protected]>
This closes #11335.
---
.../connector/FrameworkServerConnectorFactory.java | 2 +-
.../connector/ProxyHeaderValidatorCustomizer.java | 34 ++++++++++++++++++++--
.../web/server/StandardServerProviderTest.java | 30 +++++++++++++++++++
3 files changed, 63 insertions(+), 3 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
index e085cc0face..c3cd71d3693 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java
@@ -107,7 +107,7 @@ public class FrameworkServerConnectorFactory extends
StandardServerConnectorFact
// Add HostHeaderCustomizer to set Host Header for HTTP/2
httpConfiguration.addCustomizer(new HostHeaderCustomizer());
- final ProxyHeaderValidatorCustomizer proxyHeaderValidatorCustomizer =
new ProxyHeaderValidatorCustomizer(validProxyHosts);
+ final ProxyHeaderValidatorCustomizer proxyHeaderValidatorCustomizer =
new ProxyHeaderValidatorCustomizer(validProxyHosts, validPorts);
httpConfiguration.addCustomizer(proxyHeaderValidatorCustomizer);
final HostPortValidatorCustomizer hostPortValidatorCustomizer = new
HostPortValidatorCustomizer(validPorts);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/ProxyHeaderValidatorCustomizer.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/ProxyHeaderValidatorCustomizer.java
index 34c149c0877..87fa3100da2 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/ProxyHeaderValidatorCustomizer.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/ProxyHeaderValidatorCustomizer.java
@@ -31,12 +31,16 @@ import org.eclipse.jetty.server.Request;
import java.security.cert.X509Certificate;
import java.util.Objects;
import java.util.Set;
+import java.util.regex.Pattern;
/**
* Jetty Request Customizer implementing validation for supported Proxy
Request Headers
*/
public class ProxyHeaderValidatorCustomizer implements
HttpConfiguration.Customizer {
private static final String MISDIRECTED_REQUEST_REASON = "Invalid Proxy
Host Requested";
+ private static final String MISDIRECTED_REQUEST_REASON_INVALID_PORT =
"Invalid Port Requested";
+
+ private static final Pattern HOST_PORT_SEPARATOR = Pattern.compile(":");
private static final Set<String> SUPPORTED_PROXY_HOST_HEADERS = Set.of(
ProxyHeader.PROXY_HOST.getHeader(),
@@ -44,9 +48,11 @@ public class ProxyHeaderValidatorCustomizer implements
HttpConfiguration.Customi
);
private final Set<String> validProxyHosts;
+ private final Set<Integer> validPorts;
- public ProxyHeaderValidatorCustomizer(final Set<String> validProxyHosts) {
+ public ProxyHeaderValidatorCustomizer(final Set<String> validProxyHosts,
final Set<Integer> validPorts) {
this.validProxyHosts = Objects.requireNonNull(validProxyHosts, "Valid
Proxy Hosts required");
+ this.validPorts = Objects.requireNonNull(validPorts, "Valid Ports
required");
}
/**
@@ -95,16 +101,25 @@ public class ProxyHeaderValidatorCustomizer implements
HttpConfiguration.Customi
final HttpFields requestHeaders = request.getHeaders();
for (final String proxyHostHeader : SUPPORTED_PROXY_HOST_HEADERS) {
- final String hostHeader = requestHeaders.get(proxyHostHeader);
+ String hostHeader = requestHeaders.get(proxyHostHeader);
// Include empty and blank values for enforced validation of
request headers
if (hostHeader == null) {
continue;
}
+
+ final String[] hostHeaderParts =
HOST_PORT_SEPARATOR.split(hostHeader);
+ if (hostHeaderParts.length == 2) {
+ hostHeader = hostHeaderParts[0];
+ }
+
// Allow proxy host header matching request host header based on
TLS SNI and DNS SAN requirements
if (requestHost.equals(hostHeader)) {
+ processProxyHostHeaderPortNumber(hostHeaderParts);
continue;
}
+
if (validProxyHosts.contains(hostHeader)) {
+ processProxyHostHeaderPortNumber(hostHeaderParts);
continue;
}
@@ -112,6 +127,21 @@ public class ProxyHeaderValidatorCustomizer implements
HttpConfiguration.Customi
}
}
+ private void processProxyHostHeaderPortNumber(String[] hostHeaderParts) {
+ if (hostHeaderParts.length == 2) {
+ try {
+ final int port = Integer.parseInt(hostHeaderParts[1]);
+ if (validPorts.contains(port)) {
+ return;
+ } else {
+ throw new
HttpException.RuntimeException(HttpStatus.MISDIRECTED_REQUEST_421,
MISDIRECTED_REQUEST_REASON_INVALID_PORT);
+ }
+ } catch (final NumberFormatException e) {
+ throw new
HttpException.RuntimeException(HttpStatus.MISDIRECTED_REQUEST_421,
MISDIRECTED_REQUEST_REASON_INVALID_PORT);
+ }
+ }
+ }
+
private X509Certificate findPeerCertificate(final Request request) {
final X509Certificate peerCertificate;
final ConnectionMetaData connectionMetaData =
request.getConnectionMetaData();
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
index e5740b3bed8..65c815a08a9 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/StandardServerProviderTest.java
@@ -87,6 +87,12 @@ class StandardServerProviderTest {
private static final String PUBLIC_STAGED_HOST = "nifi.staged.apache.org";
+ private static final String PUBLIC_STAGED_HOST_WITH_PORT =
"nifi.staged.apache.org:8443";
+
+ private static final String PUBLIC_STAGED_HOST_WITH_INVALID_PORT =
"nifi.staged.apache.org:8444";
+
+ private static final String
PUBLIC_STAGED_HOST_WITH_A_PORT_WHICH_NOT_NUMBER = "nifi.staged.apache.org:aaa";
+
private static final String PROXY_HOST_PROPERTY =
"nifi.apache.org,nifi.staged.apache.org:8443";
private static final String PUBLIC_UNKNOWN_HOST =
"nifi.unknown.apache.org";
@@ -350,6 +356,12 @@ class StandardServerProviderTest {
.header(ProxyHeader.FORWARDED_HOST.getHeader(),
PUBLIC_STAGED_HOST)
.build();
assertResponseStatusCode(httpClient, forwardedHostRequest,
HttpStatus.MOVED_TEMPORARILY_302);
+
+ final HttpRequest forwardedHostRequestWithPort =
HttpRequest.newBuilder(localhostUri)
+ .version(HttpClient.Version.HTTP_1_1)
+ .header(ProxyHeader.FORWARDED_HOST.getHeader(),
PUBLIC_STAGED_HOST_WITH_PORT)
+ .build();
+ assertResponseStatusCode(httpClient, forwardedHostRequestWithPort,
HttpStatus.MOVED_TEMPORARILY_302);
}
void assertBadRequestsCompleted(final HttpClient httpClient, final URI
localhostUri) throws IOException, InterruptedException {
@@ -384,6 +396,24 @@ class StandardServerProviderTest {
.header(ProxyHeader.FORWARDED_HOST.getHeader(),
PUBLIC_UNKNOWN_HOST)
.build();
assertResponseStatusCode(httpClient,
publicUnknownForwardedHostRequest, HttpStatus.MISDIRECTED_REQUEST_421);
+
+ final HttpRequest publicStagedHostWithInvalidPort =
HttpRequest.newBuilder(localhostUri)
+ .version(HttpClient.Version.HTTP_1_1)
+ .header(ProxyHeader.FORWARDED_HOST.getHeader(),
PUBLIC_STAGED_HOST_WITH_INVALID_PORT)
+ .build();
+ assertResponseStatusCode(httpClient, publicStagedHostWithInvalidPort,
HttpStatus.MISDIRECTED_REQUEST_421);
+
+ final HttpRequest publicStagedHostWithAPortWhichNotNumber =
HttpRequest.newBuilder(localhostUri)
+ .version(HttpClient.Version.HTTP_1_1)
+ .header(ProxyHeader.FORWARDED_HOST.getHeader(),
PUBLIC_STAGED_HOST_WITH_A_PORT_WHICH_NOT_NUMBER)
+ .build();
+ assertResponseStatusCode(httpClient,
publicStagedHostWithAPortWhichNotNumber, HttpStatus.MISDIRECTED_REQUEST_421);
+
+ final HttpRequest sameHostNameWithInvalidPort =
HttpRequest.newBuilder(localhostUri)
+ .version(HttpClient.Version.HTTP_1_1)
+ .header(ProxyHeader.FORWARDED_HOST.getHeader(),
localhostUri.getHost() + ":" + localhostUri.getPort())
+ .build();
+ assertResponseStatusCode(httpClient, sameHostNameWithInvalidPort,
HttpStatus.MISDIRECTED_REQUEST_421);
}
void assertStandardResponseHeadersFound(final HttpResponse<Void> response)
{