This is an automated email from the ASF dual-hosted git repository.
more pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 21aaa2d48 KNOX-3113: Changed the default HSTS header for global
config, skips copying the HSTS header if its already set (#1008)
21aaa2d48 is described below
commit 21aaa2d48559eeb2646bde4e4185c6f16bc8aa83
Author: hanicz <[email protected]>
AuthorDate: Thu Mar 27 11:45:36 2025 +0100
KNOX-3113: Changed the default HSTS header for global config, skips copying
the HSTS header if its already set (#1008)
---
.../gateway/config/impl/GatewayConfigImpl.java | 2 +-
.../knox/gateway/GatewayGlobalConfigTest.java | 2 +-
.../knox/gateway/dispatch/DefaultDispatch.java | 5 +++
.../knox/gateway/dispatch/DefaultDispatchTest.java | 46 ++++++++++++++++++++++
4 files changed, 53 insertions(+), 2 deletions(-)
diff --git
a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
index 9bac7aa89..c61a8c557 100644
---
a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
+++
b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java
@@ -361,7 +361,7 @@ public class GatewayConfigImpl extends Configuration
implements GatewayConfig {
//Strict-Transport Option
public static final boolean DEFAULT_STRICT_TRANSPORT_ENABLED = false;
- public static final String DEFAULT_STRICT_TRANSPORT_OPTION =
"max-age=31536000";
+ public static final String DEFAULT_STRICT_TRANSPORT_OPTION =
"max-age=31536000; includeSubDomains";
public static final String STRICT_TRANSPORT_ENABLED =
GATEWAY_CONFIG_FILE_PREFIX + ".strict.transport.enabled";
public static final String STRICT_TRANSPORT_OPTION =
GATEWAY_CONFIG_FILE_PREFIX + ".strict.transport.option";
diff --git
a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayGlobalConfigTest.java
b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayGlobalConfigTest.java
index 1742dcba8..dbbc29e4a 100644
---
a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayGlobalConfigTest.java
+++
b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayGlobalConfigTest.java
@@ -213,6 +213,6 @@ public class GatewayGlobalConfigTest {
System.setProperty( GatewayConfigImpl.GATEWAY_HOME_VAR, getHomeDirName(
"conf-demo/conf/gateway-site.xml" ) );
GatewayConfig config = new GatewayConfigImpl();
assertFalse(config.isStrictTransportEnabled());
- assertEquals("max-age=31536000", config.getStrictTransportOption());
+ assertEquals("max-age=31536000; includeSubDomains",
config.getStrictTransportOption());
}
}
diff --git
a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
index 0aba5297c..220817386 100644
---
a/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
+++
b/gateway-spi/src/main/java/org/apache/knox/gateway/dispatch/DefaultDispatch.java
@@ -68,6 +68,7 @@ public class DefaultDispatch extends AbstractGatewayDispatch {
/* list of cookies that should be blocked when set-cookie header is allowed
*/
protected static final Set<String> EXCLUDE_SET_COOKIES_DEFAULT = new
HashSet<>(Arrays.asList("hadoop.auth", "hive.server2.auth", "impala.auth"));
+ protected static final String STRICT_TRANSPORT_SECURITY =
"Strict-Transport-Security";
protected static final SpiGatewayMessages LOG =
MessagesFactory.get(SpiGatewayMessages.class);
protected static final SpiGatewayResources RES =
ResourcesFactory.get(SpiGatewayResources.class);
@@ -359,6 +360,10 @@ public class DefaultDispatch extends
AbstractGatewayDispatch {
getOutboundResponseExcludeHeaders().stream().forEach(excludeHeader ->
excludedHeaderDirectives.put(excludeHeader,
Collections.singleton(EXCLUDE_ALL)));
excludedHeaderDirectives.put(SET_COOKIE,
getOutboundResponseExcludedSetCookieHeaderDirectives());
+ //If HSTS header is already present in the response we skip adding it to
avoid any duplication
+ if(outboundResponse.containsHeader(STRICT_TRANSPORT_SECURITY)) {
+ excludedHeaderDirectives.put(STRICT_TRANSPORT_SECURITY,
Collections.singleton(EXCLUDE_ALL));
+ }
for (Header header : inboundResponse.getAllHeaders()) {
boolean isBlockedAuthHeader =
Arrays.stream(header.getElements()).anyMatch(h ->
EXCLUDE_SET_COOKIES_DEFAULT.contains(h.getName()) &&
getOutboundResponseExcludedSetCookieHeaderDirectives().contains(h.getName()) );
diff --git
a/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/DefaultDispatchTest.java
b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/DefaultDispatchTest.java
index e755f9717..60a3adfa1 100644
---
a/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/DefaultDispatchTest.java
+++
b/gateway-spi/src/test/java/org/apache/knox/gateway/dispatch/DefaultDispatchTest.java
@@ -38,6 +38,9 @@ import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.message.BasicHeader;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.servlet.SynchronousServletOutputStreamAdapter;
import org.apache.knox.test.TestUtils;
@@ -241,4 +244,47 @@ public class DefaultDispatchTest {
}
+ @Test
+ public void testCopyResponseHeaderFieldsCopyHSTS() {
+ HttpServletResponse outboundResponse =
EasyMock.createMock(HttpServletResponse.class);
+ HttpResponse inboundResponse = EasyMock.createMock(HttpResponse.class);
+ Header[] headers = {
+ new BasicHeader(DefaultDispatch.STRICT_TRANSPORT_SECURITY,
"max-age=300"),
+ new BasicHeader("Test", "test")
+ };
+
+
EasyMock.expect(outboundResponse.containsHeader(DefaultDispatch.STRICT_TRANSPORT_SECURITY)).andReturn(false).once();
+ EasyMock.expect(inboundResponse.getAllHeaders()).andReturn(headers).once();
+ outboundResponse.addHeader(DefaultDispatch.STRICT_TRANSPORT_SECURITY,
"max-age=300");
+ EasyMock.expectLastCall().once();
+ outboundResponse.addHeader("Test", "test");
+ EasyMock.expectLastCall().once();
+ EasyMock.replay(outboundResponse, inboundResponse);
+
+ DefaultDispatch dispatch = new DefaultDispatch();
+ dispatch.copyResponseHeaderFields(outboundResponse, inboundResponse);
+
+ EasyMock.verify(outboundResponse, inboundResponse);
+ }
+
+ @Test
+ public void testCopyResponseHeaderFieldsNoCopyHSTS() {
+ HttpServletResponse outboundResponse =
EasyMock.createMock(HttpServletResponse.class);
+ HttpResponse inboundResponse = EasyMock.createMock(HttpResponse.class);
+ Header[] headers = {
+ new BasicHeader(DefaultDispatch.STRICT_TRANSPORT_SECURITY,
"max-age=300"),
+ new BasicHeader("Test", "test")
+ };
+
+
EasyMock.expect(outboundResponse.containsHeader(DefaultDispatch.STRICT_TRANSPORT_SECURITY)).andReturn(true).once();
+ EasyMock.expect(inboundResponse.getAllHeaders()).andReturn(headers).once();
+ outboundResponse.addHeader("Test", "test");
+ EasyMock.expectLastCall().once();
+ EasyMock.replay(outboundResponse, inboundResponse);
+
+ DefaultDispatch dispatch = new DefaultDispatch();
+ dispatch.copyResponseHeaderFields(outboundResponse, inboundResponse);
+
+ EasyMock.verify(outboundResponse, inboundResponse);
+ }
}