Remove deleted roles from policy on update
Closes #26915 Signed-off-by: EnneS <nathan.soulier26@gmail.com>
This commit is contained in:
parent
4dd97557cb
commit
365a3feafa
1 changed files with 36 additions and 81 deletions
|
@ -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[] {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue