Remove the ROLE_CONTROLLER_ANONYMOUS (#2948)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2026-03-05 10:01:43 +02:00
committed by GitHub
parent b38df5b512
commit 7a642f564e
8 changed files with 28 additions and 53 deletions

View File

@@ -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";

View File

@@ -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 + "')";
} }

View File

@@ -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());

View File

@@ -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);
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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);