From f7390e1e78ac0aff1e45be216680643eac1c518e Mon Sep 17 00:00:00 2001 From: Henry Avetisyan Date: Tue, 29 Oct 2024 14:29:13 -0700 Subject: [PATCH] config option to support ambiguous uris in jetty servlets Signed-off-by: Henry Avetisyan --- containers/jetty/conf/athenz.properties | 10 +++++++++- containers/jetty/pom.xml | 2 +- .../yahoo/athenz/container/AthenzConsts.java | 1 + .../container/AthenzJettyContainer.java | 20 +++++++++++++++++++ .../container/AthenzJettyContainerTest.java | 13 ++++++++++++ pom.xml | 8 ++++---- 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/containers/jetty/conf/athenz.properties b/containers/jetty/conf/athenz.properties index 8823eec257f..d17a0610631 100644 --- a/containers/jetty/conf/athenz.properties +++ b/containers/jetty/conf/athenz.properties @@ -178,7 +178,7 @@ athenz.jetty_home=/home/athenz # Enable graceful shutdown in the Jetty #athenz.graceful_shutdown=false -# How long to wait for the Jetty server to shutdown, in milliseconds +# How long to wait for the Jetty server to shut down, in milliseconds # If the athenz.graceful_shutdown is not true, this setting is invalid. #athenz.graceful_shutdown_timeout=30000 @@ -201,3 +201,11 @@ athenz.jetty_home=/home/athenz # configuration provider, then the athenz.config.source_paths property # must be set to aws-param-store://zts #athenz.config.source_paths= + +# Boolean flag to indicate whether the server should support ambiguous URIs +# in the request. If this flag is set to true, then the server will set +# uri compliance option to UriCompliance.LEGACY in the Jetty http configuration +# object and set the setDecodeAmbiguousURIs to true in the servlet handler object. +# In Athenz this is required to support AWS temporary credentials request when +# the role name contains the / character. +#athenz.decode_ambiguous_uris=true diff --git a/containers/jetty/pom.xml b/containers/jetty/pom.xml index b55910e13cb..f07cceddca5 100644 --- a/containers/jetty/pom.xml +++ b/containers/jetty/pom.xml @@ -27,7 +27,7 @@ jar - 0.8991 + 0.9055 diff --git a/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzConsts.java b/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzConsts.java index cd3154078af..ab97a284025 100644 --- a/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzConsts.java +++ b/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzConsts.java @@ -65,6 +65,7 @@ public final class AthenzConsts { public static final String ATHENZ_PROP_HEALTH_CHECK_URI_LIST = "athenz.health_check_uri_list"; public static final String ATHENZ_PROP_HEALTH_CHECK_PATH = "athenz.health_check_path"; public static final String ATHENZ_PROP_LOG_FORWARDED_FOR_ADDR = "athenz.log_forwarded_for_addr"; + public static final String ATHENZ_PROP_DECODE_AMBIGUOUS_URIS = "athenz.decode_ambiguous_uris"; public static final String ATHENZ_PROP_RATE_LIMIT_FACTORY_CLASS = "athenz.ratelimit_factory_class"; public static final String ATHENZ_PROP_PRIVATE_KEY_STORE_FACTORY_CLASS = "athenz.private_keystore_factory_class"; diff --git a/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzJettyContainer.java b/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzJettyContainer.java index a2568e8e586..d5432aaac16 100644 --- a/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzJettyContainer.java +++ b/containers/jetty/src/main/java/com/yahoo/athenz/container/AthenzJettyContainer.java @@ -31,10 +31,12 @@ import org.eclipse.jetty.deploy.DeploymentManager; import org.eclipse.jetty.deploy.providers.ContextProvider; import org.eclipse.jetty.ee10.servlet.FilterHolder; +import org.eclipse.jetty.ee10.servlet.ServletHandler; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.rewrite.handler.HeaderPatternRule; import org.eclipse.jetty.rewrite.handler.RewriteHandler; import org.eclipse.jetty.server.*; @@ -70,10 +72,19 @@ public class AthenzJettyContainer { private String banner = null; private Handler.Sequence handlers = null; private PrivateKeyStore privateKeyStore; + private final boolean decodeAmbiguousUris; private final AthenzConnectionListener connectionListener = new AthenzConnectionListener(); private final JettyConnectionLoggerFactory jettyConnectionLoggerFactory = new JettyConnectionLoggerFactory(); public AthenzJettyContainer() { + + // check to see if we want to support ambiguous uris + + decodeAmbiguousUris = Boolean.parseBoolean( + System.getProperty(AthenzConsts.ATHENZ_PROP_DECODE_AMBIGUOUS_URIS, "true")); + + // load our service private key store + loadServicePrivateKey(); } @@ -499,6 +510,9 @@ HttpConfiguration getHttpsConfig(HttpConfiguration httpConfig, int httpsPort, bo httpsConfig.setSecureScheme("https"); httpsConfig.setSecurePort(httpsPort); httpsConfig.addCustomizer(new SecureRequestCustomizer(sniRequired, sniHostCheck, -1L, false)); + if (decodeAmbiguousUris) { + httpsConfig.setUriCompliance(UriCompliance.LEGACY); + } return httpsConfig; } @@ -646,6 +660,12 @@ public void run() { server.setDumpAfterStart(true); server.start(); + + // we're going to set the decodeAmbiguousURIs flag for all our servlet + // handlers if the decodeAmbiguousUris flag is set to true. + + server.getContainedBeans(ServletHandler.class).forEach(handler -> handler.setDecodeAmbiguousURIs(decodeAmbiguousUris)); + System.out.println("Jetty server running at " + banner); server.join(); } catch (Exception e) { diff --git a/containers/jetty/src/test/java/com/yahoo/athenz/container/AthenzJettyContainerTest.java b/containers/jetty/src/test/java/com/yahoo/athenz/container/AthenzJettyContainerTest.java index 0071c9bc72a..8028c9d4619 100644 --- a/containers/jetty/src/test/java/com/yahoo/athenz/container/AthenzJettyContainerTest.java +++ b/containers/jetty/src/test/java/com/yahoo/athenz/container/AthenzJettyContainerTest.java @@ -776,6 +776,19 @@ public void testHttpResponseHeadersInvalidJson() { System.clearProperty(AthenzConsts.ATHENZ_PROP_RESPONSE_HEADERS_JSON); } + @Test + public void testContainerRunMaxThreadsFailure() { + AthenzJettyContainer container = new AthenzJettyContainer(); + container.createServer(1); + + try { + container.run(); + fail(); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("Insufficient configured threads")); + } + } + @Test public void testInitConfigManager() { System.setProperty(AthenzConsts.ATHENZ_PROP_CONFIG_SOURCE_PATHS, "prop-file://./src/test/resources/athenz.properties"); diff --git a/pom.xml b/pom.xml index 46f8cddb5f1..e63d29b6088 100644 --- a/pom.xml +++ b/pom.xml @@ -72,10 +72,10 @@ 2.0.3 - 5.4 + 5.4.1 4.5.14 1.12.777 - 2.29.1 + 2.29.2 2.5.2 2.0.2 1.78.1 @@ -91,8 +91,8 @@ 33.3.1-jre 3.0 0.3 - 2.18.0 - 2.18.0 + 2.18.1 + 2.18.1 2.1.3 2.1.1 2.1.3