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 825841d
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 6 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
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2019, WSO2 LLC. (http://www.wso2.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -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,24 @@ public static void setClaimMetadataManagementService(

ClaimManagementDataHolder.claimMetadataManagementService = claimMetadataManagementService;
}

/**
* Get organizationManager OSGi service.
*
* @return organization Manager.
*/
public static OrganizationManager getOrganizationManager() {

return organizationManager;
}

/**
* Set organizationManager OSGi service.
*
* @param organizationManager Organization Manager.
*/
public static void setOrganizationManager(OrganizationManager organizationManager) {

ClaimManagementDataHolder.organizationManager = organizationManager;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2019, WSO2 LLC. (http://www.wso2.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -201,7 +201,12 @@ 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", "Claim modification is not " +
"allowed for this organization.", "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,54 @@
/*
* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. licenses this file to you 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.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) {
throw new Exception("Unable to retrieve Organization Management service.");
}
this.organizationManager = orgMgtService;
}
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
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2019, WSO2 LLC. (http://www.wso2.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down 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 Down Expand Up @@ -162,6 +166,7 @@ public class ServerClaimManagementService {
public String addClaimDialect(ClaimDialectReqDTO claimDialectReqDTO) {

try {
allowClaimManagementAccessForRootOrganizations();
getClaimMetadataManagementService().addClaimDialect(
createClaimDialect(claimDialectReqDTO),
ContextLoader.getTenantDomainFromContext());
Expand All @@ -182,6 +187,7 @@ public String addClaimDialect(ClaimDialectReqDTO claimDialectReqDTO) {
public String addClaimDialect(String dialectURI) {

try {
allowClaimManagementAccessForRootOrganizations();
getClaimMetadataManagementService().addClaimDialect(
createClaimDialect(dialectURI),
ContextLoader.getTenantDomainFromContext());
Expand All @@ -201,6 +207,7 @@ public void deleteClaimDialect(String dialectId) {

String claimDialectURI;
try {
allowClaimManagementAccessForRootOrganizations();
claimDialectURI = base64DecodeId(dialectId);
} catch (Exception ignored) {
// Ignoring the delete operation and return 204 response code, since the resource does not exist.
Expand Down Expand Up @@ -281,6 +288,7 @@ public List<ClaimDialectResDTO> getClaimDialects(Integer limit, Integer offset,
public String updateClaimDialect(String dialectId, ClaimDialectReqDTO claimDialectReqDTO) {

try {
allowClaimManagementAccessForRootOrganizations();
// If the old and new dialect uri is the same we don't need to do a db update.
if (!StringUtils.equals(base64DecodeId(dialectId), claimDialectReqDTO.getDialectURI())) {
getClaimMetadataManagementService().renameClaimDialect(
Expand Down Expand Up @@ -320,6 +328,7 @@ public String addLocalClaim(LocalClaimReqDTO localClaimReqDTO) {
}

try {
allowClaimManagementAccessForRootOrganizations();
validateAttributeMappings(localClaimReqDTO.getAttributeMapping());
getClaimMetadataManagementService().addLocalClaim(createLocalClaim(localClaimReqDTO),
ContextLoader.getTenantDomainFromContext());
Expand All @@ -343,6 +352,7 @@ public void deleteLocalClaim(String claimId) {

String claimURI;
try {
allowClaimManagementAccessForRootOrganizations();
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 +435,7 @@ public List<LocalClaimResDTO> getLocalClaims(Boolean excludeIdentityClaims, Stri
public void updateLocalClaim(String claimId, LocalClaimReqDTO localClaimReqDTO) {

try {
allowClaimManagementAccessForRootOrganizations();
if (!StringUtils.equals(base64DecodeId(claimId), localClaimReqDTO.getClaimURI())) {
throw handleClaimManagementClientError(ERROR_CODE_LOCAL_CLAIM_CONFLICT, CONFLICT,
base64DecodeId(claimId));
Expand Down Expand Up @@ -699,6 +710,7 @@ private FileContent parseClaimDialectToYaml(ClaimDialectConfiguration dialectCon
public String addExternalClaim(String dialectId, ExternalClaimReqDTO externalClaimReqDTO) {

try {
allowClaimManagementAccessForRootOrganizations();
if (!isDialectExists(dialectId)) {
throw handleClaimManagementClientError(ERROR_CODE_INVALID_DIALECT_ID, NOT_FOUND, dialectId);
}
Expand All @@ -725,6 +737,7 @@ public void deleteExternalClaim(String dialectId, String claimId) {
String externalClaimURI;
String externalClaimDialectURI;
try {
allowClaimManagementAccessForRootOrganizations();
externalClaimURI = base64DecodeId(claimId);
externalClaimDialectURI = base64DecodeId(dialectId);
} catch (Exception ignored) {
Expand Down Expand Up @@ -820,6 +833,7 @@ public List<ExternalClaimResDTO> getExternalClaims(String dialectId, Integer lim
public void updateExternalClaim(String dialectId, String claimId, ExternalClaimReqDTO externalClaimReqDTO) {

try {
allowClaimManagementAccessForRootOrganizations();
if (!StringUtils.equals(base64DecodeId(claimId), externalClaimReqDTO.getClaimURI())) {
throw handleClaimManagementClientError(ERROR_CODE_EXTERNAL_CLAIM_CONFLICT, CONFLICT,
base64DecodeId(claimId), dialectId);
Expand Down Expand Up @@ -1444,4 +1458,21 @@ private void validateAttributeMappings(List<AttributeMappingDTO> attributeMappin
}
}
}

private void allowClaimManagementAccessForRootOrganizations() throws ClaimMetadataClientException {

String organizationId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getOrganizationId();
if (StringUtils.isNotBlank(organizationId)) {
try {
String rootOrganizationId = getOrganizationManager().getPrimaryOrganizationId(organizationId);
if (!rootOrganizationId.equals(organizationId)) {
throw handleClaimManagementClientError(ERROR_CODE_UNAUTHORIZED_ORG_FOR_CLAIM_MANAGEMENT, FORBIDDEN,
organizationId);
}
} catch (OrganizationManagementException e) {
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 825841d

Please sign in to comment.