From a7e61318b8a2e9e45345c80b591a358f242613ad Mon Sep 17 00:00:00 2001 From: Madawa Soysa Date: Tue, 25 Apr 2017 11:06:02 +0530 Subject: [PATCH] Fixing multitenant issue in certificate verification endpoint --- ...nResponce.java => ValidationResponse.java} | 2 +- ...CertificateManagementAdminServiceImpl.java | 65 ++++++++++++++----- .../jwt/client/extension/JWTClient.java | 20 +++--- .../client/extension/util/JWTClientUtil.java | 37 ++++++----- 4 files changed, 80 insertions(+), 44 deletions(-) rename components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/{ValidationResponce.java => ValidationResponse.java} (97%) diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponse.java similarity index 97% rename from components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java rename to components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponse.java index 5a72112e4d..8774fc438d 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponce.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/beans/ValidationResponse.java @@ -19,7 +19,7 @@ package org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans; -public class ValidationResponce { +public class ValidationResponse { private String JWTToken; // X-JWT-Assertion private String deviceId; diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java index 3a8a39d3f8..3206d56a6d 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.cert.admin.api/src/main/java/org/wso2/carbon/certificate/mgt/cert/jaxrs/api/impl/CertificateManagementAdminServiceImpl.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2016-2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.certificate.mgt.cert.jaxrs.api.impl; import org.apache.commons.logging.Log; @@ -6,7 +24,7 @@ import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.CertificateManagementAdmin import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.CertificateList; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.EnrollmentCertificate; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ErrorResponse; -import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponce; +import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.beans.ValidationResponse; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.CertificateMgtAPIUtils; import org.wso2.carbon.certificate.mgt.cert.jaxrs.api.util.RequestValidationUtil; import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; @@ -232,30 +250,41 @@ public class CertificateManagementAdminServiceImpl implements CertificateManagem deviceIdentifier.setId(challengeToken); deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); TenantedDeviceWrapper tenantedDeviceWrapper = scepManager.getValidatedDevice(deviceIdentifier); -// -// var claims = {"http://wso2.org/claims/enduserTenantId": adminUserTenantId, -// "http://wso2.org/claims/enduser": adminUsername}; Map claims = new HashMap<>(); - claims.put("http://wso2.org/claims/enduserTenantId", String.valueOf(tenantedDeviceWrapper.getTenantId())); - claims.put("http://wso2.org/claims/enduser", tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner()); - claims.put("http://wso2.org/claims/deviceIdentifier", tenantedDeviceWrapper.getDevice().getDeviceIdentifier()); + claims.put("http://wso2.org/claims/enduserTenantId", + String.valueOf(tenantedDeviceWrapper.getTenantId())); + claims.put("http://wso2.org/claims/enduser", + tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner() + "@" + + tenantedDeviceWrapper.getTenantDomain()); + claims.put("http://wso2.org/claims/deviceIdentifier", + tenantedDeviceWrapper.getDevice().getDeviceIdentifier()); claims.put("http://wso2.org/claims/deviceIdType", tenantedDeviceWrapper.getDevice().getType()); - JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils.getJwtClientManagerService(); - String jwdToken = jwtClientManagerService.getJWTClient().getJwtToken( - tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner(), claims); + String jwdToken; + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext() + .setTenantId(tenantedDeviceWrapper.getTenantId()); + PrivilegedCarbonContext.getThreadLocalCarbonContext() + .setTenantDomain(tenantedDeviceWrapper.getTenantDomain()); + JWTClientManagerService jwtClientManagerService = CertificateMgtAPIUtils + .getJwtClientManagerService(); + jwdToken = jwtClientManagerService.getJWTClient() + .getJwtToken(tenantedDeviceWrapper.getDevice().getEnrolmentInfo().getOwner(), claims, + true); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } - ValidationResponce validationResponce = new ValidationResponce(); - validationResponce.setDeviceId(challengeToken); - validationResponce.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); - validationResponce.setJWTToken(jwdToken); - validationResponce.setTenantId(tenantedDeviceWrapper.getTenantId()); + ValidationResponse validationResponse = new ValidationResponse(); + validationResponse.setDeviceId(challengeToken); + validationResponse.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_IOS); + validationResponse.setJWTToken(jwdToken); + validationResponse.setTenantId(tenantedDeviceWrapper.getTenantId()); - if (tenantedDeviceWrapper != null) { - return Response.status(Response.Status.OK).entity(validationResponce).build(); - } + return Response.status(Response.Status.OK).entity(validationResponse).build(); } } diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java index dc51a2c9df..aea6607a9e 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/JWTClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -29,7 +29,7 @@ import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException;; +import org.json.simple.parser.ParseException; import org.wso2.carbon.identity.jwt.client.extension.constant.JWTConstants; import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo; import org.wso2.carbon.identity.jwt.client.extension.dto.JWTConfig; @@ -43,10 +43,11 @@ import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +; + /** * this class represents an implementation of Token Client which is based on JWT */ @@ -69,7 +70,7 @@ public class JWTClient { throws JWTClientException { List params = new ArrayList<>(); params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, jwtConfig.getJwtGrantType())); - String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient); + String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, false); if (assertion == null) { throw new JWTClientException("JWT is not configured properly for user : " + username); } @@ -84,7 +85,7 @@ public class JWTClient { throws JWTClientException { List params = new ArrayList<>(); params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, jwtConfig.getJwtGrantType())); - String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient); + String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, false); if (assertion == null) { throw new JWTClientException("JWT is not configured properly for user : " + username); } @@ -104,7 +105,7 @@ public class JWTClient { throws JWTClientException { List params = new ArrayList<>(); params.add(new BasicNameValuePair(JWTConstants.GRANT_TYPE_PARAM_NAME, jwtConfig.getJwtGrantType())); - String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient); + String assertion = JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, false); if (assertion == null) { throw new JWTClientException("JWT is not configured properly for user : " + username); } @@ -188,13 +189,16 @@ public class JWTClient { } public String getJwtToken(String username) throws JWTClientException { - return JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient); + return JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, false); } public String getJwtToken(String username, Map claims) throws JWTClientException { - return JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, claims); + return JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, claims, false); } + public String getJwtToken(String username, Map claims, boolean isTenantMode) throws JWTClientException { + return JWTClientUtil.generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, claims, isTenantMode); + } } diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java index cbce86c405..75ea7bfe31 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/main/java/org/wso2/carbon/identity/jwt/client/extension/util/JWTClientUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2016-2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -33,7 +33,6 @@ import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; -import org.apache.solr.common.util.Hash; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.util.KeyStoreManager; @@ -49,14 +48,22 @@ import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.utils.CarbonUtils; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URI; import java.net.URL; -import java.security.*; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.interfaces.RSAPrivateKey; import java.util.Date; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; @@ -200,15 +207,14 @@ public class JWTClientUtil { tenantRegistryLoader.loadTenantRegistry(tenantId); } - public static String generateSignedJWTAssertion(String username, JWTConfig jwtConfig, boolean isDefaultJWTClient) - throws JWTClientException { - return generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, null); - } + public static String generateSignedJWTAssertion(String username, JWTConfig jwtConfig, boolean isDefaultJWTClient, + boolean isMultiTenantMode) throws JWTClientException { + return generateSignedJWTAssertion(username, jwtConfig, isDefaultJWTClient, null, isMultiTenantMode); + } public static String generateSignedJWTAssertion(String username, JWTConfig jwtConfig, boolean isDefaultJWTClient, - Map customClaims) throws JWTClientException { + Map customClaims, boolean isMultiTenantMode) throws JWTClientException { try { - String subject = username; long currentTimeMillis = System.currentTimeMillis(); // add the skew between servers String iss = jwtConfig.getIssuer(); @@ -246,26 +252,23 @@ public class JWTClientUtil { String privateKeyAlias = jwtConfig.getPrivateKeyAlias(); String privateKeyPassword = jwtConfig.getPrivateKeyPassword(); KeyStore keyStore; - RSAPrivateKey rsaPrivateKey = null; - if (keyStorePath != null && !keyStorePath.isEmpty()) { + RSAPrivateKey rsaPrivateKey; + if (!isMultiTenantMode && (keyStorePath != null && !keyStorePath.isEmpty())) { String keyStorePassword = jwtConfig.getKeyStorePassword(); keyStore = loadKeyStore(new File(keyStorePath), keyStorePassword, "JKS"); rsaPrivateKey = (RSAPrivateKey) keyStore.getKey(privateKeyAlias, privateKeyPassword.toCharArray()); } else { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); JWTClientUtil.loadTenantRegistry(tenantId); - if (!(MultitenantConstants.SUPER_TENANT_ID == tenantId) && !isDefaultJWTClient) { + if (isMultiTenantMode || !(MultitenantConstants.SUPER_TENANT_ID == tenantId) && !isDefaultJWTClient) { KeyStoreManager tenantKeyStoreManager = KeyStoreManager.getInstance(tenantId); String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true); String ksName = tenantDomain.trim().replace('.', '-'); String jksName = ksName + ".jks"; rsaPrivateKey = (RSAPrivateKey) tenantKeyStoreManager.getPrivateKey(jksName, tenantDomain); } else { - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); KeyStoreManager tenantKeyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID); rsaPrivateKey = (RSAPrivateKey) tenantKeyStoreManager.getDefaultPrivateKey(); - PrivilegedCarbonContext.endTenantFlow(); } } JWSSigner signer = new RSASSASigner(rsaPrivateKey);