Fine-grained permissions (#2535)
* Fine-grained permissions Adds support for permissions of type <permission>(/<rsql filter scope>) Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com> * Apply review fixes --------- Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TENANT_CONFIGURATION;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
||||
|
||||
@@ -94,7 +95,6 @@ import org.springframework.test.context.TestPropertySource;
|
||||
@WithUser(principal = "bumlux", allSpPermissions = true, authorities = { CONTROLLER_ROLE, SYSTEM_ROLE })
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@ContextConfiguration(classes = { TestConfiguration.class })
|
||||
//@Import(TestChannelBinderConfiguration.class)
|
||||
// destroy the context after each test class because otherwise we get problem when context is
|
||||
// refreshed we e.g. get two instances of CacheManager which leads to very strange test failures.
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
|
||||
@@ -176,7 +176,7 @@ public abstract class AbstractIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected TestdataFactory testdataFactory;
|
||||
@Autowired
|
||||
@Autowired(required = false)
|
||||
protected ServiceMatcher serviceMatcher;
|
||||
@Autowired
|
||||
protected ApplicationEventPublisher eventPublisher;
|
||||
@@ -203,21 +203,21 @@ public abstract class AbstractIntegrationTest {
|
||||
final String description = "Updated description.";
|
||||
|
||||
osType = SecurityContextSwitch
|
||||
.runAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_OS));
|
||||
osType = SecurityContextSwitch.runAsPrivileged(() -> softwareModuleTypeManagement
|
||||
.callAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_OS));
|
||||
osType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement
|
||||
.update(entityFactory.softwareModuleType().update(osType.getId()).description(description)));
|
||||
|
||||
appType = SecurityContextSwitch.runAsPrivileged(
|
||||
appType = SecurityContextSwitch.callAsPrivileged(
|
||||
() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_APP, Integer.MAX_VALUE));
|
||||
appType = SecurityContextSwitch.runAsPrivileged(() -> softwareModuleTypeManagement
|
||||
appType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement
|
||||
.update(entityFactory.softwareModuleType().update(appType.getId()).description(description)));
|
||||
|
||||
runtimeType = SecurityContextSwitch
|
||||
.runAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_RT));
|
||||
runtimeType = SecurityContextSwitch.runAsPrivileged(() -> softwareModuleTypeManagement
|
||||
.callAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_RT));
|
||||
runtimeType = SecurityContextSwitch.callAsPrivileged(() -> softwareModuleTypeManagement
|
||||
.update(entityFactory.softwareModuleType().update(runtimeType.getId()).description(description)));
|
||||
|
||||
standardDsType = SecurityContextSwitch.runAsPrivileged(() -> testdataFactory.findOrCreateDefaultTestDsType());
|
||||
standardDsType = SecurityContextSwitch.callAsPrivileged(() -> testdataFactory.findOrCreateDefaultTestDsType());
|
||||
|
||||
// publish the reset counter market event to reset the counters after
|
||||
// setup. The setup is transparent by the test and its @ExpectedEvent
|
||||
@@ -267,6 +267,7 @@ public abstract class AbstractIntegrationTest {
|
||||
private static final Duration AT_LEAST = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.atLeastMs", 5));
|
||||
private static final Duration POLL_INTERVAL = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.pollIntervalMs", 10));
|
||||
private static final Duration TIMEOUT = Duration.ofMillis(Integer.getInteger("hawkbit.it.rest.await.timeoutMs", 200));
|
||||
|
||||
// default wait condition factory
|
||||
protected ConditionFactory await() {
|
||||
return Awaitility.await().atLeast(AT_LEAST).pollInterval(POLL_INTERVAL).atMost(TIMEOUT);
|
||||
@@ -413,7 +414,11 @@ public abstract class AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
protected boolean isConfirmationFlowActive() {
|
||||
return tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.USER_CONFIRMATION_ENABLED, Boolean.class).getValue();
|
||||
return SecurityContextSwitch.getAs(
|
||||
SecurityContextSwitch.withUser("as_system", READ_TENANT_CONFIGURATION),
|
||||
() -> tenantConfigurationManagement
|
||||
.getConfigurationValue(TenantConfigurationKey.USER_CONFIRMATION_ENABLED, Boolean.class)
|
||||
.getValue());
|
||||
}
|
||||
|
||||
protected Long getOsModule(final DistributionSet ds) {
|
||||
|
||||
@@ -25,7 +25,7 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener
|
||||
|
||||
@Override
|
||||
public void afterTestMethod(final TestContext testContext) throws Exception {
|
||||
SecurityContextSwitch.runAsPrivileged(() -> {
|
||||
SecurityContextSwitch.callAsPrivileged(() -> {
|
||||
final ApplicationContext applicationContext = testContext.getApplicationContext();
|
||||
new JpaTestRepositoryManagement(applicationContext.getBean(TenantAwareCacheManager.class),
|
||||
applicationContext.getBean(SystemSecurityContext.class),
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -35,12 +36,12 @@ public class SecurityContextSwitch {
|
||||
private static final WithUser PRIVILEDGED_USER =
|
||||
createWithUser("bumlux", DEFAULT_TENANT, false, true, false, "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE");
|
||||
|
||||
public static <T> T runAsPrivileged(final Callable<T> callable) throws Exception {
|
||||
public static <T> T callAsPrivileged(final Callable<T> callable) throws Exception {
|
||||
createTenant(DEFAULT_TENANT);
|
||||
return runAs(PRIVILEDGED_USER, callable);
|
||||
return callAs(PRIVILEDGED_USER, callable);
|
||||
}
|
||||
|
||||
public static <T> T runAs(final WithUser withUser, final Callable<T> callable) throws Exception {
|
||||
public static <T> T callAs(final WithUser withUser, final Callable<T> callable) throws Exception {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
setSecurityContext(withUser);
|
||||
if (withUser.autoCreateTenant()) {
|
||||
@@ -53,6 +54,23 @@ public class SecurityContextSwitch {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T getAs(final WithUser withUser, final Supplier<T> supplier) {
|
||||
try {
|
||||
return callAs(withUser, supplier::get);
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalStateException("Failed to handle all rollouts", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runAs(final WithUser withUser, final Runnable runnable) {
|
||||
getAs(withUser, (Supplier<? extends Object>) () -> {
|
||||
runnable.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static WithUser withController(final String principal, final String... authorities) {
|
||||
return withUserAndTenant(principal, DEFAULT_TENANT, true, false, true, authorities);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.test.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
@@ -1018,7 +1019,7 @@ public class TestdataFactory {
|
||||
groupSize, confirmationRequired, conditions, dynamicRolloutGroupTemplate);
|
||||
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutHandler.handleAll();
|
||||
rolloutHandleAll();
|
||||
|
||||
return rolloutManagement.get(rollout.getId()).get();
|
||||
}
|
||||
@@ -1127,9 +1128,9 @@ public class TestdataFactory {
|
||||
public Rollout createSoftDeletedRollout(final String prefix) {
|
||||
final Rollout newRollout = createRollout(prefix);
|
||||
rolloutManagement.start(newRollout.getId());
|
||||
rolloutHandler.handleAll();
|
||||
rolloutHandleAll();
|
||||
rolloutManagement.delete(newRollout.getId());
|
||||
rolloutHandler.handleAll();
|
||||
rolloutHandleAll();
|
||||
return newRollout;
|
||||
}
|
||||
|
||||
@@ -1247,17 +1248,20 @@ public class TestdataFactory {
|
||||
}
|
||||
|
||||
private Action sendUpdateActionStatusToTarget(final Status status, final Action updActA, final Collection<String> msgs) {
|
||||
return controllerManagement.addUpdateActionStatus(
|
||||
entityFactory.actionStatus().create(updActA.getId()).status(status).messages(msgs));
|
||||
return controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(updActA.getId()).status(status).messages(msgs));
|
||||
}
|
||||
|
||||
private Rollout startAndReloadRollout(final Rollout rollout) {
|
||||
rolloutManagement.start(rollout.getId());
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutHandler.handleAll();
|
||||
rolloutHandleAll();
|
||||
return reloadRollout(rollout);
|
||||
}
|
||||
|
||||
private void rolloutHandleAll() {
|
||||
SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("system", SYSTEM_ROLE), rolloutHandler::handleAll);
|
||||
}
|
||||
|
||||
private Rollout reloadRollout(final Rollout rollout) {
|
||||
return rolloutManagement.get(rollout.getId()).orElseThrow(NoSuchElementException::new);
|
||||
}
|
||||
|
||||
@@ -79,3 +79,6 @@ hawkbit.server.security.dos.maxActionsPerTarget=20
|
||||
# Quota - END
|
||||
|
||||
# Properties that are managed by autoconfigure module at runtime and not available during test - END
|
||||
|
||||
# disable spring cloud bus for tests
|
||||
spring.cloud.bus.enabled=false
|
||||
Reference in New Issue
Block a user