Remove deleted roles from policy on update

Closes #26915

Signed-off-by: EnneS <nathan.soulier26@gmail.com>
This commit is contained in:
EnneS 2024-04-02 10:03:05 +02:00 committed by Pedro Igor
parent 4dd97557cb
commit 365a3feafa

View file

@ -85,8 +85,9 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
if (roles == null) { if (roles == null) {
representation.setRoles(Collections.emptySet()); representation.setRoles(Collections.emptySet());
} else { } else {
representation.setRoles(new HashSet<>( List<RolePolicyRepresentation.RoleDefinition> roleDefinitions = Arrays.asList(JsonSerialization.readValue(roles, RolePolicyRepresentation.RoleDefinition[].class));
Arrays.asList(JsonSerialization.readValue(roles, RolePolicyRepresentation.RoleDefinition[].class)))); roleDefinitions.removeIf(definition -> getRole(definition, authorization.getRealm()) == null);
representation.setRoles(new HashSet<>(roleDefinitions));
} }
String fetchRoles = policy.getConfig().get("fetchRoles"); String fetchRoles = policy.getConfig().get("fetchRoles");
@ -171,6 +172,59 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
if (roles != null) { if (roles != null) {
RealmModel realm = authorization.getRealm(); RealmModel realm = authorization.getRealm();
for (RolePolicyRepresentation.RoleDefinition definition : roles) { for (RolePolicyRepresentation.RoleDefinition definition : roles) {
RoleModel role = getRole(definition, realm);
if (role == null) {
continue;
}
definition.setId(role.getId());
updatedRoles.add(definition);
}
}
try {
policy.putConfig("roles", JsonSerialization.writeValueAsString(updatedRoles));
} catch (IOException cause) {
throw new RuntimeException("Failed to serialize roles", cause);
}
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "role";
}
private Map<String, Object>[] getRoles(Policy policy) {
String roles = policy.getConfig().get("roles");
if (roles != null) {
try {
return JsonSerialization.readValue(roles.getBytes(), Map[].class);
} catch (IOException e) {
throw new RuntimeException("Could not parse roles [" + roles + "] from policy config [" + policy.getName() + ".", e);
}
}
return new Map[] {};
}
private RoleModel getRole(RolePolicyRepresentation.RoleDefinition definition, RealmModel realm) {
String roleName = definition.getId(); String roleName = definition.getId();
String clientId = null; String clientId = null;
int clientIdSeparator = roleName.indexOf("/"); int clientIdSeparator = roleName.indexOf("/");
@ -198,105 +252,6 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory<RolePoli
role = client.getRole(roleName); role = client.getRole(roleName);
} }
if (role == null) { return role;
throw new RuntimeException("Error while updating policy [" + policy.getName() + "]. Role [" + roleName + "] could not be found.");
}
definition.setId(role.getId());
updatedRoles.add(definition);
}
}
try {
policy.putConfig("roles", JsonSerialization.writeValueAsString(updatedRoles));
} catch (IOException cause) {
throw new RuntimeException("Failed to serialize roles", cause);
}
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
factory.register(event -> {
if (event instanceof RoleRemovedEvent) {
KeycloakSession keycloakSession = ((RoleRemovedEvent) event).getKeycloakSession();
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
StoreFactory storeFactory = provider.getStoreFactory();
PolicyStore policyStore = storeFactory.getPolicyStore();
RoleModel removedRole = ((RoleRemovedEvent) event).getRole();
RoleContainerModel container = removedRole.getContainer();
ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
if (container instanceof RealmModel) {
RealmModel realm = (RealmModel) container;
realm.getClientsStream()
.forEach(clientModel -> updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore));
} else {
ClientModel clientModel = (ClientModel) container;
updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore);
}
}
});
}
private void updateResourceServer(ClientModel clientModel, RoleModel removedRole, ResourceServerStore resourceServerStore, PolicyStore policyStore) {
ResourceServer resourceServer = resourceServerStore.findByClient(clientModel);
if (resourceServer != null) {
policyStore.findByType(resourceServer, getId()).forEach(policy -> {
List<Map> roles = new ArrayList<>();
for (Map<String,Object> role : getRoles(policy)) {
if (!role.get("id").equals(removedRole.getId())) {
Map updated = new HashMap();
updated.put("id", role.get("id"));
Object required = role.get("required");
if (required != null) {
updated.put("required", required);
}
roles.add(updated);
}
}
try {
if (roles.isEmpty()) {
policyStore.delete(policy.getId());
} else {
policy.putConfig("roles", JsonSerialization.writeValueAsString(roles));
}
} catch (IOException e) {
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
}
});
}
}
@Override
public void close() {
}
@Override
public String getId() {
return "role";
}
private Map<String, Object>[] getRoles(Policy policy) {
String roles = policy.getConfig().get("roles");
if (roles != null) {
try {
return JsonSerialization.readValue(roles.getBytes(), Map[].class);
} catch (IOException e) {
throw new RuntimeException("Could not parse roles [" + roles + "] from policy config [" + policy.getName() + ".", e);
}
}
return new Map[] {};
} }
} }