From 89f56c7575457c0dfa42772f90d7813eda7539e5 Mon Sep 17 00:00:00 2001 From: shamalka Date: Thu, 7 Dec 2023 23:00:40 +0530 Subject: [PATCH] Add sub tenant reserved user creation --- .../pom.xml | 11 ++- .../rest/api/APIApplicationServicesImpl.java | 85 ++++++++++++++++-- .../rest/api/constants/Constants.java | 2 + .../internal/APIManagerServiceDataHolder.java | 27 ++++++ .../publisher/APIPublisherServiceImpl.java | 25 +++--- .../pom.xml | 4 + .../core/internal/TenantCreateObserver.java | 86 ++++++++++++++++++- 7 files changed, 219 insertions(+), 21 deletions(-) diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml index 00e8d5c08c..f850b4c50d 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.extension.rest.api/pom.xml @@ -84,6 +84,10 @@ okhttp compile + + org.wso2.carbon + org.wso2.carbon.user.api + @@ -121,7 +125,10 @@ org.wso2.carbon.apimgt.impl;version="${carbon.api.mgt.version.range}", org.wso2.carbon.apimgt.impl.utils;version="${carbon.api.mgt.version.range}", org.wso2.carbon.apimgt.impl.internal;version="${carbon.api.mgt.version.range}", - org.json + org.json, + org.wso2.carbon.user.api, + org.wso2.carbon.context;version="4.6", + org.wso2.carbon.utils.* @@ -155,4 +162,4 @@ - \ No newline at end of file + 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/APIApplicationServicesImpl.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/APIApplicationServicesImpl.java index 05ecf1fd9e..fa0462945e 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/APIApplicationServicesImpl.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/APIApplicationServicesImpl.java @@ -19,6 +19,7 @@ package io.entgra.device.mgt.core.apimgt.extension.rest.api; import com.google.gson.Gson; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.internal.APIManagerServiceDataHolder; import org.json.JSONObject; import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.HttpsTrustManagerUtils; import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey; @@ -35,7 +36,17 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.user.api.UserRealm; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.api.UserStoreManager; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + import java.io.IOException; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; public class APIApplicationServicesImpl implements APIApplicationServices { @@ -51,9 +62,27 @@ public class APIApplicationServicesImpl implements APIApplicationServices { public APIApplicationKey createAndRetrieveApplicationCredentials() throws APIServicesException { + String serverUser = null; + String serverPassword = null; + try { + UserRealm userRealm = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm(); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + UserStoreManager userStoreManager = userRealm.getUserStoreManager(); + + createUserIfNotExists(Constants.RESERVED_USER_NAME, Constants.RESERVED_USER_PASSWORD, userStoreManager); + + if(tenantDomain.equals("carbon.super")) { + serverUser = config.getFirstProperty(Constants.SERVER_USER); + serverPassword = config.getFirstProperty(Constants.SERVER_PASSWORD); + } else { + serverUser = Constants.RESERVED_USER_NAME + "@" + tenantDomain; + serverPassword = Constants.RESERVED_USER_PASSWORD; + } + } catch (UserStoreException e) { + throw new RuntimeException(e); + } + String applicationEndpoint = config.getFirstProperty(Constants.DCR_END_POINT); - String serverUser = config.getFirstProperty(Constants.SERVER_USER); - String serverPassword = config.getFirstProperty(Constants.SERVER_PASSWORD); JSONObject jsonObject = new JSONObject(); jsonObject.put("callbackUrl", Constants.EMPTY_STRING); @@ -69,8 +98,9 @@ public class APIApplicationServicesImpl implements APIApplicationServices { .post(requestBody) .build(); try { - Response response = client.newCall(request).execute(); - return gson.fromJson(response.body().string(), APIApplicationKey.class); + try (Response response = client.newCall(request).execute()) { + return gson.fromJson(response.body().string(), APIApplicationKey.class); + } } catch (IOException e) { msg = "Error occurred while processing the response"; log.error(msg, e); @@ -82,8 +112,16 @@ public class APIApplicationServicesImpl implements APIApplicationServices { public AccessTokenInfo generateAccessTokenFromRegisteredApplication(String consumerKey, String consumerSecret) throws APIServicesException { - String userName = config.getFirstProperty(Constants.SERVER_USER); - String userPassword = config.getFirstProperty(Constants.SERVER_PASSWORD); + String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + String userName = null; + String userPassword = null; + if(tenantDomain.equals("carbon.super")) { + userName = config.getFirstProperty(Constants.SERVER_USER); + userPassword = config.getFirstProperty(Constants.SERVER_PASSWORD); + } else { + userName = "shamalka@shamalka.com"; + userPassword = "admin"; + } JSONObject params = new JSONObject(); params.put(Constants.GRANT_TYPE_PARAM_NAME, Constants.PASSWORD_GRANT_TYPE); @@ -125,4 +163,39 @@ public class APIApplicationServicesImpl implements APIApplicationServices { throw new APIServicesException(e); } } + + private void createUserIfNotExists(String username, String password, UserStoreManager userStoreManager) { + + try { + if (!userStoreManager.isExistingUser(MultitenantUtils.getTenantAwareUsername(username))) { + String[] roles = {"admin"}; + userStoreManager.addUser(MultitenantUtils.getTenantAwareUsername(username), password, roles, null, ""); + +// userStoreManager.updateCredential(MultitenantUtils.getTenantAwareUsername(username), "reservedpwd", password); + } + } catch (UserStoreException e) { + String msg = "Error when trying to fetch tenant details"; + log.error(msg); + } + } + + private String generateInitialUserPassword() { + int passwordLength = 6; + //defining the pool of characters to be used for initial password generation + String lowerCaseCharset = "abcdefghijklmnopqrstuvwxyz"; + String upperCaseCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + String numericCharset = "0123456789"; + SecureRandom randomGenerator = new SecureRandom(); + String totalCharset = lowerCaseCharset + upperCaseCharset + numericCharset; + int totalCharsetLength = totalCharset.length(); + StringBuilder initialUserPassword = new StringBuilder(); + for (int i = 0; i < passwordLength; i++) { + initialUserPassword.append( + totalCharset.charAt(randomGenerator.nextInt(totalCharsetLength))); + } + if (log.isDebugEnabled()) { + log.debug("Initial user password is created for new user: " + initialUserPassword); + } + return initialUserPassword.toString(); + } } 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 5a577e3eb1..72c28f709f 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 @@ -65,6 +65,8 @@ public final class Constants { public static final String SCOPE_API_ENDPOINT = "/api/am/publisher/v2/scopes/"; public static final String API_ENDPOINT = "/api/am/publisher/v2/apis/"; public static final String GET_ALL_APIS = "/api/am/publisher/v2/apis?limit=1000"; + public static final String RESERVED_USER_NAME = "test_reserved_user"; + public static final String RESERVED_USER_PASSWORD = "reserved_user"; } 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/internal/APIManagerServiceDataHolder.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/internal/APIManagerServiceDataHolder.java index 2779366b9d..deeeaa2a06 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/internal/APIManagerServiceDataHolder.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/internal/APIManagerServiceDataHolder.java @@ -21,12 +21,16 @@ package io.entgra.device.mgt.core.apimgt.extension.rest.api.internal; import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices; import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; +import org.wso2.carbon.user.core.service.RealmService; +import org.wso2.carbon.user.core.tenant.TenantManager; public class APIManagerServiceDataHolder { private APIApplicationServices apiApplicationServices; private APIManagerConfigurationService apiManagerConfigurationService; private PublisherRESTAPIServices publisherRESTAPIServices; + private RealmService realmService; + private TenantManager tenantManager; private static APIManagerServiceDataHolder thisInstance = new APIManagerServiceDataHolder(); @@ -63,4 +67,27 @@ public class APIManagerServiceDataHolder { public void setPublisherRESTAPIServices(PublisherRESTAPIServices publisherRESTAPIServices) { this.publisherRESTAPIServices = publisherRESTAPIServices; } + + public RealmService getRealmService() { + if (realmService == null) { + throw new IllegalStateException("Realm service is not initialized properly"); + } + return realmService; + } + + public void setRealmService(RealmService realmService) { + this.realmService = realmService; + this.setTenantManager(realmService); + } + + public TenantManager getTenantManager() { + return tenantManager; + } + + private void setTenantManager(RealmService realmService) { + if (realmService == null) { + throw new IllegalStateException("Realm service is not initialized properly"); + } + this.tenantManager = realmService.getTenantManager(); + } } 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 8630a8ecb8..3a39d9d33d 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 @@ -109,17 +109,9 @@ public class APIPublisherServiceImpl implements APIPublisherService { APIApplicationServices apiApplicationServices = APIPublisherDataHolder.getInstance().getApiApplicationServices(); PublisherRESTAPIServices publisherRESTAPIServices = APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices(); - APIApplicationKey apiApplicationKey; - AccessTokenInfo accessTokenInfo; - try { - apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(); - accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication( - apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret()); - } catch (APIServicesException e) { - String errorMsg = "Error occurred while generating the API application"; - log.error(errorMsg, e); - throw new APIManagerPublisherException(e); - } + APIApplicationKey apiApplicationKey = null; + AccessTokenInfo accessTokenInfo = null; + try { boolean tenantFound = false; @@ -151,9 +143,20 @@ public class APIPublisherServiceImpl implements APIPublisherService { } if (tenantFound) { + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(apiConfig.getOwner()); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + try { + apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(); + accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication( + apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret()); + } catch (APIServicesException e) { + String errorMsg = "Error occurred while generating the API application"; + log.error(errorMsg, e); + throw new APIManagerPublisherException(e); + } + try { apiConfig.setOwner(APIUtil.getTenantAdminUserName(tenantDomain)); apiConfig.setTenantDomain(tenantDomain); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/pom.xml b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/pom.xml index a7ab146a4a..22a3e9c021 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/pom.xml +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/pom.xml @@ -374,6 +374,10 @@ 2.3.1.wso2v1 compile + + io.entgra.device.mgt.core + io.entgra.device.mgt.core.apimgt.extension.rest.api + 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 9360428b56..47329ccf1a 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,12 +17,24 @@ */ package io.entgra.device.mgt.core.device.mgt.core.internal; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServicesImpl; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey; +import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.Scope; +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 org.apache.axis2.context.ConfigurationContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants; import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants.User; +import org.wso2.carbon.stratos.common.exception.TenantManagementClientException; +import org.wso2.carbon.tenant.mgt.exception.TenantManagementException; import org.wso2.carbon.user.api.AuthorizationManager; import org.wso2.carbon.user.api.Permission; import org.wso2.carbon.user.api.UserRealm; @@ -30,6 +42,10 @@ import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.utils.AbstractAxis2ConfigurationContextObserver; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +import java.security.SecureRandom; +import java.util.Stack; /** * Load configuration files to tenant's registry. @@ -37,6 +53,7 @@ import org.wso2.carbon.utils.multitenancy.MultitenantConstants; public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObserver { private static final Log log = LogFactory.getLog(TenantCreateObserver.class); + /** * Create configuration context. * @@ -82,6 +99,29 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser userStoreManager.updateRoleListOfUser(tenantAdminName, null, new String[] {DeviceManagementConstants.User.DEFAULT_DEVICE_ADMIN, DeviceManagementConstants.User.DEFAULT_DEVICE_USER}); + +// String password = this.generateInitialUserPassword(); + +// createUserIfNotExists("test_reserved_user", password, userStoreManager); + + + PublisherRESTAPIServices publisherRESTAPIServices = new PublisherRESTAPIServicesImpl(); + APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl(); + APIApplicationKey apiApplicationKey = null; + AccessTokenInfo accessTokenInfo = null; + try { + apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials(); + accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication( + apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret()); + } catch (APIServicesException e) { + String errorMsg = "Error occurred while generating the API application"; + log.error(errorMsg, e); + throw new TenantManagementException(errorMsg, e); + } + Scope[] scopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo); + + + if (log.isDebugEnabled()) { log.debug("Device management roles: " + User.DEFAULT_DEVICE_USER + ", " + User.DEFAULT_DEVICE_ADMIN + " created for the tenant:" + tenantDomain + "." @@ -90,8 +130,50 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser " is assigned to the role:" + User.DEFAULT_DEVICE_ADMIN + "." ); } - } catch (UserStoreException e) { + } catch (UserStoreException | TenantManagementException e) { log.error("Error occurred while creating roles for the tenant: " + tenantDomain + "."); + } catch (BadRequestException e) { + throw new RuntimeException(e); + } catch (UnexpectedResponseException e) { + throw new RuntimeException(e); + } catch (APIServicesException e) { + throw new RuntimeException(e); + } + } + + private void createUserIfNotExists(String username, String password, UserStoreManager userStoreManager) { + + try { + if (!userStoreManager.isExistingUser(MultitenantUtils.getTenantAwareUsername(username))) { + String[] roles = {"admin"}; + userStoreManager.addUser(MultitenantUtils.getTenantAwareUsername(username), password, roles, null, ""); + + userStoreManager.updateCredential(MultitenantUtils.getTenantAwareUsername(username), "reservedpwd", password); + } + } catch (UserStoreException e) { + String msg = "Error when trying to fetch tenant details"; + log.error(msg); + } + } + + private String generateInitialUserPassword() { + int passwordLength = 6; + //defining the pool of characters to be used for initial password generation + String lowerCaseCharset = "abcdefghijklmnopqrstuvwxyz"; + String upperCaseCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + String numericCharset = "0123456789"; + SecureRandom randomGenerator = new SecureRandom(); + String totalCharset = lowerCaseCharset + upperCaseCharset + numericCharset; + int totalCharsetLength = totalCharset.length(); + StringBuilder initialUserPassword = new StringBuilder(); + for (int i = 0; i < passwordLength; i++) { + initialUserPassword.append( + totalCharset.charAt(randomGenerator.nextInt(totalCharsetLength))); + } + if (log.isDebugEnabled()) { + log.debug("Initial user password is created for new user: " + initialUserPassword); } + return initialUserPassword.toString(); } -} \ No newline at end of file + +}