From b9246ed7c2c6a6cd84d3de92d7078115ac100bb2 Mon Sep 17 00:00:00 2001 From: Thamindu Aluthwala Date: Sun, 15 Oct 2023 11:30:10 +0530 Subject: [PATCH] Register and authorize system apis --- .../pom.xml | 35 +- .../APIResourceManagementConstants.java | 19 + .../impl/APIResourceManagementDAOImpl.java | 15 +- ...APIResourceManagementServiceComponent.java | 65 +++ ...ourceManagementServiceComponentHolder.java | 59 +++ .../APIResourceManagementListener.java | 63 +++ .../APIResourceManagementConfigBuilder.java | 163 ++++++ .../mgt/util/APIResourceManagementUtil.java | 31 ++ .../pom.xml | 5 +- .../application/mgt/ApplicationConstants.java | 2 + ...ApplicationManagementServiceComponent.java | 6 + ...onsoleAuthorizedAPIManagementListener.java | 139 ++++++ .../pom.xml | 47 ++ .../resources/build.properties | 20 + .../resources/p2.inf | 3 + .../resources/system-api-resource.xml | 22 + .../resources/system-api-resource.xml.j2 | 464 ++++++++++++++++++ .../resources/identity.xml.j2 | 12 + ....identity.core.server.feature.default.json | 6 + 19 files changed, 1152 insertions(+), 24 deletions(-) create mode 100644 components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponentHolder.java create mode 100644 components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/listener/APIResourceManagementListener.java create mode 100644 components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementConfigBuilder.java create mode 100644 components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/ConsoleAuthorizedAPIManagementListener.java create mode 100644 features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/build.properties create mode 100644 features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/p2.inf create mode 100644 features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml create mode 100644 features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml index 21e524616831..46782c5f01cf 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/pom.xml @@ -39,6 +39,10 @@ org.apache.felix org.apache.felix.scr.ds-annotations + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + org.wso2.carbon.identity.organization.management.core org.wso2.carbon.identity.organization.management.service @@ -107,35 +111,32 @@ org.wso2.carbon.identity.api.resource.mgt.*; version="${carbon.identity.package.export.version}" - org.osgi.framework;version="${osgi.framework.imp.pkg.version.range}", - org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", - javax.sql, + javax.xml.namespace, + javax.xml.stream, + org.apache.axiom.om; version="${axiom.osgi.version.range}", + org.apache.axiom.om.impl.builder; version="${axiom.osgi.version.range}", org.apache.commons.collections; version="${commons-collections.wso2.osgi.version.range}", + org.apache.commons.io; version="${commons.io.wso2.osgi.version.range}", org.apache.commons.lang; version="${commons-lang.wso2.osgi.version.range}", org.apache.commons.logging; version="${import.package.version.commons.logging}", - org.wso2.carbon.context; version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.database.utils.jdbc; - version="${org.wso2.carbon.database.utils.version.range}", - org.wso2.carbon.database.utils.jdbc.exceptions; - version="${org.wso2.carbon.database.utils.version.range}", + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", org.wso2.carbon.identity.application.common.model; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.base; version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.core.cache; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.core.model; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.core.util; - version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.user.api; version="${carbon.user.api.imp.pkg.version.range}", - org.wso2.carbon.user.core.util; version="${carbon.kernel.package.import.version.range}", - org.wso2.carbon.utils; version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.identity.core; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.core.cache; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.core.model; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.core.util; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.organization.management.service; version="${org.wso2.carbon.identity.organization.management.core.version.range}", org.wso2.carbon.identity.organization.management.service.exception; version="${org.wso2.carbon.identity.organization.management.core.version.range}", org.wso2.carbon.identity.organization.management.service.util; version="${org.wso2.carbon.identity.organization.management.core.version.range}", + org.wso2.carbon.stratos.common.*; version="${carbon.commons.imp.pkg.version}", + org.wso2.carbon.user.core.service; version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.utils; version="${carbon.kernel.package.import.version.range}", diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/constant/APIResourceManagementConstants.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/constant/APIResourceManagementConstants.java index 54d6c50b4cf7..5edbb0166fd5 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/constant/APIResourceManagementConstants.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/constant/APIResourceManagementConstants.java @@ -30,6 +30,9 @@ public class APIResourceManagementConstants { public static final String NAME = "name"; public static final String IDENTIFIER = "identifier"; public static final String TYPE = "type"; + public static final String RBAC_AUTHORIZATION = "RBAC"; + public static final String ASC = "asc"; + public static final String SYSTEM_API_FILTER = "type eq SYSTEM"; public static final String BEFORE = "before"; public static final String AFTER = "after"; public static final String EQ = "eq"; @@ -58,6 +61,22 @@ public class APIResourceManagementConstants { scopeAttributeColumnMap.put(NAME, SQLConstants.NAME_COLUMN_NAME); } + /** + * API resource configuration builder constants. + */ + public static class APIResourceConfigBuilderConstants { + + public static final String API_RESOURCE_ELEMENT = "APIResource"; + public static final String SCOPES_ELEMENT = "Scopes"; + public static final String SCOPE_ELEMENT = "Scope"; + public static final String NAME = "name"; + public static final String IDENTIFIER = "identifier"; + public static final String DISPLAY_NAME = "displayName"; + public static final String DESCRIPTION = "description"; + public static final String REQUIRES_AUTHORIZATION = "requiresAuthorization"; + public static final String SYSTEM_TYPE = "SYSTEM"; + } + /** * Error messages. */ diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java index 4a072355566f..b4a6d67ff645 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java @@ -565,12 +565,15 @@ private static APIResource getApiResource(ResultSet resultSet) throws SQLExcepti .tenantId(resultSet.getInt(SQLConstants.API_RESOURCE_TENANT_ID_COLUMN_NAME)); apiResource = apiResourceBuilder.build(); } - Scope.ScopeBuilder scopeBuilder = new Scope.ScopeBuilder() - .id(resultSet.getString(SQLConstants.SCOPE_ID_COLUMN_NAME)) - .name(resultSet.getString(SQLConstants.SCOPE_QUALIFIED_NAME_COLUMN_NAME)) - .displayName(resultSet.getString(SQLConstants.SCOPE_DISPLAY_NAME_COLUMN_NAME)) - .description(resultSet.getString(SQLConstants.SCOPE_DESCRIPTION_COLUMN_NAME)); - scopes.add(scopeBuilder.build()); + String scopeName = resultSet.getString(SQLConstants.SCOPE_QUALIFIED_NAME_COLUMN_NAME); + if (scopeName != null) { + Scope.ScopeBuilder scopeBuilder = new Scope.ScopeBuilder() + .id(resultSet.getString(SQLConstants.SCOPE_ID_COLUMN_NAME)) + .name(scopeName) + .displayName(resultSet.getString(SQLConstants.SCOPE_DISPLAY_NAME_COLUMN_NAME)) + .description(resultSet.getString(SQLConstants.SCOPE_DESCRIPTION_COLUMN_NAME)); + scopes.add(scopeBuilder.build()); + } } if (apiResource != null) { apiResource.setScopes(scopes); diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponent.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponent.java index 39128850b270..872c3876acff 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponent.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponent.java @@ -25,8 +25,20 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager; import org.wso2.carbon.identity.api.resource.mgt.APIResourceManagerImpl; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtException; +import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants; +import org.wso2.carbon.identity.api.resource.mgt.listener.APIResourceManagementListener; +import org.wso2.carbon.identity.api.resource.mgt.model.APIResourceSearchResult; +import org.wso2.carbon.identity.api.resource.mgt.util.APIResourceManagementUtil; +import org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.stratos.common.listeners.TenantMgtListener; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; /** * Service component for the API resource management. @@ -45,6 +57,10 @@ protected void activate(ComponentContext context) { try { BundleContext bundleCtx = context.getBundleContext(); bundleCtx.registerService(APIResourceManager.class, APIResourceManagerImpl.getInstance(), null); + bundleCtx.registerService(TenantMgtListener.class, new APIResourceManagementListener(), + null); + // Register system APIs in the super tenant. + registerSystemAPIsInSuperTenant(); LOG.debug("API resource management bundle is activated"); } catch (Throwable e) { LOG.error("Error while initializing API resource management component.", e); @@ -62,4 +78,53 @@ protected void deactivate(ComponentContext context) { LOG.error("Error while deactivating API resource management component.", e); } } + + @Reference( + name = "identityCoreInitializedEventService", + service = IdentityCoreInitializedEvent.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetIdentityCoreInitializedEventService" + ) + protected void setIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) { + /* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core + is started */ + } + + protected void unsetIdentityCoreInitializedEventService(IdentityCoreInitializedEvent identityCoreInitializedEvent) { + /* reference IdentityCoreInitializedEvent service to guarantee that this component will wait until identity core + is started */ + } + + @Reference( + name = "organization.service", + service = OrganizationManager.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetOrganizationManager" + ) + protected void setOrganizationManager(OrganizationManager organizationManager) { + /* reference Organization Management service to guarantee that this component will wait until organization + management service is started */ + } + + protected void unsetOrganizationManager(OrganizationManager organizationManager) { + /* reference Organization Management service to guarantee that this component will wait until organization + management service is started */ + } + + private void registerSystemAPIsInSuperTenant() { + + String tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; + try { + APIResourceSearchResult systemAPIResources = APIResourceManagerImpl.getInstance() + .getAPIResources(null, null, 1, APIResourceManagementConstants.SYSTEM_API_FILTER, + APIResourceManagementConstants.ASC, tenantDomain); + if (systemAPIResources.getTotalCount() == 0) { + APIResourceManagementUtil.addSystemAPIs(tenantDomain); + } + } catch (APIResourceMgtException e) { + LOG.error("Error while registering system API resources in the tenant: " + tenantDomain); + } + } } diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponentHolder.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponentHolder.java new file mode 100644 index 000000000000..3e1467ec0186 --- /dev/null +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/internal/APIResourceManagementServiceComponentHolder.java @@ -0,0 +1,59 @@ +/* + * 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.resource.mgt.internal; + +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.user.core.service.RealmService; + +/** + * API Resource Management Service Component Holder class. + */ +public class APIResourceManagementServiceComponentHolder { + + private static APIResourceManagementServiceComponentHolder instance = new + APIResourceManagementServiceComponentHolder(); + + private OrganizationManager organizationManager; + private RealmService realmService; + + public static APIResourceManagementServiceComponentHolder getInstance() { + + return instance; + } + + public OrganizationManager getOrganizationManager() { + + return organizationManager; + } + + public void setOrganizationManager(OrganizationManager organizationManager) { + + this.organizationManager = organizationManager; + } + + public RealmService getRealmService() { + + return realmService; + } + + public void setRealmService(RealmService realmService) { + + this.realmService = realmService; + } +} diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/listener/APIResourceManagementListener.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/listener/APIResourceManagementListener.java new file mode 100644 index 000000000000..57ae83bb5169 --- /dev/null +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/listener/APIResourceManagementListener.java @@ -0,0 +1,63 @@ +/* + * 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.resource.mgt.listener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceManager; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceManagerImpl; +import org.wso2.carbon.identity.api.resource.mgt.util.APIResourceManagementUtil; +import org.wso2.carbon.identity.core.AbstractIdentityTenantMgtListener; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; + +/** + * APIResourceManagementListener class. + */ +public class APIResourceManagementListener extends AbstractIdentityTenantMgtListener { + + private final APIResourceManager apiResourceManager = APIResourceManagerImpl.getInstance(); + + private static final Log LOG = LogFactory.getLog(APIResourceManagementListener.class); + + @Override + public void onTenantCreate(TenantInfoBean tenantInfo) { + + if (!isEnable()) { + LOG.debug("API resource management related APIResourceManagementListener is not enabled."); + return; + } + + int tenantId = tenantInfo.getTenantId(); + if (LOG.isDebugEnabled()) { + LOG.debug("API resource management related APIResourceManagementListener fired for tenant " + + "creation for Tenant ID: " + tenantId); + } + + try { + if (OrganizationManagementUtil.isOrganization(tenantId)) { + return; + } + APIResourceManagementUtil.addSystemAPIs(tenantInfo.getTenantDomain()); + } catch (OrganizationManagementException e) { + LOG.error("Error while registering system API resources in tenant: " + tenantInfo.getTenantDomain()); + } + } +} diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementConfigBuilder.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementConfigBuilder.java new file mode 100644 index 000000000000..5a6ae37853c3 --- /dev/null +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementConfigBuilder.java @@ -0,0 +1,163 @@ +/* + * 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.resource.mgt.util; + +import edu.umd.cs.findbugs.annotations.SuppressWarnings; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.builder.StAXOMBuilder; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants.APIResourceConfigBuilderConstants; +import org.wso2.carbon.identity.application.common.model.APIResource; +import org.wso2.carbon.identity.application.common.model.Scope; +import org.wso2.carbon.utils.CarbonUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * Config builder class for organization management related configs in organization-mgt.xml file. + */ +public class APIResourceManagementConfigBuilder { + + private static final Log LOG = LogFactory.getLog(APIResourceManagementConfigBuilder.class); + private static final Map apiResourceMgtConfigurations = new HashMap<>(); + private static final APIResourceManagementConfigBuilder apiResourceManagementConfigBuilder = + new APIResourceManagementConfigBuilder(); + + private OMElement documentElement; + + public static APIResourceManagementConfigBuilder getInstance() { + + return apiResourceManagementConfigBuilder; + } + + private APIResourceManagementConfigBuilder() { + + loadConfigurations(); + } + + /** + * Get organization management related configs. + * + * @return Map of org mgt configs. + */ + public Map getAPIResourceMgtConfigurations() { + + return apiResourceMgtConfigurations; + } + + /** + * Read the system-api-resource.xml file and build the configuration map. + */ + @SuppressWarnings(value = "PATH_TRAVERSAL_IN", justification = "Don't use any user input file.") + private void loadConfigurations() { + + String configDirPath = CarbonUtils.getCarbonConfigDirPath(); + File configFile = new File(configDirPath, FilenameUtils.getName("system-api-resource.xml")); + if (!configFile.exists()) { + return; + } + try (InputStream stream = Files.newInputStream(configFile.toPath())) { + XMLInputFactory factory = XMLInputFactory.newFactory(); + // Prevents using external resources when parsing xml. + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + // Prevents using external document type definition when parsing xml. + factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + XMLStreamReader parser = factory.createXMLStreamReader(stream); + StAXOMBuilder builder = new StAXOMBuilder(parser); + documentElement = builder.getDocumentElement(); + buildAPIResourceConfig(); + } catch (IOException e) { + LOG.warn("Error while loading system API resource management configs.", e); + } catch (XMLStreamException e) { + LOG.warn("Error while streaming organization management configs.", e); + } + } + + private void buildAPIResourceConfig() { + + Iterator apiResources = this.documentElement.getChildrenWithName( + new QName(APIResourceConfigBuilderConstants.API_RESOURCE_ELEMENT)); + if (apiResources == null) { + return; + } + + while (apiResources.hasNext()) { + OMElement apiResource = apiResources.next(); + APIResource apiResourceObj = buildAPIResource(apiResource); + + if (apiResourceObj == null) { + continue; + } + + OMElement scopeElement = apiResource.getFirstChildWithName( + new QName(APIResourceConfigBuilderConstants.SCOPES_ELEMENT)); + if (scopeElement != null) { + Iterator scopes = scopeElement.getChildrenWithName( + new QName(APIResourceConfigBuilderConstants.SCOPE_ELEMENT)); + if (scopes != null) { + List scopeList = new ArrayList<>(); + while (scopes.hasNext()) { + OMElement scope = scopes.next(); + Scope scopeObj = new Scope.ScopeBuilder() + .name(apiResourceObj.getIdentifier() + + scope.getAttributeValue(new QName(APIResourceConfigBuilderConstants.NAME))) + .displayName(scope.getAttributeValue( + new QName(APIResourceConfigBuilderConstants.DISPLAY_NAME))) + .build(); + scopeList.add(scopeObj); + } + apiResourceObj.setScopes(scopeList); + } + } + apiResourceMgtConfigurations.put(apiResourceObj.getIdentifier(), apiResourceObj); + } + } + + private APIResource buildAPIResource(OMElement element) { + + String apiResourceIdentifier = element.getAttributeValue( + new QName(APIResourceConfigBuilderConstants.IDENTIFIER)); + if (apiResourceMgtConfigurations.containsKey(apiResourceIdentifier)) { + return null; + } + return new APIResource.APIResourceBuilder() + .name(element.getAttributeValue(new QName(APIResourceConfigBuilderConstants.NAME))) + .description(element.getAttributeValue(new QName(APIResourceConfigBuilderConstants.DESCRIPTION))) + .identifier(apiResourceIdentifier) + .type(APIResourceConfigBuilderConstants.SYSTEM_TYPE) + .requiresAuthorization(Boolean.parseBoolean( + element.getAttributeValue(new QName(APIResourceConfigBuilderConstants.REQUIRES_AUTHORIZATION)))) + .build(); + } +} diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementUtil.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementUtil.java index fb152d1be14a..c36d26f1f3e5 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementUtil.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/util/APIResourceManagementUtil.java @@ -19,15 +19,24 @@ package org.wso2.carbon.identity.api.resource.mgt.util; import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceManagerImpl; import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtClientException; +import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtException; import org.wso2.carbon.identity.api.resource.mgt.APIResourceMgtServerException; import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants; +import org.wso2.carbon.identity.application.common.model.APIResource; + +import java.util.Map; /** * Utility class for API Resource Management. */ public class APIResourceManagementUtil { + private static final Log LOG = LogFactory.getLog(APIResourceManagementUtil.class); + /** * Handle API Resource Management client exceptions. * @@ -64,4 +73,26 @@ public static APIResourceMgtServerException handleServerException( return new APIResourceMgtServerException(error.getMessage(), description, error.getCode(), e); } + + /** + * Fetch the configuration from the XML file and register the system API in the given tenant. + * + * @param tenantDomain tenant domain. + */ + public static void addSystemAPIs(String tenantDomain) { + + LOG.debug("Registering System APIs in tenant domain: " + tenantDomain); + Map configs = APIResourceManagementConfigBuilder.getInstance() + .getAPIResourceMgtConfigurations(); + for (APIResource apiResource : configs.values()) { + if (apiResource != null) { + try { + APIResourceManagerImpl.getInstance().addAPIResource(apiResource, tenantDomain); + } catch (APIResourceMgtException e) { + LOG.error("Error while registering system API resources in the tenant: " + tenantDomain); + } + } + } + LOG.debug("System APIs successfully registered in tenant domain: " + tenantDomain); + } } diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml index bd6227e7cc0b..94ab94b43d1c 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml @@ -246,7 +246,10 @@ org.wso2.carbon.identity.central.log.mgt.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.organization.management.service; version="${org.wso2.carbon.identity.organization.management.core.version.range}", org.wso2.carbon.identity.organization.management.service.exception; version="${org.wso2.carbon.identity.organization.management.core.version.range}", - org.wso2.carbon.identity.api.resource.mgt; version="${carbon.identity.package.import.version.range}" + org.wso2.carbon.identity.organization.management.service.util; + version="${org.wso2.carbon.identity.organization.management.core.version.range}", + org.wso2.carbon.identity.api.resource.mgt; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.api.resource.mgt.model; version="${carbon.identity.package.import.version.range}", !org.wso2.carbon.identity.application.mgt.internal, diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationConstants.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationConstants.java index c3312037fb22..5a72fc6fea33 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationConstants.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationConstants.java @@ -99,6 +99,8 @@ private ApplicationConstants() { // Application Management Service Configurations. public static final String ENABLE_APPLICATION_ROLE_VALIDATION_PROPERTY = "ApplicationMgt.EnableRoleValidation"; + public static final String CONSOLE_APPLICATION_NAME = "Console"; + /** * Group the constants related to logs. */ diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java index 0fdcbc847df1..cb39f7fdf3b2 100644 --- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java @@ -54,6 +54,7 @@ import org.wso2.carbon.identity.application.mgt.listener.ApplicationMgtAuditLogger; import org.wso2.carbon.identity.application.mgt.listener.ApplicationMgtListener; import org.wso2.carbon.identity.application.mgt.listener.ApplicationResourceManagementListener; +import org.wso2.carbon.identity.application.mgt.listener.ConsoleAuthorizedAPIManagementListener; import org.wso2.carbon.identity.application.mgt.listener.DefaultApplicationResourceMgtListener; import org.wso2.carbon.identity.application.mgt.provider.ApplicationPermissionProvider; import org.wso2.carbon.identity.application.mgt.provider.RegistryBasedApplicationPermissionProvider; @@ -138,6 +139,11 @@ protected void activate(ComponentContext context) { ApplicationManagementServiceComponentHolder.getInstance() .setApplicationPermissionProvider(new RegistryBasedApplicationPermissionProvider()); } + + // Register the Console Authorized API Management Listener. + bundleContext.registerService(ApplicationMgtListener.class, + new ConsoleAuthorizedAPIManagementListener(), null); + if (log.isDebugEnabled()) { log.debug("Identity ApplicationManagementComponent bundle is activated"); } diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/ConsoleAuthorizedAPIManagementListener.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/ConsoleAuthorizedAPIManagementListener.java new file mode 100644 index 000000000000..26205443ddb9 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/listener/ConsoleAuthorizedAPIManagementListener.java @@ -0,0 +1,139 @@ +/* + * 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.application.mgt.listener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.APIResource; +import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo; +import org.wso2.carbon.identity.application.common.model.AuthorizedAPI; +import org.wso2.carbon.identity.application.common.model.Scope; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationConstants; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementService; +import org.wso2.carbon.identity.application.mgt.AuthorizedAPIManagementServiceImpl; +import org.wso2.carbon.identity.application.mgt.internal.ApplicationManagementServiceComponentHolder; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; + +import java.util.List; + +/** + * Authorized API Management listener class. + */ +public class ConsoleAuthorizedAPIManagementListener extends AbstractApplicationMgtListener { + + private static final Log LOG = LogFactory.getLog(ConsoleAuthorizedAPIManagementListener.class); + + @Override + public boolean doPostCreateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) + throws IdentityApplicationManagementException { + + if (!isEnable()) { + LOG.debug("Authorized API Management related ConsoleAuthorizedAPIManagementListener is not enabled."); + return false; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Authorized API Management related ConsoleAuthorizedAPIManagementListener fired for tenant " + + "creation for Tenant: " + tenantDomain); + } + + if (!ApplicationConstants.CONSOLE_APPLICATION_NAME.equals(serviceProvider.getApplicationName())) { + return false; + } + + try { + if (OrganizationManagementUtil.isOrganization(tenantDomain)) { + return false; + } + authorizeSystemAPIConsole(tenantDomain); + } catch (OrganizationManagementException e) { + LOG.error("Error while registering system API resources in tenant: " + tenantDomain); + } + return true; + } + + private void authorizeSystemAPIConsole(String tenantDomain) { + + try { + ApplicationManagementService applicationManagementService = ApplicationManagementService.getInstance(); + ApplicationBasicInfo applicationBasicInfo = applicationManagementService.getApplicationBasicInfoByName( + ApplicationConstants.CONSOLE_APPLICATION_NAME, tenantDomain); + if (applicationBasicInfo == null) { + LOG.error("Error while authorizing system API console. Console application not found in tenant: " + + tenantDomain); + return; + } + AuthorizedAPIManagementService authorizedAPIManagementService = new AuthorizedAPIManagementServiceImpl(); + List authorizedAPIs = authorizedAPIManagementService.getAuthorizedAPIs( + applicationBasicInfo.getApplicationResourceId(), tenantDomain); + // Return if the system APIs are already authorized for the console application. + if (!authorizedAPIs.isEmpty()) { + LOG.debug("System APIs are already authorized for the console application in tenant: " + + tenantDomain); + return; + } + // Fetch the system API resources count. + int systemAPICount = ApplicationManagementServiceComponentHolder.getInstance() + .getAPIResourceManager().getAPIResources(null, null, 1, + APIResourceManagementConstants.SYSTEM_API_FILTER, "ASC", tenantDomain).getTotalCount(); + // Fetch all system APIs. + List apiResources = ApplicationManagementServiceComponentHolder.getInstance() + .getAPIResourceManager().getAPIResources(null, null, systemAPICount, + APIResourceManagementConstants.SYSTEM_API_FILTER, "ASC", tenantDomain).getAPIResources(); + if (apiResources.isEmpty()) { + LOG.error("Error while authorizing system API console. System APIs not found in tenant: " + + tenantDomain); + return; + } + for (APIResource apiResource : apiResources) { + List scopes = ApplicationManagementServiceComponentHolder.getInstance() + .getAPIResourceManager().getAPIScopesById(apiResource.getId(), tenantDomain); + AuthorizedAPI authorizedAPI = new AuthorizedAPI.AuthorizedAPIBuilder() + .apiId(apiResource.getId()) + .appId(applicationBasicInfo.getApplicationResourceId()) + .scopes(scopes) + .policyId(APIResourceManagementConstants.RBAC_AUTHORIZATION) + .build(); + authorizedAPIManagementService.addAuthorizedAPI(applicationBasicInfo.getApplicationResourceId(), + authorizedAPI, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + } + LOG.debug("System APIs are authorized for the console application in " + tenantDomain); + } catch (Throwable e) { + LOG.error("Error while authorizing system API to the console application.", e); + } + } + + @Override + public int getDefaultOrderId() { + + return 211; + } + + @Override + public boolean isEnable() { + + return true; + } +} diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml index 142052b263f7..9ed7c0968f2d 100644 --- a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/pom.xml @@ -41,6 +41,32 @@ + + maven-resources-plugin + + + prefilter-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + system-api-resource.xml + system-api-resource.xml.j2 + p2.inf + build.properties + + + + + + + org.wso2.maven carbon-p2-plugin @@ -67,6 +93,27 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 1.1 + + + clean_target + install + + + + + + + + + run + + + + diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/build.properties b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/build.properties new file mode 100644 index 000000000000..6197d402519c --- /dev/null +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/build.properties @@ -0,0 +1,20 @@ +# +# 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. +# + +custom = true +root.api-resource-mgt=conf diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/p2.inf b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/p2.inf new file mode 100644 index 000000000000..0a51efa3d6be --- /dev/null +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/p2.inf @@ -0,0 +1,3 @@ +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.identity.api.resource.mgt.server_${feature.version}/system-api-resource.xml,target:${installFolder}/../../conf/system-api-resource.xml,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.identity.api.resource.mgt.server_${feature.version}/system-api-resource.xml.j2,target:${installFolder}/../../resources/conf/templates/repository/conf/system-api-resource.xml.j2,overwrite:true);\ diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml new file mode 100644 index 000000000000..7eb33ddbb51a --- /dev/null +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 new file mode 100644 index 000000000000..4d6e8dd5ec19 --- /dev/null +++ b/features/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt.server.feature/resources/system-api-resource.xml.j2 @@ -0,0 +1,464 @@ + + + + + {% for api_resource in api_resources %} + + + {% for scope in api_resource.scopes %} + + {% endfor %} + + + {% endfor %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 index 871acec6f5a0..ac26fa0adb50 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 @@ -1940,6 +1940,18 @@ enable="{{event.default_listener.basic_user_info_provider.enable}}"> + + + + + + {% for listener in event_listener %}