From a939c45d5845f03c93a59e6295f878596d4b41a3 Mon Sep 17 00:00:00 2001 From: pedroigor Date: Tue, 3 Apr 2018 16:44:27 -0300 Subject: [PATCH] [KEYCLOAK-7029] - Configuration of cache policies for cached resources/path --- .../authorization/AbstractPolicyEnforcer.java | 4 +- .../adapters/authorization/PathCache.java | 6 + .../authorization/PolicyEnforcer.java | 116 ++++++++++-------- .../client/ClientAuthorizationContext.java | 4 +- .../org/keycloak/AuthorizationContext.java | 6 +- .../adapters/config/PolicyEnforcerConfig.java | 35 ++++++ .../AbstractPolicyRepresentation.java | 6 + ...keycloak-cache-disabled-authz-service.json | 26 ++++ ...keycloak-cache-lifespan-authz-service.json | 26 ++++ ...stractServletCacheDisabledAdapterTest.java | 86 +++++++++++++ ...stractServletCacheLifespanAdapterTest.java | 81 ++++++++++++ ...ildflyServletCacheDisabledAdapterTest.java | 31 +++++ ...ildflyServletCacheLifespanAdapterTest.java | 31 +++++ 13 files changed, 402 insertions(+), 56 deletions(-) create mode 100644 testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-disabled-authz-service.json create mode 100644 testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-lifespan-authz-service.json create mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheDisabledAdapterTest.java create mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheLifespanAdapterTest.java create mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheDisabledAdapterTest.java create mode 100644 testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheLifespanAdapterTest.java diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java index c600e1aa9e..402ed48d1e 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java @@ -159,7 +159,7 @@ public abstract class AbstractPolicyEnforcer { LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, grantedPermissions); } if (HTTP_METHOD_DELETE.equalsIgnoreCase(request.getMethod()) && actualPathConfig.isInstance()) { - policyEnforcer.getPaths().remove(actualPathConfig); + policyEnforcer.getPathMatcher().removeFromCache(getPath(request)); } return true; } @@ -281,7 +281,7 @@ public abstract class AbstractPolicyEnforcer { } private AuthorizationContext createAuthorizationContext(AccessToken accessToken, PathConfig pathConfig) { - return new ClientAuthorizationContext(accessToken, pathConfig, policyEnforcer.getPaths(), getAuthzClient()); + return new ClientAuthorizationContext(accessToken, pathConfig, getAuthzClient()); } private boolean isResourcePermission(PathConfig actualPathConfig, Permission permission) { diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathCache.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathCache.java index cf8815c6a9..dfeb48efc9 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathCache.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PathCache.java @@ -40,6 +40,7 @@ public class PathCache { private final AtomicBoolean writing = new AtomicBoolean(false); private final long maxAge; + private final boolean enabled; /** * Creates a new instance. @@ -55,9 +56,14 @@ public class PathCache { } }; this.maxAge = maxAge; + this.enabled = maxAge > 0; } public void put(String uri, PathConfig newValue) { + if (!enabled) { + return; + } + try { if (parkForWriteAndCheckInterrupt()) { return; diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java index 275315e4bf..2ccdf28a91 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java @@ -38,6 +38,7 @@ import org.keycloak.authorization.client.resource.ProtectedResource; import org.keycloak.common.util.PathMatcher; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; +import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCacheConfig; import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig; import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.ResourceRepresentation; @@ -52,8 +53,8 @@ public class PolicyEnforcer { private final KeycloakDeployment deployment; private final AuthzClient authzClient; private final PolicyEnforcerConfig enforcerConfig; + private final PathConfigMatcher pathMatcher; private final Map paths; - private final PathMatcher pathMatcher; public PolicyEnforcer(KeycloakDeployment deployment, AdapterConfig adapterConfig) { this.deployment = deployment; @@ -70,8 +71,8 @@ public class PolicyEnforcer { } }); - this.paths = configurePaths(this.authzClient.protection().resource(), this.enforcerConfig); - this.pathMatcher = createPathMatcher(authzClient); + paths = configurePaths(this.authzClient.protection().resource(), this.enforcerConfig); + pathMatcher = new PathConfigMatcher(paths, enforcerConfig, authzClient); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Initialization complete. Path configurations:"); @@ -117,7 +118,7 @@ public class PolicyEnforcer { return paths; } - public PathMatcher getPathMatcher() { + public PathConfigMatcher getPathMatcher() { return pathMatcher; } @@ -216,71 +217,90 @@ public class PolicyEnforcer { return paths; } - private PathMatcher createPathMatcher(final AuthzClient authzClient) { - final PathCache pathCache = new PathCache(100, 30000); + public class PathConfigMatcher extends PathMatcher { - return new PathMatcher() { - @Override - public PathConfig matches(String targetUri) { - PathConfig pathConfig = pathCache.get(targetUri); + private final Map paths; + private final PathCache pathCache; + private final AuthzClient authzClient; + private final PolicyEnforcerConfig enforcerConfig; - if (pathCache.containsKey(targetUri) || pathConfig != null) { - return pathConfig; - } + public PathConfigMatcher(Map paths, PolicyEnforcerConfig enforcerConfig, AuthzClient authzClient) { + this.paths = paths; + this.enforcerConfig = enforcerConfig; + PathCacheConfig cacheConfig = enforcerConfig.getPathCacheConfig(); - pathConfig = super.matches(targetUri); + if (cacheConfig == null) { + cacheConfig = new PathCacheConfig(); + } - if (enforcerConfig.getLazyLoadPaths() && (pathConfig == null || pathConfig.getPath().contains("*"))) { + pathCache = new PathCache(cacheConfig.getMaxEntries(), cacheConfig.getLifespan()); + this.authzClient = authzClient; + } + + @Override + public PathConfig matches(String targetUri) { + PathConfig pathConfig = pathCache.get(targetUri); + + if (pathCache.containsKey(targetUri) || pathConfig != null) { + return pathConfig; + } + + pathConfig = super.matches(targetUri); + + if (enforcerConfig.getLazyLoadPaths() || enforcerConfig.getPathCacheConfig() != null) { + if ((pathConfig == null || (pathConfig.getPath().contains("*")))) { try { List matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri); if (!matchingResources.isEmpty()) { pathConfig = PathConfig.createPathConfig(matchingResources.get(0)); - paths.put(pathConfig.getPath(), pathConfig); } } catch (Exception cause) { - LOGGER.errorf(cause, "Could not lazy load paths from server"); + LOGGER.errorf(cause, "Could not lazy load resource with path [" + targetUri + "] from server"); return null; } } - - pathCache.put(targetUri, pathConfig); - - return pathConfig; } - @Override - protected String getPath(PathConfig entry) { - return entry.getPath(); - } + pathCache.put(targetUri, pathConfig); - @Override - protected Collection getPaths() { - return paths.values(); - } + return pathConfig; + } - @Override - protected PathConfig resolvePathConfig(PathConfig originalConfig, String path) { - if (originalConfig.hasPattern()) { - ProtectedResource resource = authzClient.protection().resource(); - List search = resource.findByUri(path); + @Override + protected String getPath(PathConfig entry) { + return entry.getPath(); + } - if (!search.isEmpty()) { - // resource does exist on the server, cache it - ResourceRepresentation targetResource = search.get(0); - PathConfig config = PathConfig.createPathConfig(targetResource); + @Override + protected Collection getPaths() { + return paths.values(); + } - config.setScopes(originalConfig.getScopes()); - config.setMethods(originalConfig.getMethods()); - config.setParentConfig(originalConfig); - config.setEnforcementMode(originalConfig.getEnforcementMode()); + @Override + protected PathConfig resolvePathConfig(PathConfig originalConfig, String path) { + if (originalConfig.hasPattern()) { + ProtectedResource resource = authzClient.protection().resource(); + List search = resource.findByUri(path); - return config; - } + if (!search.isEmpty()) { + ResourceRepresentation targetResource = search.get(0); + PathConfig config = PathConfig.createPathConfig(targetResource); + + config.setScopes(originalConfig.getScopes()); + config.setMethods(originalConfig.getMethods()); + config.setParentConfig(originalConfig); + config.setEnforcementMode(originalConfig.getEnforcementMode()); + + return config; } - - return null; } - }; - } + + return null; + } + + public void removeFromCache(String pathConfig) { + pathCache.remove(pathConfig); + } + }; } diff --git a/authz/client/src/main/java/org/keycloak/authorization/client/ClientAuthorizationContext.java b/authz/client/src/main/java/org/keycloak/authorization/client/ClientAuthorizationContext.java index a46e5111f2..d848b253db 100644 --- a/authz/client/src/main/java/org/keycloak/authorization/client/ClientAuthorizationContext.java +++ b/authz/client/src/main/java/org/keycloak/authorization/client/ClientAuthorizationContext.java @@ -30,8 +30,8 @@ public class ClientAuthorizationContext extends AuthorizationContext { private final AuthzClient client; - public ClientAuthorizationContext(AccessToken authzToken, PolicyEnforcerConfig.PathConfig current, Map paths, AuthzClient client) { - super(authzToken, current, paths); + public ClientAuthorizationContext(AccessToken authzToken, PolicyEnforcerConfig.PathConfig current, AuthzClient client) { + super(authzToken, current); this.client = client; } diff --git a/core/src/main/java/org/keycloak/AuthorizationContext.java b/core/src/main/java/org/keycloak/AuthorizationContext.java index 538a70f51b..0bc7b44fe8 100644 --- a/core/src/main/java/org/keycloak/AuthorizationContext.java +++ b/core/src/main/java/org/keycloak/AuthorizationContext.java @@ -33,18 +33,16 @@ public class AuthorizationContext { private final AccessToken authzToken; private final PathConfig current; - private final Map paths; private boolean granted; - public AuthorizationContext(AccessToken authzToken, PathConfig current, Map paths) { + public AuthorizationContext(AccessToken authzToken, PathConfig current) { this.authzToken = authzToken; this.current = current; - this.paths = paths; this.granted = true; } public AuthorizationContext() { - this(null, null, null); + this(null, null); this.granted = false; } diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java index 71b44a4cdb..d01d7c5d15 100644 --- a/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java +++ b/core/src/main/java/org/keycloak/representations/adapters/config/PolicyEnforcerConfig.java @@ -38,6 +38,10 @@ public class PolicyEnforcerConfig { @JsonInclude(JsonInclude.Include.NON_EMPTY) private List paths = new ArrayList<>(); + @JsonProperty("path-cache") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private PathCacheConfig pathCacheConfig; + @JsonProperty("lazy-load-paths") private Boolean lazyLoadPaths = Boolean.FALSE; @@ -53,6 +57,10 @@ public class PolicyEnforcerConfig { return this.paths; } + public PathCacheConfig getPathCacheConfig() { + return pathCacheConfig; + } + public Boolean getLazyLoadPaths() { return lazyLoadPaths; } @@ -77,6 +85,10 @@ public class PolicyEnforcerConfig { this.paths = paths; } + public void setPathCacheConfig(PathCacheConfig pathCacheConfig) { + this.pathCacheConfig = pathCacheConfig; + } + public String getOnDenyRedirectTo() { return onDenyRedirectTo; } @@ -250,6 +262,29 @@ public class PolicyEnforcerConfig { } } + public static class PathCacheConfig { + + @JsonProperty("max-entries") + int maxEntries = 1000; + long lifespan = 30000; + + public int getMaxEntries() { + return maxEntries; + } + + public void setMaxEntries(int maxEntries) { + this.maxEntries = maxEntries; + } + + public long getLifespan() { + return lifespan; + } + + public void setLifespan(long lifespan) { + this.lifespan = lifespan; + } + } + public enum EnforcementMode { PERMISSIVE, ENFORCING, diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java index ddac66dfc0..ada763c9fc 100644 --- a/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/authorization/AbstractPolicyRepresentation.java @@ -99,6 +99,12 @@ public class AbstractPolicyRepresentation { this.policies.addAll(Arrays.asList(id)); } + public void removePolicy(String policy) { + if (policies != null) { + policies.remove(policy); + } + } + public Set getResources() { return resources; } diff --git a/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-disabled-authz-service.json b/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-disabled-authz-service.json new file mode 100644 index 0000000000..29979d8adc --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-disabled-authz-service.json @@ -0,0 +1,26 @@ +{ + "realm": "servlet-authz", + "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "auth-server-url" : "http://localhost:8180/auth", + "ssl-required" : "external", + "resource" : "servlet-authz-app", + "public-client" : false, + "credentials": { + "secret": "secret" + }, + "policy-enforcer": { + "on-deny-redirect-to" : "/servlet-authz-app/accessDenied.jsp", + "path-cache": { + "lifespan": 0, + "max-entries": 1000 + }, + "paths": [ + { + "name": "Premium Resource", + "path": "/protected/premium/pep-disabled.jsp", + "enforcement-mode": "DISABLED" + } + ] + + } +} \ No newline at end of file diff --git a/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-lifespan-authz-service.json b/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-lifespan-authz-service.json new file mode 100644 index 0000000000..d4b4af7669 --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/servlet-authz/keycloak-cache-lifespan-authz-service.json @@ -0,0 +1,26 @@ +{ + "realm": "servlet-authz", + "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "auth-server-url" : "http://localhost:8180/auth", + "ssl-required" : "external", + "resource" : "servlet-authz-app", + "public-client" : false, + "credentials": { + "secret": "secret" + }, + "policy-enforcer": { + "on-deny-redirect-to" : "/servlet-authz-app/accessDenied.jsp", + "path-cache": { + "lifespan": 5000, + "max-entries": 1000 + }, + "paths": [ + { + "name": "Premium Resource", + "path": "/protected/premium/pep-disabled.jsp", + "enforcement-mode": "DISABLED" + } + ] + + } +} \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheDisabledAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheDisabledAdapterTest.java new file mode 100644 index 0000000000..8bc641a930 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheDisabledAdapterTest.java @@ -0,0 +1,86 @@ +/* + * 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.adapter.example.authorization; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation; +import org.keycloak.representations.idm.authorization.ResourceRepresentation; + +/** + * @author Pedro Igor + */ +public abstract class AbstractServletCacheDisabledAdapterTest extends AbstractServletAuthzFunctionalAdapterTest { + + @Deployment(name = RESOURCE_SERVER_ID, managed = false) + public static WebArchive deployment() throws IOException { + return exampleDeployment(RESOURCE_SERVER_ID) + .addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-cache-disabled-authz-service.json"), "keycloak.json"); + } + + @Test + public void testCreateNewResource() { + performTests(() -> { + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertFalse(wasDenied()); + + ResourceRepresentation resource = new ResourceRepresentation(); + + resource.setName("New Resource"); + resource.setUri("/new-resource"); + + getAuthorizationResource().resources().create(resource); + + ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); + + permission.setName(resource.getName() + " Permission"); + permission.addResource(resource.getName()); + permission.addPolicy("Deny Policy"); + + permission = getAuthorizationResource().permissions().resource().create(permission).readEntity(ResourcePermissionRepresentation.class); + + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertTrue(wasDenied()); + + permission = getAuthorizationResource().permissions().resource().findById(permission.getId()).toRepresentation(); + + permission.removePolicy("Deny Policy"); + permission.addPolicy("Any User Policy"); + + getAuthorizationResource().permissions().resource().findById(permission.getId()).update(permission); + + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertFalse(wasDenied()); + }); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheLifespanAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheLifespanAdapterTest.java new file mode 100644 index 0000000000..6477cd4b0c --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractServletCacheLifespanAdapterTest.java @@ -0,0 +1,81 @@ +/* + * 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.adapter.example.authorization; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation; +import org.keycloak.representations.idm.authorization.ResourceRepresentation; + +/** + * @author Pedro Igor + */ +public abstract class AbstractServletCacheLifespanAdapterTest extends AbstractServletAuthzFunctionalAdapterTest { + + @Deployment(name = RESOURCE_SERVER_ID, managed = false) + public static WebArchive deployment() throws IOException { + return exampleDeployment(RESOURCE_SERVER_ID) + .addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-cache-lifespan-authz-service.json"), "keycloak.json"); + } + + @Test + public void testCreateNewResourceWaitExpiration() { + performTests(() -> { + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertFalse(wasDenied()); + + ResourceRepresentation resource = new ResourceRepresentation(); + + resource.setName("New Resource"); + resource.setUri("/new-resource"); + + getAuthorizationResource().resources().create(resource); + + ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation(); + + permission.setName(resource.getName() + " Permission"); + permission.addResource(resource.getName()); + permission.addPolicy("Deny Policy"); + + permission = getAuthorizationResource().permissions().resource().create(permission).readEntity(ResourcePermissionRepresentation.class); + + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertFalse(wasDenied()); + + Thread.sleep(5000); + + login("alice", "alice"); + assertFalse(wasDenied()); + + this.driver.navigate().to(getResourceServerUrl() + "/new-resource"); + assertTrue(wasDenied()); + }); + } +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheDisabledAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheDisabledAdapterTest.java new file mode 100644 index 0000000000..c4aec94a05 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheDisabledAdapterTest.java @@ -0,0 +1,31 @@ +/* + * 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.adapter.example.authorization; + +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * + * @author Pedro Igor + */ +@RunAsClient +@AppServerContainer("app-server-wildfly") +//@AdapterLibsLocationProperty("adapter.libs.wildfly") +public class WildflyServletCacheDisabledAdapterTest extends AbstractServletCacheDisabledAdapterTest { + +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheLifespanAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheLifespanAdapterTest.java new file mode 100644 index 0000000000..c3e75efe02 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/authorization/WildflyServletCacheLifespanAdapterTest.java @@ -0,0 +1,31 @@ +/* + * 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.adapter.example.authorization; + +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * + * @author Pedro Igor + */ +@RunAsClient +@AppServerContainer("app-server-wildfly") +//@AdapterLibsLocationProperty("adapter.libs.wildfly") +public class WildflyServletCacheLifespanAdapterTest extends AbstractServletCacheLifespanAdapterTest { + +}