Refactor permissions (#2544)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-07-11 16:50:01 +03:00
committed by GitHub
parent 7ffd64c6da
commit c3fdd9fcc8
6 changed files with 67 additions and 263 deletions

View File

@@ -78,8 +78,9 @@ import org.springframework.test.web.servlet.ResultMatcher;
* Feature: Component Tests - Management API<br/>
* Story: Rollout Resource
*/
@TestPropertySource(locations = "classpath:/mgmt-test.properties", properties = {
"hawkbit.server.repository.dynamicRolloutsMinInvolvePeriodMS=-1" })
@TestPropertySource(
locations = "classpath:/mgmt-test.properties",
properties = { "hawkbit.server.repository.dynamicRolloutsMinInvolvePeriodMS=-1" })
class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
private static final String HREF_ROLLOUT_PREFIX = "http://localhost/rest/v1/rollouts/";

View File

@@ -28,8 +28,7 @@ import org.springframework.web.filter.CharacterEncodingFilter;
* Abstract Test for Rest tests.
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@ContextConfiguration(classes = {
RestConfiguration.class, JpaRepositoryConfiguration.class, TestConfiguration.class })
@ContextConfiguration(classes = { RestConfiguration.class, JpaRepositoryConfiguration.class, TestConfiguration.class })
@WebAppConfiguration
@AutoConfigureMockMvc
public abstract class AbstractRestIntegrationTest extends AbstractIntegrationTest {

View File

@@ -137,8 +137,7 @@ public final class SpPermission {
public static final String APPROVE_ROLLOUT = "APPROVE_ROLLOUT";
/**
* 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";
@@ -167,10 +166,8 @@ public final class SpPermission {
* <p>
* Contains all the spring security evaluation expressions for the {@link PreAuthorize} annotation for method security.
* </p>
*
* <p>
* Examples:
*
* {@code
* hasRole([role]) Returns true if the current principal has the specified role.
* hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
@@ -188,225 +185,58 @@ public final class SpPermission {
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static final class SpringEvalExpressions {
/*
* Spring security eval expressions.
*/
public static final String BRACKET_OPEN = "(";
public static final String BRACKET_CLOSE = ")";
public static final String HAS_AUTH_PREFIX = "hasAuthority" + BRACKET_OPEN + "'";
public static final String HAS_AUTH_SUFFIX = "'" + BRACKET_CLOSE;
public static final String HAS_AUTH_AND = " and ";
public static final String HAS_AUTH_OR = " or ";
/**
* The role which contains the spring security context in case the
* system is executing code which is necessary to be privileged.
* The role which contains the spring security context in case the system is executing code which is necessary to be privileged.
*/
public static final String SYSTEM_ROLE = "ROLE_SYSTEM_CODE";
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains system code role
* {@link SpringEvalExpressions#SYSTEM_ROLE}.
*/
public static final String IS_SYSTEM_CODE = HAS_AUTH_PREFIX + SYSTEM_ROLE + HAS_AUTH_SUFFIX;
/**
* The spring security eval expression operator {@code or}.
*/
public static final String HAS_AUTH_OR = " or ";
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_ADMIN} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR
+ IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET_SEC_TOKEN} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET_SEC_TOKEN = HAS_AUTH_PREFIX + READ_TARGET_SEC_TOKEN
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_REPOSITORY} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_REPOSITORY = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_REPOSITORY
+ HAS_AUTH_SUFFIX + BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and
* {@link SpPermission#CREATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ CREATE_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + READ_ROLLOUT + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_ROLLOUT} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_ROLLOUT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE = HAS_AUTH_PREFIX + CREATE_ROLLOUT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#HANDLE_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE = HAS_AUTH_PREFIX + HANDLE_ROLLOUT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#APPROVE_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_APPROVE = HAS_AUTH_PREFIX + APPROVE_ROLLOUT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE = HAS_AUTH_PREFIX + UPDATE_ROLLOUT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_ROLLOUT} or
* {@link #IS_SYSTEM_CODE}.
*/
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
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* The role which contains in the spring security context in case an
* controller is authenticated.
* The role which contains in the spring security context in case ancontroller is authenticated.
*/
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'.
* 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";
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anonymous role or the controller specific role
* {@link SpringEvalExpressions#CONTROLLER_ROLE}.
*/
public static final String IS_SYSTEM_CODE = HAS_AUTH_PREFIX + SYSTEM_ROLE + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE;
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE;
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + READ_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_ROLLOUT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE = HAS_AUTH_PREFIX + CREATE_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE = HAS_AUTH_PREFIX + HANDLE_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_APPROVE = HAS_AUTH_PREFIX + APPROVE_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_UPDATE = HAS_AUTH_PREFIX + UPDATE_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_DELETE = HAS_AUTH_PREFIX + DELETE_ROLLOUT + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_TENANT_CONFIGURATION_READ = HAS_AUTH_PREFIX + READ_TENANT_CONFIGURATION + HAS_AUTH_SUFFIX;
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION + HAS_AUTH_SUFFIX;
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE + "')";
/**
* Spring security eval hasAuthority expression to check if spring
* 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;
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;
}
}

View File

@@ -9,6 +9,8 @@
*/
package org.eclipse.hawkbit.im.authentication;
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -54,11 +56,15 @@ public final class SpRole {
TENANT_ADMIN + IMPLIES + REPOSITORY_ADMIN + LINE_BREAK +
TENANT_ADMIN + IMPLIES + ROLLOUT_ADMIN + LINE_BREAK +
TENANT_ADMIN + IMPLIES + SpPermission.TENANT_CONFIGURATION + LINE_BREAK;
public static final String SYSTEM_ROLE_HIERARCHY =
SYSTEM_ROLE + IMPLIES + TENANT_ADMIN + LINE_BREAK +
SYSTEM_ROLE + IMPLIES + SpPermission.SYSTEM_ADMIN + LINE_BREAK;
public static final String DEFAULT_ROLE_HIERARCHY =
TARGET_ADMIN_HIERARCHY +
REPOSITORY_ADMIN_HIERARCHY +
ROLLOUT_ADMIN_HIERARCHY +
TENANT_CONFIGURATION_HIERARCHY +
TENANT_ADMIN_HIERARCHY;
TENANT_ADMIN_HIERARCHY +
SYSTEM_ROLE_HIERARCHY;
}

View File

@@ -40,7 +40,7 @@ public class StaticAuthenticationProvider extends DaoAuthenticationProvider {
public StaticAuthenticationProvider(
final TenantAwareUserProperties tenantAwareUserProperties, final SecurityProperties securityProperties) {
setUserDetailsService(userDetailsService(tenantAwareUserProperties, securityProperties));
super(userDetailsService(tenantAwareUserProperties, securityProperties));
}
@Override

View File

@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.security;
import java.io.Serial;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
@@ -42,62 +41,35 @@ public class SystemSecurityContext {
private final TenantAware tenantAware;
private final RoleHierarchy roleHierarchy;
/**
* Autowired constructor.
*
* @param tenantAware the tenant aware bean to retrieve the current tenant
*/
public SystemSecurityContext(final TenantAware tenantAware) {
this(tenantAware, null);
}
/**
* Autowired constructor.
*
* @param tenantAware the tenant aware bean to retrieve the current tenant
* @param roleHierarchy the roleHierarchy that is applied
*/
public SystemSecurityContext(final TenantAware tenantAware, final RoleHierarchy roleHierarchy) {
this.tenantAware = tenantAware;
this.roleHierarchy = roleHierarchy;
}
/**
* Runs a given {@link Callable} within a system security context, which is
* permitted to call secured system code. Often the system needs to call
* secured methods by its own without relying on the current security
* context e.g. if the current security context does not contain the
* necessary permission it's necessary to execute code as system code to
* execute necessary methods and functionality.
* <br/>
* The security context will be switched to the system code and back after
* the callable is called.
* <br/>
* The system code is executed for a current tenant by using the
* {@link TenantAware#getCurrentTenant()}.
* Runs a given {@link Callable} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality. <br/>
* The security context will be switched to the system code and back after the callable is called. <br/>
* The system code is executed for a current tenant by using the {@link TenantAware#getCurrentTenant()}.
*
* @param callable the callable to call within the system security context
* @return the return value of the {@link Callable#call()} method.
*/
// Exception squid:S2221 - Callable declares Exception
@SuppressWarnings("squid:S2221")
public <T> T runAsSystem(final Callable<T> callable) {
return runAsSystemAsTenant(callable, tenantAware.getCurrentTenant());
}
/**
* Runs a given {@link Callable} within a system security context, which is
* permitted to call secured system code. Often the system needs to call
* secured methods by its own without relying on the current security
* context e.g. if the current security context does not contain the
* necessary permission it's necessary to execute code as system code to
* execute necessary methods and functionality.
*
* The security context will be switched to the system code and back after
* the callable is called.
*
* The system code is executed for a specific given tenant by using the
* {@link TenantAware}.
* Runs a given {@link Callable} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality.<br/>
* The security context will be switched to the system code and back after the callable is called.<br/>
* The system code is executed for a specific given tenant by using the {@link TenantAware}.
*
* @param callable the callable to call within the system security context
* @param tenant the tenant to act as system code
@@ -121,20 +93,16 @@ public class SystemSecurityContext {
/**
* Runs a given {@link Callable} within a system security context, which has the provided {@link GrantedAuthority}s to successfully
* run the {@link Callable}.
* <br/>
* run the {@link Callable}.<br/>
* The security context will be switched to a new {@link SecurityContext} and back after the callable is called.
*
* @param tenant under which the {@link Callable#call()} must be executed.
* @param callable to call within the security context
* @return the return value of the {@link Callable#call()} method.
*/
// The callable API throws a Exception and not a specific one
@SuppressWarnings({ "squid:S2221", "squid:S00112" })
public <T> T runAsControllerAsTenant(@NotEmpty final String tenant, @NotNull final Callable<T> callable) {
final SecurityContext oldContext = SecurityContextHolder.getContext();
List<SimpleGrantedAuthority> authorities = Collections
.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS));
final List<SimpleGrantedAuthority> authorities = List.of(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS));
try {
return tenantAware.runAsTenant(tenant, () -> {
setCustomSecurityContext(tenant, oldContext.getAuthentication().getPrincipal(), authorities);
@@ -152,6 +120,7 @@ public class SystemSecurityContext {
return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication;
}
@SuppressWarnings("java:S3776") // java:S3776 - better in one place for better readability
public boolean hasPermission(final String permission) {
final SecurityContext context = SecurityContextHolder.getContext();
if (context != null) {
@@ -180,8 +149,8 @@ public class SystemSecurityContext {
SecurityContextHolder.setContext(securityContextImpl);
}
private void setCustomSecurityContext(final String tenantId, final Object principal,
final Collection<? extends GrantedAuthority> authorities) {
private void setCustomSecurityContext(
final String tenantId, final Object principal, final Collection<? extends GrantedAuthority> authorities) {
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
UUID.randomUUID().toString(), principal, authorities);
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenantId, true));
@@ -200,8 +169,7 @@ public class SystemSecurityContext {
@Serial
private static final long serialVersionUID = 1L;
private static final List<SimpleGrantedAuthority> AUTHORITIES =
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
private static final List<SimpleGrantedAuthority> AUTHORITIES = List.of(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
private final Authentication oldAuthentication;
private SystemCodeAuthentication(final Authentication oldAuthentication) {
@@ -240,7 +208,7 @@ public class SystemSecurityContext {
@Override
public void setAuthenticated(final boolean isAuthenticated) {
// not needed
throw new UnsupportedOperationException();
}
}
}