diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java index 64bcf4956e..933a85971d 100644 --- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java +++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/role/RolePolicyProviderFactory.java @@ -108,6 +108,30 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory config = new HashMap<>(); + Set roles = toRepresentation(policy, new RolePolicyRepresentation()).getRoles(); + + for (RolePolicyRepresentation.RoleDefinition roleDefinition : roles) { + RoleModel role = authorizationProvider.getRealm().getRoleById(roleDefinition.getId()); + + if (role.isClientRole()) { + roleDefinition.setId(ClientModel.class.cast(role.getContainer()).getClientId() + "/" + role.getName()); + } else { + roleDefinition.setId(role.getName()); + } + } + + try { + config.put("roles", JsonSerialization.writeValueAsString(roles)); + } catch (IOException cause) { + throw new RuntimeException("Failed to export role policy [" + policy.getName() + "]", cause); + } + + representation.setConfig(config); + } + private void updateRoles(Policy policy, RolePolicyRepresentation representation, AuthorizationProvider authorization) { updateRoles(policy, authorization, representation.getRoles()); } diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java index a21bf74bf0..5a90f93227 100644 --- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java +++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/user/UserPolicyProviderFactory.java @@ -20,11 +20,13 @@ package org.keycloak.authorization.policy.provider.user; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.stream.Collectors; import org.keycloak.Config; import org.keycloak.authorization.AuthorizationProvider; @@ -106,6 +108,23 @@ public class UserPolicyProviderFactory implements PolicyProviderFactory config = new HashMap<>(); + + try { + UserProvider userProvider = authorizationProvider.getKeycloakSession().users(); + RealmModel realm = authorizationProvider.getRealm(); + + config.put("users", JsonSerialization.writeValueAsString(userRep.getUsers().stream().map(id -> userProvider.getUserById(id, realm).getUsername()).collect(Collectors.toList()))); + } catch (IOException cause) { + throw new RuntimeException("Failed to export user policy [" + policy.getName() + "]", cause); + } + + representation.setConfig(config); + } + private void updateUsers(Policy policy, UserPolicyRepresentation representation, AuthorizationProvider authorization) { updateUsers(policy, authorization, representation.getUsers()); } diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java index af95b008b9..a2a86899e2 100644 --- a/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java +++ b/server-spi-private/src/main/java/org/keycloak/authorization/policy/provider/PolicyProviderFactory.java @@ -60,7 +60,11 @@ public interface PolicyProviderFactory e } + default void onExport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorizationProvider) { + representation.setConfig(policy.getConfig()); + } + default PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) { return null; } -} +} \ No newline at end of file diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 6637bd8393..a0beb7f6b1 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -817,7 +817,11 @@ public class ModelToRepresentation { representation.setLogic(policy.getLogic()); if (representation instanceof PolicyRepresentation) { - PolicyRepresentation.class.cast(representation).setConfig(policy.getConfig()); + if (providerFactory != null) { + providerFactory.onExport(policy, PolicyRepresentation.class.cast(representation), authorization); + } else { + PolicyRepresentation.class.cast(representation).setConfig(policy.getConfig()); + } } else { representation = (R) providerFactory.toRepresentation(policy, representation); } diff --git a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java index 7eaf246f23..61822926e2 100755 --- a/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java +++ b/services/src/main/java/org/keycloak/exportimport/util/ExportUtils.java @@ -370,24 +370,6 @@ public class ExportUtils { rep.setConfig(config); - String roles = config.get("roles"); - - if (roles != null && !roles.isEmpty()) { - List rolesMap = JsonSerialization.readValue(roles, List.class); - config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleMap -> { - roleMap.put("id", realm.getRoleById(roleMap.get("id").toString()).getName()); - return roleMap; - }).collect(Collectors.toList()))); - } - - String users = config.get("users"); - - if (users != null && !users.isEmpty()) { - UserProvider userManager = session.users(); - List userIds = JsonSerialization.readValue(users, List.class); - config.put("users", JsonSerialization.writeValueAsString(userIds.stream().map(userId -> userManager.getUserById(userId, realm).getUsername()).collect(Collectors.toList()))); - } - Set scopes = policy.getScopes(); if (!scopes.isEmpty()) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java index f923cf4ac2..d63a15f94d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java @@ -627,10 +627,11 @@ public class ExportImportUtil { assertPredicate(scopes, scopePredicates); List policies = authzResource.policies().policies(); - Assert.assertEquals(11, policies.size()); + Assert.assertEquals(12, policies.size()); List> policyPredicates = new ArrayList<>(); policyPredicates.add(policyRepresentation -> "Any Admin Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "Any User Policy".equals(policyRepresentation.getName())); + policyPredicates.add(representation -> "Client and Realm Role Policy".equals(representation.getName()) && representation.getConfig().get("roles").contains("\"id\":\"realm-management/impersonation\"")); policyPredicates.add(policyRepresentation -> "Only Premium User Policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "wburke policy".equals(policyRepresentation.getName())); policyPredicates.add(policyRepresentation -> "All Users Policy".equals(policyRepresentation.getName())); diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json index b540ab1bdb..e285dee989 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/model/testrealm.json @@ -282,6 +282,13 @@ "roles": "[{\"id\":\"user\"}]" } }, + { + "name": "Client and Realm Role Policy", + "type": "role", + "config": { + "roles": "[{\"id\":\"realm-management/impersonation\",\"required\":false},{\"id\":\"realm-management/manage-authorization\",\"required\":true},{\"id\":\"user\",\"required\":false}]" + } + }, { "name": "Only Premium User Policy", "description": "Defines that only premium users can do something",