diff --git a/hawkbit-http-security/pom.xml b/hawkbit-http-security/pom.xml index 689913f76..09dae931b 100644 --- a/hawkbit-http-security/pom.xml +++ b/hawkbit-http-security/pom.xml @@ -9,54 +9,55 @@ SPDX-License-Identifier: EPL-2.0 --> - - 4.0.0 - - hawkbit-parent - ${revision} - org.eclipse.hawkbit - - hawkbit-http-security - hawkBit :: HTTP Security + + 4.0.0 + + hawkbit-parent + ${revision} + org.eclipse.hawkbit + + hawkbit-http-security + hawkBit :: HTTP Security - - - org.eclipse.hawkbit - hawkbit-repository-api - ${project.version} - - - org.eclipse.hawkbit - hawkbit-security-core - ${project.version} - - - org.eclipse.hawkbit - hawkbit-security-integration - ${project.version} - - - jakarta.servlet - jakarta.servlet-api - provided - - - com.github.ben-manes.caffeine - caffeine - + + + org.eclipse.hawkbit + hawkbit-repository-api + ${project.version} + + + org.eclipse.hawkbit + hawkbit-security-core + ${project.version} + + + org.eclipse.hawkbit + hawkbit-security-integration + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + provided + + + com.github.ben-manes.caffeine + caffeine + - - - org.springframework.boot - spring-boot-starter-test - test - - - io.qameta.allure - allure-junit5 - test - - + + + org.springframework.boot + spring-boot-starter-test + test + + + io.qameta.allure + allure-junit5 + test + + \ No newline at end of file diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java index 413891d25..6f344fca3 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java @@ -39,10 +39,12 @@ import org.springframework.util.AntPathMatcher; * based on this information. */ public abstract class AbstractHttpControllerAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter { - + + protected TenantConfigurationManagement tenantConfigurationManagement; + protected TenantAware tenantAware; + protected SystemSecurityContext systemSecurityContext; private static final String TENANT_PLACE_HOLDER = "tenant"; private static final String CONTROLLER_ID_PLACE_HOLDER = "controllerId"; - /** * requestURIPathPattern the request URI path pattern in ANT style * containing the placeholder key for retrieving the principal from the URI @@ -50,20 +52,15 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac */ private static final String CONTROLLER_REQUEST_ANT_PATTERN = "/{" + TENANT_PLACE_HOLDER + "}/controller/v1" + "/{" + CONTROLLER_ID_PLACE_HOLDER + "}/**"; - private static final String CONTROLLER_DL_REQUEST_ANT_PATTERN = "/{" + TENANT_PLACE_HOLDER + "}/controller/artifacts/v1/**"; - protected TenantConfigurationManagement tenantConfigurationManagement; - protected TenantAware tenantAware; - protected SystemSecurityContext systemSecurityContext; - private final AntPathMatcher pathExtractor; private PreAuthenticationFilter abstractControllerAuthenticationFilter; /** * Constructor for subclasses. - * + * * @param tenantConfigurationManagement the tenant configuration service * @param tenantAware the tenant aware service * @param systemSecurityContext the system security context @@ -106,8 +103,6 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac } } - protected abstract PreAuthenticationFilter createControllerAuthenticationFilter(); - @Override protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final Authentication authResult) throws IOException, ServletException { @@ -120,11 +115,31 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac super.successfulAuthentication(request, response, authTokenWithGrantedAuthorities); } + @Override + protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) { + final DmfTenantSecurityToken securityToken = createTenantSecurityTokenVariables(request); + if (securityToken == null) { + return null; + } + return abstractControllerAuthenticationFilter.getPreAuthenticatedPrincipal(securityToken); + } + + @Override + protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) { + final DmfTenantSecurityToken securityToken = createTenantSecurityTokenVariables(request); + if (securityToken == null) { + return null; + } + return abstractControllerAuthenticationFilter.getPreAuthenticatedCredentials(securityToken); + } + + protected abstract PreAuthenticationFilter createControllerAuthenticationFilter(); + protected abstract Logger log(); /** * Extracts tenant and controllerId from the request URI as path variables. - * + * * @param request the Http request to extract the path variables. * @return the extracted {@link DmfTenantSecurityToken} or {@code null} if the * request does not match the pattern and no variables could be @@ -150,13 +165,13 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac return createTenantSecurityTokenVariables(request, tenant, "anonymous"); } else { log().trace("request {} does not match the path pattern {}, request gets ignored", requestURI, - CONTROLLER_REQUEST_ANT_PATTERN); + CONTROLLER_REQUEST_ANT_PATTERN); return null; } } private DmfTenantSecurityToken createTenantSecurityTokenVariables(final HttpServletRequest request, - final String tenant, final String controllerId) { + final String tenant, final String controllerId) { final DmfTenantSecurityToken securityToken = new DmfTenantSecurityToken(tenant, null, controllerId, null); Collections.list(request.getHeaderNames()) @@ -165,22 +180,4 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac return securityToken; } - @Override - protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) { - final DmfTenantSecurityToken securityToken = createTenantSecurityTokenVariables(request); - if (securityToken == null) { - return null; - } - return abstractControllerAuthenticationFilter.getPreAuthenticatedPrincipal(securityToken); - } - - @Override - protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) { - final DmfTenantSecurityToken securityToken = createTenantSecurityTokenVariables(request); - if (securityToken == null) { - return null; - } - return abstractControllerAuthenticationFilter.getPreAuthenticatedCredentials(securityToken); - } - } diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/DosFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/DosFilter.java index c913b0c3c..11e8dfc8d 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/DosFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/DosFilter.java @@ -20,6 +20,8 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import lombok.extern.slf4j.Slf4j; import org.eclipse.hawkbit.util.IpUtil; import org.slf4j.Logger; @@ -29,9 +31,6 @@ import org.springframework.http.HttpStatus; import org.springframework.util.AntPathMatcher; import org.springframework.web.filter.OncePerRequestFilter; -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; - /** * Filter for protection against denial of service attacks. It reduces the * maximum number of request per seconds which can be separately configured for @@ -65,24 +64,17 @@ public class DosFilter extends OncePerRequestFilter { /** * Filter constructor including configuration. - * - * @param includeAntPaths - * paths where filter should hit * - * @param maxRead - * Maximum number of allowed REST read/GET requests per second - * per client - * @param maxWrite - * Maximum number of allowed REST write/(PUT/POST/etc.) requests - * per second per client - * @param ipDosWhiteListPattern - * {@link Pattern} with with white list of peer IP addresses for - * DOS filter - * @param ipBlackListPattern - * {@link Pattern} with black listed IP addresses - * @param forwardHeader - * the header containing the forwarded IP address e.g. - * {@code x-forwarded-for} + * @param includeAntPaths paths where filter should hit + * @param maxRead Maximum number of allowed REST read/GET requests per second + * per client + * @param maxWrite Maximum number of allowed REST write/(PUT/POST/etc.) requests + * per second per client + * @param ipDosWhiteListPattern {@link Pattern} with with white list of peer IP addresses for + * DOS filter + * @param ipBlackListPattern {@link Pattern} with black listed IP addresses + * @param forwardHeader the header containing the forwarded IP address e.g. + * {@code x-forwarded-for} */ public DosFilter(final Collection includeAntPaths, final int maxRead, final int maxWrite, final String ipDosWhiteListPattern, final String ipBlackListPattern, final String forwardHeader) { @@ -104,15 +96,6 @@ public class DosFilter extends OncePerRequestFilter { } } - private boolean shouldInclude(final HttpServletRequest request) { - if (includeAntPaths == null || includeAntPaths.isEmpty()) { - return true; - } - - return includeAntPaths.stream() - .anyMatch(pattern -> antMatcher.match(request.getContextPath() + pattern, request.getRequestURI())); - } - @Override protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException { @@ -148,6 +131,25 @@ public class DosFilter extends OncePerRequestFilter { } } + private static boolean checkIpFails(final String ip) { + return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip); + } + + private static boolean handleMissingIpAddress(final HttpServletResponse response) { + log.error("Failed to get peer IP address"); + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + return false; + } + + private boolean shouldInclude(final HttpServletRequest request) { + if (includeAntPaths == null || includeAntPaths.isEmpty()) { + return true; + } + + return includeAntPaths.stream() + .anyMatch(pattern -> antMatcher.match(request.getContextPath() + pattern, request.getRequestURI())); + } + /** * @return false if the given ip address is on the blacklist and further * processing of the request if forbidden @@ -161,16 +163,6 @@ public class DosFilter extends OncePerRequestFilter { return true; } - private static boolean checkIpFails(final String ip) { - return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip); - } - - private static boolean handleMissingIpAddress(final HttpServletResponse response) { - log.error("Failed to get peer IP address"); - response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); - return false; - } - private boolean handleWriteRequest(final HttpServletResponse response, final String ip) { boolean processChain = true; final AtomicInteger count = writeCountCache.getIfPresent(ip); diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateAnonymousDownloadFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateAnonymousDownloadFilter.java index be1281f31..a61c104b5 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateAnonymousDownloadFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateAnonymousDownloadFilter.java @@ -26,7 +26,7 @@ public class HttpControllerPreAuthenticateAnonymousDownloadFilter extends Abstra /** * Constructor. - * + * * @param tenantConfigurationManagement the system management service to retrieve configuration properties * @param tenantAware the tenant aware service to get configuration for the specific tenant * @param systemSecurityContext the system security context diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java index 4a6f620bc..563e148a5 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticateSecurityTokenFilter.java @@ -21,7 +21,7 @@ import org.slf4j.Logger; * security-token with the {@code Authorization} HTTP header. * {@code Example Header: Authorization: TargetToken * 5d8fSD54fdsFG98DDsa.} - * + * * The {@code Authorization} header is a HTTP standard and reverse proxy or * other proxies will keep the Authorization headers untouched instead of maybe * custom headers which have then weird side-effects. Furthermore frameworks are @@ -35,18 +35,14 @@ public class HttpControllerPreAuthenticateSecurityTokenFilter extends AbstractHt /** * Constructor. - * - * @param tenantConfigurationManagement - * the system management service to retrieve configuration - * properties - * @param tenantAware - * the tenant aware service to get configuration for the specific - * tenant - * @param controllerManagement - * the controller management to retrieve the specific target - * security token to verify - * @param systemSecurityContext - * the system security context + * + * @param tenantConfigurationManagement the system management service to retrieve configuration + * properties + * @param tenantAware the tenant aware service to get configuration for the specific + * tenant + * @param controllerManagement the controller management to retrieve the specific target + * security token to verify + * @param systemSecurityContext the system security context */ public HttpControllerPreAuthenticateSecurityTokenFilter( final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java index b2c8cf6a3..23d681a58 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedGatewaySecurityTokenFilter.java @@ -27,15 +27,12 @@ public class HttpControllerPreAuthenticatedGatewaySecurityTokenFilter /** * Constructor. - * - * @param tenantConfigurationManagement - * the system management service to retrieve configuration - * properties - * @param tenantAware - * the tenant aware service to get configuration for the specific - * tenant - * @param systemSecurityContext - * the system security context + * + * @param tenantConfigurationManagement the system management service to retrieve configuration + * properties + * @param tenantAware the tenant aware service to get configuration for the specific + * tenant + * @param systemSecurityContext the system security context */ public HttpControllerPreAuthenticatedGatewaySecurityTokenFilter( final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java index fd4ce3566..541dd63cf 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpControllerPreAuthenticatedSecurityHeaderFilter.java @@ -30,21 +30,16 @@ public class HttpControllerPreAuthenticatedSecurityHeaderFilter extends Abstract * from the HTTP request with the given URI pattern, in case the URI pattern * does not match the current request then only the existence of the * configured header field is checked. - * - * @param caCommonNameHeader - * the http-header which holds the common-name of the certificate - * @param caAuthorityNameHeader - * the http-header which holds the ca-authority name of the - * certificate - * @param tenantConfigurationManagement - * the tenant configuration management service to retrieve - * configuration properties to check if the header authentication - * is enabled for this tenant - * @param tenantAware - * the tenant aware service to get configuration for the specific - * tenant - * @param systemSecurityContext - * the system security context + * + * @param caCommonNameHeader the http-header which holds the common-name of the certificate + * @param caAuthorityNameHeader the http-header which holds the ca-authority name of the + * certificate + * @param tenantConfigurationManagement the tenant configuration management service to retrieve + * configuration properties to check if the header authentication + * is enabled for this tenant + * @param tenantAware the tenant aware service to get configuration for the specific + * tenant + * @param systemSecurityContext the system security context */ public HttpControllerPreAuthenticatedSecurityHeaderFilter(final String caCommonNameHeader, final String caAuthorityNameHeader, final TenantConfigurationManagement tenantConfigurationManagement, diff --git a/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java b/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java index cc7c0feba..ff2cd1cb8 100644 --- a/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java +++ b/hawkbit-http-security/src/test/java/org/eclipse/hawkbit/security/PreAuthTokenSourceTrustAuthenticationProviderTest.java @@ -15,6 +15,9 @@ import static org.mockito.Mockito.when; import java.util.Collections; +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import io.qameta.allure.Story; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -24,10 +27,6 @@ import org.springframework.security.authentication.InsufficientAuthenticationExc import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; -import io.qameta.allure.Description; -import io.qameta.allure.Feature; -import io.qameta.allure.Story; - @Feature("Unit Tests - Security") @Story("PreAuthToken Source TrustAuthentication Provider Test") @ExtendWith(MockitoExtension.class)