From a3f556b22729f4ae93e2810d3e2f89d548986ba3 Mon Sep 17 00:00:00 2001 From: Luca Bassi Date: Wed, 20 Nov 2024 18:03:25 +0100 Subject: [PATCH] Upgrade to Spring Boot 3 --- doc/external-sessions.md | 9 +- pom.xml | 79 ++++-- robot/test/propfind.robot | 4 +- .../ErrorPageAuthenticationEntryPoint.java | 8 +- .../italiangrid/storm/webdav/authz/Utils.java | 4 +- .../authz/VOMSAuthenticationDetails.java | 6 +- .../authz/VOMSAuthenticationFilter.java | 2 +- .../authz/VOMSPreAuthDetailsSource.java | 2 +- .../StormSecurityExpressionMethods.java | 5 + .../authz/managers/ConsensusBasedManager.java | 14 +- .../managers/FineGrainedAuthzManager.java | 12 + .../FineGrainedCopyMoveAuthzManager.java | 12 + .../authz/managers/LocalAuthzManager.java | 12 + .../authz/managers/MacaroonAuthzManager.java | 12 + .../managers/UnanimousDelegatedManager.java | 13 +- .../WlcgScopeAuthzCopyMoveManager.java | 13 +- .../authz/managers/WlcgScopeAuthzManager.java | 12 + .../pdp/DefaultPathAuthorizationPdp.java | 2 +- .../authz/pdp/LocalAuthorizationPdp.java | 5 +- .../authz/pdp/PathAuthorizationPolicy.java | 2 +- .../authz/pdp/PathAuthorizationRequest.java | 2 +- .../WlcgStructuredPathAuthorizationPdp.java | 2 +- .../authz/util/CustomHttpMethodMatcher.java | 4 +- .../authz/util/EmptyPathRequestMatcher.java | 2 +- .../storm/webdav/authz/util/MatcherUtils.java | 2 +- .../authz/util/ReadonlyHttpMethodMatcher.java | 4 +- .../util/SaveAuthnAccessDeniedHandler.java | 6 +- .../util/StructuredPathScopeMatcher.java | 4 +- .../authz/util/WriteHttpMethodMatcher.java | 5 +- .../FineGrainedAuthzPolicyProperties.java | 12 +- .../storm/webdav/config/OAuthProperties.java | 8 +- .../ServiceConfigurationProperties.java | 12 +- .../config/ThirdPartyCopyProperties.java | 11 +- .../webdav/config/validation/Principal.java | 8 +- .../config/validation/PrincipalValidator.java | 4 +- .../macaroon/MacaroonRequestFilter.java | 27 +- .../webdav/metrics/HealthContextListener.java | 8 +- .../metrics/MetricsContextListener.java | 8 +- .../metrics/StorageAreaStatsFilter.java | 14 +- .../webdav/milton/StoRMMiltonRequest.java | 4 +- .../oauth/authzserver/AccessTokenRequest.java | 6 +- .../authzserver/AuthzServerController.java | 7 +- .../DefaultOidcConfigurationFetcher.java | 10 +- .../utils/PermissiveBearerTokenResolver.java | 4 +- .../oidc/ClientRegistrationCacheLoader.java | 2 +- .../redirector/DefaultRedirectionService.java | 4 +- .../webdav/redirector/RedirectFilter.java | 17 +- .../webdav/redirector/RedirectionService.java | 4 +- .../server/DefaultJettyServerCustomizer.java | 13 +- .../DefaultJettyServletWebServerFactory.java | 40 ++- .../server/DefaultWebServerFactory.java | 10 +- .../server/TLSServerConnectorBuilder.java | 2 +- .../webdav/server/servlet/ChecksumFilter.java | 56 ++--- .../servlet/DeleteSanityChecksFilter.java | 14 +- .../server/servlet/LogRequestFilter.java | 16 +- .../webdav/server/servlet/MiltonFilter.java | 18 +- .../MoveRequestSanityChecksFilter.java | 14 +- .../webdav/server/servlet/SAIndexServlet.java | 18 +- .../webdav/server/servlet/SciTagFilter.java | 12 +- .../webdav/server/servlet/StoRMServlet.java | 128 +++++++--- .../StoRMResourceHttpContentFactory.java | 88 +++++++ .../servlet/resource/StormFsResourceView.java | 9 +- .../resource/StormResourceService.java | 96 -------- .../resource/StormResourceWrapper.java | 202 +++------------ .../tracing/LogbackAccessAuthnInfoFilter.java | 13 +- .../server/tracing/RequestIdFilter.java | 16 +- .../server/util/JettyErrorPageHandler.java | 48 ---- .../storm/webdav/spring/AppConfig.java | 83 +++++-- .../storm/webdav/spring/RedirectExec.java | 230 ++++++++++++++++++ .../spring/web/AppContextLoaderListener.java | 2 +- .../web/HttpMethodRequestRejectedHandler.java | 6 +- .../storm/webdav/spring/web/MvcConfig.java | 12 +- .../spring/web/ServletConfiguration.java | 11 +- .../tpc/TpcPlainConnectionSocketFactory.java | 9 +- .../tpc/TpcSSLConnectionSocketFactory.java | 4 +- .../storm/webdav/tpc/TpcUtils.java | 7 +- .../storm/webdav/tpc/TransferFilter.java | 32 ++- .../webdav/tpc/TransferFilterSupport.java | 16 +- .../webdav/tpc/http/GetResponseHandler.java | 15 +- .../webdav/tpc/http/HttpTransferClient.java | 53 ++-- .../HttpTransferClientMetricsWrapper.java | 2 +- .../webdav/tpc/http/PutResponseHandler.java | 15 +- .../tpc/http/ResponseHandlerSupport.java | 10 +- .../tpc/http/SuperLaxRedirectStrategy.java | 90 ------- .../webdav/tpc/transfer/TransferClient.java | 10 +- .../tpc/utils/Adler32DigestHeaderHelper.java | 4 +- .../webdav/tpc/utils/CountingFileEntity.java | 4 +- .../webdav/web/ViewUtilsInterceptor.java | 4 +- src/main/resources/application-redis.yml | 11 +- .../server/TLSConnectorBuilderTest.java | 4 +- .../servlet/AvoidTraceMethodFilterTest.java | 8 +- .../storm/webdav/test/authz/AuthzTest.java | 4 + .../AuthorizationIntegrationTests.java | 45 ++-- .../webdav/test/authz/pdp/AuthzPdpTests.java | 2 +- .../test/authz/pdp/LocalAuthzPdpTests.java | 2 +- .../pdp/PolicyPropertiesValidationTests.java | 8 +- .../authz/pdp/ScopePathAuthzPdpTests.java | 5 +- .../OAuthAuthzServerIntegrationTests.java | 8 +- .../jwk/OidcConfigurationFetcherTest.java | 20 +- .../test/redirector/RedirectFilterTests.java | 10 +- .../redirector/RedirectionServiceTests.java | 7 +- .../webdav/test/tpc/PullTransferTest.java | 10 +- .../webdav/test/tpc/PushTransferTest.java | 22 +- .../test/tpc/SciTagFilterActivationTest.java | 2 +- .../tpc/TransferFilterActivationTest.java | 5 +- .../test/tpc/TransferFilterTestSupport.java | 12 +- .../tpc/TransferRequestValidationTest.java | 6 +- .../test/tpc/TransferReturnStatusTest.java | 12 +- .../webdav/test/tpc/http/ClientTest.java | 37 +-- .../test/tpc/http/ClientTestSupport.java | 11 +- .../webdav/test/tpc/http/DigestTest.java | 7 +- .../test/tpc/http/GetResponseHandlerTest.java | 14 +- .../integration/TpcClientRedirectionTest.java | 16 +- 113 files changed, 1180 insertions(+), 969 deletions(-) create mode 100644 src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StoRMResourceHttpContentFactory.java delete mode 100644 src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceService.java delete mode 100644 src/main/java/org/italiangrid/storm/webdav/server/util/JettyErrorPageHandler.java create mode 100644 src/main/java/org/italiangrid/storm/webdav/spring/RedirectExec.java delete mode 100644 src/main/java/org/italiangrid/storm/webdav/tpc/http/SuperLaxRedirectStrategy.java diff --git a/doc/external-sessions.md b/doc/external-sessions.md index 50c1cb57..e5ec900f 100644 --- a/doc/external-sessions.md +++ b/doc/external-sessions.md @@ -17,9 +17,10 @@ spring: session: store-type: redis - redis: - host: redis.host.example - port: 6379 + data: + redis: + host: redis.host.example + port: 6379 management: health: @@ -30,4 +31,4 @@ management: For other redis connection configuration options, see the [Spring boot reference guide][spring-boot-reference]. [redis]: https://redis.io/ -[spring-boot-reference]: https://docs.spring.io/spring-boot/docs/2.2.9.RELEASE/reference/htmlsingle/#data-properties +[spring-boot-reference]: https://docs.spring.io/spring-boot/appendix/application-properties/index.html#appendix.application-properties.data diff --git a/pom.xml b/pom.xml index 65f889b8..bba92475 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.18 + 3.4.0 @@ -26,13 +26,13 @@ 2.4 2.3 1.9.0 + 9.0.1 0.8.8 17 - 2.7.18 - 5.8.15 + 3.4.0 italiangrid_storm-webdav @@ -40,15 +40,19 @@ https://sonarcloud.io 3.3.3 - 2.7.1.7 + 4.0.4.2305 2.3 1.2 1.0 1.1 - 4.2.2 - 4.2.1 + 4.2.28 + 11.0.24 + 5.4.1 + + 2.0.3 + 2.0.4 32.0.0-jre @@ -77,8 +81,20 @@ - pl.project13.maven - git-commit-id-plugin + io.github.git-commit-id + git-commit-id-maven-plugin + ${plugin.git-commit-id.version} + + + + org.apache.maven.plugins + maven-compiler-plugin + + true + + -parameters + + @@ -171,6 +187,23 @@ + + org.apache.groovy + groovy + 4.0.21 + + + org.springframework.boot + spring-boot-properties-migrator + runtime + + + com.vaadin.external.google + android-json + + + + com.google.jimfs jimfs @@ -314,11 +347,13 @@ io.dropwizard.metrics metrics-core + ${metrics.version} io.dropwizard.metrics - metrics-jetty9 + metrics-jetty12 + ${metrics.version} org.eclipse.jetty @@ -329,12 +364,20 @@ io.dropwizard.metrics - metrics-servlets + metrics-jetty12-ee10 + ${metrics.version} + + + + io.dropwizard.metrics + metrics-jakarta-servlets + ${metrics.version} org.eclipse.jetty.http2 http2-server + ${http-server.version} @@ -359,8 +402,9 @@ - ch.qos.logback - logback-access + ch.qos.logback.access + common + ${logback-access.version} @@ -374,8 +418,15 @@ - org.apache.httpcomponents - httpclient + ch.qos.logback.access + logback-access-jetty12 + ${logback-access-jetty12.version} + + + + org.apache.httpcomponents.client5 + httpclient5 + ${httpclient5.version} commons-logging diff --git a/robot/test/propfind.robot b/robot/test/propfind.robot index 113aad9a..d296981c 100644 --- a/robot/test/propfind.robot +++ b/robot/test/propfind.robot @@ -22,7 +22,7 @@ Get PROPFIND PROPNAME body [Return] ${output} Get PROPFIND PROP body [Arguments] ${propname} - ${output} Set variable "" + ${output} Set variable "" [Return] ${output} @@ -71,4 +71,4 @@ Propfind status property works ${body} Get PROPFIND PROP body status ${rc} ${out} Curl Voms PROPFIND ${url} ${body} Should Contain ${out} HTTP/1.1 200 OK - [Teardown] Teardown file propfind_works \ No newline at end of file + [Teardown] Teardown file propfind_works diff --git a/src/main/java/org/italiangrid/storm/webdav/authn/ErrorPageAuthenticationEntryPoint.java b/src/main/java/org/italiangrid/storm/webdav/authn/ErrorPageAuthenticationEntryPoint.java index 80216572..40451fb2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authn/ErrorPageAuthenticationEntryPoint.java +++ b/src/main/java/org/italiangrid/storm/webdav/authn/ErrorPageAuthenticationEntryPoint.java @@ -19,10 +19,10 @@ import java.util.LinkedHashMap; import java.util.Map; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/Utils.java b/src/main/java/org/italiangrid/storm/webdav/authz/Utils.java index 8ed45b50..5b9f11da 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/Utils.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/Utils.java @@ -19,13 +19,13 @@ import java.util.Optional; import javax.security.auth.x500.X500Principal; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import eu.emi.security.authn.x509.proxy.ProxyUtils; public class Utils { - public static final String X509_CERT_REQ_ATTR = "javax.servlet.request.X509Certificate"; + public static final String X509_CERT_REQ_ATTR = "jakarta.servlet.request.X509Certificate"; private Utils() { diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationDetails.java b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationDetails.java index 653c1197..68f5d69a 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationDetails.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationDetails.java @@ -18,7 +18,7 @@ import java.util.Collection; import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.voms.VOMSAttribute; import org.springframework.security.core.GrantedAuthority; @@ -26,9 +26,9 @@ public class VOMSAuthenticationDetails extends PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails { - + private static final long serialVersionUID = 1L; - + // Transient here is due to the fact that VOMSAttributesImpl is not serializable! final transient List vomsAttributes; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationFilter.java b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationFilter.java index 843424ec..4a12fab1 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSAuthenticationFilter.java @@ -18,7 +18,7 @@ import java.security.cert.X509Certificate; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSPreAuthDetailsSource.java b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSPreAuthDetailsSource.java index 8bd704fc..25d3fdb3 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/VOMSPreAuthDetailsSource.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/VOMSPreAuthDetailsSource.java @@ -23,7 +23,7 @@ import java.util.Set; import javax.security.auth.x500.X500Principal; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.vomap.VOMapDetailsService; import org.italiangrid.voms.VOMSAttribute; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormSecurityExpressionMethods.java b/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormSecurityExpressionMethods.java index 91a81607..d44017d1 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormSecurityExpressionMethods.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormSecurityExpressionMethods.java @@ -18,9 +18,13 @@ import org.italiangrid.storm.webdav.authz.VOMSVOAuthority; import org.italiangrid.storm.webdav.authz.VOMSVOMapAuthority; import org.springframework.security.core.Authentication; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class StormSecurityExpressionMethods { + private static final Logger LOG = LoggerFactory.getLogger(StormSecurityExpressionMethods.class); + final Authentication authentication; public StormSecurityExpressionMethods(Authentication authn) { @@ -28,6 +32,7 @@ public StormSecurityExpressionMethods(Authentication authn) { } public boolean isVOMSAuthenticated() { + LOG.warn("isVOMSAuthenticated: {}", authentication.getAuthorities().stream().anyMatch(VOMSVOAuthority.class::isInstance)); return authentication.getAuthorities().stream().anyMatch(VOMSVOAuthority.class::isInstance); } diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java index 4533da30..63285411 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java @@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -39,14 +40,25 @@ public ConsensusBasedManager(String name, this.managers = managers; } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { int grant = 0; int notGrant = 0; for (AuthorizationManager manager : managers) { - AuthorizationDecision result = manager.check(authentication, requestAuthorizationContext); + AuthorizationResult result = manager.authorize(authentication, requestAuthorizationContext); if (LOG.isDebugEnabled()) { LOG.debug("Voter: {}, returned: {}", manager, result); diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java index 68039afa..17d4d613 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java @@ -27,6 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -40,9 +41,20 @@ public FineGrainedAuthzManager(ServiceConfigurationProperties config, PathResolv super(config, resolver, pdp, localUrlService, true); } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { final String requestPath = getRequestPath(requestAuthorizationContext.getRequest()); StorageAreaInfo sa = resolver.resolveStorageArea(requestPath); diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java index 6e5d4d38..ac891291 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -44,9 +45,20 @@ public FineGrainedCopyMoveAuthzManager(ServiceConfigurationProperties config, super(config, resolver, pdp, localUrlService, true); } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { if (!isCopyOrMoveRequest(requestAuthorizationContext.getRequest())) { return null; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java index 75961cb0..41c4a87c 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -56,9 +57,20 @@ private boolean isLocalAuthzToken(JwtAuthenticationToken token) { && !isNullOrEmpty(token.getToken().getClaimAsString(DefaultJwtTokenIssuer.PATH_CLAIM)); } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { if (!(authentication.get() instanceof JwtAuthenticationToken)) { return null; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java index 9dddb12d..95290bd2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java @@ -20,15 +20,27 @@ import org.springframework.http.HttpMethod; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; import org.springframework.util.Assert; public class MacaroonAuthzManager implements AuthorizationManager { + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { Assert.notNull(authentication.get(), "authentication must not be null"); Assert.notNull(requestAuthorizationContext, "filterInvocation must not be null"); diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java index b5279138..3d6a7827 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java @@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -40,13 +41,23 @@ private UnanimousDelegatedManager(String name, this.managers = managers; } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext filter) { + if (authorize(authentication, filter) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext filter) { int grant = 0; for (AuthorizationManager manager : managers) { - AuthorizationDecision result = manager.check(authentication, filter); + AuthorizationResult result = manager.authorize(authentication, filter); if (LOG.isDebugEnabled()) { LOG.debug("Voter: {}, returned: {}", manager, result); diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java index f431743d..8278eb17 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java @@ -32,6 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -45,10 +46,20 @@ public WlcgScopeAuthzCopyMoveManager(ServiceConfigurationProperties config, Path super(config, resolver, pdp, localUrlService, true); } - + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { if (!(authentication.get() instanceof JwtAuthenticationToken)) { return null; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java index 36e0c2e5..983fd3af 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java @@ -27,6 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationResult; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.web.access.intercept.RequestAuthorizationContext; @@ -41,9 +42,20 @@ public WlcgScopeAuthzManager(ServiceConfigurationProperties config, PathResolver super(config, resolver, pdp, localUrlService, true); } + @Deprecated @Override public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext requestAuthorizationContext) { + if (authorize(authentication, + requestAuthorizationContext) instanceof AuthorizationDecision authorizationDecision) { + return authorizationDecision; + } + return null; + } + + @Override + public AuthorizationResult authorize(Supplier authentication, + RequestAuthorizationContext requestAuthorizationContext) { if (!(authentication.get() instanceof JwtAuthenticationToken)) { return null; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/DefaultPathAuthorizationPdp.java b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/DefaultPathAuthorizationPdp.java index b3f0ff46..9d4a85e7 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/DefaultPathAuthorizationPdp.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/DefaultPathAuthorizationPdp.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.authz.pdp; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/LocalAuthorizationPdp.java b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/LocalAuthorizationPdp.java index 03c294df..1ac0d0d8 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/LocalAuthorizationPdp.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/LocalAuthorizationPdp.java @@ -28,7 +28,7 @@ import java.util.Set; import java.util.function.Supplier; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.oauth.authzserver.ResourceAccessTokenRequest.Permission; @@ -97,8 +97,7 @@ public PathAuthorizationResult authorizeRequest(PathAuthorizationRequest authzRe if (LOG.isDebugEnabled()) { if (originIp.isPresent()) { LOG.debug("Ok: {}, pathMatches: {}, permMatches: {}, originMatches: {}", ok, pathMatches, - permMatches, - originMatches); + permMatches, originMatches); } else { LOG.debug("Ok: {}, pathMatches: {}, permMatches: {}", ok, pathMatches, permMatches); } diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationPolicy.java b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationPolicy.java index ba29d611..5a83ad8f 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationPolicy.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationPolicy.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.UUID; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.pdp.principal.PrincipalMatcher; import org.slf4j.Logger; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationRequest.java b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationRequest.java index 9b00326a..294639eb 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationRequest.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/PathAuthorizationRequest.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.authz.pdp; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.server.servlet.WebDAVMethod; import org.springframework.lang.Nullable; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/WlcgStructuredPathAuthorizationPdp.java b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/WlcgStructuredPathAuthorizationPdp.java index 6cb4d3ba..941bcae1 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/pdp/WlcgStructuredPathAuthorizationPdp.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/pdp/WlcgStructuredPathAuthorizationPdp.java @@ -28,7 +28,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.util.MatcherUtils; import org.italiangrid.storm.webdav.authz.util.StructuredPathScopeMatcher; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/CustomHttpMethodMatcher.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/CustomHttpMethodMatcher.java index c49458be..ded39869 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/CustomHttpMethodMatcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/CustomHttpMethodMatcher.java @@ -17,7 +17,7 @@ import java.util.Set; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,5 +53,5 @@ public boolean matches(HttpServletRequest request) { public String toString() { return "CustomHttpMethodMatcher [supportedMethods=" + supportedMethods + "]"; } - + } diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/EmptyPathRequestMatcher.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/EmptyPathRequestMatcher.java index 2dc13c0f..039f9c0b 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/EmptyPathRequestMatcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/EmptyPathRequestMatcher.java @@ -17,7 +17,7 @@ import static com.google.common.base.Strings.isNullOrEmpty; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.web.util.matcher.RequestMatcher; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/MatcherUtils.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/MatcherUtils.java index f084d252..fd09d055 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/MatcherUtils.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/MatcherUtils.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.authz.util; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/ReadonlyHttpMethodMatcher.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/ReadonlyHttpMethodMatcher.java index a5aa267e..c7ac4062 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/ReadonlyHttpMethodMatcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/ReadonlyHttpMethodMatcher.java @@ -19,7 +19,7 @@ import java.util.Set; import java.util.TreeSet; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.web.util.matcher.AndRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -54,5 +54,5 @@ public boolean matches(HttpServletRequest request) { public String toString() { return "ReadonlyHttpMethodMatcher [delegate=" + delegate + "]"; } - + } diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/SaveAuthnAccessDeniedHandler.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/SaveAuthnAccessDeniedHandler.java index b563464d..4cd48a8d 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/SaveAuthnAccessDeniedHandler.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/SaveAuthnAccessDeniedHandler.java @@ -17,9 +17,9 @@ import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.authn.PrincipalHelper; import org.italiangrid.storm.webdav.server.tracing.LogbackAccessAuthnInfoFilter; diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/StructuredPathScopeMatcher.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/StructuredPathScopeMatcher.java index 42017870..54b60847 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/StructuredPathScopeMatcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/StructuredPathScopeMatcher.java @@ -22,7 +22,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.Generated; +import jakarta.annotation.Generated; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,7 +84,7 @@ public boolean matchesPathIncludingParents(String path) { public static StructuredPathScopeMatcher fromString(String scope) { final int sepIndex = scope.indexOf(SEP); final String prefix = scope.substring(0, sepIndex); - final String path = scope.substring(sepIndex+1, scope.length()); + final String path = scope.substring(sepIndex + 1, scope.length()); return new StructuredPathScopeMatcher(prefix, path); } diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/util/WriteHttpMethodMatcher.java b/src/main/java/org/italiangrid/storm/webdav/authz/util/WriteHttpMethodMatcher.java index e91535bb..90301a5e 100644 --- a/src/main/java/org/italiangrid/storm/webdav/authz/util/WriteHttpMethodMatcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/authz/util/WriteHttpMethodMatcher.java @@ -20,7 +20,7 @@ import java.util.Set; import java.util.TreeSet; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.web.util.matcher.AndRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -31,8 +31,7 @@ public class WriteHttpMethodMatcher implements RequestMatcher { // COPY is now classified as a write method since there's a single case // where COPY is a read-only method: TPC push copy, while local COPY (in the same storage // area) and TPC pull COPY all require write privileges - private static final Set METHODS = - new TreeSet<>(asList("PUT", "MKCOL", "MOVE", "COPY")); + private static final Set METHODS = new TreeSet<>(asList("PUT", "MKCOL", "MOVE", "COPY")); private final RequestMatcher delegate; diff --git a/src/main/java/org/italiangrid/storm/webdav/config/FineGrainedAuthzPolicyProperties.java b/src/main/java/org/italiangrid/storm/webdav/config/FineGrainedAuthzPolicyProperties.java index dc3d35c8..5f53601b 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/FineGrainedAuthzPolicyProperties.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/FineGrainedAuthzPolicyProperties.java @@ -19,9 +19,9 @@ import java.util.List; import java.util.Map; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import org.italiangrid.storm.webdav.authz.pdp.PolicyEffect; import org.italiangrid.storm.webdav.config.validation.Principal; @@ -74,11 +74,7 @@ public void setParams(Map params) { } public enum Action { - READ, - WRITE, - DELETE, - LIST, - ALL + READ, WRITE, DELETE, LIST, ALL } @NotBlank diff --git a/src/main/java/org/italiangrid/storm/webdav/config/OAuthProperties.java b/src/main/java/org/italiangrid/storm/webdav/config/OAuthProperties.java index aab8d1f6..37fffd6c 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/OAuthProperties.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/OAuthProperties.java @@ -17,8 +17,8 @@ import java.util.List; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; import org.hibernate.validator.constraints.URL; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -90,7 +90,7 @@ public boolean isEnforceAudienceChecks() { } List issuers; - + boolean enableOidc = false; @Min(value = 1, message = "The refresh period must be a positive integer") @@ -126,7 +126,7 @@ public void setRefreshTimeoutSeconds(int refreshTimeoutSeconds) { public void setEnableOidc(boolean enableOidc) { this.enableOidc = enableOidc; } - + public boolean isEnableOidc() { return enableOidc; } diff --git a/src/main/java/org/italiangrid/storm/webdav/config/ServiceConfigurationProperties.java b/src/main/java/org/italiangrid/storm/webdav/config/ServiceConfigurationProperties.java index dbacabad..63a77918 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/ServiceConfigurationProperties.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/ServiceConfigurationProperties.java @@ -20,12 +20,12 @@ import java.net.URI; import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Positive; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Positive; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/org/italiangrid/storm/webdav/config/ThirdPartyCopyProperties.java b/src/main/java/org/italiangrid/storm/webdav/config/ThirdPartyCopyProperties.java index b8835b69..e47ecfb8 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/ThirdPartyCopyProperties.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/ThirdPartyCopyProperties.java @@ -15,9 +15,9 @@ */ package org.italiangrid.storm.webdav.config; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Positive; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Positive; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -44,7 +44,7 @@ public class ThirdPartyCopyProperties { @Min(value = 4096, message = "tpc.httpClientSocketBufferSize must be > 4096") int httpClientSocketBufferSize = 8192; - + boolean useConscrypt = false; boolean enableTlsClientAuth = false; @@ -55,7 +55,8 @@ public class ThirdPartyCopyProperties { @Positive(message = "tpc.progressReportThreadPoolSize must be a positive integer (i.e. > 0)") int progressReportThreadPoolSize; - @Min(value = 0, message = "Threshold of content size to reach before sending 'Expect: 100-continue' header.") + @Min(value = 0, + message = "Threshold of content size to reach before sending 'Expect: 100-continue' header.") long enableExpectContinueThreshold; public String getTlsProtocol() { diff --git a/src/main/java/org/italiangrid/storm/webdav/config/validation/Principal.java b/src/main/java/org/italiangrid/storm/webdav/config/validation/Principal.java index abf86621..9572a358 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/validation/Principal.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/validation/Principal.java @@ -22,14 +22,16 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; @Retention(RUNTIME) @Target({TYPE, ANNOTATION_TYPE}) -@Constraint(validatedBy=PrincipalValidator.class) +@Constraint(validatedBy = PrincipalValidator.class) public @interface Principal { String message() default "Invalid principal"; + Class[] groups() default {}; + Class[] payload() default {}; } diff --git a/src/main/java/org/italiangrid/storm/webdav/config/validation/PrincipalValidator.java b/src/main/java/org/italiangrid/storm/webdav/config/validation/PrincipalValidator.java index dab3fe78..2ca0fa8e 100644 --- a/src/main/java/org/italiangrid/storm/webdav/config/validation/PrincipalValidator.java +++ b/src/main/java/org/italiangrid/storm/webdav/config/validation/PrincipalValidator.java @@ -29,8 +29,8 @@ import java.util.Collection; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import org.italiangrid.storm.webdav.config.FineGrainedAuthzPolicyProperties; import org.italiangrid.storm.webdav.config.FineGrainedAuthzPolicyProperties.PrincipalProperties.PrincipalType; diff --git a/src/main/java/org/italiangrid/storm/webdav/macaroon/MacaroonRequestFilter.java b/src/main/java/org/italiangrid/storm/webdav/macaroon/MacaroonRequestFilter.java index 4b810833..f1761878 100644 --- a/src/main/java/org/italiangrid/storm/webdav/macaroon/MacaroonRequestFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/macaroon/MacaroonRequestFilter.java @@ -15,19 +15,19 @@ */ package org.italiangrid.storm.webdav.macaroon; -import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; -import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; -import static javax.servlet.http.HttpServletResponse.SC_OK; +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static jakarta.servlet.http.HttpServletResponse.SC_OK; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -90,12 +90,9 @@ private void processMacaroonRequest(HttpServletRequest httpRequest, mapper.writeValue(httpResponse.getWriter(), res); } catch (AccessDeniedException e) { - httpResponse.sendError(SC_FORBIDDEN, - "Access denied"); - + httpResponse.sendError(SC_FORBIDDEN, "Access denied"); } catch (IOException e) { - httpResponse.sendError(SC_BAD_REQUEST, - "Invalid macaroon request"); + httpResponse.sendError(SC_BAD_REQUEST, "Invalid macaroon request"); } } } diff --git a/src/main/java/org/italiangrid/storm/webdav/metrics/HealthContextListener.java b/src/main/java/org/italiangrid/storm/webdav/metrics/HealthContextListener.java index 622f2d78..fc19ef72 100644 --- a/src/main/java/org/italiangrid/storm/webdav/metrics/HealthContextListener.java +++ b/src/main/java/org/italiangrid/storm/webdav/metrics/HealthContextListener.java @@ -19,19 +19,19 @@ import org.springframework.stereotype.Component; import com.codahale.metrics.health.HealthCheckRegistry; -import com.codahale.metrics.servlets.HealthCheckServlet.ContextListener; +import io.dropwizard.metrics.servlets.HealthCheckServlet.ContextListener; @Component public class HealthContextListener extends ContextListener { - + private HealthCheckRegistry registry; @Autowired public HealthContextListener(HealthCheckRegistry r) { this.registry = r; - + } - + @Override protected HealthCheckRegistry getHealthCheckRegistry() { return registry; diff --git a/src/main/java/org/italiangrid/storm/webdav/metrics/MetricsContextListener.java b/src/main/java/org/italiangrid/storm/webdav/metrics/MetricsContextListener.java index 322d489e..65eb13bf 100644 --- a/src/main/java/org/italiangrid/storm/webdav/metrics/MetricsContextListener.java +++ b/src/main/java/org/italiangrid/storm/webdav/metrics/MetricsContextListener.java @@ -19,20 +19,20 @@ import org.springframework.stereotype.Component; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.servlets.MetricsServlet.ContextListener; +import io.dropwizard.metrics.servlets.MetricsServlet.ContextListener; @Component public class MetricsContextListener extends ContextListener { - + private MetricRegistry registry; - + @Autowired public MetricsContextListener(MetricRegistry r) { registry = r; } - + @Override protected MetricRegistry getMetricRegistry() { return registry; diff --git a/src/main/java/org/italiangrid/storm/webdav/metrics/StorageAreaStatsFilter.java b/src/main/java/org/italiangrid/storm/webdav/metrics/StorageAreaStatsFilter.java index 2903f6b3..79b07508 100644 --- a/src/main/java/org/italiangrid/storm/webdav/metrics/StorageAreaStatsFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/metrics/StorageAreaStatsFilter.java @@ -19,13 +19,13 @@ import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.config.StorageAreaInfo; import org.italiangrid.storm.webdav.server.PathResolver; diff --git a/src/main/java/org/italiangrid/storm/webdav/milton/StoRMMiltonRequest.java b/src/main/java/org/italiangrid/storm/webdav/milton/StoRMMiltonRequest.java index d1021cc4..4c593039 100644 --- a/src/main/java/org/italiangrid/storm/webdav/milton/StoRMMiltonRequest.java +++ b/src/main/java/org/italiangrid/storm/webdav/milton/StoRMMiltonRequest.java @@ -18,8 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; import org.eclipse.jetty.util.URIUtil; diff --git a/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AccessTokenRequest.java b/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AccessTokenRequest.java index d1eb1a00..19362dea 100644 --- a/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AccessTokenRequest.java +++ b/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AccessTokenRequest.java @@ -15,9 +15,9 @@ */ package org.italiangrid.storm.webdav.oauth.authzserver; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; public class AccessTokenRequest { diff --git a/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AuthzServerController.java b/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AuthzServerController.java index 59d90717..eddf3561 100644 --- a/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AuthzServerController.java +++ b/src/main/java/org/italiangrid/storm/webdav/oauth/authzserver/AuthzServerController.java @@ -22,8 +22,8 @@ import static org.italiangrid.storm.webdav.oauth.authzserver.ErrorResponseDTO.INVALID_SCOPE; import static org.italiangrid.storm.webdav.oauth.authzserver.ErrorResponseDTO.UNSUPPORTED_GRANT_TYPE; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; import org.italiangrid.storm.webdav.oauth.authzserver.error.InvalidScopeError; import org.italiangrid.storm.webdav.oauth.authzserver.error.InvalidTokenRequestError; @@ -56,7 +56,8 @@ protected void handleValidationError(FieldError e) { throw new InvalidTokenRequestError(e.getDefaultMessage()); } if (INVALID_GRANT_TYPE.equals(e.getDefaultMessage())) { - throw new UnsupportedGrantTypeError(format("%s: %s", e.getDefaultMessage(), e.getRejectedValue())); + throw new UnsupportedGrantTypeError( + format("%s: %s", e.getDefaultMessage(), e.getRejectedValue())); } throw new InvalidScopeError(e.getDefaultMessage() != null ? e.getDefaultMessage() : ""); } diff --git a/src/main/java/org/italiangrid/storm/webdav/oauth/utils/DefaultOidcConfigurationFetcher.java b/src/main/java/org/italiangrid/storm/webdav/oauth/utils/DefaultOidcConfigurationFetcher.java index f1c1c1f3..089a138b 100644 --- a/src/main/java/org/italiangrid/storm/webdav/oauth/utils/DefaultOidcConfigurationFetcher.java +++ b/src/main/java/org/italiangrid/storm/webdav/oauth/utils/DefaultOidcConfigurationFetcher.java @@ -57,7 +57,7 @@ public class DefaultOidcConfigurationFetcher implements OidcConfigurationFetcher public DefaultOidcConfigurationFetcher(RestTemplateBuilder restBuilder, OAuthProperties oAuthProperties) { final Duration timeout = Duration.ofSeconds(oAuthProperties.getRefreshTimeoutSeconds()); - this.restTemplate = restBuilder.setConnectTimeout(timeout).setReadTimeout(timeout).build(); + this.restTemplate = restBuilder.connectTimeout(timeout).readTimeout(timeout).build(); } private void metadataChecks(String issuer, Map oidcConfiguration) { @@ -95,9 +95,9 @@ public Map loadConfigurationForIssuer(String issuer) { } throw new OidcConfigurationResolutionError(errorMsg, e); } - if (response.getStatusCodeValue() != 200) { + if (response.getStatusCode().value() != 200) { throw new OidcConfigurationResolutionError( - format("Received status code: %s", response.getStatusCodeValue())); + format("Received status code: %s", response.getStatusCode().value())); } if (response.getBody() == null) { throw new OidcConfigurationResolutionError("Received null body"); @@ -124,9 +124,9 @@ public String loadJWKSourceForURL(URI uri) throws KeySourceException { } throw new RemoteKeySourceException(errorMsg, e); } - if (response.getStatusCodeValue() != 200) { + if (response.getStatusCode().value() != 200) { throw new KeySourceException(format("Unable to get JWK from '%s': received status code %s", - uri, response.getStatusCodeValue())); + uri, response.getStatusCode().value())); } return response.getBody(); } diff --git a/src/main/java/org/italiangrid/storm/webdav/oauth/utils/PermissiveBearerTokenResolver.java b/src/main/java/org/italiangrid/storm/webdav/oauth/utils/PermissiveBearerTokenResolver.java index dbde22f3..6cecaef2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/oauth/utils/PermissiveBearerTokenResolver.java +++ b/src/main/java/org/italiangrid/storm/webdav/oauth/utils/PermissiveBearerTokenResolver.java @@ -18,7 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -29,7 +29,7 @@ import org.springframework.util.StringUtils; /** - * + * * Does not raise error when a bearer token is found both as parameter and in the Authorization * header. Request parameter takes precedence * diff --git a/src/main/java/org/italiangrid/storm/webdav/oidc/ClientRegistrationCacheLoader.java b/src/main/java/org/italiangrid/storm/webdav/oidc/ClientRegistrationCacheLoader.java index 805ed969..fb02a844 100644 --- a/src/main/java/org/italiangrid/storm/webdav/oidc/ClientRegistrationCacheLoader.java +++ b/src/main/java/org/italiangrid/storm/webdav/oidc/ClientRegistrationCacheLoader.java @@ -56,7 +56,7 @@ public ClientRegistrationCacheLoader(OAuth2ClientProperties clientProperties, private ClientRegistration getClientRegistration(String registrationId, OAuth2ClientProperties.Registration properties, Map providers) { - String provider = StringUtils.trimWhitespace(properties.getProvider()); + String provider = properties.getProvider().strip(); Builder builder = getBuilderFromIssuerIfPossible(registrationId, provider, providers); if (builder == null) { return null; diff --git a/src/main/java/org/italiangrid/storm/webdav/redirector/DefaultRedirectionService.java b/src/main/java/org/italiangrid/storm/webdav/redirector/DefaultRedirectionService.java index 40e9af8d..5dea18fc 100644 --- a/src/main/java/org/italiangrid/storm/webdav/redirector/DefaultRedirectionService.java +++ b/src/main/java/org/italiangrid/storm/webdav/redirector/DefaultRedirectionService.java @@ -18,8 +18,8 @@ import java.net.URI; import java.util.function.Supplier; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties.RedirectorProperties.ReplicaEndpointProperties; diff --git a/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectFilter.java b/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectFilter.java index 7150b8e4..7bf3aa1c 100644 --- a/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectFilter.java @@ -18,13 +18,13 @@ import java.io.IOException; import java.nio.file.Path; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.server.PathResolver; import org.italiangrid.storm.webdav.tpc.TpcUtils; @@ -112,8 +112,7 @@ private boolean requestedResourceExistsAndIsAFile(HttpServletRequest req) { private boolean isRedirectable(HttpServletRequest req) { return isSecureRequest(req) && !isNoRedirectRequest(req) && isGetOrPutRequest(req) - && requestDoesNotHaveAccessToken(req) - && requestedResourceExistsAndIsAFile(req); + && requestDoesNotHaveAccessToken(req) && requestedResourceExistsAndIsAFile(req); } } diff --git a/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectionService.java b/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectionService.java index 02eadf3e..2882f626 100644 --- a/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectionService.java +++ b/src/main/java/org/italiangrid/storm/webdav/redirector/RedirectionService.java @@ -15,8 +15,8 @@ */ package org.italiangrid.storm.webdav.redirector; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServerCustomizer.java b/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServerCustomizer.java index 82c028e0..60ee28e2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServerCustomizer.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServerCustomizer.java @@ -20,8 +20,9 @@ import java.io.File; import java.nio.file.Paths; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; +import org.eclipse.jetty.rewrite.handler.CompactPathRule; import org.eclipse.jetty.rewrite.handler.RewriteHandler; import org.eclipse.jetty.rewrite.handler.RewriteRegexRule; import org.eclipse.jetty.server.HttpConfiguration; @@ -38,8 +39,8 @@ import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.jetty9.InstrumentedConnectionFactory; -import com.codahale.metrics.jetty9.InstrumentedHandler; +import io.dropwizard.metrics.jetty12.InstrumentedConnectionFactory; +import io.dropwizard.metrics.jetty12.ee10.InstrumentedEE10Handler; import ch.qos.logback.access.jetty.RequestLogImpl; import eu.emi.security.authn.x509.X509CertChainValidatorExt; @@ -148,8 +149,7 @@ private void configureRewriteHandler(Server server) { RewriteHandler rh = new RewriteHandler(); - rh.setRewritePathInfo(true); - rh.setRewriteRequestURI(true); + CompactPathRule compactPathRule = new CompactPathRule(); RewriteRegexRule dropLegacyWebDAV = new RewriteRegexRule(); dropLegacyWebDAV.setRegex("/webdav/(.*)"); @@ -159,12 +159,13 @@ private void configureRewriteHandler(Server server) { dropLegacyFileTransfer.setRegex("/fileTransfer/(.*)"); dropLegacyFileTransfer.setReplacement("/$1"); + rh.addRule(compactPathRule); rh.addRule(dropLegacyWebDAV); rh.addRule(dropLegacyFileTransfer); rh.setHandler(server.getHandler()); - InstrumentedHandler ih = new InstrumentedHandler(metricRegistry, "storm.http.handler"); + InstrumentedEE10Handler ih = new InstrumentedEE10Handler(metricRegistry, "storm.http.handler"); ih.setHandler(rh); server.setHandler(ih); diff --git a/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServletWebServerFactory.java b/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServletWebServerFactory.java index 6a590332..3da0fa7e 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServletWebServerFactory.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/DefaultJettyServletWebServerFactory.java @@ -21,23 +21,16 @@ import java.util.Collection; import java.util.List; -import org.eclipse.jetty.server.handler.ErrorHandler; -import org.eclipse.jetty.servlet.ErrorPageErrorHandler; -import org.eclipse.jetty.webapp.AbstractConfiguration; -import org.eclipse.jetty.webapp.Configuration; -import org.eclipse.jetty.webapp.WebAppContext; -import org.italiangrid.storm.webdav.server.util.JettyErrorPageHandler; +import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler; +import org.eclipse.jetty.ee10.webapp.AbstractConfiguration; +import org.eclipse.jetty.ee10.webapp.Configuration; +import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; import org.springframework.boot.web.server.ErrorPage; import org.springframework.boot.web.servlet.ServletContextInitializer; public class DefaultJettyServletWebServerFactory extends JettyServletWebServerFactory { - @Override - protected void postProcessWebAppContext(WebAppContext context) { - context.setCompactPath(true); - } - @Override protected Configuration[] getWebAppContextConfigurations(WebAppContext webAppContext, ServletContextInitializer... initializers) { @@ -50,33 +43,30 @@ protected Configuration[] getWebAppContextConfigurations(WebAppContext webAppCon } private Configuration getStormErrorPageConfiguration() { - return new AbstractConfiguration() { + return new AbstractConfiguration(new AbstractConfiguration.Builder()) { @Override public void configure(WebAppContext context) throws Exception { - JettyErrorPageHandler errorHandler = new JettyErrorPageHandler(); + ErrorPageErrorHandler errorHandler = new ErrorPageErrorHandler(); context.setErrorHandler(errorHandler); addErrorPages(errorHandler, getErrorPages()); errorHandler.setShowStacks(false); } - private void addErrorPages(ErrorHandler errorHandler, Collection errorPages) { - if (errorHandler instanceof ErrorPageErrorHandler) { - ErrorPageErrorHandler handler = (ErrorPageErrorHandler) errorHandler; - for (ErrorPage errorPage : errorPages) { - if (errorPage.isGlobal()) { - handler.addErrorPage(ErrorPageErrorHandler.GLOBAL_ERROR_PAGE, errorPage.getPath()); + private void addErrorPages(ErrorPageErrorHandler errorHandler, + Collection errorPages) { + for (ErrorPage errorPage : errorPages) { + if (errorPage.isGlobal()) { + errorHandler.addErrorPage(ErrorPageErrorHandler.GLOBAL_ERROR_PAGE, errorPage.getPath()); + } else { + if (errorPage.getExceptionName() != null) { + errorHandler.addErrorPage(errorPage.getExceptionName(), errorPage.getPath()); } else { - if (errorPage.getExceptionName() != null) { - handler.addErrorPage(errorPage.getExceptionName(), errorPage.getPath()); - } else { - handler.addErrorPage(errorPage.getStatusCode(), errorPage.getPath()); - } + errorHandler.addErrorPage(errorPage.getStatusCode(), errorPage.getPath()); } } } } - }; } } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/DefaultWebServerFactory.java b/src/main/java/org/italiangrid/storm/webdav/server/DefaultWebServerFactory.java index 56d286cf..e42ac748 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/DefaultWebServerFactory.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/DefaultWebServerFactory.java @@ -24,7 +24,7 @@ import org.springframework.boot.web.server.WebServerFactoryCustomizer; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.jetty9.InstrumentedQueuedThreadPool; +import io.dropwizard.metrics.jetty12.InstrumentedQueuedThreadPool; public class DefaultWebServerFactory implements WebServerFactoryCustomizer { @@ -45,10 +45,10 @@ public DefaultWebServerFactory(ServiceConfiguration configuration, } private InstrumentedQueuedThreadPool getInstrumentedThreadPool() { - InstrumentedQueuedThreadPool tPool = - new InstrumentedQueuedThreadPool(metricRegistry, configuration.getMaxConnections(), - configuration.getMinConnections(), configuration.getThreadPoolMaxIdleTimeInMsec(), - new ArrayBlockingQueue<>(configuration.getMaxQueueSize()), "storm.http"); + InstrumentedQueuedThreadPool tPool = new InstrumentedQueuedThreadPool(metricRegistry, + configuration.getMaxConnections(), configuration.getMinConnections(), + configuration.getThreadPoolMaxIdleTimeInMsec(), + new ArrayBlockingQueue<>(configuration.getMaxQueueSize()), new ThreadGroup("storm.http")); tPool.setName("thread-pool"); return tPool; } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/TLSServerConnectorBuilder.java b/src/main/java/org/italiangrid/storm/webdav/server/TLSServerConnectorBuilder.java index 5d735f3d..d7d8f011 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/TLSServerConnectorBuilder.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/TLSServerConnectorBuilder.java @@ -45,7 +45,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.jetty9.InstrumentedConnectionFactory; +import io.dropwizard.metrics.jetty12.InstrumentedConnectionFactory; import eu.emi.security.authn.x509.X509CertChainValidatorExt; import eu.emi.security.authn.x509.helpers.ssl.SSLTrustManager; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/ChecksumFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/ChecksumFilter.java index e3b33022..12e3aed1 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/ChecksumFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/ChecksumFilter.java @@ -21,14 +21,14 @@ import java.io.File; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.fs.attrs.ExtendedAttributesHelper; import org.italiangrid.storm.webdav.server.PathResolver; @@ -40,12 +40,11 @@ public class ChecksumFilter implements Filter { private final ExtendedAttributesHelper attributeHelper; private final PathResolver resolver; - + public static final Logger logger = LoggerFactory.getLogger(ChecksumFilter.class); - + @Autowired - public ChecksumFilter(ExtendedAttributesHelper attributeHelper, - PathResolver resolver) { + public ChecksumFilter(ExtendedAttributesHelper attributeHelper, PathResolver resolver) { this.attributeHelper = attributeHelper; this.resolver = resolver; @@ -59,13 +58,13 @@ public void init(FilterConfig filterConfig) throws ServletException { } @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { addChecksumHeader((HttpServletRequest) request, (HttpServletResponse) response); - + chain.doFilter(request, response); - + } @Override @@ -74,41 +73,40 @@ public void destroy() { logger.debug("Destroying checksum filter."); } - - private void addChecksumHeader(HttpServletRequest request, - HttpServletResponse response) { + + private void addChecksumHeader(HttpServletRequest request, HttpServletResponse response) { String method = request.getMethod().toUpperCase(); - + if (!(method.equals("HEAD") || method.equals("GET"))) { - + // Skip if request is not a HEAD or a GET return; } - + logger.debug("Retrieving checksum value ..."); String requestPath = format("%s%s", request.getServletPath(), request.getPathInfo()); String pathResolved = resolver.resolvePath(requestPath); - + if (pathResolved == null) { logger.debug("Unable to resolve path {} to a local file", requestPath); return; } File f = new File(pathResolved); - + if (!f.exists()) { logger.debug("File {} doesn't exist", f); return; - + } if (f.isDirectory()) { logger.debug("{} is a directory: no checksum value to retrieve", f); return; } - + String checksumValue; try { @@ -117,9 +115,9 @@ private void addChecksumHeader(HttpServletRequest request, } catch (IOException e) { - logger.error("Error retrieving checksum value for path '{}': {}", - pathResolved,e.getMessage()); - + logger.error("Error retrieving checksum value for path '{}': {}", pathResolved, + e.getMessage()); + if (logger.isDebugEnabled()) { logger.error(e.getMessage(), e); } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/DeleteSanityChecksFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/DeleteSanityChecksFilter.java index ca449bce..2454bfe9 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/DeleteSanityChecksFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/DeleteSanityChecksFilter.java @@ -17,13 +17,13 @@ import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.server.PathResolver; import org.italiangrid.storm.webdav.tpc.TpcUtils; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/LogRequestFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/LogRequestFilter.java index 1c3b3abd..0d94c1b5 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/LogRequestFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/LogRequestFilter.java @@ -20,14 +20,14 @@ import java.util.Objects; import java.util.Optional; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/MiltonFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/MiltonFilter.java index 813c805a..a05927d2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/MiltonFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/MiltonFilter.java @@ -18,15 +18,15 @@ import java.io.IOException; import java.util.Set; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.fs.FilesystemAccess; import org.italiangrid.storm.webdav.fs.attrs.ExtendedAttributesHelper; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/MoveRequestSanityChecksFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/MoveRequestSanityChecksFilter.java index b28bcc4e..d2689dd7 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/MoveRequestSanityChecksFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/MoveRequestSanityChecksFilter.java @@ -18,13 +18,13 @@ import java.io.IOException; import java.net.MalformedURLException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.error.BadRequest; import org.italiangrid.storm.webdav.error.ResourceNotFound; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/SAIndexServlet.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/SAIndexServlet.java index 8eddbb8d..37f21eb0 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/SAIndexServlet.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/SAIndexServlet.java @@ -21,10 +21,10 @@ import java.util.Map; import java.util.TreeMap; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.config.OAuthProperties; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; @@ -34,11 +34,13 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.WebContext; +import org.thymeleaf.web.IWebExchange; +import org.thymeleaf.web.servlet.JakartaServletWebApplication; public class SAIndexServlet extends HttpServlet { /** - * + * */ private static final long serialVersionUID = -8193945050086639692L; @@ -92,7 +94,11 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) req.setAttribute(STORM_HOSTNAME_KEY, serviceConfig.getHostnames().get(0)); req.setAttribute(OIDC_ENABLED_KEY, oauthProperties.isEnableOidc()); - WebContext ctxt = new WebContext(req, resp, getServletContext(), req.getLocale()); + final IWebExchange webExchange = + JakartaServletWebApplication.buildApplication(this.getServletContext()) + .buildExchange(req, resp); + + WebContext ctxt = new WebContext(webExchange, req.getLocale()); engine.process(SA_INDEX_PAGE_NAME, ctxt, resp.getWriter()); } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/SciTagFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/SciTagFilter.java index f01c0af1..26b0c710 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/SciTagFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/SciTagFilter.java @@ -18,12 +18,12 @@ import java.io.IOException; import java.util.Optional; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.scitag.SciTag; import org.italiangrid.storm.webdav.tpc.TransferConstants; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/StoRMServlet.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/StoRMServlet.java index 68145aa7..ce96edc7 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/StoRMServlet.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/StoRMServlet.java @@ -15,23 +15,35 @@ */ package org.italiangrid.storm.webdav.server.servlet; -import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.util.resource.Resource; +import java.util.Optional; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.ee10.servlet.ResourceServlet; +import org.eclipse.jetty.ee10.servlet.ServletContextRequest; +import org.eclipse.jetty.ee10.servlet.ServletContextResponse; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.http.content.HttpContent; import org.italiangrid.storm.webdav.config.OAuthProperties; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.server.PathResolver; -import org.italiangrid.storm.webdav.server.servlet.resource.StormResourceService; -import org.italiangrid.storm.webdav.server.servlet.resource.StormResourceWrapper; +import org.italiangrid.storm.webdav.server.servlet.resource.StoRMResourceHttpContentFactory; import org.thymeleaf.TemplateEngine; +import org.eclipse.jetty.util.URIUtil; +import org.italiangrid.storm.webdav.scitag.SciTag; +import org.italiangrid.storm.webdav.scitag.SciTagTransfer; -public class StoRMServlet extends DefaultServlet { +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StoRMServlet extends ResourceServlet { + public static final Logger LOG = LoggerFactory.getLogger(StoRMServlet.class); /** * @@ -42,51 +54,109 @@ public class StoRMServlet extends DefaultServlet { final TemplateEngine templateEngine; final ServiceConfigurationProperties serviceConfig; final OAuthProperties oauthProperties; - final StormResourceService resourceService; public StoRMServlet(OAuthProperties oauthP, ServiceConfigurationProperties serviceConfig, - PathResolver resolver, TemplateEngine engine, StormResourceService rs) { - super(rs); + PathResolver resolver, TemplateEngine engine) { + super(); oauthProperties = oauthP; - resourceService = rs; pathResolver = resolver; templateEngine = engine; this.serviceConfig = serviceConfig; } @Override - public Resource getResource(String pathInContext) { - - String resolvedPath = pathResolver.resolvePath(pathInContext); + public void init() throws ServletException { + super.init(); + LOG.warn("accept_range: {}", getInitParameter("acceptRanges")); + this.getResourceService() + .setHttpContentFactory(new StoRMResourceHttpContentFactory(null, MimeTypes.DEFAULTS, + oauthProperties, serviceConfig, pathResolver, templateEngine)); + this.getResourceService().setAcceptRanges(true); + } - if (resolvedPath == null) { + // Copied from + // https://github.com/jetty/jetty.project/blob/jetty-12.0.x/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ResourceServlet.java + private Boolean getInitBoolean(String name) { + String value = getInitParameter(name); + if (value == null || value.isEmpty()) return null; - } + return (value.startsWith("t") || value.startsWith("T") || value.startsWith("y") + || value.startsWith("Y") || value.startsWith("1")); + } - File f = new File(resolvedPath); + private boolean getInitBoolean(String name, boolean dft) { + return Optional.ofNullable(getInitBoolean(name)).orElse(dft); + } - if (!f.exists()) { - return null; + @Override + protected String getEncodedPathInContext(HttpServletRequest request, boolean included) { + String servletPath = null; + String pathInfo = null; + + if (included) { + servletPath = getInitBoolean("pathInfoOnly", false) ? "/" + : (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); + pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); + if (servletPath == null) { + servletPath = request.getServletPath(); + pathInfo = request.getPathInfo(); + } + } else { + servletPath = getInitBoolean("pathInfoOnly", false) ? "/" : request.getServletPath(); + pathInfo = request.getPathInfo(); } - return new StormResourceWrapper(oauthProperties, serviceConfig, templateEngine, - Resource.newResource(f)); - + return URIUtil.addPaths(servletPath, pathInfo); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - resourceService.doGet(request, response); + SciTag scitag = (SciTag) request.getAttribute(SciTag.SCITAG_ATTRIBUTE); + SciTagTransfer scitagTransfer = null; + if (scitag != null) { + scitagTransfer = new SciTagTransfer(scitag, request.getLocalAddr(), request.getLocalPort(), + request.getRemoteAddr(), request.getRemotePort()); + scitagTransfer.writeStart(); + } + ServletContextRequest servletContextRequest = ServletContextRequest.getServletContextRequest(request); + ServletContextResponse servletContextResponse = servletContextRequest.getServletContextResponse(); + super.doGet(request, servletContextResponse.getServletApiResponse()); + if (scitagTransfer != null) { + scitagTransfer.writeEnd(); + } } @Override protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - resourceService.doHead(request, response); + final boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; + final String pathInContext = getEncodedPathInContext(request, included); + + final HttpContent content = + getResourceService().getHttpContentFactory().getContent(pathInContext); + + if (content == null || !content.getResource().exists()) { + + if (included) { + throw new FileNotFoundException("!" + pathInContext); + } + + response.sendError(HttpServletResponse.SC_NOT_FOUND); + response.isCommitted(); + } else { + response.setHeader(HttpHeader.LAST_MODIFIED.asString(), content.getLastModified().getValue()); + if (content.getContentLength() != null) { + response.setHeader(HttpHeader.CONTENT_LENGTH.asString(), + content.getContentLength().getValue()); + } + if (content.getContentType() != null) { + response.setHeader(HttpHeader.CONTENT_TYPE.asString(), content.getContentType().getValue()); + } + response.setHeader(HttpHeader.ACCEPT_RANGES.asString(), "bytes"); + } } - @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StoRMResourceHttpContentFactory.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StoRMResourceHttpContentFactory.java new file mode 100644 index 00000000..a4dbb5ae --- /dev/null +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StoRMResourceHttpContentFactory.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.italiangrid.storm.webdav.server.servlet.resource; + +import java.io.File; +import java.net.URI; + +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.http.content.HttpContent; +import org.eclipse.jetty.http.content.ResourceHttpContent; +import org.eclipse.jetty.http.content.ResourceHttpContentFactory; +import org.eclipse.jetty.util.resource.PathResourceFactory; +import org.eclipse.jetty.util.resource.Resource; +import org.italiangrid.storm.webdav.config.OAuthProperties; +import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; +import org.italiangrid.storm.webdav.server.PathResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.thymeleaf.TemplateEngine; + +public class StoRMResourceHttpContentFactory extends ResourceHttpContentFactory { + public static final Logger LOG = LoggerFactory.getLogger(StoRMResourceHttpContentFactory.class); + final PathResolver pathResolver; + final TemplateEngine templateEngine; + final ServiceConfigurationProperties serviceConfig; + final OAuthProperties oauthProperties; + MimeTypes mimeTypes; + + public StoRMResourceHttpContentFactory(Resource baseResource, MimeTypes mimeTypes, + OAuthProperties oauthP, ServiceConfigurationProperties serviceConfig, PathResolver resolver, + TemplateEngine engine) { + super(baseResource, mimeTypes); + this.mimeTypes = mimeTypes; + pathResolver = resolver; + oauthProperties = oauthP; + templateEngine = engine; + this.serviceConfig = serviceConfig; + } + + @Override + public HttpContent getContent(String pathInContext) { + + String resolvedPath = pathResolver.resolvePath(pathInContext); + LOG.warn("pathInContext: {}, resolvedPath: {}", pathInContext, resolvedPath); + + if (resolvedPath == null) { + return null; + } + + File f = new File(resolvedPath); + + if (!f.exists()) { + LOG.warn("File {} do not exist", resolvedPath); + return null; + } + + PathResourceFactory pathResourceFactory = new PathResourceFactory(); + try { + if (f.isDirectory()) { + StormResourceWrapper resource = + new StormResourceWrapper(oauthProperties, serviceConfig, templateEngine, + pathResourceFactory.newResource(new URI("file:" + resolvedPath)), pathInContext); + return new ResourceHttpContent(resource, "text/html"); + } else { + return new ResourceHttpContent( + pathResourceFactory.newResource(new URI("file:" + resolvedPath)), + mimeTypes.getMimeByExtension(pathInContext)); + } + } catch (Exception e) { + LOG.warn("PathResourceFactory exception: {}", e); + } + + return null; + } +} diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormFsResourceView.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormFsResourceView.java index 2add60c2..98fc35ce 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormFsResourceView.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormFsResourceView.java @@ -33,18 +33,18 @@ public class StormFsResourceView { private StormFsResourceView(Builder b) { if (b.isDirectory && !b.name.endsWith("/")) { - this.name = b.name +"/"; + this.name = b.name + "/"; } else { this.name = b.name; } - + this.isDirectory = b.isDirectory; this.path = b.path; this.sizeInBytes = b.sizeInBytes; this.lastModificationTime = b.lastModificationTime; this.creationTime = b.creationTime; - - + + } public String getName() { @@ -80,6 +80,7 @@ public Date getCreationTime() { public static Builder builder() { return new Builder(); } + public static class Builder { String name; boolean isDirectory; diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceService.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceService.java deleted file mode 100644 index aa606090..00000000 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceService.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.italiangrid.storm.webdav.server.servlet.resource; - -import java.io.FileNotFoundException; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.RequestDispatcher; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.http.HttpContent; -import org.eclipse.jetty.server.ResourceService; -import org.eclipse.jetty.util.URIUtil; -import org.italiangrid.storm.webdav.scitag.SciTag; -import org.italiangrid.storm.webdav.scitag.SciTagTransfer; - -public class StormResourceService extends ResourceService { - - private String pathInContext(HttpServletRequest request) { - String servletPath = null; - String pathInfo = null; - - boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; - - if (included) { - servletPath = isPathInfoOnly() ? "/" - : (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); - pathInfo = (String) request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); - if (servletPath == null) { - servletPath = request.getServletPath(); - pathInfo = request.getPathInfo(); - } - } else { - servletPath = isPathInfoOnly() ? "/" : request.getServletPath(); - pathInfo = request.getPathInfo(); - } - - return URIUtil.addPaths(servletPath, pathInfo); - } - - @Override - public boolean doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - SciTag scitag = (SciTag) request.getAttribute(SciTag.SCITAG_ATTRIBUTE); - SciTagTransfer scitagTransfer = null; - if (scitag != null) { - scitagTransfer = new SciTagTransfer(scitag, request.getLocalAddr(), request.getLocalPort(), - request.getRemoteAddr(), request.getRemotePort()); - scitagTransfer.writeStart(); - } - boolean result = super.doGet(request, response); - if (scitagTransfer != null) { - scitagTransfer.writeEnd(); - } - return result; - } - - public boolean doHead(HttpServletRequest request, HttpServletResponse response) - throws IOException { - - final boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; - final String pathInContext = pathInContext(request); - - final HttpContent content = - getContentFactory().getContent(pathInContext, response.getBufferSize()); - - if (content == null || !content.getResource().exists()) { - - if (included) { - throw new FileNotFoundException("!" + pathInContext); - } - - response.sendError(HttpServletResponse.SC_NOT_FOUND); - return response.isCommitted(); - } - - putHeaders(response, content, content.getContentLengthValue()); - return true; - } - -} diff --git a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceWrapper.java b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceWrapper.java index 73a030e9..0448d24d 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceWrapper.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/servlet/resource/StormResourceWrapper.java @@ -15,15 +15,15 @@ */ package org.italiangrid.storm.webdav.server.servlet.resource; -import java.io.File; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.time.Instant; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -45,81 +45,23 @@ public class StormResourceWrapper extends Resource { final TemplateEngine engine; final OAuthProperties oauthProperties; final ServiceConfigurationProperties serviceConfig; + final String pathInContext; public StormResourceWrapper(OAuthProperties oauth, ServiceConfigurationProperties serviceConfig, - TemplateEngine engine, Resource delegate) { + TemplateEngine engine, Resource delegate, String pathInContext) { this.oauthProperties = oauth; this.engine = engine; this.delegate = delegate; this.serviceConfig = serviceConfig; + this.pathInContext = pathInContext; } - /** - * Encode any characters that could break the URI string in an HREF. Such as ">Link - * - * The above example would parse incorrectly on various browsers as the "<" or '"' characters - * would end the href attribute value string prematurely. - * - * @param raw the raw text to encode. - * @return the defanged text. - */ - private static String hrefEncodeURI(String raw) { - - StringBuffer buf = null; - - loop: for (int i = 0; i < raw.length(); i++) { - char c = raw.charAt(i); - switch (c) { - case '\'': - case '"': - case '<': - case '>': - buf = new StringBuffer(raw.length() << 1); - break loop; - } - } - if (buf == null) - return raw; - - for (int i = 0; i < raw.length(); i++) { - char c = raw.charAt(i); - switch (c) { - case '"': - buf.append("%22"); - continue; - case '\'': - buf.append("%27"); - continue; - case '<': - buf.append("%3C"); - continue; - case '>': - buf.append("%3E"); - continue; - default: - buf.append(c); - continue; - } - } - - return buf.toString(); - } - - - @Override - public String getListHTML(String base, boolean parent, String query) throws IOException { - + public String getListHTML(String base) throws IOException { base = URIUtil.canonicalPath(base); - if (base == null || !isDirectory()) - return null; - String[] rawListing = list(); - if (rawListing == null) { - return null; - } + List rawListing = list(); Context context = new Context(); @@ -135,21 +77,20 @@ public String getListHTML(String base, boolean parent, String query) throws IOEx context.setVariable("oidcEnabled", oauthProperties.isEnableOidc()); - String encodedBase = hrefEncodeURI(decodedBase); + String encodedBase = decodedBase;// hrefEncodeURI(decodedBase); String parentDir = URIUtil.addPaths(encodedBase, "../"); - Arrays.sort(rawListing); + Collections.sort(rawListing, (a, b) -> a.getFileName().compareTo(b.getFileName())); List resources = new ArrayList<>(); - for (String l : rawListing) { - Resource r = addPath(l); + for (Resource r : rawListing) { resources.add(StormFsResourceView.builder() - .withName(l) - .withPath(URIUtil.addEncodedPaths(encodedBase, URIUtil.encodePath(l))) + .withName(r.getFileName()) + .withPath(URIUtil.addEncodedPaths(encodedBase, r.getFileName())) .withIsDirectory(r.isDirectory()) - .withLastModificationTime(new Date(r.lastModified())) + .withLastModificationTime(Date.from(r.lastModified())) .withSizeInBytes(r.length()) .build()); } @@ -160,18 +101,6 @@ public String getListHTML(String base, boolean parent, String query) throws IOEx return engine.process(JETTY_DIR_TEMPLATE, context); } - @Override - public boolean isContainedIn(Resource r) throws MalformedURLException { - - return delegate.isContainedIn(r); - } - - @Override - public void close() { - - delegate.close(); - } - @Override public boolean exists() { return delegate.exists(); @@ -179,11 +108,17 @@ public boolean exists() { @Override public boolean isDirectory() { - return delegate.isDirectory(); + // We must lie otherwise Jetty uses its non-overridable directory listing + return false; + } + + @Override + public boolean isReadable() { + return delegate.isReadable(); } @Override - public long lastModified() { + public Instant lastModified() { return delegate.lastModified(); } @@ -192,15 +127,14 @@ public long length() { return delegate.length(); } - @SuppressWarnings("deprecation") @Override - public URL getURL() { - return delegate.getURL(); + public URI getURI() { + return delegate.getURI(); } @Override - public File getFile() throws IOException { - return delegate.getFile(); + public String getFileName() { + return delegate.getFileName(); } @Override @@ -209,85 +143,23 @@ public String getName() { } @Override - public InputStream getInputStream() throws IOException { - return delegate.getInputStream(); + public Path getPath() { + // We must lie so Jetty uses our overrided newInputStream + return null; } @Override - public ReadableByteChannel getReadableByteChannel() throws IOException { - return delegate.getReadableByteChannel(); + public InputStream newInputStream() throws IOException { + return new ByteArrayInputStream(getListHTML(pathInContext).getBytes(StandardCharsets.UTF_8)); } @Override - public boolean delete() throws SecurityException { - return delegate.delete(); - } - - @Override - public boolean renameTo(Resource dest) throws SecurityException { - return delegate.renameTo(dest); - } - - @Override - public String[] list() { + public List list() { return delegate.list(); } @Override - public Resource addPath(String path) throws IOException { - return delegate.addPath(path); + public Resource resolve(String subUriPath) { + return delegate.resolve(subUriPath); } - - @Override - public void writeTo(OutputStream out, long start, long count) throws IOException { - - try (InputStream in = getInputStream()) { - if (start > 0) { - long n = in.skip(start); - if (n < start) { - throw new IOException("Skipped " + start + " bytes but read " + n); - } - } - if (count < 0) { - internalCopy(in, out); - } else { - internalCopy(in, out, count); - } - } - - } - - private void internalCopy(InputStream in, OutputStream out, long byteCount) throws IOException { - - int bufferSize = serviceConfig.getBuffer().getFileBufferSizeBytes(); - byte[] buffer = new byte[bufferSize]; - int len = bufferSize; - - if (byteCount >= 0) { - while (byteCount > 0) { - int max = byteCount < bufferSize ? (int) byteCount : bufferSize; - len = in.read(buffer, 0, max); - - if (len == -1) - break; - - byteCount -= len; - out.write(buffer, 0, len); - } - } else { - while (true) { - len = in.read(buffer, 0, bufferSize); - if (len < 0) - break; - out.write(buffer, 0, len); - } - } - - } - - private void internalCopy(InputStream in, OutputStream out) throws IOException { - internalCopy(in, out, -1); - } - - } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/tracing/LogbackAccessAuthnInfoFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/tracing/LogbackAccessAuthnInfoFilter.java index 4e62dc3f..af101132 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/tracing/LogbackAccessAuthnInfoFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/tracing/LogbackAccessAuthnInfoFilter.java @@ -17,12 +17,12 @@ import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authn.PrincipalHelper; import org.springframework.security.core.Authentication; @@ -37,6 +37,7 @@ public class LogbackAccessAuthnInfoFilter implements Filter { public LogbackAccessAuthnInfoFilter(PrincipalHelper principalHelper) { this.helper = principalHelper; } + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { diff --git a/src/main/java/org/italiangrid/storm/webdav/server/tracing/RequestIdFilter.java b/src/main/java/org/italiangrid/storm/webdav/server/tracing/RequestIdFilter.java index 023ea6a1..87411f83 100644 --- a/src/main/java/org/italiangrid/storm/webdav/server/tracing/RequestIdFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/server/tracing/RequestIdFilter.java @@ -17,11 +17,11 @@ import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import org.slf4j.MDC; @@ -32,11 +32,11 @@ public class RequestIdFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - + RequestIdHolder.setRandomId(); request.setAttribute(REQUEST_ID_ATTRIBUTE_NAME, RequestIdHolder.getRequestId()); MDC.put(REQUEST_ID_ATTRIBUTE_NAME, RequestIdHolder.getRequestId()); - + try { chain.doFilter(request, response); } finally { @@ -44,6 +44,6 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha MDC.clear(); } } - + } diff --git a/src/main/java/org/italiangrid/storm/webdav/server/util/JettyErrorPageHandler.java b/src/main/java/org/italiangrid/storm/webdav/server/util/JettyErrorPageHandler.java deleted file mode 100644 index 8e71a188..00000000 --- a/src/main/java/org/italiangrid/storm/webdav/server/util/JettyErrorPageHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.italiangrid.storm.webdav.server.util; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.servlet.ErrorPageErrorHandler; - -public class JettyErrorPageHandler extends ErrorPageErrorHandler { - - private static final Set HANDLED_HTTP_METHODS = - new HashSet<>(Arrays.asList("GET", "POST", "HEAD")); - - @Override - public boolean errorPageForMethod(String method) { - return true; - } - - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException { - if (!HANDLED_HTTP_METHODS.contains(baseRequest.getMethod())) { - baseRequest.setMethod("GET"); - } - super.doError(target, baseRequest, request, response); - } - -} diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/AppConfig.java b/src/main/java/org/italiangrid/storm/webdav/spring/AppConfig.java index 08b344a8..d20f1a1b 100644 --- a/src/main/java/org/italiangrid/storm/webdav/spring/AppConfig.java +++ b/src/main/java/org/italiangrid/storm/webdav/spring/AppConfig.java @@ -26,6 +26,8 @@ import java.security.Security; import java.security.cert.CertificateException; import java.time.Clock; +import java.time.Duration; +import java.util.HashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -37,16 +39,29 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.config.ConnectionConfig; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.http.io.HttpConnectionFactory; +import org.apache.hc.core5.util.Timeout; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.io.ManagedHttpClientConnection; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory; +import org.apache.hc.client5.http.impl.ChainElement; +import org.apache.hc.client5.http.impl.DefaultRedirectStrategy; +import org.apache.hc.client5.http.impl.DefaultSchemePortResolver; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner; import org.conscrypt.OpenSSLProvider; import org.italiangrid.storm.webdav.authn.PrincipalHelper; import org.italiangrid.storm.webdav.authz.AuthorizationPolicyService; @@ -92,7 +107,6 @@ import org.italiangrid.storm.webdav.tpc.TpcPlainConnectionSocketFactory; import org.italiangrid.storm.webdav.tpc.TpcSSLConnectionSocketFactory; import org.italiangrid.storm.webdav.tpc.TransferConstants; -import org.italiangrid.storm.webdav.tpc.http.SuperLaxRedirectStrategy; import org.italiangrid.voms.util.CertificateValidatorBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,6 +121,9 @@ import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; +import org.springframework.session.MapSession; +import org.springframework.session.MapSessionRepository; +import org.springframework.session.SessionRepository; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.health.HealthCheckRegistry; @@ -129,6 +146,8 @@ public class AppConfig { public static final Logger LOG = LoggerFactory.getLogger(AppConfig.class); + public static final String AUTHORIZATION_HEADER = "Authorization"; + @Bean Clock systemClock() { return Clock.systemDefaultZone(); @@ -239,6 +258,17 @@ ScheduledExecutorService tpcProgressReportEs(ThirdPartyCopyProperties props) { HttpClientConnectionManager tpcClientConnectionManager(ThirdPartyCopyProperties props, ServiceConfiguration conf) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException { + + Http1Config customHttpConfig = + Http1Config.custom().setBufferSize(props.getHttpClientSocketBufferSize()).build(); + HttpConnectionFactory connectionFactory = + ManagedHttpClientConnectionFactory.builder().http1Config(customHttpConfig).build(); + + ConnectionConfig connectionConfig = ConnectionConfig.custom() + .setSocketTimeout(props.getTimeoutInSecs(), TimeUnit.SECONDS) + .setConnectTimeout(props.getTimeoutInSecs(), TimeUnit.SECONDS) + .build(); + PEMCredential serviceCredential = serviceCredential(conf); SSLTrustManager tm = new SSLTrustManager(canlCertChainValidator(conf)); @@ -272,9 +302,11 @@ HttpClientConnectionManager tpcClientConnectionManager(ThirdPartyCopyProperties .register(TransferConstants.DAVS, tlsSf) .build(); - PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r); - cm.setMaxTotal(props.getMaxConnections()); + PoolingHttpClientConnectionManager cm = + new PoolingHttpClientConnectionManager(r, connectionFactory); + cm.setDefaultConnectionConfig(connectionConfig); cm.setDefaultMaxPerRoute(props.getMaxConnectionsPerRoute()); + cm.setMaxTotal(props.getMaxConnections()); return cm; } @@ -282,29 +314,25 @@ HttpClientConnectionManager tpcClientConnectionManager(ThirdPartyCopyProperties CloseableHttpClient transferClient(ThirdPartyCopyProperties props, @Qualifier("tpcConnectionManager") HttpClientConnectionManager cm) { - ConnectionConfig connectionConfig = - ConnectionConfig.custom().setBufferSize(props.getHttpClientSocketBufferSize()).build(); - - int timeoutMsec = (int) TimeUnit.SECONDS.toMillis(props.getTimeoutInSecs()); RequestConfig config = RequestConfig.custom() .setExpectContinueEnabled(false) - .setConnectTimeout(timeoutMsec) - .setConnectionRequestTimeout(timeoutMsec) - .setSocketTimeout(timeoutMsec) + .setConnectionRequestTimeout(props.getTimeoutInSecs(), TimeUnit.SECONDS) .build(); return HttpClients.custom() .setConnectionManager(cm) - .setDefaultConnectionConfig(connectionConfig) + .disableRedirectHandling() + .addExecInterceptorFirst("RemoveAuthorizationHeader", + new RedirectExec(new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE), + DefaultRedirectStrategy.INSTANCE)) .setDefaultRequestConfig(config) - .setRedirectStrategy(SuperLaxRedirectStrategy.INSTANCE) .build(); } @Bean @ConditionalOnProperty(name = "oauth.enable-oidc", havingValue = "true") - ClientRegistrationRepository clientRegistrationRepository( - OAuth2ClientProperties clientProperties, OAuthProperties props, ExecutorService executor) { + ClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties clientProperties, + OAuthProperties props, ExecutorService executor) { ClientRegistrationCacheLoader loader = @@ -443,6 +471,13 @@ PrincipalHelper principalHelper(ServiceConfigurationProperties config) throws MalformedURLException { return new PrincipalHelper(config); } + + @Bean + @ConditionalOnProperty(name = "spring.session.store-type", havingValue = "none") + public SessionRepository sessionRepository() { + return new MapSessionRepository(new HashMap<>()); + } + } diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/RedirectExec.java b/src/main/java/org/italiangrid/storm/webdav/spring/RedirectExec.java new file mode 100644 index 00000000..12b4306e --- /dev/null +++ b/src/main/java/org/italiangrid/storm/webdav/spring/RedirectExec.java @@ -0,0 +1,230 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.italiangrid.storm.webdav.spring; + +import java.io.IOException; +import java.net.URI; +import java.util.Objects; + +import org.apache.hc.client5.http.CircularRedirectException; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.RedirectException; +import org.apache.hc.client5.http.auth.AuthExchange; +import org.apache.hc.client5.http.classic.ExecChain; +import org.apache.hc.client5.http.classic.ExecChainHandler; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.http.protocol.RedirectLocations; +import org.apache.hc.client5.http.protocol.RedirectStrategy; +import org.apache.hc.client5.http.routing.HttpRoutePlanner; +import org.apache.hc.client5.http.utils.URIUtils; +import org.apache.hc.core5.annotation.Contract; +import org.apache.hc.core5.annotation.ThreadingBehavior; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.Method; +import org.apache.hc.core5.http.ProtocolException; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.apache.hc.core5.util.Args; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Request execution handler in the classic request execution chain + * responsible for handling of request redirects. + *

