Remove the ROLE_CONTROLLER_ANONYMOUS (#2948)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -29,8 +29,6 @@ public final class SpRole {
|
|||||||
public static final String SYSTEM_ROLE = "ROLE_SYSTEM_CODE";
|
public static final String SYSTEM_ROLE = "ROLE_SYSTEM_CODE";
|
||||||
/** The role which contains in the spring security context in case a controller is authenticated */
|
/** The role which contains in the spring security context in case a controller is authenticated */
|
||||||
public static final String CONTROLLER_ROLE = "ROLE_CONTROLLER";
|
public static final String CONTROLLER_ROLE = "ROLE_CONTROLLER";
|
||||||
/** The role which contained in the spring security context in case that a controller is authenticated, but only as 'anonymous'. */
|
|
||||||
public static final String CONTROLLER_ROLE_ANONYMOUS = "ROLE_CONTROLLER_ANONYMOUS";
|
|
||||||
|
|
||||||
private static final String IMPLIES = " > ";
|
private static final String IMPLIES = " > ";
|
||||||
private static final String LINE_BREAK = "\n";
|
private static final String LINE_BREAK = "\n";
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public final class SpringEvalExpressions {
|
public final class SpringEvalExpressions {
|
||||||
|
|
||||||
public static final String IS_SYSTEM_CODE = "hasAuthority('ROLE_SYSTEM_CODE')";
|
public static final String IS_SYSTEM_CODE = "hasAuthority('" + SpRole.SYSTEM_ROLE + "')";
|
||||||
|
public static final String IS_CONTROLLER = "hasAuthority('" + SpRole.CONTROLLER_ROLE + "')";
|
||||||
|
|
||||||
public static final String PERMISSION_GROUP_PLACEHOLDER = "${permissionGroup}";
|
public static final String PERMISSION_GROUP_PLACEHOLDER = "${permissionGroup}";
|
||||||
// evaluated to <permission>_<permissionGroup> (e.g. CREATE_DISTRIBUTION_SET)
|
// evaluated to <permission>_<permissionGroup> (e.g. CREATE_DISTRIBUTION_SET)
|
||||||
@@ -44,6 +45,4 @@ public final class SpringEvalExpressions {
|
|||||||
public static final String HAS_READ_REPOSITORY = "hasPermission(#root, 'READ_${permissionGroup}')";
|
public static final String HAS_READ_REPOSITORY = "hasPermission(#root, 'READ_${permissionGroup}')";
|
||||||
public static final String HAS_UPDATE_REPOSITORY = "hasPermission(#root, 'UPDATE_${permissionGroup}')";
|
public static final String HAS_UPDATE_REPOSITORY = "hasPermission(#root, 'UPDATE_${permissionGroup}')";
|
||||||
public static final String HAS_DELETE_REPOSITORY = "hasPermission(#root, 'DELETE_${permissionGroup}')";
|
public static final String HAS_DELETE_REPOSITORY = "hasPermission(#root, 'DELETE_${permissionGroup}')";
|
||||||
|
|
||||||
public static final String IS_CONTROLLER = "hasAnyRole('" + SpRole.CONTROLLER_ROLE_ANONYMOUS + "', '" + SpRole.CONTROLLER_ROLE + "')";
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.ddi.rest.resource;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.eclipse.hawkbit.auth.SpPermission.TENANT_CONFIGURATION;
|
import static org.eclipse.hawkbit.auth.SpPermission.TENANT_CONFIGURATION;
|
||||||
import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE_ANONYMOUS;
|
import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE;
|
||||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs;
|
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs;
|
||||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs;
|
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs;
|
||||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController;
|
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController;
|
||||||
@@ -34,7 +34,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.auth.SpPermission;
|
import org.eclipse.hawkbit.auth.SpPermission;
|
||||||
@@ -131,13 +130,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId);
|
final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId);
|
||||||
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
|
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
|
||||||
// make a poll, audit information should not be changed, run as controller principal!
|
// make a poll, audit information should not be changed, run as controller principal!
|
||||||
callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
callAs(withController("controller", CONTROLLER_ROLE), () -> {
|
||||||
() -> {
|
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownTargetControllerId))
|
||||||
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownTargetControllerId))
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk());
|
||||||
.andExpect(status().isOk());
|
return null;
|
||||||
return null;
|
});
|
||||||
});
|
|
||||||
// verify that audit information has not changed
|
// verify that audit information has not changed
|
||||||
final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId);
|
final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId);
|
||||||
assertThat(targetVerify.getCreatedBy()).isEqualTo(findTargetByControllerID.getCreatedBy());
|
assertThat(targetVerify.getCreatedBy()).isEqualTo(findTargetByControllerID.getCreatedBy());
|
||||||
@@ -203,16 +201,14 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
|
||||||
@Expect(type = TenantConfigurationDeletedEvent.class, count = 1) })
|
@Expect(type = TenantConfigurationDeletedEvent.class, count = 1) })
|
||||||
void pollWithModifiedGlobalPollingTime() throws Exception {
|
void pollWithModifiedGlobalPollingTime() throws Exception {
|
||||||
withPollingTime("00:02:00", () -> callAs(
|
withPollingTime("00:02:00", () -> callAs(withUser("controller", CONTROLLER_ROLE), () -> {
|
||||||
withUser("controller", CONTROLLER_ROLE_ANONYMOUS),
|
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
|
||||||
() -> {
|
.andDo(MockMvcResultPrinter.print())
|
||||||
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
|
.andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(status().isOk())
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
return null;
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
}));
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -234,8 +230,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
});
|
});
|
||||||
|
|
||||||
withPollingTime("00:02:00, controllerid == 4711 -> 00:01:00, group == 'Europe' -> 00:05:05", () -> callAs(
|
withPollingTime("00:02:00, controllerid == 4711 -> 00:01:00, group == 'Europe' -> 00:05:05", () -> callAs(
|
||||||
withUser("controller", CONTROLLER_ROLE_ANONYMOUS),
|
withUser("controller", CONTROLLER_ROLE), () -> {
|
||||||
() -> {
|
|
||||||
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
|
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
@@ -381,13 +376,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final String knownControllerId1 = "0815";
|
final String knownControllerId1 = "0815";
|
||||||
final long create = System.currentTimeMillis();
|
final long create = System.currentTimeMillis();
|
||||||
// make a poll, audit information should be set on plug and play
|
// make a poll, audit information should be set on plug and play
|
||||||
callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
callAs(withController("controller", CONTROLLER_ROLE), () -> {
|
||||||
() -> {
|
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownControllerId1))
|
||||||
mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownControllerId1))
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andExpect(status().isOk());
|
||||||
.andExpect(status().isOk());
|
return null;
|
||||||
return null;
|
});
|
||||||
});
|
|
||||||
// verify
|
// verify
|
||||||
assertThat(targetManagement.getByControllerId(knownControllerId1)).satisfies(target -> {
|
assertThat(targetManagement.getByControllerId(knownControllerId1)).satisfies(target -> {
|
||||||
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString());
|
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString());
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
private static void setTenantSecurityContext(final String tenant) {
|
private static void setTenantSecurityContext(final String tenant) {
|
||||||
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
|
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
|
||||||
UUID.randomUUID().toString(), "AMQP-Controller",
|
UUID.randomUUID().toString(), "AMQP-Controller",
|
||||||
List.of(new SimpleGrantedAuthority(SpRole.CONTROLLER_ROLE_ANONYMOUS)));
|
List.of(new SimpleGrantedAuthority(SpRole.CONTROLLER_ROLE)));
|
||||||
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenant, true));
|
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenant, true));
|
||||||
setSecurityContext(authenticationToken);
|
setSecurityContext(authenticationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
package org.eclipse.hawkbit.repository.jpa.model;
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
|
|
||||||
import jakarta.persistence.Access;
|
import jakarta.persistence.Access;
|
||||||
import jakarta.persistence.AccessType;
|
import jakarta.persistence.AccessType;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
@@ -50,9 +48,6 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
|||||||
|
|
||||||
protected static final int USERNAME_FIELD_LENGTH = 64;
|
protected static final int USERNAME_FIELD_LENGTH = 64;
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Setter // should be used just for test purposes
|
@Setter // should be used just for test purposes
|
||||||
@Getter
|
@Getter
|
||||||
@Id
|
@Id
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
package org.eclipse.hawkbit.repository.jpa.model;
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
@@ -41,9 +40,6 @@ import org.eclipse.persistence.annotations.TenantDiscriminatorColumn;
|
|||||||
@Multitenant(MultitenantType.SINGLE_TABLE)
|
@Multitenant(MultitenantType.SINGLE_TABLE)
|
||||||
public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEntity implements TenantAwareBaseEntity {
|
public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEntity implements TenantAwareBaseEntity {
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Column(name = "tenant", nullable = false, insertable = false, updatable = false, length = 40)
|
@Column(name = "tenant", nullable = false, insertable = false, updatable = false, length = 40)
|
||||||
@Size(min = 1, max = 40)
|
@Size(min = 1, max = 40)
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -398,10 +398,6 @@ class ArtifactManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
SecurityContextSwitch.withUser("test_user", SpRole.CONTROLLER_ROLE),
|
SecurityContextSwitch.withUser("test_user", SpRole.CONTROLLER_ROLE),
|
||||||
() -> assertEqualFileContents(
|
() -> assertEqualFileContents(
|
||||||
artifactManagement.getArtifactStream(artifact.getSha1Hash(), smOs.getId(), smOs.isEncrypted()), randomBytes));
|
artifactManagement.getArtifactStream(artifact.getSha1Hash(), smOs.getId(), smOs.isEncrypted()), randomBytes));
|
||||||
SecurityContextSwitch.runAs(
|
|
||||||
SecurityContextSwitch.withUser("test_user", SpRole.CONTROLLER_ROLE_ANONYMOUS),
|
|
||||||
() -> assertEqualFileContents(
|
|
||||||
artifactManagement.getArtifactStream(artifact.getSha1Hash(), smOs.getId(), smOs.isEncrypted()), randomBytes));
|
|
||||||
SecurityContextSwitch.runAs(
|
SecurityContextSwitch.runAs(
|
||||||
SecurityContextSwitch.withUser("test_user", SpPermission.READ_PREFIX + SpPermission.SOFTWARE_MODULE),
|
SecurityContextSwitch.withUser("test_user", SpPermission.READ_PREFIX + SpPermission.SOFTWARE_MODULE),
|
||||||
() -> assertThatExceptionOfType(InsufficientPermissionException.class)
|
() -> assertThatExceptionOfType(InsufficientPermissionException.class)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||||
import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE;
|
import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE;
|
||||||
import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE_ANONYMOUS;
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
|
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
|
||||||
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX;
|
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX;
|
||||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
||||||
@@ -108,7 +107,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final int allowedAttributes = quotaManagement.getMaxAttributeEntriesPerTarget();
|
final int allowedAttributes = quotaManagement.getMaxAttributeEntriesPerTarget();
|
||||||
testdataFactory.createTarget(controllerId);
|
testdataFactory.createTarget(controllerId);
|
||||||
|
|
||||||
final WithUser withController = SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS);
|
final WithUser withController = SecurityContextSwitch.withController("controller", CONTROLLER_ROLE);
|
||||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||||
.isThrownBy(() -> runAs(withController, () -> writeAttributes(controllerId, allowedAttributes + 1, "key", "value")))
|
.isThrownBy(() -> runAs(withController, () -> writeAttributes(controllerId, allowedAttributes + 1, "key", "value")))
|
||||||
.withMessageContaining("" + allowedAttributes);
|
.withMessageContaining("" + allowedAttributes);
|
||||||
@@ -184,7 +183,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final Long actionId = createTargetAndAssignDs();
|
final Long actionId = createTargetAndAssignDs();
|
||||||
|
|
||||||
SecurityContextSwitch
|
SecurityContextSwitch
|
||||||
.getAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
.getAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE), () -> {
|
||||||
// Fails as one entry is already in there from the assignment
|
// Fails as one entry is already in there from the assignment
|
||||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||||
.isThrownBy(() -> writeStatus(actionId, allowStatusEntries))
|
.isThrownBy(() -> writeStatus(actionId, allowStatusEntries))
|
||||||
@@ -1161,9 +1160,7 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final String controllerId = "test123";
|
final String controllerId = "test123";
|
||||||
final Target target = testdataFactory.createTarget(controllerId);
|
final Target target = testdataFactory.createTarget(controllerId);
|
||||||
|
|
||||||
SecurityContextSwitch.getAs(SecurityContextSwitch.withController(
|
SecurityContextSwitch.getAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE, SpPermission.READ_TARGET), () -> {
|
||||||
"controller",
|
|
||||||
CONTROLLER_ROLE_ANONYMOUS, SpPermission.READ_TARGET), () -> {
|
|
||||||
addAttributeAndVerify(controllerId);
|
addAttributeAndVerify(controllerId);
|
||||||
addSecondAttributeAndVerify(controllerId);
|
addSecondAttributeAndVerify(controllerId);
|
||||||
updateAttributeAndVerify(controllerId);
|
updateAttributeAndVerify(controllerId);
|
||||||
|
|||||||
Reference in New Issue
Block a user