From b0a33c9765fb12cb99e174b8997c423c4927764a Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Thu, 13 Jul 2017 14:51:27 -0400 Subject: [PATCH] KEYCLOAK-5155 --- .../freemarker/model/ApplicationsBean.java | 18 +++++-- .../admin/permissions/AdminPermissions.java | 4 ++ .../admin/permissions/MgmtPermissions.java | 8 +++ .../testsuite/account/AccountTest.java | 36 ++++++++++--- .../admin/FineGrainAdminUnitTest.java | 54 +++++++++++++++++++ 5 files changed, 110 insertions(+), 10 deletions(-) diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java index e3611f7a94..2669c2967e 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java @@ -19,6 +19,7 @@ package org.keycloak.forms.account.freemarker.model; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.models.ClientModel; +import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; @@ -27,8 +28,10 @@ import org.keycloak.models.UserConsentModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.services.managers.UserSessionManager; +import org.keycloak.services.resources.admin.permissions.AdminPermissions; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -51,10 +54,17 @@ public class ApplicationsBean { continue; } - Set availableRoles = TokenManager.getAccess(null, false, client, user); - // Don't show applications, which user doesn't have access into (any available roles) - if (availableRoles.isEmpty()) { - continue; + Set availableRoles = new HashSet<>(); + if (client.getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID) + || client.getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) { + if (!AdminPermissions.realms(session, realm, user).isAdmin()) continue; + + } else { + availableRoles = TokenManager.getAccess(null, false, client, user); + // Don't show applications, which user doesn't have access into (any available roles) + if (availableRoles.isEmpty()) { + continue; + } } List realmRolesAvailable = new LinkedList(); MultivaluedHashMap resourceRolesAvailable = new MultivaluedHashMap(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java index f809e1dad7..705b258c4b 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/AdminPermissions.java @@ -46,6 +46,10 @@ public class AdminPermissions { return new MgmtPermissions(session, auth); } + public static RealmsPermissionEvaluator realms(KeycloakSession session, RealmModel adminsRealm, UserModel admin) { + return new MgmtPermissions(session, adminsRealm, admin); + } + public static AdminPermissionManagement management(KeycloakSession session, RealmModel realm) { return new MgmtPermissions(session, realm); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java index 2df495322b..400cee1fe6 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/permissions/MgmtPermissions.java @@ -107,6 +107,14 @@ class MgmtPermissions implements AdminPermissionEvaluator, AdminPermissionManage this.identity = new KeycloakIdentity(auth.getToken(), session); } } + + MgmtPermissions(KeycloakSession session, RealmModel adminsRealm, UserModel admin) { + this.session = session; + this.admin = admin; + this.adminsRealm = adminsRealm; + this.identity = new UserModelIdentity(adminsRealm, admin); + } + MgmtPermissions(KeycloakSession session, RealmModel realm, RealmModel adminsRealm, UserModel admin) { this(session, realm); this.admin = admin; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java index 9dad375df6..c69f489000 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java @@ -28,6 +28,9 @@ import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.EventType; +import org.keycloak.models.AccountRoles; +import org.keycloak.models.AdminRoles; +import org.keycloak.models.Constants; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.utils.TimeBasedOTP; import org.keycloak.representations.idm.ClientRepresentation; @@ -78,11 +81,18 @@ public class AccountTest extends AbstractTestRealmKeycloakTest { //UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost"); //ClientRepresentation accountApp = findClientInRealmRep(testRealm, ACCOUNT_MANAGEMENT_CLIENT_ID); UserRepresentation user2 = UserBuilder.create() - .enabled(true) - .username("test-user-no-access@localhost") - .email("test-user-no-access@localhost") - .password("password") - .build(); + .enabled(true) + .username("test-user-no-access@localhost") + .email("test-user-no-access@localhost") + .password("password") + .build(); + UserRepresentation realmAdmin = UserBuilder.create() + .enabled(true) + .username("realm-admin") + .password("password") + .role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.REALM_ADMIN) + .role(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID, AccountRoles.MANAGE_ACCOUNT) + .build(); testRealm.addIdentityProvider(IdentityProviderBuilder.create() .providerId("github") @@ -105,7 +115,8 @@ public class AccountTest extends AbstractTestRealmKeycloakTest { .build()); RealmBuilder.edit(testRealm) - .user(user2); + .user(user2) + .user(realmAdmin); } private static final UriBuilder BASE = UriBuilder.fromUri("http://localhost:8180/auth"); @@ -870,6 +881,19 @@ public class AccountTest extends AbstractTestRealmKeycloakTest { } } + // KEYCLOAK-5155 + @Test + public void testConsoleListedInApplications() { + applicationsPage.open(); + loginPage.login("realm-admin", "password"); + Assert.assertTrue(applicationsPage.isCurrent()); + Map apps = applicationsPage.getApplications(); + Assert.assertThat(apps.keySet(), hasItems("Admin CLI", "Security Admin Console")); + events.clear(); + } + + + // More tests (including revoke) are in OAuthGrantTest and OfflineTokenTest @Test public void applications() { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java index 2fb1d40dce..5ea5797cea 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java @@ -648,6 +648,60 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest { } } + + // KEYCLOAK-5152 + @Test + public void testMasterRealmWithComposites() throws Exception { + RoleRepresentation composite = new RoleRepresentation(); + composite.setName("composite"); + composite.setComposite(true); + adminClient.realm(TEST).roles().create(composite); + composite = adminClient.realm(TEST).roles().get("composite").toRepresentation(); + + RoleRepresentation compositePart = new RoleRepresentation(); + compositePart.setName("composite-part"); + adminClient.realm(TEST).roles().create(compositePart); + compositePart = adminClient.realm(TEST).roles().get("composite-part").toRepresentation(); + + List composites = new LinkedList<>(); + composites.add(compositePart); + adminClient.realm(TEST).rolesById().addComposites(composite.getId(), composites); + } + + public static void setup5152(KeycloakSession session) { + RealmModel realm = session.realms().getRealmByName(TEST); + ClientModel realmAdminClient = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID); + RoleModel realmAdminRole = realmAdminClient.getRole(AdminRoles.REALM_ADMIN); + + UserModel realmUser = session.users().addUser(realm, "realm-admin"); + realmUser.grantRole(realmAdminRole); + realmUser.setEnabled(true); + session.userCredentialManager().updateCredential(realm, realmUser, UserCredentialModel.password("password")); + } + + // KEYCLOAK-5152 + @Test + public void testRealmWithComposites() throws Exception { + testingClient.server().run(FineGrainAdminUnitTest::setup5152); + + Keycloak realmClient = AdminClientUtil.createAdminClient(suiteContext.isAdapterCompatTesting(), + TEST, "realm-admin", "password", Constants.ADMIN_CLI_CLIENT_ID, null); + + RoleRepresentation composite = new RoleRepresentation(); + composite.setName("composite"); + composite.setComposite(true); + realmClient.realm(TEST).roles().create(composite); + composite = adminClient.realm(TEST).roles().get("composite").toRepresentation(); + + RoleRepresentation compositePart = new RoleRepresentation(); + compositePart.setName("composite-part"); + realmClient.realm(TEST).roles().create(compositePart); + compositePart = adminClient.realm(TEST).roles().get("composite-part").toRepresentation(); + + List composites = new LinkedList<>(); + composites.add(compositePart); + realmClient.realm(TEST).rolesById().addComposites(composite.getId(), composites); + } // testRestEvaluationMasterRealm // testRestEvaluationMasterAdminTestRealm