[KEYCLOAK-6628] - Expose methods to query roles, groups, and attributes of users in Evaluation API

This commit is contained in:
pedroigor 2018-03-15 14:02:15 -03:00
parent 22e32117e0
commit 711bf244ed
4 changed files with 845 additions and 0 deletions

View file

@ -18,11 +18,26 @@
package org.keycloak.authorization.policy.evaluation;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.Decision.Effect;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RoleUtils;
import org.keycloak.representations.idm.authorization.Logic;
/**
@ -36,6 +51,7 @@ public class DefaultEvaluation implements Evaluation {
private final Policy policy;
private final Policy parentPolicy;
private final AuthorizationProvider authorizationProvider;
private final Realm realm;
private Effect effect;
public DefaultEvaluation(ResourcePermission permission, EvaluationContext executionContext, Policy parentPolicy, Policy policy, Decision decision, AuthorizationProvider authorizationProvider) {
@ -45,6 +61,7 @@ public class DefaultEvaluation implements Evaluation {
this.policy = policy;
this.decision = decision;
this.authorizationProvider = authorizationProvider;
this.realm = createRealm();
}
@Override
@ -84,6 +101,11 @@ public class DefaultEvaluation implements Evaluation {
return this.policy;
}
@Override
public Realm getRealm() {
return realm;
}
@Override
public AuthorizationProvider getAuthorizationProvider() {
return authorizationProvider;
@ -102,4 +124,128 @@ public class DefaultEvaluation implements Evaluation {
deny();
}
}
private Realm createRealm() {
return new Realm() {
@Override
public boolean isUserInGroup(String id, String groupId, boolean checkParent) {
KeycloakSession session = authorizationProvider.getKeycloakSession();
UserModel user = getUser(id, session);
if (Objects.isNull(user)) {
return false;
}
RealmModel realm = session.getContext().getRealm();
GroupModel group = KeycloakModelUtils.findGroupByPath(realm, groupId);
if (Objects.isNull(group)) {
return false;
}
if (checkParent) {
return RoleUtils.isMember(user.getGroups(), group);
}
return user.isMemberOf(group);
}
private UserModel getUser(String id, KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
UserModel user = session.users().getUserById(id, realm);
if (Objects.isNull(user)) {
user = session.users().getUserByUsername(id, realm);
if (Objects.isNull(user)) {
user = session.users().getUserByEmail(id, realm);
}
}
return user;
}
@Override
public boolean isUserInRealmRole(String id, String roleName) {
KeycloakSession session = authorizationProvider.getKeycloakSession();
UserModel user = getUser(id, session);
if (Objects.isNull(user)) {
return false;
}
Set<RoleModel> roleMappings = user.getRoleMappings().stream()
.filter(role -> !role.isClientRole())
.collect(Collectors.toSet());
return RoleUtils.hasRole(roleMappings, session.getContext().getRealm().getRole(roleName));
}
@Override
public boolean isUserInClientRole(String id, String clientId, String roleName) {
KeycloakSession session = authorizationProvider.getKeycloakSession();
RealmModel realm = session.getContext().getRealm();
UserModel user = getUser(id, session);
if (Objects.isNull(user)) {
return false;
}
Set<RoleModel> roleMappings = user.getRoleMappings().stream()
.filter(role -> role.isClientRole() && ClientModel.class.cast(role.getContainer()).getClientId().equals(clientId))
.collect(Collectors.toSet());
if (roleMappings.isEmpty()) {
return false;
}
RoleModel role = realm.getClientById(ClientModel.class.cast(roleMappings.iterator().next().getContainer()).getId()).getRole(roleName);
if (Objects.isNull(role)) {
return false;
}
return RoleUtils.hasRole(roleMappings, role);
}
@Override
public boolean isGroupInRole(String id, String role) {
KeycloakSession session = authorizationProvider.getKeycloakSession();
RealmModel realm = session.getContext().getRealm();
GroupModel group = KeycloakModelUtils.findGroupByPath(realm, id);
return RoleUtils.hasRoleFromGroup(group, realm.getRole(role), false);
}
@Override
public List<String> getUserRealmRoles(String id) {
return getUser(id, authorizationProvider.getKeycloakSession()).getRoleMappings().stream()
.filter(role -> !role.isClientRole())
.map(RoleModel::getName)
.collect(Collectors.toList());
}
@Override
public List<String> getUserClientRoles(String id, String clientId) {
return getUser(id, authorizationProvider.getKeycloakSession()).getRoleMappings().stream()
.filter(role -> role.isClientRole())
.map(RoleModel::getName)
.collect(Collectors.toList());
}
@Override
public List<String> getUserGroups(String id) {
return getUser(id, authorizationProvider.getKeycloakSession()).getGroups().stream()
.map(ModelToRepresentation::buildGroupPath)
.collect(Collectors.toList());
}
@Override
public Map<String, List<String>> getUserAttributes(String id) {
Map<String, List<String>> attributes = getUser(id, authorizationProvider.getKeycloakSession()).getAttributes();
return attributes;
}
};
}
}

View file

@ -51,6 +51,13 @@ public interface Evaluation {
*/
Policy getPolicy();
/**
* Returns a {@link Realm} that can be used by policies to query information.
*
* @return a {@link Realm} instance
*/
Realm getRealm();
AuthorizationProvider getAuthorizationProvider();
/**

View file

@ -0,0 +1,114 @@
/*
* Copyright 2018 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.authorization.policy.evaluation;
import java.util.List;
import java.util.Map;
/**
* This interface provides methods to query information from a realm.
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public interface Realm {
/**
* <p>Checks whether or not a user with the given <code>id</code> is a member of the given <code>group</code>.
*
* <p>This method will also consider memberships where the user is a member of any child group of the given <code>group</code>.
* For instance, if user is member of <code>/Group A/Group B</code> and this method is checking if user is a member of <code>/Group A</code>
* the result will be <code>true</code> given that the user is a member of a child group of <code>/Group A</code>.
*
* @param id the user id. It can be the id, username or email
* @param group the group path. For instance, /Group A/Group B.
* @return true if user is a member of the given group. Otherwise returns false.
*/
default boolean isUserInGroup(String id, String group) {
return isUserInGroup(id, group, true);
}
/**
* Checks whether or not a user with the given <code>id</code> is a member of the given <code>group</code>.
*
* @param id the user id. It can be the id, username or email
* @param group the group path. For instance, /Group A/Group B.
* @param checkParent if true, this method returns true even though the user is not directly associated with the given group but a member of any child of the group.
* @return true if user is a member of the given group. Otherwise returns false.
*/
boolean isUserInGroup(String id, String group, boolean checkParent);
/**
* Checks whether or not a user with the given <code>id</code> is granted with the given realm <code>role</code>.
*
* @param id the user id. It can be the id, username or email
* @param role the role name
* @return true if the user is granted with the role. Otherwise, false.
*/
boolean isUserInRealmRole(String id, String role);
/**
* Checks whether or not a user with the given <code>id</code> is granted with the given client <code>role</code>.
*
* @param id the user id. It can be the id, username or email
* @param clientId the client id
* @param role the role name
* @return true if the user is granted with the role. Otherwise, false.
*/
boolean isUserInClientRole(String id, String clientId, String role);
/**
* Checks whether or not a <code>group</code> is granted with the given realm <code>role</code>.
*
* @param group the group path. For instance, /Group A/Group B.
* @param role the role name
* @return true if the group is granted with the role. Otherwise, false.
*/
boolean isGroupInRole(String group, String role);
/**
* Returns all realm roles granted for a user with the given <code>id</code>.
*
* @param id the user id. It can be the id, username or email
* @return the roles granted to the user
*/
List<String> getUserRealmRoles(String id);
/**
* Returns all client roles granted for a user with the given <code>id</code>.
*
* @param id the user id. It can be the id, username or email
* @param clientId the client id
* @return the roles granted to the user
*/
List<String> getUserClientRoles(String id, String clientId);
/**
* Returns all groups which the user with the given <code>id</code> is a member.
*
* @param id the user id. It can be the id, username or email
* @return the groups which the user is a member
*/
List<String> getUserGroups(String id);
/**
* Returns all attributes associated with the a user with the given <code>id</code>.
*
* @param id the user id. It can be the id, username or email
* @return a map with the attributes associated with the user
*/
Map<String, List<String>> getUserAttributes(String id);
}

