From 6b5c4177421fcb064f7b93dbc6a9d781168f0690 Mon Sep 17 00:00:00 2001 From: Michal Hajas Date: Tue, 1 Feb 2022 13:43:33 +0100 Subject: [PATCH] Add HotRod store for authorization services Closes #9679 --- .../HotRodMapStorageProviderFactory.java | 85 ++++++++++++ .../IckleQueryMapModelCriteriaBuilder.java | 11 ++ .../hotRod/IckleQueryWhereClauses.java | 32 +++++ .../authorization/HotRodDecisionStrategy.java | 41 ++++++ .../hotRod/authorization/HotRodLogic.java | 34 +++++ .../HotRodPermissionTicketEntity.java | 102 ++++++++++++++ .../HotRodPolicyEnforcementMode.java | 40 ++++++ .../authorization/HotRodPolicyEntity.java | 128 ++++++++++++++++++ .../authorization/HotRodResourceEntity.java | 124 +++++++++++++++++ .../HotRodResourceServerEntity.java | 84 ++++++++++++ .../authorization/HotRodScopeEntity.java | 99 ++++++++++++++ .../hotRod/common/HotRodTypesUtils.java | 30 ++++ .../hotRod/common/ProtoSchemaInitializer.java | 18 +++ .../src/main/resources/config/cacheConfig.xml | 12 ++ .../src/main/resources/config/infinispan.xml | 12 ++ .../MapPermissionTicketStore.java | 2 +- .../keycloak/authorization/model/Scope.java | 2 +- .../resources/META-INF/keycloak-server.json | 2 +- .../integration-arquillian/tests/pom.xml | 1 + .../src/main/resources/hotrod/infinispan.xml | 12 ++ .../model/parameters/HotRodMapStorage.java | 2 +- 21 files changed, 869 insertions(+), 4 deletions(-) create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodDecisionStrategy.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodLogic.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPermissionTicketEntity.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEnforcementMode.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEntity.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceEntity.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceServerEntity.java create mode 100644 model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodScopeEntity.java diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java index d838bb0dbe..2287895563 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/HotRodMapStorageProviderFactory.java @@ -19,6 +19,11 @@ package org.keycloak.models.map.storage.hotRod; import org.jboss.logging.Logger; import org.keycloak.Config; +import org.keycloak.authorization.model.PermissionTicket; +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.common.Profile; import org.keycloak.component.AmphibianProviderFactory; import org.keycloak.models.AuthenticatedClientSessionModel; @@ -32,6 +37,11 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.UserLoginFailureModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity; +import org.keycloak.models.map.authorization.entity.MapPolicyEntity; +import org.keycloak.models.map.authorization.entity.MapResourceEntity; +import org.keycloak.models.map.authorization.entity.MapResourceServerEntity; +import org.keycloak.models.map.authorization.entity.MapScopeEntity; import org.keycloak.models.map.authSession.MapAuthenticationSessionEntity; import org.keycloak.models.map.authSession.MapRootAuthenticationSessionEntity; import org.keycloak.models.map.clientscope.MapClientScopeEntity; @@ -53,6 +63,16 @@ import org.keycloak.models.map.role.MapRoleEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntityDelegate; import org.keycloak.models.map.storage.hotRod.authSession.HotRodRootAuthenticationSessionEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodRootAuthenticationSessionEntityDelegate; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPermissionTicketEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPermissionTicketEntityDelegate; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEntityDelegate; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceEntityDelegate; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceServerEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceServerEntityDelegate; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntityDelegate; import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntity; import org.keycloak.models.map.storage.hotRod.loginFailure.HotRodUserLoginFailureEntityDelegate; import org.keycloak.models.map.storage.hotRod.role.HotRodRoleEntity; @@ -113,15 +133,21 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory private final static DeepCloner CLONER = new DeepCloner.Builder() .constructor(MapRootAuthenticationSessionEntity.class, HotRodRootAuthenticationSessionEntityDelegate::new) .constructor(MapAuthenticationSessionEntity.class, HotRodAuthenticationSessionEntityDelegate::new) + .constructor(MapClientEntity.class, HotRodClientEntityDelegate::new) .constructor(MapProtocolMapperEntity.class, HotRodProtocolMapperEntityDelegate::new) + .constructor(MapClientScopeEntity.class, HotRodClientScopeEntityDelegate::new) + .constructor(MapGroupEntity.class, HotRodGroupEntityDelegate::new) + .constructor(MapRoleEntity.class, HotRodRoleEntityDelegate::new) + .constructor(MapUserEntity.class, HotRodUserEntityDelegate::new) .constructor(MapUserCredentialEntity.class, HotRodUserCredentialEntityDelegate::new) .constructor(MapUserFederatedIdentityEntity.class, HotRodUserFederatedIdentityEntityDelegate::new) .constructor(MapUserConsentEntity.class, HotRodUserConsentEntityDelegate::new) + .constructor(MapUserLoginFailureEntity.class, HotRodUserLoginFailureEntityDelegate::new) .constructor(MapRealmEntity.class, HotRodRealmEntityDelegate::new) @@ -136,8 +162,16 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory .constructor(MapRequiredActionProviderEntity.class, HotRodRequiredActionProviderEntityDelegate::new) .constructor(MapRequiredCredentialEntity.class, HotRodRequiredCredentialEntityDelegate::new) .constructor(MapWebAuthnPolicyEntity.class, HotRodWebAuthnPolicyEntityDelegate::new) + .constructor(MapUserSessionEntity.class, HotRodUserSessionEntityDelegate::new) .constructor(MapAuthenticatedClientSessionEntity.class, HotRodAuthenticatedClientSessionEntityDelegate::new) + + .constructor(MapResourceServerEntity.class, HotRodResourceServerEntityDelegate::new) + .constructor(MapResourceEntity.class, HotRodResourceEntityDelegate::new) + .constructor(MapScopeEntity.class, HotRodScopeEntityDelegate::new) + .constructor(MapPolicyEntity.class, HotRodPolicyEntityDelegate::new) + .constructor(MapPermissionTicketEntity.class, HotRodPermissionTicketEntityDelegate::new) + .build(); public static final Map, HotRodEntityDescriptor> ENTITY_DESCRIPTOR_MAP = new HashMap<>(); @@ -200,6 +234,57 @@ public class HotRodMapStorageProviderFactory implements AmphibianProviderFactory new HotRodEntityDescriptor<>(AuthenticatedClientSessionModel.class, HotRodAuthenticatedClientSessionEntity.class, HotRodAuthenticatedClientSessionEntityDelegate::new)); + + // authz + ENTITY_DESCRIPTOR_MAP.put(ResourceServer.class, + new HotRodEntityDescriptor(ResourceServer.class, + HotRodResourceServerEntity.class, + HotRodResourceServerEntityDelegate::new) { + @Override + public String getCacheName() { + return "authz"; + } + }); + + ENTITY_DESCRIPTOR_MAP.put(Resource.class, + new HotRodEntityDescriptor(Resource.class, + HotRodResourceEntity.class, + HotRodResourceEntityDelegate::new){ + @Override + public String getCacheName() { + return "authz"; + } + }); + + ENTITY_DESCRIPTOR_MAP.put(Scope.class, + new HotRodEntityDescriptor(Scope.class, + HotRodScopeEntity.class, + HotRodScopeEntityDelegate::new){ + @Override + public String getCacheName() { + return "authz"; + } + }); + + ENTITY_DESCRIPTOR_MAP.put(Policy.class, + new HotRodEntityDescriptor(Policy.class, + HotRodPolicyEntity.class, + HotRodPolicyEntityDelegate::new){ + @Override + public String getCacheName() { + return "authz"; + } + }); + + ENTITY_DESCRIPTOR_MAP.put(PermissionTicket.class, + new HotRodEntityDescriptor(PermissionTicket.class, + HotRodPermissionTicketEntity.class, + HotRodPermissionTicketEntityDelegate::new){ + @Override + public String getCacheName() { + return "authz"; + } + }); } @Override diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java index 293b80812d..31c1b424c5 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryMapModelCriteriaBuilder.java @@ -17,6 +17,8 @@ package org.keycloak.models.map.storage.hotRod; +import org.keycloak.authorization.model.Policy; +import org.keycloak.authorization.model.Resource; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; import org.keycloak.models.GroupModel; @@ -78,6 +80,13 @@ public class IckleQueryMapModelCriteriaBuilder hotRodEntityClass, StringBuilder whereClauseBuilder, Map parameters) { diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryWhereClauses.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryWhereClauses.java index c5011681a6..d7a68c5b57 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryWhereClauses.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/IckleQueryWhereClauses.java @@ -17,6 +17,7 @@ package org.keycloak.models.map.storage.hotRod; +import org.keycloak.authorization.model.Policy; import org.keycloak.models.ClientModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; @@ -56,6 +57,7 @@ public class IckleQueryWhereClauses { WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserModel.SearchableFields.IDP_AND_USER, IckleQueryWhereClauses::whereClauseForUserIdpAlias); WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserModel.SearchableFields.CONSENT_CLIENT_FEDERATION_LINK, IckleQueryWhereClauses::whereClauseForConsentClientFederationLink); WHERE_CLAUSE_PRODUCER_OVERRIDES.put(UserSessionModel.SearchableFields.CORRESPONDING_SESSION_ID, IckleQueryWhereClauses::whereClauseForCorrespondingSessionId); + WHERE_CLAUSE_PRODUCER_OVERRIDES.put(Policy.SearchableFields.CONFIG, IckleQueryWhereClauses::whereClauseForPolicyConfig); } @FunctionalInterface @@ -172,4 +174,34 @@ public class IckleQueryWhereClauses { return "(" + nameClause + ")" + " AND " + "(" + valueClause + ")"; } + + private static String whereClauseForPolicyConfig(String modelFieldName, ModelCriteriaBuilder.Operator op, Object[] values, Map parameters) { + if (values == null || values.length == 0) { + throw new CriterionNotSupportedException(Policy.SearchableFields.CONFIG, op, "Invalid arguments, expected (config_name, config_value_operator_arguments), got: " + Arrays.toString(values)); + } + + final Object attrName = values[0]; + if (!(attrName instanceof String)) { + throw new CriterionNotSupportedException(Policy.SearchableFields.CONFIG, op, "Invalid arguments, expected (String config_name), got: " + Arrays.toString(values)); + } + + String attrNameS = (String) attrName; + Object[] realValues = new Object[values.length - 1]; + System.arraycopy(values, 1, realValues, 0, values.length - 1); + + boolean isNotExists = op.equals(ModelCriteriaBuilder.Operator.NOT_EXISTS); + if (isNotExists || op.equals(ModelCriteriaBuilder.Operator.EXISTS)) { + ModelCriteriaBuilder.Operator o = isNotExists ? ModelCriteriaBuilder.Operator.NE : ModelCriteriaBuilder.Operator.EQ; + return IckleQueryOperators.combineExpressions(o, modelFieldName + ".key", new String[] { attrNameS }, parameters); + } + + String nameClause = IckleQueryOperators.combineExpressions(ModelCriteriaBuilder.Operator.EQ, modelFieldName + ".key", new String[] { attrNameS }, parameters); + + if (realValues.length == 0) { + return nameClause; + } + + String valueClause = IckleQueryOperators.combineExpressions(op, modelFieldName + ".value", realValues, parameters); + return "(" + nameClause + ")" + " AND " + "(" + valueClause + ")"; + } } diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodDecisionStrategy.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodDecisionStrategy.java new file mode 100644 index 0000000000..1cdb849459 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodDecisionStrategy.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoEnumValue; + +public enum HotRodDecisionStrategy { + /** + * Defines that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. + */ + @ProtoEnumValue(number = 0) + AFFIRMATIVE, + + /** + * Defines that all policies must evaluate to a positive decision in order to the overall decision be also positive. + */ + @ProtoEnumValue(number = 1) + UNANIMOUS, + + /** + * Defines that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, + * the final decision will be negative. + */ + @ProtoEnumValue(number = 2) + CONSENSUS +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodLogic.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodLogic.java new file mode 100644 index 0000000000..3f60b00a74 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodLogic.java @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoEnumValue; + +public enum HotRodLogic { + /** + * Defines that this policy follows a positive logic. In other words, the final decision is the policy outcome. + */ + @ProtoEnumValue(number = 0) + POSITIVE, + + /** + * Defines that this policy uses a logical negation. In other words, the final decision would be a negative of the policy outcome. + */ + @ProtoEnumValue(number = 1) + NEGATIVE, +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPermissionTicketEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPermissionTicketEntity.java new file mode 100644 index 0000000000..45688a0bed --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPermissionTicketEntity.java @@ -0,0 +1,102 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoDoc; +import org.infinispan.protostream.annotations.ProtoField; +import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation; +import org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity; +import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; +import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl; + +@GenerateHotRodEntityImplementation( + implementInterface = "org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity", + inherits = "org.keycloak.models.map.storage.hotRod.authorization.HotRodPermissionTicketEntity.AbstractHotRodPermissionTicketEntity" +) +@ProtoDoc("@Indexed") +public class HotRodPermissionTicketEntity extends AbstractHotRodEntity { + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 1, required = true) + public int entityVersion = 1; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 2) + public String id; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 3) + public String realmId; + + @ProtoField(number = 4) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String owner; + + @ProtoField(number = 5) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String requester; + + @ProtoField(number = 6) + public Long createdTimestamp; + + @ProtoField(number = 7) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Long grantedTimestamp; + + @ProtoField(number = 8) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String resourceId; + + @ProtoField(number = 9) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String scopeId; + + @ProtoField(number = 10) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String resourceServerId; + + @ProtoField(number = 11) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String policyId; + + public static abstract class AbstractHotRodPermissionTicketEntity extends UpdatableHotRodEntityDelegateImpl implements MapPermissionTicketEntity { + + @Override + public String getId() { + return getHotRodEntity().id; + } + + @Override + public void setId(String id) { + HotRodPermissionTicketEntity entity = getHotRodEntity(); + if (entity.id != null) throw new IllegalStateException("Id cannot be changed"); + entity.id = id; + entity.updated |= id != null; + } + } + + @Override + public boolean equals(Object o) { + return HotRodPermissionTicketEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodPermissionTicketEntityDelegate.entityHashCode(this); + } +} \ No newline at end of file diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEnforcementMode.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEnforcementMode.java new file mode 100644 index 0000000000..0c61504e4e --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEnforcementMode.java @@ -0,0 +1,40 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoEnumValue; + +public enum HotRodPolicyEnforcementMode { + /** + * Requests are denied by default even when there is no policy associated with a given resource. + */ + @ProtoEnumValue(number = 0) + ENFORCING, + + /** + * Requests are allowed even when there is no policy associated with a given resource. + */ + @ProtoEnumValue(number = 1) + PERMISSIVE, + + /** + * Completely disables the evaluation of policies and allow access to any resource. + */ + @ProtoEnumValue(number = 2) + DISABLED +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEntity.java new file mode 100644 index 0000000000..b44a6b684b --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodPolicyEntity.java @@ -0,0 +1,128 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoDoc; +import org.infinispan.protostream.annotations.ProtoField; +import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation; +import org.keycloak.models.map.authorization.entity.MapPolicyEntity; +import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; +import org.keycloak.models.map.storage.hotRod.common.HotRodStringPair; +import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl; + +import java.util.Objects; +import java.util.Set; + +@GenerateHotRodEntityImplementation( + implementInterface = "org.keycloak.models.map.authorization.entity.MapPolicyEntity", + inherits = "org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEntity.AbstractHotRodPolicyEntity" +) +@ProtoDoc("@Indexed") +public class HotRodPolicyEntity extends AbstractHotRodEntity { + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 1, required = true) + public int entityVersion = 1; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 2) + public String id; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 3) + public String realmId; + + @ProtoField(number = 4) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String name; + + @ProtoField(number = 5) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String nameLowercase; + + @ProtoField(number = 6) + public String description; + + @ProtoField(number = 7) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = \"filename\"))") + public String type; + + @ProtoField(number = 8) + public HotRodDecisionStrategy decisionStrategy; + + @ProtoField(number = 9) + public HotRodLogic logic; + + @ProtoField(number = 10) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set configs; + + @ProtoField(number = 11) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String resourceServerId; + + @ProtoField(number = 12) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set associatedPolicyIds; + + @ProtoField(number = 13) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set resourceIds; + + @ProtoField(number = 14) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set scopeIds; + + @ProtoField(number = 15) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String owner; + + public static abstract class AbstractHotRodPolicyEntity extends UpdatableHotRodEntityDelegateImpl implements MapPolicyEntity { + + @Override + public String getId() { + return getHotRodEntity().id; + } + + @Override + public void setId(String id) { + HotRodPolicyEntity entity = getHotRodEntity(); + if (entity.id != null) throw new IllegalStateException("Id cannot be changed"); + entity.id = id; + entity.updated |= id != null; + } + + @Override + public void setName(String name) { + HotRodPolicyEntity entity = getHotRodEntity(); + entity.updated |= ! Objects.equals(entity.name, name); + entity.name = name; + entity.nameLowercase = name == null ? null : name.toLowerCase(); + } + } + + @Override + public boolean equals(Object o) { + return HotRodPolicyEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodPolicyEntityDelegate.entityHashCode(this); + } +} \ No newline at end of file diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceEntity.java new file mode 100644 index 0000000000..18ac386b0f --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceEntity.java @@ -0,0 +1,124 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoDoc; +import org.infinispan.protostream.annotations.ProtoField; +import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation; +import org.keycloak.models.map.authorization.entity.MapResourceEntity; +import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; +import org.keycloak.models.map.storage.hotRod.common.HotRodAttributeEntityNonIndexed; +import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl; + +import java.util.Objects; +import java.util.Set; + +@GenerateHotRodEntityImplementation( + implementInterface = "org.keycloak.models.map.authorization.entity.MapResourceEntity", + inherits = "org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceEntity.AbstractHotRodResourceEntity" +) +@ProtoDoc("@Indexed") +public class HotRodResourceEntity extends AbstractHotRodEntity { + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 1, required = true) + public int entityVersion = 1; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 2) + public String id; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 3) + public String realmId; + + @ProtoField(number = 4) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String name; + + @ProtoField(number = 5) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String nameLowercase; + + @ProtoField(number = 6) + public String displayName; + + @ProtoField(number = 7) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set uris; + + @ProtoField(number = 8) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = \"filename\"))") + public String type; + + @ProtoField(number = 9) + public String iconUri; + + @ProtoField(number = 10) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String owner; + + @ProtoField(number = 11) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Boolean ownerManagedAccess; + + @ProtoField(number = 12) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String resourceServerId; + + @ProtoField(number = 13) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public Set scopeIds; + + @ProtoField(number = 14) + public Set attributes; + + public static abstract class AbstractHotRodResourceEntity extends UpdatableHotRodEntityDelegateImpl implements MapResourceEntity { + + @Override + public String getId() { + return getHotRodEntity().id; + } + + @Override + public void setId(String id) { + HotRodResourceEntity entity = getHotRodEntity(); + if (entity.id != null) throw new IllegalStateException("Id cannot be changed"); + entity.id = id; + entity.updated |= id != null; + } + + @Override + public void setName(String name) { + HotRodResourceEntity entity = getHotRodEntity(); + entity.updated |= ! Objects.equals(entity.name, name); + entity.name = name; + entity.nameLowercase = name == null ? null : name.toLowerCase(); + } + } + + @Override + public boolean equals(Object o) { + return HotRodResourceEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodResourceEntityDelegate.entityHashCode(this); + } +} \ No newline at end of file diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceServerEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceServerEntity.java new file mode 100644 index 0000000000..1f7b03dcb2 --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodResourceServerEntity.java @@ -0,0 +1,84 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoDoc; +import org.infinispan.protostream.annotations.ProtoField; +import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation; +import org.keycloak.models.map.authorization.entity.MapResourceServerEntity; +import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; +import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl; + + +@GenerateHotRodEntityImplementation( + implementInterface = "org.keycloak.models.map.authorization.entity.MapResourceServerEntity", + inherits = "org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceServerEntity.AbstractHotRodResourceServerEntity" +) +public class HotRodResourceServerEntity extends AbstractHotRodEntity { + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 1, required = true) + public int entityVersion = 1; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 2) + public String id; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 3) + public String realmId; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 4) + public String clientId; + + @ProtoField(number = 5) + public Boolean allowRemoteResourceManagement; + + @ProtoField(number = 6) + public HotRodPolicyEnforcementMode policyEnforcementMode; + + @ProtoField(number = 7) + public HotRodDecisionStrategy decisionStrategy; + + public static abstract class AbstractHotRodResourceServerEntity extends UpdatableHotRodEntityDelegateImpl implements MapResourceServerEntity { + + @Override + public String getId() { + return getHotRodEntity().id; + } + + @Override + public void setId(String id) { + HotRodResourceServerEntity entity = getHotRodEntity(); + if (entity.id != null) throw new IllegalStateException("Id cannot be changed"); + entity.id = id; + entity.updated |= id != null; + } + } + + @Override + public boolean equals(Object o) { + return HotRodResourceServerEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodResourceServerEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodScopeEntity.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodScopeEntity.java new file mode 100644 index 0000000000..50143d6c9a --- /dev/null +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/authorization/HotRodScopeEntity.java @@ -0,0 +1,99 @@ +/* + * Copyright 2022 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.models.map.storage.hotRod.authorization; + +import org.infinispan.protostream.annotations.ProtoDoc; +import org.infinispan.protostream.annotations.ProtoField; +import org.keycloak.models.map.annotations.GenerateHotRodEntityImplementation; +import org.keycloak.models.map.authorization.entity.MapScopeEntity; +import org.keycloak.models.map.storage.hotRod.common.AbstractHotRodEntity; +import org.keycloak.models.map.storage.hotRod.common.UpdatableHotRodEntityDelegateImpl; + +import java.util.Objects; + +@GenerateHotRodEntityImplementation( + implementInterface = "org.keycloak.models.map.authorization.entity.MapScopeEntity", + inherits = "org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntity.AbstractHotRodScopeEntity" +) +@ProtoDoc("@Indexed") +public class HotRodScopeEntity extends AbstractHotRodEntity { + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 1, required = true) + public int entityVersion = 1; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 2) + public String id; + + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + @ProtoField(number = 3) + public String realmId; + + @ProtoField(number = 4) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String name; + + @ProtoField(number = 5) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String nameLowercase; + + @ProtoField(number = 6) + public String displayName; + + @ProtoField(number = 7) + public String iconUri; + + @ProtoField(number = 8) + @ProtoDoc("@Field(index = Index.YES, store = Store.YES)") + public String resourceServerId; + + public static abstract class AbstractHotRodScopeEntity extends UpdatableHotRodEntityDelegateImpl implements MapScopeEntity { + + @Override + public String getId() { + return getHotRodEntity().id; + } + + @Override + public void setId(String id) { + HotRodScopeEntity entity = getHotRodEntity(); + if (entity.id != null) throw new IllegalStateException("Id cannot be changed"); + entity.id = id; + entity.updated |= id != null; + } + + @Override + public void setName(String name) { + HotRodScopeEntity entity = getHotRodEntity(); + entity.updated |= ! Objects.equals(entity.name, name); + entity.name = name; + entity.nameLowercase = name == null ? null : name.toLowerCase(); + } + } + + @Override + public boolean equals(Object o) { + return HotRodScopeEntityDelegate.entityEquals(this, o); + } + + @Override + public int hashCode() { + return HotRodScopeEntityDelegate.entityHashCode(this); + } +} diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java index 7da1c2f2bf..821a4b2ada 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/HotRodTypesUtils.java @@ -21,11 +21,17 @@ import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.map.common.AbstractEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodDecisionStrategy; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodLogic; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEnforcementMode; import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodLocalizationTexts; import org.keycloak.models.map.storage.hotRod.realm.entity.HotRodRequirement; import org.keycloak.models.map.storage.hotRod.user.HotRodUserConsentEntity; import org.keycloak.models.map.storage.hotRod.user.HotRodUserFederatedIdentityEntity; import org.keycloak.models.map.storage.hotRod.userSession.HotRodSessionState; +import org.keycloak.representations.idm.authorization.DecisionStrategy; +import org.keycloak.representations.idm.authorization.Logic; +import org.keycloak.representations.idm.authorization.PolicyEnforcementMode; import java.util.HashMap; import java.util.List; @@ -165,4 +171,28 @@ public class HotRodTypesUtils { public static HotRodSessionState migrateStateToHotRodSessionState(UserSessionModel.State state) { return HotRodSessionState.valueOf(state.name()); } + + public static HotRodDecisionStrategy migrateDecisionStrategyToHotRodDecisionStrategy(DecisionStrategy p0) { + return p0 == null ? null : HotRodDecisionStrategy.values()[p0.ordinal()]; + } + + public static DecisionStrategy migrateHotRodDecisionStrategyToDecisionStrategy(HotRodDecisionStrategy p0) { + return p0 == null ? null : DecisionStrategy.values()[p0.ordinal()]; + } + + public static HotRodPolicyEnforcementMode migratePolicyEnforcementModeToHotRodPolicyEnforcementMode(PolicyEnforcementMode p0) { + return p0 == null ? null : HotRodPolicyEnforcementMode.values()[p0.ordinal()]; + } + + public static PolicyEnforcementMode migrateHotRodPolicyEnforcementModeToPolicyEnforcementMode(HotRodPolicyEnforcementMode p0) { + return p0 == null ? null : PolicyEnforcementMode.values()[p0.ordinal()]; + } + + public static HotRodLogic migrateLogicToHotRodLogic(Logic p0) { + return p0 == null ? null : HotRodLogic.values()[p0.ordinal()]; + } + + public static Logic migrateHotRodLogicToLogic(HotRodLogic p0) { + return p0 == null ? null : Logic.values()[p0.ordinal()]; + } } diff --git a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java index 979f6004ec..d71c8b7d0a 100644 --- a/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java +++ b/model/map-hot-rod/src/main/java/org/keycloak/models/map/storage/hotRod/common/ProtoSchemaInitializer.java @@ -22,6 +22,14 @@ import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder; import org.keycloak.models.map.storage.hotRod.authSession.HotRodAuthenticationSessionEntity; import org.keycloak.models.map.storage.hotRod.authSession.HotRodExecutionStatus; import org.keycloak.models.map.storage.hotRod.authSession.HotRodRootAuthenticationSessionEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodDecisionStrategy; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodLogic; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPermissionTicketEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEnforcementMode; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodPolicyEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodResourceServerEntity; +import org.keycloak.models.map.storage.hotRod.authorization.HotRodScopeEntity; import org.keycloak.models.map.storage.hotRod.client.HotRodClientEntity; import org.keycloak.models.map.storage.hotRod.client.HotRodProtocolMapperEntity; import org.keycloak.models.map.storage.hotRod.clientscope.HotRodClientScopeEntity; @@ -105,6 +113,16 @@ import org.keycloak.models.map.storage.hotRod.userSession.HotRodUserSessionEntit // Client sessions HotRodAuthenticatedClientSessionEntity.class, + // Authz + HotRodResourceServerEntity.class, + HotRodResourceEntity.class, + HotRodScopeEntity.class, + HotRodPolicyEntity.class, + HotRodPermissionTicketEntity.class, + HotRodDecisionStrategy.class, + HotRodLogic.class, + HotRodPolicyEnforcementMode.class, + // Common HotRodPair.class, HotRodStringPair.class, diff --git a/model/map-hot-rod/src/main/resources/config/cacheConfig.xml b/model/map-hot-rod/src/main/resources/config/cacheConfig.xml index 3ad1c6f1b4..cca1644c7b 100644 --- a/model/map-hot-rod/src/main/resources/config/cacheConfig.xml +++ b/model/map-hot-rod/src/main/resources/config/cacheConfig.xml @@ -88,5 +88,17 @@ + + + + + kc.HotRodResourceEntity + kc.HotRodScopeEntity + kc.HotRodPolicyEntity + kc.HotRodPermissionTicketEntity + kc.HotRodStringPair + + + diff --git a/model/map-hot-rod/src/main/resources/config/infinispan.xml b/model/map-hot-rod/src/main/resources/config/infinispan.xml index b7f2174b7d..ce334c64af 100644 --- a/model/map-hot-rod/src/main/resources/config/infinispan.xml +++ b/model/map-hot-rod/src/main/resources/config/infinispan.xml @@ -90,5 +90,17 @@ + + + + + kc.HotRodResourceEntity + kc.HotRodScopeEntity + kc.HotRodPolicyEntity + kc.HotRodPermissionTicketEntity + kc.HotRodStringPair + + + diff --git a/model/map/src/main/java/org/keycloak/models/map/authorization/MapPermissionTicketStore.java b/model/map/src/main/java/org/keycloak/models/map/authorization/MapPermissionTicketStore.java index 3e5662e1de..b079937346 100644 --- a/model/map/src/main/java/org/keycloak/models/map/authorization/MapPermissionTicketStore.java +++ b/model/map/src/main/java/org/keycloak/models/map/authorization/MapPermissionTicketStore.java @@ -107,7 +107,7 @@ public class MapPermissionTicketStore implements PermissionTicketStore { // @UniqueConstraint(columnNames = {"OWNER", "REQUESTER", "RESOURCE_SERVER_ID", "RESOURCE_ID", "SCOPE_ID"}) DefaultModelCriteria mcb = forResourceServer(resourceServer) .compare(SearchableFields.OWNER, Operator.EQ, owner) - .compare(SearchableFields.RESOURCE_ID, Operator.EQ, resource) + .compare(SearchableFields.RESOURCE_ID, Operator.EQ, resource.getId()) .compare(SearchableFields.REQUESTER, Operator.EQ, requester); if (scope != null) { diff --git a/server-spi-private/src/main/java/org/keycloak/authorization/model/Scope.java b/server-spi-private/src/main/java/org/keycloak/authorization/model/Scope.java index 75b655c481..b8821e767c 100644 --- a/server-spi-private/src/main/java/org/keycloak/authorization/model/Scope.java +++ b/server-spi-private/src/main/java/org/keycloak/authorization/model/Scope.java @@ -32,7 +32,7 @@ public interface Scope { public static final SearchableModelField ID = new SearchableModelField<>("id", String.class); public static final SearchableModelField NAME = new SearchableModelField<>("name", String.class); public static final SearchableModelField RESOURCE_SERVER_ID = new SearchableModelField<>("resourceServerId", String.class); - public static final SearchableModelField REALM_ID = new SearchableModelField<>("resourceServerId", String.class); + public static final SearchableModelField REALM_ID = new SearchableModelField<>("realmId", String.class); } public static enum FilterOption { diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json index 2a3bf97e02..a2c489313e 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json @@ -264,7 +264,7 @@ "username": "${keycloak.connectionsHotRod.username:myuser}", "password": "${keycloak.connectionsHotRod.password:qwer1234!}", "enableSecurity": "${keycloak.connectionsHotRod.enableSecurity:true}", - "reindexCaches": "${keycloak.connectionsHotRod.reindexCaches:auth-sessions,clients,client-scopes,groups,users,user-login-failures,user-sessions,client-sessions,roles,realms}" + "reindexCaches": "${keycloak.connectionsHotRod.reindexCaches:auth-sessions,clients,client-scopes,groups,users,user-login-failures,user-sessions,client-sessions,roles,realms,authz}" } }, diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 927e9e59da..a64f6f35bc 100755 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -1505,6 +1505,7 @@ hotrod hotrod hotrod + hotrod diff --git a/testsuite/model/src/main/resources/hotrod/infinispan.xml b/testsuite/model/src/main/resources/hotrod/infinispan.xml index 8e96168383..fd7a03055f 100644 --- a/testsuite/model/src/main/resources/hotrod/infinispan.xml +++ b/testsuite/model/src/main/resources/hotrod/infinispan.xml @@ -86,5 +86,17 @@ + + + + + kc.HotRodResourceEntity + kc.HotRodScopeEntity + kc.HotRodPolicyEntity + kc.HotRodPermissionTicketEntity + kc.HotRodStringPair + + + diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java index c95962d011..2bd57da6af 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java @@ -79,7 +79,7 @@ public class HotRodMapStorage extends KeycloakModelParameters { .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) + .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi("user").provider(MapUserProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) .spi(UserSessionSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID).config("storage-user-sessions.provider", HotRodMapStorageProviderFactory.PROVIDER_ID) .config("storage-client-sessions.provider", HotRodMapStorageProviderFactory.PROVIDER_ID)