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