/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.admin;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.authorization.DecisionEffect;
import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.PolicyEvaluationRequest;
import org.keycloak.representations.idm.authorization.PolicyEvaluationResponse;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Ignore
public class FineGrainAdminLocalTest extends AbstractKeycloakTest {
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation testRealmRep = new RealmRepresentation();
testRealmRep.setId(TEST);
testRealmRep.setRealm(TEST);
testRealmRep.setEnabled(true);
testRealms.add(testRealmRep);
}
public static void setupDefaults(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
ClientModel client = realm.getClientByClientId("realm-management");
AuthorizationProvider authz = session.getProvider(AuthorizationProvider.class);
ResourceServer resourceServer = authz.getStoreFactory().getResourceServerStore().create(client.getId());
Scope mapRoleScope = authz.getStoreFactory().getScopeStore().create("map-role", resourceServer);
Scope manageScope = authz.getStoreFactory().getScopeStore().create("manage", resourceServer);
Policy manageUsersPolicy = null;
Policy manageClientsPolicy = null;
for (RoleModel role : client.getRoles()) {
Policy policy = createRolePolicy(authz, resourceServer, role);
if (role.getName().equals(AdminRoles.MANAGE_USERS)) {
manageUsersPolicy = policy;
} else if (role.getName().equals(AdminRoles.MANAGE_CLIENTS)) {
manageClientsPolicy = policy;
}
Resource resource = createRoleResource(authz, resourceServer, role);
Set<Scope> scopeset = new HashSet<>();
scopeset.add(mapRoleScope);
resource.updateScopes(scopeset);
String name = "map.role.permission." + client.getClientId() + "." + role.getName();
Policy permission = addScopePermission(authz, resourceServer, name, resource, mapRoleScope, policy);
}
Resource usersResource = authz.getStoreFactory().getResourceStore().create("Users", resourceServer, resourceServer.getClientId());
Set<Scope> scopeset = new HashSet<>();
scopeset.add(manageScope);
usersResource.updateScopes(scopeset);
addScopePermission(authz, resourceServer, "Users.manage.permission", usersResource, manageScope, manageUsersPolicy);
}
private static Policy addScopePermission(AuthorizationProvider authz, ResourceServer resourceServer, String name, Resource resource, Scope scope, Policy policy) {
ScopePermissionRepresentation representation = new ScopePermissionRepresentation();
representation.setName(name);
representation.setDecisionStrategy(DecisionStrategy.UNANIMOUS);
representation.setLogic(Logic.POSITIVE);
representation.addResource(resource.getName());
representation.addScope(scope.getName());
representation.addPolicy(policy.getName());
return authz.getStoreFactory().getPolicyStore().create(representation, resourceServer);
}
private static Resource createRoleResource(AuthorizationProvider authz, ResourceServer resourceServer, RoleModel role) {
String roleName = getRoleResourceName(role);
Resource resource = authz.getStoreFactory().getResourceStore().create(roleName, resourceServer, resourceServer.getClientId());
resource.setType("Role");
return resource;
}
private static String getRoleResourceName(RoleModel role) {
String roleName = "realm";
if (role.getContainer() instanceof ClientModel) {
ClientModel client = (ClientModel)role.getContainer();
roleName = client.getClientId();
}
roleName = "role.resource." + roleName + "." + role.getName();
return roleName;
}
private static Policy createRolePolicy(AuthorizationProvider authz, ResourceServer resourceServer, RoleModel role) {
String roleName = "realm";
if (role.getContainer() instanceof ClientModel) {
ClientModel client = (ClientModel) role.getContainer();
roleName = client.getClientId() ;
}
roleName = "role.policy." + roleName + "." + role.getName();
PolicyRepresentation representation = new PolicyRepresentation();
representation.setName(roleName);
representation.setType("role");
representation.setDecisionStrategy(DecisionStrategy.UNANIMOUS);
representation.setLogic(Logic.POSITIVE);
String roleValues = "[{\"id\":\"" + role.getId() + "\",\"required\": true}]";
Map<String, String> config = new HashMap<>();
config.put("roles", roleValues);
representation.setConfig(config);
return authz.getStoreFactory().getPolicyStore().create(representation, resourceServer);
}
public static void setupUsers(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
ClientModel client = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
UserModel admin = session.users().addUser(realm, "admin");
admin.grantRole(client.getRole(AdminRoles.REALM_ADMIN));
UserModel manageUserOnlyUser = session.users().addUser(realm, "manage-user");
RoleModel manageUsersRole = client.getRole(AdminRoles.MANAGE_USERS);
manageUserOnlyUser.grantRole(manageUsersRole);
UserModel manageRealmUser = session.users().addUser(realm, "manage-realm");
manageRealmUser.grantRole(manageUsersRole);
RoleModel manageRealmRole = client.getRole(AdminRoles.MANAGE_REALM);
manageRealmUser.grantRole(manageRealmRole);
}
@Test
public void testUI() throws Exception {
testingClient.server().run(FineGrainAdminLocalTest::setupDefaults);
testingClient.server().run(FineGrainAdminLocalTest::setupUsers);
//Thread.sleep(1000000000);
}
public static void evaluateAdminHasManageRealmPermissions(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName(TEST);
UserModel admin = session.users().getUserByUsername("admin", realm);
AuthorizationProvider authz = session.getProvider(AuthorizationProvider.class);
ClientModel client = realm.getClientByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID);
ResourceServer resourceServer = authz.getStoreFactory().getResourceServerStore().findByClient(client.getId());
RoleModel manageRealmRole = client.getRole(AdminRoles.MANAGE_REALM);
Resource roleResource = authz.getStoreFactory().getResourceStore().findByName(getRoleResourceName(manageRealmRole), resourceServer.getId());
}
@Test
public void testEvaluation() throws Exception {
testingClient.server().run(FineGrainAdminLocalTest::setupDefaults);
testingClient.server().run(FineGrainAdminLocalTest::setupUsers);
RealmResource realm = adminClient.realm(TEST);
String resourceServerId = realm.clients().findByClientId(Constants.REALM_MANAGEMENT_CLIENT_ID).get(0).getId();
UserRepresentation admin = realm.users().search("admin").get(0);
UserRepresentation manageUser = realm.users().search("manage-user").get(0);
UserRepresentation manageRealm = realm.users().search("manage-realm").get(0);
PolicyEvaluationRequest request = new PolicyEvaluationRequest();
request.setUserId(admin.getId());
request.setClientId(resourceServerId);
request.addResource("role.resource." + Constants.REALM_MANAGEMENT_CLIENT_ID + "." + AdminRoles.MANAGE_REALM,
"map-role");
PolicyEvaluationResponse result = realm.clients().get(resourceServerId).authorization().policies().evaluate(request);
Assert.assertEquals(result.getStatus(), DecisionEffect.PERMIT);
}
}