[KEYCLOAK-3144] - Add authorization settings when exporting/importing a realm.
This commit is contained in:
parent
fd983690e2
commit
a8d2b810cf
24 changed files with 1376 additions and 849 deletions
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.representations.idm;
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ public class ClientRepresentation {
|
||||||
private Boolean useTemplateConfig;
|
private Boolean useTemplateConfig;
|
||||||
private Boolean useTemplateScope;
|
private Boolean useTemplateScope;
|
||||||
private Boolean useTemplateMappers;
|
private Boolean useTemplateMappers;
|
||||||
|
private ResourceServerRepresentation authorizationSettings;
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -241,6 +244,9 @@ public class ClientRepresentation {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getAuthorizationServicesEnabled() {
|
public Boolean getAuthorizationServicesEnabled() {
|
||||||
|
if (authorizationSettings != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return authorizationServicesEnabled;
|
return authorizationServicesEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,4 +359,11 @@ public class ClientRepresentation {
|
||||||
this.useTemplateMappers = useTemplateMappers;
|
this.useTemplateMappers = useTemplateMappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResourceServerRepresentation getAuthorizationSettings() {
|
||||||
|
return authorizationSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorizationSettings(ResourceServerRepresentation authorizationSettings) {
|
||||||
|
this.authorizationSettings = authorizationSettings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
|
@ -64,17 +65,19 @@ public final class AuthorizationProvider implements Provider {
|
||||||
private final StoreFactory storeFactory;
|
private final StoreFactory storeFactory;
|
||||||
private final List<PolicyProviderFactory> policyProviderFactories;
|
private final List<PolicyProviderFactory> policyProviderFactories;
|
||||||
private final KeycloakSession keycloakSession;
|
private final KeycloakSession keycloakSession;
|
||||||
|
private final RealmModel realm;
|
||||||
|
|
||||||
public AuthorizationProvider(KeycloakSession session, StoreFactory storeFactory, Executor scheduller) {
|
public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory, Executor scheduller) {
|
||||||
this.keycloakSession = session;
|
this.keycloakSession = session;
|
||||||
|
this.realm = realm;
|
||||||
this.storeFactory = storeFactory;
|
this.storeFactory = storeFactory;
|
||||||
this.scheduller = scheduller;
|
this.scheduller = scheduller;
|
||||||
this.policyProviderFactories = configurePolicyProviderFactories(session);
|
this.policyProviderFactories = configurePolicyProviderFactories(session);
|
||||||
this.policyEvaluator = new DefaultPolicyEvaluator(this, this.policyProviderFactories);
|
this.policyEvaluator = new DefaultPolicyEvaluator(this, this.policyProviderFactories);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorizationProvider(KeycloakSession session, StoreFactory storeFactory) {
|
public AuthorizationProvider(KeycloakSession session, RealmModel realm, StoreFactory storeFactory) {
|
||||||
this(session, storeFactory, Runnable::run);
|
this(session, realm, storeFactory, Runnable::run);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,6 +123,10 @@ public final class AuthorizationProvider implements Provider {
|
||||||
return this.keycloakSession;
|
return this.keycloakSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RealmModel getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
private List<PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSession session) {
|
private List<PolicyProviderFactory> configurePolicyProviderFactories(KeycloakSession session) {
|
||||||
List<ProviderFactory> providerFactories = session.getKeycloakSessionFactory().getProviderFactories(PolicyProvider.class);
|
List<ProviderFactory> providerFactories = session.getKeycloakSessionFactory().getProviderFactories(PolicyProvider.class);
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,14 @@
|
||||||
|
|
||||||
package org.keycloak.authorization;
|
package org.keycloak.authorization;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public interface AuthorizationProviderFactory extends ProviderFactory<AuthorizationProvider> {
|
public interface AuthorizationProviderFactory extends ProviderFactory<AuthorizationProvider> {
|
||||||
|
|
||||||
|
AuthorizationProvider create(KeycloakSession session, RealmModel realm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
|
|
||||||
package org.keycloak.models.utils;
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.events.Event;
|
import org.keycloak.events.Event;
|
||||||
import org.keycloak.events.admin.AdminEvent;
|
import org.keycloak.events.admin.AdminEvent;
|
||||||
|
@ -31,6 +39,7 @@ import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelException;
|
import org.keycloak.models.ModelException;
|
||||||
import org.keycloak.models.OTPPolicy;
|
import org.keycloak.models.OTPPolicy;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
|
@ -72,8 +81,25 @@ import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
import java.util.*;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -767,4 +793,181 @@ public class ModelToRepresentation {
|
||||||
rep.setConfig(component.getConfig());
|
rep.setConfig(component.getConfig());
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ScopeRepresentation toRepresentation(Scope model, AuthorizationProvider authorizationProvider) {
|
||||||
|
ScopeRepresentation scope = new ScopeRepresentation();
|
||||||
|
|
||||||
|
scope.setId(model.getId());
|
||||||
|
scope.setName(model.getName());
|
||||||
|
scope.setIconUri(model.getIconUri());
|
||||||
|
|
||||||
|
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
||||||
|
|
||||||
|
scope.setResources(new ArrayList<>());
|
||||||
|
|
||||||
|
storeFactory.getResourceStore().findByScope(model.getId()).forEach(resource -> scope.getResources().add(toRepresentation(resource, resource.getResourceServer(), authorizationProvider)));
|
||||||
|
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
|
|
||||||
|
scope.setPolicies(new ArrayList<>());
|
||||||
|
|
||||||
|
policyStore.findByScopeIds(Arrays.asList(model.getId()), model.getResourceServer().getId()).forEach(policyModel -> {
|
||||||
|
PolicyRepresentation policy = new PolicyRepresentation();
|
||||||
|
|
||||||
|
policy.setId(policyModel.getId());
|
||||||
|
policy.setName(policyModel.getName());
|
||||||
|
policy.setType(policyModel.getType());
|
||||||
|
|
||||||
|
if (!scope.getPolicies().contains(policy)) {
|
||||||
|
scope.getPolicies().add(policy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceServerRepresentation toRepresentation(ResourceServer model, ClientModel client) {
|
||||||
|
ResourceServerRepresentation server = new ResourceServerRepresentation();
|
||||||
|
|
||||||
|
server.setId(model.getId());
|
||||||
|
server.setClientId(model.getClientId());
|
||||||
|
server.setName(client.getClientId());
|
||||||
|
server.setAllowRemoteResourceManagement(model.isAllowRemoteResourceManagement());
|
||||||
|
server.setPolicyEnforcementMode(model.getPolicyEnforcementMode());
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PolicyRepresentation toRepresentation(Policy model, AuthorizationProvider authorization) {
|
||||||
|
PolicyRepresentation representation = new PolicyRepresentation();
|
||||||
|
|
||||||
|
representation.setId(model.getId());
|
||||||
|
representation.setName(model.getName());
|
||||||
|
representation.setDescription(model.getDescription());
|
||||||
|
representation.setType(model.getType());
|
||||||
|
representation.setDecisionStrategy(model.getDecisionStrategy());
|
||||||
|
representation.setLogic(model.getLogic());
|
||||||
|
representation.setConfig(new HashMap<>(model.getConfig()));
|
||||||
|
|
||||||
|
List<Policy> policies = authorization.getStoreFactory().getPolicyStore().findDependentPolicies(model.getId());
|
||||||
|
|
||||||
|
representation.setDependentPolicies(policies.stream().map(policy -> {
|
||||||
|
PolicyRepresentation representation1 = new PolicyRepresentation();
|
||||||
|
|
||||||
|
representation1.setId(policy.getId());
|
||||||
|
representation1.setName(policy.getName());
|
||||||
|
|
||||||
|
return representation1;
|
||||||
|
}).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
List<PolicyRepresentation> associatedPolicies = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> obj = model.getAssociatedPolicies().stream().map(policy -> {
|
||||||
|
PolicyRepresentation representation1 = new PolicyRepresentation();
|
||||||
|
|
||||||
|
representation1.setId(policy.getId());
|
||||||
|
representation1.setName(policy.getName());
|
||||||
|
representation1.setType(policy.getType());
|
||||||
|
|
||||||
|
associatedPolicies.add(representation1);
|
||||||
|
|
||||||
|
return policy.getId();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
representation.setAssociatedPolicies(associatedPolicies);
|
||||||
|
|
||||||
|
try {
|
||||||
|
representation.getConfig().put("applyPolicies", JsonSerialization.writeValueAsString(obj));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return representation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
ResourceRepresentation resource = new ResourceRepresentation();
|
||||||
|
|
||||||
|
resource.setId(model.getId());
|
||||||
|
resource.setType(model.getType());
|
||||||
|
resource.setName(model.getName());
|
||||||
|
resource.setUri(model.getUri());
|
||||||
|
resource.setIconUri(model.getIconUri());
|
||||||
|
|
||||||
|
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
|
||||||
|
|
||||||
|
owner.setId(model.getOwner());
|
||||||
|
|
||||||
|
KeycloakSession keycloakSession = authorization.getKeycloakSession();
|
||||||
|
RealmModel realm = authorization.getRealm();
|
||||||
|
|
||||||
|
if (owner.getId().equals(resourceServer.getClientId())) {
|
||||||
|
ClientModel clientModel = realm.getClientById(resourceServer.getClientId());
|
||||||
|
owner.setName(clientModel.getClientId());
|
||||||
|
} else {
|
||||||
|
UserModel userModel = keycloakSession.users().getUserById(owner.getId(), realm);
|
||||||
|
|
||||||
|
if (userModel == null) {
|
||||||
|
throw new RuntimeException("Could not find the user [" + owner.getId() + "] who owns the Resource [" + resource.getId() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
owner.setName(userModel.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.setOwner(owner);
|
||||||
|
|
||||||
|
resource.setScopes(model.getScopes().stream().map(model1 -> {
|
||||||
|
ScopeRepresentation scope = new ScopeRepresentation();
|
||||||
|
scope.setId(model1.getId());
|
||||||
|
scope.setName(model1.getName());
|
||||||
|
String iconUri = model1.getIconUri();
|
||||||
|
if (iconUri != null) {
|
||||||
|
scope.setIconUri(iconUri);
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}).collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
resource.setTypedScopes(new ArrayList<>());
|
||||||
|
|
||||||
|
if (resource.getType() != null) {
|
||||||
|
ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
|
||||||
|
for (Resource typed : resourceStore.findByType(resource.getType())) {
|
||||||
|
if (typed.getOwner().equals(resourceServer.getClientId()) && !typed.getId().equals(resource.getId())) {
|
||||||
|
resource.setTypedScopes(typed.getScopes().stream().map(model1 -> {
|
||||||
|
ScopeRepresentation scope = new ScopeRepresentation();
|
||||||
|
scope.setId(model1.getId());
|
||||||
|
scope.setName(model1.getName());
|
||||||
|
String iconUri = model1.getIconUri();
|
||||||
|
if (iconUri != null) {
|
||||||
|
scope.setIconUri(iconUri);
|
||||||
|
}
|
||||||
|
return scope;
|
||||||
|
}).filter(scopeRepresentation -> !resource.getScopes().contains(scopeRepresentation)).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.setPolicies(new ArrayList<>());
|
||||||
|
|
||||||
|
Set<Policy> policies = new HashSet<>();
|
||||||
|
PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
|
||||||
|
|
||||||
|
policies.addAll(policyStore.findByResource(resource.getId()));
|
||||||
|
policies.addAll(policyStore.findByResourceType(resource.getType(), resourceServer.getId()));
|
||||||
|
policies.addAll(policyStore.findByScopeIds(resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toList()), resourceServer.getId()));
|
||||||
|
|
||||||
|
for (Policy policyModel : policies) {
|
||||||
|
PolicyRepresentation policy = new PolicyRepresentation();
|
||||||
|
|
||||||
|
policy.setId(policyModel.getId());
|
||||||
|
policy.setName(policyModel.getName());
|
||||||
|
policy.setType(policyModel.getType());
|
||||||
|
|
||||||
|
if (!resource.getPolicies().contains(policy)) {
|
||||||
|
resource.getPolicies().add(policy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,16 @@
|
||||||
package org.keycloak.models.utils;
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.AuthorizationProviderFactory;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.model.Scope;
|
||||||
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
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.util.MultivaluedHashMap;
|
import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.hash.Pbkdf2PasswordHashProvider;
|
import org.keycloak.hash.Pbkdf2PasswordHashProvider;
|
||||||
|
@ -84,6 +92,12 @@ import org.keycloak.representations.idm.UserFederationMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
import org.keycloak.representations.idm.authorization.PolicyEnforcementMode;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -95,8 +109,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.function.Function;
|
||||||
import static java.lang.Boolean.TRUE;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class RepresentationToModel {
|
public class RepresentationToModel {
|
||||||
|
|
||||||
|
@ -277,6 +291,13 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rep.getClients() != null) {
|
||||||
|
rep.getClients().forEach(clientRepresentation -> {
|
||||||
|
ClientModel client = newRealm.getClientByClientId(clientRepresentation.getClientId());
|
||||||
|
importAuthorizationSettings(clientRepresentation, client, session);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (rep.getSmtpServer() != null) {
|
if (rep.getSmtpServer() != null) {
|
||||||
newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
|
newRealm.setSmtpConfig(new HashMap(rep.getSmtpServer()));
|
||||||
}
|
}
|
||||||
|
@ -1022,22 +1043,6 @@ public class RepresentationToModel {
|
||||||
if (resourceRep.isUseTemplateMappers() != null) client.setUseTemplateMappers(resourceRep.isUseTemplateMappers());
|
if (resourceRep.isUseTemplateMappers() != null) client.setUseTemplateMappers(resourceRep.isUseTemplateMappers());
|
||||||
else client.setUseTemplateMappers(resourceRep.getClientTemplate() != null);
|
else client.setUseTemplateMappers(resourceRep.getClientTemplate() != null);
|
||||||
|
|
||||||
boolean createResourceServer = TRUE.equals(resourceRep.getAuthorizationServicesEnabled());
|
|
||||||
|
|
||||||
if (createResourceServer) {
|
|
||||||
AuthorizationProvider provider = session.getProvider(AuthorizationProvider.class);
|
|
||||||
ResourceServerStore resourceServerStore = provider.getStoreFactory().getResourceServerStore();
|
|
||||||
|
|
||||||
client.setServiceAccountsEnabled(true);
|
|
||||||
client.setBearerOnly(false);
|
|
||||||
client.setPublicClient(false);
|
|
||||||
|
|
||||||
ResourceServer resourceServer = resourceServerStore.create(client.getId());
|
|
||||||
|
|
||||||
resourceServer.setAllowRemoteResourceManagement(true);
|
|
||||||
resourceServer.setPolicyEnforcementMode(PolicyEnforcementMode.ENFORCING);
|
|
||||||
}
|
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,4 +1661,432 @@ public class RepresentationToModel {
|
||||||
model.setName(rep.getName());
|
model.setName(rep.getName());
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void importAuthorizationSettings(ClientRepresentation clientRepresentation, ClientModel client, KeycloakSession session) {
|
||||||
|
if (Boolean.TRUE.equals(clientRepresentation.getAuthorizationServicesEnabled())) {
|
||||||
|
AuthorizationProviderFactory authorizationFactory = (AuthorizationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(AuthorizationProvider.class);
|
||||||
|
AuthorizationProvider authorization = authorizationFactory.create(session, client.getRealm());
|
||||||
|
|
||||||
|
client.setServiceAccountsEnabled(true);
|
||||||
|
client.setBearerOnly(false);
|
||||||
|
client.setPublicClient(false);
|
||||||
|
|
||||||
|
ResourceServerRepresentation rep = clientRepresentation.getAuthorizationSettings();
|
||||||
|
|
||||||
|
if (rep == null) {
|
||||||
|
rep = new ResourceServerRepresentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.setClientId(client.getId());
|
||||||
|
|
||||||
|
toModel(rep, authorization);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void toModel(ResourceServerRepresentation rep, AuthorizationProvider authorization) {
|
||||||
|
ResourceServerStore resourceServerStore = authorization.getStoreFactory().getResourceServerStore();
|
||||||
|
ResourceServer resourceServer;
|
||||||
|
ResourceServer existing = resourceServerStore.findByClient(rep.getClientId());
|
||||||
|
|
||||||
|
if (existing == null) {
|
||||||
|
resourceServer = resourceServerStore.create(rep.getClientId());
|
||||||
|
resourceServer.setAllowRemoteResourceManagement(true);
|
||||||
|
resourceServer.setPolicyEnforcementMode(PolicyEnforcementMode.ENFORCING);
|
||||||
|
} else {
|
||||||
|
resourceServer = existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceServer.setPolicyEnforcementMode(rep.getPolicyEnforcementMode());
|
||||||
|
resourceServer.setAllowRemoteResourceManagement(rep.isAllowRemoteResourceManagement());
|
||||||
|
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
ScopeStore scopeStore = storeFactory.getScopeStore();
|
||||||
|
|
||||||
|
rep.getScopes().forEach(scope -> {
|
||||||
|
toModel(scope, resourceServer, authorization);
|
||||||
|
});
|
||||||
|
|
||||||
|
KeycloakSession session = authorization.getKeycloakSession();
|
||||||
|
RealmModel realm = authorization.getRealm();
|
||||||
|
|
||||||
|
rep.getResources().forEach(resourceRepresentation -> {
|
||||||
|
ResourceOwnerRepresentation owner = resourceRepresentation.getOwner();
|
||||||
|
|
||||||
|
if (owner == null) {
|
||||||
|
owner = new ResourceOwnerRepresentation();
|
||||||
|
resourceRepresentation.setOwner(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
owner.setId(resourceServer.getClientId());
|
||||||
|
|
||||||
|
if (owner.getName() != null) {
|
||||||
|
UserModel user = session.users().getUserByUsername(owner.getName(), realm);
|
||||||
|
|
||||||
|
if (user != null) {
|
||||||
|
owner.setId(user.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toModel(resourceRepresentation, resourceServer, authorization);
|
||||||
|
});
|
||||||
|
|
||||||
|
rep.getPolicies().forEach(policyRepresentation -> {
|
||||||
|
Map<String, String> config = policyRepresentation.getConfig();
|
||||||
|
|
||||||
|
String roles = config.get("roles");
|
||||||
|
|
||||||
|
if (roles != null && !roles.isEmpty()) {
|
||||||
|
try {
|
||||||
|
List<Map> rolesMap = JsonSerialization.readValue(roles, List.class);
|
||||||
|
config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleConfig -> {
|
||||||
|
String roleName = roleConfig.get("id").toString();
|
||||||
|
String clientId = null;
|
||||||
|
int clientIdSeparator = roleName.indexOf("/");
|
||||||
|
|
||||||
|
if (clientIdSeparator != -1) {
|
||||||
|
clientId = roleName.substring(0, clientIdSeparator);
|
||||||
|
roleName = roleName.substring(clientIdSeparator + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoleModel role;
|
||||||
|
|
||||||
|
if (clientId == null) {
|
||||||
|
role = realm.getRole(roleName);
|
||||||
|
} else {
|
||||||
|
role = realm.getClientByClientId(clientId).getRole(roleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to find any client role with the given name
|
||||||
|
if (role == null) {
|
||||||
|
String finalRoleName = roleName;
|
||||||
|
role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == null) {
|
||||||
|
throw new RuntimeException("Error while importing configuration. Role [" + roleName + "] could not be found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
roleConfig.put("id", role.getId());
|
||||||
|
return roleConfig;
|
||||||
|
}).collect(Collectors.toList())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String users = config.get("users");
|
||||||
|
|
||||||
|
if (users != null && !users.isEmpty()) {
|
||||||
|
try {
|
||||||
|
List<String> usersMap = JsonSerialization.readValue(users, List.class);
|
||||||
|
config.put("users", JsonSerialization.writeValueAsString(usersMap.stream().map(userName -> session.users().getUserByUsername(userName, realm).getId()).collect(Collectors.toList())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String scopes = config.get("scopes");
|
||||||
|
|
||||||
|
if (scopes != null && !scopes.isEmpty()) {
|
||||||
|
try {
|
||||||
|
List<String> scopesMap = JsonSerialization.readValue(scopes, List.class);
|
||||||
|
config.put("scopes", JsonSerialization.writeValueAsString(scopesMap.stream().map(scopeName -> {
|
||||||
|
Scope newScope = scopeStore.findByName(scopeName, resourceServer.getId());
|
||||||
|
|
||||||
|
if (newScope == null) {
|
||||||
|
throw new RuntimeException("Scope with name [" + scopeName + "] not defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return newScope.getId();
|
||||||
|
}).collect(Collectors.toList())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String policyResources = config.get("resources");
|
||||||
|
|
||||||
|
if (policyResources != null && !policyResources.isEmpty()) {
|
||||||
|
ResourceStore resourceStore = storeFactory.getResourceStore();
|
||||||
|
try {
|
||||||
|
List<String> resources = JsonSerialization.readValue(policyResources, List.class);
|
||||||
|
config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(resourceName -> {
|
||||||
|
return resourceStore.findByName(resourceName, resourceServer.getId()).getId();
|
||||||
|
}).collect(Collectors.toList())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String applyPolicies = config.get("applyPolicies");
|
||||||
|
|
||||||
|
if (applyPolicies != null && !applyPolicies.isEmpty()) {
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
|
try {
|
||||||
|
List<String> policies = JsonSerialization.readValue(applyPolicies, List.class);
|
||||||
|
config.put("applyPolicies", JsonSerialization.writeValueAsString(policies.stream().map(policyName -> {
|
||||||
|
Policy policy = policyStore.findByName(policyName, resourceServer.getId());
|
||||||
|
|
||||||
|
if (policy == null) {
|
||||||
|
throw new RuntimeException("Policy with name [" + policyName + "] not defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return policy.getId();
|
||||||
|
}).collect(Collectors.toList())));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toModel(policyRepresentation, resourceServer, authorization);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Policy toModel(PolicyRepresentation policy, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
|
||||||
|
Policy existing;
|
||||||
|
|
||||||
|
if (policy.getId() != null) {
|
||||||
|
existing = policyStore.findById(policy.getId());
|
||||||
|
} else {
|
||||||
|
existing = policyStore.findByName(policy.getName(), resourceServer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
existing.setName(policy.getName());
|
||||||
|
existing.setDescription(policy.getDescription());
|
||||||
|
existing.setConfig(policy.getConfig());
|
||||||
|
existing.setDecisionStrategy(policy.getDecisionStrategy());
|
||||||
|
existing.setLogic(policy.getLogic());
|
||||||
|
|
||||||
|
updateResources(existing, authorization);
|
||||||
|
updateAssociatedPolicies(existing, resourceServer, authorization);
|
||||||
|
updateScopes(existing, authorization);
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
Policy model = policyStore.create(policy.getName(), policy.getType(), resourceServer);
|
||||||
|
|
||||||
|
model.setDescription(policy.getDescription());
|
||||||
|
model.setDecisionStrategy(policy.getDecisionStrategy());
|
||||||
|
model.setLogic(policy.getLogic());
|
||||||
|
model.setConfig(policy.getConfig());
|
||||||
|
|
||||||
|
updateResources(model, authorization);
|
||||||
|
updateAssociatedPolicies(model, resourceServer, authorization);
|
||||||
|
updateScopes(model, authorization);
|
||||||
|
|
||||||
|
policy.setId(model.getId());
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateScopes(Policy policy, AuthorizationProvider authorization) {
|
||||||
|
String scopes = policy.getConfig().get("scopes");
|
||||||
|
if (scopes != null) {
|
||||||
|
String[] scopeIds;
|
||||||
|
|
||||||
|
try {
|
||||||
|
scopeIds = JsonSerialization.readValue(scopes, String[].class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
|
||||||
|
for (String scopeId : scopeIds) {
|
||||||
|
boolean hasScope = false;
|
||||||
|
|
||||||
|
for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
|
||||||
|
if (scopeModel.getId().equals(scopeId)) {
|
||||||
|
hasScope = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasScope) {
|
||||||
|
policy.addScope(storeFactory.getScopeStore().findById(scopeId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
|
||||||
|
boolean hasScope = false;
|
||||||
|
|
||||||
|
for (String scopeId : scopeIds) {
|
||||||
|
if (scopeModel.getId().equals(scopeId)) {
|
||||||
|
hasScope = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasScope) {
|
||||||
|
policy.removeScope(scopeModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateAssociatedPolicies(Policy policy, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
String policies = policy.getConfig().get("applyPolicies");
|
||||||
|
|
||||||
|
if (policies != null) {
|
||||||
|
String[] policyIds;
|
||||||
|
|
||||||
|
try {
|
||||||
|
policyIds = JsonSerialization.readValue(policies, String[].class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
|
|
||||||
|
for (String policyId : policyIds) {
|
||||||
|
boolean hasPolicy = false;
|
||||||
|
|
||||||
|
for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
|
||||||
|
if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
|
||||||
|
hasPolicy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!hasPolicy) {
|
||||||
|
Policy associatedPolicy = policyStore.findById(policyId);
|
||||||
|
|
||||||
|
if (associatedPolicy == null) {
|
||||||
|
associatedPolicy = policyStore.findByName(policyId, resourceServer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
policy.addAssociatedPolicy(associatedPolicy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
|
||||||
|
boolean hasPolicy = false;
|
||||||
|
|
||||||
|
for (String policyId : policyIds) {
|
||||||
|
if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
|
||||||
|
hasPolicy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPolicy) {
|
||||||
|
policy.removeAssociatedPolicy(policyModel);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateResources(Policy policy, AuthorizationProvider authorization) {
|
||||||
|
String resources = policy.getConfig().get("resources");
|
||||||
|
if (resources != null) {
|
||||||
|
String[] resourceIds;
|
||||||
|
|
||||||
|
try {
|
||||||
|
resourceIds = JsonSerialization.readValue(resources, String[].class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
|
||||||
|
for (String resourceId : resourceIds) {
|
||||||
|
boolean hasResource = false;
|
||||||
|
for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
|
||||||
|
if (resourceModel.getId().equals(resourceId)) {
|
||||||
|
hasResource = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasResource && !"".equals(resourceId)) {
|
||||||
|
policy.addResource(storeFactory.getResourceStore().findById(resourceId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
|
||||||
|
boolean hasResource = false;
|
||||||
|
|
||||||
|
for (String resourceId : resourceIds) {
|
||||||
|
if (resourceModel.getId().equals(resourceId)) {
|
||||||
|
hasResource = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasResource) {
|
||||||
|
policy.removeResource(resourceModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Resource toModel(ResourceRepresentation resource, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
|
||||||
|
Resource existing;
|
||||||
|
|
||||||
|
if (resource.getId() != null) {
|
||||||
|
existing = resourceStore.findById(resource.getId());
|
||||||
|
} else {
|
||||||
|
existing = resourceStore.findByName(resource.getName(), resourceServer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
existing.setName(resource.getName());
|
||||||
|
existing.setType(resource.getType());
|
||||||
|
existing.setUri(resource.getUri());
|
||||||
|
existing.setIconUri(resource.getIconUri());
|
||||||
|
|
||||||
|
existing.updateScopes(resource.getScopes().stream()
|
||||||
|
.map((ScopeRepresentation scope) -> toModel(scope, resourceServer, authorization))
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceOwnerRepresentation owner = resource.getOwner();
|
||||||
|
|
||||||
|
if (owner == null) {
|
||||||
|
owner = new ResourceOwnerRepresentation();
|
||||||
|
owner.setId(resourceServer.getClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner.getId() == null) {
|
||||||
|
throw new RuntimeException("No owner specified for resource [" + resource.getName() + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource model = resourceStore.create(resource.getName(), resourceServer, owner.getId());
|
||||||
|
|
||||||
|
model.setType(resource.getType());
|
||||||
|
model.setUri(resource.getUri());
|
||||||
|
model.setIconUri(resource.getIconUri());
|
||||||
|
|
||||||
|
Set<ScopeRepresentation> scopes = resource.getScopes();
|
||||||
|
|
||||||
|
if (scopes != null) {
|
||||||
|
model.updateScopes(scopes.stream().map((Function<ScopeRepresentation, Scope>) scope -> toModel(scope, resourceServer, authorization)).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.setId(model.getId());
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Scope toModel(ScopeRepresentation scope, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
ScopeStore scopeStore = storeFactory.getScopeStore();
|
||||||
|
Scope existing;
|
||||||
|
|
||||||
|
if (scope.getId() != null) {
|
||||||
|
existing = scopeStore.findById(scope.getId());
|
||||||
|
} else {
|
||||||
|
existing = scopeStore.findByName(scope.getName(), resourceServer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
existing.setName(scope.getName());
|
||||||
|
existing.setIconUri(scope.getIconUri());
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope model = scopeStore.create(scope.getName(), resourceServer);
|
||||||
|
model.setIconUri(scope.getIconUri());
|
||||||
|
scope.setId(model.getId());
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.Config;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
import org.keycloak.models.cache.authorization.CachedStoreFactoryProvider;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
@ -35,13 +36,7 @@ public class DefaultAuthorizationProviderFactory implements AuthorizationProvide
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizationProvider create(KeycloakSession session) {
|
public AuthorizationProvider create(KeycloakSession session) {
|
||||||
StoreFactory storeFactory = session.getProvider(CachedStoreFactoryProvider.class);
|
return create(session, session.getContext().getRealm());
|
||||||
|
|
||||||
if (storeFactory == null) {
|
|
||||||
storeFactory = session.getProvider(StoreFactory.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AuthorizationProvider(session, storeFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,4 +65,15 @@ public class DefaultAuthorizationProviderFactory implements AuthorizationProvide
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return "authorization";
|
return "authorization";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthorizationProvider create(KeycloakSession session, RealmModel realm) {
|
||||||
|
StoreFactory storeFactory = session.getProvider(CachedStoreFactoryProvider.class);
|
||||||
|
|
||||||
|
if (storeFactory == null) {
|
||||||
|
storeFactory = session.getProvider(StoreFactory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AuthorizationProvider(session, realm, storeFactory);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -90,15 +90,15 @@ public class PolicyEvaluationService {
|
||||||
public void evaluate(PolicyEvaluationRequest evaluationRequest, @Suspended AsyncResponse asyncResponse) {
|
public void evaluate(PolicyEvaluationRequest evaluationRequest, @Suspended AsyncResponse asyncResponse) {
|
||||||
KeycloakIdentity identity = createIdentity(evaluationRequest);
|
KeycloakIdentity identity = createIdentity(evaluationRequest);
|
||||||
EvaluationContext evaluationContext = createEvaluationContext(evaluationRequest, identity);
|
EvaluationContext evaluationContext = createEvaluationContext(evaluationRequest, identity);
|
||||||
authorization.evaluators().from(createPermissions(evaluationRequest, evaluationContext, authorization), evaluationContext).evaluate(createDecisionCollector(evaluationRequest, authorization, identity, asyncResponse));
|
authorization.evaluators().from(createPermissions(evaluationRequest, evaluationContext, authorization), evaluationContext).evaluate(createDecisionCollector(authorization, identity, asyncResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DecisionResultCollector createDecisionCollector(PolicyEvaluationRequest evaluationRequest, AuthorizationProvider authorization, KeycloakIdentity identity, AsyncResponse asyncResponse) {
|
private DecisionResultCollector createDecisionCollector(AuthorizationProvider authorization, KeycloakIdentity identity, AsyncResponse asyncResponse) {
|
||||||
return new DecisionResultCollector() {
|
return new DecisionResultCollector() {
|
||||||
@Override
|
@Override
|
||||||
protected void onComplete(List<Result> results) {
|
protected void onComplete(List<Result> results) {
|
||||||
try {
|
try {
|
||||||
asyncResponse.resume(Response.ok(PolicyEvaluationResponse.build(evaluationRequest, results, resourceServer, authorization, identity)).build());
|
asyncResponse.resume(Response.ok(PolicyEvaluationResponse.build(results, resourceServer, authorization, identity)).build());
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
asyncResponse.resume(cause);
|
asyncResponse.resume(cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,11 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.admin;
|
package org.keycloak.authorization.admin;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.admin.util.Models;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
@ -45,11 +41,10 @@ import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import javax.ws.rs.core.Response.Status;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.keycloak.authorization.admin.util.Models.toRepresentation;
|
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||||
|
import static org.keycloak.models.utils.RepresentationToModel.toModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -72,12 +67,7 @@ public class PolicyService {
|
||||||
@NoCache
|
@NoCache
|
||||||
public Response create(PolicyRepresentation representation) {
|
public Response create(PolicyRepresentation representation) {
|
||||||
this.auth.requireManage();
|
this.auth.requireManage();
|
||||||
Policy policy = Models.toModel(representation, this.resourceServer, authorization);
|
Policy policy = toModel(representation, this.resourceServer, authorization);
|
||||||
|
|
||||||
updateResources(policy, authorization);
|
|
||||||
updateAssociatedPolicies(policy);
|
|
||||||
updateScopes(policy, authorization);
|
|
||||||
|
|
||||||
PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
|
PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
|
||||||
|
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
@ -108,15 +98,7 @@ public class PolicyService {
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
policy.setName(representation.getName());
|
policy = toModel(representation, resourceServer, authorization);
|
||||||
policy.setDescription(representation.getDescription());
|
|
||||||
policy.setConfig(representation.getConfig());
|
|
||||||
policy.setDecisionStrategy(representation.getDecisionStrategy());
|
|
||||||
policy.setLogic(representation.getLogic());
|
|
||||||
|
|
||||||
updateResources(policy, authorization);
|
|
||||||
updateAssociatedPolicies(policy);
|
|
||||||
updateScopes(policy, authorization);
|
|
||||||
|
|
||||||
PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
|
PolicyProviderAdminService resource = getPolicyProviderAdminResource(policy.getType(), authorization);
|
||||||
|
|
||||||
|
@ -262,137 +244,4 @@ public class PolicyService {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScopes(Policy policy, AuthorizationProvider authorization) {
|
|
||||||
String scopes = policy.getConfig().get("scopes");
|
|
||||||
if (scopes != null) {
|
|
||||||
String[] scopeIds;
|
|
||||||
|
|
||||||
try {
|
|
||||||
scopeIds = new ObjectMapper().readValue(scopes, String[].class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
|
||||||
|
|
||||||
for (String scopeId : scopeIds) {
|
|
||||||
boolean hasScope = false;
|
|
||||||
|
|
||||||
for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
|
|
||||||
if (scopeModel.getId().equals(scopeId)) {
|
|
||||||
hasScope = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasScope) {
|
|
||||||
policy.addScope(storeFactory.getScopeStore().findById(scopeId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Scope scopeModel : new HashSet<Scope>(policy.getScopes())) {
|
|
||||||
boolean hasScope = false;
|
|
||||||
|
|
||||||
for (String scopeId : scopeIds) {
|
|
||||||
if (scopeModel.getId().equals(scopeId)) {
|
|
||||||
hasScope = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasScope) {
|
|
||||||
policy.removeScope(scopeModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAssociatedPolicies(Policy policy) {
|
|
||||||
String policies = policy.getConfig().get("applyPolicies");
|
|
||||||
|
|
||||||
if (policies != null) {
|
|
||||||
String[] policyIds;
|
|
||||||
|
|
||||||
try {
|
|
||||||
policyIds = new ObjectMapper().readValue(policies, String[].class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
|
|
||||||
for (String policyId : policyIds) {
|
|
||||||
boolean hasPolicy = false;
|
|
||||||
|
|
||||||
for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
|
|
||||||
if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
|
|
||||||
hasPolicy = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!hasPolicy) {
|
|
||||||
Policy associatedPolicy = policyStore.findById(policyId);
|
|
||||||
|
|
||||||
if (associatedPolicy == null) {
|
|
||||||
associatedPolicy = policyStore.findByName(policyId, this.resourceServer.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
policy.addAssociatedPolicy(associatedPolicy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Policy policyModel : new HashSet<Policy>(policy.getAssociatedPolicies())) {
|
|
||||||
boolean hasPolicy = false;
|
|
||||||
|
|
||||||
for (String policyId : policyIds) {
|
|
||||||
if (policyModel.getId().equals(policyId) || policyModel.getName().equals(policyId)) {
|
|
||||||
hasPolicy = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasPolicy) {
|
|
||||||
policy.removeAssociatedPolicy(policyModel);;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateResources(Policy policy, AuthorizationProvider authorization) {
|
|
||||||
String resources = policy.getConfig().get("resources");
|
|
||||||
if (resources != null) {
|
|
||||||
String[] resourceIds;
|
|
||||||
|
|
||||||
try {
|
|
||||||
resourceIds = new ObjectMapper().readValue(resources, String[].class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
|
||||||
|
|
||||||
for (String resourceId : resourceIds) {
|
|
||||||
boolean hasResource = false;
|
|
||||||
for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
|
|
||||||
if (resourceModel.getId().equals(resourceId)) {
|
|
||||||
hasResource = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasResource && !"".equals(resourceId)) {
|
|
||||||
policy.addResource(storeFactory.getResourceStore().findById(resourceId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Resource resourceModel : new HashSet<Resource>(policy.getResources())) {
|
|
||||||
boolean hasResource = false;
|
|
||||||
|
|
||||||
for (String resourceId : resourceIds) {
|
|
||||||
if (resourceModel.getId().equals(resourceId)) {
|
|
||||||
hasResource = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasResource) {
|
|
||||||
policy.removeResource(resourceModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,33 +19,25 @@ package org.keycloak.authorization.admin;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.admin.util.Models;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
import org.keycloak.authorization.store.ScopeStore;
|
import org.keycloak.authorization.store.ScopeStore;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.exportimport.util.ExportUtils;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserFederationManager;
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||||
import org.keycloak.representations.idm.authorization.Logic;
|
import org.keycloak.representations.idm.authorization.Logic;
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
|
||||||
import org.keycloak.services.resources.admin.RealmAuth;
|
import org.keycloak.services.resources.admin.RealmAuth;
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import javax.management.relation.Role;
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
|
@ -57,14 +49,9 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -73,7 +60,6 @@ public class ResourceServerService {
|
||||||
|
|
||||||
private final AuthorizationProvider authorization;
|
private final AuthorizationProvider authorization;
|
||||||
private final RealmAuth auth;
|
private final RealmAuth auth;
|
||||||
private final RealmModel realm;
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
private ResourceServer resourceServer;
|
private ResourceServer resourceServer;
|
||||||
private final ClientModel client;
|
private final ClientModel client;
|
||||||
|
@ -83,7 +69,6 @@ public class ResourceServerService {
|
||||||
this.session = authorization.getKeycloakSession();
|
this.session = authorization.getKeycloakSession();
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.resourceServer = resourceServer;
|
this.resourceServer = resourceServer;
|
||||||
this.realm = client.getRealm();
|
|
||||||
this.auth = auth;
|
this.auth = auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +113,7 @@ public class ResourceServerService {
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public Response findById() {
|
public Response findById() {
|
||||||
this.auth.requireView();
|
this.auth.requireView();
|
||||||
return Response.ok(Models.toRepresentation(this.resourceServer, this.realm)).build();
|
return Response.ok(toRepresentation(this.resourceServer, this.client)).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/settings")
|
@Path("/settings")
|
||||||
|
@ -136,59 +121,7 @@ public class ResourceServerService {
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public Response exportSettings() {
|
public Response exportSettings() {
|
||||||
this.auth.requireManage();
|
this.auth.requireManage();
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
return Response.ok(ExportUtils.exportAuthorizationSettings(session, client)).build();
|
||||||
ResourceServerRepresentation settings = Models.toRepresentation(resourceServer, this.realm);
|
|
||||||
|
|
||||||
settings.setId(null);
|
|
||||||
settings.setName(null);
|
|
||||||
settings.setClientId(null);
|
|
||||||
|
|
||||||
List<ResourceRepresentation> resources = storeFactory.getResourceStore().findByResourceServer(resourceServer.getId())
|
|
||||||
.stream().map(resource -> {
|
|
||||||
ResourceRepresentation rep = Models.toRepresentation(resource, resourceServer, authorization);
|
|
||||||
|
|
||||||
if (rep.getOwner().getId().equals(this.resourceServer.getClientId())) {
|
|
||||||
rep.setOwner(null);
|
|
||||||
} else {
|
|
||||||
rep.getOwner().setId(null);
|
|
||||||
}
|
|
||||||
rep.setId(null);
|
|
||||||
rep.setPolicies(null);
|
|
||||||
rep.getScopes().forEach(scopeRepresentation -> {
|
|
||||||
scopeRepresentation.setId(null);
|
|
||||||
scopeRepresentation.setIconUri(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return rep;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
settings.setResources(resources);
|
|
||||||
|
|
||||||
List<PolicyRepresentation> policies = new ArrayList<>();
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
|
|
||||||
policies.addAll(policyStore.findByResourceServer(resourceServer.getId())
|
|
||||||
.stream().filter(policy -> !policy.getType().equals("resource") && !policy.getType().equals("scope"))
|
|
||||||
.map(policy -> createPolicyRepresentation(storeFactory, policy)).collect(Collectors.toList()));
|
|
||||||
policies.addAll(policyStore.findByResourceServer(resourceServer.getId())
|
|
||||||
.stream().filter(policy -> policy.getType().equals("resource") || policy.getType().equals("scope"))
|
|
||||||
.map(policy -> createPolicyRepresentation(storeFactory, policy)).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
settings.setPolicies(policies);
|
|
||||||
|
|
||||||
List<ScopeRepresentation> scopes = storeFactory.getScopeStore().findByResourceServer(resourceServer.getId()).stream().map(scope -> {
|
|
||||||
ScopeRepresentation rep = Models.toRepresentation(scope, authorization);
|
|
||||||
|
|
||||||
rep.setId(null);
|
|
||||||
rep.setPolicies(null);
|
|
||||||
rep.setResources(null);
|
|
||||||
|
|
||||||
return rep;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
settings.setScopes(scopes);
|
|
||||||
|
|
||||||
return Response.ok(settings).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/import")
|
@Path("/import")
|
||||||
|
@ -197,172 +130,9 @@ public class ResourceServerService {
|
||||||
public Response importSettings(@Context final UriInfo uriInfo, ResourceServerRepresentation rep) throws IOException {
|
public Response importSettings(@Context final UriInfo uriInfo, ResourceServerRepresentation rep) throws IOException {
|
||||||
this.auth.requireManage();
|
this.auth.requireManage();
|
||||||
|
|
||||||
resourceServer.setPolicyEnforcementMode(rep.getPolicyEnforcementMode());
|
rep.setClientId(client.getId());
|
||||||
resourceServer.setAllowRemoteResourceManagement(rep.isAllowRemoteResourceManagement());
|
|
||||||
|
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
RepresentationToModel.toModel(rep, authorization);
|
||||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
|
||||||
ScopeStore scopeStore = storeFactory.getScopeStore();
|
|
||||||
ScopeService scopeResource = new ScopeService(resourceServer, this.authorization, this.auth);
|
|
||||||
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(scopeResource);
|
|
||||||
|
|
||||||
rep.getScopes().forEach(scope -> {
|
|
||||||
Scope existing = scopeStore.findByName(scope.getName(), resourceServer.getId());
|
|
||||||
|
|
||||||
if (existing != null) {
|
|
||||||
scopeResource.update(existing.getId(), scope);
|
|
||||||
} else {
|
|
||||||
scopeResource.create(scope);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ResourceSetService resourceSetResource = new ResourceSetService(resourceServer, this.authorization, this.auth);
|
|
||||||
|
|
||||||
rep.getResources().forEach(resourceRepresentation -> {
|
|
||||||
ResourceOwnerRepresentation owner = resourceRepresentation.getOwner();
|
|
||||||
|
|
||||||
if (owner == null) {
|
|
||||||
owner = new ResourceOwnerRepresentation();
|
|
||||||
}
|
|
||||||
|
|
||||||
owner.setId(resourceServer.getClientId());
|
|
||||||
|
|
||||||
if (owner.getName() != null) {
|
|
||||||
UserModel user = this.session.users().getUserByUsername(owner.getName(), this.realm);
|
|
||||||
|
|
||||||
if (user != null) {
|
|
||||||
owner.setId(user.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Resource existing = resourceStore.findByName(resourceRepresentation.getName(), this.resourceServer.getId());
|
|
||||||
|
|
||||||
if (existing != null) {
|
|
||||||
resourceSetResource.update(existing.getId(), resourceRepresentation);
|
|
||||||
} else {
|
|
||||||
resourceSetResource.create(resourceRepresentation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
PolicyService policyResource = new PolicyService(resourceServer, this.authorization, this.auth);
|
|
||||||
|
|
||||||
ResteasyProviderFactory.getInstance().injectProperties(policyResource);
|
|
||||||
|
|
||||||
rep.getPolicies().forEach(policyRepresentation -> {
|
|
||||||
Map<String, String> config = policyRepresentation.getConfig();
|
|
||||||
|
|
||||||
String roles = config.get("roles");
|
|
||||||
|
|
||||||
if (roles != null && !roles.isEmpty()) {
|
|
||||||
try {
|
|
||||||
List<Map> rolesMap = JsonSerialization.readValue(roles, List.class);
|
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleConfig -> {
|
|
||||||
String roleName = roleConfig.get("id").toString();
|
|
||||||
String clientId = null;
|
|
||||||
int clientIdSeparator = roleName.indexOf("/");
|
|
||||||
|
|
||||||
if (clientIdSeparator != -1) {
|
|
||||||
clientId = roleName.substring(0, clientIdSeparator);
|
|
||||||
roleName = roleName.substring(clientIdSeparator + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RoleModel role;
|
|
||||||
|
|
||||||
if (clientId == null) {
|
|
||||||
role = realm.getRole(roleName);
|
|
||||||
} else {
|
|
||||||
role = realm.getClientByClientId(clientId).getRole(roleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback to find any client role with the given name
|
|
||||||
if (role == null) {
|
|
||||||
String finalRoleName = roleName;
|
|
||||||
role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName)).filter(roleModel -> roleModel != null)
|
|
||||||
.findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (role == null) {
|
|
||||||
throw new RuntimeException("Error while importing configuration. Role [" + role + "] could not be found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
roleConfig.put("id", role.getId());
|
|
||||||
return roleConfig;
|
|
||||||
}).collect(Collectors.toList())));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String users = config.get("users");
|
|
||||||
|
|
||||||
if (users != null && !users.isEmpty()) {
|
|
||||||
try {
|
|
||||||
List<String> usersMap = JsonSerialization.readValue(users, List.class);
|
|
||||||
config.put("users", JsonSerialization.writeValueAsString(usersMap.stream().map(userName -> this.session.users().getUserByUsername(userName, this.realm).getId()).collect(Collectors.toList())));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String scopes = config.get("scopes");
|
|
||||||
|
|
||||||
if (scopes != null && !scopes.isEmpty()) {
|
|
||||||
try {
|
|
||||||
List<String> scopesMap = JsonSerialization.readValue(scopes, List.class);
|
|
||||||
config.put("scopes", JsonSerialization.writeValueAsString(scopesMap.stream().map(scopeName -> {
|
|
||||||
Scope newScope = scopeStore.findByName(scopeName, resourceServer.getId());
|
|
||||||
|
|
||||||
if (newScope == null) {
|
|
||||||
throw new RuntimeException("Scope with name [" + scopeName + "] not defined.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return newScope.getId();
|
|
||||||
}).collect(Collectors.toList())));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String policyResources = config.get("resources");
|
|
||||||
|
|
||||||
if (policyResources != null && !policyResources.isEmpty()) {
|
|
||||||
try {
|
|
||||||
List<String> resources = JsonSerialization.readValue(policyResources, List.class);
|
|
||||||
config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(resourceName -> storeFactory.getResourceStore().findByName(resourceName, resourceServer.getId()).getId()).collect(Collectors.toList())));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String applyPolicies = config.get("applyPolicies");
|
|
||||||
|
|
||||||
if (applyPolicies != null && !applyPolicies.isEmpty()) {
|
|
||||||
try {
|
|
||||||
List<String> policies = JsonSerialization.readValue(applyPolicies, List.class);
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(policies.stream().map(policyName -> {
|
|
||||||
Policy policy = policyStore.findByName(policyName, resourceServer.getId());
|
|
||||||
|
|
||||||
if (policy == null) {
|
|
||||||
throw new RuntimeException("Policy with name [" + policyName + "] not defined.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return policy.getId();
|
|
||||||
}).collect(Collectors.toList())));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Policy existing = policyStore.findByName(policyRepresentation.getName(), this.resourceServer.getId());
|
|
||||||
|
|
||||||
if (existing != null) {
|
|
||||||
policyResource.update(existing.getId(), policyRepresentation);
|
|
||||||
} else {
|
|
||||||
policyResource.create(policyRepresentation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
}
|
}
|
||||||
|
@ -458,61 +228,4 @@ public class ResourceServerService {
|
||||||
serviceAccount.grantRole(umaProtectionRole);
|
serviceAccount.grantRole(umaProtectionRole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PolicyRepresentation createPolicyRepresentation(StoreFactory storeFactory, Policy policy) {
|
|
||||||
try {
|
|
||||||
PolicyRepresentation rep = Models.toRepresentation(policy, authorization);
|
|
||||||
|
|
||||||
rep.setId(null);
|
|
||||||
rep.setDependentPolicies(null);
|
|
||||||
|
|
||||||
Map<String, String> config = rep.getConfig();
|
|
||||||
|
|
||||||
String roles = config.get("roles");
|
|
||||||
|
|
||||||
if (roles != null && !roles.isEmpty()) {
|
|
||||||
List<Map> rolesMap = JsonSerialization.readValue(roles, List.class);
|
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleMap -> {
|
|
||||||
roleMap.put("id", realm.getRoleById(roleMap.get("id").toString()).getName());
|
|
||||||
return roleMap;
|
|
||||||
}).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
String users = config.get("users");
|
|
||||||
|
|
||||||
if (users != null && !users.isEmpty()) {
|
|
||||||
UserFederationManager userManager = this.session.users();
|
|
||||||
List<String> userIds = JsonSerialization.readValue(users, List.class);
|
|
||||||
config.put("users", JsonSerialization.writeValueAsString(userIds.stream().map(userId -> userManager.getUserById(userId, this.realm).getUsername()).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
String scopes = config.get("scopes");
|
|
||||||
|
|
||||||
if (scopes != null && !scopes.isEmpty()) {
|
|
||||||
ScopeStore scopeStore = storeFactory.getScopeStore();
|
|
||||||
List<String> scopeIds = JsonSerialization.readValue(scopes, List.class);
|
|
||||||
config.put("scopes", JsonSerialization.writeValueAsString(scopeIds.stream().map(scopeId -> scopeStore.findById(scopeId).getName()).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
String policyResources = config.get("resources");
|
|
||||||
|
|
||||||
if (policyResources != null && !policyResources.isEmpty()) {
|
|
||||||
ResourceStore resourceStore = storeFactory.getResourceStore();
|
|
||||||
List<String> resourceIds = JsonSerialization.readValue(policyResources, List.class);
|
|
||||||
config.put("resources", JsonSerialization.writeValueAsString(resourceIds.stream().map(resourceId -> resourceStore.findById(resourceId).getName()).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
|
|
||||||
|
|
||||||
if (!associatedPolicies.isEmpty()) {
|
|
||||||
config.put("applyPolicies", JsonSerialization.writeValueAsString(associatedPolicies.stream().map(associated -> associated.getName()).collect(Collectors.toList())));
|
|
||||||
}
|
|
||||||
|
|
||||||
rep.setAssociatedPolicies(null);
|
|
||||||
|
|
||||||
return rep;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error while exporting policy [" + policy.getName() + "].", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ package org.keycloak.authorization.admin;
|
||||||
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.admin.util.Models;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.model.Resource;
|
import org.keycloak.authorization.model.Resource;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
@ -27,7 +26,6 @@ import org.keycloak.authorization.store.PolicyStore;
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
import org.keycloak.services.resources.admin.RealmAuth;
|
import org.keycloak.services.resources.admin.RealmAuth;
|
||||||
|
|
||||||
|
@ -45,7 +43,8 @@ import javax.ws.rs.core.Response.Status;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.keycloak.authorization.admin.util.Models.toRepresentation;
|
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||||
|
import static org.keycloak.models.utils.RepresentationToModel.toModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -75,7 +74,7 @@ public class ResourceSetService {
|
||||||
return ErrorResponse.exists("Resource with name [" + resource.getName() + "] already exists.");
|
return ErrorResponse.exists("Resource with name [" + resource.getName() + "] already exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource model = Models.toModel(resource, this.resourceServer, authorization);
|
Resource model = toModel(resource, this.resourceServer, authorization);
|
||||||
|
|
||||||
ResourceRepresentation representation = new ResourceRepresentation();
|
ResourceRepresentation representation = new ResourceRepresentation();
|
||||||
|
|
||||||
|
@ -99,14 +98,7 @@ public class ResourceSetService {
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
model.setName(resource.getName());
|
toModel(resource, resourceServer, authorization);
|
||||||
model.setType(resource.getType());
|
|
||||||
model.setUri(resource.getUri());
|
|
||||||
model.setIconUri(resource.getIconUri());
|
|
||||||
|
|
||||||
model.updateScopes(resource.getScopes().stream()
|
|
||||||
.map((ScopeRepresentation scope) -> Models.toModel(scope, this.resourceServer, authorization))
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
|
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,8 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.keycloak.authorization.admin.util.Models.toModel;
|
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||||
import static org.keycloak.authorization.admin.util.Models.toRepresentation;
|
import static org.keycloak.models.utils.RepresentationToModel.toModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -88,8 +88,7 @@ public class ScopeService {
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
model.setName(scope.getName());
|
toModel(scope, resourceServer, authorization);
|
||||||
model.setIconUri(scope.getIconUri());
|
|
||||||
|
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.keycloak.authorization.admin.representation;
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.Decision.Effect;
|
import org.keycloak.authorization.Decision.Effect;
|
||||||
import org.keycloak.authorization.admin.util.Models;
|
|
||||||
import org.keycloak.authorization.common.KeycloakIdentity;
|
import org.keycloak.authorization.common.KeycloakIdentity;
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
@ -28,6 +27,7 @@ import org.keycloak.authorization.model.Scope;
|
||||||
import org.keycloak.authorization.policy.evaluation.Result;
|
import org.keycloak.authorization.policy.evaluation.Result;
|
||||||
import org.keycloak.authorization.policy.evaluation.Result.PolicyResult;
|
import org.keycloak.authorization.policy.evaluation.Result.PolicyResult;
|
||||||
import org.keycloak.authorization.util.Permissions;
|
import org.keycloak.authorization.util.Permissions;
|
||||||
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
|
@ -56,7 +56,7 @@ public class PolicyEvaluationResponse {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PolicyEvaluationResponse build(PolicyEvaluationRequest evaluationRequest, List<Result> results, ResourceServer resourceServer, AuthorizationProvider authorization, KeycloakIdentity identity) {
|
public static PolicyEvaluationResponse build(List<Result> results, ResourceServer resourceServer, AuthorizationProvider authorization, KeycloakIdentity identity) {
|
||||||
PolicyEvaluationResponse response = new PolicyEvaluationResponse();
|
PolicyEvaluationResponse response = new PolicyEvaluationResponse();
|
||||||
List<EvaluationResultRepresentation> resultsRep = new ArrayList<>();
|
List<EvaluationResultRepresentation> resultsRep = new ArrayList<>();
|
||||||
AccessToken accessToken = identity.getAccessToken();
|
AccessToken accessToken = identity.getAccessToken();
|
||||||
|
@ -80,21 +80,16 @@ public class PolicyEvaluationResponse {
|
||||||
resultsRep.add(rep);
|
resultsRep.add(rep);
|
||||||
|
|
||||||
if (result.getPermission().getResource() != null) {
|
if (result.getPermission().getResource() != null) {
|
||||||
rep.setResource(Models.toRepresentation(result.getPermission().getResource(), resourceServer, authorization));
|
rep.setResource(ModelToRepresentation.toRepresentation(result.getPermission().getResource(), resourceServer, authorization));
|
||||||
} else {
|
} else {
|
||||||
ResourceRepresentation resource = new ResourceRepresentation();
|
ResourceRepresentation resource = new ResourceRepresentation();
|
||||||
|
|
||||||
resource.setName("Any Resource with Scopes " + result.getPermission().getScopes().stream().map(new Function<Scope, String>() {
|
resource.setName("Any Resource with Scopes " + result.getPermission().getScopes().stream().map(Scope::getName).collect(Collectors.toList()));
|
||||||
@Override
|
|
||||||
public String apply(Scope scope) {
|
|
||||||
return scope.getName();
|
|
||||||
}
|
|
||||||
}).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
rep.setResource(resource);
|
rep.setResource(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
rep.setScopes(result.getPermission().getScopes().stream().map(scope -> Models.toRepresentation(scope, authorization)).collect(Collectors.toList()));
|
rep.setScopes(result.getPermission().getScopes().stream().map(scope -> ModelToRepresentation.toRepresentation(scope, authorization)).collect(Collectors.toList()));
|
||||||
|
|
||||||
List<PolicyResultRepresentation> policies = new ArrayList<>();
|
List<PolicyResultRepresentation> policies = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -163,7 +158,7 @@ public class PolicyEvaluationResponse {
|
||||||
|
|
||||||
if (policy.getStatus().equals(Effect.DENY)) {
|
if (policy.getStatus().equals(Effect.DENY)) {
|
||||||
Policy policyModel = authorization.getStoreFactory().getPolicyStore().findById(policy.getPolicy().getId());
|
Policy policyModel = authorization.getStoreFactory().getPolicyStore().findById(policy.getPolicy().getId());
|
||||||
for (ScopeRepresentation scope : policyModel.getScopes().stream().map(scopeModel -> Models.toRepresentation(scopeModel, authorization)).collect(Collectors.toList())) {
|
for (ScopeRepresentation scope : policyModel.getScopes().stream().map(scopeModel -> ModelToRepresentation.toRepresentation(scopeModel, authorization)).collect(Collectors.toList())) {
|
||||||
if (!policy.getScopes().contains(scope)) {
|
if (!policy.getScopes().contains(scope)) {
|
||||||
policy.getScopes().add(scope);
|
policy.getScopes().add(scope);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +180,7 @@ public class PolicyEvaluationResponse {
|
||||||
private static PolicyResultRepresentation toRepresentation(PolicyResult policy, AuthorizationProvider authorization) {
|
private static PolicyResultRepresentation toRepresentation(PolicyResult policy, AuthorizationProvider authorization) {
|
||||||
PolicyResultRepresentation policyResultRep = new PolicyResultRepresentation();
|
PolicyResultRepresentation policyResultRep = new PolicyResultRepresentation();
|
||||||
|
|
||||||
policyResultRep.setPolicy(Models.toRepresentation(policy.getPolicy(), authorization));
|
policyResultRep.setPolicy(ModelToRepresentation.toRepresentation(policy.getPolicy(), authorization));
|
||||||
policyResultRep.setStatus(policy.getStatus());
|
policyResultRep.setStatus(policy.getStatus());
|
||||||
policyResultRep.setAssociatedPolicies(policy.getAssociatedPolicies().stream().map(result -> toRepresentation(result, authorization)).collect(Collectors.toList()));
|
policyResultRep.setAssociatedPolicies(policy.getAssociatedPolicies().stream().map(result -> toRepresentation(result, authorization)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
|
|
@ -1,321 +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.authorization.admin.util;
|
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
|
||||||
import org.keycloak.authorization.ErrorCode;
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.Resource;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
|
||||||
import org.keycloak.authorization.model.Scope;
|
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
|
||||||
import org.keycloak.authorization.store.ResourceServerStore;
|
|
||||||
import org.keycloak.authorization.store.ResourceStore;
|
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
|
||||||
import org.keycloak.services.ErrorResponseException;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some utility methods to transform models to representations and vice-versa.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
|
||||||
*/
|
|
||||||
public final class Models {
|
|
||||||
|
|
||||||
public static ScopeRepresentation toRepresentation(Scope model, AuthorizationProvider authorizationProvider) {
|
|
||||||
ScopeRepresentation scope = new ScopeRepresentation();
|
|
||||||
|
|
||||||
scope.setId(model.getId());
|
|
||||||
scope.setName(model.getName());
|
|
||||||
scope.setIconUri(model.getIconUri());
|
|
||||||
|
|
||||||
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
|
||||||
|
|
||||||
scope.setResources(new ArrayList<>());
|
|
||||||
|
|
||||||
storeFactory.getResourceStore().findByScope(model.getId()).forEach(resource -> scope.getResources().add(toRepresentation(resource, resource.getResourceServer(), authorizationProvider)));
|
|
||||||
|
|
||||||
PolicyStore policyStore = storeFactory.getPolicyStore();
|
|
||||||
|
|
||||||
scope.setPolicies(new ArrayList<>());
|
|
||||||
|
|
||||||
policyStore.findByScopeIds(Arrays.asList(model.getId()), model.getResourceServer().getId()).forEach(policyModel -> {
|
|
||||||
PolicyRepresentation policy = new PolicyRepresentation();
|
|
||||||
|
|
||||||
policy.setId(policyModel.getId());
|
|
||||||
policy.setName(policyModel.getName());
|
|
||||||
policy.setType(policyModel.getType());
|
|
||||||
|
|
||||||
if (!scope.getPolicies().contains(policy)) {
|
|
||||||
scope.getPolicies().add(policy);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Scope toModel(ScopeRepresentation scope, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
|
||||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
|
||||||
Scope model = storeFactory.getScopeStore().findByName(scope.getName(), resourceServer.getId());
|
|
||||||
|
|
||||||
if (model == null) {
|
|
||||||
model = storeFactory.getScopeStore().create(scope.getName(), resourceServer);
|
|
||||||
|
|
||||||
model.setIconUri(scope.getIconUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceServerRepresentation toRepresentation(ResourceServer model, RealmModel realm) {
|
|
||||||
ResourceServerRepresentation server = new ResourceServerRepresentation();
|
|
||||||
|
|
||||||
server.setId(model.getId());
|
|
||||||
server.setClientId(model.getClientId());
|
|
||||||
ClientModel clientById = realm.getClientById(model.getClientId());
|
|
||||||
server.setName(clientById.getClientId());
|
|
||||||
server.setAllowRemoteResourceManagement(model.isAllowRemoteResourceManagement());
|
|
||||||
server.setPolicyEnforcementMode(model.getPolicyEnforcementMode());
|
|
||||||
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceServer toModel(ResourceServerRepresentation server, AuthorizationProvider authorization) {
|
|
||||||
RealmModel realm = authorization.getKeycloakSession().getContext().getRealm();
|
|
||||||
ClientModel client = realm.getClientById(server.getClientId());
|
|
||||||
|
|
||||||
if (client == null) {
|
|
||||||
throw new ErrorResponseException(ErrorCode.INVALID_CLIENT_ID, "Client with id [" + server.getClientId() + "] not found in realm [" + realm.getName() + "].", Status.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!client.isServiceAccountsEnabled()) {
|
|
||||||
throw new ErrorResponseException(ErrorCode.INVALID_CLIENT_ID, "Client with id [" + server.getClientId() + "] must have a service account.", Status.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceServer existingResourceServer = authorization.getStoreFactory().getResourceServerStore().findByClient(client.getId());
|
|
||||||
|
|
||||||
if (existingResourceServer != null) {
|
|
||||||
throw new ErrorResponseException(ErrorCode.INVALID_CLIENT_ID, "Resource server already exists with client id [" + server.getClientId() + "].", Status.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.getName() == null) {
|
|
||||||
server.setName(client.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceServer model = authorization.getStoreFactory().getResourceServerStore().create(client.getId());
|
|
||||||
|
|
||||||
model.setAllowRemoteResourceManagement(server.isAllowRemoteResourceManagement());
|
|
||||||
model.setPolicyEnforcementMode(server.getPolicyEnforcementMode());
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PolicyRepresentation toRepresentation(Policy model, AuthorizationProvider authorization) {
|
|
||||||
PolicyRepresentation representation = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation.setId(model.getId());
|
|
||||||
representation.setName(model.getName());
|
|
||||||
representation.setDescription(model.getDescription());
|
|
||||||
representation.setType(model.getType());
|
|
||||||
representation.setDecisionStrategy(model.getDecisionStrategy());
|
|
||||||
representation.setLogic(model.getLogic());
|
|
||||||
representation.setConfig(new HashMap<>(model.getConfig()));
|
|
||||||
|
|
||||||
List<Policy> policies = authorization.getStoreFactory().getPolicyStore().findDependentPolicies(model.getId());
|
|
||||||
|
|
||||||
representation.setDependentPolicies(policies.stream().map(policy -> {
|
|
||||||
PolicyRepresentation representation1 = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation1.setId(policy.getId());
|
|
||||||
representation1.setName(policy.getName());
|
|
||||||
|
|
||||||
return representation1;
|
|
||||||
}).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
List<PolicyRepresentation> associatedPolicies = new ArrayList<>();
|
|
||||||
|
|
||||||
List<String> obj = model.getAssociatedPolicies().stream().map(policy -> {
|
|
||||||
PolicyRepresentation representation1 = new PolicyRepresentation();
|
|
||||||
|
|
||||||
representation1.setId(policy.getId());
|
|
||||||
representation1.setName(policy.getName());
|
|
||||||
representation1.setType(policy.getType());
|
|
||||||
|
|
||||||
associatedPolicies.add(representation1);
|
|
||||||
|
|
||||||
return policy.getId();
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
representation.setAssociatedPolicies(associatedPolicies);
|
|
||||||
|
|
||||||
try {
|
|
||||||
representation.getConfig().put("applyPolicies", JsonSerialization.writeValueAsString(obj));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return representation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Policy toModel(PolicyRepresentation policy, ResourceServer resourceServer, AuthorizationProvider authorizationManager) {
|
|
||||||
Policy model = authorizationManager.getStoreFactory().getPolicyStore().create(policy.getName(), policy.getType(), resourceServer);
|
|
||||||
|
|
||||||
model.setDescription(policy.getDescription());
|
|
||||||
model.setDecisionStrategy(policy.getDecisionStrategy());
|
|
||||||
model.setLogic(policy.getLogic());
|
|
||||||
model.setConfig(policy.getConfig());
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceRepresentation toRepresentation(Resource model, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
|
||||||
ResourceRepresentation resource = new ResourceRepresentation();
|
|
||||||
|
|
||||||
resource.setId(model.getId());
|
|
||||||
resource.setType(model.getType());
|
|
||||||
resource.setName(model.getName());
|
|
||||||
resource.setUri(model.getUri());
|
|
||||||
resource.setIconUri(model.getIconUri());
|
|
||||||
|
|
||||||
ResourceOwnerRepresentation owner = new ResourceOwnerRepresentation();
|
|
||||||
|
|
||||||
owner.setId(model.getOwner());
|
|
||||||
|
|
||||||
KeycloakSession keycloakSession = authorization.getKeycloakSession();
|
|
||||||
RealmModel realm = keycloakSession.getContext().getRealm();
|
|
||||||
|
|
||||||
if (owner.getId().equals(resourceServer.getClientId())) {
|
|
||||||
ClientModel clientModel = realm.getClientById(resourceServer.getClientId());
|
|
||||||
owner.setName(clientModel.getClientId());
|
|
||||||
} else {
|
|
||||||
UserModel userModel = keycloakSession.users().getUserById(owner.getId(), realm);
|
|
||||||
|
|
||||||
if (userModel == null) {
|
|
||||||
throw new ErrorResponseException("invalid_owner", "Could not find the user [" + owner.getId() + "] who owns the Resource [" + resource.getId() + "].", Status.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
owner.setName(userModel.getUsername());
|
|
||||||
}
|
|
||||||
|
|
||||||
resource.setOwner(owner);
|
|
||||||
|
|
||||||
resource.setScopes(model.getScopes().stream().map(model1 -> {
|
|
||||||
ScopeRepresentation scope = new ScopeRepresentation();
|
|
||||||
scope.setId(model1.getId());
|
|
||||||
scope.setName(model1.getName());
|
|
||||||
String iconUri = model1.getIconUri();
|
|
||||||
if (iconUri != null) {
|
|
||||||
scope.setIconUri(iconUri);
|
|
||||||
}
|
|
||||||
return scope;
|
|
||||||
}).collect(Collectors.toSet()));
|
|
||||||
|
|
||||||
resource.setTypedScopes(new ArrayList<>());
|
|
||||||
|
|
||||||
if (resource.getType() != null) {
|
|
||||||
ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
|
|
||||||
for (Resource typed : resourceStore.findByType(resource.getType())) {
|
|
||||||
if (typed.getOwner().equals(resourceServer.getClientId()) && !typed.getId().equals(resource.getId())) {
|
|
||||||
resource.setTypedScopes(typed.getScopes().stream().map(model1 -> {
|
|
||||||
ScopeRepresentation scope = new ScopeRepresentation();
|
|
||||||
scope.setId(model1.getId());
|
|
||||||
scope.setName(model1.getName());
|
|
||||||
String iconUri = model1.getIconUri();
|
|
||||||
if (iconUri != null) {
|
|
||||||
scope.setIconUri(iconUri);
|
|
||||||
}
|
|
||||||
return scope;
|
|
||||||
}).filter(scopeRepresentation -> !resource.getScopes().contains(scopeRepresentation)).collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource.setPolicies(new ArrayList<>());
|
|
||||||
|
|
||||||
Set<Policy> policies = new HashSet<>();
|
|
||||||
PolicyStore policyStore = authorization.getStoreFactory().getPolicyStore();
|
|
||||||
|
|
||||||
policies.addAll(policyStore.findByResource(resource.getId()));
|
|
||||||
policies.addAll(policyStore.findByResourceType(resource.getType(), resourceServer.getId()));
|
|
||||||
policies.addAll(policyStore.findByScopeIds(resource.getScopes().stream().map(scope -> scope.getId()).collect(Collectors.toList()), resourceServer.getId()));
|
|
||||||
|
|
||||||
for (Policy policyModel : policies) {
|
|
||||||
PolicyRepresentation policy = new PolicyRepresentation();
|
|
||||||
|
|
||||||
policy.setId(policyModel.getId());
|
|
||||||
policy.setName(policyModel.getName());
|
|
||||||
policy.setType(policyModel.getType());
|
|
||||||
|
|
||||||
if (!resource.getPolicies().contains(policy)) {
|
|
||||||
resource.getPolicies().add(policy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Resource toModel(ResourceRepresentation resource, ResourceServer resourceServer, AuthorizationProvider authorization) {
|
|
||||||
ResourceOwnerRepresentation owner = resource.getOwner();
|
|
||||||
|
|
||||||
if (owner == null) {
|
|
||||||
owner = new ResourceOwnerRepresentation();
|
|
||||||
owner.setId(resourceServer.getClientId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (owner.getId() == null) {
|
|
||||||
throw new ErrorResponseException("invalid_owner", "No owner specified for resource [" + resource.getName() + "].", Status.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceStore resourceStore = authorization.getStoreFactory().getResourceStore();
|
|
||||||
Resource model = resourceStore.create(resource.getName(), resourceServer, owner.getId());
|
|
||||||
|
|
||||||
model.setType(resource.getType());
|
|
||||||
model.setUri(resource.getUri());
|
|
||||||
model.setIconUri(resource.getIconUri());
|
|
||||||
|
|
||||||
Set<ScopeRepresentation> scopes = resource.getScopes();
|
|
||||||
|
|
||||||
if (scopes != null) {
|
|
||||||
model.updateScopes(scopes.stream().map((Function<ScopeRepresentation, Scope>) scope -> toModel(scope, resourceServer, authorization)).collect(Collectors.toSet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,12 +19,12 @@ package org.keycloak.authorization.protection.resource;
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.admin.ResourceSetService;
|
import org.keycloak.authorization.admin.ResourceSetService;
|
||||||
import org.keycloak.authorization.admin.util.Models;
|
|
||||||
import org.keycloak.authorization.identity.Identity;
|
import org.keycloak.authorization.identity.Identity;
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.protection.resource.representation.UmaResourceRepresentation;
|
import org.keycloak.authorization.protection.resource.representation.UmaResourceRepresentation;
|
||||||
import org.keycloak.authorization.protection.resource.representation.UmaScopeRepresentation;
|
import org.keycloak.authorization.protection.resource.representation.UmaScopeRepresentation;
|
||||||
import org.keycloak.authorization.store.StoreFactory;
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceOwnerRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
|
@ -133,25 +133,25 @@ public class ResourceService {
|
||||||
|
|
||||||
if ("name".equals(filterType)) {
|
if ("name".equals(filterType)) {
|
||||||
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getName())).collect(Collectors.toSet()).stream()
|
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getName())).collect(Collectors.toSet()).stream()
|
||||||
.map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
|
.map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
} else if ("type".equals(filterType)) {
|
} else if ("type".equals(filterType)) {
|
||||||
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getType())).collect(Collectors.toSet()).stream()
|
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getType())).collect(Collectors.toSet()).stream()
|
||||||
.map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
|
.map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
} else if ("uri".equals(filterType)) {
|
} else if ("uri".equals(filterType)) {
|
||||||
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getUri())).collect(Collectors.toSet()).stream()
|
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getUri())).collect(Collectors.toSet()).stream()
|
||||||
.map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
|
.map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
} else if ("owner".equals(filterType)) {
|
} else if ("owner".equals(filterType)) {
|
||||||
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getOwner())).collect(Collectors.toSet()).stream()
|
resources.addAll(storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream().filter(description -> filterValue == null || filterValue.equals(description.getOwner())).collect(Collectors.toSet()).stream()
|
||||||
.map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
|
.map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resources = storeFactory.getResourceStore().findByOwner(identity.getId()).stream()
|
resources = storeFactory.getResourceStore().findByOwner(identity.getId()).stream()
|
||||||
.map(resource -> Models.toRepresentation(resource, this.resourceServer, authorization))
|
.map(resource -> ModelToRepresentation.toRepresentation(resource, this.resourceServer, authorization))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,61 @@ import com.fasterxml.jackson.core.JsonFactory;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.AuthorizationProviderFactory;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceStore;
|
||||||
|
import org.keycloak.authorization.store.ScopeStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
import org.keycloak.common.Version;
|
import org.keycloak.common.Version;
|
||||||
import org.keycloak.common.util.Base64;
|
import org.keycloak.common.util.Base64;
|
||||||
import org.keycloak.common.util.MultivaluedHashMap;
|
import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.models.*;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientTemplateModel;
|
||||||
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.GroupModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleContainerModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserConsentModel;
|
||||||
|
import org.keycloak.models.UserCredentialValueModel;
|
||||||
|
import org.keycloak.models.UserFederationManager;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.representations.idm.*;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ClientTemplateRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ComponentExportRepresentation;
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RoleRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RolesRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserConsentRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -58,7 +102,7 @@ public class ExportUtils {
|
||||||
List<ClientModel> clients = realm.getClients();
|
List<ClientModel> clients = realm.getClients();
|
||||||
List<ClientRepresentation> clientReps = new ArrayList<>();
|
List<ClientRepresentation> clientReps = new ArrayList<>();
|
||||||
for (ClientModel app : clients) {
|
for (ClientModel app : clients) {
|
||||||
ClientRepresentation clientRep = exportClient(app);
|
ClientRepresentation clientRep = exportClient(session, app);
|
||||||
clientReps.add(clientRep);
|
clientReps.add(clientRep);
|
||||||
}
|
}
|
||||||
rep.setClients(clientReps);
|
rep.setClients(clientReps);
|
||||||
|
@ -207,12 +251,137 @@ public class ExportUtils {
|
||||||
* @param client
|
* @param client
|
||||||
* @return full ApplicationRepresentation
|
* @return full ApplicationRepresentation
|
||||||
*/
|
*/
|
||||||
public static ClientRepresentation exportClient(ClientModel client) {
|
public static ClientRepresentation exportClient(KeycloakSession session, ClientModel client) {
|
||||||
ClientRepresentation clientRep = ModelToRepresentation.toRepresentation(client);
|
ClientRepresentation clientRep = ModelToRepresentation.toRepresentation(client);
|
||||||
clientRep.setSecret(client.getSecret());
|
clientRep.setSecret(client.getSecret());
|
||||||
|
clientRep.setAuthorizationSettings(exportAuthorizationSettings(session,client));
|
||||||
return clientRep;
|
return clientRep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceServerRepresentation exportAuthorizationSettings(KeycloakSession session, ClientModel client) {
|
||||||
|
AuthorizationProviderFactory providerFactory = (AuthorizationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(AuthorizationProvider.class);
|
||||||
|
AuthorizationProvider authorization = providerFactory.create(session, client.getRealm());
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
ResourceServer settingsModel = authorization.getStoreFactory().getResourceServerStore().findByClient(client.getId());
|
||||||
|
|
||||||
|
if (settingsModel == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceServerRepresentation representation = toRepresentation(settingsModel, client);
|
||||||
|
|
||||||
|
representation.setId(null);
|
||||||
|
representation.setName(null);
|
||||||
|
representation.setClientId(null);
|
||||||
|
|
||||||
|
List<ResourceRepresentation> resources = storeFactory.getResourceStore().findByResourceServer(settingsModel.getId())
|
||||||
|
.stream().map(resource -> {
|
||||||
|
ResourceRepresentation rep = toRepresentation(resource, settingsModel, authorization);
|
||||||
|
|
||||||
|
if (rep.getOwner().getId().equals(settingsModel.getClientId())) {
|
||||||
|
rep.setOwner(null);
|
||||||
|
} else {
|
||||||
|
rep.getOwner().setId(null);
|
||||||
|
}
|
||||||
|
rep.setId(null);
|
||||||
|
rep.setPolicies(null);
|
||||||
|
rep.getScopes().forEach(scopeRepresentation -> {
|
||||||
|
scopeRepresentation.setId(null);
|
||||||
|
scopeRepresentation.setIconUri(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rep;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
representation.setResources(resources);
|
||||||
|
|
||||||
|
List<PolicyRepresentation> policies = new ArrayList<>();
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
|
|
||||||
|
policies.addAll(policyStore.findByResourceServer(settingsModel.getId())
|
||||||
|
.stream().filter(policy -> !policy.getType().equals("resource") && !policy.getType().equals("scope"))
|
||||||
|
.map(policy -> createPolicyRepresentation(authorization, policy)).collect(Collectors.toList()));
|
||||||
|
policies.addAll(policyStore.findByResourceServer(settingsModel.getId())
|
||||||
|
.stream().filter(policy -> policy.getType().equals("resource") || policy.getType().equals("scope"))
|
||||||
|
.map(policy -> createPolicyRepresentation(authorization, policy)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
representation.setPolicies(policies);
|
||||||
|
|
||||||
|
List<ScopeRepresentation> scopes = storeFactory.getScopeStore().findByResourceServer(settingsModel.getId()).stream().map(scope -> {
|
||||||
|
ScopeRepresentation rep = toRepresentation(scope, authorization);
|
||||||
|
|
||||||
|
rep.setId(null);
|
||||||
|
rep.setPolicies(null);
|
||||||
|
rep.setResources(null);
|
||||||
|
|
||||||
|
return rep;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
representation.setScopes(scopes);
|
||||||
|
|
||||||
|
return representation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PolicyRepresentation createPolicyRepresentation(AuthorizationProvider authorizationProvider, Policy policy) {
|
||||||
|
KeycloakSession session = authorizationProvider.getKeycloakSession();
|
||||||
|
RealmModel realm = authorizationProvider.getRealm();
|
||||||
|
StoreFactory storeFactory = authorizationProvider.getStoreFactory();
|
||||||
|
try {
|
||||||
|
PolicyRepresentation rep = toRepresentation(policy, authorizationProvider);
|
||||||
|
|
||||||
|
rep.setId(null);
|
||||||
|
rep.setDependentPolicies(null);
|
||||||
|
|
||||||
|
Map<String, String> config = rep.getConfig();
|
||||||
|
|
||||||
|
String roles = config.get("roles");
|
||||||
|
|
||||||
|
if (roles != null && !roles.isEmpty()) {
|
||||||
|
List<Map> rolesMap = JsonSerialization.readValue(roles, List.class);
|
||||||
|
config.put("roles", JsonSerialization.writeValueAsString(rolesMap.stream().map(roleMap -> {
|
||||||
|
roleMap.put("id", realm.getRoleById(roleMap.get("id").toString()).getName());
|
||||||
|
return roleMap;
|
||||||
|
}).collect(Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
String users = config.get("users");
|
||||||
|
|
||||||
|
if (users != null && !users.isEmpty()) {
|
||||||
|
UserFederationManager userManager = session.users();
|
||||||
|
List<String> userIds = JsonSerialization.readValue(users, List.class);
|
||||||
|
config.put("users", JsonSerialization.writeValueAsString(userIds.stream().map(userId -> userManager.getUserById(userId, realm).getUsername()).collect(Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
String scopes = config.get("scopes");
|
||||||
|
|
||||||
|
if (scopes != null && !scopes.isEmpty()) {
|
||||||
|
ScopeStore scopeStore = storeFactory.getScopeStore();
|
||||||
|
List<String> scopeIds = JsonSerialization.readValue(scopes, List.class);
|
||||||
|
config.put("scopes", JsonSerialization.writeValueAsString(scopeIds.stream().map(scopeId -> scopeStore.findById(scopeId).getName()).collect(Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
String policyResources = config.get("resources");
|
||||||
|
|
||||||
|
if (policyResources != null && !policyResources.isEmpty()) {
|
||||||
|
ResourceStore resourceStore = storeFactory.getResourceStore();
|
||||||
|
List<String> resourceIds = JsonSerialization.readValue(policyResources, List.class);
|
||||||
|
config.put("resources", JsonSerialization.writeValueAsString(resourceIds.stream().map(resourceId -> resourceStore.findById(resourceId).getName()).collect(Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
|
||||||
|
|
||||||
|
if (!associatedPolicies.isEmpty()) {
|
||||||
|
config.put("applyPolicies", JsonSerialization.writeValueAsString(associatedPolicies.stream().map(associated -> associated.getName()).collect(Collectors.toList())));
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.setAssociatedPolicies(null);
|
||||||
|
|
||||||
|
return rep;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error while exporting policy [" + policy.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
|
public static List<RoleRepresentation> exportRoles(Collection<RoleModel> roles) {
|
||||||
List<RoleRepresentation> roleReps = new ArrayList<RoleRepresentation>();
|
List<RoleRepresentation> roleReps = new ArrayList<RoleRepresentation>();
|
||||||
|
|
||||||
|
|
|
@ -733,7 +733,7 @@ public class AccountTest extends TestRealmKeycloakTest {
|
||||||
Assert.assertTrue(applicationsPage.isCurrent());
|
Assert.assertTrue(applicationsPage.isCurrent());
|
||||||
|
|
||||||
Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
|
Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
|
||||||
Assert.assertEquals(3, apps.size());
|
Assert.assertEquals(4, apps.size());
|
||||||
|
|
||||||
AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
|
AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
|
||||||
Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
|
Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
|
||||||
|
|
|
@ -21,12 +21,16 @@ import org.jboss.arquillian.container.test.api.Deployment;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||||
import org.junit.Test;
|
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.ClientsResource;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -67,6 +71,21 @@ public abstract class AbstractDefaultAuthzConfigAdapterTest extends AbstractExam
|
||||||
|
|
||||||
assertTrue(this.driver.getPageSource().contains("Your permissions are"));
|
assertTrue(this.driver.getPageSource().contains("Your permissions are"));
|
||||||
assertTrue(this.driver.getPageSource().contains("Default Resource"));
|
assertTrue(this.driver.getPageSource().contains("Default Resource"));
|
||||||
|
|
||||||
|
boolean hasDefaultPermission = false;
|
||||||
|
boolean hasDefaultPolicy = false;
|
||||||
|
|
||||||
|
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
|
||||||
|
if ("Default Policy".equals(policy.getName())) {
|
||||||
|
hasDefaultPolicy = true;
|
||||||
|
}
|
||||||
|
if ("Default Permission".equals(policy.getName())) {
|
||||||
|
hasDefaultPermission = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(hasDefaultPermission);
|
||||||
|
assertTrue(hasDefaultPolicy);
|
||||||
} finally {
|
} finally {
|
||||||
this.deployer.undeploy(RESOURCE_SERVER_ID);
|
this.deployer.undeploy(RESOURCE_SERVER_ID);
|
||||||
}
|
}
|
||||||
|
@ -95,4 +114,14 @@ public abstract class AbstractDefaultAuthzConfigAdapterTest extends AbstractExam
|
||||||
// enable authorization services in order to generate the default config and continue with tests
|
// enable authorization services in order to generate the default config and continue with tests
|
||||||
clients.get(client.getId()).update(client);
|
clients.get(client.getId()).update(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AuthorizationResource getAuthorizationResource() throws FileNotFoundException {
|
||||||
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.keycloak.testsuite.admin;
|
package org.keycloak.testsuite.admin;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.admin.client.resource.RoleResource;
|
import org.keycloak.admin.client.resource.RoleResource;
|
||||||
|
@ -192,4 +193,13 @@ public class ApiUtil {
|
||||||
}
|
}
|
||||||
return contains;
|
return contains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AuthorizationResource findAuthorizationSettings(RealmResource realm, String clientId) {
|
||||||
|
for (ClientRepresentation c : realm.clients().findAll()) {
|
||||||
|
if (c.getClientId().equals(clientId)) {
|
||||||
|
return realm.clients().get(c.getId()).authorization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -814,7 +814,7 @@ public class UserTest extends AbstractAdminTest {
|
||||||
|
|
||||||
// List realm roles
|
// List realm roles
|
||||||
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite", "user", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION);
|
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite", "user", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION);
|
||||||
assertNames(roles.realmLevel().listAvailable(), "admin");
|
assertNames(roles.realmLevel().listAvailable(), "admin", "customer-user-premium");
|
||||||
assertNames(roles.realmLevel().listEffective(), "realm-role", "realm-composite", "realm-child", "user", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION);
|
assertNames(roles.realmLevel().listEffective(), "realm-role", "realm-composite", "realm-child", "user", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION);
|
||||||
|
|
||||||
// List client roles
|
// List client roles
|
||||||
|
|
|
@ -432,7 +432,7 @@ public class GroupTest extends AbstractGroupTest {
|
||||||
|
|
||||||
// List realm roles
|
// List realm roles
|
||||||
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite");
|
assertNames(roles.realmLevel().listAll(), "realm-role", "realm-composite");
|
||||||
assertNames(roles.realmLevel().listAvailable(), "admin", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION, "user");
|
assertNames(roles.realmLevel().listAvailable(), "admin", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION, "user", "customer-user-premium");
|
||||||
assertNames(roles.realmLevel().listEffective(), "realm-role", "realm-composite", "realm-child");
|
assertNames(roles.realmLevel().listEffective(), "realm-role", "realm-composite", "realm-child");
|
||||||
|
|
||||||
// List client roles
|
// List client roles
|
||||||
|
|
|
@ -17,14 +17,18 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.exportimport;
|
package org.keycloak.testsuite.exportimport;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
|
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.admin.client.resource.ClientTemplateResource;
|
import org.keycloak.admin.client.resource.ClientTemplateResource;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
|
@ -50,6 +54,10 @@ import org.keycloak.representations.idm.RoleRepresentation;
|
||||||
import org.keycloak.representations.idm.UserFederationMapperRepresentation;
|
import org.keycloak.representations.idm.UserFederationMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
import org.keycloak.representations.idm.UserFederationProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||||
|
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||||
import org.keycloak.testsuite.admin.ApiUtil;
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
import org.keycloak.testsuite.client.KeycloakTestingClient;
|
import org.keycloak.testsuite.client.KeycloakTestingClient;
|
||||||
import org.keycloak.testsuite.util.RealmRepUtil;
|
import org.keycloak.testsuite.util.RealmRepUtil;
|
||||||
|
@ -86,7 +94,7 @@ public class ExportImportUtil {
|
||||||
Assert.assertEquals(0, userRsc.getFederatedIdentity().size());
|
Assert.assertEquals(0, userRsc.getFederatedIdentity().size());
|
||||||
|
|
||||||
List<ClientRepresentation> resources = realmRsc.clients().findAll();
|
List<ClientRepresentation> resources = realmRsc.clients().findAll();
|
||||||
Assert.assertEquals(8, resources.size());
|
Assert.assertEquals(9, resources.size());
|
||||||
|
|
||||||
// Test applications imported
|
// Test applications imported
|
||||||
ClientRepresentation application = ApiUtil.findClientByClientId(realmRsc, "Application").toRepresentation();
|
ClientRepresentation application = ApiUtil.findClientByClientId(realmRsc, "Application").toRepresentation();
|
||||||
|
@ -97,7 +105,7 @@ public class ExportImportUtil {
|
||||||
Assert.assertNotNull(otherApp);
|
Assert.assertNotNull(otherApp);
|
||||||
Assert.assertNull(nonExisting);
|
Assert.assertNull(nonExisting);
|
||||||
List<ClientRepresentation> clients = realmRsc.clients().findAll();
|
List<ClientRepresentation> clients = realmRsc.clients().findAll();
|
||||||
Assert.assertEquals(8, clients.size());
|
Assert.assertEquals(9, clients.size());
|
||||||
Assert.assertTrue(hasClient(clients, application));
|
Assert.assertTrue(hasClient(clients, application));
|
||||||
Assert.assertTrue(hasClient(clients, otherApp));
|
Assert.assertTrue(hasClient(clients, otherApp));
|
||||||
Assert.assertTrue(hasClient(clients, accountApp));
|
Assert.assertTrue(hasClient(clients, accountApp));
|
||||||
|
@ -366,6 +374,8 @@ public class ExportImportUtil {
|
||||||
UserRepresentation linked = testingClient.testing().getUserByServiceAccountClient(realm.getRealm(), otherApp.getClientId());//session.users().getUserByServiceAccountClient(otherApp);
|
UserRepresentation linked = testingClient.testing().getUserByServiceAccountClient(realm.getRealm(), otherApp.getClientId());//session.users().getUserByServiceAccountClient(otherApp);
|
||||||
Assert.assertNotNull(linked);
|
Assert.assertNotNull(linked);
|
||||||
Assert.assertEquals("my-service-user", linked.getUsername());
|
Assert.assertEquals("my-service-user", linked.getUsername());
|
||||||
|
|
||||||
|
assertAuthorizationSettings(realmRsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isProtocolMapperGranted(Map<String, Object> consent, ProtocolMapperRepresentation mapperRep) {
|
private static boolean isProtocolMapperGranted(Map<String, Object> consent, ProtocolMapperRepresentation mapperRep) {
|
||||||
|
@ -544,4 +554,89 @@ public class ExportImportUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void assertAuthorizationSettings(RealmResource realmRsc) {
|
||||||
|
AuthorizationResource authzResource = ApiUtil.findAuthorizationSettings(realmRsc, "test-app-authz");
|
||||||
|
|
||||||
|
Assert.assertNotNull(authzResource);
|
||||||
|
|
||||||
|
List<ResourceRepresentation> resources = authzResource.resources().resources();
|
||||||
|
Assert.assertEquals(4, resources.size());
|
||||||
|
ResourceServerRepresentation authzSettings = authzResource.getSettings();
|
||||||
|
List<Predicate<ResourceRepresentation>> resourcePredicates = new ArrayList<>();
|
||||||
|
resourcePredicates.add(resourceRep -> {
|
||||||
|
if ("Admin Resource".equals(resourceRep.getName())) {
|
||||||
|
Assert.assertEquals(authzSettings.getClientId(), resourceRep.getOwner().getId());
|
||||||
|
Assert.assertEquals("/protected/admin/*", resourceRep.getUri());
|
||||||
|
Assert.assertEquals("http://test-app-authz/protected/admin", resourceRep.getType());
|
||||||
|
Assert.assertEquals("http://icons.com/icon-admin", resourceRep.getIconUri());
|
||||||
|
Assert.assertEquals(1, resourceRep.getScopes().size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
resourcePredicates.add(resourceRep -> {
|
||||||
|
if ("Protected Resource".equals(resourceRep.getName())) {
|
||||||
|
Assert.assertEquals(authzSettings.getClientId(), resourceRep.getOwner().getId());
|
||||||
|
Assert.assertEquals("/*", resourceRep.getUri());
|
||||||
|
Assert.assertEquals("http://test-app-authz/protected/resource", resourceRep.getType());
|
||||||
|
Assert.assertEquals("http://icons.com/icon-resource", resourceRep.getIconUri());
|
||||||
|
Assert.assertEquals(1, resourceRep.getScopes().size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
resourcePredicates.add(resourceRep -> {
|
||||||
|
if ("Premium Resource".equals(resourceRep.getName())) {
|
||||||
|
Assert.assertEquals(authzSettings.getClientId(), resourceRep.getOwner().getId());
|
||||||
|
Assert.assertEquals("/protected/premium/*", resourceRep.getUri());
|
||||||
|
Assert.assertEquals("urn:test-app-authz:protected:resource", resourceRep.getType());
|
||||||
|
Assert.assertEquals("http://icons.com/icon-premium", resourceRep.getIconUri());
|
||||||
|
Assert.assertEquals(1, resourceRep.getScopes().size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
resourcePredicates.add(resourceRep -> {
|
||||||
|
if ("Main Page".equals(resourceRep.getName())) {
|
||||||
|
Assert.assertEquals(authzSettings.getClientId(), resourceRep.getOwner().getId());
|
||||||
|
Assert.assertNull(resourceRep.getUri());
|
||||||
|
Assert.assertEquals("urn:test-app-authz:protected:resource", resourceRep.getType());
|
||||||
|
Assert.assertEquals("http://icons.com/icon-main-page", resourceRep.getIconUri());
|
||||||
|
Assert.assertEquals(3, resourceRep.getScopes().size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
assertPredicate(resources, resourcePredicates);
|
||||||
|
|
||||||
|
List<ScopeRepresentation> scopes = authzResource.scopes().scopes();
|
||||||
|
Assert.assertEquals(6, scopes.size());
|
||||||
|
List<Predicate<ScopeRepresentation>> scopePredicates = new ArrayList<>();
|
||||||
|
scopePredicates.add(scopeRepresentation -> "admin-access".equals(scopeRepresentation.getName()));
|
||||||
|
scopePredicates.add(scopeRepresentation -> "resource-access".equals(scopeRepresentation.getName()));
|
||||||
|
scopePredicates.add(scopeRepresentation -> "premium-access".equals(scopeRepresentation.getName()));
|
||||||
|
scopePredicates.add(scopeRepresentation -> "urn:test-app-authz:page:main:actionForAdmin".equals(scopeRepresentation.getName()));
|
||||||
|
scopePredicates.add(scopeRepresentation -> "urn:test-app-authz:page:main:actionForUser".equals(scopeRepresentation.getName()));
|
||||||
|
scopePredicates.add(scopeRepresentation -> "urn:test-app-authz:page:main:actionForPremiumUser".equals(scopeRepresentation.getName()));
|
||||||
|
assertPredicate(scopes, scopePredicates);
|
||||||
|
|
||||||
|
List<PolicyRepresentation> policies = authzResource.policies().policies();
|
||||||
|
Assert.assertEquals(10, policies.size());
|
||||||
|
List<Predicate<PolicyRepresentation>> policyPredicates = new ArrayList<>();
|
||||||
|
policyPredicates.add(policyRepresentation -> "Any Admin Policy".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Any User Policy".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Only Premium User Policy".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "All Users Policy".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Premium Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Administrative Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Protected Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Action 1 on Main Page Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Action 2 on Main Page Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
policyPredicates.add(policyRepresentation -> "Action 3 on Main Page Resource Permission".equals(policyRepresentation.getName()));
|
||||||
|
assertPredicate(policies, policyPredicates);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <D> void assertPredicate(List<D> source, List<Predicate<D>> predicate) {
|
||||||
|
Assert.assertTrue(!source.stream().filter(object -> !predicate.stream().filter(predicate1 -> predicate1.test(object)).findFirst().isPresent()).findAny().isPresent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,168 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientId": "test-app-authz",
|
||||||
|
"enabled": true,
|
||||||
|
"baseUrl": "/test-app-authz",
|
||||||
|
"adminUrl": "/test-app-authz",
|
||||||
|
"bearerOnly": false,
|
||||||
|
"authorizationSettings": {
|
||||||
|
"allowRemoteResourceManagement": true,
|
||||||
|
"policyEnforcementMode": "ENFORCING",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "Admin Resource",
|
||||||
|
"uri": "/protected/admin/*",
|
||||||
|
"type": "http://test-app-authz/protected/admin",
|
||||||
|
"icon_uri" : "http://icons.com/icon-admin",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "admin-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protected Resource",
|
||||||
|
"uri": "/*",
|
||||||
|
"type": "http://test-app-authz/protected/resource",
|
||||||
|
"icon_uri" : "http://icons.com/icon-resource",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "resource-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Premium Resource",
|
||||||
|
"uri": "/protected/premium/*",
|
||||||
|
"type": "urn:test-app-authz:protected:resource",
|
||||||
|
"icon_uri" : "http://icons.com/icon-premium",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "premium-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Main Page",
|
||||||
|
"type": "urn:test-app-authz:protected:resource",
|
||||||
|
"icon_uri" : "http://icons.com/icon-main-page",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForAdmin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForUser"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForPremiumUser"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"policies": [
|
||||||
|
{
|
||||||
|
"name": "Any Admin Policy",
|
||||||
|
"description": "Defines that adminsitrators can do something",
|
||||||
|
"type": "role",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"admin\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Any User Policy",
|
||||||
|
"description": "Defines that any user can do something",
|
||||||
|
"type": "role",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"user\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Only Premium User Policy",
|
||||||
|
"description": "Defines that only premium users can do something",
|
||||||
|
"type": "role",
|
||||||
|
"logic": "POSITIVE",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"customer-user-premium\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "All Users Policy",
|
||||||
|
"description": "Defines that all users can do something",
|
||||||
|
"type": "aggregate",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"applyPolicies": "[\"Any User Policy\",\"Any Admin Policy\",\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Premium Resource Permission",
|
||||||
|
"description": "A policy that defines access to premium resources",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "UNANIMOUS",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Premium Resource\"]",
|
||||||
|
"applyPolicies": "[\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Administrative Resource Permission",
|
||||||
|
"description": "A policy that defines access to administrative resources",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "UNANIMOUS",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Admin Resource\"]",
|
||||||
|
"applyPolicies": "[\"Any Admin Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protected Resource Permission",
|
||||||
|
"description": "A policy that defines access to any protected resource",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Protected Resource\"]",
|
||||||
|
"applyPolicies": "[\"All Users Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 1 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 1 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForAdmin\"]",
|
||||||
|
"applyPolicies": "[\"Any Admin Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 2 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 2 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForUser\"]",
|
||||||
|
"applyPolicies": "[\"Any User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 3 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 3 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForPremiumUser\"]",
|
||||||
|
"applyPolicies": "[\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirectUris": [
|
||||||
|
"/test-app-authz/*"
|
||||||
|
],
|
||||||
|
"secret": "secret"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"oauthClients" : [
|
"oauthClients" : [
|
||||||
|
@ -239,6 +401,13 @@
|
||||||
"realm" : [
|
"realm" : [
|
||||||
{
|
{
|
||||||
"name": "admin"
|
"name": "admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "customer-user-premium",
|
||||||
|
"description": "Have User Premium privileges"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"application" : {
|
"application" : {
|
||||||
|
|
|
@ -117,6 +117,164 @@
|
||||||
"http://localhost:8180/auth/realms/master/app/*"
|
"http://localhost:8180/auth/realms/master/app/*"
|
||||||
],
|
],
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clientId": "test-app-authz",
|
||||||
|
"enabled": true,
|
||||||
|
"baseUrl": "/test-app-authz",
|
||||||
|
"adminUrl": "/test-app-authz",
|
||||||
|
"bearerOnly": false,
|
||||||
|
"authorizationSettings": {
|
||||||
|
"allowRemoteResourceManagement": true,
|
||||||
|
"policyEnforcementMode": "ENFORCING",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "Admin Resource",
|
||||||
|
"uri": "/protected/admin/*",
|
||||||
|
"type": "http://test-app-authz/protected/admin",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "admin-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protected Resource",
|
||||||
|
"uri": "/*",
|
||||||
|
"type": "http://test-app-authz/protected/resource",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "resource-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Premium Resource",
|
||||||
|
"uri": "/protected/premium/*",
|
||||||
|
"type": "urn:test-app-authz:protected:resource",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "premium-access"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Main Page",
|
||||||
|
"type": "urn:test-app-authz:protected:resource",
|
||||||
|
"scopes": [
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForAdmin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForUser"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "urn:test-app-authz:page:main:actionForPremiumUser"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"policies": [
|
||||||
|
{
|
||||||
|
"name": "Any Admin Policy",
|
||||||
|
"description": "Defines that adminsitrators can do something",
|
||||||
|
"type": "role",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"admin\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Any User Policy",
|
||||||
|
"description": "Defines that any user can do something",
|
||||||
|
"type": "role",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"user\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Only Premium User Policy",
|
||||||
|
"description": "Defines that only premium users can do something",
|
||||||
|
"type": "role",
|
||||||
|
"logic": "POSITIVE",
|
||||||
|
"config": {
|
||||||
|
"roles": "[{\"id\":\"customer-user-premium\"}]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "All Users Policy",
|
||||||
|
"description": "Defines that all users can do something",
|
||||||
|
"type": "aggregate",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"applyPolicies": "[\"Any User Policy\",\"Any Admin Policy\",\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Premium Resource Permission",
|
||||||
|
"description": "A policy that defines access to premium resources",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "UNANIMOUS",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Premium Resource\"]",
|
||||||
|
"applyPolicies": "[\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Administrative Resource Permission",
|
||||||
|
"description": "A policy that defines access to administrative resources",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "UNANIMOUS",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Admin Resource\"]",
|
||||||
|
"applyPolicies": "[\"Any Admin Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Protected Resource Permission",
|
||||||
|
"description": "A policy that defines access to any protected resource",
|
||||||
|
"type": "resource",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"resources": "[\"Protected Resource\"]",
|
||||||
|
"applyPolicies": "[\"All Users Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 1 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 1 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForAdmin\"]",
|
||||||
|
"applyPolicies": "[\"Any Admin Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 2 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 2 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForUser\"]",
|
||||||
|
"applyPolicies": "[\"Any User Policy\"]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Action 3 on Main Page Resource Permission",
|
||||||
|
"description": "A policy that defines access to action 3 on the main page",
|
||||||
|
"type": "scope",
|
||||||
|
"decisionStrategy": "AFFIRMATIVE",
|
||||||
|
"config": {
|
||||||
|
"scopes": "[\"urn:test-app-authz:page:main:actionForPremiumUser\"]",
|
||||||
|
"applyPolicies": "[\"Only Premium User Policy\"]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"redirectUris": [
|
||||||
|
"/test-app-authz/*"
|
||||||
|
],
|
||||||
|
"secret": "secret"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"roles" : {
|
"roles" : {
|
||||||
|
@ -128,6 +286,10 @@
|
||||||
{
|
{
|
||||||
"name": "admin",
|
"name": "admin",
|
||||||
"description": "Have Administrator privileges"
|
"description": "Have Administrator privileges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "customer-user-premium",
|
||||||
|
"description": "Have User Premium privileges"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"client" : {
|
"client" : {
|
||||||
|
|
Loading…
Reference in a new issue