Avoid removing static path config from cache

Closes #9855
This commit is contained in:
Pedro Igor 2022-08-11 16:36:30 -03:00 committed by Bruno Oliveira da Silva
parent bd926b8fd0
commit 15bbb46657
3 changed files with 112 additions and 5 deletions

View file

@ -191,12 +191,16 @@ public class PolicyEnforcer {
if (resource != null) {
pathConfig.setId(resource.getId());
// if the resource is staticly bound to a resource it means the config can not be invalidated
// if the resource is statically bound to a resource it means the config can not be invalidated
if (resourceName != null) {
pathConfig.setStatic(true);
}
}
if (PolicyEnforcerConfig.EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
pathConfig.setStatic(true);
}
PathConfig existingPath = null;
for (PathConfig current : paths.values()) {
@ -282,11 +286,13 @@ public class PolicyEnforcer {
PolicyEnforcerConfig.EnforcementMode enforcementMode = PolicyEnforcerConfig.EnforcementMode.ENFORCING;
ResourceRepresentation targetResource = matchingResources.get(0);
List<PolicyEnforcerConfig.MethodConfig> methodConfig = null;
boolean isStatic = false;
if (pathConfig != null) {
cipConfig = pathConfig.getClaimInformationPointConfig();
enforcementMode = pathConfig.getEnforcementMode();
methodConfig = pathConfig.getMethods();
isStatic = pathConfig.isStatic();
} else {
for (PathConfig existingPath : paths.values()) {
if (targetResource.getId().equals(existingPath.getId())
@ -307,6 +313,7 @@ public class PolicyEnforcer {
pathConfig.setMethods(methodConfig);
}
pathConfig.setStatic(isStatic);
pathConfig.setEnforcementMode(enforcementMode);
}
} catch (Exception cause) {

View file

@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.keycloak.common.Profile.Feature.AUTHORIZATION;
import javax.security.cert.X509Certificate;
@ -85,13 +84,13 @@ import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.ProfileAssume;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.RoleBuilder;
import org.keycloak.testsuite.util.RolesBuilder;
import org.keycloak.testsuite.util.UserBuilder;
import org.keycloak.testsuite.util.WaitUtils;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@ -340,6 +339,76 @@ public class PolicyEnforcerTest extends AbstractKeycloakTest {
assertTrue(context.isGranted());
}
@Test
public void testDisabledPathNoCache() {
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-disabled-path-nocache.json"));
PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
OIDCHttpFacade httpFacade = createHttpFacade("/api/resource/public");
AuthorizationContext context = policyEnforcer.enforce(httpFacade);
assertTrue(context.isGranted());
ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID);
ResourceRepresentation resource = clientResource.authorization().resources()
.findByName("Root").get(0);
clientResource.authorization().resources().resource(resource.getId()).remove();
// first request caches the path and the entry is invalidated due to the lifespan
httpFacade = createHttpFacade("/api/resource/all-public");
context = policyEnforcer.enforce(httpFacade);
assertTrue(context.isGranted());
WaitUtils.pause(1000);
// second request can not fail because entry should not be invalidated
httpFacade = createHttpFacade("/api/resource/all-public");
context = policyEnforcer.enforce(httpFacade);
assertTrue(context.isGranted());
}
@Test
public void testLazyLoadedPathIsCached() {
ClientResource clientResource = getClientResource(RESOURCE_SERVER_CLIENT_ID);
createResource(clientResource, "Static Test Resource", "/api/any-resource/*");
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
permission.setName("Any Resource Permission");
permission.addResource("Static Test Resource");
permission.addPolicy("Always Grant Policy");
clientResource.authorization().permissions().resource().create(permission);
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-disabled-path-nocache.json"));
PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
oauth.realm(REALM_NAME);
oauth.clientId("public-client-test");
oauth.doLogin("marta", "password");
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
String token = response.getAccessToken();
OIDCHttpFacade httpFacade = createHttpFacade("/api/any-resource/test", token);
AuthorizationContext context = policyEnforcer.enforce(httpFacade);
assertTrue(context.isGranted());
httpFacade = createHttpFacade("/api/any-resource/test", token);
context = policyEnforcer.enforce(httpFacade);
assertTrue(context.isGranted());
ResourceRepresentation resource = clientResource.authorization().resources()
.findByName("Static Test Resource").get(0);
clientResource.authorization().resources().resource(resource.getId()).remove();
httpFacade = createHttpFacade("/api/any-resource/test", token);
context = policyEnforcer.enforce(httpFacade);
assertFalse(context.isGranted());
}
@Test
public void testEnforcementModeDisabled() {
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getAdapterConfiguration("enforcer-disabled-enforce-mode.json"));

View file

@ -0,0 +1,31 @@
{
"realm": "authz-test",
"auth-server-url": "http://localhost:8180/auth",
"ssl-required": "external",
"resource": "resource-server-test",
"credentials": {
"secret": "secret"
},
"bearer-only": true,
"policy-enforcer": {
"path-cache": {
"lifespan": 1
},
"paths": [
{
"name": "Resource B",
"path": "/api/resource/public",
"enforcement-mode": "DISABLED"
},
{
"name": "Nonexistent",
"path": "/api/resource/all-public/*",
"enforcement-mode": "DISABLED"
},
{
"name": "Static Test Resource",
"path": "/api/any-resource/test"
}
]
}
}