Add fine grained sm/ds type permission (#2649)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -41,7 +41,7 @@ public interface DistributionSetTypeManagement<T extends DistributionSetType>
|
||||
|
||||
@Override
|
||||
default String permissionGroup() {
|
||||
return SpPermission.DISTRIBUTION_SET;
|
||||
return SpPermission.DISTRIBUTION_SET_TYPE;
|
||||
}
|
||||
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
||||
|
||||
@@ -35,7 +35,7 @@ public interface SoftwareModuleTypeManagement<T extends SoftwareModuleType>
|
||||
|
||||
@Override
|
||||
default String permissionGroup() {
|
||||
return SpPermission.SOFTWARE_MODULE;
|
||||
return SpPermission.SOFTWARE_MODULE_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,19 +46,17 @@ public interface SystemManagement {
|
||||
Page<String> findTenants(@NotNull Pageable pageable);
|
||||
|
||||
/**
|
||||
* Runs consumer for each teant as
|
||||
* Runs consumer for each tenant as
|
||||
* {@link TenantAware#runAsTenant(String, org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner)}
|
||||
* sliently (i.e. exceptions will be logged but operations will continue for
|
||||
* further tenants).
|
||||
* silently (i.e. exceptions will be logged but operations will continue for further tenants).
|
||||
*
|
||||
* @param consumer to run as teanant
|
||||
* @param consumer to run as tenant
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||
void forEachTenant(Consumer<String> consumer);
|
||||
|
||||
/**
|
||||
* Calculated system usage statistics, both overall for the entire system
|
||||
* and per tenant;
|
||||
* Calculated system usage statistics, both overall for the entire system and per tenant;
|
||||
*
|
||||
* @return SystemUsageReport of the current system
|
||||
*/
|
||||
|
||||
@@ -61,7 +61,7 @@ public interface Target extends NamedEntity, Identifiable<Long> {
|
||||
|
||||
/**
|
||||
* @return the securityToken if the current security context contains the necessary permission
|
||||
* {@link org.eclipse.hawkbit.im.authentication.SpPermission#READ_TARGET_SEC_TOKEN}
|
||||
* {@link org.eclipse.hawkbit.im.authentication.SpPermission#READ_TARGET_SECURITY_TOKEN}
|
||||
* or the current context is executed as system code, otherwise {@code null}.
|
||||
*/
|
||||
String getSecurityToken();
|
||||
|
||||
@@ -9,10 +9,17 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields;
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeFields;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -26,18 +33,36 @@ public class DefaultAccessControllerConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target.enabled", havingValue = "true", matchIfMissing = true)
|
||||
AccessController<JpaTarget> targetAccessController() {
|
||||
return new DefaultAccessController<>(TargetFields.class, "TARGET");
|
||||
return new DefaultAccessController<>(TargetFields.class, SpPermission.TARGET);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target-type.enabled", havingValue = "true", matchIfMissing = true)
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target-type.enabled", havingValue = "true")
|
||||
AccessController<JpaTargetType> targetTypeAccessController() {
|
||||
return new DefaultAccessController<>(TargetTypeFields.class, "TARGET_TYPE");
|
||||
return new DefaultAccessController<>(TargetTypeFields.class, SpPermission.TARGET_TYPE);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.software-module.enabled", havingValue = "true", matchIfMissing = true)
|
||||
AccessController<JpaSoftwareModule> softwareModuleAccessController() {
|
||||
return new DefaultAccessController<>(SoftwareModuleFields.class, SpPermission.SOFTWARE_MODULE);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.software-module-type.enabled", havingValue = "true")
|
||||
AccessController<JpaSoftwareModuleType> softwareModuleTypeAccessController() {
|
||||
return new DefaultAccessController<>(SoftwareModuleTypeFields.class, SpPermission.SOFTWARE_MODULE_TYPE);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.distribution-set.enabled", havingValue = "true", matchIfMissing = true)
|
||||
AccessController<JpaDistributionSet> distributionSetAccessController() {
|
||||
return new DefaultAccessController<>(DistributionSetFields.class, "DISTRIBUTION_SET");
|
||||
return new DefaultAccessController<>(DistributionSetFields.class, SpPermission.DISTRIBUTION_SET);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.distribution-set-type.enabled", havingValue = "true")
|
||||
AccessController<JpaDistributionSetType> distributionSetTypeAccessController() {
|
||||
return new DefaultAccessController<>(DistributionSetTypeFields.class, SpPermission.DISTRIBUTION_SET_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.PollingTime;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
@@ -249,9 +248,9 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
if (AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY.equalsIgnoreCase(configurationKeyName)) {
|
||||
final SystemSecurityContext systemSecurityContext = SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
|
||||
if (!systemSecurityContext.isCurrentThreadSystemCode() &&
|
||||
!systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SEC_TOKEN)) {
|
||||
!systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SECURITY_TOKEN)) {
|
||||
throw new InsufficientPermissionException(
|
||||
"Can't read gateway security token! " + SpPermission.READ_GATEWAY_SEC_TOKEN + " is required!");
|
||||
"Can't read gateway security token! " + SpPermission.READ_GATEWAY_SECURITY_TOKEN + " is required!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Target, EventAw
|
||||
@Override
|
||||
public String getSecurityToken() {
|
||||
final SystemSecurityContext systemSecurityContext = SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
|
||||
if (systemSecurityContext.isCurrentThreadSystemCode() || systemSecurityContext.hasPermission(SpPermission.READ_TARGET_SEC_TOKEN)) {
|
||||
if (systemSecurityContext.isCurrentThreadSystemCode() || systemSecurityContext.hasPermission(SpPermission.READ_TARGET_SECURITY_TOKEN)) {
|
||||
return securityToken;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -31,12 +31,14 @@ import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Feature: Component Tests - Access Control<br/>
|
||||
* Story: Test Target Type Access Controller
|
||||
*/
|
||||
@ContextConfiguration(classes = { DefaultAccessControllerConfiguration.class })
|
||||
@TestPropertySource(properties = { "hawkbit.acm.access-controller.target-type.enabled=true" })
|
||||
class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
/**
|
||||
@@ -92,8 +94,8 @@ class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
DELETE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
DELETE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
// delete the manageableTargetType
|
||||
targetTypeManagement.delete(manageableTargetType.getId());
|
||||
|
||||
@@ -113,8 +115,8 @@ class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
UPDATE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
UPDATE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
// update the manageableTargetType
|
||||
targetTypeManagement.update(Update.builder().id(manageableTargetType.getId())
|
||||
.name(manageableTargetType.getName() + "/new").description("newDesc").build());
|
||||
|
||||
@@ -139,7 +139,7 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest<
|
||||
|
||||
// retrieve security token only with READ_TARGET_SEC_TOKEN permission
|
||||
final String securityTokenWithReadPermission = SecurityContextSwitch.getAs(
|
||||
SecurityContextSwitch.withUser("OnlyTargetReadPermission", SpPermission.READ_TARGET_SEC_TOKEN),
|
||||
SecurityContextSwitch.withUser("OnlyTargetReadPermission", SpPermission.READ_TARGET_SECURITY_TOKEN),
|
||||
createdTarget::getSecurityToken);
|
||||
// retrieve security token only with ROLE_TARGET_ADMIN permission
|
||||
final String securityTokenWithTargetAdminPermission = SecurityContextSwitch.getAs(
|
||||
|
||||
@@ -108,8 +108,7 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
||||
*/
|
||||
@Test
|
||||
@WithUser(tenantId = "mytenant", autoCreateTenant = false, allSpPermissions = true)
|
||||
void getTenanatMetdata() throws Exception {
|
||||
|
||||
void getTenantMetdata() throws Exception {
|
||||
// logged in tenant mytenant - check if tenant default data is
|
||||
// autogenerated
|
||||
assertThat(distributionSetTypeManagement.findAll(PAGE)).isEmpty();
|
||||
|
||||
Reference in New Issue
Block a user