diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
index d70eff970..e9cda6cc5 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java
@@ -89,7 +89,7 @@ public interface SystemManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
TenantMetaData getTenantMetadata();
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java
index 523a6821d..32ddeb021 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java
@@ -62,22 +62,6 @@ public interface TenantConfigurationManagement {
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
Map> addOrUpdateConfiguration(Map configurations);
- /**
- * Build the tenant configuration by the given key
- *
- * @param configurationKey
- * the key
- * @param propertyType
- * the property type
- * @param tenantConfiguration
- * the configuration
- * @return if no default value is set and no database value available
- * or returns the tenant configuration value
- */
- @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
- TenantConfigurationValue buildTenantConfigurationValueByKey(
- TenantConfigurationKey configurationKey, Class propertyType, TenantConfiguration tenantConfiguration);
-
/**
* Deletes a specific configuration for the current tenant. Does nothing in
* case there is no tenant specific configuration value.
@@ -106,7 +90,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given
* {@code propertyType}
*/
- @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ)
TenantConfigurationValue getConfigurationValue(String configurationKeyName);
/**
@@ -132,7 +116,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given
* {@code propertyType}
*/
- @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ)
TenantConfigurationValue getConfigurationValue(String configurationKeyName,
Class propertyType);
@@ -156,6 +140,6 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given
* {@code propertyType}
*/
- @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ)
T getGlobalConfigurationValue(String configurationKeyName, Class propertyType);
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java
index 519360a8a..b5b5e6dd9 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantStatsManagement.java
@@ -28,7 +28,7 @@ public interface TenantStatsManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
- + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR
+ + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_SYSTEM_CODE)
TenantUsage getStatsOfTenant();
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java
index b0592b091..ac27eefcb 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java
@@ -21,7 +21,9 @@ import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
+import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
+import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValueChangeNotAllowedException;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
@@ -29,6 +31,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration;
import org.eclipse.hawkbit.repository.jpa.repository.TenantConfigurationRepository;
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
+import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
+import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
@@ -75,6 +79,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
@Cacheable(value = "tenantConfiguration", key = "#configurationKeyName")
public TenantConfigurationValue getConfigurationValue(final String configurationKeyName,
final Class propertyType) {
+ checkAccess(configurationKeyName);
final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName);
@@ -86,48 +91,11 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
return buildTenantConfigurationValueByKey(configurationKey, propertyType, tenantConfiguration);
}
- /**
- * Validates the data type of the tenant configuration. If it is possible to
- * cast to the given data type.
- *
- * @param configurationKey
- * the key
- * @param propertyType
- * the class
- */
- static void validateTenantConfigurationDataType(final TenantConfigurationKey configurationKey,
- final Class propertyType) {
-
- if (!configurationKey.getDataType().isAssignableFrom(propertyType)) {
- throw new TenantConfigurationValidatorException(
- String.format("Cannot parse the database value of type %s into the type %s.",
- configurationKey.getDataType(), propertyType));
- }
- }
-
- @Override
- public TenantConfigurationValue buildTenantConfigurationValueByKey(
- final TenantConfigurationKey configurationKey, final Class propertyType,
- final TenantConfiguration tenantConfiguration) {
- if (tenantConfiguration != null) {
- return TenantConfigurationValue. builder().global(false).createdBy(tenantConfiguration.getCreatedBy())
- .createdAt(tenantConfiguration.getCreatedAt())
- .lastModifiedAt(tenantConfiguration.getLastModifiedAt())
- .lastModifiedBy(tenantConfiguration.getLastModifiedBy())
- .value(conversionService.convert(tenantConfiguration.getValue(), propertyType)).build();
-
- } else if (configurationKey.getDefaultValue() != null) {
-
- return TenantConfigurationValue. builder().global(true).createdBy(null).createdAt(null)
- .lastModifiedAt(null).lastModifiedBy(null)
- .value(getGlobalConfigurationValue(configurationKey.getKeyName(), propertyType)).build();
- }
- return null;
- }
-
@Override
public TenantConfigurationValue getConfigurationValue(
final String configurationKeyName) {
+ checkAccess(configurationKeyName);
+
final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(configurationKeyName);
return getConfigurationValue(configurationKeyName, (Class)configurationKey.getDataType());
@@ -135,6 +103,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
@Override
public T getGlobalConfigurationValue(final String configurationKeyName, final Class propertyType) {
+ checkAccess(configurationKeyName);
final TenantConfigurationKey key = tenantConfigurationProperties.fromKeyName(configurationKeyName);
@@ -146,6 +115,19 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
return conversionService.convert(key.getDefaultValue(), propertyType);
}
+ private void checkAccess(final String configurationKeyName) {
+ if (TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY
+ .equalsIgnoreCase(configurationKeyName)) {
+ final SystemSecurityContext systemSecurityContext =
+ SystemSecurityContextHolder.getInstance().getSystemSecurityContext();
+ if (!systemSecurityContext.isCurrentThreadSystemCode() &&
+ !systemSecurityContext.hasPermission(SpPermission.READ_GATEWAY_SEC_TOKEN)) {
+ throw new InsufficientPermissionException(
+ "Can't read gateway security token! " + SpPermission.READ_GATEWAY_SEC_TOKEN + " is required!");
+ }
+ }
+ }
+
@Override
@CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
@Transactional
@@ -217,6 +199,51 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
}));
}
+ @Override
+ @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
+ @Transactional
+ @Retryable(include = {
+ ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
+ public void deleteConfiguration(final String configurationKeyName) {
+ tenantConfigurationRepository.deleteByKey(configurationKeyName);
+ }
+
+ /**
+ * Validates the data type of the tenant configuration. If it is possible to
+ * cast to the given data type.
+ *
+ * @param configurationKey the key
+ * @param propertyType the class
+ */
+ private static void validateTenantConfigurationDataType(final TenantConfigurationKey configurationKey,
+ final Class propertyType) {
+
+ if (!configurationKey.getDataType().isAssignableFrom(propertyType)) {
+ throw new TenantConfigurationValidatorException(
+ String.format("Cannot parse the database value of type %s into the type %s.",
+ configurationKey.getDataType(), propertyType));
+ }
+ }
+
+ private TenantConfigurationValue buildTenantConfigurationValueByKey(
+ final TenantConfigurationKey configurationKey, final Class propertyType,
+ final TenantConfiguration tenantConfiguration) {
+ if (tenantConfiguration != null) {
+ return TenantConfigurationValue. builder().global(false).createdBy(tenantConfiguration.getCreatedBy())
+ .createdAt(tenantConfiguration.getCreatedAt())
+ .lastModifiedAt(tenantConfiguration.getLastModifiedAt())
+ .lastModifiedBy(tenantConfiguration.getLastModifiedBy())
+ .value(conversionService.convert(tenantConfiguration.getValue(), propertyType)).build();
+
+ } else if (configurationKey.getDefaultValue() != null) {
+
+ return TenantConfigurationValue. builder().global(true).createdBy(null).createdAt(null)
+ .lastModifiedAt(null).lastModifiedBy(null)
+ .value(getGlobalConfigurationValue(configurationKey.getKeyName(), propertyType)).build();
+ }
+ return null;
+ }
+
/**
* Asserts that the requested configuration value change is allowed. Throws
* a {@link TenantConfigurationValueChangeNotAllowedException} otherwise.
@@ -271,13 +298,4 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
}
}
}
-
- @Override
- @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName")
- @Transactional
- @Retryable(include = {
- ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
- public void deleteConfiguration(final String configurationKeyName) {
- tenantConfigurationRepository.deleteByKey(configurationKeyName);
- }
}
diff --git a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java
index 3a58ce50c..d93e5369f 100644
--- a/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java
+++ b/hawkbit-rest/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java
@@ -12,7 +12,7 @@ package org.eclipse.hawkbit.ddi.rest.resource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS;
-import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION;
+import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.containsString;
@@ -210,7 +210,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Expect(type = TargetPollEvent.class, count = 1),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void pollWithModifiedGlobalPollingTime() throws Exception {
- SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION),
+ SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION_READ),
() -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
"00:02:00");
@@ -611,7 +611,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
void sleepTimeResponseForDifferentMaintenanceWindowParameters() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet("");
- SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION),
+ SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION_READ),
() -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
"00:05:00");
diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java
index 47b44fbc3..bc1910123 100644
--- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java
+++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTenantManagementRestApi.java
@@ -45,7 +45,7 @@ public interface MgmtTenantManagementRestApi {
* @return a map of all configuration values.
*/
@Operation(summary = "Return all tenant specific configuration values", description = "The GET request returns " +
- "a list of all possible configuration keys for the tenant. Required Permission: TENANT_CONFIGURATION")
+ "a list of all possible configuration keys for the tenant. Required Permission: READ_TENANT_CONFIGURATION")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
@@ -115,7 +115,7 @@ public interface MgmtTenantManagementRestApi {
*/
@Operation(summary = "Return a tenant specific configuration value", description = "The GET request returns the " +
"configuration value of a specific configuration key for the tenant. " +
- "Required Permission: TENANT_CONFIGURATION")
+ "Required Permission: READ_TENANT_CONFIGURATION")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java
index 736f62edc..0c0f23beb 100644
--- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java
+++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java
@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.mgmt.rest.resource;
import java.io.Serializable;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -21,6 +22,7 @@ import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationV
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
+import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
@@ -51,14 +53,21 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
@Override
public ResponseEntity
*/
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public final class SpPermission {
@@ -93,6 +96,19 @@ public final class SpPermission {
*/
public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT";
+ /**
+ * Permission to read the tenant settings.
+ */
+ public static final String READ_TENANT_CONFIGURATION = "READ_TENANT_CONFIGURATION";
+
+ /**
+ * 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},
+ * {@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.
+ */
+ public static final String READ_GATEWAY_SEC_TOKEN = "READ_GATEWAY_SECURITY_TOKEN";
+
/**
* Permission to administrate the tenant settings.
*/
@@ -128,10 +144,6 @@ public final class SpPermission {
*/
public static final String APPROVE_ROLLOUT = "APPROVE_ROLLOUT";
- private SpPermission() {
- // Constants only
- }
-
/**
* Return all permission.
* @return all permissions
@@ -175,6 +187,7 @@ public final class SpPermission {
* }
*
*/
+ @NoArgsConstructor(access = AccessLevel.PRIVATE)
public static final class SpringEvalExpressions {
/*
* Spring security eval expressions.
@@ -404,6 +417,14 @@ public final class SpPermission {
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_DELETE = HAS_AUTH_PREFIX + DELETE_ROLLOUT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
+ /**
+ * Spring security eval hasAuthority expression to check if spring
+ * context contains {@link SpPermission#READ_TENANT_CONFIGURATION} or
+ * {@link #IS_SYSTEM_CODE}.
+ */
+ public static final String HAS_AUTH_TENANT_CONFIGURATION_READ = HAS_AUTH_PREFIX + READ_TENANT_CONFIGURATION
+ + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
+
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#TENANT_CONFIGURATION} or
@@ -414,14 +435,10 @@ public final class SpPermission {
/**
* Spring security eval hasAuthority expression to check if spring
- * context contains {@link SpPermission#IS_CONTROLLER} or
+ * context contains {@link #IS_CONTROLLER} or
* {@link #HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET}.
*/
public static final String IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET =
IS_CONTROLLER + HAS_AUTH_OR + HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET;
-
- private SpringEvalExpressions() {
- // utility class
- }
}
-}
+}
\ No newline at end of file
diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpRole.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpRole.java
index f0c226992..585efde08 100644
--- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpRole.java
+++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpRole.java
@@ -48,6 +48,10 @@ public final class SpRole {
ROLLOUT_ADMIN + IMPLIES + SpPermission.HANDLE_ROLLOUT + LINE_BREAK +
ROLLOUT_ADMIN + IMPLIES + SpPermission.APPROVE_ROLLOUT + LINE_BREAK;
+ public static final String TENANT_CONFIGURATION_HIERARCHY =
+ SpPermission.TENANT_CONFIGURATION + IMPLIES + SpPermission.READ_TENANT_CONFIGURATION + LINE_BREAK +
+ SpPermission.TENANT_CONFIGURATION + IMPLIES + SpPermission.READ_GATEWAY_SEC_TOKEN;
+
public static final String TENANT_ADMIN = "ROLE_TENANT_ADMIN";
public static final String TENANT_ADMIN_HIERARCHY =
TENANT_ADMIN + IMPLIES + TARGET_ADMIN + LINE_BREAK +
@@ -61,6 +65,8 @@ public final class SpRole {
public static String DEFAULT_ROLE_HIERARCHY =
TARGET_ADMIN_HIERARCHY +
REPOSITORY_ADMIN_HIERARCHY +
- ROLLOUT_ADMIN_HIERARCHY + TENANT_ADMIN_HIERARCHY +
+ ROLLOUT_ADMIN_HIERARCHY +
+ TENANT_CONFIGURATION_HIERARCHY +
+ TENANT_ADMIN_HIERARCHY +
SYSTEM_ADMIN_HIERARCHY;
}
\ No newline at end of file
diff --git a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/SpPermissionTest.java b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/SpPermissionTest.java
index a72b717f2..0caff6a43 100644
--- a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/SpPermissionTest.java
+++ b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/SpPermissionTest.java
@@ -34,7 +34,7 @@ public final class SpPermissionTest {
@Test
@Description("Verify the get permission function")
public void testGetPermissions() {
- final int allPermission = 18;
+ final int allPermission = 20;
final Collection allAuthorities = SpPermission.getAllAuthorities();
final List allAuthoritiesList = PermissionUtils.createAllAuthorityList();
assertThat(allAuthorities).hasSize(allPermission);