Add fine grained sm/ds type permission (#2649)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-09-04 15:05:32 +03:00
committed by GitHub
parent 2e97d67489
commit 2c995b3665
17 changed files with 139 additions and 74 deletions

View File

@@ -15,9 +15,13 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Hierarchy {
// @formatter:off
public static final String DEFAULT =
SpPermission.TARGET_HIERARCHY +
SpPermission.REPOSITORY_HIERARCHY +
SpPermission.SOFTWARE_MODULE_HIERARCHY +
SpPermission.DISTRIBUTION_SET_HIERARCHY +
SpPermission.TENANT_CONFIGURATION_HIERARCHY +
SpRole.DEFAULT_ROLE_HIERARCHY;
// @formatter:on
}

View File

@@ -9,8 +9,6 @@
*/
package org.eclipse.hawkbit.im.authentication;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -46,7 +44,9 @@ public final class SpPermission {
public static final String TARGET = "TARGET";
public static final String TARGET_TYPE = "TARGET_TYPE";
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_TYPE = "DISTRIBUTION_SET_TYPE";
public static final String ROLLOUT = "ROLLOUT";
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 DELETE_TARGET = DELETE_PREFIX + TARGET;
/**
* Permission to read the target security token. The security token is security
* 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.
* Permission to read the target security token. The security token is security 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.
*/
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 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 CREATE_REPOSITORY = "CREATE_REPOSITORY";
public static final String DELETE_REPOSITORY = "DELETE_REPOSITORY";
public static final String DOWNLOAD_REPOSITORY_ARTIFACT = "DOWNLOAD_REPOSITORY_ARTIFACT";
/**
* Permission to read the tenant settings.
*/
public static final String READ_TENANT_CONFIGURATION = READ_PREFIX + 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";
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 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. */
public static final String SYSTEM_ADMIN = "SYSTEM_ADMIN";
public static final String TARGET_HIERARCHY = """
CREATE_TARGET > CREATE_TARGET_TYPE
READ_TARGET > READ_TARGET_TYPE
UPDATE_TARGET > UPDATE_TARGET_TYPE
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
""";
public static final String IMPLY_CREATE = " > " + CREATE_PREFIX;
public static final String IMPLY_READ = " > " + READ_PREFIX;
public static final String IMPLY_UPDATE = " > " + UPDATE_PREFIX;
public static final String IMPLY_DELETE = " > " + DELETE_PREFIX;
// @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(() -> {
final List<String> allPermissions = new ArrayList<>();
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
for (final Field field : declaredFields) {
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) &&
String.class.equals(field.getType()) && !field.getName().endsWith("_HIERARCHY")) {
try {
final String role = (String) field.get(null);
allPermissions.add(role);
} catch (final IllegalAccessException e) {
log.error(e.getMessage(), e);
}
// groups with access, canonical
for (final String group : new String[] {
TARGET, TARGET_TYPE,
SOFTWARE_MODULE, SOFTWARE_MODULE_TYPE, DISTRIBUTION_SET, DISTRIBUTION_SET_TYPE,
ROLLOUT,
TENANT_CONFIGURATION }) {
for (final String access_prefix : new String[] { CREATE_PREFIX, READ_PREFIX, UPDATE_PREFIX, DELETE_PREFIX }) {
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);
});

View File

@@ -36,10 +36,14 @@ public final class SpRole {
private static final String LINE_BREAK = "\n";
public static final String TARGET_ADMIN_HIERARCHY =
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.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 =
REPOSITORY_ADMIN + IMPLIES + SpPermission.READ_REPOSITORY + LINE_BREAK +
REPOSITORY_ADMIN + IMPLIES + SpPermission.UPDATE_REPOSITORY + LINE_BREAK +

View File

@@ -66,8 +66,7 @@ public class StaticAuthenticationProvider extends DaoAuthenticationProvider {
: new TenantAwareUser(username, password, credentials, user.getTenant()));
});
if (securityProperties != null && securityProperties.getUser() != null &&
!securityProperties.getUser().isPasswordGenerated()) {
if (securityProperties != null && securityProperties.getUser() != null && !securityProperties.getUser().isPasswordGenerated()) {
// explicitly setup system user - add is as a regular (non-tenant scoped) user
userPrincipals.add(new User(
securityProperties.getUser().getName(),