[KEYCLOAK-17885] - Delete user-managed policies when removing groups

This commit is contained in:
Pedro Igor 2021-05-07 17:56:49 -03:00
parent 1855a5e17c
commit 6397671c88
5 changed files with 65 additions and 8 deletions

View file

@ -166,8 +166,7 @@ public class JPAPolicyStore implements PolicyStore {
}
}
break;
case OWNER_IS_NOT_NULL:
predicates.add(builder.isNotNull(root.get("owner")));
case ANY_OWNER:
break;
case CONFIG:
if (value.length != 2) {
@ -186,7 +185,7 @@ public class JPAPolicyStore implements PolicyStore {
}
});
if (!attributes.containsKey(Policy.FilterOption.OWNER) && !attributes.containsKey(Policy.FilterOption.OWNER_IS_NOT_NULL)) {
if (!attributes.containsKey(Policy.FilterOption.OWNER) && !attributes.containsKey(Policy.FilterOption.ANY_OWNER)) {
predicates.add(builder.isNull(root.get("owner")));
}

View file

@ -36,6 +36,7 @@ import org.keycloak.representations.idm.authorization.AbstractPolicyRepresentati
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@ -144,10 +145,11 @@ public class MapPolicyStore<K> implements PolicyStore {
ModelCriteriaBuilder<Policy> mcb = forResourceServer(resourceServerId).and(
attributes.entrySet().stream()
.map(this::filterEntryToModelCriteriaBuilder)
.filter(Objects::nonNull)
.toArray(ModelCriteriaBuilder[]::new)
);
if (!attributes.containsKey(Policy.FilterOption.OWNER) && !attributes.containsKey(Policy.FilterOption.OWNER_IS_NOT_NULL)) {
if (!attributes.containsKey(Policy.FilterOption.OWNER) && !attributes.containsKey(Policy.FilterOption.ANY_OWNER)) {
mcb = mcb.compare(SearchableFields.OWNER, Operator.NOT_EXISTS);
}
@ -180,9 +182,8 @@ public class MapPolicyStore<K> implements PolicyStore {
return mcb;
}
case OWNER_IS_NOT_NULL:
return policyStore.createCriteriaBuilder()
.compare(SearchableFields.OWNER, Operator.EXISTS);
case ANY_OWNER:
return null;
case CONFIG:
if (value.length != 2) {
throw new IllegalArgumentException("Config filter option requires value with two items: [config_name, expected_config_value]");

View file

@ -48,13 +48,14 @@ public interface Policy {
ID("id", SearchableFields.ID),
PERMISSION("permission", SearchableFields.TYPE),
OWNER("owner", SearchableFields.OWNER),
OWNER_IS_NOT_NULL("owner_is_not_null", SearchableFields.OWNER),
ANY_OWNER("owner.any", SearchableFields.OWNER),
RESOURCE_ID("resources.id", SearchableFields.RESOURCE_ID),
SCOPE_ID("scopes.id", SearchableFields.SCOPE_ID),
CONFIG("config", SearchableFields.CONFIG),
TYPE("type", SearchableFields.TYPE),
NAME("name", SearchableFields.NAME);
public static final String[] EMPTY_FILTER = new String[0];
private final String name;
private final SearchableModelField<Policy> searchableModelField;

View file

@ -49,6 +49,7 @@ public class GroupSynchronizer implements Synchronizer<GroupModel.GroupRemovedEv
attributes.put(Policy.FilterOption.TYPE, new String[] {"group"});
attributes.put(Policy.FilterOption.CONFIG, new String[] {"groups", group.getId()});
attributes.put(Policy.FilterOption.ANY_OWNER, Policy.FilterOption.EMPTY_FILTER);
List<Policy> search = policyStore.findByResourceServer(attributes, null, -1, -1);

View file

@ -89,6 +89,7 @@ public class UserManagedPermissionServiceTest extends AbstractResourceServerTest
.subGroups(Arrays.asList(GroupBuilder.create().name("group_b").build()))
.build())
.group(GroupBuilder.create().name("group_c").build())
.group(GroupBuilder.create().name("group_remove").build())
.user(UserBuilder.create().username("marta").password("password")
.addRoles("uma_authorization", "uma_protection")
.role("resource-server-test", "uma_protection"))
@ -937,6 +938,60 @@ public class UserManagedPermissionServiceTest extends AbstractResourceServerTest
assertTrue(policies.isEmpty());
}
@Test
public void testRemovePoliciesOnGroupDelete() {
ResourceRepresentation resource = new ResourceRepresentation();
resource.setName("Resource A");
resource.setOwnerManagedAccess(true);
resource.setOwner("marta");
resource.addScope("Scope A", "Scope B", "Scope C");
resource = getAuthzClient().protection().resource().create(resource);
UmaPermissionRepresentation newPermission = new UmaPermissionRepresentation();
newPermission.setName("Custom User-Managed Permission");
newPermission.addGroup("/group_remove");
ProtectionResource protection = getAuthzClient().protection("marta", "password");
protection.policy(resource.getId()).create(newPermission);
getTestingClient().server().run((RunOnServer) UserManagedPermissionServiceTest::testRemovePoliciesOnGroupDelete);
}
private static void testRemovePoliciesOnGroupDelete(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName("authz-test");
ClientModel client = realm.getClientByClientId("resource-server-test");
AuthorizationProvider provider = session.getProvider(AuthorizationProvider.class);
UserModel user = session.users().getUserByUsername(realm, "marta");
Map<Policy.FilterOption, String[]> filters = new HashMap<>();
filters.put(Policy.FilterOption.TYPE, new String[] {"uma"});
filters.put(OWNER, new String[] {user.getId()});
List<Policy> policies = provider.getStoreFactory().getPolicyStore()
.findByResourceServer(filters, client.getId(), -1, -1);
assertEquals(1, policies.size());
Policy policy = policies.get(0);
assertFalse(policy.getResources().isEmpty());
Resource resource = policy.getResources().iterator().next();
assertEquals("Resource A", resource.getName());
realm.removeGroup(realm.searchForGroupByNameStream("group_remove", -1, -1).findAny().get());
filters = new HashMap<>();
filters.put(OWNER, new String[] {user.getId()});
policies = provider.getStoreFactory().getPolicyStore()
.findByResourceServer(filters, client.getId(), -1, -1);
assertTrue(policies.isEmpty());
}
private List<PolicyRepresentation> getAssociatedPolicies(UmaPermissionRepresentation permission) {
return getClient(getRealm()).authorization().policies().policy(permission.getId()).associatedPolicies();
}