Class AdminAclEvaluationTest
UserGroupServiceTest#testUpdateUserGroup: when the admin test user
(authority GROUP_ADMIN) calls a method protected by
@PreAuthorize("hasPermission(#group, 'administration')") on a
UserGroup whose ACL was created by BaseAclAdvice.setupBaseAces(MutableAcl, ObjectIdentity, Sid, boolean) —
which inserts a GrantedAuthoritySid("GROUP_ADMIN") ADMINISTRATION
granting=true ACE — the evaluation returns false even though by
inspection it should return true.
The hasAuthority('GROUP_ADMIN') or ... disjunct in gsec
UserService.removeUserFromGroup is the workaround we want to drop;
this test is the gating fixture for that work.
Runs on the same in-memory ACL fixture as AclEventListenerTest
(no Hibernate, no JDBC, no MySQL), wired with the same Spring Security
collaborators production uses: AclPermissionEvaluator, gsec's
AclSidRetrievalStrategyImpl (role-hierarchy aware), and a real
RoleHierarchyImpl carrying Gemma's
GROUP_ADMIN > GROUP_USER > IS_AUTHENTICATED_ANONYMOUSLY hierarchy.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classMinimalSecurablestand-in — only needs a class name and id for theObjectIdentityImplkey. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid🛑 And it does NOT run the other way.void🛑 A curator has NO ace on a User or UserGroup, so they cannot reachBaseUserService.removeUserFromGroup— whose gate ishasPermission(#group, 'write') or hasPermission(#group, 'administration').voidThe headline reproducer.voidSame setup, but ask for WRITE.void🛑 The rule the whole widening rests on: an ADMINISTRATOR satisfies a GROUP_CURATOR ace through the hierarchy.voidA plain user is unaffected by the curator ace -- the widening gave nothing to GROUP_USER.voidA curator holds ADMINISTRATION through the acesetupBaseAcesnow grants GROUP_CURATOR, which is what lets every ACL_SECURABLE_EDIT check pass for them.voidsetUp()voidSanity check: the role-hierarchy-aware sid retrieval really does emit aGrantedAuthoritySid("GROUP_ADMIN")for an admin user, so the ACE sid and the user sid should match.voidtearDown()
-
Constructor Details
-
AdminAclEvaluationTest
public AdminAclEvaluationTest()
-
-
Method Details
-
setUp
@BeforeEach public void setUp() -
tearDown
@AfterEach public void tearDown() -
sidRetrievalForAdmin_includesGroupAdminAuthoritySid
@Test public void sidRetrievalForAdmin_includesGroupAdminAuthoritySid()Sanity check: the role-hierarchy-aware sid retrieval really does emit aGrantedAuthoritySid("GROUP_ADMIN")for an admin user, so the ACE sid and the user sid should match. -
adminHasAdministrationOnUserGroupAcl
@Test public void adminHasAdministrationOnUserGroupAcl()The headline reproducer. ACL set up exactly asBaseAclAdvice#setupBaseAceswould (with the UserGroup-specific extra READ-by-own-group ACE), then askAclPermissionEvaluator.hasPermission(admin, group, "administration"). -
adminLacksWriteWhenOnlyAdministrationAceExists
@Test public void adminLacksWriteWhenOnlyAdministrationAceExists()Same setup, but ask for WRITE. Spring'sBasePermission.WRITE(mask=2) is NOT the same asBasePermission.ADMINISTRATION(mask=16), so an ADMINISTRATION-only ACE should NOT satisfy a WRITE permission check. This test exists to pin down the contract — if thehasPermission(group, 'write')disjunct in the SpEL is ever to do useful work for admin, it has to come from a different ACE. -
curatorHasAdministrationOnAnObjectFromSetupBaseAces
@Test public void curatorHasAdministrationOnAnObjectFromSetupBaseAces()A curator holds ADMINISTRATION through the acesetupBaseAcesnow grants GROUP_CURATOR, which is what lets every ACL_SECURABLE_EDIT check pass for them.ADMINISTRATION rather than WRITE is deliberate and this is where it shows: it is also what
AclAuthorizationStrategyImplfalls back to when the caller lacks the configured authority, so the same ace covers editing a design AND changing a dataset's visibility. A WRITE ace would satisfy the edit check and then fail on makePublic. -
anAdministratorSatisfiesACuratorAce
@Test public void anAdministratorSatisfiesACuratorAce()🛑 The rule the whole widening rests on: an ADMINISTRATOR satisfies a GROUP_CURATOR ace through the hierarchy. 61 routes moved fromhasAuthority('GROUP_ADMIN')tohasAuthority('GROUP_CURATOR'), and if this direction did not hold, every one of them would have locked administrators out of work they could do the day before. -
aCuratorDoesNotSatisfyAnAdminOnlyAce
@Test public void aCuratorDoesNotSatisfyAnAdminOnlyAce()🛑 And it does NOT run the other way. A curator must never satisfy an admin-only ace, or the user-account and server-operation routes that kepthasAuthority('GROUP_ADMIN')would be open to them — which is the entire distinction between the two groups. -
aPlainUserDoesNotSatisfyACuratorAce
@Test public void aPlainUserDoesNotSatisfyACuratorAce()A plain user is unaffected by the curator ace -- the widening gave nothing to GROUP_USER. -
aCuratorHasNoAuthorityOverAUserGroup
@Test public void aCuratorHasNoAuthorityOverAUserGroup()🛑 A curator has NO ace on a User or UserGroup, so they cannot reachBaseUserService.removeUserFromGroup— whose gate ishasPermission(#group, 'write') or hasPermission(#group, 'administration').Without the exclusion in
setupBaseAces, a curator satisfies that check and can move anyone between groups, themselves into Administrators included — which is precisely the authority the group was defined not to have. This is not hypothetical: the first production backfill granted over every acl_object_identity and 668 aces (661 users plus the groups) had to be deleted back out an hour later.The ace list here is what setupBaseAces writes for a user-group object: admin and agent, no curator.
-