Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIFI-14209 Restructure Host Header Validation #9680

Merged
merged 1 commit into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,6 @@ private RequestUriBuilder(final String scheme, final String host, final int port
*/
public static RequestUriBuilder fromHttpServletRequest(final HttpServletRequest httpServletRequest) {
final List<String> allowedContextPaths = getAllowedContextPathsConfigured(httpServletRequest);
return fromHttpServletRequest(httpServletRequest, allowedContextPaths);
}

/**
* Return Builder from HTTP Servlet Request using Scheme, Host, Port, and Context Path reading from headers
*
* @param httpServletRequest HTTP Servlet Request
* @param allowedContextPaths Comma-separated string of allowed context path values for proxy headers
* @return Request URI Builder
*/
public static RequestUriBuilder fromHttpServletRequest(final HttpServletRequest httpServletRequest, final List<String> allowedContextPaths) {
final RequestUriProvider requestUriProvider = new StandardRequestUriProvider(allowedContextPaths);
final URI requestUri = requestUriProvider.getRequestUri(httpServletRequest);
return new RequestUriBuilder(requestUri.getScheme(), requestUri.getHost(), requestUri.getPort(), requestUri.getPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@
*/
package org.apache.nifi.web.servlet.shared;

import jakarta.servlet.ServletContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import jakarta.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand All @@ -48,16 +47,22 @@ public class RequestUriBuilderTest {

private static final String EMPTY = "";

private static final String ALLOWED_CONTEXT_PATHS = "allowedContextPaths";

@Mock
private HttpServletRequest httpServletRequest;

@Mock
private ServletContext servletContext;

@Test
public void testFromHttpServletRequestBuild() {
when(httpServletRequest.getServletContext()).thenReturn(servletContext);
when(httpServletRequest.getServerPort()).thenReturn(PORT);
when(httpServletRequest.getScheme()).thenReturn(SCHEME);
lenient().when(httpServletRequest.getHeader(eq(HOST_HEADER))).thenReturn(HOST);

final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest, Collections.emptyList());
final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest);
final URI uri = builder.build();

assertNotNull(uri);
Expand All @@ -69,11 +74,12 @@ public void testFromHttpServletRequestBuild() {

@Test
public void testFromHttpServletRequestPathBuild() {
when(httpServletRequest.getServletContext()).thenReturn(servletContext);
when(httpServletRequest.getServerPort()).thenReturn(PORT);
when(httpServletRequest.getScheme()).thenReturn(SCHEME);
lenient().when(httpServletRequest.getHeader(eq(HOST_HEADER))).thenReturn(HOST);

final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest, Collections.emptyList());
final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest);
builder.fragment(FRAGMENT).path(CONTEXT_PATH);
final URI uri = builder.build();

Expand All @@ -87,12 +93,14 @@ public void testFromHttpServletRequestPathBuild() {

@Test
public void testFromHttpServletRequestProxyHeadersBuild() {
when(httpServletRequest.getServletContext()).thenReturn(servletContext);
when(servletContext.getInitParameter(eq(ALLOWED_CONTEXT_PATHS))).thenReturn(CONTEXT_PATH);
when(httpServletRequest.getHeader(eq(ProxyHeader.PROXY_SCHEME.getHeader()))).thenReturn(SCHEME);
when(httpServletRequest.getHeader(eq(ProxyHeader.PROXY_HOST.getHeader()))).thenReturn(HOST);
when(httpServletRequest.getHeader(eq(ProxyHeader.PROXY_PORT.getHeader()))).thenReturn(Integer.toString(PORT));
when(httpServletRequest.getHeader(eq(ProxyHeader.PROXY_CONTEXT_PATH.getHeader()))).thenReturn(CONTEXT_PATH);

final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest, List.of(CONTEXT_PATH));
final RequestUriBuilder builder = RequestUriBuilder.fromHttpServletRequest(httpServletRequest);
final URI uri = builder.build();

assertNotNull(uri);
Expand Down
1 change: 1 addition & 0 deletions nifi-docs/src/main/asciidoc/administration-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3444,6 +3444,7 @@ The value can be set to `h2` to require HTTP/2 and disable HTTP/1.1.
|`nifi.web.proxy.host`|A comma separated list of allowed HTTP Host header values to consider when NiFi is running securely and will be receiving requests to a different host[:port] than it is bound to.
For example, when running in a Docker container or behind a proxy (e.g. localhost:18443, proxyhost:443). By default, this value is blank meaning NiFi should only allow requests sent to the
host[:port] that NiFi is bound to.
Requests containing an invalid port in the Host or authority header return an HTTP 421 Misdirected Request status.
|`nifi.web.proxy.context.path`|A comma separated list of allowed HTTP X-ProxyContextPath, X-Forwarded-Context, or X-Forwarded-Prefix header values to consider. By default, this value is
blank meaning all requests containing a proxy context path are rejected. Configuring this property would allow requests where the proxy path is contained in this listing.
|`nifi.web.max.content.size`|The maximum size (HTTP `Content-Length`) for PUT and POST requests. No default value is set for backward compatibility. Providing a value for this property enables the `Content-Length` filter on all incoming API requests (except Site-to-Site and cluster communications). A suggested value is `20 MB`.
Expand Down
Loading