From a7af88396247f39a603533df30cd235e203cf29f Mon Sep 17 00:00:00 2001 From: inoshperera Date: Thu, 23 Jul 2020 20:45:30 +0530 Subject: [PATCH 1/2] Add tenant create API --- .../pom.xml | 4 + .../DeviceManagementConfigServiceImpl.java | 90 +++++++++++++++++++ .../src/main/webapp/WEB-INF/web.xml | 3 +- 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml index 8ffc22a4ec8..fe1ff78a87a 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/pom.xml @@ -273,5 +273,9 @@ + + org.wso2.carbon.multitenancy + org.wso2.carbon.tenant.mgt + diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java index 9ccbecda3d8..bb1a04bba74 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/java/io/entgra/carbon/device/mgt/config/jaxrs/service/impl/DeviceManagementConfigServiceImpl.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.entgra.carbon.device.mgt.config.jaxrs.beans.ErrorResponse; import io.entgra.carbon.device.mgt.config.jaxrs.service.DeviceManagementConfigService; import io.entgra.carbon.device.mgt.config.jaxrs.util.DeviceMgtAPIUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.base.MultitenantConstants; @@ -35,6 +36,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfiguratio import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; +import org.wso2.carbon.device.mgt.common.general.OneTimeTokenDetails; import org.wso2.carbon.device.mgt.common.general.TenantDetail; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagementException; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService; @@ -48,22 +50,29 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.stratos.common.beans.TenantInfoBean; +import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService; import org.wso2.carbon.user.api.Tenant; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.service.RealmService; +import javax.validation.constraints.Size; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.IOException; import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import java.util.Map; @@ -270,6 +279,87 @@ public class DeviceManagementConfigServiceImpl implements DeviceManagementConfig return tenantDetail; } + /** + * This API will add a tenant to the system and can be called by the super tenant only. + * @return Returns the + */ + @Path("/tenant") + @POST + @Produces(MediaType.APPLICATION_JSON) + public Response addTenant(@HeaderParam("one-time-token") String token) { + + TenantMgtAdminService tenantMgtAdminService = null; + OneTimeTokenDetails tenantWrapper = null; + + // Request validation + String errorMsg = null; + Response.Status errorStatus = Response.Status.BAD_REQUEST; + if (StringUtils.isEmpty(token)) { + errorMsg = "Authentication failure when creating tenant"; + } else { + tenantWrapper = new OneTimeTokenDetails(); //TODO: Call one time token validation API + if (tenantWrapper == null) { + errorMsg = "One time token is not present in the database"; + } else { + try { + tenantMgtAdminService = new TenantMgtAdminService(); + if (tenantMgtAdminService == null) { + errorMsg = "Request can only be made by super admin"; + errorStatus = Response.Status.INTERNAL_SERVER_ERROR; + } else { + TenantInfoBean[] tenant = tenantMgtAdminService.retrievePartialSearchTenants(tenantWrapper.getDomain()); + if (!PrivilegedCarbonContext.getThreadLocalCarbonContext() + .getTenantDomain().equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + errorMsg = "Request can only be made by super admin"; + } else if (tenant != null && tenant.length > 0) { + for (TenantInfoBean tenantInfoBean : tenant) { + if (tenantInfoBean.getTenantDomain().equals(tenantWrapper.getDomain())) { + errorMsg = "Tenant domain is already in use"; + break; + } + } + } + } + + } catch (Exception e) { // Carbon multi-tenancy is throwing generic exceptions. + errorMsg = "Could not create tenant domain " + tenantWrapper.getDomain(); + errorStatus = Response.Status.INTERNAL_SERVER_ERROR; + } + } + } + + if (errorMsg != null) { + log.error(errorMsg); + return Response.status(errorStatus).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(errorMsg).build() + ).build(); + } + + try { + TenantInfoBean tenantInfoBean = new TenantInfoBean(); + tenantInfoBean.setActive(true); + tenantInfoBean.setAdminPassword(tenantWrapper.getPassword()); + tenantInfoBean.setAdmin(tenantWrapper.getAdminName()); + tenantInfoBean.setFirstname(tenantWrapper.getAdminFirstName()); + tenantInfoBean.setLastname(tenantWrapper.getAdminLastName()); + tenantInfoBean.setEmail(tenantWrapper.getEmail()); + Calendar calendar = new GregorianCalendar(); + calendar.setTime(new Date()); + tenantInfoBean.setCreatedDate(calendar); + tenantInfoBean.setTenantDomain(tenantWrapper.getDomain()); + + String response = tenantMgtAdminService.addTenant(tenantInfoBean); + return Response.status(Response.Status.OK).entity(response).build(); + + } catch (Exception e) { // The underlying API is throwing a generic exception. + String msg = "Error while adding tenant"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + + } + @POST @Path("/permissions") @Produces({MediaType.APPLICATION_JSON}) diff --git a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml index 6b397c9fbec..3b97a83bbcb 100644 --- a/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml +++ b/components/device-mgt/io.entgra.carbon.device.mgt.config.api/src/main/webapp/WEB-INF/web.xml @@ -49,7 +49,8 @@ nonSecuredEndPoints /api/device-mgt-config/v1.0/configurations, - /api/device-mgt-config/v1.0/configurations/ui-config + /api/device-mgt-config/v1.0/configurations/ui-config, + /api/device-mgt-config/v1.0/tenant From 160c463672034ff3978795234fecd9f695391879 Mon Sep 17 00:00:00 2001 From: inoshperera Date: Sun, 26 Jul 2020 23:05:01 +0530 Subject: [PATCH 2/2] Add token validation with one time token This is to validate one time tokens in the APIM handlers and in the valve --- .../handlers/AuthenticationHandler.java | 9 ++ .../apimgt/handlers/utils/AuthConstants.java | 1 + .../authenticator/framework/Constants.java | 1 + .../OneTimeTokenAuthenticator.java | 93 +++++++++++++++++++ .../AuthenticatorFrameworkDataHolder.java | 11 +++ ...uthenticatorFrameworkServiceComponent.java | 23 +++++ 6 files changed, 138 insertions(+) create mode 100644 components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java index c9873629b71..415ec063049 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/AuthenticationHandler.java @@ -182,6 +182,15 @@ public class AuthenticationHandler extends AbstractHandler { if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } + } else if (headers.containsKey(AuthConstants.ONE_TIME_TOKEN_HEADER)) { + String token = headers.get(AuthConstants.ONE_TIME_TOKEN_HEADER); + //TODO: validate token service. Since this is getting validated in the valve, + // this may not even be necessery +// if (log.isDebugEnabled()) { +// log.debug("One time time :" + token + ", status : " + ); +// } + return true; + } else { log.warn("Unauthorized request for api: " + ctxPath); return false; diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java index f2a9f7a42bd..d9a9ef8a7b6 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.handlers/src/main/java/org/wso2/carbon/apimgt/handlers/utils/AuthConstants.java @@ -24,6 +24,7 @@ public class AuthConstants { public static final String MDM_SIGNATURE = "mdm-signature"; public static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header"; public static final String MUTUAL_AUTH_HEADER = "mutual-auth-header"; + public static final String ONE_TIME_TOKEN_HEADER = "one-time-token"; public static final String ENCODED_PEM = "encoded-pem"; public static final String CALLBACK_URL = ""; public static final String CLIENT_NAME = "IOT-API-MANAGER"; diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java index 2694ea069af..6426c53f473 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/Constants.java @@ -31,6 +31,7 @@ public final class Constants { public static final String HEADER_HTTP_ACCEPT = "Accept"; public static final String HEADER_HTTP_AUTHORIZATION = "Authorization"; + public static final String ONE_TIME_TOKEN_HEADER = "one-time-token"; } public static final class ContentTypes { diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java new file mode 100644 index 00000000000..7b207aa034f --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/OneTimeTokenAuthenticator.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.webapp.authenticator.framework.authenticator; + +import org.apache.catalina.connector.Response; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.MessageBytes; +import org.wso2.carbon.device.mgt.common.general.OneTimeTokenDetails; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; +import org.wso2.carbon.webapp.authenticator.framework.Constants; +import org.wso2.carbon.webapp.authenticator.framework.Utils.Utils; +import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuth2TokenValidator; +import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthTokenValidationException; +import org.wso2.carbon.webapp.authenticator.framework.authenticator.oauth.OAuthValidationResponse; + +import java.util.Properties; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class OneTimeTokenAuthenticator implements WebappAuthenticator { + private static final Log log = LogFactory.getLog(OneTimeTokenAuthenticator.class); + + + @Override + public void init() { + + } + + public boolean canHandle(org.apache.catalina.connector.Request request) { + return request.getHeader(Constants.HTTPHeaders.ONE_TIME_TOKEN_HEADER) != null; + } + + public AuthenticationInfo authenticate(org.apache.catalina.connector.Request request, Response response) { + + String token = request.getHeader(Constants.HTTPHeaders.ONE_TIME_TOKEN_HEADER); +// DeviceMgtAPIUtils.getDeviceManagementService();//TODO: call token validate service in core + OneTimeTokenDetails tokenDetails = new OneTimeTokenDetails();//TODO: use token details + + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + + try { + authenticationInfo.setTenantDomain(tokenDetails.getDomain()); + authenticationInfo.setStatus(Status.CONTINUE); + //authenticationInfo.setUsername(tokenDetails.get); //TODO: set username + //authenticationInfo.setTenantId();//TODO: set tenant Id + } catch (Exception e) { // TODO: remove this if not needed + authenticationInfo.setStatus(Status.FAILURE); + authenticationInfo.setMessage("Could not identify tenant domain."); + } + + return null; + } + + public String getName() { + return "One-Time-Token"; + } + + @Override + public void setProperties(Properties properties) { + + } + + @Override + public Properties getProperties() { + return null; + } + + @Override + public String getProperty(String name) { + return null; + } + + +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java index 8607d02239d..0bfbcc8f436 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/AuthenticatorFrameworkDataHolder.java @@ -20,6 +20,7 @@ package org.wso2.carbon.webapp.authenticator.framework.internal; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; @@ -35,6 +36,7 @@ public class AuthenticatorFrameworkDataHolder { private OAuth2TokenValidationService oAuth2TokenValidationService; private TenantIndexingLoader tenantIndexingLoader; private TenantRegistryLoader tenantRegistryLoader; + private DeviceManagementProviderService deviceManagementService; private static AuthenticatorFrameworkDataHolder thisInstance = new AuthenticatorFrameworkDataHolder(); @@ -114,4 +116,13 @@ public class AuthenticatorFrameworkDataHolder { public TenantRegistryLoader getTenantRegistryLoader() { return tenantRegistryLoader; } + + + public DeviceManagementProviderService getDeviceManagementService() { + return deviceManagementService; + } + + public void setDeviceManagementService(DeviceManagementProviderService deviceManagementService) { + this.deviceManagementService = deviceManagementService; + } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java index 36dd1c09c66..1fc7ba2bb98 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponent.java @@ -25,6 +25,7 @@ import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.identity.oauth2.OAuth2TokenValidationService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; @@ -80,6 +81,12 @@ import java.util.Properties; * cardinality="1..1" policy="dynamic" * bind="setTenantRegistryLoader" * unbind="unsetTenantRegistryLoader" + * @scr.reference name="org.wso2.carbon.device.manager" + * interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService" + * cardinality="1..1" + * policy="dynamic" + * bind="setDeviceManagementService" + * unbind="unsetDeviceManagementService" */ public class WebappAuthenticatorFrameworkServiceComponent { private static final Log log = LogFactory.getLog(WebappAuthenticatorFrameworkServiceComponent.class); @@ -211,4 +218,20 @@ public class WebappAuthenticatorFrameworkServiceComponent { protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegistryLoader) { AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(null); } + + @SuppressWarnings("unused") + protected void setDeviceManagementService(DeviceManagementProviderService deviceManagementProviderService) { + if (log.isDebugEnabled()) { + log.debug("Setting ApplicationDTO Management OSGI Manager"); + } + AuthenticatorFrameworkDataHolder.getInstance().setDeviceManagementService(deviceManagementProviderService); + } + + @SuppressWarnings("unused") + protected void unsetDeviceManagementService(DeviceManagementProviderService deviceManagementProviderService) { + if (log.isDebugEnabled()) { + log.debug("Removing ApplicationDTO Management OSGI Manager"); + } + AuthenticatorFrameworkDataHolder.getInstance().setDeviceManagementService(null); + } }