Implement JSON security context serializer (new default) - smaller info and human readable (#2652)
keeps backward compatibility by being able to fallback to JAVA_SERIALIZATION + fix DMF messages with status code Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -10,22 +10,31 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.security.SecurityContextSerializer.JSON_SERIALIZATION;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.eclipse.hawkbit.ContextAware;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
@@ -35,14 +44,16 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
*/
|
||||
class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private static final List<String> AUTHORITIES = SpPermission.getAllAuthorities();
|
||||
|
||||
@Autowired
|
||||
AutoAssignExecutor autoAssignExecutor;
|
||||
|
||||
@Autowired
|
||||
ContextAware contextAware;
|
||||
|
||||
private static final SecurityContextSerializer SECURITY_CONTEXT_SERIALIZER =
|
||||
SecurityContextSerializer.JAVA_SERIALIZATION;
|
||||
@Autowired
|
||||
AuditorAware<String> auditorAware;
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
@@ -55,13 +66,12 @@ class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void verifyAcmContextIsPersistedInCreatedRollout() {
|
||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
final SecurityContext securityContext = createContext(0);
|
||||
assertThat(securityContext).isNotNull();
|
||||
|
||||
final Rollout exampleRollout = testdataFactory.createRollout();
|
||||
final Rollout exampleRollout = runInContext(securityContext, testdataFactory::createRollout);
|
||||
assertThat(exampleRollout.getAccessControlContext())
|
||||
.hasValueSatisfying(ctx ->
|
||||
assertThat(SECURITY_CONTEXT_SERIALIZER.deserialize(ctx)).isEqualTo(securityContext));
|
||||
.hasValueSatisfying(ctx -> assertEssentialEquals(JSON_SERIALIZATION.deserialize(ctx), securityContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,12 +79,11 @@ class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void verifyContextIsReusedWhenHandlingRollout() {
|
||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
assertThat(securityContext).isNotNull();
|
||||
final SecurityContext securityContext = createContext(1);
|
||||
|
||||
// testdataFactory#createRollout will trigger a rollout handling
|
||||
testdataFactory.createRollout();
|
||||
verify(contextAware).runInContext(eq(SECURITY_CONTEXT_SERIALIZER.serialize(securityContext)), any(Runnable.class));
|
||||
runInContext(securityContext, testdataFactory::createRollout);
|
||||
verify(contextAware).runInContext(eq(JSON_SERIALIZATION.serialize(securityContext)), any(Runnable.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,13 +91,12 @@ class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void verifyContextIsPersistedInActiveAutoAssignment() {
|
||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
assertThat(securityContext).isNotNull();
|
||||
final SecurityContext securityContext = createContext(2);
|
||||
|
||||
final TargetFilterQuery targetFilterQuery = testdataFactory.createTargetFilterWithTargetsAndActiveAutoAssignment();
|
||||
final TargetFilterQuery targetFilterQuery =
|
||||
runInContext(securityContext, testdataFactory::createTargetFilterWithTargetsAndActiveAutoAssignment);
|
||||
assertThat(targetFilterQuery.getAccessControlContext())
|
||||
.hasValueSatisfying(ctx ->
|
||||
assertThat(SECURITY_CONTEXT_SERIALIZER.deserialize(ctx)).isEqualTo(securityContext));
|
||||
.hasValueSatisfying(ctx -> assertEssentialEquals(JSON_SERIALIZATION.deserialize(ctx), securityContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,12 +104,14 @@ class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void verifyContextIsReusedWhenCheckingForAutoAssignmentAllTargets() {
|
||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
assertThat(securityContext).isNotNull();
|
||||
final SecurityContext securityContext = createContext(3);
|
||||
|
||||
testdataFactory.createTargetFilterWithTargetsAndActiveAutoAssignment();
|
||||
autoAssignExecutor.checkAllTargets();
|
||||
verify(contextAware).runInContext(eq(SECURITY_CONTEXT_SERIALIZER.serialize(securityContext)), any(Runnable.class));
|
||||
runInContext(securityContext, testdataFactory::createTargetFilterWithTargetsAndActiveAutoAssignment);
|
||||
runInContext(securityContext, () -> {
|
||||
autoAssignExecutor.checkAllTargets();
|
||||
return null;
|
||||
});
|
||||
verify(contextAware).runInContext(eq(JSON_SERIALIZATION.serialize(securityContext)), any(Runnable.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,12 +119,52 @@ class ContextAwareTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
void verifyContextIsReusedWhenCheckingForAutoAssignmentSingleTarget() {
|
||||
final SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
final SecurityContext securityContext = createContext(4);
|
||||
|
||||
runInContext(securityContext, testdataFactory::createTargetFilterWithTargetsAndActiveAutoAssignment);
|
||||
runInContext(securityContext, () -> {
|
||||
autoAssignExecutor.checkSingleTarget(targetManagement.findAll(Pageable.ofSize(1)).getContent().get(0).getControllerId());
|
||||
return null;
|
||||
});
|
||||
verify(contextAware).runInContext(eq(JSON_SERIALIZATION.serialize(securityContext)), any(Runnable.class));
|
||||
}
|
||||
|
||||
private static SecurityContext createContext(final int testId) {
|
||||
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
final UsernamePasswordAuthenticationToken userPassAuthentication = new UsernamePasswordAuthenticationToken(
|
||||
"user", null, AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList());
|
||||
final TenantAwareAuthenticationDetails details = new TenantAwareAuthenticationDetails("my_tenant_" + testId, false);
|
||||
userPassAuthentication.setDetails(details);
|
||||
securityContext.setAuthentication(userPassAuthentication);
|
||||
|
||||
assertThat(securityContext).isNotNull();
|
||||
|
||||
testdataFactory.createTargetFilterWithTargetsAndActiveAutoAssignment();
|
||||
autoAssignExecutor
|
||||
.checkSingleTarget(targetManagement.findAll(Pageable.ofSize(1)).getContent().get(0).getControllerId());
|
||||
verify(contextAware).runInContext(eq(SECURITY_CONTEXT_SERIALIZER.serialize(securityContext)), any(Runnable.class));
|
||||
return securityContext;
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private <T> T runInContext(final SecurityContext securityContext, final Callable<T> runnable) {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
try {
|
||||
return runnable.call();
|
||||
} finally {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertEssentialEquals(final SecurityContext sc1, final SecurityContext sc2) {
|
||||
assertThat(auditor(sc1)).hasToString(auditor(sc2));
|
||||
assertThat(sc1.getAuthentication().getAuthorities()).isEqualTo(sc2.getAuthentication().getAuthorities());
|
||||
assertThat(sc1.getAuthentication().isAuthenticated()).isEqualTo(sc2.getAuthentication().isAuthenticated());
|
||||
assertThat(sc1.getAuthentication().getDetails()).isEqualTo(sc2.getAuthentication().getDetails());
|
||||
}
|
||||
|
||||
private String auditor(final SecurityContext securityContext) {
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
try {
|
||||
return auditorAware.getCurrentAuditor().orElseThrow();
|
||||
} finally {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpRole;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
@@ -130,9 +129,8 @@ class SystemManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
private void createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets, final int updates) {
|
||||
final Random randomgen = new Random();
|
||||
final byte[] random = new byte[artifactSize];
|
||||
randomgen.nextBytes(random);
|
||||
RND.nextBytes(random);
|
||||
|
||||
for (int i = 0; i < tenants; i++) {
|
||||
final String tenantname = "TENANT" + i;
|
||||
|
||||
Reference in New Issue
Block a user