[KEYCLOAK-8617] - Permission cache not handling decisions from negative policies correctly

This commit is contained in:
Pedro Igor 2018-10-19 16:54:59 -03:00
parent 2af9d002b6
commit 460cdf4508
2 changed files with 57 additions and 13 deletions

View file

@ -89,23 +89,19 @@ public class DefaultEvaluation implements Evaluation {
@Override
public void grant() {
if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
this.effect = Effect.DENY;
setEffect(Effect.DENY);
} else {
this.effect = Effect.PERMIT;
setEffect(Effect.PERMIT);
}
this.decision.onDecision(this);
}
@Override
public void deny() {
if (policy != null && Logic.NEGATIVE.equals(policy.getLogic())) {
this.effect = Effect.PERMIT;
setEffect(Effect.PERMIT);
} else {
this.effect = Effect.DENY;
setEffect(Effect.DENY);
}
this.decision.onDecision(this);
}
@Override
@ -274,10 +270,7 @@ public class DefaultEvaluation implements Evaluation {
}
public void setEffect(Effect effect) {
if (Effect.PERMIT.equals(effect)) {
grant();
} else {
deny();
}
this.effect = effect;
this.decision.onDecision(this);
}
}

View file

@ -50,6 +50,7 @@ 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.KeycloakModelUtils;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
@ -58,7 +59,10 @@ 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.representations.idm.authorization.Logic;
import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
import org.keycloak.representations.idm.authorization.ScopePermissionRepresentation;
import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import org.keycloak.testsuite.util.ClientBuilder;
@ -678,6 +682,53 @@ public class PolicyEvaluationTest extends AbstractAuthzTest {
}
}
@Test
public void testCachedDecisionsWithNegativePolicies() {
testingClient.server().run(PolicyEvaluationTest::testCachedDecisionsWithNegativePolicies);
}
public static void testCachedDecisionsWithNegativePolicies(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());
Scope readScope = storeFactory.getScopeStore().create("read", resourceServer);
Scope writeScope = storeFactory.getScopeStore().create("write", resourceServer);
JSPolicyRepresentation policy = new JSPolicyRepresentation();
policy.setName(KeycloakModelUtils.generateId());
policy.setCode("$evaluation.grant()");
policy.setLogic(Logic.NEGATIVE);
storeFactory.getPolicyStore().create(policy, resourceServer);
ScopePermissionRepresentation readPermission = new ScopePermissionRepresentation();
readPermission.setName(KeycloakModelUtils.generateId());
readPermission.addScope(readScope.getId());
readPermission.addPolicy(policy.getName());
storeFactory.getPolicyStore().create(readPermission, resourceServer);
ScopePermissionRepresentation writePermission = new ScopePermissionRepresentation();
writePermission.setName(KeycloakModelUtils.generateId());
writePermission.addScope(writeScope.getId());
writePermission.addPolicy(policy.getName());
storeFactory.getPolicyStore().create(writePermission, resourceServer);
Resource resource = storeFactory.getResourceStore().create(KeycloakModelUtils.generateId(), resourceServer, resourceServer.getId());
PermissionEvaluator evaluator = authorization.evaluators().from(Arrays.asList(new ResourcePermission(resource, Arrays.asList(readScope, writeScope), resourceServer)), createEvaluationContext(session, Collections.emptyMap()));
Collection<Permission> permissions = evaluator.evaluate(resourceServer, null);
Assert.assertEquals(0, permissions.size());
}
private static DefaultEvaluation createEvaluation(KeycloakSession session, AuthorizationProvider authorization, ResourceServer resourceServer, Policy policy) {
return createEvaluation(session, authorization, null, resourceServer, policy);
}