+ * Further responsibilities such as communication with the opposite + * endpoint is delegated to the next executor in the request execution + * chain. + *

+ * + * @since 4.3 + */ +// Copied from https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/RedirectExec.java +// Added the drop of Authorization header +@Contract(threading = ThreadingBehavior.STATELESS) +public final class RedirectExec implements ExecChainHandler { + + private static final Logger LOG = LoggerFactory.getLogger(RedirectExec.class); + + private final RedirectStrategy redirectStrategy; + private final HttpRoutePlanner routePlanner; + + public RedirectExec( + final HttpRoutePlanner routePlanner, + final RedirectStrategy redirectStrategy) { + super(); + Args.notNull(routePlanner, "HTTP route planner"); + Args.notNull(redirectStrategy, "HTTP redirect strategy"); + this.routePlanner = routePlanner; + this.redirectStrategy = redirectStrategy; + } + + @Override + public ClassicHttpResponse execute( + final ClassicHttpRequest request, + final ExecChain.Scope scope, + final ExecChain chain) throws IOException, HttpException { + Args.notNull(request, "HTTP request"); + Args.notNull(scope, "Scope"); + + final HttpClientContext context = scope.clientContext; + context.setRedirectLocations(null); + + final RequestConfig config = context.getRequestConfigOrDefault(); + final int maxRedirects = config.getMaxRedirects() > 0 ? config.getMaxRedirects() : 50; + ClassicHttpRequest currentRequest = request; + ExecChain.Scope currentScope = scope; + for (int redirectCount = 0;;) { + final String exchangeId = currentScope.exchangeId; + final ClassicHttpResponse response = chain.proceed(currentRequest, currentScope); + try { + if (config.isRedirectsEnabled() && this.redirectStrategy.isRedirected(request, response, context)) { + final HttpEntity requestEntity = request.getEntity(); + // This is the only modification + scope.originalRequest.removeHeaders("Authorization"); + if (requestEntity != null && !requestEntity.isRepeatable()) { + if (LOG.isDebugEnabled()) { + LOG.debug("{} cannot redirect non-repeatable request", exchangeId); + } + return response; + } + if (redirectCount >= maxRedirects) { + throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded"); + } + redirectCount++; + + final URI redirectUri = this.redirectStrategy.getLocationURI(currentRequest, response, context); + if (LOG.isDebugEnabled()) { + LOG.debug("{} redirect requested to location '{}'", exchangeId, redirectUri); + } + + final HttpHost newTarget = URIUtils.extractHost(redirectUri); + if (newTarget == null) { + throw new ProtocolException("Redirect URI does not specify a valid host name: " + + redirectUri); + } + + final RedirectLocations redirectLocations = context.getRedirectLocations(); + if (!config.isCircularRedirectsAllowed()) { + if (redirectLocations.contains(redirectUri)) { + throw new CircularRedirectException("Circular redirect to '" + redirectUri + "'"); + } + } + redirectLocations.add(redirectUri); + + final int statusCode = response.getCode(); + final ClassicRequestBuilder redirectBuilder; + switch (statusCode) { + case HttpStatus.SC_MOVED_PERMANENTLY: + case HttpStatus.SC_MOVED_TEMPORARILY: + if (Method.POST.isSame(request.getMethod())) { + redirectBuilder = ClassicRequestBuilder.get(); + } else { + redirectBuilder = ClassicRequestBuilder.copy(currentScope.originalRequest); + } + break; + case HttpStatus.SC_SEE_OTHER: + if (!Method.GET.isSame(request.getMethod()) && !Method.HEAD.isSame(request.getMethod())) { + redirectBuilder = ClassicRequestBuilder.get(); + } else { + redirectBuilder = ClassicRequestBuilder.copy(currentScope.originalRequest); + } + break; + default: + redirectBuilder = ClassicRequestBuilder.copy(currentScope.originalRequest); + } + redirectBuilder.setUri(redirectUri); + + HttpRoute currentRoute = currentScope.route; + if (!Objects.equals(currentRoute.getTargetHost(), newTarget)) { + final HttpRoute newRoute = this.routePlanner.determineRoute(newTarget, context); + if (!Objects.equals(currentRoute, newRoute)) { + if (LOG.isDebugEnabled()) { + LOG.debug("{} new route required", exchangeId); + } + final AuthExchange targetAuthExchange = context.getAuthExchange(currentRoute.getTargetHost()); + if (LOG.isDebugEnabled()) { + LOG.debug("{} resetting target auth state", exchangeId); + } + targetAuthExchange.reset(); + if (currentRoute.getProxyHost() != null) { + final AuthExchange proxyAuthExchange = context.getAuthExchange(currentRoute.getProxyHost()); + if (proxyAuthExchange.isConnectionBased()) { + if (LOG.isDebugEnabled()) { + LOG.debug("{} resetting proxy auth state", exchangeId); + } + proxyAuthExchange.reset(); + } + } + currentRoute = newRoute; + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("{} redirecting to '{}' via {}", exchangeId, redirectUri, currentRoute); + } + currentScope = new ExecChain.Scope( + scope.exchangeId, + currentRoute, + redirectBuilder.build(), + scope.execRuntime, + scope.clientContext); + currentRequest = redirectBuilder.build(); + + EntityUtils.consume(response.getEntity()); + response.close(); + } else { + return response; + } + } catch (final RuntimeException | IOException ex) { + response.close(); + throw ex; + } catch (final HttpException ex) { + // Protocol exception related to a direct. + // The underlying connection may still be salvaged. + try { + EntityUtils.consume(response.getEntity()); + } catch (final IOException ioex) { + if (LOG.isDebugEnabled()) { + LOG.debug("{} I/O error while releasing connection", exchangeId, ioex); + } + } finally { + response.close(); + } + throw ex; + } + } + } + +} diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/AppContextLoaderListener.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/AppContextLoaderListener.java index 1f39b68b..bcc4d36f 100644 --- a/src/main/java/org/italiangrid/storm/webdav/spring/web/AppContextLoaderListener.java +++ b/src/main/java/org/italiangrid/storm/webdav/spring/web/AppContextLoaderListener.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.spring.web; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; import org.springframework.context.ApplicationContext; import org.springframework.web.context.ContextLoaderListener; diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/HttpMethodRequestRejectedHandler.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/HttpMethodRequestRejectedHandler.java index 76f65842..62098bd2 100644 --- a/src/main/java/org/italiangrid/storm/webdav/spring/web/HttpMethodRequestRejectedHandler.java +++ b/src/main/java/org/italiangrid/storm/webdav/spring/web/HttpMethodRequestRejectedHandler.java @@ -18,9 +18,9 @@ import java.io.IOException; import java.util.List; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/MvcConfig.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/MvcConfig.java index 57288094..e79fbd43 100644 --- a/src/main/java/org/italiangrid/storm/webdav/spring/web/MvcConfig.java +++ b/src/main/java/org/italiangrid/storm/webdav/spring/web/MvcConfig.java @@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -31,16 +32,21 @@ @Configuration public class MvcConfig implements WebMvcConfigurer { - + @Autowired ServiceConfigurationProperties properties; - + @Autowired OAuthProperties oauthProperties; @Autowired StorageAreaConfiguration saConfig; - + + @Override + public void configurePathMatch(PathMatchConfigurer configurer) { + configurer.setUseTrailingSlashMatch(true); + } + @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ViewUtilsInterceptor(properties, saConfig, oauthProperties)); diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/ServletConfiguration.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/ServletConfiguration.java index 23ce8b49..fb01e534 100644 --- a/src/main/java/org/italiangrid/storm/webdav/spring/web/ServletConfiguration.java +++ b/src/main/java/org/italiangrid/storm/webdav/spring/web/ServletConfiguration.java @@ -41,7 +41,6 @@ import org.italiangrid.storm.webdav.server.servlet.SAIndexServlet; import org.italiangrid.storm.webdav.server.servlet.SciTagFilter; import org.italiangrid.storm.webdav.server.servlet.StoRMServlet; -import org.italiangrid.storm.webdav.server.servlet.resource.StormResourceService; import org.italiangrid.storm.webdav.server.tracing.LogbackAccessAuthnInfoFilter; import org.italiangrid.storm.webdav.server.tracing.RequestIdFilter; import org.italiangrid.storm.webdav.tpc.LocalURLService; @@ -59,7 +58,7 @@ import org.thymeleaf.TemplateEngine; import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.servlets.MetricsServlet; +import io.dropwizard.metrics.servlets.MetricsServlet; import com.fasterxml.jackson.databind.ObjectMapper; @@ -233,14 +232,12 @@ ServletRegistrationBean stormServlet(OAuthProperties oauthProperti ServiceConfigurationProperties serviceConfig, StorageAreaConfiguration saConfig, PathResolver pathResolver, TemplateEngine templateEngine) { - ServletRegistrationBean stormServlet = - new ServletRegistrationBean<>(new StoRMServlet(oauthProperties, serviceConfig, pathResolver, - templateEngine, new StormResourceService())); + ServletRegistrationBean stormServlet = new ServletRegistrationBean<>( + new StoRMServlet(oauthProperties, serviceConfig, pathResolver, templateEngine)); stormServlet.addInitParameter("acceptRanges", "true"); stormServlet.addInitParameter("dirAllowed", "true"); - stormServlet.addInitParameter("aliases", "false"); - stormServlet.addInitParameter("gzip", "false"); + stormServlet.addInitParameter("precompressed", "false"); saConfig.getStorageAreaInfo() diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcPlainConnectionSocketFactory.java b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcPlainConnectionSocketFactory.java index 04289a9d..2ba595b5 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcPlainConnectionSocketFactory.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcPlainConnectionSocketFactory.java @@ -18,9 +18,10 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; -import org.apache.http.HttpHost; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.protocol.HttpContext; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.util.TimeValue; import org.italiangrid.storm.webdav.scitag.SciTag; import org.italiangrid.storm.webdav.scitag.SciTagTransfer; @@ -38,7 +39,7 @@ public TpcPlainConnectionSocketFactory() { } @Override - public Socket connectSocket(int connectTimeout, Socket socket, HttpHost host, + public Socket connectSocket(TimeValue connectTimeout, Socket socket, HttpHost host, InetSocketAddress remoteAddress, InetSocketAddress localAddress, HttpContext context) throws IOException { Socket s = diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcSSLConnectionSocketFactory.java b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcSSLConnectionSocketFactory.java index d7660cb6..d062fc51 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcSSLConnectionSocketFactory.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcSSLConnectionSocketFactory.java @@ -18,8 +18,8 @@ import java.io.IOException; import java.net.Socket; import javax.net.ssl.SSLContext; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.protocol.HttpContext; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.protocol.HttpContext; import org.italiangrid.storm.webdav.scitag.SciTag; import org.italiangrid.storm.webdav.scitag.SciTagTransfer; diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcUtils.java b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcUtils.java index 5e7a1ec0..ff5445dd 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/TpcUtils.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/TpcUtils.java @@ -24,7 +24,7 @@ import java.util.function.Supplier; import java.util.regex.Matcher; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.config.StorageAreaInfo; import org.italiangrid.storm.webdav.error.ResourceNotFound; @@ -106,8 +106,9 @@ default boolean isCopy(HttpServletRequest request) { } default boolean isPushTpc(HttpServletRequest request, LocalURLService localUrlService) { - return "COPY".equals(request.getMethod()) && (requestHasRemoteDestinationHeader(request, localUrlService) - || requestHasTranferHeader(request)); + return "COPY".equals(request.getMethod()) + && (requestHasRemoteDestinationHeader(request, localUrlService) + || requestHasTranferHeader(request)); } default boolean requestHasTranferHeader(HttpServletRequest request) { diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilter.java b/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilter.java index c40d2a56..47d351ad 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilter.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilter.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.tpc; -import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED; +import static jakarta.servlet.http.HttpServletResponse.SC_ACCEPTED; import java.io.IOException; import java.net.MalformedURLException; @@ -23,17 +23,17 @@ import java.time.Clock; import java.util.Optional; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.io.FileUtils; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpResponseException; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.HttpResponseException; import org.italiangrid.storm.webdav.error.BadRequest; import org.italiangrid.storm.webdav.error.ResourceNotFound; import org.italiangrid.storm.webdav.scitag.SciTag; @@ -183,11 +183,8 @@ protected void logTransferDone(GetTransferRequest req) { if (TransferStatus.Status.DONE.equals(lastStatus.getStatus())) { LOG.info( "Pull third-party transfer completed: {}. Source: {}, Destination: {}, Bytes transferred: {}, Duration (msec): {}, Throughput: {}/sec, id: {}", - lastStatus, req.remoteURI(), req.path(), - req.bytesTransferred(), - req.duration().toMillis(), - getUserFriendlyThroughputString(req), - req.uuid()); + lastStatus, req.remoteURI(), req.path(), req.bytesTransferred(), + req.duration().toMillis(), getUserFriendlyThroughputString(req), req.uuid()); } else { LOG.warn("Pull third-party transfer completed: {}. Source: {}, Destination: {}", lastStatus, req.remoteURI(), req.path()); @@ -200,9 +197,8 @@ protected void logTransferDone(PutTransferRequest req) { LOG.info( "Push third-party transfer completed: {}. Source: {}, Destination: {}, Bytes transferred: {}, Duration (msec): {}, Throughput: {}/sec, id: {}", - req.lastTransferStatus().get(), req.path(), req.remoteURI(), - req.bytesTransferred(), req.duration().toMillis(), getUserFriendlyThroughputString(req), - req.uuid()); + req.lastTransferStatus().get(), req.path(), req.remoteURI(), req.bytesTransferred(), + req.duration().toMillis(), getUserFriendlyThroughputString(req), req.uuid()); } } diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilterSupport.java b/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilterSupport.java index ad0b487d..29e23bea 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilterSupport.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/TransferFilterSupport.java @@ -16,7 +16,7 @@ package org.italiangrid.storm.webdav.tpc; import static java.lang.String.format; -import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; +import static jakarta.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; import static org.springframework.http.HttpStatus.BAD_REQUEST; import java.io.IOException; @@ -28,11 +28,11 @@ import java.util.Enumeration; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpResponseException; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.HttpResponseException; import org.italiangrid.storm.webdav.scitag.SciTag; import org.italiangrid.storm.webdav.server.PathResolver; import org.italiangrid.storm.webdav.tpc.transfer.TransferRequest; @@ -99,9 +99,9 @@ protected Multimap getTransferHeaders(HttpServletRequest request } } - if (isPushTpc(request, localURLService) && request.getContentLength() >= enableExpectContinueThreshold) { - xferHeaders.put(org.apache.http.protocol.HTTP.EXPECT_DIRECTIVE, - org.apache.http.protocol.HTTP.EXPECT_CONTINUE); + if (isPushTpc(request, localURLService) + && request.getContentLength() >= enableExpectContinueThreshold) { + xferHeaders.put("Expect", "100-continue"); } return xferHeaders; diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/GetResponseHandler.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/GetResponseHandler.java index 98b16e66..24008134 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/GetResponseHandler.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/http/GetResponseHandler.java @@ -21,10 +21,10 @@ import java.util.Collections; import java.util.Map; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.util.EntityUtils; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.italiangrid.storm.webdav.checksum.Adler32ChecksumOutputStream; import org.italiangrid.storm.webdav.fs.attrs.ExtendedAttributesHelper; import org.italiangrid.storm.webdav.tpc.transfer.GetTransferRequest; @@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory; public class GetResponseHandler extends ResponseHandlerSupport - implements org.apache.http.client.ResponseHandler { + implements HttpClientResponseHandler { public static final int DEFAULT_BUFFER_SIZE = 4096; @@ -83,15 +83,14 @@ private void writeEntityToStream(HttpEntity entity, OutputStream os) @Override - public Boolean handleResponse(HttpResponse response) throws IOException { + public Boolean handleResponse(ClassicHttpResponse response) throws IOException { setupMDC(); LOG.debug("Response: {}", response); - StatusLine sl = response.getStatusLine(); HttpEntity entity = response.getEntity(); - checkResponseStatus(sl); + checkResponseStatus(response); Adler32ChecksumOutputStream checkedStream = null; diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClient.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClient.java index a4f77887..73cdfa53 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClient.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClient.java @@ -32,15 +32,16 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.http.HttpEntity; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpResponseException; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.Method; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.HttpResponseException; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.config.ThirdPartyCopyProperties; import org.italiangrid.storm.webdav.fs.attrs.ExtendedAttributesHelper; @@ -105,10 +106,10 @@ public void destroy() throws Exception { executorService.shutdownNow(); } - HttpGet prepareRequest(GetTransferRequest request) { + BasicClassicHttpRequest prepareRequest(GetTransferRequest request) { request.setTransferStatus(TransferStatus.builder(clock).inProgress(0)); - HttpGet get = new HttpGet(request.remoteURI()); + BasicClassicHttpRequest get = new BasicClassicHttpRequest(Method.GET, request.remoteURI()); for (Map.Entry h : request.transferHeaders().entries()) { get.addHeader(h.getKey(), h.getValue()); @@ -116,11 +117,11 @@ HttpGet prepareRequest(GetTransferRequest request) { return get; } - HttpPut prepareRequest(PutTransferRequest request, HttpEntity cfe) { + BasicClassicHttpRequest prepareRequest(PutTransferRequest request, HttpEntity cfe) { request.setTransferStatus(TransferStatus.builder(clock).inProgress(0)); - HttpPut put = new HttpPut(request.remoteURI()); + BasicClassicHttpRequest put = new BasicClassicHttpRequest(Method.PUT, request.remoteURI()); for (Map.Entry h : request.transferHeaders().entries()) { put.addHeader(h.getKey(), h.getValue()); @@ -167,7 +168,7 @@ StormCountingOutputStream prepareOutputStream(String path) { public void handle(GetTransferRequest request, TransferStatusCallback cb) { StormCountingOutputStream os = prepareOutputStream(resolver.resolvePath(request.path())); - HttpGet get = prepareRequest(request); + BasicClassicHttpRequest get = prepareRequest(request); HttpClientContext context = HttpClientContext.create(); ScheduledFuture reportTask = executorService.scheduleAtFixedRate( @@ -177,8 +178,8 @@ public void handle(GetTransferRequest request, TransferStatusCallback cb) { try { context.setAttribute(SciTag.SCITAG_ATTRIBUTE, request.scitag()); - httpClient.execute(get, new GetResponseHandler(request, os, attributesHelper, - MDC.getCopyOfContextMap(), socketBufferSize, true), context); + httpClient.execute(get, context, new GetResponseHandler(request, os, attributesHelper, + MDC.getCopyOfContextMap(), socketBufferSize, true)); reportTask.cancel(true); reportStatus(cb, request, statusBuilder.done(os.getCount())); @@ -215,13 +216,15 @@ protected void checkOverwrite(PutTransferRequest request) throws IOException { for (Map.Entry h : request.transferHeaders().entries()) { head.addHeader(h.getKey(), h.getValue()); } - CloseableHttpResponse response = httpClient.execute(head); - if (response.getStatusLine().getStatusCode() == 200) { - throw new TransferError("Remote file exists and overwrite is false"); - } else if (response.getStatusLine().getStatusCode() != 404) { - throw new TransferError(format("Error checking if remote file exists: %d %s", - response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase())); - } + httpClient.execute(head, response -> { + if (response.getCode() == 200) { + throw new TransferError("Remote file exists and overwrite is false"); + } else if (response.getCode() != 404) { + throw new TransferError(format("Error checking if remote file exists: %d %s", + response.getCode(), response.getReasonPhrase())); + } + return null; + }); } } @@ -230,7 +233,7 @@ public void handle(PutTransferRequest request, TransferStatusCallback cb) { CountingFileEntity cfe = prepareFileEntity(resolver.resolvePath(request.path())); - HttpPut put = null; + BasicClassicHttpRequest put = null; HttpClientContext context = HttpClientContext.create(); put = prepareRequest(request, cfe); @@ -242,7 +245,7 @@ public void handle(PutTransferRequest request, TransferStatusCallback cb) { try { checkOverwrite(request); context.setAttribute(SciTag.SCITAG_ATTRIBUTE, request.scitag()); - httpClient.execute(put, new PutResponseHandler(MDC.getCopyOfContextMap()), context); + httpClient.execute(put, context, new PutResponseHandler(MDC.getCopyOfContextMap())); reportTask.cancel(true); reportStatus(cb, request, statusBuilder.done(cfe.getCount())); } catch (HttpResponseException e) { diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClientMetricsWrapper.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClientMetricsWrapper.java index 80e58a3a..34a66439 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClientMetricsWrapper.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/http/HttpTransferClientMetricsWrapper.java @@ -17,7 +17,7 @@ import static com.codahale.metrics.MetricRegistry.name; -import org.apache.http.client.ClientProtocolException; +import org.apache.hc.client5.http.ClientProtocolException; import org.italiangrid.storm.webdav.tpc.transfer.GetTransferRequest; import org.italiangrid.storm.webdav.tpc.transfer.PutTransferRequest; import org.italiangrid.storm.webdav.tpc.transfer.TransferClient; diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/PutResponseHandler.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/PutResponseHandler.java index 7d4a5227..588fa39b 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/PutResponseHandler.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/http/PutResponseHandler.java @@ -18,14 +18,15 @@ import java.io.IOException; import java.util.Map; -import org.apache.http.HttpResponse; -import org.apache.http.client.ResponseHandler; -import org.apache.http.util.EntityUtils; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.io.entity.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -public class PutResponseHandler extends ResponseHandlerSupport implements ResponseHandler { +public class PutResponseHandler extends ResponseHandlerSupport + implements HttpClientResponseHandler { public static final Logger LOG = LoggerFactory.getLogger(PutResponseHandler.class); @@ -34,11 +35,11 @@ public PutResponseHandler(Map mdcContextMap) { } @Override - public Boolean handleResponse(HttpResponse response) throws IOException { + public Boolean handleResponse(ClassicHttpResponse response) throws IOException { setupMDC(); - + try { - checkResponseStatus(response.getStatusLine()); + checkResponseStatus(response); return true; } finally { EntityUtils.consumeQuietly(response.getEntity()); diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/ResponseHandlerSupport.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/ResponseHandlerSupport.java index 7ef4bb7d..25929a1c 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/ResponseHandlerSupport.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/http/ResponseHandlerSupport.java @@ -17,8 +17,8 @@ import java.util.Map; -import org.apache.http.StatusLine; -import org.apache.http.client.HttpResponseException; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.client5.http.HttpResponseException; import org.slf4j.MDC; public abstract class ResponseHandlerSupport { @@ -35,9 +35,9 @@ protected void setupMDC() { } } - protected void checkResponseStatus(StatusLine sl) throws HttpResponseException { - if (sl.getStatusCode() >= 300) { - throw new HttpResponseException(sl.getStatusCode(), sl.getReasonPhrase()); + protected void checkResponseStatus(HttpResponse response) throws HttpResponseException { + if (response.getCode() >= 300) { + throw new HttpResponseException(response.getCode(), response.getReasonPhrase()); } } diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/http/SuperLaxRedirectStrategy.java b/src/main/java/org/italiangrid/storm/webdav/tpc/http/SuperLaxRedirectStrategy.java deleted file mode 100644 index 025f159f..00000000 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/http/SuperLaxRedirectStrategy.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.italiangrid.storm.webdav.tpc.http; - -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolException; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.client.DefaultRedirectStrategy; -import org.apache.http.protocol.HttpContext; - -public class SuperLaxRedirectStrategy extends DefaultRedirectStrategy { - - /* - * SUH stands for Sad, Useless Header. - */ - public static final String SUH_HEADER = "X-SUH"; - - public static final String AUTHORIZATION_HEADER = "Authorization"; - - private static final String[] REDIRECT_METHODS = new String[] {HttpGet.METHOD_NAME, - HttpPut.METHOD_NAME, HttpPost.METHOD_NAME, HttpHead.METHOD_NAME, HttpDelete.METHOD_NAME}; - - public static final SuperLaxRedirectStrategy INSTANCE = new SuperLaxRedirectStrategy(); - - private SuperLaxRedirectStrategy() { - // empty ctor - } - - @Override - public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) - throws ProtocolException { - - HttpUriRequest redirect = super.getRedirect(request, response, context); - - /* - * If this method returns an HttpUriRequest that has no HTTP headers then the RedirectExec code - * will copy all the headers from the original request into the HttpUriRequest. - * DefaultRedirectStrategy returns such requests under several circumstances. Therefore, in - * order to suppress the Authorization header we must ensure the returned request - * includes headers. - */ - if (!redirect.headerIterator().hasNext()) { - redirect.setHeaders(request.getAllHeaders()); - } - - redirect.removeHeaders(AUTHORIZATION_HEADER); - - if (!redirect.headerIterator().hasNext()) { - /* - * If the Authorization header was the only one set in the original request or in the redirect, we need to - * add back an empty header otherwise the RedirectExec code will copy the Authorization header from the original - * request back in. - */ - redirect.addHeader(SUH_HEADER, ""); - } - - return redirect; - } - - - @Override - protected boolean isRedirectable(String method) { - for (final String m : REDIRECT_METHODS) { - if (m.equalsIgnoreCase(method)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/transfer/TransferClient.java b/src/main/java/org/italiangrid/storm/webdav/tpc/transfer/TransferClient.java index 58dfd993..057758b9 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/transfer/TransferClient.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/transfer/TransferClient.java @@ -15,12 +15,14 @@ */ package org.italiangrid.storm.webdav.tpc.transfer; -import org.apache.http.client.ClientProtocolException; +import org.apache.hc.client5.http.ClientProtocolException; public interface TransferClient { - void handle(GetTransferRequest request, TransferStatusCallback status) throws ClientProtocolException; - - void handle(PutTransferRequest request, TransferStatusCallback status) throws ClientProtocolException; + void handle(GetTransferRequest request, TransferStatusCallback status) + throws ClientProtocolException; + + void handle(PutTransferRequest request, TransferStatusCallback status) + throws ClientProtocolException; } diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/utils/Adler32DigestHeaderHelper.java b/src/main/java/org/italiangrid/storm/webdav/tpc/utils/Adler32DigestHeaderHelper.java index c75c991f..1f0469f4 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/utils/Adler32DigestHeaderHelper.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/utils/Adler32DigestHeaderHelper.java @@ -22,8 +22,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.http.Header; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpResponse; public class Adler32DigestHeaderHelper { diff --git a/src/main/java/org/italiangrid/storm/webdav/tpc/utils/CountingFileEntity.java b/src/main/java/org/italiangrid/storm/webdav/tpc/utils/CountingFileEntity.java index e0d5e365..8c7757d5 100644 --- a/src/main/java/org/italiangrid/storm/webdav/tpc/utils/CountingFileEntity.java +++ b/src/main/java/org/italiangrid/storm/webdav/tpc/utils/CountingFileEntity.java @@ -15,13 +15,13 @@ */ package org.italiangrid.storm.webdav.tpc.utils; -import static org.apache.http.entity.ContentType.APPLICATION_OCTET_STREAM; +import static org.apache.hc.core5.http.ContentType.APPLICATION_OCTET_STREAM; import java.io.File; import java.io.IOException; import java.io.OutputStream; -import org.apache.http.entity.FileEntity; +import org.apache.hc.core5.http.io.entity.FileEntity; import com.google.common.io.CountingOutputStream; diff --git a/src/main/java/org/italiangrid/storm/webdav/web/ViewUtilsInterceptor.java b/src/main/java/org/italiangrid/storm/webdav/web/ViewUtilsInterceptor.java index f1b54e2b..4021e2df 100644 --- a/src/main/java/org/italiangrid/storm/webdav/web/ViewUtilsInterceptor.java +++ b/src/main/java/org/italiangrid/storm/webdav/web/ViewUtilsInterceptor.java @@ -15,8 +15,8 @@ */ package org.italiangrid.storm.webdav.web; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.authn.AuthenticationUtils; import org.italiangrid.storm.webdav.config.OAuthProperties; diff --git a/src/main/resources/application-redis.yml b/src/main/resources/application-redis.yml index a1431435..5e77524b 100644 --- a/src/main/resources/application-redis.yml +++ b/src/main/resources/application-redis.yml @@ -4,10 +4,11 @@ management: enabled: true spring: - redis: - host: ${STORM_WEBDAV_REDIS_HOST:localhost} - port: ${STORM_WEBDAV_REDIS_PORT:6379} - password: ${STORM_WEBDAV_REDIS_PASSWORD:} + data: + redis: + host: ${STORM_WEBDAV_REDIS_HOST:localhost} + port: ${STORM_WEBDAV_REDIS_PORT:6379} + password: ${STORM_WEBDAV_REDIS_PASSWORD:} session: - store-type: redis \ No newline at end of file + store-type: redis diff --git a/src/test/java/org/italiangrid/storm/webdav/server/TLSConnectorBuilderTest.java b/src/test/java/org/italiangrid/storm/webdav/server/TLSConnectorBuilderTest.java index b7fcbba9..408bee0f 100644 --- a/src/test/java/org/italiangrid/storm/webdav/server/TLSConnectorBuilderTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/server/TLSConnectorBuilderTest.java @@ -24,7 +24,7 @@ import javax.net.ssl.KeyManager; -import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -114,4 +114,4 @@ void tlsConnectorBuilderTests() { ServerConnector c = builder.build(); assertThat(c.getPort(), is(1234)); } -} \ No newline at end of file +} diff --git a/src/test/java/org/italiangrid/storm/webdav/server/servlet/AvoidTraceMethodFilterTest.java b/src/test/java/org/italiangrid/storm/webdav/server/servlet/AvoidTraceMethodFilterTest.java index f4ed7af1..fb11740b 100644 --- a/src/test/java/org/italiangrid/storm/webdav/server/servlet/AvoidTraceMethodFilterTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/server/servlet/AvoidTraceMethodFilterTest.java @@ -70,27 +70,27 @@ void traceAsNonAnonymousOnRootLeadsTo405() throws Exception { @Test void trackAsAnonymousLeadsTo405() throws Exception { - mvc.perform(MockMvcRequestBuilders.request("TRACK", new URI("/test/file"))) + mvc.perform(MockMvcRequestBuilders.request(HttpMethod.valueOf("TRACK"), new URI("/test/file"))) .andExpect(status().isMethodNotAllowed()); } @Test @WithMockVOMSUser(vos = "wlcg", saReadPermissions = {"wlcg"}) void trackAsNonAnonymousLeadsTo405() throws Exception { - mvc.perform(MockMvcRequestBuilders.request("TRACK", new URI("/wlcg/file"))) + mvc.perform(MockMvcRequestBuilders.request(HttpMethod.valueOf("TRACK"), new URI("/wlcg/file"))) .andExpect(status().isMethodNotAllowed()); } @Test void trackAsAnonymousOnRootLeadsTo405() throws Exception { - mvc.perform(MockMvcRequestBuilders.request("TRACK", new URI("/"))) + mvc.perform(MockMvcRequestBuilders.request(HttpMethod.valueOf("TRACK"), new URI("/"))) .andExpect(status().isMethodNotAllowed()); } @Test @WithMockVOMSUser(vos = "wlcg", saReadPermissions = {"wlcg"}) void trackAsNonAnonymousOnRootLeadsTo405() throws Exception { - mvc.perform(MockMvcRequestBuilders.request("TRACK", new URI("/"))) + mvc.perform(MockMvcRequestBuilders.request(HttpMethod.valueOf("TRACK"), new URI("/"))) .andExpect(status().isMethodNotAllowed()); } diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/AuthzTest.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/AuthzTest.java index 698d9572..4d0e697f 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/AuthzTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/AuthzTest.java @@ -19,6 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.italiangrid.storm.webdav.authz.VOMSAuthenticationFilter; +import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; @@ -43,6 +44,9 @@ class AuthzTest { @Autowired VOMSAuthenticationFilter filter; + @Autowired + ServiceConfigurationProperties props; + @BeforeEach public void setup() { filter.setCheckForPrincipalChanges(false); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/integration/AuthorizationIntegrationTests.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/integration/AuthorizationIntegrationTests.java index db4c60c4..9295aaf8 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/integration/AuthorizationIntegrationTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/integration/AuthorizationIntegrationTests.java @@ -36,6 +36,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.http.HttpMethod; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.test.context.ActiveProfiles; @@ -281,17 +282,17 @@ void writeAccessWithoutMatchedJWTIsDenied() throws Exception { @WithMockVOMSUser(vos = "wlcg", saReadPermissions = {"wlcg"}) @Test void localVomsCopyRequiresWithReadPermissionsGetsAccessDenied() throws Exception { - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")).header("Destination", - "http://localhost/wlcg/destination")) + mvc + .perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) + .header("Destination", "http://localhost/wlcg/destination")) .andExpect(status().isForbidden()); } @WithMockVOMSUser(vos = "wlcg", saWritePermissions = {"wlcg"}, saReadPermissions = {"wlcg"}) @Test void localVomsCopyRequiresReadAndWritePermissions() throws Exception { - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")).header("Destination", - "http://localhost/wlcg/destination")) - .andExpect(status().isOk()); + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) + .header("Destination", "http://localhost/wlcg/destination")).andExpect(status().isOk()); } @Test @@ -303,7 +304,7 @@ void tpcJwtPullCopyBlockedWithStorageReadScope() throws Exception { .claim("scope", "storage.read:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Source", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); } @@ -317,7 +318,7 @@ void tpcJwtPullCopyRequiresStorageModifyScope() throws Exception { .claim("scope", "storage.modify:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Source", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isAccepted()); } @@ -331,7 +332,7 @@ void tpcJwtPullCopyRequiresStorageModifyScopeWithRightPath() throws Exception { .claim("scope", "storage.modify:/subdir storage.read:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Source", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); } @@ -346,7 +347,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -357,7 +358,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.modify:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -368,7 +369,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/ storage.modify:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isOk()); @@ -379,7 +380,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/subdir storage.modify:/") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -390,7 +391,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/ storage.modify:/subdir") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -401,7 +402,7 @@ void tpcJwtLocalCopyRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/source storage.modify:/destination") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isOk()); } @@ -415,7 +416,7 @@ void tpcJwtLocalMoveRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.read:/") .build(); - mvc.perform(request("MOVE", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("MOVE"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -426,7 +427,7 @@ void tpcJwtLocalMoveRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.modify:/") .build(); - mvc.perform(request("MOVE", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("MOVE"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isOk()); @@ -438,7 +439,7 @@ void tpcJwtLocalMoveRequiresAppropriatePermissions() throws Exception { .claim("scope", "storage.modify:/subdir") .build(); - mvc.perform(request("MOVE", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("MOVE"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isForbidden()); @@ -450,7 +451,7 @@ void tpcJwtLocalMoveRequiresAppropriatePermissions() throws Exception { .claim("scope", "openid storage.modify:/source storage.modify:/destination") .build(); - mvc.perform(request("MOVE", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("MOVE"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token))).andExpect(status().isOk()); } @@ -465,7 +466,7 @@ void tpcJwtFineGrainedAuthzCopyTests() throws Exception { .subject("123") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token).authorities(authConverter))).andExpect(status().isForbidden()); @@ -477,7 +478,7 @@ void tpcJwtFineGrainedAuthzCopyTests() throws Exception { .claim("groups", "/example/admins") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token).authorities(authConverter))).andExpect(status().isOk()); @@ -488,7 +489,7 @@ void tpcJwtFineGrainedAuthzCopyTests() throws Exception { .claim("groups", "/example") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token).authorities(authConverter))).andExpect(status().isForbidden()); @@ -499,7 +500,7 @@ void tpcJwtFineGrainedAuthzCopyTests() throws Exception { .claim("groups", "/example/admins") .build(); - mvc.perform(request("COPY", URI.create("http://localhost/wlcg/source")) + mvc.perform(request(HttpMethod.valueOf("COPY"), URI.create("http://localhost/wlcg/source")) .header("Destination", "http://localhost/wlcg/destination") .with(jwt().jwt(token).authorities(authConverter))).andExpect(status().isForbidden()); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/AuthzPdpTests.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/AuthzPdpTests.java index 342326fc..460a0fbb 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/AuthzPdpTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/AuthzPdpTests.java @@ -27,7 +27,7 @@ import java.util.List; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.VOMSFQANAuthority; import org.italiangrid.storm.webdav.authz.VOMSVOAuthority; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/LocalAuthzPdpTests.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/LocalAuthzPdpTests.java index 3f082100..26be701f 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/LocalAuthzPdpTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/LocalAuthzPdpTests.java @@ -28,7 +28,7 @@ import java.net.URL; import java.util.Enumeration; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.pdp.LocalAuthorizationPdp; import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationResult; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/PolicyPropertiesValidationTests.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/PolicyPropertiesValidationTests.java index 31cfea4f..913b5a54 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/PolicyPropertiesValidationTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/PolicyPropertiesValidationTests.java @@ -25,10 +25,10 @@ import java.util.Locale; import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; import org.italiangrid.storm.webdav.authz.pdp.PolicyEffect; import org.italiangrid.storm.webdav.config.FineGrainedAuthzPolicyProperties; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/ScopePathAuthzPdpTests.java b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/ScopePathAuthzPdpTests.java index 803f7f59..726568f9 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/ScopePathAuthzPdpTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/authz/pdp/ScopePathAuthzPdpTests.java @@ -30,7 +30,7 @@ import java.net.URL; import java.util.Enumeration; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationResult; import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationResult.Decision; @@ -460,8 +460,7 @@ void parentDirCreationIsNotAllowedWithWrongScopes() { lenient().when(pathResolver.resolveStorageArea(anyString())).thenReturn(sa); lenient().when(request.getPathInfo()).thenReturn("test/dir/subdir"); - lenient().when(jwt.getClaimAsString(SCOPE_CLAIM)) - .thenReturn("openid storage.read:/dir/subdir"); + lenient().when(jwt.getClaimAsString(SCOPE_CLAIM)).thenReturn("openid storage.read:/dir/subdir"); lenient().when(request.getMethod()).thenReturn("MKCOL"); PathAuthorizationResult result = pdp.authorizeRequest(newAuthorizationRequest(request, jwtAuth)); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/oauth/integration/OAuthAuthzServerIntegrationTests.java b/src/test/java/org/italiangrid/storm/webdav/test/oauth/integration/OAuthAuthzServerIntegrationTests.java index 41eaaac3..f2d36cf8 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/oauth/integration/OAuthAuthzServerIntegrationTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/oauth/integration/OAuthAuthzServerIntegrationTests.java @@ -16,7 +16,6 @@ package org.italiangrid.storm.webdav.test.oauth.integration; import static java.lang.String.format; -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.CoreMatchers.is; import static org.italiangrid.storm.webdav.oauth.authzserver.ErrorResponseDTO.UNSUPPORTED_GRANT_TYPE; import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED; @@ -30,6 +29,7 @@ import java.time.Instant; import java.time.ZoneId; +import org.apache.commons.lang3.RandomStringUtils; import org.italiangrid.storm.webdav.authz.VOMSAuthenticationFilter; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.oauth.authzserver.AccessTokenRequest; @@ -161,7 +161,9 @@ void requestedLifetimeLimited() throws Exception { @WithMockVOMSUser void scopeLengthIsChecked() throws Exception { - String randomAlphabetic = randomAlphabetic(AccessTokenRequest.MAX_SCOPE_LENGTH); + RandomStringUtils randomStringUtils = RandomStringUtils.insecure(); + + String randomAlphabetic = randomStringUtils.nextAlphabetic(AccessTokenRequest.MAX_SCOPE_LENGTH); mvc .perform(post("/oauth/token").content(format("%s&scope=%s", CONTENT, randomAlphabetic)) @@ -169,7 +171,7 @@ void scopeLengthIsChecked() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.access_token").exists()); - randomAlphabetic = randomAlphabetic(AccessTokenRequest.MAX_SCOPE_LENGTH + 1); + randomAlphabetic = randomStringUtils.nextAlphabetic(AccessTokenRequest.MAX_SCOPE_LENGTH + 1); mvc .perform(post("/oauth/token").content(format("%s&scope=%s", CONTENT, randomAlphabetic)) diff --git a/src/test/java/org/italiangrid/storm/webdav/test/oauth/jwk/OidcConfigurationFetcherTest.java b/src/test/java/org/italiangrid/storm/webdav/test/oauth/jwk/OidcConfigurationFetcherTest.java index 0725f914..64f93704 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/oauth/jwk/OidcConfigurationFetcherTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/oauth/jwk/OidcConfigurationFetcherTest.java @@ -49,6 +49,7 @@ import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; @@ -94,8 +95,7 @@ private ResponseEntity> getWellKnownResponse(HttpStatus stat ResponseEntity> mockedEntity = (ResponseEntity>) Mockito.mock(ResponseEntity.class); - lenient().when(mockedEntity.getStatusCode()).thenReturn(status); - lenient().when(mockedEntity.getStatusCodeValue()).thenReturn(status.value()); + lenient().when(mockedEntity.getStatusCode()).thenReturn(HttpStatusCode.valueOf(status.value())); lenient().when(mockedEntity.getBody()).thenReturn(map); return mockedEntity; } @@ -113,8 +113,7 @@ private ResponseEntity getJWKURIResponse(HttpStatus status, String data) ResponseEntity mockedEntity = (ResponseEntity) Mockito.mock(ResponseEntity.class); lenient().when(mockedEntity.getBody()).thenReturn(data); - lenient().when(mockedEntity.getStatusCode()).thenReturn(status); - lenient().when(mockedEntity.getStatusCodeValue()).thenReturn(status.value()); + lenient().when(mockedEntity.getStatusCode()).thenReturn(HttpStatusCode.valueOf(status.value())); return mockedEntity; } @@ -126,18 +125,20 @@ private OidcConfigurationFetcher getFetcher(ResponseEntity> return getFetcher(restTemplate); } - private OidcConfigurationFetcher getFetcherWithException(ResponseEntity> wellKnownResponse) { + private OidcConfigurationFetcher getFetcherWithException( + ResponseEntity> wellKnownResponse) { lenient().when(restTemplate.exchange(any(), eq(typeReference))).thenReturn(wellKnownResponse); - lenient().when(restTemplate.exchange(any(), eq(String.class))).thenThrow(new RuntimeException("ERROR")); + lenient().when(restTemplate.exchange(any(), eq(String.class))) + .thenThrow(new RuntimeException("ERROR")); return getFetcher(restTemplate); } private OidcConfigurationFetcher getFetcher(RestTemplate restTemplate) { lenient().when(restBuilder.build()).thenReturn(restTemplate); - lenient().when(restBuilder.setConnectTimeout(any())).thenReturn(restBuilder); - lenient().when(restBuilder.setReadTimeout(any())).thenReturn(restBuilder); + lenient().when(restBuilder.connectTimeout(any())).thenReturn(restBuilder); + lenient().when(restBuilder.readTimeout(any())).thenReturn(restBuilder); lenient().when(oAuthProperties.getRefreshTimeoutSeconds()).thenReturn(30); lenient().when(oAuthProperties.getRefreshPeriodMinutes()).thenReturn(1); return new DefaultOidcConfigurationFetcher(restBuilder, oAuthProperties); @@ -195,7 +196,8 @@ private OidcConfigurationFetcher getFetcherWithErrorOnGetJwk() throws RestClient return getFetcher(mockedResponseMapEntity, mockedResponseStringEntity); } - private OidcConfigurationFetcher getFetcherWithRuntimeExceptionOnGetJwk() throws RestClientException { + private OidcConfigurationFetcher getFetcherWithRuntimeExceptionOnGetJwk() + throws RestClientException { ResponseEntity> mockedResponseMapEntity = getWellKnownResponse(OK, getMapWithIssuerAndJwkUri(ISSUER, JWK_URI)); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectFilterTests.java b/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectFilterTests.java index ec96bbc7..41878932 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectFilterTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectFilterTests.java @@ -15,7 +15,7 @@ */ package org.italiangrid.storm.webdav.test.redirector; -import static javax.servlet.http.HttpServletResponse.SC_TEMPORARY_REDIRECT; +import static jakarta.servlet.http.HttpServletResponse.SC_TEMPORARY_REDIRECT; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.lenient; @@ -28,10 +28,10 @@ import java.nio.file.Path; import java.util.Map; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.redirector.RedirectFilter; import org.italiangrid.storm.webdav.redirector.RedirectionService; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectionServiceTests.java b/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectionServiceTests.java index 6f7d4489..7bd57ade 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectionServiceTests.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/redirector/RedirectionServiceTests.java @@ -26,8 +26,8 @@ import java.net.URI; import java.util.Optional; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.oauth.authzserver.ResourceAccessTokenRequest; @@ -81,7 +81,8 @@ class RedirectionServiceTests extends RedirectorTestSupport { @BeforeEach public void setup() { config = buildConfigurationProperties(); - lenient().when(tokenIssuer.createResourceAccessToken(Mockito.any(), Mockito.any())).thenReturn(token); + lenient().when(tokenIssuer.createResourceAccessToken(Mockito.any(), Mockito.any())) + .thenReturn(token); lenient().when(token.serialize()).thenReturn(RANDOM_TOKEN_STRING); lenient().when(selector.selectReplica()).thenReturn(Optional.empty()); lenient().when(request.getServletPath()).thenReturn(PATH); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/PullTransferTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/PullTransferTest.java index 09527a6a..1fc62c70 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/PullTransferTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/PullTransferTest.java @@ -28,7 +28,7 @@ import java.io.IOException; -import javax.servlet.ServletException; +import jakarta.servlet.ServletException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -109,8 +109,8 @@ void checkTransferHeaderPassing() throws IOException, ServletException { when(request.getHeader(TRANSFER_HEADER_SCITAG)).thenReturn(SCITAG_HEADER_VALUE); when(request.getHeader(SCITAG_HEADER)).thenReturn(null); - when(request.getHeaderNames()).thenReturn(enumeration( - asList(TRANSFER_HEADER_AUTHORIZATION_KEY, TRANSFER_HEADER_WHATEVER_KEY, TRANSFER_HEADER_SCITAG))); + when(request.getHeaderNames()).thenReturn(enumeration(asList(TRANSFER_HEADER_AUTHORIZATION_KEY, + TRANSFER_HEADER_WHATEVER_KEY, TRANSFER_HEADER_SCITAG))); filter.doFilter(request, response, chain); verify(client).handle(getXferRequest.capture(), Mockito.any()); @@ -134,8 +134,8 @@ void checkTransferHeaderPassing() throws IOException, ServletException { @Test void emptyTransferHeaderAreIgnored() throws IOException, ServletException { - when(request.getHeaderNames()).thenReturn( - enumeration(asList(TRANSFER_HEADER, TRANSFER_HEADER_WHATEVER_KEY))); + when(request.getHeaderNames()) + .thenReturn(enumeration(asList(TRANSFER_HEADER, TRANSFER_HEADER_WHATEVER_KEY))); when(request.getHeader(TRANSFER_HEADER_WHATEVER_KEY)) .thenReturn(TRANSFER_HEADER_WHATEVER_VALUE); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/PushTransferTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/PushTransferTest.java index 8806e50c..c9c80b60 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/PushTransferTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/PushTransferTest.java @@ -18,7 +18,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyEnumeration; import static java.util.Collections.enumeration; -import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; +import static jakarta.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.COPY; @@ -29,8 +29,8 @@ import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -139,8 +139,8 @@ void checkTransferHeaderPassing() throws IOException, ServletException { @Test void emptyTransferHeaderAreIgnored() throws IOException, ServletException { - when(request.getHeaderNames()).thenReturn( - enumeration(asList(TRANSFER_HEADER, TRANSFER_HEADER_WHATEVER_KEY))); + when(request.getHeaderNames()) + .thenReturn(enumeration(asList(TRANSFER_HEADER, TRANSFER_HEADER_WHATEVER_KEY))); when(request.getHeader(TRANSFER_HEADER_WHATEVER_KEY)) .thenReturn(TRANSFER_HEADER_WHATEVER_VALUE); @@ -178,9 +178,9 @@ void checkExpectContinueHeaderIsSet() throws IOException, ServletException { when(request.getHeader(TRANSFER_HEADER_AUTHORIZATION_KEY)) .thenReturn(TRANSFER_HEADER_AUTHORIZATION_VALUE); - when(request.getHeaderNames()).thenReturn( - enumeration(asList(TRANSFER_HEADER_AUTHORIZATION_KEY))); - when(request.getContentLength()).thenReturn(1024*1024+1); + when(request.getHeaderNames()) + .thenReturn(enumeration(asList(TRANSFER_HEADER_AUTHORIZATION_KEY))); + when(request.getContentLength()).thenReturn(1024 * 1024 + 1); filter.doFilter(request, response, chain); verify(client).handle(putXferRequest.capture(), Mockito.any()); @@ -198,9 +198,9 @@ void checkExpectContinueHeaderIsNotSet() throws IOException, ServletException { when(request.getHeader(TRANSFER_HEADER_AUTHORIZATION_KEY)) .thenReturn(TRANSFER_HEADER_AUTHORIZATION_VALUE); - when(request.getHeaderNames()).thenReturn( - enumeration(asList(TRANSFER_HEADER_AUTHORIZATION_KEY))); - when(request.getContentLength()).thenReturn(1024*1024-1); + when(request.getHeaderNames()) + .thenReturn(enumeration(asList(TRANSFER_HEADER_AUTHORIZATION_KEY))); + when(request.getContentLength()).thenReturn(1024 * 1024 - 1); filter.doFilter(request, response, chain); verify(client).handle(putXferRequest.capture(), Mockito.any()); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/SciTagFilterActivationTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/SciTagFilterActivationTest.java index 51e587c9..ac438355 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/SciTagFilterActivationTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/SciTagFilterActivationTest.java @@ -27,7 +27,7 @@ import java.io.File; import java.io.IOException; -import javax.servlet.ServletException; +import jakarta.servlet.ServletException; import org.italiangrid.storm.webdav.config.StorageAreaInfo; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterActivationTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterActivationTest.java index b7b9a3a0..2fa25695 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterActivationTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterActivationTest.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.util.EnumSet; -import javax.servlet.ServletException; +import jakarta.servlet.ServletException; import org.italiangrid.storm.webdav.config.StorageAreaInfo; import org.italiangrid.storm.webdav.server.servlet.WebDAVMethod; @@ -82,8 +82,7 @@ void filterIgnoresOtherHttpOrWebdavMethods() throws IOException, ServletExceptio } @Test - void filterSkippedIfSourceAndDestionationHeaderMissing() - throws IOException, ServletException { + void filterSkippedIfSourceAndDestionationHeaderMissing() throws IOException, ServletException { // No source or destination header when(request.getHeader(TransferConstants.SOURCE_HEADER)).thenReturn(null); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterTestSupport.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterTestSupport.java index 6f81b5c1..4b8289a0 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterTestSupport.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferFilterTestSupport.java @@ -26,9 +26,9 @@ import java.util.Arrays; import java.util.Enumeration; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.italiangrid.storm.webdav.server.PathResolver; import org.italiangrid.storm.webdav.tpc.LocalURLService; @@ -76,8 +76,8 @@ public class TransferFilterTestSupport { public static final String[] INVALID_URLs = {"http:whatever", "httpg://storm.example/test", "gsiftp://whatever/test"}; - public static final String EXPECTED_HEADER = org.apache.http.protocol.HTTP.EXPECT_DIRECTIVE; - public static final String EXPECTED_VALUE = org.apache.http.protocol.HTTP.EXPECT_CONTINUE; + public static final String EXPECTED_HEADER = "Expect"; + public static final String EXPECTED_VALUE = "100-continue"; @Mock FilterChain chain; @@ -117,7 +117,7 @@ public class TransferFilterTestSupport { LocalURLService lus = new StaticHostListLocalURLService(Arrays.asList("localhost")); protected void setup() throws IOException { - filter = new TransferFilter(clock, client, resolver, lus, true, 1024L*1024L); + filter = new TransferFilter(clock, client, resolver, lus, true, 1024L * 1024L); lenient().when(request.getHeaderNames()).thenReturn(requestHeaderNames); } diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferRequestValidationTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferRequestValidationTest.java index 619e7782..b8a741af 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferRequestValidationTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferRequestValidationTest.java @@ -16,7 +16,7 @@ package org.italiangrid.storm.webdav.test.tpc; import static java.util.Collections.emptyEnumeration; -import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; +import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -29,8 +29,8 @@ import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferReturnStatusTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferReturnStatusTest.java index b54b1bac..96cb54d1 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferReturnStatusTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/TransferReturnStatusTest.java @@ -16,8 +16,8 @@ package org.italiangrid.storm.webdav.test.tpc; import static java.util.Collections.emptyEnumeration; -import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED; -import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; +import static jakarta.servlet.http.HttpServletResponse.SC_ACCEPTED; +import static jakarta.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.COPY; @@ -26,11 +26,11 @@ import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.HttpResponseException; +import org.apache.hc.client5.http.ClientProtocolException; +import org.apache.hc.client5.http.HttpResponseException; import org.italiangrid.storm.webdav.tpc.TransferConstants; import org.italiangrid.storm.webdav.tpc.transfer.GetTransferRequest; import org.italiangrid.storm.webdav.tpc.transfer.error.ChecksumVerificationError; diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTest.java index efd8b40b..fdd9d9bc 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTest.java @@ -24,13 +24,14 @@ import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.protocol.HttpClientContext; +import org.apache.hc.core5.http.io.HttpClientResponseHandler; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; +import org.apache.hc.client5.http.protocol.HttpClientContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -53,7 +54,9 @@ class ClientTest extends ClientTestSupport { public void setup() throws IOException { super.setup(); - lenient().when(es.scheduleAtFixedRate(Mockito.any(), Mockito.anyLong(), Mockito.anyLong(), Mockito.any())) + lenient() + .when(es.scheduleAtFixedRate(Mockito.any(), Mockito.anyLong(), Mockito.anyLong(), + Mockito.any())) .thenReturn(sf); lenient().when(req.remoteURI()).thenReturn(HTTP_URI_URI); lenient().when(req.path()).thenReturn(LOCAL_PATH); @@ -70,38 +73,36 @@ public void setup() throws IOException { } @Test - void testClientCorrectlyBuildsHttpRequestNoHeaders() throws IOException { + void testClientCorrectlyBuildsHttpRequestNoHeaders() throws IOException, URISyntaxException { client.handle(req, (r, s) -> { }); - verify(httpClient).execute(getRequest.capture(), - ArgumentMatchers.>any(), - ArgumentMatchers.any()); + verify(httpClient).execute(getRequest.capture(), ArgumentMatchers.any(), + ArgumentMatchers.>any()); - HttpGet httpGetReq = getRequest.getValue(); + BasicClassicHttpRequest httpGetReq = getRequest.getValue(); - assertThat(httpGetReq.getURI(), is(HTTP_URI_URI)); - assertThat(httpGetReq.getAllHeaders(), arrayWithSize(0)); + assertThat(httpGetReq.getUri(), is(HTTP_URI_URI)); + assertThat(httpGetReq.getHeaders(), arrayWithSize(0)); } @Test - void testClientCorrectlyBuildsHttpRequestWithHeaders() throws IOException { + void testClientCorrectlyBuildsHttpRequestWithHeaders() throws IOException, URISyntaxException { when(req.transferHeaders()).thenReturn(HEADER_MAP); client.handle(req, (r, s) -> { }); - verify(httpClient).execute(getRequest.capture(), - ArgumentMatchers.>any(), - ArgumentMatchers.any()); + verify(httpClient).execute(getRequest.capture(), ArgumentMatchers.any(), + ArgumentMatchers.>any()); - HttpGet httpGetReq = getRequest.getValue(); + BasicClassicHttpRequest httpGetReq = getRequest.getValue(); - assertThat(httpGetReq.getURI(), is(HTTP_URI_URI)); - assertThat(httpGetReq.getAllHeaders(), arrayWithSize(1)); + assertThat(httpGetReq.getUri(), is(HTTP_URI_URI)); + assertThat(httpGetReq.getHeaders(), arrayWithSize(1)); assertThat(httpGetReq.getHeaders(AUTHORIZATION_HEADER)[0].getValue(), is(AUTHORIZATION_HEADER_VALUE)); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTestSupport.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTestSupport.java index ce3ef8ce..e1697c5f 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTestSupport.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/ClientTestSupport.java @@ -22,8 +22,8 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.hc.core5.http.message.BasicClassicHttpRequest; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties; import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties.BufferProperties; import org.italiangrid.storm.webdav.config.ThirdPartyCopyProperties; @@ -79,7 +79,7 @@ public class ClientTestSupport { HttpTransferClient client; @Captor - ArgumentCaptor getRequest; + ArgumentCaptor getRequest; public static final String MOCKFS_WORKDIR = "/mockfs"; @@ -100,9 +100,8 @@ public void setup() throws IOException { BufferProperties buffer = new BufferProperties(); config.setBuffer(buffer); - client = - new HttpTransferClient(Clock.systemDefaultZone(), httpClient, resolver, eah, es, props, - config); + client = new HttpTransferClient(Clock.systemDefaultZone(), httpClient, resolver, eah, es, props, + config); } } diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/DigestTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/DigestTest.java index 5ace7612..24a0dfe6 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/DigestTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/DigestTest.java @@ -20,8 +20,8 @@ import static org.italiangrid.storm.webdav.tpc.utils.Adler32DigestHeaderHelper.extractAdler32DigestFromResponse; import static org.mockito.Mockito.lenient; -import org.apache.http.Header; -import org.apache.http.HttpResponse; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpResponse; import org.italiangrid.storm.webdav.tpc.utils.Adler32DigestHeaderHelper; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -45,7 +45,8 @@ public class DigestTest { protected void instrumentResponse(String headerValue) { - lenient().when(response.getFirstHeader(Adler32DigestHeaderHelper.DIGEST_HEADER)).thenReturn(header); + lenient().when(response.getFirstHeader(Adler32DigestHeaderHelper.DIGEST_HEADER)) + .thenReturn(header); lenient().when(header.getName()).thenReturn(Adler32DigestHeaderHelper.DIGEST_HEADER); lenient().when(header.getValue()).thenReturn(headerValue); } diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/GetResponseHandlerTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/GetResponseHandlerTest.java index 498be64d..72f434d3 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/GetResponseHandlerTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/GetResponseHandlerTest.java @@ -18,14 +18,12 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import java.io.IOException; import java.nio.file.Path; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.ClassicHttpResponse; import org.italiangrid.storm.webdav.tpc.http.GetResponseHandler; import org.italiangrid.storm.webdav.tpc.utils.StormCountingOutputStream; import org.junit.jupiter.api.BeforeEach; @@ -38,14 +36,11 @@ @ExtendWith(MockitoExtension.class) class GetResponseHandlerTest extends ClientTestSupport { - @Mock - StatusLine status; - @Mock HttpEntity entity; @Mock - HttpResponse response; + ClassicHttpResponse response; @Mock StormCountingOutputStream os; @@ -57,14 +52,11 @@ class GetResponseHandlerTest extends ClientTestSupport { public void setup() { handler = new GetResponseHandler(null, os, eah); - lenient().when(response.getStatusLine()).thenReturn(status); lenient().when(response.getEntity()).thenReturn(entity); } @Test void handlerWritesToStream() throws IOException { - when(status.getStatusCode()).thenReturn(200); - handler.handleResponse(response); verify(entity).getContent(); diff --git a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/integration/TpcClientRedirectionTest.java b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/integration/TpcClientRedirectionTest.java index 33e51df0..3405c60b 100644 --- a/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/integration/TpcClientRedirectionTest.java +++ b/src/test/java/org/italiangrid/storm/webdav/test/tpc/http/integration/TpcClientRedirectionTest.java @@ -26,14 +26,14 @@ import javax.net.ssl.SSLContext; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.italiangrid.storm.webdav.WebdavService; import org.italiangrid.storm.webdav.config.ServiceConfiguration; import org.italiangrid.storm.webdav.config.ThirdPartyCopyProperties;