diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java index 1c6e1befc2..112efb6eaf 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/src/main/java/io/entgra/device/mgt/core/apimgt/extension/rest/api/constants/Constants.java @@ -69,6 +69,7 @@ public final class Constants { public static final String SCOPE_PUBLISH_RESERVED_USER_PASSWORD = "&gKfyE8E4rUY4Q"; public static final String SUPER_TENANT_DOMAIN = "carbon.super"; public static final String ADMIN_ROLE_KEY = "admin"; + public static final String PERM_SCOPE_MAPPING_META_KEY = "perm-scope-mapping"; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/TenantCreateObserver.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/TenantCreateObserver.java index 1f9d09bd1e..7bbbe1008e 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/TenantCreateObserver.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/internal/TenantCreateObserver.java @@ -17,6 +17,7 @@ */ package io.entgra.device.mgt.core.device.mgt.core.internal; +import com.google.gson.Gson; import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices; import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices; import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants; @@ -26,6 +27,10 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo; import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException; import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException; import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException; +import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException; +import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata; +import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService; import org.apache.axis2.context.ConfigurationContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,7 +49,9 @@ import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Load configuration files to tenant's registry. @@ -135,6 +142,25 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser */ private void publishScopesToTenant(String tenantDomain) throws TenantManagementException { if (!Constants.SUPER_TENANT_DOMAIN.equals(tenantDomain)) { + + MetadataManagementService metadataManagementService = DeviceManagementDataHolder.getInstance().getMetadataManagementService(); + + Map superTenantPermScopeMapping = getPermScopeMapping(Constants.SUPER_TENANT_DOMAIN); + Map subTenantPermScopeMapping = getPermScopeMapping(tenantDomain); + + if (superTenantPermScopeMapping == null) { + msg = "Error occurred while retrieving meta key '" + Constants.PERM_SCOPE_MAPPING_META_KEY + "' for tenant '" + + Constants.SUPER_TENANT_DOMAIN + "'. Hence aborting publishing scopes to tenant: '" + tenantDomain + "'."; + log.error(msg); + throw new TenantManagementException(msg); + } + if (superTenantPermScopeMapping.equals(subTenantPermScopeMapping)) { + if (log.isDebugEnabled()) { + log.debug( "Scopes in '" + tenantDomain + "' are up to date with super tenant scopes."); + } + return; + } + APIApplicationServices apiApplicationServices = DeviceManagementDataHolder.getInstance().getApiApplicationServices(); APIApplicationKey apiApplicationKey; AccessTokenInfo accessTokenInfo; @@ -239,12 +265,18 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser } } } + + if (missingScopes.size() > 0 || deletedScopes.size() > 0) { + updatePermScopeMetaData(superTenantPermScopeMapping, metadataManagementService); + } } else { if (log.isDebugEnabled()) { log.debug("Starting to publish shared scopes to newly created tenant: '" + tenantDomain + "'."); } + publishSharedScopes(Arrays.asList(superTenantScopes), publisherRESTAPIServices, apiApplicationKey, accessTokenInfo); + updatePermScopeMetaData(superTenantPermScopeMapping, metadataManagementService); } // Delete the temporary scope publish user after scopes are added or deleted to sub tenant space UserStoreManager userStoreManager = @@ -279,12 +311,58 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser msg = "Error occurred while publishing scopes to '" + tenantDomain + "' tenant space."; log.error(msg, e); throw new TenantManagementException(msg, e); + } catch (MetadataManagementException e) { + msg = "Error occurred trying to create metadata entry '" + Constants.PERM_SCOPE_MAPPING_META_KEY + "'."; + log.error(msg); + throw new TenantManagementException(msg); + } catch (MetadataKeyAlreadyExistsException e) { + msg = "Error occurred trying to create metadata entry '" + Constants.PERM_SCOPE_MAPPING_META_KEY + "'. The meta key " + + "already exists."; + log.error(msg); + throw new TenantManagementException(msg); } finally { PrivilegedCarbonContext.endTenantFlow(); } } } + private Map getPermScopeMapping(String tenantDomain) throws TenantManagementException { + if (log.isDebugEnabled()) { + log.debug("Retrieving permission scope mapping from metadata from the tenant: '" + tenantDomain + "'."); + } + Map permScopeMapping = null; + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + MetadataManagementService metadataManagementService = DeviceManagementDataHolder.getInstance().getMetadataManagementService(); + Metadata metadata = metadataManagementService.retrieveMetadata("perm-scope-mapping"); + if (metadata != null) { + permScopeMapping = new Gson().fromJson(metadata.getMetaValue().toString(), HashMap.class); + } + } catch (MetadataManagementException e) { + msg = "Error occurred while retrieving permission scope mapping from metadata for tenant: '" + tenantDomain + "'."; + log.error(msg, e); + throw new TenantManagementException(msg, e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + return permScopeMapping; + } + + private void updatePermScopeMetaData(Map superTenantPermScopeMapping, + MetadataManagementService metadataManagementService) throws MetadataManagementException, + MetadataKeyAlreadyExistsException { + + Metadata newMetaData = new Metadata(); + newMetaData.setMetaKey(Constants.PERM_SCOPE_MAPPING_META_KEY); + newMetaData.setMetaValue(new Gson().toJson(superTenantPermScopeMapping)); + if (metadataManagementService.retrieveMetadata(Constants.PERM_SCOPE_MAPPING_META_KEY) == null) { + metadataManagementService.createMetadata(newMetaData); + } else { + metadataManagementService.updateMetadata(newMetaData); + } + } + /** * Get all the scopes from the super tenant space * @param apiApplicationServices {@link APIApplicationServices} is used to create an OAuth application and retrieve client ID and secret