Skip to content

Commit

Permalink
Restrict specific claim management endpoints for sub-organizations
Browse files Browse the repository at this point in the history
  • Loading branch information
ChanikaRuchini committed Oct 6, 2023
1 parent 395077f commit f63cf15
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
<artifactId>org.wso2.carbon.identity.claim.metadata.mgt</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
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.
*/
public class ClaimManagementDataHolder {

private static ClaimMetadataManagementService claimMetadataManagementService;
private static OrganizationManager organizationManager;

public static ClaimMetadataManagementService getClaimMetadataManagementService() {

Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<OrganizationManager> {

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;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,10 @@
<artifactId>org.wso2.carbon.identity.api.server.claim.management.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -320,6 +325,7 @@ public String addLocalClaim(LocalClaimReqDTO localClaimReqDTO) {
}

try {
validateRootOrganization();
validateAttributeMappings(localClaimReqDTO.getAttributeMapping());
getClaimMetadataManagementService().addLocalClaim(createLocalClaim(localClaimReqDTO),
ContextLoader.getTenantDomainFromContext());
Expand All @@ -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.
Expand Down Expand Up @@ -425,6 +432,7 @@ public List<LocalClaimResDTO> 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));
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -820,6 +830,7 @@ public List<ExternalClaimResDTO> 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);
Expand Down Expand Up @@ -1444,4 +1455,27 @@ private void validateAttributeMappings(List<AttributeMappingDTO> 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());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
class="org.wso2.carbon.identity.api.server.claim.management.common.ClaimManagementDataHolder">
<property name="claimMetadataManagementService" ref="claimManagerFactoryBean"/>
</bean>
<bean id="organizationManagerHolderBean"
class="org.wso2.carbon.identity.api.server.claim.management.common.ClaimManagementDataHolder">
<property name="organizationManager" ref="organizationManagerFactoryBean"/>
</bean>
<bean id="claimManagerFactoryBean"
class="org.wso2.carbon.identity.api.server.claim.management.common.factory.OSGIServiceFactory"/>
<bean id="organizationManagerFactoryBean"
class="org.wso2.carbon.identity.api.server.claim.management.common.factory.OrganizationManagementOSGIServiceFactory"/>
</beans>
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -753,13 +753,13 @@
<identity.verification.version>1.0.3</identity.verification.version>

<!-- Organization management core Version -->
<org.wso2.carbon.identity.organization.management.core.version>1.0.56
<org.wso2.carbon.identity.organization.management.core.version>1.0.64
</org.wso2.carbon.identity.organization.management.core.version>
<org.wso2.carbon.identity.organization.management.core.version.range>[1.0.0, 2.0.0)
</org.wso2.carbon.identity.organization.management.core.version.range>

<!-- Organization management service Version -->
<org.wso2.carbon.identity.organization.management.version>1.3.70
<org.wso2.carbon.identity.organization.management.version>1.3.73
</org.wso2.carbon.identity.organization.management.version>

<!-- Unit test versions -->
Expand Down

0 comments on commit f63cf15

Please sign in to comment.