[KEYCLOAK-6492] - Migrate authorization package from old testsuite
This commit is contained in:
parent
eb326cd1bb
commit
8112c5d3f2
8 changed files with 11 additions and 1622 deletions
|
@ -1,13 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* JBoss, Home of Professional Open Source.
|
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||||
* Copyright 2016 Red Hat, Inc., and individual contributors
|
* and other contributors as indicated by the @author tags.
|
||||||
* as indicated by the @author tags.
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -16,11 +15,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.keycloak.testsuite.authorization;
|
package org.keycloak.testsuite.authz;
|
||||||
|
|
||||||
import org.apache.commons.collections.map.HashedMap;
|
import static java.util.Arrays.asList;
|
||||||
import org.junit.Test;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.keycloak.authorization.attribute.Attributes;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -29,10 +29,9 @@ import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import org.apache.commons.collections.map.HashedMap;
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.Test;
|
||||||
import static org.junit.Assert.assertFalse;
|
import org.keycloak.authorization.attribute.Attributes;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization;
|
|
||||||
|
|
||||||
import org.junit.Assume;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.keycloak.admin.client.Keycloak;
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
|
||||||
import org.keycloak.common.Profile;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.Constants;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakTransactionManager;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.ClientBuilder;
|
|
||||||
import javax.ws.rs.client.ClientRequestFilter;
|
|
||||||
import javax.ws.rs.client.Invocation;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MASTER;
|
|
||||||
import static org.keycloak.models.AdminRoles.ADMIN;
|
|
||||||
import static org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractAuthorizationTest {
|
|
||||||
|
|
||||||
protected static final String TEST_REALM_NAME = "photoz";
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public KeycloakAuthorizationServerRule keycloak = new KeycloakAuthorizationServerRule(TEST_REALM_NAME);
|
|
||||||
|
|
||||||
private Keycloak adminClient;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void enabled() {
|
|
||||||
Assume.assumeTrue("Ignoring test as community/preview profile is not enabled", !Profile.getName().equals("product"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void onBefore() {
|
|
||||||
adminClient = Keycloak.getInstance(AUTH_SERVER_ROOT, MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected <R> R onAuthorizationSession(Function<AuthorizationProvider, R> function) {
|
|
||||||
KeycloakSession keycloakSession = startKeycloakSession();
|
|
||||||
KeycloakTransactionManager transaction = keycloakSession.getTransactionManager();
|
|
||||||
|
|
||||||
try {
|
|
||||||
AuthorizationProvider authorizationProvider = keycloakSession.getProvider(AuthorizationProvider.class);
|
|
||||||
|
|
||||||
R result = function.apply(authorizationProvider);
|
|
||||||
|
|
||||||
transaction.commit();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (Exception e) {
|
|
||||||
transaction.rollback();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
if (keycloakSession != null) {
|
|
||||||
keycloakSession.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onAuthorizationSession(Consumer<AuthorizationProvider> consumer) {
|
|
||||||
KeycloakSession keycloakSession = startKeycloakSession();
|
|
||||||
KeycloakTransactionManager transaction = keycloakSession.getTransactionManager();
|
|
||||||
|
|
||||||
try {
|
|
||||||
AuthorizationProvider authorizationProvider = keycloakSession.getProvider(AuthorizationProvider.class);
|
|
||||||
|
|
||||||
consumer.accept(authorizationProvider);
|
|
||||||
|
|
||||||
transaction.commit();
|
|
||||||
} catch (Exception e) {
|
|
||||||
transaction.rollback();
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
if (keycloakSession != null) {
|
|
||||||
keycloakSession.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Invocation.Builder newClient(ClientModel client, String authzRelativePath) {
|
|
||||||
String targetUrl = AUTH_SERVER_ROOT + "/admin/realms/" + TEST_REALM_NAME + "/clients/" + client.getId() + "/authz" + authzRelativePath;
|
|
||||||
|
|
||||||
return ClientBuilder.newClient()
|
|
||||||
.register((ClientRequestFilter) requestContext -> {
|
|
||||||
AccessTokenResponse accessToken = adminClient.tokenManager().getAccessToken();
|
|
||||||
requestContext.getHeaders().add("Authorization", "Bearer " + accessToken.getToken());
|
|
||||||
}).target(targetUrl).request();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClientModel getClientByClientId(String clientId) {
|
|
||||||
KeycloakSession session = this.keycloak.startSession();
|
|
||||||
|
|
||||||
try {
|
|
||||||
RealmModel realm = session.realms().getRealmByName(TEST_REALM_NAME);
|
|
||||||
return realm.getClientByClientId(clientId);
|
|
||||||
} finally {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeycloakSession startKeycloakSession() {
|
|
||||||
KeycloakSession keycloakSession = this.keycloak.startSession();
|
|
||||||
|
|
||||||
keycloakSession.getContext().setRealm(keycloakSession.realms().getRealmByName(TEST_REALM_NAME));
|
|
||||||
|
|
||||||
return keycloakSession;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,394 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.authorization;
|
|
||||||
|
|
||||||
import org.apache.commons.collections.map.HashedMap;
|
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
|
||||||
import org.keycloak.authorization.Decision;
|
|
||||||
import org.keycloak.authorization.common.KeycloakEvaluationContext;
|
|
||||||
import org.keycloak.authorization.common.KeycloakIdentity;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.permission.ResourcePermission;
|
|
||||||
import org.keycloak.authorization.policy.evaluation.DefaultEvaluation;
|
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
|
||||||
import org.keycloak.authorization.store.ScopeStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.common.ClientConnection;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.representations.AccessToken;
|
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.Invocation;
|
|
||||||
import javax.ws.rs.core.Cookie;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractPhotozAdminTest extends AbstractAuthorizationTest {
|
|
||||||
|
|
||||||
protected ResourceServer resourceServer;
|
|
||||||
protected Resource adminResource;
|
|
||||||
protected Policy anyAdminPolicy;
|
|
||||||
protected Policy onlyFromSpecificAddressPolicy;
|
|
||||||
protected Policy administrationPolicy;
|
|
||||||
|
|
||||||
protected Resource albumResource;
|
|
||||||
protected Policy anyUserPolicy;
|
|
||||||
protected UserModel aliceUser;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void onBefore() {
|
|
||||||
super.onBefore();
|
|
||||||
this.resourceServer = createResourceServer();
|
|
||||||
this.adminResource = createAdminAlbumResource();
|
|
||||||
this.anyAdminPolicy = createAnyAdminPolicy();
|
|
||||||
this.onlyFromSpecificAddressPolicy = createOnlyFromSpecificAddressPolicy();
|
|
||||||
this.administrationPolicy = createAdministrationPolicy();
|
|
||||||
|
|
||||||
this.albumResource = createAlbumResource();
|
|
||||||
this.anyUserPolicy = createAnyUserPolicy();
|
|
||||||
this.aliceUser = onAuthorizationSession(new Function<AuthorizationProvider, UserModel>() {
|
|
||||||
@Override
|
|
||||||
public UserModel apply(AuthorizationProvider authorizationProvider) {
|
|
||||||
return authorizationProvider.getKeycloakSession().users().getUserByUsername("alice", authorizationProvider.getRealm());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ResourceServer createResourceServer() {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
|
|
||||||
|
|
||||||
ResourceServer resourceServer = resourceServerStore.create(getClientByClientId("photoz-restful-api").getId());
|
|
||||||
|
|
||||||
resourceServer.setAllowRemoteResourceManagement(true);
|
|
||||||
|
|
||||||
return resourceServer;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Map<String, DefaultEvaluation> performEvaluation(List<ResourcePermission> permissions, AccessToken accessToken, ClientConnection clientConnection) {
|
|
||||||
Map<String, DefaultEvaluation> evaluations = new HashedMap();
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
|
|
||||||
// during tests we create resource instances, but we need to reload them to get their collections updated
|
|
||||||
List<ResourcePermission> updatedPermissions = permissions.stream().map(permission -> {
|
|
||||||
Resource resource = storeFactory.getResourceStore().findById(permission.getResource().getId(), resourceServer.getId());
|
|
||||||
return new ResourcePermission(resource, permission.getScopes(), permission.getResourceServer());
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
authorizationProvider.evaluators().from(updatedPermissions, createEvaluationContext(accessToken, clientConnection, authorizationProvider)).evaluate(new Decision<DefaultEvaluation>() {
|
|
||||||
@Override
|
|
||||||
public void onDecision(DefaultEvaluation evaluation) {
|
|
||||||
evaluations.put(evaluation.getPolicy().getId(), evaluation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable cause) {
|
|
||||||
throw new RuntimeException("Permission evaluation failed.", cause);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return evaluations;
|
|
||||||
}
|
|
||||||
|
|
||||||
private KeycloakEvaluationContext createEvaluationContext(AccessToken accessToken, ClientConnection clientConnection, AuthorizationProvider authorizationProvider) {
|
|
||||||
KeycloakSession keycloakSession = authorizationProvider.getKeycloakSession();
|
|
||||||
|
|
||||||
keycloakSession.getContext().setConnection(clientConnection);
|
|
||||||
|
|
||||||
keycloakSession.getContext().setClient(getClientByClientId("photoz-html5-client"));
|
|
||||||
|
|
||||||
ResteasyProviderFactory.pushContext(HttpHeaders.class, createHttpHeaders());
|
|
||||||
|
|
||||||
KeycloakIdentity identity = new KeycloakIdentity(accessToken, keycloakSession);
|
|
||||||
|
|
||||||
return new KeycloakEvaluationContext(identity, keycloakSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AccessToken createAccessToken(Set<String> roles) {
|
|
||||||
AccessToken accessToken = new AccessToken();
|
|
||||||
|
|
||||||
accessToken.setRealmAccess(new AccessToken.Access());
|
|
||||||
accessToken.getRealmAccess().roles(roles);
|
|
||||||
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private HttpHeaders createHttpHeaders() {
|
|
||||||
return new HttpHeaders() {
|
|
||||||
@Override
|
|
||||||
public List<String> getRequestHeader(String name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHeaderString(String name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MultivaluedMap<String, String> getRequestHeaders() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MediaType> getAcceptableMediaTypes() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Locale> getAcceptableLanguages() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaType getMediaType() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Locale getLanguage() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Cookie> getCookies() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Date getDate() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClientConnection createClientConnection(String remoteAddr) {
|
|
||||||
return new ClientConnection() {
|
|
||||||
@Override
|
|
||||||
public String getRemoteAddr() {
|
|
||||||
return remoteAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRemoteHost() {
|
|
||||||
return "localhost";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getRemotePort() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLocalAddr() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLocalPort() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Invocation.Builder newPermissionRequest(String... id) {
|
|
||||||
String idPathParam = "";
|
|
||||||
|
|
||||||
if (id.length != 0) {
|
|
||||||
idPathParam = "/" + id[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return newClient(getClientByClientId("photoz-restful-api"), "/resource-server/policy" + idPathParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createAdministrationPolicy() {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
PolicyRepresentation representation = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Administration Policy");
|
|
||||||
representation.setType("aggregate");
|
|
||||||
representation.addPolicy(anyAdminPolicy.getName());
|
|
||||||
representation.addPolicy(onlyFromSpecificAddressPolicy.getName());
|
|
||||||
|
|
||||||
Policy policy = policyStore.create(representation, resourceServer);
|
|
||||||
|
|
||||||
return policy;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createOnlyFromSpecificAddressPolicy() {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
PolicyRepresentation representation = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Only From a Specific Client Address");
|
|
||||||
representation.setType("js");
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
config.put("code",
|
|
||||||
"var contextAttributes = $evaluation.getContext().getAttributes();" +
|
|
||||||
"var networkAddress = contextAttributes.getValue('kc.client.network.ip_address');" +
|
|
||||||
"if ('127.0.0.1'.equals(networkAddress.asInetAddress(0).getHostAddress())) {" +
|
|
||||||
"$evaluation.grant();" +
|
|
||||||
"}");
|
|
||||||
|
|
||||||
representation.setConfig(config);
|
|
||||||
|
|
||||||
return policyStore.create(representation, resourceServer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createAnyAdminPolicy() {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
RolePolicyRepresentation representation = new RolePolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Any Admin Policy");
|
|
||||||
representation.setType("role");
|
|
||||||
representation.addRole("admin", false);
|
|
||||||
|
|
||||||
return policyStore.create(representation, resourceServer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource createAdminAlbumResource() {
|
|
||||||
ResourceRepresentation representation = new ResourceRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Admin Resources");
|
|
||||||
representation.setType("http://photoz.com/admin");
|
|
||||||
representation.setUri("/admin/*");
|
|
||||||
|
|
||||||
HashSet<ScopeRepresentation> scopes = new HashSet<>();
|
|
||||||
|
|
||||||
scopes.add(new ScopeRepresentation("urn:photoz.com:scopes:album:admin:manage"));
|
|
||||||
|
|
||||||
representation.setScopes(scopes);
|
|
||||||
|
|
||||||
return createResource(representation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Resource createAlbumResource() {
|
|
||||||
ResourceRepresentation representation = new ResourceRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Album Resource");
|
|
||||||
representation.setType("http://photoz.com/album");
|
|
||||||
representation.setUri("/album/*");
|
|
||||||
|
|
||||||
HashSet<ScopeRepresentation> scopes = new HashSet<>();
|
|
||||||
|
|
||||||
scopes.add(new ScopeRepresentation("urn:photoz.com:scopes:album:view"));
|
|
||||||
scopes.add(new ScopeRepresentation("urn:photoz.com:scopes:album:create"));
|
|
||||||
scopes.add(new ScopeRepresentation("urn:photoz.com:scopes:album:delete"));
|
|
||||||
|
|
||||||
representation.setScopes(scopes);
|
|
||||||
|
|
||||||
return createResource(representation);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Resource createResource(ResourceRepresentation representation) {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
ScopeStore scopeStore = storeFactory.getScopeStore();
|
|
||||||
|
|
||||||
representation.getScopes().forEach(scopeRepresentation -> {
|
|
||||||
scopeStore.create(scopeRepresentation.getName(), resourceServer);
|
|
||||||
});
|
|
||||||
|
|
||||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
|
||||||
Resource albumResource = resourceStore.create(representation.getName(), resourceServer, resourceServer.getId());
|
|
||||||
|
|
||||||
albumResource.setType(representation.getType());
|
|
||||||
albumResource.setUri(representation.getUri());
|
|
||||||
albumResource.setIconUri(representation.getIconUri());
|
|
||||||
|
|
||||||
return albumResource;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createAnyUserPolicy() {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
PolicyRepresentation representation = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Any User Policy");
|
|
||||||
representation.setType("role");
|
|
||||||
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
RealmModel realm = authorizationProvider.getKeycloakSession().realms().getRealmByName(TEST_REALM_NAME);
|
|
||||||
RoleModel userRole = realm.getRole("user");
|
|
||||||
|
|
||||||
Map role = new HashMap();
|
|
||||||
|
|
||||||
role.put("id", userRole.getId());
|
|
||||||
|
|
||||||
try {
|
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(new Map[] {role}));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
representation.setConfig(config);
|
|
||||||
|
|
||||||
Policy policy = policyStore.create(representation, resourceServer);
|
|
||||||
|
|
||||||
return policy;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.authorization;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.authorization.client.AuthzClient;
|
|
||||||
import org.keycloak.authorization.client.Configuration;
|
|
||||||
import org.keycloak.authorization.client.representation.RegistrationResponse;
|
|
||||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
|
||||||
import org.keycloak.authorization.client.representation.ScopeRepresentation;
|
|
||||||
import org.keycloak.authorization.client.resource.ProtectedResource;
|
|
||||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class AuthorizationClientTest extends AbstractPhotozAdminTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreate() throws Exception {
|
|
||||||
AuthzClient authzClient = getAuthzClient();
|
|
||||||
// create a new resource representation with the information we want
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("urn:hello-world-authz:resources:example");
|
|
||||||
|
|
||||||
newResource.addScope(new ScopeRepresentation("urn:hello-world-authz:scopes:view"));
|
|
||||||
|
|
||||||
ProtectedResource resourceClient = authzClient.protection().resource();
|
|
||||||
Set<String> existingResource = resourceClient.findByFilter("name=" + newResource.getName());
|
|
||||||
|
|
||||||
if (!existingResource.isEmpty()) {
|
|
||||||
resourceClient.delete(existingResource.iterator().next());
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the resource on the server
|
|
||||||
RegistrationResponse response = resourceClient.create(newResource);
|
|
||||||
String resourceId = response.getId();
|
|
||||||
|
|
||||||
// query the resource using its newly generated id
|
|
||||||
ResourceRepresentation resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertNotNull(resource.getId());
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdate() throws Exception {
|
|
||||||
AuthzClient authzClient = getAuthzClient();
|
|
||||||
// create a new resource representation with the information we want
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
|
|
||||||
ProtectedResource protectedResource = authzClient.protection().resource();
|
|
||||||
ProtectedResource resourceClient = protectedResource;
|
|
||||||
Set<String> existingResource = resourceClient.findByFilter("name=" + newResource.getName());
|
|
||||||
|
|
||||||
if (!existingResource.isEmpty()) {
|
|
||||||
resourceClient.delete(existingResource.iterator().next());
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the resource on the server
|
|
||||||
RegistrationResponse response = resourceClient.create(newResource);
|
|
||||||
String resourceId = response.getId();
|
|
||||||
|
|
||||||
// query the resource using its newly generated id
|
|
||||||
ResourceRepresentation resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertNotNull(resource.getId());
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
|
|
||||||
resource.setType("Changed Type");
|
|
||||||
resource.setUri("Changed Uri");
|
|
||||||
resource.addScope(new ScopeRepresentation("new-scope"));
|
|
||||||
|
|
||||||
protectedResource.update(resource);
|
|
||||||
|
|
||||||
resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertEquals("Changed Type", resource.getType());
|
|
||||||
assertEquals("Changed Uri", resource.getUri());
|
|
||||||
|
|
||||||
Set<ScopeRepresentation> scopes = resource.getScopes();
|
|
||||||
|
|
||||||
assertEquals(1, scopes.size());
|
|
||||||
assertEquals("new-scope", scopes.iterator().next().getName());
|
|
||||||
|
|
||||||
resource.setScopes(Collections.emptySet());
|
|
||||||
|
|
||||||
protectedResource.update(resource);
|
|
||||||
|
|
||||||
resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertEquals(0, resource.getScopes().size());
|
|
||||||
|
|
||||||
resource.setScopes(scopes);
|
|
||||||
|
|
||||||
protectedResource.update(resource);
|
|
||||||
|
|
||||||
resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertEquals(1, resource.getScopes().size());
|
|
||||||
assertEquals(scopes.iterator().next().getId(), resource.getScopes().iterator().next().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDelete() throws Exception {
|
|
||||||
AuthzClient authzClient = getAuthzClient();
|
|
||||||
// create a new resource representation with the information we want
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
|
|
||||||
ProtectedResource resourceClient = authzClient.protection().resource();
|
|
||||||
Set<String> existingResource = resourceClient.findByFilter("name=" + newResource.getName());
|
|
||||||
|
|
||||||
if (!existingResource.isEmpty()) {
|
|
||||||
resourceClient.delete(existingResource.iterator().next());
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the resource on the server
|
|
||||||
RegistrationResponse response = resourceClient.create(newResource);
|
|
||||||
String resourceId = response.getId();
|
|
||||||
|
|
||||||
// query the resource using its newly generated id
|
|
||||||
ResourceRepresentation resource = resourceClient.findById(resourceId).getResourceDescription();
|
|
||||||
|
|
||||||
assertNotNull(resource);
|
|
||||||
|
|
||||||
authzClient.protection().resource().delete(resource.getId());
|
|
||||||
|
|
||||||
try {
|
|
||||||
resourceClient.findById(resourceId);
|
|
||||||
fail();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
HttpResponseException cause = (HttpResponseException) e.getCause();
|
|
||||||
assertEquals(404, cause.getStatusCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AuthzClient getAuthzClient() throws java.io.IOException {
|
|
||||||
Configuration configuration = JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/keycloak.json"), Configuration.class);
|
|
||||||
return AuthzClient.create(configuration);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization;
|
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
|
||||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class KeycloakAuthorizationServerRule extends AbstractKeycloakRule {
|
|
||||||
|
|
||||||
private final String realmName;
|
|
||||||
|
|
||||||
KeycloakAuthorizationServerRule(String realmName) {
|
|
||||||
this.realmName = realmName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
|
|
||||||
server.importRealm(getClass().getResourceAsStream("/authorization-test/test-" + realmName + "-realm.json"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String[] getTestRealms() {
|
|
||||||
return new String[] {this.realmName};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,242 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.Entity;
|
|
||||||
import javax.ws.rs.client.Invocation.Builder;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class ResourceManagementTest extends AbstractPhotozAdminTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateWithoutOwner() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("Resource Type");
|
|
||||||
newResource.setIconUri("Resource Icon URI");
|
|
||||||
newResource.setUri("Resource URI");
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
response = newResourceRequest(resource.getId()).get();
|
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
assertEquals("Resource Type", resource.getType());
|
|
||||||
assertEquals("Resource Icon URI", resource.getIconUri());
|
|
||||||
assertEquals("Resource URI", resource.getUri());
|
|
||||||
assertEquals(resourceServer.getId(), resource.getOwner().getId());
|
|
||||||
assertEquals("photoz-restful-api", resource.getOwner().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateWithOwnerUser() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("Resource Type");
|
|
||||||
newResource.setIconUri("Resource Icon URI");
|
|
||||||
newResource.setUri("Resource URI");
|
|
||||||
|
|
||||||
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
|
|
||||||
|
|
||||||
owner.setId("alice");
|
|
||||||
|
|
||||||
newResource.setOwner(owner);
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
response = newResourceRequest(resource.getId()).get();
|
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
assertEquals("Resource Type", resource.getType());
|
|
||||||
assertEquals("Resource Icon URI", resource.getIconUri());
|
|
||||||
assertEquals("Resource URI", resource.getUri());
|
|
||||||
assertEquals(aliceUser.getId(), resource.getOwner().getId());
|
|
||||||
assertEquals(aliceUser.getUsername(), resource.getOwner().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateWithOwnerResourceServer() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("Resource Type");
|
|
||||||
newResource.setIconUri("Resource Icon URI");
|
|
||||||
newResource.setUri("Resource URI");
|
|
||||||
|
|
||||||
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
|
|
||||||
|
|
||||||
owner.setId("photoz-restful-api");
|
|
||||||
|
|
||||||
newResource.setOwner(owner);
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
response = newResourceRequest(resource.getId()).get();
|
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
assertEquals("Resource Type", resource.getType());
|
|
||||||
assertEquals("Resource Icon URI", resource.getIconUri());
|
|
||||||
assertEquals("Resource URI", resource.getUri());
|
|
||||||
assertEquals(resourceServer.getId(), resource.getOwner().getId());
|
|
||||||
assertEquals("photoz-restful-api", resource.getOwner().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdate() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("Resource Type");
|
|
||||||
newResource.setIconUri("Resource Icon URI");
|
|
||||||
newResource.setUri("Resource URI");
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
newResource.setName("New Resource Changed");
|
|
||||||
newResource.setType("Resource Type Changed");
|
|
||||||
newResource.setIconUri("Resource Icon URI Changed");
|
|
||||||
newResource.setUri("Resource URI Changed");
|
|
||||||
|
|
||||||
response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(resourceModel);
|
|
||||||
assertEquals(resource.getId(), resourceModel.getId());
|
|
||||||
assertEquals("New Resource Changed", resourceModel.getName());
|
|
||||||
assertEquals("Resource Type Changed", resourceModel.getType());
|
|
||||||
assertEquals("Resource Icon URI Changed", resourceModel.getIconUri());
|
|
||||||
assertEquals("Resource URI Changed", resourceModel.getUri());
|
|
||||||
assertEquals(resourceServer.getId(), resourceModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFindById() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
newResource.setType("Resource Type");
|
|
||||||
newResource.setIconUri("Resource Icon URI");
|
|
||||||
newResource.setUri("Resource URI");
|
|
||||||
|
|
||||||
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
|
|
||||||
|
|
||||||
owner.setId("alice");
|
|
||||||
|
|
||||||
newResource.setOwner(owner);
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
response = newResourceRequest(resource.getId()).get();
|
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals("New Resource", resource.getName());
|
|
||||||
assertEquals("Resource Type", resource.getType());
|
|
||||||
assertEquals("Resource Icon URI", resource.getIconUri());
|
|
||||||
assertEquals("Resource URI", resource.getUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDelete() throws Exception {
|
|
||||||
ResourceRepresentation newResource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
newResource.setName("New Resource");
|
|
||||||
|
|
||||||
Response response = newResourceRequest().post(Entity.entity(newResource, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ResourceRepresentation resource = response.readEntity(ResourceRepresentation.class);
|
|
||||||
|
|
||||||
assertNotNull(resource.getId());
|
|
||||||
|
|
||||||
response = newResourceRequest(resource.getId()).delete();
|
|
||||||
|
|
||||||
assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Resource resourceModel = authorizationProvider.getStoreFactory().getResourceStore().findById(resource.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNull(resourceModel);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Builder newResourceRequest(String... id) {
|
|
||||||
String idPathParam = "";
|
|
||||||
|
|
||||||
if (id.length != 0) {
|
|
||||||
idPathParam = "/" + id[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return newClient(getClientByClientId("photoz-restful-api"), "/resource-server/resource" + idPathParam);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,465 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization;
|
|
||||||
|
|
||||||
import org.apache.commons.collections.map.HashedMap;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.authorization.Decision.Effect;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.permission.ResourcePermission;
|
|
||||||
import org.keycloak.authorization.policy.evaluation.DefaultEvaluation;
|
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.representations.AccessToken;
|
|
||||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.Entity;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class ResourcePermissionManagementTest extends AbstractPhotozAdminTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateForTypeWithSinglePolicy() throws Exception {
|
|
||||||
PolicyRepresentation newPermission = new PolicyRepresentation();
|
|
||||||
|
|
||||||
newPermission.setName("Admin Resource Policy");
|
|
||||||
newPermission.setType("resource");
|
|
||||||
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
config.put("defaultResourceType", "http://photoz.com/admin");
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(new String[] {this.administrationPolicy.getId()}));
|
|
||||||
|
|
||||||
newPermission.setConfig(config);
|
|
||||||
|
|
||||||
Response response = newPermissionRequest().post(Entity.entity(newPermission, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(policyModel);
|
|
||||||
assertEquals(permission.getId(), policyModel.getId());
|
|
||||||
assertEquals(newPermission.getName(), policyModel.getName());
|
|
||||||
assertEquals(newPermission.getType(), policyModel.getType());
|
|
||||||
assertEquals(resourceServer.getId(), policyModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
|
|
||||||
Set<String> roles = new HashSet<>();
|
|
||||||
|
|
||||||
roles.add("admin");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsAdminRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(adminResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluationsAdminRole.size());
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluationsAdminRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
evaluationsAdminRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(adminResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.10"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluationsAdminRole.size());
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluationsAdminRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
roles.clear();
|
|
||||||
roles.add("user");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsUserRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(adminResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluationsUserRole.size());
|
|
||||||
assertTrue(evaluationsUserRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluationsUserRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreateForTypeWithMultiplePolicies() throws Exception {
|
|
||||||
createAlbumResourceTypePermission();
|
|
||||||
|
|
||||||
HashSet<String> roles = new HashSet<>();
|
|
||||||
|
|
||||||
roles.add("admin");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsAdminRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(albumResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(2, evaluationsAdminRole.size());
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.anyUserPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluationsAdminRole.get(this.anyUserPolicy.getId()).getEffect());
|
|
||||||
assertEquals(Effect.PERMIT, evaluationsAdminRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
evaluationsAdminRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(albumResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.10"));
|
|
||||||
|
|
||||||
assertEquals(2, evaluationsAdminRole.size());
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.anyUserPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluationsAdminRole.get(this.anyUserPolicy.getId()).getEffect());
|
|
||||||
assertEquals(Effect.DENY, evaluationsAdminRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
roles.clear();
|
|
||||||
roles.add("user");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsUserRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(albumResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(2, evaluationsUserRole.size());
|
|
||||||
assertTrue(evaluationsUserRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertTrue(evaluationsUserRole.containsKey(this.anyUserPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluationsUserRole.get(this.anyUserPolicy.getId()).getEffect());
|
|
||||||
assertEquals(Effect.DENY, evaluationsUserRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdate() throws Exception {
|
|
||||||
PolicyRepresentation permission = createAlbumResourceTypePermission();
|
|
||||||
Map<String, String> config = permission.getConfig();
|
|
||||||
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(new String[] {this.anyUserPolicy.getId()}));
|
|
||||||
|
|
||||||
permission.setConfig(config);
|
|
||||||
|
|
||||||
newPermissionRequest(permission.getId()).put(Entity.entity(permission, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
HashSet<String> roles = new HashSet<>();
|
|
||||||
|
|
||||||
roles.add("admin");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsAdminRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(albumResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluationsAdminRole.size());
|
|
||||||
assertTrue(evaluationsAdminRole.containsKey(this.anyUserPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluationsAdminRole.get(this.anyUserPolicy.getId()).getEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDelete() throws Exception {
|
|
||||||
PolicyRepresentation newPermission = createAlbumResourceTypePermission();
|
|
||||||
|
|
||||||
Response delete = newPermissionRequest(newPermission.getId()).delete();
|
|
||||||
|
|
||||||
assertEquals(Status.NO_CONTENT.getStatusCode(), delete.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFindById() throws Exception {
|
|
||||||
PolicyRepresentation newPermission = createAlbumResourceTypePermission();
|
|
||||||
|
|
||||||
Response response = newPermissionRequest(newPermission.getId()).get();
|
|
||||||
|
|
||||||
PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals(newPermission.getId(), permission.getId());
|
|
||||||
assertEquals(newPermission.getName(), permission.getName());
|
|
||||||
assertEquals(newPermission.getType(), permission.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreatePolicyForResource() throws Exception {
|
|
||||||
PolicyRepresentation newPermission = new PolicyRepresentation();
|
|
||||||
|
|
||||||
newPermission.setName("Multiple Resource Policy");
|
|
||||||
newPermission.setType("resource");
|
|
||||||
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
config.put("resources", JsonSerialization.writeValueAsString(new String[] {this.albumResource.getId(), this.adminResource.getId()}));
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(new String[] {this.onlyFromSpecificAddressPolicy.getId()}));
|
|
||||||
|
|
||||||
newPermission.setConfig(config);
|
|
||||||
|
|
||||||
Response response = newPermissionRequest().post(Entity.entity(newPermission, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
List<ResourcePermission> permissions = new ArrayList<>();
|
|
||||||
|
|
||||||
permissions.add(new ResourcePermission(this.albumResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluations = performEvaluation(
|
|
||||||
permissions,
|
|
||||||
createAccessToken(Collections.emptySet()),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations.size());
|
|
||||||
assertTrue(evaluations.containsKey(this.onlyFromSpecificAddressPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluations.get(this.onlyFromSpecificAddressPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
permissions = new ArrayList<>();
|
|
||||||
|
|
||||||
permissions.add(new ResourcePermission(this.adminResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
|
|
||||||
evaluations = performEvaluation(
|
|
||||||
permissions,
|
|
||||||
createAccessToken(Collections.emptySet()),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations.size());
|
|
||||||
assertTrue(evaluations.containsKey(this.onlyFromSpecificAddressPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluations.get(this.onlyFromSpecificAddressPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
permissions = new ArrayList<>();
|
|
||||||
|
|
||||||
permissions.add(new ResourcePermission(this.adminResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
permissions.add(new ResourcePermission(this.albumResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
|
|
||||||
evaluations = performEvaluation(
|
|
||||||
permissions,
|
|
||||||
createAccessToken(Collections.emptySet()),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations.size());
|
|
||||||
assertTrue(evaluations.containsKey(this.onlyFromSpecificAddressPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluations.get(this.onlyFromSpecificAddressPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
permissions = new ArrayList<>();
|
|
||||||
|
|
||||||
permissions.add(new ResourcePermission(this.adminResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
permissions.add(new ResourcePermission(this.albumResource, Collections.emptyList(), this.resourceServer));
|
|
||||||
|
|
||||||
evaluations = performEvaluation(
|
|
||||||
permissions,
|
|
||||||
createAccessToken(Collections.emptySet()),
|
|
||||||
createClientConnection("127.0.0.10"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations.size());
|
|
||||||
assertTrue(evaluations.containsKey(this.onlyFromSpecificAddressPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluations.get(this.onlyFromSpecificAddressPolicy.getId()).getEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if a resource can inherit the policies defined for another resource based on its type
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testInheritPoliciesBasedOnResourceType() throws Exception {
|
|
||||||
createAlbumResourceTypePermission();
|
|
||||||
ResourceRepresentation representation = new ResourceRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Alice Family Album");
|
|
||||||
representation.setType(this.albumResource.getType());
|
|
||||||
|
|
||||||
Resource resource = createResource(representation);
|
|
||||||
|
|
||||||
Set<String> roles = new HashSet<>();
|
|
||||||
|
|
||||||
roles.add("user");
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluationsUserRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(resource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(2, evaluationsUserRole.size());
|
|
||||||
assertTrue(evaluationsUserRole.containsKey(this.administrationPolicy.getId()));
|
|
||||||
assertTrue(evaluationsUserRole.containsKey(this.anyUserPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluationsUserRole.get(this.anyUserPolicy.getId()).getEffect());
|
|
||||||
assertEquals(Effect.DENY, evaluationsUserRole.get(this.administrationPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
ResourceRepresentation someResourceRep = new ResourceRepresentation();
|
|
||||||
|
|
||||||
someResourceRep.setName("Some Resource");
|
|
||||||
someResourceRep.setType("Some non-existent type");
|
|
||||||
|
|
||||||
Resource someResource = createResource(someResourceRep);
|
|
||||||
|
|
||||||
evaluationsUserRole = performEvaluation(
|
|
||||||
Arrays.asList(new ResourcePermission(someResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessToken(roles),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
// no policies can be applied given that there is no policy defined for this resource or its type
|
|
||||||
assertEquals(0, evaluationsUserRole.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testResourceAccessWithClientBasedPolicy() throws Exception {
|
|
||||||
ClientModel testClient1 = getClientByClientId("test-client-1");
|
|
||||||
ClientModel testClient2 = getClientByClientId("test-client-2");
|
|
||||||
Policy clientPolicy = createClientPolicy(Collections.singletonList(testClient1));
|
|
||||||
|
|
||||||
PolicyRepresentation newPermission = new PolicyRepresentation();
|
|
||||||
|
|
||||||
newPermission.setName("Client Permission");
|
|
||||||
newPermission.setType("resource");
|
|
||||||
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
config.put("defaultResourceType", "http://photoz.com/admin");
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(new String[] {clientPolicy.getId()}));
|
|
||||||
|
|
||||||
newPermission.setConfig(config);
|
|
||||||
|
|
||||||
Response response = newPermissionRequest().post(Entity.entity(newPermission, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(policyModel);
|
|
||||||
assertEquals(permission.getId(), policyModel.getId());
|
|
||||||
assertEquals(newPermission.getName(), policyModel.getName());
|
|
||||||
assertEquals(resourceServer.getId(), policyModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluations = performEvaluation(
|
|
||||||
Collections.singletonList(new ResourcePermission(adminResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessTokenForClient(testClient1),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations.size());
|
|
||||||
assertTrue(evaluations.containsKey(clientPolicy.getId()));
|
|
||||||
assertEquals(Effect.PERMIT, evaluations.get(clientPolicy.getId()).getEffect());
|
|
||||||
|
|
||||||
Map<String, DefaultEvaluation> evaluations2 = performEvaluation(
|
|
||||||
Collections.singletonList(new ResourcePermission(adminResource, Collections.emptyList(), resourceServer)),
|
|
||||||
createAccessTokenForClient(testClient2),
|
|
||||||
createClientConnection("127.0.0.1"));
|
|
||||||
|
|
||||||
assertEquals(1, evaluations2.size());
|
|
||||||
assertTrue(evaluations2.containsKey(clientPolicy.getId()));
|
|
||||||
assertEquals(Effect.DENY, evaluations2.get(clientPolicy.getId()).getEffect());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Policy createClientPolicy(List<ClientModel> allowedClients) {
|
|
||||||
return onAuthorizationSession(authorizationProvider -> {
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
PolicyRepresentation representation = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setName("Client-Based Policy");
|
|
||||||
representation.setType("client");
|
|
||||||
|
|
||||||
List<String> clientIds = new ArrayList<>();
|
|
||||||
for (ClientModel client : allowedClients) {
|
|
||||||
clientIds.add(client.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] clients = clientIds.toArray(new String[clientIds.size()]);
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
try {
|
|
||||||
config.put("clients", JsonSerialization.writeValueAsString(clients));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
representation.setConfig(config);
|
|
||||||
|
|
||||||
return policyStore.create(representation, resourceServer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private AccessToken createAccessTokenForClient(ClientModel client) {
|
|
||||||
AccessToken accessToken = new AccessToken();
|
|
||||||
|
|
||||||
accessToken.setRealmAccess(new AccessToken.Access());
|
|
||||||
accessToken.issuedFor = client.getClientId();
|
|
||||||
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyRepresentation createAlbumResourceTypePermission() throws Exception {
|
|
||||||
PolicyRepresentation newPermission = new PolicyRepresentation();
|
|
||||||
|
|
||||||
newPermission.setName("Album Resource Policy");
|
|
||||||
newPermission.setType("resource");
|
|
||||||
newPermission.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
|
|
||||||
|
|
||||||
HashedMap config = new HashedMap();
|
|
||||||
|
|
||||||
config.put("defaultResourceType", albumResource.getType());
|
|
||||||
|
|
||||||
String[] associatedPolicies = {this.anyUserPolicy.getId(), this.administrationPolicy.getId()};
|
|
||||||
String applyPolicies = JsonSerialization.writeValueAsString(associatedPolicies);
|
|
||||||
|
|
||||||
config.put("applyPolicies", applyPolicies);
|
|
||||||
|
|
||||||
newPermission.setConfig(config);
|
|
||||||
|
|
||||||
Response response = newPermissionRequest().post(Entity.entity(newPermission, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
PolicyRepresentation permission = response.readEntity(PolicyRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Policy policyModel = authorizationProvider.getStoreFactory().getPolicyStore().findById(permission.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(policyModel);
|
|
||||||
assertEquals(permission.getId(), policyModel.getId());
|
|
||||||
assertEquals(permission.getName(), policyModel.getName());
|
|
||||||
assertEquals(permission.getType(), policyModel.getType());
|
|
||||||
assertTrue(permission.getConfig().containsValue(albumResource.getType()));
|
|
||||||
assertTrue(policyModel.getAssociatedPolicies().stream().map(Policy::getId).collect(Collectors.toList()).containsAll(Arrays.asList(associatedPolicies)));
|
|
||||||
|
|
||||||
assertEquals(resourceServer.getId(), policyModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
|
|
||||||
return permission;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source.
|
|
||||||
* Copyright 2016 Red Hat, Inc., and individual 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.authorization;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import javax.ws.rs.client.Entity;
|
|
||||||
import javax.ws.rs.client.Invocation.Builder;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public class ScopeManagementTest extends AbstractPhotozAdminTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCreate() throws Exception {
|
|
||||||
ScopeRepresentation newScope = new ScopeRepresentation();
|
|
||||||
|
|
||||||
newScope.setName("New Scope");
|
|
||||||
newScope.setIconUri("Icon URI");
|
|
||||||
|
|
||||||
Response response = newScopeRequest().post(Entity.entity(newScope, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(scopeModel);
|
|
||||||
assertEquals(scope.getId(), scopeModel.getId());
|
|
||||||
assertEquals("New Scope", scopeModel.getName());
|
|
||||||
assertEquals("Icon URI", scopeModel.getIconUri());
|
|
||||||
assertEquals(resourceServer.getId(), scopeModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdate() throws Exception {
|
|
||||||
ScopeRepresentation newScope = new ScopeRepresentation();
|
|
||||||
|
|
||||||
newScope.setName("New Scope");
|
|
||||||
newScope.setIconUri("Icon URI");
|
|
||||||
|
|
||||||
Response response = newScopeRequest().post(Entity.entity(newScope, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
newScope.setName("New Scope Changed");
|
|
||||||
newScope.setIconUri("Icon URI Changed");
|
|
||||||
|
|
||||||
response = newScopeRequest().post(Entity.entity(newScope, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNotNull(scopeModel);
|
|
||||||
assertEquals(scope.getId(), scopeModel.getId());
|
|
||||||
assertEquals("New Scope Changed", scopeModel.getName());
|
|
||||||
assertEquals("Icon URI Changed", scopeModel.getIconUri());
|
|
||||||
assertEquals(resourceServer.getId(), scopeModel.getResourceServer().getId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFindById() throws Exception {
|
|
||||||
ScopeRepresentation newScope = new ScopeRepresentation();
|
|
||||||
|
|
||||||
newScope.setName("New Scope");
|
|
||||||
newScope.setIconUri("Icon URI");
|
|
||||||
|
|
||||||
Response response = newScopeRequest().post(Entity.entity(newScope, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
|
|
||||||
|
|
||||||
response = newScopeRequest(scope.getId()).get();
|
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
scope = response.readEntity(ScopeRepresentation.class);
|
|
||||||
|
|
||||||
assertEquals("New Scope", scope.getName());
|
|
||||||
assertEquals("Icon URI", scope.getIconUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDelete() throws Exception {
|
|
||||||
ScopeRepresentation newScope = new ScopeRepresentation();
|
|
||||||
|
|
||||||
newScope.setName("New Scope");
|
|
||||||
|
|
||||||
Response response = newScopeRequest().post(Entity.entity(newScope, MediaType.APPLICATION_JSON_TYPE));
|
|
||||||
|
|
||||||
assertEquals(Status.CREATED.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
ScopeRepresentation scope = response.readEntity(ScopeRepresentation.class);
|
|
||||||
|
|
||||||
assertNotNull(scope.getId());
|
|
||||||
|
|
||||||
response = newScopeRequest(scope.getId()).delete();
|
|
||||||
|
|
||||||
assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
onAuthorizationSession(authorizationProvider -> {
|
|
||||||
Scope scopeModel = authorizationProvider.getStoreFactory().getScopeStore().findById(scope.getId(), resourceServer.getId());
|
|
||||||
|
|
||||||
assertNull(scopeModel);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Builder newScopeRequest(String... id) {
|
|
||||||
String idPathParam = "";
|
|
||||||
|
|
||||||
if (id.length != 0) {
|
|
||||||
idPathParam = "/" + id[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return newClient(getClientByClientId("photoz-restful-api"), "/resource-server/scope" + idPathParam);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue