[KEYCLOAK-2753] - Fine-grained Authorization Services

This commit is contained in:
Pedro Igor committed 2016-06-17 02:07:34 -03:00
1 parent 443772d5ec
commit 086c29112a
387 files changed
+27499 -96

No files matched your search

+5
View File
@@ -31,6 +31,11 @@
<name>Keycloak Model Mongo</name>
<description/>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
@@ -0,0 +1,168 @@
package org.keycloak.authorization.mongo.adapter;
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.mongo.entities.PolicyEntity;
import org.keycloak.authorization.mongo.entities.ResourceEntity;
import org.keycloak.authorization.mongo.entities.ScopeEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.adapters.AbstractMongoAdapter;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static javafx.scene.input.KeyCode.R;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class PolicyAdapter extends AbstractMongoAdapter<PolicyEntity> implements Policy {
private final PolicyEntity entity;
private final AuthorizationProvider authorizationProvider;
public PolicyAdapter(PolicyEntity entity, MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
super(invocationContext);
this.entity = entity;
this.authorizationProvider = authorizationProvider;
}
@Override
protected PolicyEntity getMongoEntity() {
return entity;
}
@Override
public String getId() {
return getMongoEntity().getId();
}
@Override
public String getType() {
return getMongoEntity().getType();
}
@Override
public DecisionStrategy getDecisionStrategy() {
return getMongoEntity().getDecisionStrategy();
}
@Override
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
getMongoEntity().setDecisionStrategy(decisionStrategy);
updateMongoEntity();
}
@Override
public Logic getLogic() {
return getMongoEntity().getLogic();
}
@Override
public void setLogic(Logic logic) {
getMongoEntity().setLogic(logic);
updateMongoEntity();
}
@Override
public Map<String, String> getConfig() {
return getMongoEntity().getConfig();
}
@Override
public void setConfig(Map<String, String> config) {
getMongoEntity().setConfig(config);
updateMongoEntity();
}
@Override
public String getName() {
return getMongoEntity().getName();
}
@Override
public void setName(String name) {
getMongoEntity().setName(name);
updateMongoEntity();
}
@Override
public String getDescription() {
return getMongoEntity().getDescription();
}
@Override
public void setDescription(String description) {
getMongoEntity().setDescription(description);
updateMongoEntity();
}
@Override
public ResourceServer getResourceServer() {
return this.authorizationProvider.getStoreFactory().getResourceServerStore().findById(getMongoEntity().getResourceServerId());
}
@Override
public Set<Policy> getAssociatedPolicies() {
return getMongoEntity().getAssociatedPolicies().stream()
.map((Function<String, Policy>) id -> authorizationProvider.getStoreFactory().getPolicyStore().findById(id))
.collect(Collectors.toSet());
}
@Override
public Set<Resource> getResources() {
return getMongoEntity().getResources().stream()
.map((Function<String, Resource>) id -> authorizationProvider.getStoreFactory().getResourceStore().findById(id))
.collect(Collectors.toSet());
}
@Override
public Set<Scope> getScopes() {
return getMongoEntity().getScopes().stream()
.map((Function<String, Scope>) id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id))
.collect(Collectors.toSet());
}
@Override
public void addScope(Scope scope) {
getMongoEntity().addScope(scope.getId());
updateMongoEntity();
}
@Override
public void removeScope(Scope scope) {
getMongoEntity().removeScope(scope.getId());
updateMongoEntity();
}
@Override
public void addAssociatedPolicy(Policy associatedPolicy) {
getMongoEntity().addAssociatedPolicy(associatedPolicy.getId());
updateMongoEntity();
}
@Override
public void removeAssociatedPolicy(Policy associatedPolicy) {
getMongoEntity().removeAssociatedPolicy(associatedPolicy.getId());
updateMongoEntity();
}
@Override
public void addResource(Resource resource) {
getMongoEntity().addResource(resource.getId());
updateMongoEntity();
}
@Override
public void removeResource(Resource resource) {
getMongoEntity().removeResource(resource.getId());
updateMongoEntity();
}
}
@@ -0,0 +1,106 @@
package org.keycloak.authorization.mongo.adapter;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.mongo.entities.ResourceEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.adapters.AbstractMongoAdapter;
import java.util.List;
import java.util.Set;
import static java.util.stream.Collectors.toList;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ResourceAdapter extends AbstractMongoAdapter<ResourceEntity> implements Resource {
private final ResourceEntity entity;
private final AuthorizationProvider authorizationProvider;
public ResourceAdapter(ResourceEntity entity, MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
super(invocationContext);
this.entity = entity;
this.authorizationProvider = authorizationProvider;
}
@Override
public String getId() {
return getMongoEntity().getId();
}
@Override
public String getName() {
return getMongoEntity().getName();
}
@Override
public void setName(String name) {
getMongoEntity().setName(name);
updateMongoEntity();
}
@Override
public String getUri() {
return getMongoEntity().getUri();
}
@Override
public void setUri(String uri) {
getMongoEntity().setUri(uri);
updateMongoEntity();
}
@Override
public String getType() {
return getMongoEntity().getType();
}
@Override
public void setType(String type) {
getMongoEntity().setType(type);
updateMongoEntity();
}
@Override
public List<Scope> getScopes() {
return getMongoEntity().getScopes().stream()
.map(id -> authorizationProvider.getStoreFactory().getScopeStore().findById(id))
.collect(toList());
}
@Override
public String getIconUri() {
return getMongoEntity().getIconUri();
}
@Override
public void setIconUri(String iconUri) {
getMongoEntity().setIconUri(iconUri);
updateMongoEntity();
}
@Override
public ResourceServer getResourceServer() {
return this.authorizationProvider.getStoreFactory().getResourceServerStore().findById(getMongoEntity().getResourceServerId());
}
@Override
public String getOwner() {
return getMongoEntity().getOwner();
}
@Override
public void updateScopes(Set<Scope> scopes) {
getMongoEntity().updateScopes(scopes);
updateMongoEntity();
}
@Override
protected ResourceEntity getMongoEntity() {
return this.entity;
}
}
@@ -0,0 +1,56 @@
package org.keycloak.authorization.mongo.adapter;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.mongo.entities.ResourceServerEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.adapters.AbstractMongoAdapter;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ResourceServerAdapter extends AbstractMongoAdapter<ResourceServerEntity> implements ResourceServer{
private final ResourceServerEntity entity;
public ResourceServerAdapter(ResourceServerEntity entity, MongoStoreInvocationContext invocationContext) {
super(invocationContext);
this.entity = entity;
}
@Override
public String getId() {
return getMongoEntity().getId();
}
@Override
public String getClientId() {
return getMongoEntity().getClientId();
}
@Override
public boolean isAllowRemoteResourceManagement() {
return getMongoEntity().isAllowRemoteResourceManagement();
}
@Override
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
getMongoEntity().setAllowRemoteResourceManagement(allowRemoteResourceManagement);
updateMongoEntity();
}
@Override
public PolicyEnforcementMode getPolicyEnforcementMode() {
return getMongoEntity().getPolicyEnforcementMode();
}
@Override
public void setPolicyEnforcementMode(PolicyEnforcementMode enforcementMode) {
getMongoEntity().setPolicyEnforcementMode(enforcementMode);
updateMongoEntity();
}
@Override
protected ResourceServerEntity getMongoEntity() {
return this.entity;
}
}
@@ -0,0 +1,60 @@
package org.keycloak.authorization.mongo.adapter;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.mongo.entities.ScopeEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.keycloak.adapters.AbstractMongoAdapter;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class ScopeAdapter extends AbstractMongoAdapter<ScopeEntity> implements Scope {
private final ScopeEntity entity;
private final AuthorizationProvider authorizationProvider;
public ScopeAdapter(ScopeEntity entity, MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
super(invocationContext);
this.entity = entity;
this.authorizationProvider = authorizationProvider;
}
@Override
public String getId() {
return getMongoEntity().getId();
}
@Override
public String getName() {
return getMongoEntity().getName();
}
@Override
public void setName(String name) {
getMongoEntity().setName(name);
updateMongoEntity();
}
@Override
public String getIconUri() {
return getMongoEntity().getIconUri();
}
@Override
public void setIconUri(String iconUri) {
getMongoEntity().setIconUri(iconUri);
updateMongoEntity();
}
@Override
public ResourceServer getResourceServer() {
return this.authorizationProvider.getStoreFactory().getResourceServerStore().findById(getMongoEntity().getResourceServerId());
}
@Override
protected ScopeEntity getMongoEntity() {
return this.entity;
}
}
@@ -0,0 +1,166 @@
/*
* 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.mongo.entities;
import org.keycloak.authorization.model.Policy.DecisionStrategy;
import org.keycloak.authorization.model.Policy.Logic;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.entities.AbstractIdentifiableEntity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@MongoCollection(collectionName = "policies")
public class PolicyEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
private String name;
private String description;
private String type;
private DecisionStrategy decisionStrategy = DecisionStrategy.UNANIMOUS;
private Logic logic = Logic.POSITIVE;
private Map<String, String> config = new HashMap();
private String resourceServerId;
private Set<String> associatedPolicies = new HashSet<>();
private Set<String> resources = new HashSet<>();
private Set<String> scopes = new HashSet<>();
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public DecisionStrategy getDecisionStrategy() {
return this.decisionStrategy;
}
public void setDecisionStrategy(DecisionStrategy decisionStrategy) {
this.decisionStrategy = decisionStrategy;
}
public Logic getLogic() {
return this.logic;
}
public void setLogic(Logic logic) {
this.logic = logic;
}
public Map<String, String> getConfig() {
return this.config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getResourceServerId() {
return this.resourceServerId;
}
public void setResourceServerId(String resourceServerId) {
this.resourceServerId = resourceServerId;
}
public Set<String> getAssociatedPolicies() {
return this.associatedPolicies;
}
public void setAssociatedPolicies(Set<String> associatedPolicies) {
this.associatedPolicies = associatedPolicies;
}
public Set<String> getResources() {
return this.resources;
}
public void setResources(Set<String> resources) {
this.resources = resources;
}
public Set<String> getScopes() {
return this.scopes;
}
public void setScopes(Set<String> scopes) {
this.scopes = scopes;
}
public void addScope(String scopeId) {
getScopes().add(scopeId);
}
public void removeScope(String scopeId) {
getScopes().remove(scopeId);
}
public void addAssociatedPolicy(String policyId) {
getAssociatedPolicies().add(policyId);
}
public void removeAssociatedPolicy(String policyId) {
getAssociatedPolicies().remove(policyId);
}
public void addResource(String resourceId) {
getResources().add(resourceId);
}
public void removeResource(String resourceId) {
getResources().remove(resourceId);
}
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -0,0 +1,142 @@
/*
* 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.mongo.entities;
import org.keycloak.authorization.model.Scope;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.entities.AbstractIdentifiableEntity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@MongoCollection(collectionName = "resources")
public class ResourceEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
private String name;
private String uri;
private String type;
private String iconUri;
private String owner;
private String resourceServerId;
private List<String> scopes = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<String> getScopes() {
return this.scopes;
}
public void setScopes(List<String> scopes) {
this.scopes = scopes;
}
public String getIconUri() {
return iconUri;
}
public void setIconUri(String iconUri) {
this.iconUri = iconUri;
}
public String getResourceServerId() {
return resourceServerId;
}
public void setResourceServerId(String resourceServerId) {
this.resourceServerId = resourceServerId;
}
public String getOwner() {
return this.owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public void updateScopes(Set<Scope> toUpdate) {
for (Scope scope : toUpdate) {
boolean hasScope = false;
for (String existingScope : this.scopes) {
if (existingScope.equals(scope.getId())) {
hasScope = true;
}
}
if (!hasScope) {
this.scopes.add(scope.getId());
}
}
for (String scopeId : new HashSet<String>(this.scopes)) {
boolean hasScope = false;
for (Scope scope : toUpdate) {
if (scopeId.equals(scope.getId())) {
hasScope = true;
}
}
if (!hasScope) {
this.scopes.remove(scopeId);
}
}
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -0,0 +1,67 @@
/*
* 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.mongo.entities;
import org.keycloak.authorization.model.ResourceServer.PolicyEnforcementMode;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.entities.AbstractIdentifiableEntity;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@MongoCollection(collectionName = "resource-servers")
public class ResourceServerEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
private String clientId;
private boolean allowRemoteResourceManagement;
private PolicyEnforcementMode policyEnforcementMode = PolicyEnforcementMode.ENFORCING;
public String getClientId() {
return this.clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public boolean isAllowRemoteResourceManagement() {
return this.allowRemoteResourceManagement;
}
public void setAllowRemoteResourceManagement(boolean allowRemoteResourceManagement) {
this.allowRemoteResourceManagement = allowRemoteResourceManagement;
}
public PolicyEnforcementMode getPolicyEnforcementMode() {
return this.policyEnforcementMode;
}
public void setPolicyEnforcementMode(PolicyEnforcementMode policyEnforcementMode) {
this.policyEnforcementMode = policyEnforcementMode;
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -0,0 +1,66 @@
/*
* 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.mongo.entities;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.entities.AbstractIdentifiableEntity;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@MongoCollection(collectionName = "scopes")
public class ScopeEntity extends AbstractIdentifiableEntity implements MongoIdentifiableEntity {
private String name;
private String iconUri;
private String resourceServerId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIconUri() {
return iconUri;
}
public void setIconUri(String iconUri) {
this.iconUri = iconUri;
}
public String getResourceServerId() {
return resourceServerId;
}
public void setResourceServerId(String resourceServerId) {
this.resourceServerId = resourceServerId;
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
}
}
@@ -0,0 +1,53 @@
/*
* 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.mongo.store;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.store.AuthorizationStoreFactory;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.connections.mongo.MongoConnectionProvider;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoAuthorizationStoreFactory implements AuthorizationStoreFactory {
@Override
public StoreFactory create(KeycloakSession session) {
MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
AuthorizationProvider provider = session.getProvider(AuthorizationProvider.class);
return new MongoStoreFactory(connection.getInvocationContext(), provider);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "mongo";
}
}
@@ -0,0 +1,171 @@
/*
* 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.mongo.store;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.mongo.adapter.PolicyAdapter;
import org.keycloak.authorization.mongo.entities.PolicyEntity;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoPolicyStore implements PolicyStore {
private final MongoStoreInvocationContext invocationContext;
private final AuthorizationProvider authorizationProvider;
public MongoPolicyStore(MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
this.invocationContext = invocationContext;
this.authorizationProvider = authorizationProvider;
}
@Override
public Policy create(String name, String type, ResourceServer resourceServer) {
PolicyEntity entity = new PolicyEntity();
entity.setId(KeycloakModelUtils.generateId());
entity.setName(name);
entity.setType(type);
entity.setResourceServerId(resourceServer.getId());
getMongoStore().insertEntity(entity, getInvocationContext());
return new PolicyAdapter(entity, getInvocationContext(), this.authorizationProvider) ;
}
@Override
public void delete(String id) {
getMongoStore().removeEntity(PolicyEntity.class, id, getInvocationContext());
}
@Override
public Policy findById(String id) {
PolicyEntity entity = getMongoStore().loadEntity(PolicyEntity.class, id, getInvocationContext());
if (entity == null) {
return null;
}
return new PolicyAdapter(entity, getInvocationContext(), this.authorizationProvider);
}
@Override
public Policy findByName(String name, String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.and("name").is(name)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId())).findFirst().orElse(null);
}
@Override
public List<Policy> findByResourceServer(String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public List<Policy> findByResource(String resourceId) {
DBObject query = new QueryBuilder()
.and("resources").is(resourceId)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public List<Policy> findByResourceType(String resourceType, String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.filter(policyEntity -> {
String defaultResourceType = policyEntity.getConfig().get("defaultResourceType");
return defaultResourceType != null && defaultResourceType.equals(resourceType);
})
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public List<Policy> findByScopeIds(List<String> scopeIds, String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.and("scopes").in(scopeIds)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public List<Policy> findByType(String type) {
DBObject query = new QueryBuilder()
.and("type").is(type)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public List<Policy> findDependentPolicies(String policyId) {
DBObject query = new QueryBuilder()
.and("associatedPolicies").is(policyId)
.get();
return getMongoStore().loadEntities(PolicyEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
private MongoStoreInvocationContext getInvocationContext() {
return this.invocationContext;
}
private MongoStore getMongoStore() {
return getInvocationContext().getMongoStore();
}
}
@@ -0,0 +1,90 @@
/*
* 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.mongo.store;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.mongo.adapter.ResourceServerAdapter;
import org.keycloak.authorization.mongo.entities.ResourceServerEntity;
import org.keycloak.authorization.store.ResourceServerStore;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoResourceServerStore implements ResourceServerStore {
private final MongoStoreInvocationContext invocationContext;
private final AuthorizationProvider authorizationProvider;
public MongoResourceServerStore(MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
this.invocationContext = invocationContext;
this.authorizationProvider = authorizationProvider;
}
@Override
public ResourceServer create(String clientId) {
ResourceServerEntity entity = new ResourceServerEntity();
entity.setId(KeycloakModelUtils.generateId());
entity.setClientId(clientId);
getMongoStore().insertEntity(entity, getInvocationContext());
return new ResourceServerAdapter(entity, getInvocationContext());
}
@Override
public void delete(String id) {
getMongoStore().removeEntity(ResourceServerEntity.class, id, getInvocationContext());
}
@Override
public ResourceServer findById(String id) {
ResourceServerEntity entity = getMongoStore().loadEntity(ResourceServerEntity.class, id, getInvocationContext());
if (entity == null) {
return null;
}
return new ResourceServerAdapter(entity, getInvocationContext());
}
@Override
public ResourceServer findByClient(String clientId) {
DBObject query = new QueryBuilder()
.and("clientId").is(clientId)
.get();
return getMongoStore().loadEntities(ResourceServerEntity.class, query, getInvocationContext()).stream()
.map(resourceServer -> findById(resourceServer.getId())).findFirst().orElse(null);
}
private MongoStoreInvocationContext getInvocationContext() {
return this.invocationContext;
}
private MongoStore getMongoStore() {
return getInvocationContext().getMongoStore();
}
}
@@ -0,0 +1,141 @@
/*
* 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.mongo.store;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.mongo.adapter.ResourceAdapter;
import org.keycloak.authorization.mongo.entities.ResourceEntity;
import org.keycloak.authorization.store.ResourceStore;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoResourceStore implements ResourceStore {
private final MongoStoreInvocationContext invocationContext;
private final AuthorizationProvider authorizationProvider;
public MongoResourceStore(MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
this.invocationContext = invocationContext;
this.authorizationProvider = authorizationProvider;
}
@Override
public Resource create(String name, ResourceServer resourceServer, String owner) {
ResourceEntity entity = new ResourceEntity();
entity.setId(KeycloakModelUtils.generateId());
entity.setName(name);
entity.setResourceServerId(resourceServer.getId());
entity.setOwner(owner);
getMongoStore().insertEntity(entity, getInvocationContext());
return new ResourceAdapter(entity, getInvocationContext(), this.authorizationProvider);
}
@Override
public void delete(String id) {
getMongoStore().removeEntity(ResourceEntity.class, id, getInvocationContext());
}
@Override
public Resource findById(String id) {
ResourceEntity entity = getMongoStore().loadEntity(ResourceEntity.class, id, getInvocationContext());
if (entity == null) {
return null;
}
return new ResourceAdapter(entity, getInvocationContext(), this.authorizationProvider);
}
@Override
public List<Resource> findByOwner(String ownerId) {
DBObject query = new QueryBuilder()
.and("owner").is(ownerId)
.get();
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
.map(scope -> findById(scope.getId())).collect(toList());
}
@Override
public List findByResourceServer(String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.get();
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
.map(scope -> findById(scope.getId())).collect(toList());
}
@Override
public List<Resource> findByScope(String... id) {
DBObject query = new QueryBuilder()
.and("scopes.id").in(id)
.get();
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
@Override
public Resource findByName(String name, String resourceServerId) {
DBObject query = new QueryBuilder()
.and("name").is(name)
.and("resourceServerId").is(resourceServerId)
.get();
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId())).findFirst().orElse(null);
}
@Override
public List<Resource> findByType(String type) {
DBObject query = new QueryBuilder()
.and("type").is(type)
.get();
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
private MongoStoreInvocationContext getInvocationContext() {
return this.invocationContext;
}
private MongoStore getMongoStore() {
return getInvocationContext().getMongoStore();
}
}
@@ -0,0 +1,108 @@
/*
* 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.mongo.store;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.mongo.adapter.ScopeAdapter;
import org.keycloak.authorization.mongo.entities.ScopeEntity;
import org.keycloak.authorization.store.ScopeStore;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.List;
import static java.util.stream.Collectors.toList;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoScopeStore implements ScopeStore {
private final MongoStoreInvocationContext invocationContext;
private final AuthorizationProvider authorizationProvider;
public MongoScopeStore(MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
this.invocationContext = invocationContext;
this.authorizationProvider = authorizationProvider;
}
@Override
public Scope create(final String name, final ResourceServer resourceServer) {
ScopeEntity entity = new ScopeEntity();
entity.setId(KeycloakModelUtils.generateId());
entity.setName(name);
entity.setResourceServerId(resourceServer.getId());
getMongoStore().insertEntity(entity, getInvocationContext());
return new ScopeAdapter(entity, getInvocationContext(), this.authorizationProvider);
}
@Override
public void delete(String id) {
getMongoStore().removeEntity(ScopeEntity.class, id, getInvocationContext());
}
@Override
public Scope findById(String id) {
ScopeEntity entity = getMongoStore().loadEntity(ScopeEntity.class, id, getInvocationContext());
if (entity == null) {
return null;
}
return new ScopeAdapter(entity, getInvocationContext(), this.authorizationProvider);
}
@Override
public Scope findByName(String name, String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.and("name").is(name)
.get();
return getMongoStore().loadEntities(ScopeEntity.class, query, getInvocationContext()).stream()
.map(scope -> findById(scope.getId())).findFirst().orElse(null);
}
@Override
public List<Scope> findByResourceServer(String resourceServerId) {
DBObject query = new QueryBuilder()
.and("resourceServerId").is(resourceServerId)
.get();
return getMongoStore().loadEntities(ScopeEntity.class, query, getInvocationContext()).stream()
.map(policyEntity -> findById(policyEntity.getId()))
.collect(toList());
}
private MongoStoreInvocationContext getInvocationContext() {
return this.invocationContext;
}
private MongoStore getMongoStore() {
return getInvocationContext().getMongoStore();
}
}
@@ -0,0 +1,66 @@
/*
* 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.mongo.store;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.ResourceServerStore;
import org.keycloak.authorization.store.ResourceStore;
import org.keycloak.authorization.store.ScopeStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class MongoStoreFactory implements StoreFactory {
private final MongoStoreInvocationContext invocationContext;
private final AuthorizationProvider authorizationProvider;
public MongoStoreFactory(MongoStoreInvocationContext invocationContext, AuthorizationProvider authorizationProvider) {
this.invocationContext = invocationContext;
this.authorizationProvider = authorizationProvider;
}
@Override
public PolicyStore getPolicyStore() {
return new MongoPolicyStore(this.invocationContext, this.authorizationProvider);
}
@Override
public ResourceServerStore getResourceServerStore() {
return new MongoResourceServerStore(this.invocationContext, this.authorizationProvider);
}
@Override
public ResourceStore getResourceStore() {
return new MongoResourceStore(this.invocationContext, this.authorizationProvider);
}
@Override
public ScopeStore getScopeStore() {
return new MongoScopeStore(this.invocationContext, this.authorizationProvider);
}
@Override
public void close() {
}
}
@@ -74,6 +74,10 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
"org.keycloak.models.entities.RequiredActionProviderEntity",
"org.keycloak.models.entities.PersistentUserSessionEntity",
"org.keycloak.models.entities.PersistentClientSessionEntity",
"org.keycloak.authorization.mongo.entities.PolicyEntity",
"org.keycloak.authorization.mongo.entities.ResourceEntity",
"org.keycloak.authorization.mongo.entities.ResourceServerEntity",
"org.keycloak.authorization.mongo.entities.ScopeEntity"
};
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
@@ -129,10 +129,26 @@ public class MongoRealmProvider implements RealmProvider {
@Override
public boolean removeRealm(String id) {
RealmModel realm = getRealm(id);
final RealmModel realm = getRealm(id);
if (realm == null) return false;
session.users().preRemove(realm);
return getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
boolean removed = getMongoStore().removeEntity(MongoRealmEntity.class, id, invocationContext);
if (removed) {
session.getKeycloakSessionFactory().publish(new RealmModel.RealmRemovedEvent() {
@Override
public RealmModel getRealm() {
return realm;
}
@Override
public KeycloakSession getKeycloakSession() {
return session;
}
});
}
return removed;
}
protected MongoStore getMongoStore() {
@@ -408,12 +424,27 @@ public class MongoRealmProvider implements RealmProvider {
@Override
public boolean removeClient(String id, RealmModel realm) {
if (id == null) return false;
ClientModel client = getClientById(id, realm);
final ClientModel client = getClientById(id, realm);
if (client == null) return false;
session.users().preRemove(realm, client);
boolean removed = getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
return getMongoStore().removeEntity(MongoClientEntity.class, id, invocationContext);
if (removed) {
session.getKeycloakSessionFactory().publish(new RealmModel.ClientRemovedEvent() {
@Override
public ClientModel getClient() {
return client;
}
@Override
public KeycloakSession getKeycloakSession() {
return session;
}
});
}
return removed;
}
@Override
@@ -0,0 +1,37 @@
#
# 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.
#
#
# 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.
#
org.keycloak.authorization.mongo.store.MongoAuthorizationStoreFactory