From 7e5501def1ef2af526cef8ddfc16f5de57c424f0 Mon Sep 17 00:00:00 2001 From: geethkokila Date: Mon, 4 Sep 2017 11:57:38 +0530 Subject: [PATCH] Adding the certificate caching to improve performance --- .../pom.xml | 1 + .../core/cache/CertificateCacheManager.java | 39 ++++++ .../impl/CertificateCacheManagerImpl.java | 132 ++++++++++++++++++ .../mgt/core/impl/KeyStoreReader.java | 44 +++--- .../core/config/DeviceManagementConfig.java | 11 ++ .../cache/CertificateCacheConfiguration.java | 47 +++++++ .../mgt/core/util/DeviceManagerUtil.java | 8 +- .../src/main/resources/conf/cdm-config.xml | 4 + 8 files changed, 265 insertions(+), 21 deletions(-) create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/CertificateCacheManager.java create mode 100644 components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/impl/CertificateCacheManagerImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/cache/CertificateCacheConfiguration.java diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml index 1c343c5216..ec0d8325c2 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml @@ -94,6 +94,7 @@ io.swagger.annotations.*;resolution:=optional, org.wso2.carbon.device.mgt.core.*, org.wso2.carbon.registry.indexing.*, + javax.cache.* diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/CertificateCacheManager.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/CertificateCacheManager.java new file mode 100644 index 0000000000..c5fe9715cc --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/CertificateCacheManager.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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.core.cache; + +import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; + +/** + * This interface for caching the certificates. + */ + +public interface CertificateCacheManager { + + void addCertificateBySerial(String serialNumber, CertificateResponse certificate) ; + + void addCertificateByCN(String commonName, CertificateResponse certificate) ; + + CertificateResponse getCertificateBySerial(String serialNumber) ; + + CertificateResponse getCertificateByCN(String commonName) ; + +} + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/impl/CertificateCacheManagerImpl.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/impl/CertificateCacheManagerImpl.java new file mode 100644 index 0000000000..b76af59b3e --- /dev/null +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/cache/impl/CertificateCacheManagerImpl.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 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.core.cache.impl; + +import org.wso2.carbon.certificate.mgt.core.cache.CertificateCacheManager; +import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; +import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; + +import javax.cache.Cache; +import javax.cache.CacheConfiguration; +import javax.cache.CacheManager; +import javax.cache.Caching; +import java.util.concurrent.TimeUnit; + +public class CertificateCacheManagerImpl implements CertificateCacheManager { + + public static final String CERTIFICATE_CACHE_MANAGER = "CERTIFICATE_CACHE_MANAGER"; + public static final String CERTIFICATE_CACHE = "CERTIFICATE_CACHE"; + private static boolean isCertificateCacheInitialized = false; + private static String SERIAL_PRE = "S_"; + private static String COMMON_NAME_PRE = "C_"; + + private static CertificateCacheManager certificateCacheManager; + + + private CertificateCacheManagerImpl() { + } + + public static CertificateCacheManager getInstance() { + if (certificateCacheManager == null) { + synchronized (CertificateCacheManagerImpl.class) { + if (certificateCacheManager == null) { + certificateCacheManager = new CertificateCacheManagerImpl(); + } + } + } + return certificateCacheManager; + } + + @Override + public void addCertificateBySerial(String serialNumber, CertificateResponse certificate) { + CertificateCacheManagerImpl.getCertificateCache().put(SERIAL_PRE + serialNumber, certificate); + } + + @Override + public void addCertificateByCN(String commonName, CertificateResponse certificate) { + CertificateCacheManagerImpl.getCertificateCache().put(COMMON_NAME_PRE + commonName, certificate); + } + + @Override + public CertificateResponse getCertificateBySerial(String serialNumber) { + return CertificateCacheManagerImpl.getCertificateCache().get(SERIAL_PRE + serialNumber); + } + + @Override + public CertificateResponse getCertificateByCN(String commonName) { + return CertificateCacheManagerImpl.getCertificateCache().get(COMMON_NAME_PRE + commonName); + } + + + private static CacheManager getCacheManager() { + return Caching.getCacheManagerFactory().getCacheManager(CertificateCacheManagerImpl.CERTIFICATE_CACHE_MANAGER); + } + + public static Cache getCertificateCache() { + DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); + CacheManager manager = getCacheManager(); + Cache certificateCache = null; + if (config.getDeviceCacheConfiguration().isEnabled()) { + if (!isCertificateCacheInitialized) { + initializeCertificateCache(); + } + if (manager != null) { + certificateCache = manager.getCache(CertificateCacheManagerImpl.CERTIFICATE_CACHE); + } else { + certificateCache = Caching.getCacheManager(CertificateCacheManagerImpl.CERTIFICATE_CACHE_MANAGER). + getCache(CertificateCacheManagerImpl.CERTIFICATE_CACHE); + } + } + return certificateCache; + } + + public static void initializeCertificateCache() { + DeviceManagementConfig config = DeviceConfigurationManager.getInstance().getDeviceManagementConfig(); + int certificateCacheExpiry = config.getCertificateCacheConfiguration().getExpiryTime(); + CacheManager manager = getCacheManager(); + if (config.getCertificateCacheConfiguration().isEnabled()) { + if (!isCertificateCacheInitialized) { + isCertificateCacheInitialized = true; + if (manager != null) { + if (certificateCacheExpiry > 0) { + manager.createCacheBuilder(CertificateCacheManagerImpl.CERTIFICATE_CACHE). + setExpiry(CacheConfiguration.ExpiryType.MODIFIED, new CacheConfiguration.Duration(TimeUnit.SECONDS, + certificateCacheExpiry)).setExpiry(CacheConfiguration.ExpiryType.ACCESSED, new CacheConfiguration. + Duration(TimeUnit.SECONDS, certificateCacheExpiry)).setStoreByValue(true).build(); + } else { + manager.getCache(CertificateCacheManagerImpl.CERTIFICATE_CACHE); + } + } else { + if (certificateCacheExpiry > 0) { + Caching.getCacheManager(). + createCacheBuilder(CertificateCacheManagerImpl.CERTIFICATE_CACHE). + setExpiry(CacheConfiguration.ExpiryType.MODIFIED, new CacheConfiguration.Duration(TimeUnit.SECONDS, + certificateCacheExpiry)).setExpiry(CacheConfiguration.ExpiryType.ACCESSED, new CacheConfiguration. + Duration(TimeUnit.SECONDS, certificateCacheExpiry)).setStoreByValue(true).build(); + } else { + Caching.getCacheManager().getCache(CertificateCacheManagerImpl.CERTIFICATE_CACHE); + } + } + } + } + } +} + diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/KeyStoreReader.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/KeyStoreReader.java index 594ceeec9b..60a7800863 100755 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/KeyStoreReader.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/KeyStoreReader.java @@ -19,6 +19,8 @@ package org.wso2.carbon.certificate.mgt.core.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.certificate.mgt.core.cache.CertificateCacheManager; +import org.wso2.carbon.certificate.mgt.core.cache.impl.CertificateCacheManagerImpl; import org.wso2.carbon.certificate.mgt.core.config.CertificateConfigurationManager; import org.wso2.carbon.certificate.mgt.core.config.CertificateKeystoreConfig; import org.wso2.carbon.certificate.mgt.core.dao.CertificateDAO; @@ -126,8 +128,8 @@ public class KeyStoreReader { CertificateKeystoreConfig certificateKeystoreConfig = CertificateConfigurationManager.getInstance(). getCertificateKeyStoreConfig(); keyStore = loadKeyStore(certificateKeystoreConfig.getCertificateKeystoreType(), - certificateKeystoreConfig.getCertificateKeystoreLocation(), - certificateKeystoreConfig.getCertificateKeystorePassword()); + certificateKeystoreConfig.getCertificateKeystoreLocation(), + certificateKeystoreConfig.getCertificateKeystorePassword()); } catch (CertificateManagementException e) { String errorMsg = "Unable to find KeyStore configuration in certificate-mgt.config file."; throw new KeystoreException(errorMsg, e); @@ -140,7 +142,7 @@ public class KeyStoreReader { CertificateKeystoreConfig certificateKeystoreConfig = CertificateConfigurationManager.getInstance(). getCertificateKeyStoreConfig(); saveKeyStore(keyStore, certificateKeystoreConfig.getCertificateKeystoreLocation(), - certificateKeystoreConfig.getCertificateKeystorePassword()); + certificateKeystoreConfig.getCertificateKeystorePassword()); } catch (CertificateManagementException e) { String errorMsg = "Unable to find KeyStore configuration in certificate-mgt.config file."; throw new KeystoreException(errorMsg, e); @@ -251,7 +253,7 @@ public class KeyStoreReader { CertificateKeystoreConfig certificateKeystoreConfig = CertificateConfigurationManager.getInstance(). getCertificateKeyStoreConfig(); raPrivateKey = (PrivateKey) keystore.getKey(certificateKeystoreConfig.getRACertAlias(), - certificateKeystoreConfig.getRAPrivateKeyPassword().toCharArray()); + certificateKeystoreConfig.getRAPrivateKeyPassword().toCharArray()); } catch (UnrecoverableKeyException e) { String errorMsg = "Key is unrecoverable when retrieving RA private key"; throw new KeystoreException(errorMsg, e); @@ -276,28 +278,36 @@ public class KeyStoreReader { public CertificateResponse getCertificateBySerial(String serialNumber) throws KeystoreException { CertificateResponse certificateResponse = null; try { - CertificateManagementDAOFactory.openConnection(); - certificateResponse = certDao.retrieveCertificate(serialNumber); - if (certificateResponse != null && certificateResponse.getCertificate() != null) { - Certificate certificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate()); - if (certificate instanceof X509Certificate) { - X509Certificate x509cert = (X509Certificate) certificate; - String commonName = CertificateGenerator.getCommonName(x509cert); - certificateResponse.setCommonName(commonName); + CertificateCacheManager cacheManager = CertificateCacheManagerImpl.getInstance(); + certificateResponse = cacheManager.getCertificateBySerial(serialNumber); + if (certificateResponse == null) { + try { + CertificateManagementDAOFactory.openConnection(); + certificateResponse = certDao.retrieveCertificate(serialNumber); + } catch (SQLException e) { + String errorMsg = "Error when making a connection to the database."; + throw new KeystoreException(errorMsg, e); + } finally { + CertificateManagementDAOFactory.closeConnection(); + } + if (certificateResponse != null && certificateResponse.getCertificate() != null) { + Certificate certificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate()); + if (certificate instanceof X509Certificate) { + X509Certificate x509cert = (X509Certificate) certificate; + String commonName = CertificateGenerator.getCommonName(x509cert); + certificateResponse.setCommonName(commonName); + cacheManager.addCertificateBySerial(serialNumber, certificateResponse); + } } } } catch (CertificateManagementDAOException e) { String errorMsg = "Error when retrieving certificate from the the database for the serial number: " + serialNumber; throw new KeystoreException(errorMsg, e); - } catch (SQLException e) { - String errorMsg = "Error when making a connection to the database."; - throw new KeystoreException(errorMsg, e); + } catch (ClassNotFoundException | IOException e) { String errorMsg = "Error when de-serializing saved certificate."; throw new KeystoreException(errorMsg, e); - } finally { - CertificateManagementDAOFactory.closeConnection(); } return certificateResponse; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java index 5d757f4f0b..72f9944fb2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceManagementConfig.java @@ -17,6 +17,7 @@ */ package org.wso2.carbon.device.mgt.core.config; +import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration; import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration; import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations; @@ -46,6 +47,7 @@ public final class DeviceManagementConfig { private PullNotificationConfiguration pullNotificationConfiguration; private DeviceStatusTaskConfig deviceStatusTaskConfig; private DeviceCacheConfiguration deviceCacheConfiguration; + private CertificateCacheConfiguration certificateCacheConfiguration; private GeoLocationConfiguration geoLocationConfiguration; private String defaultGroupsConfiguration; @@ -131,6 +133,15 @@ public final class DeviceManagementConfig { this.deviceCacheConfiguration = deviceCacheConfiguration; } + @XmlElement(name = "CertificateCacheConfiguration", required = true) + public CertificateCacheConfiguration getCertificateCacheConfiguration() { + return certificateCacheConfiguration; + } + + public void setCertificateCacheConfiguration(CertificateCacheConfiguration certificateCacheConfiguration) { + this.certificateCacheConfiguration = certificateCacheConfiguration; + } + @XmlElement(name = "GeoLocationConfiguration", required = true) public GeoLocationConfiguration getGeoLocationConfiguration() { return geoLocationConfiguration; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/cache/CertificateCacheConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/cache/CertificateCacheConfiguration.java new file mode 100644 index 0000000000..541fbda7a2 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/cache/CertificateCacheConfiguration.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 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.device.mgt.core.config.cache; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "CertificateCacheConfiguration") +public class CertificateCacheConfiguration { + + private boolean isEnabled; + private int expiryTime; + + @XmlElement(name = "Enable", required = true) + public boolean isEnabled() { + return isEnabled; + } + + public void setEnabled(boolean enabled) { + isEnabled = enabled; + } + + @XmlElement(name = "ExpiryTime", required = true) + public int getExpiryTime() { + return expiryTime; + } + + public void setExpiryTime(int expiryTime) { + this.expiryTime = expiryTime; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 50582799ce..c3ceec40b7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -76,7 +76,7 @@ public final class DeviceManagerUtil { private static final Log log = LogFactory.getLog(DeviceManagerUtil.class); - private static boolean isDeviceCacheInistialized = false; + private static boolean isDeviceCacheInitialized = false; public static Document convertToDocument(File file) throws DeviceManagementException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); @@ -494,8 +494,8 @@ public final class DeviceManagerUtil { int deviceCacheExpiry = config.getDeviceCacheConfiguration().getExpiryTime(); CacheManager manager = getCacheManager(); if (config.getDeviceCacheConfiguration().isEnabled()) { - if(!isDeviceCacheInistialized) { - isDeviceCacheInistialized = true; + if(!isDeviceCacheInitialized) { + isDeviceCacheInitialized = true; if (manager != null) { if (deviceCacheExpiry > 0) { manager.createCacheBuilder(DeviceManagementConstants.DEVICE_CACHE). @@ -525,7 +525,7 @@ public final class DeviceManagerUtil { CacheManager manager = getCacheManager(); Cache deviceCache = null; if (config.getDeviceCacheConfiguration().isEnabled()) { - if(!isDeviceCacheInistialized) { + if(!isDeviceCacheInitialized) { initializeDeviceCache(); } if (manager != null) { diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml index fbf6103cff..1368469451 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.server.feature/src/main/resources/conf/cdm-config.xml @@ -78,6 +78,10 @@ true 600 + + true + 86400 + false false