Add fine grained sm/ds type permission (#2649)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -431,7 +431,7 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@WithUser(allSpPermissions = false, authorities = { SpPermission.READ_TARGET, SpPermission.CREATE_TARGET,
|
@WithUser(allSpPermissions = false, authorities = { SpPermission.READ_TARGET, SpPermission.CREATE_TARGET,
|
||||||
SpPermission.READ_TARGET_SEC_TOKEN })
|
SpPermission.READ_TARGET_SECURITY_TOKEN })
|
||||||
void securityTokenIsInResponseWithCorrectPermission() throws Exception {
|
void securityTokenIsInResponseWithCorrectPermission() throws Exception {
|
||||||
|
|
||||||
final String knownControllerId = "knownControllerId";
|
final String knownControllerId = "knownControllerId";
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ class MgmtTargetTypeResourceTest extends AbstractManagementApiIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
@WithUser(
|
@WithUser(
|
||||||
principal = "targetTypeTester", allSpPermissions = true,
|
principal = "targetTypeTester", allSpPermissions = true,
|
||||||
removeFromAllPermission = { SpPermission.READ_TARGET, SpPermission.READ_TARGET_TYPE })
|
removeFromAllPermission = {
|
||||||
|
SpPermission.CREATE_TARGET, SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET, SpPermission.DELETE_TARGET,
|
||||||
|
SpPermission.READ_TARGET_TYPE })
|
||||||
void getTargetTypesWithoutPermission() throws Exception {
|
void getTargetTypesWithoutPermission() throws Exception {
|
||||||
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON))
|
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ public class MgmtTenantManagementResourceTest extends AbstractManagementApiInteg
|
|||||||
|
|
||||||
// TODO - should be able to read with TENANT_CONFIGURATION but somehow here the role hierarchy doesn't play
|
// TODO - should be able to read with TENANT_CONFIGURATION but somehow here the role hierarchy doesn't play
|
||||||
// checked in mgmt / update server runtime PreAuthorizeEnabledTest
|
// checked in mgmt / update server runtime PreAuthorizeEnabledTest
|
||||||
callAs(withUser("tenant_admin", SpPermission.READ_TENANT_CONFIGURATION, SpPermission.READ_GATEWAY_SEC_TOKEN), () -> {
|
callAs(withUser("tenant_admin", SpPermission.READ_TENANT_CONFIGURATION, SpPermission.READ_GATEWAY_SECURITY_TOKEN), () -> {
|
||||||
mvc.perform(get(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs"))
|
mvc.perform(get(MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING + "/configs"))
|
||||||
.andDo(MockMvcResultPrinter.print())
|
.andDo(MockMvcResultPrinter.print())
|
||||||
.andDo(m -> System.out.println("-> 1: " + m.getResponse().getContentAsString()))
|
.andDo(m -> System.out.println("-> 1: " + m.getResponse().getContentAsString()))
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public interface DistributionSetTypeManagement<T extends DistributionSetType>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String permissionGroup() {
|
default String permissionGroup() {
|
||||||
return SpPermission.DISTRIBUTION_SET;
|
return SpPermission.DISTRIBUTION_SET_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public interface SoftwareModuleTypeManagement<T extends SoftwareModuleType>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String permissionGroup() {
|
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);
|
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)}
|
* {@link TenantAware#runAsTenant(String, org.eclipse.hawkbit.tenancy.TenantAware.TenantRunner)}
|
||||||
* sliently (i.e. exceptions will be logged but operations will continue for
|
* silently (i.e. exceptions will be logged but operations will continue for further tenants).
|
||||||
* further tenants).
|
|
||||||
*
|
*
|
||||||
* @param consumer to run as teanant
|
* @param consumer to run as tenant
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||||
void forEachTenant(Consumer<String> consumer);
|
void forEachTenant(Consumer<String> consumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculated system usage statistics, both overall for the entire system
|
* Calculated system usage statistics, both overall for the entire system and per tenant;
|
||||||
* and per tenant;
|
|
||||||
*
|
*
|
||||||
* @return SystemUsageReport of the current system
|
* @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
|
* @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}.
|
* or the current context is executed as system code, otherwise {@code null}.
|
||||||
*/
|
*/
|
||||||
String getSecurityToken();
|
String getSecurityToken();
|
||||||
|
|||||||
@@ -9,10 +9,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
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.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.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.TargetTypeFields;
|
import org.eclipse.hawkbit.repository.TargetTypeFields;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
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.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
@@ -26,18 +33,36 @@ public class DefaultAccessControllerConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target.enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.target.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
AccessController<JpaTarget> targetAccessController() {
|
AccessController<JpaTarget> targetAccessController() {
|
||||||
return new DefaultAccessController<>(TargetFields.class, "TARGET");
|
return new DefaultAccessController<>(TargetFields.class, SpPermission.TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@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() {
|
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
|
@Bean
|
||||||
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.distribution-set.enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(name = "hawkbit.acm.access-controller.distribution-set.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
AccessController<JpaDistributionSet> distributionSetAccessController() {
|
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.PollingTime;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
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.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
@@ -249,9 +248,9 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
|||||||
if (AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY.equalsIgnoreCase(configurationKeyName)) {
|
if (AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY.equalsIgnoreCase(configurationKeyName)) {
|
||||||
final SystemSecurityContext systemSecurityContext = SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
|
final SystemSecurityContext systemSecurityContext = SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
|
||||||
if (!systemSecurityContext.isCurrentThreadSystemCode() &&
|
if (!systemSecurityContext.isCurrentThreadSystemCode() &&
|
||||||
!systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SEC_TOKEN)) {
|
!systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SECURITY_TOKEN)) {
|
||||||
throw new InsufficientPermissionException(
|
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
|
@Override
|
||||||
public String getSecurityToken() {
|
public String getSecurityToken() {
|
||||||
final SystemSecurityContext systemSecurityContext = SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
|
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 securityToken;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -31,12 +31,14 @@ import org.eclipse.hawkbit.repository.model.TargetType;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Feature: Component Tests - Access Control<br/>
|
* Feature: Component Tests - Access Control<br/>
|
||||||
* Story: Test Target Type Access Controller
|
* Story: Test Target Type Access Controller
|
||||||
*/
|
*/
|
||||||
@ContextConfiguration(classes = { DefaultAccessControllerConfiguration.class })
|
@ContextConfiguration(classes = { DefaultAccessControllerConfiguration.class })
|
||||||
|
@TestPropertySource(properties = { "hawkbit.acm.access-controller.target-type.enabled=true" })
|
||||||
class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,8 +94,8 @@ class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
|||||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||||
|
|
||||||
runAs(withUser("user",
|
runAs(withUser("user",
|
||||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||||
DELETE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
DELETE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||||
// delete the manageableTargetType
|
// delete the manageableTargetType
|
||||||
targetTypeManagement.delete(manageableTargetType.getId());
|
targetTypeManagement.delete(manageableTargetType.getId());
|
||||||
|
|
||||||
@@ -113,8 +115,8 @@ class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
|||||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||||
|
|
||||||
runAs(withUser("user",
|
runAs(withUser("user",
|
||||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||||
UPDATE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
UPDATE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||||
// update the manageableTargetType
|
// update the manageableTargetType
|
||||||
targetTypeManagement.update(Update.builder().id(manageableTargetType.getId())
|
targetTypeManagement.update(Update.builder().id(manageableTargetType.getId())
|
||||||
.name(manageableTargetType.getName() + "/new").description("newDesc").build());
|
.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
|
// retrieve security token only with READ_TARGET_SEC_TOKEN permission
|
||||||
final String securityTokenWithReadPermission = SecurityContextSwitch.getAs(
|
final String securityTokenWithReadPermission = SecurityContextSwitch.getAs(
|
||||||
SecurityContextSwitch.withUser("OnlyTargetReadPermission", SpPermission.READ_TARGET_SEC_TOKEN),
|
SecurityContextSwitch.withUser("OnlyTargetReadPermission", SpPermission.READ_TARGET_SECURITY_TOKEN),
|
||||||
createdTarget::getSecurityToken);
|
createdTarget::getSecurityToken);
|
||||||
// retrieve security token only with ROLE_TARGET_ADMIN permission
|
// retrieve security token only with ROLE_TARGET_ADMIN permission
|
||||||
final String securityTokenWithTargetAdminPermission = SecurityContextSwitch.getAs(
|
final String securityTokenWithTargetAdminPermission = SecurityContextSwitch.getAs(
|
||||||
|
|||||||
@@ -108,8 +108,7 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@WithUser(tenantId = "mytenant", autoCreateTenant = false, allSpPermissions = true)
|
@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
|
// logged in tenant mytenant - check if tenant default data is
|
||||||
// autogenerated
|
// autogenerated
|
||||||
assertThat(distributionSetTypeManagement.findAll(PAGE)).isEmpty();
|
assertThat(distributionSetTypeManagement.findAll(PAGE)).isEmpty();
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ import lombok.NoArgsConstructor;
|
|||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class Hierarchy {
|
public class Hierarchy {
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
public static final String DEFAULT =
|
public static final String DEFAULT =
|
||||||
SpPermission.TARGET_HIERARCHY +
|
SpPermission.TARGET_HIERARCHY +
|
||||||
SpPermission.REPOSITORY_HIERARCHY +
|
SpPermission.REPOSITORY_HIERARCHY +
|
||||||
|
SpPermission.SOFTWARE_MODULE_HIERARCHY +
|
||||||
|
SpPermission.DISTRIBUTION_SET_HIERARCHY +
|
||||||
SpPermission.TENANT_CONFIGURATION_HIERARCHY +
|
SpPermission.TENANT_CONFIGURATION_HIERARCHY +
|
||||||
SpRole.DEFAULT_ROLE_HIERARCHY;
|
SpRole.DEFAULT_ROLE_HIERARCHY;
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.im.authentication;
|
package org.eclipse.hawkbit.im.authentication;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -46,7 +44,9 @@ public final class SpPermission {
|
|||||||
public static final String TARGET = "TARGET";
|
public static final String TARGET = "TARGET";
|
||||||
public static final String TARGET_TYPE = "TARGET_TYPE";
|
public static final String TARGET_TYPE = "TARGET_TYPE";
|
||||||
public static final String SOFTWARE_MODULE = "SOFTWARE_MODULE";
|
public static final String SOFTWARE_MODULE = "SOFTWARE_MODULE";
|
||||||
|
public static final String SOFTWARE_MODULE_TYPE = "SOFTWARE_MODULE_TYPE";
|
||||||
public static final String DISTRIBUTION_SET = "DISTRIBUTION_SET";
|
public static final String DISTRIBUTION_SET = "DISTRIBUTION_SET";
|
||||||
|
public static final String DISTRIBUTION_SET_TYPE = "DISTRIBUTION_SET_TYPE";
|
||||||
public static final String ROLLOUT = "ROLLOUT";
|
public static final String ROLLOUT = "ROLLOUT";
|
||||||
public static final String TENANT_CONFIGURATION = "TENANT_CONFIGURATION";
|
public static final String TENANT_CONFIGURATION = "TENANT_CONFIGURATION";
|
||||||
|
|
||||||
@@ -55,12 +55,10 @@ public final class SpPermission {
|
|||||||
public static final String UPDATE_TARGET = UPDATE_PREFIX + TARGET;
|
public static final String UPDATE_TARGET = UPDATE_PREFIX + TARGET;
|
||||||
public static final String DELETE_TARGET = DELETE_PREFIX + TARGET;
|
public static final String DELETE_TARGET = DELETE_PREFIX + TARGET;
|
||||||
/**
|
/**
|
||||||
* Permission to read the target security token. The security token is security
|
* Permission to read the target security token. The security token is security concerned and should be protected. So the combination
|
||||||
* concerned and should be protected. So the combination
|
* {@linkplain #READ_TARGET} and {@code READ_TARGET_SEC_TOKEN} is necessary to be able to read the security token of a target.
|
||||||
* {@linkplain #READ_TARGET} and {@code READ_TARGET_SEC_TOKEN} is necessary to
|
|
||||||
* be able to read the security token of a target.
|
|
||||||
*/
|
*/
|
||||||
public static final String READ_TARGET_SEC_TOKEN = READ_TARGET + "_SECURITY_TOKEN";
|
public static final String READ_TARGET_SECURITY_TOKEN = READ_TARGET + "_SECURITY_TOKEN";
|
||||||
|
|
||||||
public static final String READ_TARGET_TYPE = READ_PREFIX + TARGET_TYPE;
|
public static final String READ_TARGET_TYPE = READ_PREFIX + TARGET_TYPE;
|
||||||
public static final String UPDATE_TARGET_TYPE = UPDATE_PREFIX + TARGET_TYPE;
|
public static final String UPDATE_TARGET_TYPE = UPDATE_PREFIX + TARGET_TYPE;
|
||||||
@@ -73,21 +71,19 @@ public final class SpPermission {
|
|||||||
public static final String UPDATE_REPOSITORY = "UPDATE_REPOSITORY";
|
public static final String UPDATE_REPOSITORY = "UPDATE_REPOSITORY";
|
||||||
public static final String CREATE_REPOSITORY = "CREATE_REPOSITORY";
|
public static final String CREATE_REPOSITORY = "CREATE_REPOSITORY";
|
||||||
public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY";
|
public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY";
|
||||||
|
|
||||||
public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT";
|
public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission to read the tenant settings.
|
* Permission to read the tenant settings.
|
||||||
*/
|
*/
|
||||||
public static final String READ_TENANT_CONFIGURATION = READ_PREFIX + TENANT_CONFIGURATION;
|
public static final String READ_TENANT_CONFIGURATION = READ_PREFIX + TENANT_CONFIGURATION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission to read the gateway security token. The gateway security token is security
|
* Permission to read the gateway security token. The gateway security token is security
|
||||||
* concerned and should be protected. So in addition to {@linkplain #READ_TENANT_CONFIGURATION},
|
* concerned and should be protected. So in addition to {@linkplain #READ_TENANT_CONFIGURATION},
|
||||||
* {@code READ_GATEWAY_SEC_TOKEN} is necessary to read gateway security token. {@link #TENANT_CONFIGURATION}
|
* {@code READ_GATEWAY_SEC_TOKEN} is necessary to read gateway security token. {@link #TENANT_CONFIGURATION}
|
||||||
* implies both permissions - so it is sufficient to read the gateway security token.
|
* implies both permissions - so it is sufficient to read the gateway security token.
|
||||||
*/
|
*/
|
||||||
public static final String READ_GATEWAY_SEC_TOKEN = "READ_GATEWAY_SECURITY_TOKEN";
|
public static final String READ_GATEWAY_SECURITY_TOKEN = "READ_GATEWAY_SECURITY_TOKEN";
|
||||||
|
|
||||||
public static final String CREATE_ROLLOUT = CREATE_PREFIX + ROLLOUT;
|
public static final String CREATE_ROLLOUT = CREATE_PREFIX + ROLLOUT;
|
||||||
public static final String READ_ROLLOUT = READ_PREFIX + ROLLOUT;
|
public static final String READ_ROLLOUT = READ_PREFIX + ROLLOUT;
|
||||||
@@ -101,44 +97,81 @@ public final class SpPermission {
|
|||||||
/** Permission to administrate the system on a global, i.e. tenant independent scale. That includes the deletion of tenants. */
|
/** Permission to administrate the system on a global, i.e. tenant independent scale. That includes the deletion of tenants. */
|
||||||
public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN";
|
public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN";
|
||||||
|
|
||||||
public static final String TARGET_HIERARCHY = """
|
public static final String IMPLY_CREATE = " > " + CREATE_PREFIX;
|
||||||
CREATE_TARGET > CREATE_TARGET_TYPE
|
public static final String IMPLY_READ = " > " + READ_PREFIX;
|
||||||
READ_TARGET > READ_TARGET_TYPE
|
public static final String IMPLY_UPDATE = " > " + UPDATE_PREFIX;
|
||||||
UPDATE_TARGET > UPDATE_TARGET_TYPE
|
public static final String IMPLY_DELETE = " > " + DELETE_PREFIX;
|
||||||
DELETE_TARGET > DELETE_TARGET_TYPE
|
|
||||||
""";
|
|
||||||
public static final String REPOSITORY_HIERARCHY = """
|
|
||||||
CREATE_REPOSITORY > CREATE_DISTRIBUTION_SET
|
|
||||||
READ_REPOSITORY > READ_DISTRIBUTION_SET
|
|
||||||
UPDATE_REPOSITORY > UPDATE_DISTRIBUTION_SET
|
|
||||||
DELETE_REPOSITORY > DELETE_DISTRIBUTION_SET
|
|
||||||
CREATE_REPOSITORY > CREATE_SOFTWARE_MODULE
|
|
||||||
READ_REPOSITORY > READ_SOFTWARE_MODULE
|
|
||||||
UPDATE_REPOSITORY > UPDATE_SOFTWARE_MODULE
|
|
||||||
DELETE_REPOSITORY > DELETE_SOFTWARE_MODULE
|
|
||||||
""";
|
|
||||||
public static final String TENANT_CONFIGURATION_HIERARCHY = """
|
|
||||||
TENANT_CONFIGURATION > CREATE_TENANT_CONFIGURATION
|
|
||||||
TENANT_CONFIGURATION > READ_TENANT_CONFIGURATION
|
|
||||||
TENANT_CONFIGURATION > UPDATE_TENANT_CONFIGURATION
|
|
||||||
TENANT_CONFIGURATION > DELETE_TENANT_CONFIGURATION
|
|
||||||
TENANT_CONFIGURATION > READ_GATEWAY_SECURITY_TOKEN
|
|
||||||
""";
|
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
public static final String TARGET_HIERARCHY =
|
||||||
|
CREATE_TARGET + IMPLY_READ + TARGET_TYPE + "\n" +
|
||||||
|
READ_TARGET + IMPLY_READ + TARGET_TYPE + "\n" +
|
||||||
|
UPDATE_TARGET + IMPLY_READ + TARGET_TYPE + "\n" +
|
||||||
|
DELETE_TARGET + IMPLY_READ + TARGET_TYPE + "\n";
|
||||||
|
public static final String REPOSITORY_HIERARCHY =
|
||||||
|
CREATE_REPOSITORY + IMPLY_CREATE + SOFTWARE_MODULE + "\n" +
|
||||||
|
READ_REPOSITORY + IMPLY_READ + SOFTWARE_MODULE + "\n" +
|
||||||
|
UPDATE_REPOSITORY + IMPLY_UPDATE + SOFTWARE_MODULE + "\n" +
|
||||||
|
DELETE_REPOSITORY + IMPLY_DELETE + SOFTWARE_MODULE + "\n" +
|
||||||
|
CREATE_REPOSITORY + IMPLY_CREATE + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
READ_REPOSITORY + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
UPDATE_REPOSITORY + IMPLY_UPDATE + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
DELETE_REPOSITORY + IMPLY_DELETE + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
CREATE_REPOSITORY + IMPLY_CREATE + DISTRIBUTION_SET + "\n" +
|
||||||
|
READ_REPOSITORY + IMPLY_READ + DISTRIBUTION_SET + "\n" +
|
||||||
|
UPDATE_REPOSITORY + IMPLY_UPDATE + DISTRIBUTION_SET + "\n" +
|
||||||
|
DELETE_REPOSITORY + IMPLY_DELETE + DISTRIBUTION_SET + "\n" +
|
||||||
|
CREATE_REPOSITORY + IMPLY_CREATE + DISTRIBUTION_SET_TYPE + "\n" +
|
||||||
|
READ_REPOSITORY + IMPLY_READ + DISTRIBUTION_SET_TYPE + "\n" +
|
||||||
|
UPDATE_REPOSITORY + IMPLY_UPDATE + DISTRIBUTION_SET_TYPE + "\n" +
|
||||||
|
DELETE_REPOSITORY + IMPLY_DELETE + DISTRIBUTION_SET_TYPE + "\n";
|
||||||
|
public static final String SOFTWARE_MODULE_HIERARCHY =
|
||||||
|
CREATE_PREFIX + SOFTWARE_MODULE + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
READ_PREFIX + SOFTWARE_MODULE + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
UPDATE_PREFIX + SOFTWARE_MODULE + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
DELETE_PREFIX + SOFTWARE_MODULE + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n";
|
||||||
|
public static final String DISTRIBUTION_SET_HIERARCHY =
|
||||||
|
CREATE_PREFIX + DISTRIBUTION_SET + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
READ_PREFIX + DISTRIBUTION_SET + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
UPDATE_PREFIX + DISTRIBUTION_SET + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n" +
|
||||||
|
DELETE_PREFIX + DISTRIBUTION_SET + IMPLY_READ + SOFTWARE_MODULE_TYPE + "\n";
|
||||||
|
public static final String TENANT_CONFIGURATION_HIERARCHY =
|
||||||
|
TENANT_CONFIGURATION + IMPLY_CREATE + TENANT_CONFIGURATION + "\n" +
|
||||||
|
TENANT_CONFIGURATION + IMPLY_READ + TENANT_CONFIGURATION + "\n" +
|
||||||
|
TENANT_CONFIGURATION + IMPLY_UPDATE + TENANT_CONFIGURATION + "\n" +
|
||||||
|
TENANT_CONFIGURATION + IMPLY_DELETE + TENANT_CONFIGURATION + "\n" +
|
||||||
|
TENANT_CONFIGURATION + IMPLY_CREATE + READ_GATEWAY_SECURITY_TOKEN + "\n";
|
||||||
|
|
||||||
|
// @formatter:on
|
||||||
private static final SingletonSupplier<List<String>> ALL_AUTHORITIES = SingletonSupplier.of(() -> {
|
private static final SingletonSupplier<List<String>> ALL_AUTHORITIES = SingletonSupplier.of(() -> {
|
||||||
final List<String> allPermissions = new ArrayList<>();
|
final List<String> allPermissions = new ArrayList<>();
|
||||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
|
||||||
for (final Field field : declaredFields) {
|
// groups with access, canonical
|
||||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) &&
|
for (final String group : new String[] {
|
||||||
String.class.equals(field.getType()) && !field.getName().endsWith("_HIERARCHY")) {
|
TARGET, TARGET_TYPE,
|
||||||
try {
|
SOFTWARE_MODULE, SOFTWARE_MODULE_TYPE, DISTRIBUTION_SET, DISTRIBUTION_SET_TYPE,
|
||||||
final String role = (String) field.get(null);
|
ROLLOUT,
|
||||||
allPermissions.add(role);
|
TENANT_CONFIGURATION }) {
|
||||||
} catch (final IllegalAccessException e) {
|
for (final String access_prefix : new String[] { CREATE_PREFIX, READ_PREFIX, UPDATE_PREFIX, DELETE_PREFIX }) {
|
||||||
log.error(e.getMessage(), e);
|
allPermissions.add(access_prefix + group);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// special
|
||||||
|
allPermissions.add(READ_TARGET_SECURITY_TOKEN);
|
||||||
|
allPermissions.add(READ_GATEWAY_SECURITY_TOKEN);
|
||||||
|
allPermissions.add(DOWNLOAD_REPOSITORY_ARTIFACT);
|
||||||
|
allPermissions.add(APPROVE_ROLLOUT);
|
||||||
|
allPermissions.add(HANDLE_ROLLOUT);
|
||||||
|
|
||||||
|
// coarse-grained - maybe to be deprecated
|
||||||
|
for (final String access_prefix : new String[] { CREATE_PREFIX, READ_PREFIX, UPDATE_PREFIX, DELETE_PREFIX }) {
|
||||||
|
allPermissions.add(access_prefix + "REPOSITORY");
|
||||||
|
}
|
||||||
|
allPermissions.add(TENANT_CONFIGURATION);
|
||||||
|
|
||||||
|
// system permission, (!) take care with
|
||||||
|
allPermissions.add(SYSTEM_ADMIN);
|
||||||
|
|
||||||
return Collections.unmodifiableList(allPermissions);
|
return Collections.unmodifiableList(allPermissions);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,14 @@ public final class SpRole {
|
|||||||
private static final String LINE_BREAK = "\n";
|
private static final String LINE_BREAK = "\n";
|
||||||
public static final String TARGET_ADMIN_HIERARCHY =
|
public static final String TARGET_ADMIN_HIERARCHY =
|
||||||
TARGET_ADMIN + IMPLIES + SpPermission.READ_TARGET + LINE_BREAK +
|
TARGET_ADMIN + IMPLIES + SpPermission.READ_TARGET + LINE_BREAK +
|
||||||
TARGET_ADMIN + IMPLIES + SpPermission.READ_TARGET_SEC_TOKEN + LINE_BREAK +
|
TARGET_ADMIN + IMPLIES + SpPermission.READ_TARGET_SECURITY_TOKEN + LINE_BREAK +
|
||||||
TARGET_ADMIN + IMPLIES + SpPermission.UPDATE_TARGET + LINE_BREAK +
|
TARGET_ADMIN + IMPLIES + SpPermission.UPDATE_TARGET + LINE_BREAK +
|
||||||
TARGET_ADMIN + IMPLIES + SpPermission.CREATE_TARGET + LINE_BREAK +
|
TARGET_ADMIN + IMPLIES + SpPermission.CREATE_TARGET + LINE_BREAK +
|
||||||
TARGET_ADMIN + IMPLIES + SpPermission.DELETE_TARGET + LINE_BREAK;
|
TARGET_ADMIN + IMPLIES + SpPermission.DELETE_TARGET + LINE_BREAK +
|
||||||
|
TARGET_ADMIN + IMPLIES + SpPermission.READ_TARGET_TYPE + LINE_BREAK +
|
||||||
|
TARGET_ADMIN + IMPLIES + SpPermission.UPDATE_TARGET_TYPE + LINE_BREAK +
|
||||||
|
TARGET_ADMIN + IMPLIES + SpPermission.CREATE_PREFIX + SpPermission.TARGET_TYPE + LINE_BREAK +
|
||||||
|
TARGET_ADMIN + IMPLIES + SpPermission.DELETE_TARGET_TYPE + LINE_BREAK;
|
||||||
public static final String REPOSITORY_ADMIN_HIERARCHY =
|
public static final String REPOSITORY_ADMIN_HIERARCHY =
|
||||||
REPOSITORY_ADMIN + IMPLIES + SpPermission.READ_REPOSITORY + LINE_BREAK +
|
REPOSITORY_ADMIN + IMPLIES + SpPermission.READ_REPOSITORY + LINE_BREAK +
|
||||||
REPOSITORY_ADMIN + IMPLIES + SpPermission.UPDATE_REPOSITORY + LINE_BREAK +
|
REPOSITORY_ADMIN + IMPLIES + SpPermission.UPDATE_REPOSITORY + LINE_BREAK +
|
||||||
|
|||||||
@@ -66,8 +66,7 @@ public class StaticAuthenticationProvider extends DaoAuthenticationProvider {
|
|||||||
: new TenantAwareUser(username, password, credentials, user.getTenant()));
|
: new TenantAwareUser(username, password, credentials, user.getTenant()));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (securityProperties != null && securityProperties.getUser() != null &&
|
if (securityProperties != null && securityProperties.getUser() != null && !securityProperties.getUser().isPasswordGenerated()) {
|
||||||
!securityProperties.getUser().isPasswordGenerated()) {
|
|
||||||
// explicitly setup system user - add is as a regular (non-tenant scoped) user
|
// explicitly setup system user - add is as a regular (non-tenant scoped) user
|
||||||
userPrincipals.add(new User(
|
userPrincipals.add(new User(
|
||||||
securityProperties.getUser().getName(),
|
securityProperties.getUser().getName(),
|
||||||
|
|||||||
Reference in New Issue
Block a user