From 730f3aaa0793ee34adc0ae3f88cee8e0ea5fc92a Mon Sep 17 00:00:00 2001 From: Dharmakeerthi Lasantha Date: Tue, 13 Jun 2023 04:06:04 +0530 Subject: [PATCH] Improve API publishing functionality --- ...ApiApplicationRegistrationServiceImpl.java | 14 +-- .../APIManagementProviderServiceImpl.java | 84 ++++++++--------- .../publisher/APIPublisherServiceImpl.java | 91 ++++++++----------- .../application/mgt/core/util/OAuthUtils.java | 10 +- 4 files changed, 85 insertions(+), 114 deletions(-) diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension.api/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension.api/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java index f3fb909372..133a5d1a9c 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension.api/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension.api/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java @@ -59,15 +59,13 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi } String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() .getRealmConfiguration().getAdminUserName(); - //todo - PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() - .getRealmConfiguration().getAdminPassword(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( applicationName, APIUtil.getDefaultTags(), ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username, false, - ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD); + ApiApplicationConstants.DEFAULT_VALIDITY_PERIOD, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminPassword()); return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build(); } catch (APIManagerException e) { String msg = "Error occurred while registering an application '" + applicationName + "'"; @@ -110,12 +108,10 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi if (username.equals(registrationProfile.getUsername())) { synchronized (ApiApplicationRegistrationServiceImpl.class) { - //todo - registrationProfile.getPassword(); ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( applicationName, registrationProfile.getTags(), ApiApplicationConstants.DEFAULT_TOKEN_TYPE, username, - registrationProfile.isAllowedToAllDomains(), validityPeriod); + registrationProfile.isAllowedToAllDomains(), validityPeriod, registrationProfile.getPassword()); return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build(); } } @@ -123,13 +119,11 @@ public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegi PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext. getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName()); - //todo - registrationProfile.getPassword(); synchronized (ApiApplicationRegistrationServiceImpl.class) { ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( applicationName, registrationProfile.getTags(), ApiApplicationConstants.DEFAULT_TOKEN_TYPE, registrationProfile.getUsername(), - registrationProfile.isAllowedToAllDomains(), validityPeriod); + registrationProfile.isAllowedToAllDomains(), validityPeriod, registrationProfile.getPassword()); return Response.status(Response.Status.CREATED).entity(apiApplicationKey.toString()).build(); } } catch (APIManagerException e) { diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/APIManagementProviderServiceImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/APIManagementProviderServiceImpl.java index 6ab71de887..66ba639ea0 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/APIManagementProviderServiceImpl.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.application.extension/src/main/java/io/entgra/device/mgt/core/apimgt/application/extension/APIManagementProviderServiceImpl.java @@ -45,7 +45,6 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.Unexpected import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.eclipse.jetty.http.MetaData; import org.wso2.carbon.apimgt.api.APIAdmin; import org.wso2.carbon.apimgt.api.APIConsumer; import org.wso2.carbon.apimgt.api.APIManagementException; @@ -64,7 +63,14 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; /** * This class represents an implementation of APIManagementProviderService. @@ -197,6 +203,11 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe throw new APIManagerException(msg); } String[] metaValues = metaData.getMetaValue().split(":"); + if (metaValues.length != 2) { + String msg = "Found invalid Meta value for meta key: " + applicationName; + log.error(msg); + throw new APIManagerException(msg); + } String applicationId = metaValues[0]; String keyMappingId = metaValues[1]; //todo call the API key retrieving call, return apiApplicationKey; @@ -296,41 +307,29 @@ Otherwise, Generate Application Keys and return them } try { APIConsumer apiConsumer = API_MANAGER_FACTORY.getAPIConsumer(username); - Application application = null; // todo:apim - apiConsumer.getApplicationsByName(username, applicationName, ""); -// cnt rm -// // curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://localhost:9443/api/am/devportal/v3/applications?query=CalculatorApp" - + Application application = null; // todo:resolve:apim - apiConsumer.getApplicationsByName(username, applicationName, ""); int applicationId = 0; Subscriber subscriber = null; if (application == null) { - subscriber = null; // todo:apim - apiConsumer.getSubscriber(username); -// cnt rm + subscriber = null; // todo:resolve:apim - apiConsumer.getSubscriber(username); if (subscriber == null) { // create subscriber - // todo:apim - apiConsumer.addSubscriber(username, ""); -// cnt rm - subscriber = null; // todo:apim - apiConsumer.getSubscriber(username); -// cnt rm + // todo:resolve:apim - apiConsumer.addSubscriber(username, ""); + subscriber = null; // todo:resolve:apim - apiConsumer.getSubscriber(username); } //create application application = new Application(applicationName, subscriber); application.setTier(ApiApplicationConstants.DEFAULT_TIER); application.setGroupId(""); application.setTokenType("OAUTH"); - // todo:apim - apiConsumer.addApplication(application, username); -// cnt rm - application = null; // todo:apim - apiConsumer.getApplicationsByName(username, applicationName, ""); -// cnt rm + // todo:resolve:apim - apiConsumer.addApplication(application, username); + application = null; // todo:resolve:apim - apiConsumer.getApplicationsByName(username, applicationName, ""); } else { - subscriber = null; // todo:apim - apiConsumer.getSubscriber(username); -// cnt rm + subscriber = null; // todo:resolve:apim - apiConsumer.getSubscriber(username); } Set subscribedAPIs = - null; // todo:apim - apiConsumer.getSubscribedAPIs(subscriber, applicationName, ""); - - //curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://localhost:9443/api/am/devportal/v3/subscriptions?apiId=02e658e7-71c7-4b1d-a623-be145b789340" -// cnt rm + null; // todo:resolve:apim - apiConsumer.getSubscribedAPIs(subscriber, applicationName, ""); log.info("Already subscribed API count: " + subscribedAPIs.size()); @@ -339,9 +338,7 @@ Otherwise, Generate Application Keys and return them if (tags != null && tags.length > 0) { for (String tag : tags) { boolean startedTenantFlow = false; - Set apisWithTag = null; // todo:apim - apiConsumer.getAPIsWithTag(tag, tenantDomain); -// curl -k "https://localhost:9443/api/am/devportal/v3/apis" -// cnt rm + Set apisWithTag = null; // todo:resolve:apim - apiConsumer.getAPIsWithTag(tag, tenantDomain); /** * From APIM 4.0.0, APIs published in the super tenant can only be listed by @@ -364,8 +361,7 @@ Otherwise, Generate Application Keys and return them ". Caused by to inability to get super tenant username", e); } - apisWithTag = null; // todo:apim - apiConsumerAPIPublishedTenant.getAPIsWithTag(tag, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); -// cnt rm + apisWithTag = null; // todo:resolve:apim - apiConsumerAPIPublishedTenant.getAPIsWithTag(tag, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); startedTenantFlow = true; } @@ -378,8 +374,7 @@ Otherwise, Generate Application Keys and return them boolean subscriptionExist = false; if (subscribedAPIs.size() > 0) { for (SubscribedAPI subscribedAPI : subscribedAPIs) { - // todo:apim -// cnt rm + // todo:resolve:apim // if (String.valueOf(subscribedAPI.getApiId().toString()).equals(id)) { // subscriptionExist = true; // break; @@ -422,8 +417,7 @@ Otherwise, Generate Application Keys and return them * Oauth app for a child tenant. */ for (ApiTypeWrapper apiTypeWrapper : apiTypeWrapperList) { - // todo:apim - apiConsumer.addSubscription(apiTypeWrapper, username, application); -// cnt rm + // todo:resolve:apim - apiConsumer.addSubscription(apiTypeWrapper, username, application); } } } @@ -454,7 +448,7 @@ Otherwise, Generate Application Keys and return them APIAdmin apiAdmin = new APIAdminImpl(); String keyManagerId = null; try { - List keyManagerConfigurations = null; // todo:apim - + List keyManagerConfigurations = null; // todo:resolve:apim - // apiAdmin.getKeyManagerConfigurationsByTenant(tenantDomain); if (keyManagerConfigurations != null) { for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keyManagerConfigurations) { @@ -474,7 +468,7 @@ Otherwise, Generate Application Keys and return them "\\\"id_token_expiry_time\\\":\\\"N\\/A\\\"}\"," + "\"username\":\"" + username + "\"}"; - Map keyDetails = null; // todo:apim - apiConsumer + Map keyDetails = null; // todo:resolve:apim - apiConsumer // .requestApprovalForApplicationRegistration(username, applicationName, keyType, "", // allowedDomains.toArray(new String[allowedDomains.size()]), validityTime, "default", "", // jsonString, keyManagerId, tenantDomain); @@ -486,7 +480,7 @@ Otherwise, Generate Application Keys and return them return apiApplicationKey; } throw new APIManagerException("Failed to generate keys for tenant: " + tenantDomain); -// todo:apim - commected as it says never throw since we commented apim calls above +// todo:resolve:apim - commected as it says never throw since we commented apim calls above // cnt rm // } catch (APIManagementException e) { } catch (Exception e) { @@ -525,11 +519,10 @@ Otherwise, Generate Application Keys and return them JWTClientManagerService jwtClientManagerService = APIApplicationManagerExtensionDataHolder.getInstance() .getJwtClientManagerService(); JWTClient jwtClient = jwtClientManagerService.getJWTClient(); - AccessTokenInfo accessTokenForAdmin = jwtClient + + return jwtClient .getAccessToken(clientCredentials.getConsumerKey(), clientCredentials.getConsumerSecret(), username, scopes); - - return accessTokenForAdmin; } catch (JWTClientException e) { String msg = "JWT Error occurred while registering Application to get access token."; log.error(msg, e); @@ -546,7 +539,8 @@ Otherwise, Generate Application Keys and return them } /** - * Get Client credentials + * Get Client credentials of application belongs to tenant admin + * * @param tenantDomain Tenant Domain * @param tags Tags * @param applicationName Application Name @@ -554,7 +548,7 @@ Otherwise, Generate Application Keys and return them * @param validityPeriod Validity Period * @return {@link ApiApplicationKey} * @throws APIManagerException if error occurred while generating access token - * @throws UserStoreException if error ocurred while getting admin username. + * @throws UserStoreException if error occurred while getting admin username. */ private ApiApplicationKey getClientCredentials(String tenantDomain, String[] tags, String applicationName, String tokenType, String validityPeriod) throws APIManagerException, UserStoreException { @@ -565,7 +559,6 @@ Otherwise, Generate Application Keys and return them registrationProfile.setTags(tags); registrationProfile.setApplicationName(applicationName); - ApiApplicationKey info = null; if (tenantDomain == null || tenantDomain.isEmpty()) { tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME; } @@ -576,15 +569,14 @@ Otherwise, Generate Application Keys and return them PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration() .getAdminUserName()); - if (registrationProfile.getUsername() == null || registrationProfile.getUsername().isEmpty()) { - info = generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(), - registrationProfile.getTags(), tokenType, null, - registrationProfile.isAllowedToAllDomains(), validityPeriod); - } + return generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(), + registrationProfile.getTags(), tokenType, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminUserName(), + registrationProfile.isAllowedToAllDomains(), validityPeriod, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminPassword()); } finally { PrivilegedCarbonContext.endTenantFlow(); } - return info; } private ApiApplicationInfo getApplicationInfo(String username, String password) diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java index 8d30d3daf2..fe98a8cef8 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -153,17 +153,8 @@ public class APIPublisherServiceImpl implements APIPublisherService { } if (!apiFound) { // add new scopes as shared scopes - for (ApiScope apiScope : apiConfig.getScopes()) { - if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, - apiScope.getKey())) { - Scope scope = new Scope(); - scope.setName(apiScope.getName()); - scope.setDescription(apiScope.getDescription()); - scope.setKey(apiScope.getKey()); - scope.setRoles(apiScope.getRoles()); - publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope); - } - } + addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices, apiApplicationKey, + accessTokenInfo); APIInfo api = getAPI(apiConfig, true); JSONObject createdAPI = publisherRESTAPIServices.addAPI(apiApplicationKey, accessTokenInfo, api); if (apiConfig.getEndpointType() != null && "WS".equals(apiConfig.getEndpointType())) { @@ -202,7 +193,6 @@ public class APIPublisherServiceImpl implements APIPublisherService { } } else { if (WebappPublisherConfig.getInstance().isEnabledUpdateApi()) { - // With 4.x to 5.x upgrade // - there cannot be same local scope assigned in 2 different APIs // - local scopes will be deprecated in the future, so need to move all scopes as shared scopes @@ -217,50 +207,17 @@ public class APIPublisherServiceImpl implements APIPublisherService { // 1. add new scopes as shared scopes // 2. update the API adding scopes for the URI Templates - Set scopesToMoveAsSharedScopes = new HashSet<>(); - for (ApiScope apiScope : apiConfig.getScopes()) { - // if the scope is not available as shared scope, and it is assigned to an API as a local scope - // need remove the local scope and add as a shared scope - if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, - apiScope.getKey())) { - //resolve- todo:apim- resolve -// if (apiProvider.isScopeKeyAssignedLocally(apiIdentifier, apiScope.getKey(), tenantId)) { - if (true) { - // collect scope to move as shared scopes - scopesToMoveAsSharedScopes.add(apiScope); - } else { - // if new scope add as shared scope - Scope scope = new Scope(); - scope.setName(apiScope.getName()); - scope.setDescription(apiScope.getDescription()); - scope.setKey(apiScope.getKey()); - scope.setRoles(apiScope.getRoles()); - publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope); + // It is guaranteed that there is no local scope if we update from 5.0.0 to the most + // recent version. Therefore, if the scope is not already available as a shared scope, + // new scopes must be added as shared scopes. Additionally, it is necessary to + // upgrade to 5.0.0 first before updating from 5.0.0 to the most recent version if we + // are updating from a version that is older than 5.0.0. - } - } - } + addNewSharedScope(apiConfig.getScopes(), publisherRESTAPIServices, apiApplicationKey, + accessTokenInfo); - // Get existing API - JSONObject existingAPI = publisherRESTAPIServices.getApi(apiApplicationKey, accessTokenInfo, - apiIdentifier); - if (scopesToMoveAsSharedScopes.size() > 0) { - // update API to remove local scopes - APIInfo api = getAPI(apiConfig, false); - api.setLifeCycleStatus(existingAPI.getString("lifeCycleStatus")); - publisherRESTAPIServices.updateApi(apiApplicationKey, accessTokenInfo, api); - - for (ApiScope apiScope : scopesToMoveAsSharedScopes) { - Scope scope = new Scope(); - scope.setName(apiScope.getName()); - scope.setDescription(apiScope.getDescription()); - scope.setKey(apiScope.getKey()); - scope.setRoles(apiScope.getRoles()); - publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope); - } - } - - existingAPI = publisherRESTAPIServices.getApi(apiApplicationKey, accessTokenInfo, apiIdentifier); + JSONObject existingAPI = publisherRESTAPIServices.getApi(apiApplicationKey, + accessTokenInfo, apiIdentifier); APIInfo api = getAPI(apiConfig, true); api.setLastUpdatedTime(existingAPI.getString("lifeCycleStatus")); api.setId(existingAPI.getString("id")); @@ -408,6 +365,32 @@ public class APIPublisherServiceImpl implements APIPublisherService { } } + /** + * Add new Shared Scopes + * + * @param apiScopes set of API scopes + * @param publisherRESTAPIServices {@link PublisherRESTAPIServices} + * @param apiApplicationKey API application Key + * @param accessTokenInfo Details of access token + * @throws BadRequestException if invalid payload receives to add new shared scopes. + * @throws UnexpectedResponseException if the response is not either 200 or 400. + * @throws APIServicesException if error occurred while processing the response. + */ + private void addNewSharedScope(Set apiScopes, PublisherRESTAPIServices publisherRESTAPIServices, + APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo) throws BadRequestException, UnexpectedResponseException, APIServicesException { + for (ApiScope apiScope : apiScopes) { + if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, + apiScope.getKey())) { + Scope scope = new Scope(); + scope.setName(apiScope.getName()); + scope.setDescription(apiScope.getDescription()); + scope.setKey(apiScope.getKey()); + scope.setRoles(apiScope.getRoles()); + publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope); + } + } + } + @Override public void updateScopeRoleMapping() throws APIManagerPublisherException { diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/OAuthUtils.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/OAuthUtils.java index 272a5b45b0..c5975cb500 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/OAuthUtils.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/OAuthUtils.java @@ -55,16 +55,18 @@ public class OAuthUtils { try { PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext. - getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName()); + String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminUserName(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username); PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); APIManagementProviderService apiManagementProviderService = (APIManagementProviderService) ctx. getOSGiService(APIManagementProviderService.class, null); apiApplicationKeyInfo = apiManagementProviderService. generateAndRetrieveApplicationKeys(registrationProfile.getApplicationName(), registrationProfile.getTags(), Constants.ApplicationInstall.DEFAULT_TOKEN_TYPE, - null, registrationProfile.isAllowedToAllDomains(), - Constants.ApplicationInstall.DEFAULT_VALIDITY_PERIOD); + username, registrationProfile.isAllowedToAllDomains(), + Constants.ApplicationInstall.DEFAULT_VALIDITY_PERIOD, PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() + .getRealmConfiguration().getAdminPassword()); } finally { PrivilegedCarbonContext.endTenantFlow(); }