Skip to content

Commit

Permalink
Support RoleHierarchy in AclAuthorizationStrategyImpl
Browse files Browse the repository at this point in the history
Closes gh-4186
  • Loading branch information
marcusdacoregio committed May 24, 2024
1 parent 752a56a commit 1d3cb3f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
package org.springframework.security.acls.domain;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.SidRetrievalStrategy;
Expand Down Expand Up @@ -59,6 +62,8 @@ public class AclAuthorizationStrategyImpl implements AclAuthorizationStrategy {

private SidRetrievalStrategy sidRetrievalStrategy = new SidRetrievalStrategyImpl();

private RoleHierarchy roleHierarchy = new NullRoleHierarchy();

/**
* Constructor. The only mandatory parameter relates to the system-wide
* {@link GrantedAuthority} instances that can be held to always permit ACL changes.
Expand Down Expand Up @@ -100,7 +105,9 @@ public void securityCheck(Acl acl, int changeType) {
}

// Iterate this principal's authorities to determine right
Set<String> authorities = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
Collection<? extends GrantedAuthority> reachableGrantedAuthorities = this.roleHierarchy
.getReachableGrantedAuthorities(authentication.getAuthorities());
Set<String> authorities = AuthorityUtils.authorityListToSet(reachableGrantedAuthorities);
if (acl.getOwner() instanceof GrantedAuthoritySid
&& authorities.contains(((GrantedAuthoritySid) acl.getOwner()).getGrantedAuthority())) {
return;
Expand Down Expand Up @@ -162,4 +169,14 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy secur
this.securityContextHolderStrategy = securityContextHolderStrategy;
}

/**
* Sets the {@link RoleHierarchy} to use. The default is to use a
* {@link NullRoleHierarchy}
* @since 6.4
*/
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "roleHierarchy cannot be null");
this.roleHierarchy = roleHierarchy;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@

import java.util.Arrays;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
Expand All @@ -34,6 +36,7 @@
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextImpl;

import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;

Expand Down Expand Up @@ -86,6 +89,15 @@ public void securityCheckWhenAclOwnedByGrantedAuthority() {
this.strategy.securityCheck(this.acl, AclAuthorizationStrategy.CHANGE_GENERAL);
}

@Test
public void securityCheckWhenRoleReachableByHierarchyThenAuthorized() {
given(this.acl.getOwner()).willReturn(new GrantedAuthoritySid("ROLE_AUTH_B"));
this.strategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_SYSTEM_ADMIN"));
this.strategy.setRoleHierarchy(RoleHierarchyImpl.fromHierarchy("ROLE_AUTH > ROLE_AUTH_B"));
assertThatNoException()
.isThrownBy(() -> this.strategy.securityCheck(this.acl, AclAuthorizationStrategy.CHANGE_GENERAL));
}

@Test
public void securityCheckWhenCustomSecurityContextHolderStrategyThenUses() {
given(this.securityContextHolderStrategy.getContext()).willReturn(this.context);
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/whats-new.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@

Spring Security 6.4 provides a number of new features.
Below are the highlights of the release, or you can view https://github.com/spring-projects/spring-security/releases[the release notes] for a detailed listing of each feature and bug fix.

- https://github.com/spring-projects/spring-security/issues/4186[gh-4186] - Support `RoleHierarchy` in `AclAuthorizationStrategyImpl`

0 comments on commit 1d3cb3f

Please sign in to comment.