|
|
@ -17,23 +17,27 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
package io.entgra.device.mgt.core.device.mgt.core.internal;
|
|
|
|
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.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.PublisherRESTAPIServices;
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServicesImpl;
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.constants.Constants;
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
|
|
|
|
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.APIInfo.Scope;
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
|
|
|
|
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.APIServicesException;
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
|
|
|
|
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.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
|
|
|
|
|
|
|
|
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.APIPublisherUtils;
|
|
|
|
|
|
|
|
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.axis2.context.ConfigurationContext;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
|
|
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;
|
|
|
|
import io.entgra.device.mgt.core.device.mgt.core.DeviceManagementConstants.User;
|
|
|
|
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.tenant.mgt.exception.TenantManagementException;
|
|
|
|
import org.wso2.carbon.user.api.AuthorizationManager;
|
|
|
|
import org.wso2.carbon.user.api.AuthorizationManager;
|
|
|
|
import org.wso2.carbon.user.api.Permission;
|
|
|
|
import org.wso2.carbon.user.api.Permission;
|
|
|
@ -44,19 +48,18 @@ import org.wso2.carbon.utils.AbstractAxis2ConfigurationContextObserver;
|
|
|
|
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
|
|
|
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
|
|
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
|
|
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
|
|
|
|
|
|
|
|
|
|
|
import java.security.SecureRandom;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Stack;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Load configuration files to tenant's registry.
|
|
|
|
* Load configuration files to tenant's registry.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObserver {
|
|
|
|
public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObserver {
|
|
|
|
private static final Log log = LogFactory.getLog(TenantCreateObserver.class);
|
|
|
|
private static final Log log = LogFactory.getLog(TenantCreateObserver.class);
|
|
|
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
private String msg = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Create configuration context.
|
|
|
|
* Create configuration context.
|
|
|
@ -104,32 +107,18 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
|
|
|
|
new String[] {DeviceManagementConstants.User.DEFAULT_DEVICE_ADMIN,
|
|
|
|
new String[] {DeviceManagementConstants.User.DEFAULT_DEVICE_ADMIN,
|
|
|
|
DeviceManagementConstants.User.DEFAULT_DEVICE_USER});
|
|
|
|
DeviceManagementConstants.User.DEFAULT_DEVICE_USER});
|
|
|
|
|
|
|
|
|
|
|
|
// String password = this.generateInitialUserPassword();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// createUserIfNotExists("test_reserved_user", password, userStoreManager);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Thread thread = new Thread(new Runnable() {
|
|
|
|
Thread thread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
createApplication(tenantDomain);
|
|
|
|
publishScopesToTenant(tenantDomain);
|
|
|
|
} catch (TenantManagementException e) {
|
|
|
|
} catch (TenantManagementException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
log.error("Error occurred while generating API application for the tenant: " + tenantDomain + ".");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
thread.start();
|
|
|
|
thread.start();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// executor.submit(() -> {
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
|
|
// createApplication();
|
|
|
|
|
|
|
|
// } catch (TenantManagementException e) {
|
|
|
|
|
|
|
|
// throw new RuntimeException(e);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
log.debug("Device management roles: " + User.DEFAULT_DEVICE_USER + ", " + User.DEFAULT_DEVICE_ADMIN +
|
|
|
|
log.debug("Device management roles: " + User.DEFAULT_DEVICE_USER + ", " + User.DEFAULT_DEVICE_ADMIN +
|
|
|
|
" created for the tenant:" + tenantDomain + "."
|
|
|
|
" created for the tenant:" + tenantDomain + "."
|
|
|
@ -143,61 +132,307 @@ public class TenantCreateObserver extends AbstractAxis2ConfigurationContextObser
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* This method will create OAuth application under the given tenant domain and generate an access token against the
|
|
|
|
|
|
|
|
* client credentials. Once this access token is generated it will then be used to retrieve all the scopes that are already
|
|
|
|
|
|
|
|
* published to that tenant space. The scopes of the super tenant will also be retrieved in order to compare which scopes were added
|
|
|
|
|
|
|
|
* or removed. (A temporary admin user will be created in the sub tenant space to publish the scopes and will be deleted once
|
|
|
|
|
|
|
|
* the scope publishing task is done)
|
|
|
|
|
|
|
|
* @param tenantDomain tenant domain that the scopes will be published to.
|
|
|
|
|
|
|
|
* @throws TenantManagementException if there are any errors when publishing scopes to a tenant
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void publishScopesToTenant(String tenantDomain) throws TenantManagementException {
|
|
|
|
|
|
|
|
if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MetadataManagementService metadataManagementService = DeviceManagementDataHolder.getInstance().getMetadataManagementService();
|
|
|
|
|
|
|
|
|
|
|
|
private void createApplication(String tenantDomain) throws TenantManagementException {
|
|
|
|
Map<String, String> superTenantPermScopeMapping = getPermScopeMapping(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
|
|
|
|
PrivilegedCarbonContext.startTenantFlow();
|
|
|
|
Map<String, String> subTenantPermScopeMapping = getPermScopeMapping(tenantDomain);
|
|
|
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PublisherRESTAPIServices publisherRESTAPIServices = new PublisherRESTAPIServicesImpl();
|
|
|
|
if (superTenantPermScopeMapping == null) {
|
|
|
|
APIApplicationServices apiApplicationServices = new APIApplicationServicesImpl();
|
|
|
|
msg = "Error occurred while retrieving meta key '" + Constants.PERM_SCOPE_MAPPING_META_KEY + "' for tenant '" +
|
|
|
|
APIApplicationKey apiApplicationKey = null;
|
|
|
|
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME + "'. Hence aborting publishing scopes to tenant: '" +
|
|
|
|
AccessTokenInfo accessTokenInfo = null;
|
|
|
|
tenantDomain + "'.";
|
|
|
|
try {
|
|
|
|
log.error(msg);
|
|
|
|
apiApplicationServices.createAndRetrieveApplicationCredentialsAndGenerateToken();
|
|
|
|
throw new TenantManagementException(msg);
|
|
|
|
// log.error("apiApplicationKey: " + apiApplicationKey.getClientId());
|
|
|
|
}
|
|
|
|
// log.error("apiApplicationKey: " + apiApplicationKey.getClientSecret());
|
|
|
|
if (superTenantPermScopeMapping.equals(subTenantPermScopeMapping)) {
|
|
|
|
// accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
// apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
|
|
|
|
log.debug( "Scopes in '" + tenantDomain + "' are up to date with super tenant scopes.");
|
|
|
|
} catch (APIServicesException e) {
|
|
|
|
}
|
|
|
|
String errorMsg = "Error occurred while generating the API application";
|
|
|
|
return;
|
|
|
|
log.error(errorMsg, e);
|
|
|
|
}
|
|
|
|
throw new TenantManagementException(errorMsg, e);
|
|
|
|
|
|
|
|
|
|
|
|
APIApplicationServices apiApplicationServices = DeviceManagementDataHolder.getInstance().getApiApplicationServices();
|
|
|
|
|
|
|
|
APIApplicationKey apiApplicationKey;
|
|
|
|
|
|
|
|
AccessTokenInfo accessTokenInfo;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.startTenantFlow();
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
APIPublisherUtils.createScopePublishUserIfNotExists(tenantDomain);
|
|
|
|
|
|
|
|
apiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials();
|
|
|
|
|
|
|
|
accessTokenInfo = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
|
|
|
|
|
|
|
|
apiApplicationKey.getClientId(), apiApplicationKey.getClientSecret());
|
|
|
|
|
|
|
|
} catch (APIServicesException e) {
|
|
|
|
|
|
|
|
msg = "Error occurred while generating the API application for tenant: '" + tenantDomain + "'.";
|
|
|
|
|
|
|
|
log.error(msg, e);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg, e);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
PublisherRESTAPIServices publisherRESTAPIServices = DeviceManagementDataHolder.getInstance().getPublisherRESTAPIServices();
|
|
|
|
|
|
|
|
Scope[] superTenantScopes = getAllScopesFromSuperTenant(apiApplicationServices, publisherRESTAPIServices);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (superTenantScopes != null) {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Number of super tenant scopes already published - " + superTenantScopes.length);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Scope[] subTenantScopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (subTenantScopes.length > 0) {
|
|
|
|
|
|
|
|
// If there is already existing scopes on the sub tenant space then do a comparison with the
|
|
|
|
|
|
|
|
// super tenant scopes to add those new scopes to sub tenant space or to delete them from
|
|
|
|
|
|
|
|
// sub tenant space if it is not existing on the super tenant scope list.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Number of sub tenant scopes already published - " + subTenantScopes.length);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Scope> missingScopes = new ArrayList<>();
|
|
|
|
|
|
|
|
List<Scope> deletedScopes = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (Scope superTenantScope : superTenantScopes) {
|
|
|
|
|
|
|
|
boolean isMatchingScope = false;
|
|
|
|
|
|
|
|
for (Scope subTenantScope : subTenantScopes) {
|
|
|
|
|
|
|
|
if (superTenantScope.getName().equals(subTenantScope.getName())) {
|
|
|
|
|
|
|
|
isMatchingScope = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isMatchingScope) {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Missing scope found in sub tenant space - " +
|
|
|
|
|
|
|
|
superTenantScope.getName());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
missingScopes.add(superTenantScope);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Total number of missing scopes found in sub tenant space - " +
|
|
|
|
|
|
|
|
missingScopes.size());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (missingScopes.size() > 0) {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Starting to add new/updated shared scopes to the tenant: '" + tenantDomain + "'.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
publishSharedScopes(missingScopes, publisherRESTAPIServices, apiApplicationKey,
|
|
|
|
|
|
|
|
accessTokenInfo);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (Scope subTenantScope : subTenantScopes) {
|
|
|
|
|
|
|
|
boolean isMatchingScope = false;
|
|
|
|
|
|
|
|
for (Scope superTenantScope : superTenantScopes) {
|
|
|
|
|
|
|
|
if (superTenantScope.getName().equals(subTenantScope.getName())) {
|
|
|
|
|
|
|
|
isMatchingScope = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isMatchingScope) {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Deleted scope found in sub tenant space - " +
|
|
|
|
|
|
|
|
subTenantScope.getName());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
deletedScopes.add(subTenantScope);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Total number of deleted scopes found in sub tenant space - " +
|
|
|
|
|
|
|
|
deletedScopes.size());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (deletedScopes.size() > 0) {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Starting to delete shared scopes from the tenant: '" + tenantDomain + "'.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Scope deletedScope : deletedScopes) {
|
|
|
|
|
|
|
|
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
|
|
|
|
|
|
|
|
deletedScope.getName())) {
|
|
|
|
|
|
|
|
Scope scope = createScopeObject(deletedScope);
|
|
|
|
|
|
|
|
publisherRESTAPIServices.deleteSharedScope(apiApplicationKey, accessTokenInfo, scope);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
msg = "Unable to publish scopes to sub tenants due to super tenant scopes list being empty.";
|
|
|
|
|
|
|
|
log.error(msg);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (BadRequestException e) {
|
|
|
|
|
|
|
|
msg = "Invalid request sent when publishing scopes to '" + tenantDomain + "' tenant space.";
|
|
|
|
|
|
|
|
log.error(msg, e);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg, e);
|
|
|
|
|
|
|
|
} catch (UnexpectedResponseException e) {
|
|
|
|
|
|
|
|
msg = "Unexpected response received when publishing scopes to '" + tenantDomain + "' tenant space.";
|
|
|
|
|
|
|
|
log.error(msg, e);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg, e);
|
|
|
|
|
|
|
|
} catch (APIServicesException e) {
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
|
|
|
APIPublisherUtils.removeScopePublishUserIfExists(tenantDomain);
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.endTenantFlow();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Scope[] scopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void createUserIfNotExists(String username, String password, UserStoreManager userStoreManager) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* This method will retrieve the value of the permission scope mapping meta key stored in each tenant's metadata
|
|
|
|
|
|
|
|
* @param tenantDomain the tenant domain that the permission scope mapping meta value retrieved from
|
|
|
|
|
|
|
|
* @return {@link Map} containing the permission key and the scope value
|
|
|
|
|
|
|
|
* @throws TenantManagementException if there is an error while retrieving permission scope metadata
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private Map<String, String> getPermScopeMapping(String tenantDomain) throws TenantManagementException {
|
|
|
|
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
|
|
|
|
log.debug("Retrieving permission scope mapping from metadata from the tenant: '" + tenantDomain + "'.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, String> permScopeMapping = null;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
if (!userStoreManager.isExistingUser(MultitenantUtils.getTenantAwareUsername(username))) {
|
|
|
|
PrivilegedCarbonContext.startTenantFlow();
|
|
|
|
String[] roles = {"admin"};
|
|
|
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
|
|
|
|
userStoreManager.addUser(MultitenantUtils.getTenantAwareUsername(username), password, roles, null, "");
|
|
|
|
MetadataManagementService metadataManagementService = DeviceManagementDataHolder.getInstance().getMetadataManagementService();
|
|
|
|
|
|
|
|
Metadata metadata = metadataManagementService.retrieveMetadata(Constants.PERM_SCOPE_MAPPING_META_KEY);
|
|
|
|
userStoreManager.updateCredential(MultitenantUtils.getTenantAwareUsername(username), "reservedpwd", password);
|
|
|
|
if (metadata != null) {
|
|
|
|
|
|
|
|
permScopeMapping = new Gson().fromJson(metadata.getMetaValue().toString(), HashMap.class);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (UserStoreException e) {
|
|
|
|
} catch (MetadataManagementException e) {
|
|
|
|
String msg = "Error when trying to fetch tenant details";
|
|
|
|
msg = "Error occurred while retrieving permission scope mapping from metadata for tenant: '" + tenantDomain + "'.";
|
|
|
|
log.error(msg);
|
|
|
|
log.error(msg, e);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg, e);
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.endTenantFlow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return permScopeMapping;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private String generateInitialUserPassword() {
|
|
|
|
/**
|
|
|
|
int passwordLength = 6;
|
|
|
|
* This method will create a new metadata entry or update the existing metadata entry in the sub tenant metadata repository which is
|
|
|
|
//defining the pool of characters to be used for initial password generation
|
|
|
|
* taken from the super tenant metadata
|
|
|
|
String lowerCaseCharset = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
* @param superTenantPermScopeMapping {@link Map} containing the permission key and the scope value of the super tenant
|
|
|
|
String upperCaseCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
* @param metadataManagementService {@link MetadataManagementService} instance
|
|
|
|
String numericCharset = "0123456789";
|
|
|
|
* @throws MetadataManagementException if there is an error while creating or updating the metadata entry
|
|
|
|
SecureRandom randomGenerator = new SecureRandom();
|
|
|
|
* @throws MetadataKeyAlreadyExistsException if the metadata key already exists while trying to create a new metadata entry
|
|
|
|
String totalCharset = lowerCaseCharset + upperCaseCharset + numericCharset;
|
|
|
|
*/
|
|
|
|
int totalCharsetLength = totalCharset.length();
|
|
|
|
private void updatePermScopeMetaData(Map<String, String> superTenantPermScopeMapping,
|
|
|
|
StringBuilder initialUserPassword = new StringBuilder();
|
|
|
|
MetadataManagementService metadataManagementService) throws MetadataManagementException,
|
|
|
|
for (int i = 0; i < passwordLength; i++) {
|
|
|
|
MetadataKeyAlreadyExistsException {
|
|
|
|
initialUserPassword.append(
|
|
|
|
|
|
|
|
totalCharset.charAt(randomGenerator.nextInt(totalCharsetLength)));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (log.isDebugEnabled()) {
|
|
|
|
}
|
|
|
|
log.debug("Initial user password is created for new user: " + initialUserPassword);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 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
|
|
|
|
|
|
|
|
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices} is used to get all scopes under a given tenant using client credentials
|
|
|
|
|
|
|
|
* @return array of {@link Scope}
|
|
|
|
|
|
|
|
* @throws BadRequestException if an invalid request is sent to the API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
* @throws UnexpectedResponseException if an unexpected response is received from the API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
* @throws TenantManagementException if an error occurred while processing the request sent to API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private Scope[] getAllScopesFromSuperTenant(APIApplicationServices apiApplicationServices,
|
|
|
|
|
|
|
|
PublisherRESTAPIServices publisherRESTAPIServices) throws BadRequestException,
|
|
|
|
|
|
|
|
UnexpectedResponseException, TenantManagementException {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
// Get all scopes of super tenant to compare later with the sub tenant scopes. This is done
|
|
|
|
|
|
|
|
// in order to see if any new scopes were added or deleted
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.startTenantFlow();
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
|
|
|
|
|
|
|
|
APIApplicationKey superTenantApiApplicationKey = apiApplicationServices.createAndRetrieveApplicationCredentials();
|
|
|
|
|
|
|
|
AccessTokenInfo superTenantAccessToken = apiApplicationServices.generateAccessTokenFromRegisteredApplication(
|
|
|
|
|
|
|
|
superTenantApiApplicationKey.getClientId(), superTenantApiApplicationKey.getClientSecret());
|
|
|
|
|
|
|
|
return publisherRESTAPIServices.getScopes(superTenantApiApplicationKey, superTenantAccessToken);
|
|
|
|
|
|
|
|
} catch (APIServicesException e) {
|
|
|
|
|
|
|
|
msg = "Error occurred while retrieving access token from super tenant";
|
|
|
|
|
|
|
|
log.error(msg, e);
|
|
|
|
|
|
|
|
throw new TenantManagementException(msg, e);
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
PrivilegedCarbonContext.endTenantFlow();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Add shared scopes to the tenant space.
|
|
|
|
|
|
|
|
* @param scopeList {@link List} of {@link Scope}
|
|
|
|
|
|
|
|
* @param publisherRESTAPIServices {@link PublisherRESTAPIServices} is used to add shared scopes to a given tenant using client credentials
|
|
|
|
|
|
|
|
* @param apiApplicationKey {@link APIApplicationKey} contains client credentials of the OAuth application
|
|
|
|
|
|
|
|
* @param accessTokenInfo {@link AccessTokenInfo} contains token information generated from the client credentials
|
|
|
|
|
|
|
|
* @throws BadRequestException if an invalid request is sent to the API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
* @throws UnexpectedResponseException if an unexpected response is received from the API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
* @throws APIServicesException if an error occurred while processing the request sent to API Manager Publisher REST API Service
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void publishSharedScopes (List<Scope> scopeList, PublisherRESTAPIServices publisherRESTAPIServices,
|
|
|
|
|
|
|
|
APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo)
|
|
|
|
|
|
|
|
throws BadRequestException, UnexpectedResponseException, APIServicesException {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (Scope tenantScope : scopeList) {
|
|
|
|
|
|
|
|
if (!publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
|
|
|
|
|
|
|
|
tenantScope.getName())) {
|
|
|
|
|
|
|
|
Scope scope = createScopeObject(tenantScope);
|
|
|
|
|
|
|
|
publisherRESTAPIServices.addNewSharedScope(apiApplicationKey, accessTokenInfo, scope);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return initialUserPassword.toString();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Creates a new scope object from the passed scope which includes the id, display name, description, name and bindings.
|
|
|
|
|
|
|
|
* @param tenantScope existing {@link Scope} from a tenant
|
|
|
|
|
|
|
|
* @return {@link Scope}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private Scope createScopeObject (Scope tenantScope) {
|
|
|
|
|
|
|
|
Scope scope = new Scope();
|
|
|
|
|
|
|
|
scope.setId(tenantScope.getId());
|
|
|
|
|
|
|
|
scope.setDisplayName(tenantScope.getDisplayName());
|
|
|
|
|
|
|
|
scope.setDescription(tenantScope.getDescription());
|
|
|
|
|
|
|
|
scope.setName(tenantScope.getName());
|
|
|
|
|
|
|
|
List<String> bindings = new ArrayList<>();
|
|
|
|
|
|
|
|
bindings.add(Constants.ADMIN_ROLE_KEY);
|
|
|
|
|
|
|
|
scope.setBindings(bindings);
|
|
|
|
|
|
|
|
return scope;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|