View file

@ -0,0 +1,578 @@
/*
* Copyright 2018 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.authz;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.Decision;
import org.keycloak.authorization.Decision.Effect;
import org.keycloak.authorization.attribute.Attributes;
import org.keycloak.authorization.common.DefaultEvaluationContext;
import org.keycloak.authorization.identity.Identity;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.policy.evaluation.DefaultEvaluation;
import org.keycloak.authorization.policy.evaluation.Evaluation;
import org.keycloak.authorization.policy.provider.PolicyProvider;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.GroupBuilder;
import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.RoleBuilder;
import org.keycloak.testsuite.util.RolesBuilder;
import org.keycloak.testsuite.util.UserBuilder;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class PolicyEvaluationTest extends AbstractAuthzTest {
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
ProtocolMapperRepresentation groupProtocolMapper = new ProtocolMapperRepresentation();
groupProtocolMapper.setName("groups");
groupProtocolMapper.setProtocolMapper(GroupMembershipMapper.PROVIDER_ID);
groupProtocolMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
groupProtocolMapper.setConsentRequired(false);
Map<String, String> config = new HashMap<>();
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "groups");
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
config.put("full.path", "true");
groupProtocolMapper.setConfig(config);
testRealms.add(RealmBuilder.create().name("authz-test")
.roles(RolesBuilder.create()
.realmRole(RoleBuilder.create().name("uma_authorization").build())
.realmRole(RoleBuilder.create().name("role-a").build())
.realmRole(RoleBuilder.create().name("role-b").build())
)
.group(GroupBuilder.create().name("Group A")
.subGroups(Arrays.asList("Group B", "Group D").stream().map(name -> {
if ("Group B".equals(name)) {
return GroupBuilder.create().name(name).subGroups(Arrays.asList("Group C", "Group E").stream().map(new Function<String, GroupRepresentation>() {
@Override
public GroupRepresentation apply(String name) {
return GroupBuilder.create().name(name).build();
}
}).collect(Collectors.toList())).build();
}
return GroupBuilder.create().name(name).realmRoles(Arrays.asList("role-a")).build();
}).collect(Collectors.toList())).build())
.group(GroupBuilder.create().name("Group E").build())
.user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization", "role-a").addGroups("Group A"))
.user(UserBuilder.create().username("alice").password("password").addRoles("uma_authorization").addGroups("/Group A/Group B/Group E"))
.user(UserBuilder.create().username("kolo").password("password").addRoles("uma_authorization").addGroups("/Group A/Group D"))
.user(UserBuilder.create().username("trinity").password("password").addRoles("uma_authorization").role("role-mapping-client", "client-role-a"))
.user(UserBuilder.create().username("jdoe").password("password").addGroups("/Group A/Group B", "/Group A/Group D"))
.client(ClientBuilder.create().clientId("resource-server-test")
.secret("secret")
.authorizationServicesEnabled(true)
.redirectUris("http://localhost/resource-server-test")
.defaultRoles("uma_protection")
.directAccessGrants()
.protocolMapper(groupProtocolMapper))
.client(ClientBuilder.create().clientId("role-mapping-client")
.defaultRoles("client-role-a", "client-role-b"))
.build());
}
@Deployment
public static WebArchive deploy() {
return RunOnServerDeployment.create(AbstractAuthzTest.class);
}
@Test
public void testCheckUserInGroup() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserInGroup);
}
public static void testCheckUserInGroup(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserInGroup");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('marta', 'Group C')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('marta', 'Group A')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('marta', '/Group A')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('marta', '/Group A/Group B')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('alice', '/Group A/Group B/Group E')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('alice', '/Group A')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (!realm.isUserInGroup('alice', '/Group A', false)) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('alice', '/Group E')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInGroup('alice', 'Group E')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
}
@Test
public void testCheckUserInRole() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserInRole);
}
public static void testCheckUserInRole(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserInRole");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInRealmRole('marta', 'role-a')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInRealmRole('marta', 'role-b')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
}
@Test
public void testCheckUserInClientRole() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserInClientRole);
}
public static void testCheckUserInClientRole(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserInClientRole");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInClientRole('trinity', 'role-mapping-client', 'client-role-a')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isUserInRealmRole('trinity', 'client-role-b')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
}
@Test
public void testCheckGroupInRole() {
testingClient.server().run(PolicyEvaluationTest::testCheckGroupInRole);
}
public static void testCheckGroupInRole(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckGroupInRole");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isGroupInRole('/Group A/Group D', 'role-a')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("if (realm.isGroupInRole('/Group A/Group D', 'role-b')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
policyRepresentation.setId(policy.getId());
policy = RepresentationToModel.toModel(policyRepresentation, authorization, policy);
evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertNull(evaluation.getEffect());
}
@Test
public void testCheckUserRealmRoles() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserRealmRoles);
}
public static void testCheckUserRealmRoles(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserRealmRoles");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("var roles = realm.getUserRealmRoles('marta');");
builder.append("if (roles.size() == 2 && roles.contains('uma_authorization') && roles.contains('role-a')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
}
@Test
public void testCheckUserClientRoles() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserClientRoles);
}
public static void testCheckUserClientRoles(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserClientRoles");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("var roles = realm.getUserClientRoles('trinity', 'role-mapping-client');");
builder.append("if (roles.size() == 1 && roles.contains('client-role-a')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
}
@Test
public void testCheckUserGroups() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserGroups);
}
public static void testCheckUserGroups(KeycloakSession session) {
session.getContext().setRealm(session.realms().getRealmByName("authz-test"));
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserGroups");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("var groups = realm.getUserGroups('jdoe');");
builder.append("if (groups.size() == 2 && groups.contains('/Group A/Group B') && groups.contains('/Group A/Group D')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
}
@Test
public void testCheckUserAttributes() {
testingClient.server().run(PolicyEvaluationTest::testCheckUserAttributes);
}
public static void testCheckUserAttributes(KeycloakSession session) {
RealmModel realm = session.realms().getRealmByName("authz-test");
UserModel jdoe = session.users().getUserByUsername("jdoe", realm);
jdoe.setAttribute("a1", Arrays.asList("1", "2"));
jdoe.setSingleAttribute("a2", "3");
session.getContext().setRealm(realm);
AuthorizationProvider authorization = session.getProvider(AuthorizationProvider.class);
ClientModel clientModel = session.realms().getClientByClientId("resource-server-test", session.getContext().getRealm());
StoreFactory storeFactory = authorization.getStoreFactory();
ResourceServer resourceServer = storeFactory.getResourceServerStore().findById(clientModel.getId());
JSPolicyRepresentation policyRepresentation = new JSPolicyRepresentation();
policyRepresentation.setName("testCheckUserAttributes");
StringBuilder builder = new StringBuilder();
builder.append("var realm = $evaluation.getRealm();");
builder.append("var attributes = realm.getUserAttributes('jdoe');");
builder.append("if (attributes.size() == 2 && attributes.containsKey('a1') && attributes.containsKey('a2') && attributes.get('a1').size() == 2 && attributes.get('a2').get(0).equals('3')) { $evaluation.grant(); }");
policyRepresentation.setCode(builder.toString());
Policy policy = storeFactory.getPolicyStore().create(policyRepresentation, resourceServer);
PolicyProvider provider = authorization.getProvider(policy.getType());
DefaultEvaluation evaluation = createEvaluation(session, authorization, resourceServer, policy);
provider.evaluate(evaluation);
Assert.assertEquals(Effect.PERMIT, evaluation.getEffect());
}
@NotNull
private static DefaultEvaluation createEvaluation(KeycloakSession session, AuthorizationProvider authorization, ResourceServer resourceServer, Policy policy) {
return new DefaultEvaluation(new ResourcePermission(null, null, resourceServer), new DefaultEvaluationContext(new Identity() {
@Override
public String getId() {
return null;
}
@Override
public Attributes getAttributes() {
return null;
}
}, session), policy, policy, new Decision() {
@Override
public void onDecision(Evaluation evaluation) {
}
}, authorization);
}
}