From e361900f4cd5d4d9522f6793073b1524a6db2771 Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Thu, 9 Nov 2023 09:58:48 +0530 Subject: [PATCH 1/3] Support federated IDP groups to role assignments --- .../application/common/model/IdPGroup.java | 24 +++++++++ .../idp/mgt/IdentityProviderManager.java | 18 +++++++ .../org/wso2/carbon/idp/mgt/IdpManager.java | 15 ++++++ .../idp/mgt/dao/CacheBackedIdPMgtDAO.java | 15 ++++++ .../carbon/idp/mgt/dao/IdPManagementDAO.java | 38 +++++++++++++ .../idp/mgt/util/IdPManagementConstants.java | 7 ++- .../role/v2/mgt/core/dao/RoleDAOImpl.java | 53 ++++++++++++------- 7 files changed, 151 insertions(+), 19 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/IdPGroup.java b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/IdPGroup.java index fe450ddf8f82..57447c91ca82 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/IdPGroup.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.common/src/main/java/org/wso2/carbon/identity/application/common/model/IdPGroup.java @@ -48,6 +48,10 @@ public class IdPGroup implements Serializable { @XmlTransient @JsonIgnore private String idpGroupId = null; + @IgnoreNullElement + @XmlTransient + @JsonIgnore + private String idpId = null; public static IdPGroup build(OMElement idpGroupOM) { @@ -101,4 +105,24 @@ public void setIdpGroupId(String idpGroupId) { this.idpGroupId = idpGroupId; } + + /** + * Get idp id. + * + * @return idp Id. + */ + public String getIdpId() { + + return idpId; + } + + /** + * Set idp id. + * + * @param idpId idp id. + */ + public void setIdpId(String idpId) { + + this.idpId = idpId; + } } diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdentityProviderManager.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdentityProviderManager.java index 1e5d55ed539d..d5dc13d983ef 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdentityProviderManager.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdentityProviderManager.java @@ -32,6 +32,7 @@ import org.wso2.carbon.identity.application.common.model.ClaimConfig; import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.IdPGroup; import org.wso2.carbon.identity.application.common.model.IdentityProvider; import org.wso2.carbon.identity.application.common.model.IdentityProviderProperty; import org.wso2.carbon.identity.application.common.model.LocalRole; @@ -81,6 +82,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -2959,6 +2961,22 @@ public IdentityProvider getIdPByMetadataProperty(String property, String value, return getIdPByName(idPName, tenantDomain, ignoreFileBasedIdps); } + @Override + public List getValidIdPGroupsByIdPGroupIds(List idpGroupIds, String tenantDomain) + throws IdentityProviderManagementException { + + if (CollectionUtils.isEmpty(idpGroupIds)) { + return Collections.emptyList(); + } + try { + int tenantId = IdentityTenantUtil.getTenantId(tenantDomain); + return dao.getIdPGroupsByIds(idpGroupIds, tenantId); + } catch (IdentityProviderManagementException e) { + throw IdPManagementUtil.handleServerException( + IdPManagementConstants.ErrorMessage.ERROR_CODE_RETRIEVING_IDP_GROUPS, null, e); + } + } + /** * Method to validate the uniqueness of the IDP Issuer Name. * Ideally used when adding a IDP. diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdpManager.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdpManager.java index bacf734a5a40..d42eefcdf856 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdpManager.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/IdpManager.java @@ -20,6 +20,7 @@ import org.wso2.carbon.identity.application.common.model.ClaimMapping; import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig; +import org.wso2.carbon.identity.application.common.model.IdPGroup; import org.wso2.carbon.identity.application.common.model.IdentityProvider; import org.wso2.carbon.identity.application.common.model.LocalRole; import org.wso2.carbon.identity.application.common.model.ProvisioningConnectorConfig; @@ -531,4 +532,18 @@ default IdentityProvider getIdPByMetadataProperty(String property, String value, return null; } + + /** + * Get valid IDP groups by IDP group IDs. + * + * @param idpGroupIds List of IDP group IDs. + * @param tenantDomain Tenant domain. + * @return List of valid IDP groups. + * @throws IdentityProviderManagementException If an error occurred while getting IDP Group data. + */ + default List getValidIdPGroupsByIdPGroupIds(List idpGroupIds, String tenantDomain) + throws IdentityProviderManagementException { + + return null; + } } diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/CacheBackedIdPMgtDAO.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/CacheBackedIdPMgtDAO.java index a01e086c79f1..c1e3a060585f 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/CacheBackedIdPMgtDAO.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/CacheBackedIdPMgtDAO.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.identity.application.common.model.IdPGroup; import org.wso2.carbon.identity.application.common.model.IdentityProvider; import org.wso2.carbon.identity.application.common.model.IdentityProviderProperty; import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants; @@ -1062,4 +1063,18 @@ public Map getIdPNamesById(int tenantId, Set idpIds) return idPMgtDAO.getIdPNamesById(tenantId, idpIds); } + + /** + * Get IDP group data by IDP group IDs. + * + * @param idpGroupIds List of IDP group IDs. + * @param tenantId Tenant ID. + * @return List of IDP groups. + * @throws IdentityProviderManagementException If an error occurred while retrieving IDP groups. + */ + public List getIdPGroupsByIds(List idpGroupIds, int tenantId) + throws IdentityProviderManagementException { + + return idPMgtDAO.getIdPGroupsByIds(idpGroupIds, tenantId); + } } diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java index 85ec245870c8..498db7eaa5fa 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java @@ -74,6 +74,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -5022,4 +5023,41 @@ public Map getIdPNamesById(int tenantId, Set idpIds) IdentityDatabaseUtil.closeAllConnections(dbConnection, rs, prepStmt); } } + + /** + * Get IDP group data by IDP group IDs. + * + * @param idpGroupIds List of IDP group IDs. + * @param tenantId Tenant ID. + * @return List of IDP groups. + * @throws IdentityProviderManagementException If an error occurred while retrieving IDP groups. + */ + public List getIdPGroupsByIds(List idpGroupIds, int tenantId) + throws IdentityProviderManagementException { + + String query = IdPManagementConstants.SQLQueries.GET_IDP_GROUPS_BY_IDP_GROUP_IDS; + String placeholders = String.join(",", Collections.nCopies(idpGroupIds.size(), "?")); + query = query.replace(IdPManagementConstants.IDP_GROUP_LIST_PLACEHOLDER, placeholders); + try (Connection connection = IdentityDatabaseUtil.getDBConnection(false); + PreparedStatement prepStmt = connection.prepareStatement(query)) { + prepStmt.setInt(1, tenantId); + for (int i = 0; i < idpGroupIds.size(); i++) { + prepStmt.setString(i + 2, idpGroupIds.get(i)); + } + try (ResultSet resultSet = prepStmt.executeQuery()) { + List idpGroups = new ArrayList<>(); + while (resultSet.next()) { + IdPGroup idpGroup = new IdPGroup(); + idpGroup.setIdpGroupId(resultSet.getString("UUID")); + idpGroup.setIdpGroupName(resultSet.getString("GROUP_NAME")); + idpGroup.setIdpId(resultSet.getString("IDP_ID")); + idpGroups.add(idpGroup); + } + return idpGroups; + } + } catch (SQLException e) { + throw new IdentityProviderManagementException("Error occurred while retrieving IDP groups for IDP group " + + "IDs: " + idpGroupIds, e); + } + } } diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/IdPManagementConstants.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/IdPManagementConstants.java index a5e0a38dbe09..95f2ac75c9d3 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/IdPManagementConstants.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/util/IdPManagementConstants.java @@ -25,6 +25,7 @@ public class IdPManagementConstants { public static final String SHARED_IDP_PREFIX = "SHARED_"; public static final String SCOPE_LIST_PLACEHOLDER = "_SCOPE_LIST_"; + public static final String IDP_GROUP_LIST_PLACEHOLDER = "_IDP_GROUP_LIST_"; public static final String MULTI_VALUED_PROPERTY_CHARACTER = "."; public static final String IS_TRUE_VALUE = "1"; public static final String IS_FALSE_VALUE = "0"; @@ -553,6 +554,9 @@ public static class SQLQueries { "IDP_METADATA.TENANT_ID = ?"; public static final String GET_TOTAL_IDP_CLAIM_USAGES = "SELECT COUNT(*) FROM IDP_CLAIM_MAPPING WHERE " + "TENANT_ID = ? AND LOCAL_CLAIM = ?"; + public static final String GET_IDP_GROUPS_BY_IDP_GROUP_IDS = "SELECT IDP_GROUP.UUID, IDP_GROUP.GROUP_NAME, " + + "IDP.UUID AS IDP_ID FROM IDP_GROUP LEFT JOIN IDP ON IDP.ID = IDP_GROUP.IDP_ID WHERE " + + "IDP_GROUP.TENANT_ID = ? AND IDP_GROUP.UUID IN (" + IDP_GROUP_LIST_PLACEHOLDER + ")"; } public enum ErrorMessage { @@ -585,7 +589,8 @@ public enum ErrorMessage { ERROR_CODE_RETRIEVE_IDP_CONNECTED_APPS("IDP-65007", "Error while retrieving connected " + "applications of Identity Provider with resource ID: %s."), ERROR_CODE_VALIDATING_OUTBOUND_PROVISIONING_ROLES("IDP-65008", "Error while validating " + - "the outbound provisioning roles"); + "the outbound provisioning roles"), + ERROR_CODE_RETRIEVING_IDP_GROUPS("IDP-65009", "Error while retrieving IDP groups"); private final String code; private final String message; diff --git a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java index 4c8a74a3dd7e..9bf88eb9d5be 100644 --- a/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java +++ b/components/role-mgt/org.wso2.carbon.identity.role.v2.mgt.core/src/main/java/org/wso2/carbon/identity/role/v2/mgt/core/dao/RoleDAOImpl.java @@ -1253,25 +1253,14 @@ private void resolveIdpGroups(List groups, String tenantDomain) throws if (groups == null || groups.isEmpty()) { return; } - for (IdpGroup group : groups) { - IdentityProvider identityProvider = getIdpById(group.getIdpId(), tenantDomain); - if (identityProvider == null) { - throw new IdentityRoleManagementException("Idp not found.", - "Idp not found for id : " + group.getIdpId()); - } - IdPGroup[] idpGroups = identityProvider.getIdPGroupConfig(); - Map idpGroupIdList = new HashMap<>(); - for (IdPGroup idpGroup : idpGroups) { - idpGroupIdList.put(idpGroup.getIdpGroupId(), idpGroup.getIdpGroupName()); - } - if (idpGroupIdList.containsKey(group.getGroupId())) { - group.setGroupName(idpGroupIdList.get(group.getGroupId())); - } else { - throw new IdentityRoleManagementException("Idp group not found.", - "Idp group not found for id : " + group.getGroupId()); - } - } + List idpGroupIds = groups.stream() + .map(IdpGroup::getGroupId) + .collect(Collectors.toList()); + List idpGroups = getIdpGroupsByIds(idpGroupIds, tenantDomain); + + groups.clear(); + idpGroups.stream().map(this::convertToIdpGroup).forEach(groups::add); } /** @@ -2958,6 +2947,27 @@ private IdentityProvider getIdpById(String idpId, String tenantDomain) return identityProvider; } + /** + * Get idp groups by id. + * + * @param idpGroupIds Idp group ids. + * @param tenantDomain Tenant domain. + * @throws IdentityRoleManagementException Error occurred while retrieving idp groups by id. + */ + private List getIdpGroupsByIds(List idpGroupIds, String tenantDomain) + throws IdentityRoleManagementException { + + List idpGroups; + try { + idpGroups = RoleManagementServiceComponentHolder.getInstance() + .getIdentityProviderManager().getValidIdPGroupsByIdPGroupIds(idpGroupIds, tenantDomain); + } catch (IdentityProviderManagementException e) { + throw new IdentityRoleManagementException("Error while retrieving idp groups", "Error while retrieving idp " + + "groups for idp Ids: " + idpGroupIds, e); + } + return idpGroups; + } + /** * Delete SCIM role. * @@ -3245,4 +3255,11 @@ private void lessThanFilterBuilder(String value, String attributeName, StringBui filter.append(attributeName).append(filterString); filterQueryBuilder.setFilterAttributeValue(attributeName, value); } + + private IdpGroup convertToIdpGroup(IdPGroup idpGroup) { + + IdpGroup convertedGroup = new IdpGroup(idpGroup.getIdpGroupId(), idpGroup.getIdpId()); + convertedGroup.setGroupName(idpGroup.getIdpGroupName()); + return convertedGroup; + } } From 59d76c136ee1265884f58566d006288cb4d3dbde Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Tue, 14 Nov 2023 09:38:49 +0530 Subject: [PATCH 2/3] add idp id for idp group --- .../src/main/resources/IdentityProviderMgtService.wsdl | 1 + 1 file changed, 1 insertion(+) diff --git a/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/src/main/resources/IdentityProviderMgtService.wsdl b/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/src/main/resources/IdentityProviderMgtService.wsdl index 37f420897080..03fcbc99e080 100644 --- a/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/src/main/resources/IdentityProviderMgtService.wsdl +++ b/service-stubs/identity/org.wso2.carbon.idp.mgt.stub/src/main/resources/IdentityProviderMgtService.wsdl @@ -130,6 +130,7 @@ + From 5b7138f04fb974349e2e0a3157b9ce2109f58313 Mon Sep 17 00:00:00 2001 From: SujanSanjula96 Date: Tue, 14 Nov 2023 09:39:07 +0530 Subject: [PATCH 3/3] Return empty list --- .../java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java index 498db7eaa5fa..76a37d85bf9a 100644 --- a/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java +++ b/components/idp-mgt/org.wso2.carbon.idp.mgt/src/main/java/org/wso2/carbon/idp/mgt/dao/IdPManagementDAO.java @@ -5035,6 +5035,9 @@ public Map getIdPNamesById(int tenantId, Set idpIds) public List getIdPGroupsByIds(List idpGroupIds, int tenantId) throws IdentityProviderManagementException { + if (CollectionUtils.isEmpty(idpGroupIds)) { + return Collections.emptyList(); + } String query = IdPManagementConstants.SQLQueries.GET_IDP_GROUPS_BY_IDP_GROUP_IDS; String placeholders = String.join(",", Collections.nCopies(idpGroupIds.size(), "?")); query = query.replace(IdPManagementConstants.IDP_GROUP_LIST_PLACEHOLDER, placeholders);