diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java index cc0bb20a9f7..641605b87a3 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/ApiApplicationRegistrationServiceImpl.java @@ -42,12 +42,12 @@ import javax.ws.rs.core.Response; public class ApiApplicationRegistrationServiceImpl implements ApiApplicationRegistrationService { private static final Log log = LogFactory.getLog(ApiApplicationRegistrationServiceImpl.class); - @Path("register/tenants/{tenantDomain}") + @Path("register/tenants") @POST - public Response register(@PathParam("tenantDomain") String tenantDomain, + public Response register(@QueryParam("tenantDomain") String tenantDomain, @QueryParam("applicationName") String applicationName) { String authenticatedTenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); - if (authenticatedTenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + if (!authenticatedTenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { return Response.status(Response.Status.NOT_ACCEPTABLE).build(); } try { diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java index 1395566b70b..7f9e3e8dd94 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/java/org/wso2/carbon/apimgt/application/extension/api/filter/ApiPermissionFilter.java @@ -21,7 +21,7 @@ import java.util.List; /** * this filter check for permission for the request */ -public class ApiPermissionFilter implements Filter{ +public class ApiPermissionFilter implements Filter { private static final Log log = LogFactory.getLog(ApiPermissionFilter.class); private static final String UI_EXECUTE = "ui.execute"; private static final String PERMISSION_CONFIG_PATH = File.separator + "META-INF" + File.separator @@ -53,16 +53,9 @@ public class ApiPermissionFilter implements Filter{ if (servletRequest instanceof HttpServletRequest) { String uri = ((HttpServletRequest)servletRequest).getRequestURI(); boolean status = false; - if (uri.contains("register/tenants")) { - String urlPermission = getPermission("/register/tenants/*"); - if (urlPermission != null) { - status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE); - } - } else { - String urlPermission = getPermission(uri); - if (urlPermission != null) { - status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE); - } + String urlPermission = getPermission(uri); + if (urlPermission != null) { + status = isUserAuthorized(PERMISSION_PREFIX + urlPermission, UI_EXECUTE); } if (status) { filterChain.doFilter(servletRequest, servletResponse); diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml index 1feabf39250..0124990741f 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension.api/src/main/webapp/META-INF/permissions.xml @@ -31,7 +31,7 @@ Register tenant specific application /device-mgt/admin - /register/tenants/* + /register/tenants POST super_admin_user diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml index d9f371913a7..de06da15aad 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/pom.xml @@ -63,6 +63,10 @@ com.googlecode.json-simple.wso2 json-simple + + org.wso2.carbon.registry + org.wso2.carbon.registry.indexing + @@ -103,7 +107,9 @@ org.wso2.carbon.utils.multitenancy, org.json.simple, org.wso2.carbon.context, - org.wso2.carbon.base + org.wso2.carbon.base, + org.wso2.carbon.registry.core.*;resolution:=optional, + org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}" !org.wso2.carbon.apimgt.application.extension.internal, diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java index 8c0e51a7f9c..30f8d62d436 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java @@ -35,6 +35,7 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIManagerFactory; +import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; @@ -57,6 +58,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe String username, boolean isAllowedAllDomains) throws APIManagerException { try { + APIManagerUtil.loadTenantRegistry(); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); int applicationId = createApplicationAndSubscribeToAllAPIs(apiApplicationName, username); @@ -121,6 +123,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe boolean isAllowedAllDomains, String keyType) throws APIManagerException { try { + APIManagerUtil.loadTenantRegistry(); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); if (apiConsumer != null) { String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); @@ -177,6 +180,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe @Override public void removeAPIApplication(String applicationName, String username) throws APIManagerException { try { + APIManagerUtil.loadTenantRegistry(); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); if (apiConsumer != null) { String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); @@ -203,6 +207,7 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe boolean isAllowedAllDomains) throws APIManagerException { try { + APIManagerUtil.loadTenantRegistry(); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); String groupId = getLoggedInUserGroupId(username, APIManagerUtil.getTenantDomain()); int applicationId = createApplicationAndSubscribeToAPIs(apiApplicationName, tags, username); @@ -405,6 +410,9 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe int applicationId = createApplication(apiConsumer, apiApplicationName, username, groupId); String tenantDomain = MultitenantUtils.getTenantDomain(username); Set userVisibleAPIs = apiConsumer.getAllPublishedAPIs(tenantDomain); + if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + userVisibleAPIs.addAll(apiConsumer.getAllPublishedAPIs(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)); + } Subscriber subscriber = apiConsumer.getSubscriber(username); Set subscribedAPIs = apiConsumer.getSubscribedAPIs(subscriber); for (API visibleApi : userVisibleAPIs) { @@ -441,4 +449,5 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe throw new APIManagerException("Unable to get groupIds of user " + username, e); } } + } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java index 6f360ae6492..6beb0bbb62e 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionDataHolder.java @@ -18,6 +18,8 @@ package org.wso2.carbon.apimgt.application.extension.internal; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.user.core.tenant.TenantManager; @@ -26,6 +28,8 @@ public class APIApplicationManagerExtensionDataHolder { private APIManagementProviderService apiManagementProviderService; private RealmService realmService; private TenantManager tenantManager; + private TenantRegistryLoader tenantRegistryLoader; + private TenantIndexingLoader indexLoader; private APIApplicationManagerExtensionDataHolder() { } @@ -66,4 +70,20 @@ public class APIApplicationManagerExtensionDataHolder { public TenantManager getTenantManager() { return tenantManager; } + + public void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader){ + this.tenantRegistryLoader = tenantRegistryLoader; + } + + public TenantRegistryLoader getTenantRegistryLoader(){ + return tenantRegistryLoader; + } + + public void setIndexLoaderService(TenantIndexingLoader indexLoader) { + this.indexLoader = indexLoader; + } + + public TenantIndexingLoader getIndexLoaderService(){ + return indexLoader; + } } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java index 557d47aa110..27104c13bd8 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/internal/APIApplicationManagerExtensionServiceComponent.java @@ -23,10 +23,24 @@ import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext;; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService; import org.wso2.carbon.apimgt.application.extension.APIManagementProviderServiceImpl; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.core.service.RealmService; /** * @scr.component name="org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionServiceComponent" + * @scr.reference name="tenant.registryloader" + * interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader" + * cardinality="1..1" + * policy="dynamic" + * bind="setTenantRegistryLoader" + * unbind="unsetTenantRegistryLoader" + * @scr.reference name="tenant.indexloader" + * interface="org.wso2.carbon.registry.indexing.service.TenantIndexingLoader" + * cardinality="1..1" + * policy="dynamic" + * bind="setIndexLoader" + * unbind="unsetIndexLoader" * @scr.reference name="realm.service" * immediate="true" * interface="org.wso2.carbon.user.core.service.RealmService" @@ -53,6 +67,25 @@ public class APIApplicationManagerExtensionServiceComponent { //do nothing } + protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { + APIApplicationManagerExtensionDataHolder.getInstance().setTenantRegistryLoader(tenantRegistryLoader); + } + + protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { + APIApplicationManagerExtensionDataHolder.getInstance().setTenantRegistryLoader(null); + } + + protected void setIndexLoader(TenantIndexingLoader indexLoader) { + if (indexLoader != null && log.isDebugEnabled()) { + log.debug("IndexLoader service initialized"); + } + APIApplicationManagerExtensionDataHolder.getInstance().setIndexLoaderService(indexLoader); + } + + protected void unsetIndexLoader(TenantIndexingLoader indexLoader) { + APIApplicationManagerExtensionDataHolder.getInstance().setIndexLoaderService(null); + } + /** * Sets Realm Service. * diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/util/APIManagerUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/util/APIManagerUtil.java index 96dba4cfb4d..530dfa662fc 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/util/APIManagerUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/util/APIManagerUtil.java @@ -23,6 +23,8 @@ import org.wso2.carbon.apimgt.application.extension.exception.APIManagerExceptio import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.user.api.TenantManager; import org.wso2.carbon.user.api.UserStoreException; @@ -52,4 +54,18 @@ public final class APIManagerUtil { public static String getTenantDomain() { return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); } + + public static void loadTenantRegistry() throws APIManagerException { + String tenantDomain = getTenantDomain(); + try { + int tenantId = getTenantId(tenantDomain); + TenantRegistryLoader tenantRegistryLoader = + APIApplicationManagerExtensionDataHolder.getInstance().getTenantRegistryLoader(); + APIApplicationManagerExtensionDataHolder.getInstance().getIndexLoaderService().loadTenantIndex(tenantId); + tenantRegistryLoader.loadTenantRegistry(tenantId); + } catch (RegistryException e) { + throw new APIManagerException("Error occured while loading registry for tenant '" + tenantDomain + "'"); + } + } + } diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java index 1b4758a475b..27e2af8fb61 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.webapp.publisher/src/main/java/org/wso2/carbon/apimgt/webapp/publisher/APIPublisherUtil.java @@ -289,8 +289,7 @@ public class APIPublisherUtil { apiConfig.setTransports(transports); String sharingValueParam = servletContext.getInitParameter(PARAM_SHARED_WITH_ALL_TENANTS); - boolean isSharedWithAllTenants = (sharingValueParam == null || (!sharingValueParam.isEmpty()) - && Boolean.parseBoolean(sharingValueParam)); + boolean isSharedWithAllTenants = Boolean.parseBoolean(sharingValueParam); apiConfig.setSharedWithAllTenants(isSharedWithAllTenants); Set uriTemplates = new LinkedHashSet<>(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java index 6756e863deb..f5a15604470 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Device.java @@ -117,7 +117,7 @@ public interface Device { */ @GET @Path("user/{user}/count") - @Permission(scope = "device-count-own", permissions = { + @Permission(scope = "device-view-own", permissions = { "/permission/admin/device-mgt/user/devices/list", "/permission/admin/device-mgt/admin/devices/list"}) Response getDeviceCountOfUser(@PathParam("user") String user); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java index 64a2b243c57..805e7654220 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Feature.java @@ -28,7 +28,7 @@ import javax.ws.rs.core.Response; /** * Features */ -@API(name = "Device Search", version = "1.0.0", context = "/devicemgt_admin/features", tags = {"devicemgt_admin"}) +@API(name = "Feature", version = "1.0.0", context = "/devicemgt_admin/features", tags = {"devicemgt_admin"}) // Below Api is for swagger annotations @Api(value = "Feature", description = "Feature management related operations can be found here.") @@ -58,7 +58,7 @@ public interface Feature { @ApiResponses(value = { @ApiResponse(code = 200, message = "List of Features"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of features" + ".") }) - @Permission(scope = "device-search", permissions = {"/permission/admin/device-mgt/admin/devices/view", + @Permission(scope = "feature-view", permissions = {"/permission/admin/device-mgt/admin/devices/view", "/permission/admin/device-mgt/user/devices/view"}) Response getFeatures(@ApiParam(name = "type", value = "Provide the device type, such as ios, android or windows", required = true) @PathParam("type") String type); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java index 735e4cfaf8c..2cfcda7deb7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/Role.java @@ -146,7 +146,7 @@ public interface Role { notes = "You are able to add a new role to WSO2 EMM using the REST API.") @ApiResponses(value = { @ApiResponse(code = 200, message = "Added the role."), @ApiResponse(code = 500, message = "Error occurred while adding the user role.") }) - @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/add"}) + @Permission(scope = "roles-add", permissions = {"/permission/admin/device-mgt/admin/roles/add"}) Response addRole(@ApiParam(name = "roleWrapper", value = "Role and permission details.", required = true) RoleWrapper roleWrapper); @@ -180,7 +180,7 @@ public interface Role { @ApiResponses(value = { @ApiResponse(code = 200, message = "Deleted the role."), @ApiResponse(code = 500, message = "Error occurred while deleting the user role details" + ".") }) - @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/remove"}) + @Permission(scope = "roles-remove", permissions = {"/permission/admin/device-mgt/admin/roles/remove"}) Response deleteRole(@ApiParam(name = "rolename", value = "Provide the name of the role you wish to delete.", required = true) @QueryParam("rolename") String roleName); @@ -217,7 +217,7 @@ public interface Role { notes = "Get the number of roles in WSO2 EMM.") @ApiResponses(value = { @ApiResponse(code = 200, message = "Retrieved the role count."), @ApiResponse(code = 500, message = "Error occurred while retrieving the role count.") }) - @Permission(scope = "roles-modify", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) + @Permission(scope = "roles-view", permissions = {"/permission/admin/device-mgt/admin/roles/list"}) Response getRoleCount(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java index eef95c6b6b0..603329afb21 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/api/User.java @@ -52,7 +52,7 @@ public interface User { @ApiResponse(code = 201, message = "Created"), @ApiResponse(code = 500, message = "Exception in trying to add user by username: 'username'") }) - @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/add"}) + @Permission(scope = "user-add", permissions = {"/permission/admin/device-mgt/admin/user/add"}) Response addUser(@ApiParam(name = "userWrapper", value = "Includes the required properties to add a user" + " as the value", required = true) UserWrapper userWrapper); @@ -113,7 +113,7 @@ public interface User { @ApiResponse(code = 400, message = "User by username: 'username' does not exist for removal"), @ApiResponse(code = 500, message = "Exception in trying to remove user by username: 'username'") }) - @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/user/remove"}) + @Permission(scope = "user-remove", permissions = {"/permission/admin/device-mgt/admin/user/remove"}) Response removeUser(@ApiParam(name = "username", value = "Provide the name of the user you wish to delete" + " as the value for {username}", required = true) @QueryParam("username") String username); @@ -220,7 +220,7 @@ public interface User { @ApiResponse(code = 200, message = "Email invitation was successfully sent to user"), @ApiResponse(code = 500, message = "Error occurred while retrieving the list of users") }) - @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/invite"}) + @Permission(scope = "user-invite", permissions = {"/permission/admin/device-mgt/admin/users/invite"}) Response inviteExistingUsersToEnrollDevice(@ApiParam(name = "usernames", value = "List of the users to be" + " invited as the ", required = true) List usernames); @@ -291,7 +291,7 @@ public interface User { + " Character Encoding is not supported"), @ApiResponse(code = 500, message = "Internal Server Error") }) - @Permission(scope = "user-modify", permissions = {"/permission/admin/login"}) + @Permission(scope = "user-password-modify", permissions = {"/permission/admin/login"}) Response resetPassword(@ApiParam(name = "credentials", value = "Include the required properties to change" + " the user password as value", required = true) UserCredentialWrapper credentials); @@ -317,7 +317,7 @@ public interface User { + " Character Encoding is not supported"), @ApiResponse(code = 500, message = "Internal Server Error") }) - @Permission(scope = "user-modify", permissions = {"/permission/admin/device-mgt/admin/users/password-reset"}) + @Permission(scope = "user-password-reset", permissions = {"/permission/admin/device-mgt/admin/users/password-reset"}) Response resetPasswordByAdmin(@ApiParam(name = "credentials", value = "Include the required properties " + "to change a user password as value", required = true) UserCredentialWrapper credentials); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml index 406c03fac7b..2d2be4349d1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/web.xml @@ -79,6 +79,10 @@ managed-api-owner admin + + isSharedWithAllTenants + true + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json index bdfd53568a7..a64219b95dd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/app-conf.json @@ -26,7 +26,14 @@ } }, "sso": { - "enabled": false + "enabled": false, + "issuer" : "devicemgt", + "appName" : "devicemgt", + "identityProviderUrl" : "https://localhost:9443/samlsso", + "acs": "https://localhost:9443/devicemgt/uuf/sso/acs", + "identityAlias": "wso2carbon", + "responseSigningEnabled" : "true", + "useTenantKey": false } }, "errorPages": { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index 8d8f82d08b4..98014634563 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -2,8 +2,9 @@ "appContext" : "/devicemgt/", "webAgentContext" : "/devicemgt-web-agent/", "apiContext" : "api", - "httpsURL" : "%https.ip%", + "httpsURL" : "https://localhost:9443", "httpURL" : "%http.ip%", + "httpsWebURL" : "%https.ip%", "wssURL" : "%https.ip%", "wsURL" : "%http.ip%", "enrollmentDir": "/emm-web-agent/enrollment", @@ -11,9 +12,9 @@ "iOSAPIRoot" : "%https.ip%/ios/", "dynamicClientRegistrationEndPoint" : "%https.ip%/dynamic-client-web/register/", "adminService":"%https.ip%", - "idPServer":"%https.ip%", + "idPServer":"https://localhost:8243", "callBackUrl":"%https.ip%/devicemgt_admin", - "adminUser":"admin", + "adminUser":"admin@carbon.super", "adminRole":"admin", "usernameLength":30, "ssoConfiguration" : { @@ -55,5 +56,12 @@ "copyrightOwner" : "WSO2 Inc.", "copyrightOwnersSite" : "http://www.wso2.org", "copyrightSuffix" : " All Rights Reserved." - } + }, + "scopes" : ["license-add", "license-view", "device-view", "device-info", "device-list", "device-view-own", + "device-modify", "device-search", "operation-install", "operation-view", "operation-modify", "operation-uninstall", + "group-add", "group-share", "group-modify", "group-view", "group-remove", "certificate-modify", "certificate-view", + "configuration-view", "configuration-modify", "policy-view", "policy-modify", "device-notification-view", + "device-notification-modify", "feature-view", "arduino_device", "arduino_user", " android_sense_user", + "virtual_firealarm_user", "raspberrypi_user", "roles-view", "roles-modify", "roles-remove", "roles-add", + "user-password-reset", "user-password-modify", "user-modify", "user-view", "user-invite", "user-remove", "user-add"] } \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/api-wrapper-util.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/api-wrapper-util.js index 1a518bcf22b..becd0c13c81 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/api-wrapper-util.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/api-wrapper-util.js @@ -20,7 +20,8 @@ var apiWrapperUtil = function () { var module = {}; var tokenUtil = require("/app/modules/util.js").util; var constants = require("/app/modules/constants.js"); - var constants = require("/app/modules/constants.js"); + var devicemgtProps = require('/app/conf/devicemgt-props.js').config(); + var log = new Log("/app/modules/api-wrapper-util.js"); module.refreshToken = function () { var tokenPair = session.get(constants.ACCESS_TOKEN_PAIR_IDENTIFIER); @@ -31,11 +32,19 @@ var apiWrapperUtil = function () { module.setupAccessTokenPair = function (type, properties) { var tokenPair; var clientData = tokenUtil.getDyanmicCredentials(properties); + var jwtToken = tokenUtil.getTokenWithJWTGrantType(clientData); + clientData = tokenUtil.getTenantBasedAppCredentials(properties.username, jwtToken); var encodedClientKeys = tokenUtil.encode(clientData.clientId + ":" + clientData.clientSecret); session.put(constants.ENCODED_CLIENT_KEYS_IDENTIFIER, encodedClientKeys); if (type == constants.GRANT_TYPE_PASSWORD) { + var scopes = devicemgtProps.scopes; + var scope = ""; + scopes.forEach(function(entry) { + scope += entry + " "; + }); tokenPair = - tokenUtil.getTokenWithPasswordGrantType(properties.username, encodeURIComponent(properties.password), encodedClientKeys); + tokenUtil.getTokenWithPasswordGrantType(properties.username, encodeURIComponent(properties.password), + encodedClientKeys, scope); } else if (type == constants.GRANT_TYPE_SAML) { tokenPair = tokenUtil. getTokenWithSAMLGrantType(properties.samlToken, encodedClientKeys, "PRODUCTION"); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/backend-service-invoker.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/backend-service-invoker.js index 1e3f0bd69a3..2410d54aab6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/backend-service-invoker.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/backend-service-invoker.js @@ -65,6 +65,7 @@ var backendServiceInvoker = function () { } xmlHttpRequest.setRequestHeader(constants.CONTENT_TYPE_IDENTIFIER, contentType); xmlHttpRequest.setRequestHeader(constants.ACCEPT_IDENTIFIER, acceptType); + xmlHttpRequest.setRequestHeader(constants.REFERER, String(privateMethods.getClientDomain())); if (IS_OAUTH_ENABLED) { var accessToken = privateMethods.getAccessToken(); if (!accessToken) { @@ -150,6 +151,10 @@ var backendServiceInvoker = function () { header.setName(constants.ACCEPT_IDENTIFIER); header.setValue(acceptType); httpMethodObject.addRequestHeader(header); + header = new Header(); + header.setName(constants.REFERER); + header.setValue(String(privateMethods.getClientDomain())); + httpMethodObject.addRequestHeader(header); if (IS_OAUTH_ENABLED) { var accessToken = privateMethods.getAccessToken(); if (accessToken) { @@ -210,6 +215,12 @@ var backendServiceInvoker = function () { oAuthAuthenticationData.name = authenticationHeaderName; oAuthAuthenticationData.value = authenticationHeaderValue; headers.push(oAuthAuthenticationData); + + var referrerData = {}; + referrerData.name = constants.REFERER; + referrerData.value = String(privateMethods.getClientDomain()); + headers.push(referrerData); + options.HTTPHeaders = headers; } else { response.sendRedirect(devicemgtProps["httpsURL"] + "/devicemgt/login"); @@ -331,6 +342,16 @@ var backendServiceInvoker = function () { return privateMethods.initiateHTTPClientRequest(constants.HTTP_DELETE, url, successCallback, errorCallback, contentType, acceptType); }; + /** + * This method fetch the current logged user from the session and returns + * the tenant domain name of the user + * @returns {tenantDomain} + */ + privateMethods.getClientDomain = function () { + var user = session.get(constants.USER_SESSION_KEY); + return user.domain; + } + var publicInvokers = {}; publicInvokers.XMLHttp = publicXMLHTTPInvokers; publicInvokers.WS = publicWSInvokers; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js index 8d043b5d0dd..a8ab77a8d1a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/constants.js @@ -70,6 +70,7 @@ var HTTP_GET = "GET"; var HTTP_POST = "POST"; var HTTP_PUT = "PUT"; var HTTP_DELETE = "DELETE"; +var REFERER = "referer" var GRANT_TYPE_PASSWORD = "password"; var GRANT_TYPE_SAML = "saml"; @@ -78,3 +79,5 @@ var MQTT_QUEUE_CONFIG_NAME = "MQTT"; var HTTP_CONFLICT = 409; var HTTP_CREATED = 201; + +var CACHED_CREDENTIALS = "tenantBasedCredentials"; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js index d24df7c4806..4597c2d7374 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/login.js @@ -35,7 +35,7 @@ var onFail; } var devicemgtProps = require('/app/conf/devicemgt-props.js').config(); var carbonServer = require("carbon").server; - (new carbonServer.Server({url: devicemgtProps["httpsURL"]})) + (new carbonServer.Server({url: devicemgtProps["adminService"]})) .login(context.input.username, context.input.password); }; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/util.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/util.js index 6b58c5ae1ed..b9e31aaba5e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/util.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/util.js @@ -23,16 +23,15 @@ var util = function () { var String = Packages.java.lang.String; var devicemgtProps = require('/app/conf/devicemgt-props.js').config(); var carbon = require('carbon'); - var realmService = carbon.server.osgiService('org.wso2.carbon.user.core.service.RealmService'); - var adminUserName = realmService.getBootstrapRealmConfiguration().getAdminUserName(); var constants = require("/app/modules/constants.js"); + var adminUser = devicemgtProps["adminUser"]; module.getDyanmicCredentials = function (owner) { var payload = { "callbackUrl": devicemgtProps.callBackUrl, "clientName": "devicemgt", "tokenScope": "admin", - "owner": adminUserName, + "owner": adminUser, "applicationType": "webapp", "grantType": "password refresh_token urn:ietf:params:oauth:grant-type:saml2-bearer", "saasApp" :true @@ -47,6 +46,7 @@ var util = function () { var data = parse(xhr.responseText); clientData.clientId = data.client_id; clientData.clientSecret = data.client_secret; + } else if (xhr.status == 400) { throw "Invalid client meta data"; } else { @@ -79,7 +79,7 @@ var util = function () { */ module.getTokenWithPasswordGrantType = function (username, password, encodedClientKeys, scope) { var xhr = new XMLHttpRequest(); - var tokenEndpoint = devicemgtProps.idPServer + "/oauth2/token"; + var tokenEndpoint = devicemgtProps.idPServer + "/token"; xhr.open("POST", tokenEndpoint, false); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Authorization", "Basic " + encodedClientKeys); @@ -137,6 +137,7 @@ var util = function () { } return tokenPair; }; + module.refreshToken = function (tokenPair, clientData, scope) { var xhr = new XMLHttpRequest(); var tokenEndpoint = devicemgtProps.idPServer + "/oauth2/token"; @@ -163,5 +164,62 @@ var util = function () { } return tokenPair; }; + + module.getTokenWithJWTGrantType = function (clientData) { + var jwtService = carbon.server.osgiService('org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); + var jwtClient = jwtService.getJWTClient(); + var jwtToken = jwtClient.getAccessToken(clientData.clientId, clientData.clientSecret, adminUser, null); + return jwtToken; + }; + + module.getTenantBasedAppCredentials = function (uname, token) { + var tenantDomain = carbonModule.server.tenantDomain({ + username: uname + }); + var clientData = this.getCachedCredentials(tenantDomain); + if (!clientData) { + var applicationName = "webapp_" + tenantDomain; + var xhr = new XMLHttpRequest(); + var endpoint = devicemgtProps["adminService"] + "/api-application-registration/register/tenants?tenantDomain=" + + tenantDomain + "&applicationName=" + applicationName; + xhr.open("POST", endpoint, false); + xhr.setRequestHeader("Content-Type", "application/json"); + xhr.setRequestHeader("Authorization", "Bearer " + token.accessToken); + xhr.send(); + + if (xhr.status == 201) { + var data = parse(xhr.responseText); + clientData = {}; + clientData.clientId = data.client_id; + clientData.clientSecret = data.client_secret; + this.setTenantBasedAppCredentials(tenantDomain, clientData); + } else if (xhr.status == 400) { + throw "Invalid client meta data"; + } else { + throw "Error in obtaining client id and secret from APIM"; + } + } + return clientData; + }; + + module.setTenantBasedAppCredentials = function (tenantDomain, clientData) { + var cachedMap = application.get(constants.CACHED_CREDENTIALS); + if (!cachedMap) { + cachedMap = new Object(); + cachedMap[tenantDomain] = clientData; + application.put(constants.CACHED_CREDENTIALS, cachedMap); + } else { + cachedMap[tenantDomain] = clientData; + } + }; + + module.getCachedCredentials = function(tenantDomain) { + var cachedMap = application.get(constants.CACHED_CREDENTIALS); + if (cachedMap) { + return cachedMap[tenantDomain]; + } + return null; + }; + return module; }(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/constants.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/constants.js index 82b339f43bf..f7806238b68 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/constants.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/constants.js @@ -69,6 +69,8 @@ var constants = { APP_CONF_AUTH_MODULE_SSO_IDENTITY_PROVIDER_ALIAS: "identityProviderAlias", APP_CONF_AUTH_MODULE_SSO_IDENTITY_PROVIDER_URL: "identityProviderUrl", APP_CONF_AUTH_MODULE_SSO_INTERMEDIATE_PAGE: "intermediatePage", + APP_CONF_AUTH_MODULE_SSO_IDENTITY_ALIAS : "identityAlias", + APP_CONF_AUTH_MODULE_SSO_USE_ST_KEY : "useTenantKey", // Configurations - UUF UUF_CONF_DISPLAY_NAME: "displayName", UUF_CONF_LOG_LEVEL: "logLevel", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js index 922563ed6bf..9809f0a9988 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/uuf-template-app/lib/modules/auth/auth.js @@ -501,7 +501,6 @@ var module = {}; response.sendError(500, e.message); return; } - if (ssoClient.isLogoutResponse(samlResponseObj)) { // This is a logout response. module.logout(response); @@ -510,11 +509,15 @@ var module = {}; var ssoConfigs = getSsoConfigurations(); var rsEnabled = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_RESPONSE_SIGNING_ENABLED]; if (utils.parseBoolean(rsEnabled)) { - // Response signing is enabled. + var CarbonUtils = Packages.org.wso2.carbon.utils.CarbonUtils; + var keyStorePassword = CarbonUtils.getServerConfiguration().getFirstProperty("Security.TrustStore.Password"); + var keyStoreName = CarbonUtils.getServerConfiguration().getFirstProperty("Security.TrustStore.Location"); + var identityAlias = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_IDENTITY_ALIAS]; var keyStoreParams = { - KEY_STORE_NAME: ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_KEY_STORE_NAME], - KEY_STORE_PASSWORD: ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_KEY_STORE_PASSWORD], - IDP_ALIAS: ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_IDENTITY_PROVIDER_ALIAS] + KEY_STORE_NAME: keyStoreName, + KEY_STORE_PASSWORD: keyStorePassword, + IDP_ALIAS: identityAlias, + USE_ST_KEY: !ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_USE_ST_KEY] }; if (!ssoClient.validateSignature(samlResponseObj, keyStoreParams)) { var msg = "Invalid signature found in the SAML response."; @@ -532,10 +535,13 @@ var module = {}; if (ssoSession.sessionId) { var ssoSessions = getSsoSessions(); ssoSessions[ssoSession.sessionId] = ssoSession; - var carbonUser = (require("carbon")).server.tenantUser(ssoSession.loggedInUser); - utils.setCurrentUser(carbonUser.username, carbonUser.domain, carbonUser.tenantId); - var scriptArgument = {input: {samlToken: ssoSession.samlToken}, user: module.getCurrentUser()}; - handleEvent(OPERATION_LOGIN, EVENT_SUCCESS, scriptArgument); + if (ssoSessions.sessionIndex != null || ssoSessions.sessionIndex != 'undefined') { + module.loadTenant(ssoSessions.loggedInUser); + var carbonUser = (require("carbon")).server.tenantUser(ssoSession.loggedInUser); + utils.setCurrentUser(carbonUser.username, carbonUser.domain, carbonUser.tenantId); + var scriptArgument = {input: {samlToken: ssoSession.samlToken}, user: module.getCurrentUser()}; + handleEvent(OPERATION_LOGIN, EVENT_SUCCESS, scriptArgument); + } } else { var msg = "Cannot decode SAML login response."; log.error(msg); @@ -544,6 +550,25 @@ var module = {}; } }; + /** + * Load current user tenant + * @param username logged user name + */ + module.loadTenant = function (username) { + var carbon = require('carbon'); + var MultitenantUtils = Packages.org.wso2.carbon.utils.multitenancy.MultitenantUtils; + var MultitenantConstants = Packages.org.wso2.carbon.base.MultitenantConstants; + var TenantAxisUtils = Packages.org.wso2.carbon.core.multitenancy.utils.TenantAxisUtils; + var service; + var ctx; + var domain = MultitenantUtils.getTenantDomain(username); + if (domain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(domain)) { + service = carbon.server.osgiService('org.wso2.carbon.utils.ConfigurationContextService'); + ctx = service.getServerConfigContext(); + TenantAxisUtils.setTenantAccessed(domain, ctx); + } + }; + /** * Basic login. * @param request {Object} HTTP request diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/service/JWTClientManagerServiceImpl.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/service/JWTClientManagerServiceImpl.java index df9a862fad4..f12d295b7a2 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/service/JWTClientManagerServiceImpl.java +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/service/JWTClientManagerServiceImpl.java @@ -41,128 +41,128 @@ import java.util.concurrent.ConcurrentHashMap; /** * This creates JWT Client for each tenant and implements the JWTClientManagerService interface. */ -public class JWTClientManagerServiceImpl implements JWTClientManagerService{ +public class JWTClientManagerServiceImpl implements JWTClientManagerService { - private static Map jwtClientMap; - private static final Log log = LogFactory.getLog(JWTClientManagerServiceImpl.class); - private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties"; - private static JWTClient defaultJWTClient; + private static Map jwtClientMap; + private static final Log log = LogFactory.getLog(JWTClientManagerServiceImpl.class); + private static final String TENANT_JWT_CONFIG_LOCATION = "/jwt-config/jwt.properties"; + private static JWTClient defaultJWTClient; - public JWTClientManagerServiceImpl() { - jwtClientMap = new ConcurrentHashMap<>(); - } + public JWTClientManagerServiceImpl() { + jwtClientMap = new ConcurrentHashMap<>(); + } - /** - * this return the jwt based token client to generate token for the tenant. - */ - @Override - public JWTClient getJWTClient() throws JWTClientException { - String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); - int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); - if (tenantId == -1) { - throw new JWTClientException("Invalid tenant domain :" + tenantDomain); - } - //Get jwt client which has been registered for the tenant. - JWTClient jwtClient = getJWTClient(tenantDomain); - if (jwtClient == null) { - //Create a new jwt client for the tenant. - try { - Properties properties = getJWTConfigProperties(tenantId); - if (properties == null) { - if (defaultJWTClient != null) { - return defaultJWTClient; - } else { - throw new JWTClientException("JWT Configuration is not available for tenant " + tenantDomain); - } - } - JWTConfig jwtConfig = new JWTConfig(properties); - jwtClient = new JWTClient(jwtConfig); - addJWTClient(tenantDomain, jwtClient); - } catch (JWTClientAlreadyExistsException e) { - log.warn("Attempting to register a jwt client for the tenant " + tenantDomain + - " when one already exists. Returning existing jwt client"); - return getJWTClient(tenantDomain); - } catch (JWTClientConfigurationException e) { - throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e); - } - } - return jwtClient; - } + /** + * this return the jwt based token client to generate token for the tenant. + */ + @Override + public JWTClient getJWTClient() throws JWTClientException { + String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + if (tenantId == -1) { + throw new JWTClientException("Invalid tenant domain :" + tenantDomain); + } + //Get jwt client which has been registered for the tenant. + JWTClient jwtClient = getJWTClient(tenantDomain); + if (jwtClient == null) { + //Create a new jwt client for the tenant. + try { + Properties properties = getJWTConfigProperties(tenantId); + if (properties == null) { + if (defaultJWTClient != null) { + return defaultJWTClient; + } else { + throw new JWTClientException("JWT Configuration is not available for tenant " + tenantDomain); + } + } + JWTConfig jwtConfig = new JWTConfig(properties); + jwtClient = new JWTClient(jwtConfig); + addJWTClient(tenantDomain, jwtClient); + } catch (JWTClientAlreadyExistsException e) { + log.warn("Attempting to register a jwt client for the tenant " + tenantDomain + + " when one already exists. Returning existing jwt client"); + return getJWTClient(tenantDomain); + } catch (JWTClientConfigurationException e) { + throw new JWTClientException("Failed to parse jwt configuration for tenant " + tenantDomain, e); + } + } + return jwtClient; + } - /** - * This will set the default JWT Client that will be used if there is any available for tenants. - */ - @Override - public void setDefaultJWTClient(Properties properties) throws JWTClientConfigurationException { - if (properties == null) { - throw new JWTClientConfigurationException("Failed to load jwt configuration for super tenant."); - } - String defaultJWTClientMode = properties.getProperty(JWTConstants.DEFAULT_JWT_CLIENT); - boolean isDefaultJwtClient = false; - if (defaultJWTClientMode != null && !defaultJWTClientMode.isEmpty()) { - isDefaultJwtClient = Boolean.parseBoolean(defaultJWTClientMode); - } - if (isDefaultJwtClient) { - try { - JWTConfig jwtConfig = new JWTConfig(properties); - defaultJWTClient = new JWTClient(jwtConfig, true); - addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient); - } catch (JWTClientAlreadyExistsException e) { - log.warn("Attempting to register a jwt client for the super tenant" + - " when one already exists. Returning existing jwt client"); - } - } - } + /** + * This will set the default JWT Client that will be used if there is any available for tenants. + */ + @Override + public void setDefaultJWTClient(Properties properties) throws JWTClientConfigurationException { + if (properties == null) { + throw new JWTClientConfigurationException("Failed to load jwt configuration for super tenant."); + } + String defaultJWTClientMode = properties.getProperty(JWTConstants.DEFAULT_JWT_CLIENT); + boolean isDefaultJwtClient = false; + if (defaultJWTClientMode != null && !defaultJWTClientMode.isEmpty()) { + isDefaultJwtClient = Boolean.parseBoolean(defaultJWTClientMode); + } + if (isDefaultJwtClient) { + try { + JWTConfig jwtConfig = new JWTConfig(properties); + defaultJWTClient = new JWTClient(jwtConfig, true); + addJWTClient(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, defaultJWTClient); + } catch (JWTClientAlreadyExistsException e) { + log.warn("Attempting to register a jwt client for the super tenant" + + " when one already exists. Returning existing jwt client"); + } + } + } - /** - * Fetch the jwt client which has been registered under the tenant domain. - * - * @param tenantDomain - The tenant domain under which the jwt client is registered - * @return - Instance of the jwt client which was registered. Null if not registered. - */ - private JWTClient getJWTClient(String tenantDomain) { - if (jwtClientMap.containsKey(tenantDomain)) { - return jwtClientMap.get(tenantDomain); - } - return null; - } + /** + * Fetch the jwt client which has been registered under the tenant domain. + * + * @param tenantDomain - The tenant domain under which the jwt client is registered + * @return - Instance of the jwt client which was registered. Null if not registered. + */ + private JWTClient getJWTClient(String tenantDomain) { + if (jwtClientMap.containsKey(tenantDomain)) { + return jwtClientMap.get(tenantDomain); + } + return null; + } - /** - * Adds a jwt client to the jwt client map. - * - * @param tenantDomain - The tenant domain under which the jwt client will be registered. - * @param jwtClient - Instance of the jwt client - * @throws JWTClientAlreadyExistsException - If a jwt client has already been registered under the tenantdomain - */ - private void addJWTClient(String tenantDomain, JWTClient jwtClient) throws JWTClientAlreadyExistsException { - synchronized (jwtClientMap) { - if (jwtClientMap.containsKey(tenantDomain)) { - throw new JWTClientAlreadyExistsException( - "A jwt client has already been created for the tenant " + tenantDomain); - } - jwtClientMap.put(tenantDomain, jwtClient); - } - } + /** + * Adds a jwt client to the jwt client map. + * + * @param tenantDomain - The tenant domain under which the jwt client will be registered. + * @param jwtClient - Instance of the jwt client + * @throws JWTClientAlreadyExistsException - If a jwt client has already been registered under the tenantdomain + */ + private void addJWTClient(String tenantDomain, JWTClient jwtClient) throws JWTClientAlreadyExistsException { + synchronized (jwtClientMap) { + if (jwtClientMap.containsKey(tenantDomain)) { + throw new JWTClientAlreadyExistsException( + "A jwt client has already been created for the tenant " + tenantDomain); + } + jwtClientMap.put(tenantDomain, jwtClient); + } + } - /** - * Retrieve JWT configs from registry. - */ - private Properties getJWTConfigProperties(int tenantId) throws JWTClientConfigurationException { - try { - Resource config = JWTClientUtil.getConfigRegistryResourceContent(tenantId, TENANT_JWT_CONFIG_LOCATION); - Properties properties = null; - if (config != null) { - properties = new Properties(); - properties.load(config.getContentStream()); - } - return properties; - } catch (RegistryException e) { - throw new JWTClientConfigurationException("Failed to load the content from registry for tenant " + - tenantId, e); - } catch (IOException e) { - throw new JWTClientConfigurationException( - "Failed to parse the content from the registry for tenant " + tenantId, e); - } - } + /** + * Retrieve JWT configs from registry. + */ + private Properties getJWTConfigProperties(int tenantId) throws JWTClientConfigurationException { + try { + Resource config = JWTClientUtil.getConfigRegistryResourceContent(tenantId, TENANT_JWT_CONFIG_LOCATION); + Properties properties = null; + if (config != null) { + properties = new Properties(); + properties.load(config.getContentStream()); + } + return properties; + } catch (RegistryException e) { + throw new JWTClientConfigurationException("Failed to load the content from registry for tenant " + + tenantId, e); + } catch (IOException e) { + throw new JWTClientConfigurationException( + "Failed to parse the content from the registry for tenant " + tenantId, e); + } + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index d9bf6ff65ac..6893eb1e886 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -121,6 +121,7 @@ org.wso2.carbon.registry.core.*, org.wso2.carbon.registry.common.*;version="${carbon.registry.imp.pkg.version.range}", org.wso2.carbon.registry.indexing.*; version="${carbon.registry.imp.pkg.version.range}", + org.wso2.carbon.base diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java index 91c1b966f71..1b754e4ee2d 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java @@ -26,6 +26,8 @@ import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.util.KeyStoreManager; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; @@ -88,12 +90,23 @@ public class JWTAuthenticator implements WebappAuthenticator { String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); String tenantDomain = MultitenantUtils.getTenantDomain(username); int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID)); + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId); PublicKey publicKey = publicKeyHolder.get(tenantDomain); if (publicKey == null) { loadTenantRegistry(tenantId); KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); - publicKey = keyStoreManager.getDefaultPublicKey(); - publicKeyHolder.put(tenantDomain, publicKey); + if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + publicKey = keyStoreManager.getDefaultPublicKey(); + } else { + String ksName = tenantDomain.trim().replace('.', '-'); + String jksName = ksName + ".jks"; + publicKey = keyStoreManager.getKeyStore(jksName).getCertificate(tenantDomain).getPublicKey(); + } + if (publicKey != null) { + publicKeyHolder.put(tenantDomain, publicKey); + } } //Get the filesystem keystore default primary certificate @@ -124,6 +137,8 @@ public class JWTAuthenticator implements WebappAuthenticator { log.error("Error occurred while verifying the JWT header.", e); } catch (Exception e) { log.error("Error occurred while verifying the JWT header.", e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); } return authenticationInfo; }