From f63cf15a076ed7967415ae2b836b27b06652636a Mon Sep 17 00:00:00 2001 From: ChanikaRuchini Date: Fri, 6 Oct 2023 20:56:03 +0530 Subject: [PATCH] Restrict specific claim management endpoints for sub-organizations --- .../pom.xml | 5 +++ .../common/ClaimManagementDataHolder.java | 12 ++++++ .../claim/management/common/Constant.java | 6 ++- ...anizationManagementOSGIServiceFactory.java | 38 +++++++++++++++++++ .../pom.xml | 5 +++ .../v1/core/ServerClaimManagementService.java | 34 +++++++++++++++++ .../cxf/claim-management-server-v1-cxf.xml | 6 +++ pom.xml | 4 +- 8 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/factory/OrganizationManagementOSGIServiceFactory.java diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/pom.xml b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/pom.xml index 25e8e7cb74..7d6eec20e8 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/pom.xml @@ -45,6 +45,11 @@ org.wso2.carbon.identity.claim.metadata.mgt provided + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + provided + org.springframework spring-web diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/ClaimManagementDataHolder.java b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/ClaimManagementDataHolder.java index 34db4413eb..0f88cf9067 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/ClaimManagementDataHolder.java +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/ClaimManagementDataHolder.java @@ -17,6 +17,7 @@ package org.wso2.carbon.identity.api.server.claim.management.common; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; /** * Service holder class for identity governance. @@ -24,6 +25,7 @@ public class ClaimManagementDataHolder { private static ClaimMetadataManagementService claimMetadataManagementService; + private static OrganizationManager organizationManager; public static ClaimMetadataManagementService getClaimMetadataManagementService() { @@ -35,4 +37,14 @@ public static void setClaimMetadataManagementService( ClaimManagementDataHolder.claimMetadataManagementService = claimMetadataManagementService; } + + public static OrganizationManager getOrganizationManager() { + + return organizationManager; + } + + public static void setOrganizationManager(OrganizationManager organizationManager) { + + ClaimManagementDataHolder.organizationManager = organizationManager; + } } diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/Constant.java b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/Constant.java index a9863bd7af..ca244e68e8 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/Constant.java +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/Constant.java @@ -201,7 +201,11 @@ public enum ErrorMessage { ERROR_CODE_USERSTORE_NOT_SPECIFIED_IN_MAPPINGS("CMT-60005", "Userstore not specified", "Mapped userstore cannot be empty"), ERROR_CODE_EMPTY_ATTRIBUTE_MAPPINGS("CMT-60006", "Attribute mapping not specified", - "Attribute mapping cannot be empty"); + "Attribute mapping cannot be empty"), + ERROR_CODE_UNAUTHORIZED_ORG_FOR_CLAIM_MANAGEMENT("CMT-60007", "Unauthorized organization for " + + "claim management", "Unable to execute the requested organization claim management task."), + ERROR_CODE_ERROR_RESOLVING_ORGANIZATION("CMT-60008", "Error resolving organization", + "Unable to resolve organization"); private final String code; private final String message; diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/factory/OrganizationManagementOSGIServiceFactory.java b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/factory/OrganizationManagementOSGIServiceFactory.java new file mode 100644 index 0000000000..399e31bfe1 --- /dev/null +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.api.server.claim.management.common/src/main/java/org/wso2/carbon/identity/api/server/claim/management/common/factory/OrganizationManagementOSGIServiceFactory.java @@ -0,0 +1,38 @@ +package org.wso2.carbon.identity.api.server.claim.management.common.factory; + +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; + +/** + * Factory Beans serves as a factory for creating other beans within the IOC container. This factory bean is used to + * instantiate the OrganizationManagementService type of object inside the container. + */ +public class OrganizationManagementOSGIServiceFactory extends AbstractFactoryBean { + + private OrganizationManager organizationManager; + + @Override + public Class getObjectType() { + + return Object.class; + } + + @Override + protected OrganizationManager createInstance() throws Exception { + + if (this.organizationManager == null) { + OrganizationManager orgMgtService = (OrganizationManager) PrivilegedCarbonContext. + getThreadLocalCarbonContext().getOSGiService(OrganizationManager.class, null); + + if (orgMgtService != null) { + this.organizationManager = orgMgtService; + } else { + throw new Exception("Unable to retrieve Organization Management service."); + } + } + return this.organizationManager; + } +} + + diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/pom.xml b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/pom.xml index 3ae82b772c..fedaa1ced4 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/pom.xml +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/pom.xml @@ -140,5 +140,10 @@ org.wso2.carbon.identity.api.server.claim.management.common provided + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + provided + diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/java/org/wso2/carbon/identity/rest/api/server/claim/management/v1/core/ServerClaimManagementService.java b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/java/org/wso2/carbon/identity/rest/api/server/claim/management/v1/core/ServerClaimManagementService.java index 51369de3a1..3799e63658 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/java/org/wso2/carbon/identity/rest/api/server/claim/management/v1/core/ServerClaimManagementService.java +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/java/org/wso2/carbon/identity/rest/api/server/claim/management/v1/core/ServerClaimManagementService.java @@ -27,6 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.api.server.claim.management.common.Constant; import org.wso2.carbon.identity.api.server.common.ContextLoader; import org.wso2.carbon.identity.api.server.common.FileContent; @@ -43,6 +44,7 @@ import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim; import org.wso2.carbon.identity.claim.metadata.mgt.util.ClaimConstants; import org.wso2.carbon.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; import org.wso2.carbon.identity.rest.api.server.claim.management.v1.dto.AttributeMappingDTO; import org.wso2.carbon.identity.rest.api.server.claim.management.v1.dto.ClaimDialectReqDTO; import org.wso2.carbon.identity.rest.api.server.claim.management.v1.dto.ClaimDialectResDTO; @@ -85,6 +87,7 @@ import javax.xml.bind.Unmarshaller; import static org.wso2.carbon.identity.api.server.claim.management.common.ClaimManagementDataHolder.getClaimMetadataManagementService; +import static org.wso2.carbon.identity.api.server.claim.management.common.ClaimManagementDataHolder.getOrganizationManager; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.CMT_PATH_COMPONENT; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_ATTRIBUTE_FILTERING_NOT_IMPLEMENTED; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_CLAIMS_NOT_FOUND_FOR_DIALECT; @@ -115,6 +118,7 @@ import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_LOCAL_CLAIM_NOT_FOUND; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_PAGINATION_NOT_IMPLEMENTED; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_SORTING_NOT_IMPLEMENTED; +import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_UNAUTHORIZED_ORG_FOR_CLAIM_MANAGEMENT; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.ErrorMessage.ERROR_CODE_USERSTORE_NOT_SPECIFIED_IN_MAPPINGS; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.LOCAL_DIALECT; import static org.wso2.carbon.identity.api.server.claim.management.common.Constant.LOCAL_DIALECT_PATH; @@ -133,6 +137,7 @@ import static org.wso2.carbon.identity.api.server.common.Constants.XML_FILE_EXTENSION; import static org.wso2.carbon.identity.api.server.common.Constants.YAML_FILE_EXTENSION; import static org.wso2.carbon.identity.api.server.common.ContextLoader.buildURIForBody; +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CONFLICT; @@ -320,6 +325,7 @@ public String addLocalClaim(LocalClaimReqDTO localClaimReqDTO) { } try { + validateRootOrganization(); validateAttributeMappings(localClaimReqDTO.getAttributeMapping()); getClaimMetadataManagementService().addLocalClaim(createLocalClaim(localClaimReqDTO), ContextLoader.getTenantDomainFromContext()); @@ -343,6 +349,7 @@ public void deleteLocalClaim(String claimId) { String claimURI; try { + validateRootOrganization(); claimURI = base64DecodeId(claimId); } catch (Exception ignored) { // Ignoring the delete operation and return 204 response code, since the resource does not exist. @@ -425,6 +432,7 @@ public List getLocalClaims(Boolean excludeIdentityClaims, Stri public void updateLocalClaim(String claimId, LocalClaimReqDTO localClaimReqDTO) { try { + validateRootOrganization(); if (!StringUtils.equals(base64DecodeId(claimId), localClaimReqDTO.getClaimURI())) { throw handleClaimManagementClientError(ERROR_CODE_LOCAL_CLAIM_CONFLICT, CONFLICT, base64DecodeId(claimId)); @@ -699,6 +707,7 @@ private FileContent parseClaimDialectToYaml(ClaimDialectConfiguration dialectCon public String addExternalClaim(String dialectId, ExternalClaimReqDTO externalClaimReqDTO) { try { + validateRootOrganization(); if (!isDialectExists(dialectId)) { throw handleClaimManagementClientError(ERROR_CODE_INVALID_DIALECT_ID, NOT_FOUND, dialectId); } @@ -725,6 +734,7 @@ public void deleteExternalClaim(String dialectId, String claimId) { String externalClaimURI; String externalClaimDialectURI; try { + validateRootOrganization(); externalClaimURI = base64DecodeId(claimId); externalClaimDialectURI = base64DecodeId(dialectId); } catch (Exception ignored) { @@ -820,6 +830,7 @@ public List getExternalClaims(String dialectId, Integer lim public void updateExternalClaim(String dialectId, String claimId, ExternalClaimReqDTO externalClaimReqDTO) { try { + validateRootOrganization(); if (!StringUtils.equals(base64DecodeId(claimId), externalClaimReqDTO.getClaimURI())) { throw handleClaimManagementClientError(ERROR_CODE_EXTERNAL_CLAIM_CONFLICT, CONFLICT, base64DecodeId(claimId), dialectId); @@ -1444,4 +1455,27 @@ private void validateAttributeMappings(List attributeMappin } } } + + private void validateRootOrganization() throws ClaimMetadataClientException { + + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String rootOrganizationId = getOrganizationManager().getPrimaryOrganizationId(organizationId); + if (!rootOrganizationId.equals(organizationId)) { + throw handleClaimManagementClientError(ERROR_CODE_UNAUTHORIZED_ORG_FOR_CLAIM_MANAGEMENT, FORBIDDEN, + organizationId); + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new ClaimMetadataClientException(Constant.ErrorMessage.ERROR_CODE_ERROR_RESOLVING_ORGANIZATION. + getCode(), Constant.ErrorMessage.ERROR_CODE_ERROR_RESOLVING_ORGANIZATION.getDescription()); + } + } } diff --git a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/resources/META-INF/cxf/claim-management-server-v1-cxf.xml b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/resources/META-INF/cxf/claim-management-server-v1-cxf.xml index eb6581cfbc..a3f3cfcc8d 100644 --- a/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/resources/META-INF/cxf/claim-management-server-v1-cxf.xml +++ b/components/org.wso2.carbon.identity.api.server.claim.management/org.wso2.carbon.identity.rest.api.server.claim.management.v1/src/main/resources/META-INF/cxf/claim-management-server-v1-cxf.xml @@ -22,6 +22,12 @@ class="org.wso2.carbon.identity.api.server.claim.management.common.ClaimManagementDataHolder"> + + + + diff --git a/pom.xml b/pom.xml index 18bbfeb1c1..bff6852fc2 100644 --- a/pom.xml +++ b/pom.xml @@ -753,13 +753,13 @@ 1.0.3 - 1.0.56 + 1.0.64 [1.0.0, 2.0.0) - 1.3.70 + 1.3.73