[KEYCLOAK-13942] - Invalidate pre-defined paths when paths are invalidated
This commit is contained in:
parent
882f5ffea4
commit
40efbb0f9c
12 changed files with 1091 additions and 586 deletions
|
@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
/**
|
||||
|
@ -42,14 +43,16 @@ public class PathCache {
|
|||
|
||||
private final long maxAge;
|
||||
private final boolean enabled;
|
||||
private final Map<String, PathConfig> paths;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param maxEntries the maximum number of entries to keep in the cache
|
||||
* @param maxEntries the maximum number of entries to keep in the cache
|
||||
* @param maxAge the time in milliseconds that an entry can stay in the cache. If {@code -1}, entries never expire
|
||||
* @param paths the pre-configured paths
|
||||
*/
|
||||
public PathCache(final int maxEntries, long maxAge) {
|
||||
public PathCache(final int maxEntries, long maxAge,
|
||||
Map<String, PathConfig> paths) {
|
||||
cache = new LinkedHashMap<String, CacheEntry>(16, DEFAULT_LOAD_FACTOR, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||
|
@ -58,10 +61,15 @@ public class PathCache {
|
|||
};
|
||||
this.maxAge = maxAge;
|
||||
this.enabled = ! (maxAge < -1 || (maxAge > -1 && maxAge <= 0));
|
||||
this.paths = paths;
|
||||
}
|
||||
|
||||
public void put(String uri, PathConfig newValue) {
|
||||
if (!enabled) {
|
||||
if (newValue != null) {
|
||||
// if disabled we also remove from the pre-defined paths map
|
||||
markForInvalidation(newValue);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -80,6 +88,15 @@ public class PathCache {
|
|||
}
|
||||
}
|
||||
|
||||
private void markForInvalidation(PathConfig newValue) {
|
||||
PathConfig pathConfig = paths.get(newValue.getPath());
|
||||
|
||||
if (pathConfig != null && !pathConfig.isStatic()) {
|
||||
// invalidate the configuration so that the path config is reload based on latest changes on the server
|
||||
pathConfig.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(String uri) {
|
||||
return cache.containsKey(uri);
|
||||
}
|
||||
|
@ -115,12 +132,19 @@ public class PathCache {
|
|||
return null;
|
||||
}
|
||||
|
||||
PathConfig config = cached.value();
|
||||
|
||||
if (cached.isExpired()) {
|
||||
remove(cached.key());
|
||||
|
||||
if (config != null && config.getPath() != null) {
|
||||
// also remove from pre-defined paths map so that changes on the server are properly reflected
|
||||
markForInvalidation(config);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return cached.value();
|
||||
return config;
|
||||
}
|
||||
|
||||
private boolean parkForWriteAndCheckInterrupt() {
|
||||
|
|
|
@ -191,8 +191,12 @@ 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 (resourceName != null) {
|
||||
pathConfig.setStatic(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PathConfig existingPath = null;
|
||||
|
||||
for (PathConfig current : paths.values()) {
|
||||
|
@ -248,7 +252,7 @@ public class PolicyEnforcer {
|
|||
cacheConfig = new PathCacheConfig();
|
||||
}
|
||||
|
||||
pathCache = new PathCache(cacheConfig.getMaxEntries(), cacheConfig.getLifespan());
|
||||
pathCache = new PathCache(cacheConfig.getMaxEntries(), cacheConfig.getLifespan(), paths);
|
||||
this.authzClient = authzClient;
|
||||
}
|
||||
|
||||
|
@ -263,20 +267,35 @@ public class PolicyEnforcer {
|
|||
pathConfig = super.matches(targetUri);
|
||||
|
||||
if (enforcerConfig.getLazyLoadPaths() || enforcerConfig.getPathCacheConfig() != null) {
|
||||
if ((pathConfig == null || (pathConfig.getPath().contains("*")))) {
|
||||
if ((pathConfig == null || pathConfig.isInvalidated() || pathConfig.getPath().contains("*"))) {
|
||||
try {
|
||||
List<ResourceRepresentation> matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri);
|
||||
|
||||
if (!matchingResources.isEmpty()) {
|
||||
if (matchingResources.isEmpty()) {
|
||||
// if this config is invalidated (e.g.: due to cache expiration) we remove and return null
|
||||
if (pathConfig != null && pathConfig.isInvalidated()) {
|
||||
paths.remove(targetUri);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Map<String, Map<String, Object>> cipConfig = null;
|
||||
PolicyEnforcerConfig.EnforcementMode enforcementMode = PolicyEnforcerConfig.EnforcementMode.ENFORCING;
|
||||
ResourceRepresentation targetResource = matchingResources.get(0);
|
||||
|
||||
if (pathConfig != null) {
|
||||
cipConfig = pathConfig.getClaimInformationPointConfig();
|
||||
enforcementMode = pathConfig.getEnforcementMode();
|
||||
} else {
|
||||
for (PathConfig existingPath : paths.values()) {
|
||||
if (existingPath.getId().equals(targetResource.getId())
|
||||
&& existingPath.isStatic()
|
||||
&& !PolicyEnforcerConfig.EnforcementMode.DISABLED.equals(existingPath.getEnforcementMode())) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pathConfig = PathConfig.createPathConfigs(matchingResources.get(0)).iterator().next();
|
||||
pathConfig = PathConfig.createPathConfigs(targetResource).iterator().next();
|
||||
|
||||
if (cipConfig != null) {
|
||||
pathConfig.setClaimInformationPointConfig(cipConfig);
|
||||
|
|
|
@ -177,6 +177,10 @@ public class PolicyEnforcerConfig {
|
|||
@JsonIgnore
|
||||
private PathConfig parentConfig;
|
||||
|
||||
private boolean invalidated;
|
||||
|
||||
private boolean staticPath;
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
@ -270,6 +274,22 @@ public class PolicyEnforcerConfig {
|
|||
public PathConfig getParentConfig() {
|
||||
return parentConfig;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
this.invalidated = true;
|
||||
}
|
||||
|
||||
public boolean isInvalidated() {
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return staticPath;
|
||||
}
|
||||
|
||||
public void setStatic(boolean staticPath) {
|
||||
this.staticPath = staticPath;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MethodConfig {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"realm": "photoz",
|
||||
"realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "photoz-restful-api",
|
||||
"bearer-only" : true,
|
||||
"credentials": {
|
||||
"jwt": {
|
||||
"client-key-password": "password",
|
||||
"client-keystore-file": "classpath:keystore.jks",
|
||||
"client-keystore-password": "password",
|
||||
"client-key-alias": "secure-portal",
|
||||
"token-timeout": 10,
|
||||
"client-keystore-type": "jks"
|
||||
}
|
||||
},
|
||||
"policy-enforcer": {
|
||||
"enforcement-mode": "PERMISSIVE",
|
||||
"user-managed-access": {},
|
||||
"path-cache": {
|
||||
"lifespan": 10000
|
||||
},
|
||||
"paths": [
|
||||
{
|
||||
"name" : "Album Resource",
|
||||
"path" : "/album",
|
||||
"methods" : [
|
||||
{
|
||||
"method": "GET",
|
||||
"scopes-enforcement-mode" : "DISABLED"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "Album Resource",
|
||||
"path" : "/album/{id}/",
|
||||
"methods" : [
|
||||
{
|
||||
"method": "DELETE",
|
||||
"scopes" : ["album:delete"]
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"scopes" : ["album:view"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path" : "/profile"
|
||||
},
|
||||
{
|
||||
"name" : "Admin Resources",
|
||||
"path" : "/admin/*"
|
||||
},
|
||||
{
|
||||
"name" : "Scope Protected Resource",
|
||||
"path" : "/scope-any",
|
||||
"methods": [
|
||||
{
|
||||
"method": "GET",
|
||||
"scopes": ["scope-a", "scope-b"],
|
||||
"scopes-enforcement-mode": "ANY"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "Scope Protected Resource",
|
||||
"path" : "/scope-all",
|
||||
"methods": [
|
||||
{
|
||||
"method": "GET",
|
||||
"scopes": ["scope-a", "scope-b"],
|
||||
"scopes-enforcement-mode": "ALL"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<%@page import="org.keycloak.common.util.Time"%>
|
||||
|
||||
<%
|
||||
Time.setOffset(Integer.parseInt(request.getParameter("offset")));
|
||||
%>
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
"realm": "servlet-policy-enforcer-authz",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "servlet-policy-enforcer",
|
||||
"credentials": {
|
||||
"secret": "secret"
|
||||
},
|
||||
"policy-enforcer": {
|
||||
"on-deny-redirect-to": "/servlet-policy-enforcer/denied.jsp",
|
||||
"lazy-load-paths": false,
|
||||
"path-cache": {
|
||||
"lifespan": 5
|
||||
},
|
||||
"paths": [
|
||||
{
|
||||
"name": "Welcome Resource",
|
||||
"path": "/index.jsp"
|
||||
},
|
||||
{
|
||||
"name": "Welcome Resource",
|
||||
"path": "/"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 1",
|
||||
"path": "/resource/{pattern}/{sub-resource}"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 2",
|
||||
"path": "/{pattern}/resource-a"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 3",
|
||||
"path": "/{pattern}/resource-b"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 4",
|
||||
"path": "/resource-c"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 5",
|
||||
"path": "/a/{pattern}/resource-d"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 6",
|
||||
"path": "/resource/{pattern}"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 7",
|
||||
"path": "/resource/{pattern}/f/{resource}"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 8",
|
||||
"path": "/resource"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 9",
|
||||
"path": "/file/*.suffix"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 10",
|
||||
"path": "/resource/{pattern}/i/{resource}/*"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 11",
|
||||
"path": "/api/{version}/{resource}"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 12",
|
||||
"path": "/keycloak_json_uri"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 14",
|
||||
"path": "/keycloak-6623/sub-resource/*"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 13",
|
||||
"path": "/keycloak-6623/*"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 15",
|
||||
"path": "/keycloak-7148/{id}/*"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 16",
|
||||
"path": "/keycloak-7269/sub-resource1"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 16",
|
||||
"path": "/keycloak-7269/sub-resource2/*"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 16",
|
||||
"path": "/keycloak-7269/sub-resource1/{test-pattern}/specialSuffix"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 17",
|
||||
"path": "/keycloak-8823/resource/{version}/subresource/{id}/{other}"
|
||||
},
|
||||
{
|
||||
"name": "Pattern 17 Entities",
|
||||
"path": "/keycloak-8823/resource/{version}/subresource/{id}/entities"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -178,6 +178,15 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl {
|
|||
pause(WAIT_AFTER_OPERATION);
|
||||
}
|
||||
|
||||
public void viewProfile(ResponseValidator validator) {
|
||||
testExecutor.sendXMLHttpRequest(
|
||||
XMLHttpRequest.create()
|
||||
.method("GET")
|
||||
.addHeader("Accept", "application/json")
|
||||
.url(apiUrl + "/profile")
|
||||
, validator);
|
||||
}
|
||||
|
||||
public void viewAlbum(String name, ResponseValidator validator) {
|
||||
testExecutor.sendXMLHttpRequest(
|
||||
XMLHttpRequest.create()
|
||||
|
|
|
@ -80,7 +80,7 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractBasePhoto
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyOwnerCanDeleteAlbum() throws Exception {
|
||||
public void testPathConfigInvalidation() throws Exception {
|
||||
loginToClientPage(aliceUser);
|
||||
clientPage.createAlbum(ALICE_ALBUM_NAME);
|
||||
|
||||
|
|
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* 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.adapter.example.authorization;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.admin.client.resource.ResourcePermissionsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.util.ServerURLs;
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AbstractServletPolicyEnforcerTest extends AbstractExampleAdapterTest {
|
||||
|
||||
protected static final String REALM_NAME = "servlet-policy-enforcer-authz";
|
||||
protected static final String RESOURCE_SERVER_ID = "servlet-policy-enforcer";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern1() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern2() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern3() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern4() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern5() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern6() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern7() throws Exception {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern8() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern9() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern10() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern11UsingResourceInstancePermission() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/api/v1/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/api/v1/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation("/api/v1/resource-c");
|
||||
|
||||
resource.setUri(resource.getName());
|
||||
|
||||
getAuthorizationResource().resources().create(resource);
|
||||
|
||||
createResourcePermission(resource.getName() + " permission", resource.getName(), "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
navigateTo("/api/v1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/v1/");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathWithPatternSlashAllAndResourceInstance() {
|
||||
performTests(() -> {
|
||||
ResourceRepresentation resource = new ResourceRepresentation("Pattern 15 Instance");
|
||||
|
||||
resource.setType("pattern-15");
|
||||
resource.setUri("/keycloak-7148/1");
|
||||
resource.setOwner("alice");
|
||||
|
||||
getAuthorizationResource().resources().create(resource).close();
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 15 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
// does not exist
|
||||
navigateTo("/keycloak-7148/2");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriorityOfURIForResource() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathOrderWithAllPaths() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 13 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 14 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource/resource");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleUriForResourceJSONConfig() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Default Policy");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverloadedTemplateUri() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateTo(String path) {
|
||||
this.driver.navigate().to(getResourceServerUrl() + path);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable assertion) {
|
||||
performTests(() -> {}, assertion);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable beforeDeploy, ExceptionRunnable assertion) {
|
||||
try {
|
||||
beforeDeploy.run();
|
||||
deployer.deploy(RESOURCE_SERVER_ID);
|
||||
assertion.run();
|
||||
} catch (FileNotFoundException cause) {
|
||||
throw new RuntimeException("Failed to import authorization settings", cause);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error while executing tests", cause);
|
||||
} finally {
|
||||
deployer.undeploy(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private AuthorizationResource getAuthorizationResource() {
|
||||
return getClientResource(RESOURCE_SERVER_ID).authorization();
|
||||
}
|
||||
|
||||
private ClientResource getClientResource(String clientId) {
|
||||
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
|
||||
return clients.get(resourceServer.getId());
|
||||
}
|
||||
|
||||
private void logOut() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(driver.findElement(By.xpath("//a[text() = 'Sign Out']")));
|
||||
}
|
||||
|
||||
private void login(String username, String password) {
|
||||
try {
|
||||
navigateTo();
|
||||
if (this.driver.getCurrentUrl().startsWith(getResourceServerUrl().toString())) {
|
||||
logOut();
|
||||
navigateTo();
|
||||
}
|
||||
this.loginPage.form().login(username, password);
|
||||
navigateTo();
|
||||
assertFalse(wasDenied());
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Login failed", cause);
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateTo() {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/");
|
||||
waitForPageToLoad();
|
||||
}
|
||||
|
||||
private boolean wasDenied() {
|
||||
return this.driver.getPageSource().contains("You can not access this resource");
|
||||
}
|
||||
|
||||
private URL getResourceServerUrl() {
|
||||
try {
|
||||
return new URL(ServerURLs.getAppServerContextRoot() + "/" + RESOURCE_SERVER_ID);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Could not obtain resource server url.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePermissionPolicies(String permissionName, String... policyNames) {
|
||||
ResourcePermissionsResource permissions = getAuthorizationResource().permissions().resource();
|
||||
ResourcePermissionRepresentation permission = permissions.findByName(permissionName);
|
||||
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
permissions.findById(permission.getId()).update(permission);
|
||||
}
|
||||
|
||||
private void createResourcePermission(String name, String resourceName, String... policyNames) {
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(name);
|
||||
permission.addResource(resourceName);
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
getAuthorizationResource().permissions().resource().create(permission);
|
||||
}
|
||||
|
||||
private interface ExceptionRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* 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.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.adapter.page.PhotozClientAuthzTestApp;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.javascript.ResponseValidator;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY_DEPRECATED)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class LifespanAdapterTest extends AbstractPhotozExampleAdapterTest {
|
||||
|
||||
@Deployment(name = PhotozClientAuthzTestApp.DEPLOYMENT_NAME)
|
||||
public static WebArchive deploymentClient() throws IOException {
|
||||
return exampleDeployment(PhotozClientAuthzTestApp.DEPLOYMENT_NAME);
|
||||
}
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false, testable = false)
|
||||
public static WebArchive deploymentResourceServer() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID,
|
||||
webArchive -> webArchive.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/photoz/keycloak-cache-lifespan-authz-service.json"), "keycloak.json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathConfigInvalidation() throws Exception {
|
||||
loginToClientPage(aliceUser);
|
||||
assertSuccess();
|
||||
|
||||
ResourceRepresentation resource = getAuthorizationResource().resources().findByName("Profile Resource").get(0);
|
||||
AuthorizationResource authorizationResource = getAuthorizationResource();
|
||||
|
||||
authorizationResource.resources().resource(resource.getId()).remove();
|
||||
|
||||
loginToClientPage(aliceUser);
|
||||
|
||||
// should throw an error because the resource was removed and cache entry did not expire yet
|
||||
clientPage.viewProfile(new ResponseValidator() {
|
||||
@Override
|
||||
public void validate(Map<String, Object> response) {
|
||||
Object res = response.get("res");
|
||||
assertThat(res, Matchers.notNullValue());
|
||||
assertThat(res.toString(), Matchers.not(Matchers.containsString("userName")));
|
||||
}
|
||||
});
|
||||
|
||||
setTimeOffsetOfAdapter(20);
|
||||
|
||||
loginToClientPage(aliceUser);
|
||||
assertSuccess();
|
||||
setTimeOffsetOfAdapter(0);
|
||||
|
||||
try (Response response = authorizationResource.resources().create(resource)) {
|
||||
resource = response.readEntity(ResourceRepresentation.class);
|
||||
}
|
||||
|
||||
loginToClientPage(aliceUser);
|
||||
assertSuccess();
|
||||
|
||||
RealmResource realm = this.realmsResouce().realm(REALM_NAME);
|
||||
UserRepresentation userRepresentation = realm.users().search(aliceUser.getUsername()).get(0);
|
||||
UserResource userResource = realm.users().get(userRepresentation.getId());
|
||||
|
||||
userRepresentation.setEmail("alice@anotherdomain.org");
|
||||
|
||||
userResource.update(userRepresentation);
|
||||
loginToClientPage(aliceUser);
|
||||
assertTicket();
|
||||
|
||||
try {
|
||||
PolicyRepresentation resourceInstancePermission = new PolicyRepresentation();
|
||||
|
||||
resourceInstancePermission.setName("View User Permission");
|
||||
resourceInstancePermission.setType("resource");
|
||||
|
||||
Map<String, String> config = new HashMap<>();
|
||||
|
||||
config.put("resources", JsonSerialization.writeValueAsString(Arrays.asList(resource.getId())));
|
||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(Arrays.asList("Only From @keycloak.org or Admin")));
|
||||
|
||||
resourceInstancePermission.setConfig(config);
|
||||
authorizationResource.policies().create(resourceInstancePermission);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error creating policy.", e);
|
||||
}
|
||||
|
||||
loginToClientPage(aliceUser);
|
||||
// should throw an error because the resource was removed and cache entry did not expire yet
|
||||
clientPage.viewProfile(new ResponseValidator() {
|
||||
@Override
|
||||
public void validate(Map<String, Object> response) {
|
||||
Object res = response.get("res");
|
||||
assertThat(res, Matchers.notNullValue());
|
||||
assertThat(res.toString(), Matchers.not(Matchers.containsString("userName")));
|
||||
}
|
||||
});
|
||||
|
||||
userRepresentation.setEmail("alice@keycloak.org");
|
||||
|
||||
userResource.update(userRepresentation);
|
||||
loginToClientPage(aliceUser);
|
||||
assertSuccess();
|
||||
}
|
||||
|
||||
private void assertSuccess() {
|
||||
clientPage.viewProfile((ResponseValidator) response -> {
|
||||
Object res = response.get("res");
|
||||
assertThat(res, Matchers.notNullValue());
|
||||
assertThat(res.toString(), Matchers.containsString("userName"));
|
||||
});
|
||||
}
|
||||
|
||||
private void assertTicket() {
|
||||
clientPage.viewProfile((ResponseValidator) response -> {
|
||||
Object headers = response.get("responseHeaders");
|
||||
assertThat(headers, Matchers.notNullValue());
|
||||
assertThat(headers.toString(), Matchers.containsString("WWW-Authenticate: UMA"));
|
||||
});
|
||||
}
|
||||
|
||||
public void setTimeOffsetOfAdapter(int offset) {
|
||||
this.driver.navigate().to(clientPage.getInjectedUrl() + "/timeOffset.jsp?offset=" + String.valueOf(offset));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.adapter.example.authorization;
|
||||
|
||||
import static org.keycloak.common.Profile.Feature.UPLOAD_SCRIPTS;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_WILDFLY_DEPRECATED)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP6)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_EAP71)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_TOMCAT7)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_TOMCAT8)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_TOMCAT9)
|
||||
@EnableFeature(value = UPLOAD_SCRIPTS, skipRestart = true)
|
||||
public class ServletPolicyEnforcerLifespanTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID,
|
||||
webArchive -> webArchive.addAsWebInfResource(
|
||||
new File(TEST_APPS_HOME_DIR
|
||||
+ "/servlet-policy-enforcer/servlet-policy-enforcer-lifespan-authz-service.json"),
|
||||
"keycloak.json"));
|
||||
}
|
||||
}
|
|
@ -16,41 +16,16 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.adapter.example.authorization;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.common.Profile.Feature.UPLOAD_SCRIPTS;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.admin.client.resource.ResourcePermissionsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.util.ServerURLs;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -65,559 +40,10 @@ import org.openqa.selenium.By;
|
|||
@AppServerContainer(ContainerConstants.APP_SERVER_TOMCAT8)
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_TOMCAT9)
|
||||
@EnableFeature(value = UPLOAD_SCRIPTS, skipRestart = true)
|
||||
public class ServletPolicyEnforcerTest extends AbstractExampleAdapterTest {
|
||||
|
||||
protected static final String REALM_NAME = "servlet-policy-enforcer-authz";
|
||||
protected static final String RESOURCE_SERVER_ID = "servlet-policy-enforcer";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json")));
|
||||
}
|
||||
public class ServletPolicyEnforcerTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
public static WebArchive deployment() {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern1() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern2() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern3() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern4() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern5() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern6() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern7() throws Exception {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern8() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern9() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern10() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern11UsingResourceInstancePermission() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/api/v1/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/api/v1/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation("/api/v1/resource-c");
|
||||
|
||||
resource.setUri(resource.getName());
|
||||
|
||||
getAuthorizationResource().resources().create(resource);
|
||||
|
||||
createResourcePermission(resource.getName() + " permission", resource.getName(), "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
navigateTo("/api/v1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/v1/");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathWithPatternSlashAllAndResourceInstance() {
|
||||
performTests(() -> {
|
||||
ResourceRepresentation resource = new ResourceRepresentation("Pattern 15 Instance");
|
||||
|
||||
resource.setType("pattern-15");
|
||||
resource.setUri("/keycloak-7148/1");
|
||||
resource.setOwner("alice");
|
||||
|
||||
getAuthorizationResource().resources().create(resource).close();
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 15 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
// does not exist
|
||||
navigateTo("/keycloak-7148/2");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriorityOfURIForResource() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathOrderWithAllPaths() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 13 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 14 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource/resource");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleUriForResourceJSONConfig() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Default Policy");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverloadedTemplateUri() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateTo(String path) {
|
||||
this.driver.navigate().to(getResourceServerUrl() + path);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable assertion) {
|
||||
performTests(() -> {}, assertion);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable beforeDeploy, ExceptionRunnable assertion) {
|
||||
try {
|
||||
beforeDeploy.run();
|
||||
deployer.deploy(RESOURCE_SERVER_ID);
|
||||
assertion.run();
|
||||
} catch (FileNotFoundException cause) {
|
||||
throw new RuntimeException("Failed to import authorization settings", cause);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error while executing tests", cause);
|
||||
} finally {
|
||||
deployer.undeploy(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private AuthorizationResource getAuthorizationResource() {
|
||||
return getClientResource(RESOURCE_SERVER_ID).authorization();
|
||||
}
|
||||
|
||||
private ClientResource getClientResource(String clientId) {
|
||||
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
|
||||
return clients.get(resourceServer.getId());
|
||||
}
|
||||
|
||||
private void logOut() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(driver.findElement(By.xpath("//a[text() = 'Sign Out']")));
|
||||
}
|
||||
|
||||
private void login(String username, String password) {
|
||||
try {
|
||||
navigateTo();
|
||||
if (this.driver.getCurrentUrl().startsWith(getResourceServerUrl().toString())) {
|
||||
logOut();
|
||||
navigateTo();
|
||||
}
|
||||
this.loginPage.form().login(username, password);
|
||||
navigateTo();
|
||||
assertFalse(wasDenied());
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Login failed", cause);
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateTo() {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/");
|
||||
waitForPageToLoad();
|
||||
}
|
||||
|
||||
private boolean wasDenied() {
|
||||
return this.driver.getPageSource().contains("You can not access this resource");
|
||||
}
|
||||
|
||||
private URL getResourceServerUrl() {
|
||||
try {
|
||||
return new URL(ServerURLs.getAppServerContextRoot() + "/" + RESOURCE_SERVER_ID);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Could not obtain resource server url.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePermissionPolicies(String permissionName, String... policyNames) {
|
||||
ResourcePermissionsResource permissions = getAuthorizationResource().permissions().resource();
|
||||
ResourcePermissionRepresentation permission = permissions.findByName(permissionName);
|
||||
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
permissions.findById(permission.getId()).update(permission);
|
||||
}
|
||||
|
||||
private void createResourcePermission(String name, String resourceName, String... policyNames) {
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(name);
|
||||
permission.addResource(resourceName);
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
getAuthorizationResource().permissions().resource().create(permission);
|
||||
}
|
||||
|
||||
private interface ExceptionRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue