diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java index 0e1d97945..662b5c675 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.im.authentication.TenantAwareUserProperties.User; import org.eclipse.hawkbit.security.DdiSecurityProperties; import org.eclipse.hawkbit.security.InMemoryUserAuthoritiesResolver; import org.eclipse.hawkbit.security.HawkbitSecurityProperties; -import org.eclipse.hawkbit.security.MDCHandler; +import org.eclipse.hawkbit.security.MdcHandler; import org.eclipse.hawkbit.security.SecurityContextSerializer; import org.eclipse.hawkbit.security.SecurityContextTenantAware; import org.eclipse.hawkbit.security.SecurityTokenGenerator; @@ -124,8 +124,8 @@ public class SecurityAutoConfiguration { @Bean @ConditionalOnMissingBean - public MDCHandler mdcHandler() { - return MDCHandler.getInstance(); + public MdcHandler mdcHandler() { + return MdcHandler.getInstance(); } @Bean diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java index 1694e0013..07b2ed0d9 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java @@ -33,7 +33,7 @@ import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateAnonymousDownlo import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter; import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter; import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter; -import org.eclipse.hawkbit.security.MDCHandler; +import org.eclipse.hawkbit.security.MdcHandler; import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; @@ -62,7 +62,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.access.intercept.AuthorizationFilter; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.firewall.FirewalledRequest; @@ -203,7 +202,7 @@ public class SecurityManagedConfiguration { .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); } - MDCHandler.Filter.addLoggingFilter(http); + MdcHandler.Filter.addMdcFilter(http); return http.build(); } @@ -320,7 +319,7 @@ public class SecurityManagedConfiguration { .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); } - MDCHandler.Filter.addLoggingFilter(http); + MdcHandler.Filter.addMdcFilter(http); return http.build(); } @@ -453,7 +452,7 @@ public class SecurityManagedConfiguration { httpSecurityCustomizer.customize(http); } - MDCHandler.Filter.addLoggingFilter(http); + MdcHandler.Filter.addMdcFilter(http); return http.build(); } diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MDCHandler.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java similarity index 63% rename from hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MDCHandler.java rename to hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java index 6e975636e..1d239da6e 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MDCHandler.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/MdcHandler.java @@ -30,36 +30,34 @@ import java.util.Objects; import java.util.concurrent.Callable; @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MDCHandler { +public class MdcHandler { public static String MDC_KEY_TENANT = "tenant"; public static String MDC_KEY_USER = "user"; - private static final MDCHandler SINGLETON = new MDCHandler(); + private static final MdcHandler SINGLETON = new MdcHandler(); @Value("${hawkbit.logging.mdchandler.enabled:true}") private boolean mdcEnabled; @Autowired(required = false) private SpringSecurityAuditorAware springSecurityAuditorAware = new SpringSecurityAuditorAware(); - @Autowired(required = false) - private SystemSecurityContext securityContext; /** * @return The holder singleton instance. */ - public static MDCHandler getInstance() { + public static MdcHandler getInstance() { return SINGLETON; } /** - * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user in the MDC context. + * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. * * @param the return type * @param callable the callable to execute * @return the result * @throws Exception if thrown by the callable */ - public T withLogging(final Callable callable) throws Exception { + public T callWithAuth(final Callable callable) throws Exception { if (!mdcEnabled) { return callable.call(); } @@ -76,30 +74,25 @@ public class MDCHandler { tenant = null; } - final String currentTenant = MDC.get(MDC_KEY_TENANT); - if (Objects.equals(currentTenant, tenant)) { - return putUserAndCall(callable); - } else { - put(MDC_KEY_TENANT, tenant); - try { - return putUserAndCall(callable); - } finally { - put(MDC_KEY_TENANT, currentTenant); - } - } + final String user = springSecurityAuditorAware + .getCurrentAuditor() + .filter(username -> !username.equals("system")) // null and system are the same - system user + .orElse(null); + + return callWithTenantAndUser0(callable, tenant, user); } /** - * With logging throwing Runtime Exception (withLoggingRE). Calls the {@link #withLogging(Callable)} method and - * wraps any catchable exception into a {@link RuntimeException}. + * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. + * Calls the {@link #callWithAuth(Callable)} method and wraps any catchable exception into a {@link RuntimeException}. * * @param the return type * @param callable the callable to execute * @return the result */ - public T withLoggingRE(final Callable callable) { + public T callWithAuthRE(final Callable callable) { try { - return withLogging(callable); + return callWithAuth(callable); } catch (final RuntimeException re) { throw re; } catch (final Exception e) { @@ -107,12 +100,58 @@ public class MDCHandler { } } - private T putUserAndCall(final Callable callable) throws Exception { - final String user = springSecurityAuditorAware - .getCurrentAuditor() - .filter(username -> !username.equals("system")) // null and system are the same - system user - .orElse(null); + /** + * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user in the MDC context. + * + * @param the return type + * @param callable the callable to execute + * @param tenant the tenant to set in the MDC context + * @param user the user to set in the MDC context + * @return the result + */ + public T callWithTenantAndUser(final Callable callable, final String tenant, final String user) throws Exception { + if (!mdcEnabled) { + return callable.call(); + } + return callWithTenantAndUser0(callable, tenant, user); + } + + /** + * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. + * Calls the {@link #callWithTenantAndUser(Callable, String, String)} method and wraps any catchable exception into a {@link RuntimeException}. + * + * @param the return type + * @param callable the callable to execute + * @param tenant the tenant to set in the MDC context + * @param user the user to set in the MDC context + * @return the result + */ + public T callWithTenantAndUserRE(final Callable callable, final String tenant, final String user) { + try { + return callWithTenantAndUser(callable, tenant, user); + } catch (final RuntimeException re) { + throw re; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + private static T callWithTenantAndUser0(final Callable callable, final String tenant, final String user) throws Exception { + final String currentTenant = MDC.get(MDC_KEY_TENANT); + if (Objects.equals(currentTenant, tenant)) { + return callWithUser(callable, user); + } else { + put(MDC_KEY_TENANT, tenant); + try { + return callWithUser(callable, user); + } finally { + put(MDC_KEY_TENANT, currentTenant); + } + } + } + + private static T callWithUser(final Callable callable, final String user) throws Exception { final String currentUser = MDC.get(MDC_KEY_USER); if (Objects.equals(currentUser, user)) { return callable.call(); @@ -137,17 +176,17 @@ public class MDCHandler { @NoArgsConstructor(access = AccessLevel.PRIVATE) public static class Filter { - public static void addLoggingFilter(final HttpSecurity httpSecurity) { + public static void addMdcFilter(final HttpSecurity httpSecurity) { httpSecurity.addFilterBefore(new OncePerRequestFilter() { - private final MDCHandler mdcFilter = MDCHandler.getInstance(); + private final MdcHandler mdcFilter = MdcHandler.getInstance(); @Override protected void doFilterInternal( final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) throws ServletException, IOException { try { - mdcFilter.withLogging(() -> { + mdcFilter.callWithAuth(() -> { filterChain.doFilter(request, response); return null; }); diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java index 78fe5d359..aea434a2c 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java @@ -142,7 +142,7 @@ public class SecurityContextTenantAware implements ContextAware { } else { SecurityContextHolder.setContext(securityContext); try { - return MDCHandler.getInstance().withLoggingRE(supplier::get); + return MdcHandler.getInstance().callWithAuthRE(supplier::get); } finally { SecurityContextHolder.setContext(originalContext); } @@ -153,7 +153,7 @@ public class SecurityContextTenantAware implements ContextAware { final SecurityContext currentContext = SecurityContextHolder.getContext(); SystemSecurityContext.setSystemContext(currentContext); try { - return MDCHandler.getInstance().withLoggingRE(tenantRunner::run); + return MdcHandler.getInstance().callWithAuthRE(tenantRunner::run); } finally { SecurityContextHolder.setContext(currentContext); } diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java index ca55f85dd..9628a5a11 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java @@ -110,7 +110,7 @@ public class SystemSecurityContext { log.debug("Entering system code execution"); return tenantAware.runAsTenant(tenant, () -> { setSystemContext(SecurityContextHolder.getContext()); - return MDCHandler.getInstance().withLoggingRE(callable); + return MdcHandler.getInstance().callWithAuthRE(callable); }); } finally { SecurityContextHolder.setContext(oldContext); @@ -139,7 +139,7 @@ public class SystemSecurityContext { try { return tenantAware.runAsTenant(tenant, () -> { setCustomSecurityContext(tenant, oldContext.getAuthentication().getPrincipal(), authorities); - return MDCHandler.getInstance().withLoggingRE(callable); + return MdcHandler.getInstance().callWithAuthRE(callable); }); } finally { SecurityContextHolder.setContext(oldContext);