From 6e92cb8913c67e92fd4f02bec52d5f19e69c3955 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Thu, 31 Oct 2024 17:28:47 +0530 Subject: [PATCH 1/8] add ssl sender reloader --- .../IKeyStoreLoader.java | 9 ++++++ .../KeyStoreReloader.java | 32 +++++++++++++++++++ .../KeyStoreReloaderHolder.java | 28 ++++++++++++++++ .../passthru/PassThroughHttpSSLSender.java | 11 ++++++- .../passthru/PassThroughHttpSender.java | 12 +++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java create mode 100644 modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java create mode 100644 modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java new file mode 100644 index 0000000000..6f8d8c0220 --- /dev/null +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java @@ -0,0 +1,9 @@ +package org.apache.synapse.transport.dynamicconfigurations; + +import org.apache.axis2.AxisFault; +import org.apache.axis2.description.ParameterInclude; + +public interface IKeyStoreLoader { + + void loadKeyStore(ParameterInclude transport) throws AxisFault; +} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java new file mode 100644 index 0000000000..e907f9d761 --- /dev/null +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java @@ -0,0 +1,32 @@ +package org.apache.synapse.transport.dynamicconfigurations; + +import org.apache.axis2.AxisFault; +import org.apache.axis2.description.ParameterInclude; + +public class KeyStoreReloader { + + private IKeyStoreLoader keyStoreLoader; + private ParameterInclude transportOutDescription; + + public KeyStoreReloader(IKeyStoreLoader keyStoreLoader, ParameterInclude transportOutDescription) { + + this.keyStoreLoader = keyStoreLoader; + this.transportOutDescription = transportOutDescription; + + registerListener(transportOutDescription); + } + + private void registerListener(ParameterInclude transportOutDescription) { + + KeyStoreReloaderHolder.getInstance().addKeyStoreLoader(this); + } + + public void update() { + + try { + keyStoreLoader.loadKeyStore(transportOutDescription); + } catch (AxisFault e) { + throw new RuntimeException(e); + } + } +} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java new file mode 100644 index 0000000000..9e7b19e3db --- /dev/null +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java @@ -0,0 +1,28 @@ +package org.apache.synapse.transport.dynamicconfigurations; + +import java.util.ArrayList; +import java.util.List; + +public class KeyStoreReloaderHolder { + + private static KeyStoreReloaderHolder instance = new KeyStoreReloaderHolder(); + private List keyStoreLoaders; + + private KeyStoreReloaderHolder() { + keyStoreLoaders = new ArrayList<>(); + } + + public static KeyStoreReloaderHolder getInstance() { + return instance; + } + + public void addKeyStoreLoader(KeyStoreReloader keyStoreLoader) { + keyStoreLoaders.add(keyStoreLoader); + } + + public void reloadAllKeyStores() { + for (KeyStoreReloader keyStoreLoader : keyStoreLoaders) { + keyStoreLoader.update(); + } + } +} diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSSLSender.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSSLSender.java index 5fe55383d0..f10541807c 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSSLSender.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSSLSender.java @@ -21,18 +21,21 @@ import org.apache.axis2.description.ParameterInclude; import org.apache.axis2.description.TransportOutDescription; import org.apache.synapse.transport.certificatevalidation.cache.CertCache; +import org.apache.synapse.transport.dynamicconfigurations.IKeyStoreLoader; +import org.apache.synapse.transport.dynamicconfigurations.KeyStoreReloader; import org.apache.synapse.transport.dynamicconfigurations.SSLProfileLoader; import org.apache.synapse.transport.dynamicconfigurations.SenderProfileReloader; import org.apache.synapse.transport.http.conn.Scheme; import org.apache.synapse.transport.nhttp.config.ClientConnFactoryBuilder; import org.apache.synapse.transport.nhttp.config.TrustStoreHolder; -public class PassThroughHttpSSLSender extends PassThroughHttpSender implements SSLProfileLoader { +public class PassThroughHttpSSLSender extends PassThroughHttpSender implements SSLProfileLoader, IKeyStoreLoader { @Override public void init(ConfigurationContext configurationContext, TransportOutDescription transportOutDescription) throws AxisFault { super.init(configurationContext, transportOutDescription); + new KeyStoreReloader(this, transportOutDescription); new SenderProfileReloader(this, transportOutDescription); } @@ -60,4 +63,10 @@ public void reloadConfig(ParameterInclude transport) throws AxisFault { reloadDynamicSSLConfig((TransportOutDescription) transport); } + @Override + public void loadKeyStore(ParameterInclude transport) throws AxisFault { + CertCache.resetCache(); + TrustStoreHolder.resetInstance(); + reloadSSL((TransportOutDescription) transport); + } } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java index 3af961c03f..ccb24756c1 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/PassThroughHttpSender.java @@ -722,6 +722,18 @@ public void reloadDynamicSSLConfig(TransportOutDescription transport) throws Axi } } + public void reloadSSL(TransportOutDescription transport) throws AxisFault { + log.info("PassThroughHttpSender SSL Config.."); + ClientConnFactoryBuilder connFactoryBuilder = + initConnFactoryBuilder(transport, this.configurationContext).parseSSL(); + connFactory = connFactoryBuilder.createConnFactory(targetConfiguration.getHttpParams()); + + handler.setConnFactory(connFactory); + ioEventDispatch.setConnFactory(connFactory); + + log.info("Pass-through " + namePrefix + " Sender updated with SSL Configuration Updates ..."); + } + /** * Set content type headers along with the charactor encoding if content type header is not preserved * @param msgContext message context From a57581d8bc9cbddd3b67261933715a3da32c2614 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Mon, 25 Nov 2024 23:49:21 +0530 Subject: [PATCH 2/8] update ssl sender trust store holder --- .../config/ClientConnFactoryBuilder.java | 15 +++++++++++--- .../config/SslSenderTrustStoreHolder.java | 20 ++++++++++++++++++- .../config/SslSenderTrustStoreHolderTest.java | 14 +++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java index 66fde8487c..d85def1532 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ClientConnFactoryBuilder.java @@ -370,14 +370,18 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE if (log.isDebugEnabled()) { log.debug(name + " Loading Trust Keystore from : " + location); } - SslSenderTrustStoreHolder.getInstance().setLocation(location); - SslSenderTrustStoreHolder.getInstance().setPassword(passwordElement.getText()); - SslSenderTrustStoreHolder.getInstance().setType(type); + trustStore.load(fis, storePassword.toCharArray()); TrustManagerFactory trustManagerfactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerfactory.init(trustStore); trustManagers = trustManagerfactory.getTrustManagers(); + + SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); + sslSenderTrustStoreHolder.setKeyStore(trustStore); + sslSenderTrustStoreHolder.setLocation(location); + sslSenderTrustStoreHolder.setPassword(storePassword); + SslSenderTrustStoreHolder.getInstance().setType(type); } catch (GeneralSecurityException gse) { log.error(name + " Error loading Key store : " + location, gse); throw new AxisFault("Error loading Key store : " + location, gse); @@ -472,6 +476,11 @@ private SSLContext createSSLContext(OMElement keyStoreElt, OMElement trustStoreE trustManagerfactory.init(trustStore); trustManagers = trustManagerfactory.getTrustManagers(); + SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); + sslSenderTrustStoreHolder.setKeyStore(trustStore); + sslSenderTrustStoreHolder.setLocation(location); + sslSenderTrustStoreHolder.setPassword(storePassword); + } catch (GeneralSecurityException gse) { log.error(name + " Error loading Key store : " + location, gse); throw new AxisFault("Error loading Key store : " + location, gse); diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java index ae1a4dcb6d..cb7ef8884c 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java @@ -17,6 +17,8 @@ */ package org.apache.synapse.transport.nhttp.config; +import java.security.KeyStore; + /** * The SSL Sender TrustStore Holder class to store the client trust store's configurable details. */ @@ -26,6 +28,7 @@ public class SslSenderTrustStoreHolder { private SslSenderTrustStoreHolder() {} + private KeyStore keyStore; private String location; private String password; private String type; @@ -33,7 +36,7 @@ private SslSenderTrustStoreHolder() {} public static SslSenderTrustStoreHolder getInstance() { if (instance == null) { - synchronized (TrustStoreHolder.class) { + synchronized (SslSenderTrustStoreHolder.class) { if (instance == null) { instance = new SslSenderTrustStoreHolder(); } @@ -42,6 +45,21 @@ public static SslSenderTrustStoreHolder getInstance() { return instance; } + public static void resetInstance() { + + instance = null; + } + + public KeyStore getKeyStore() { + + return keyStore; + } + + public void setKeyStore(KeyStore keyStore) { + + this.keyStore = keyStore; + } + public void setLocation(String location) { this.location = location; } diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java new file mode 100644 index 0000000000..e220083b19 --- /dev/null +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java @@ -0,0 +1,14 @@ +package org.apache.synapse.transport.nhttp.config; + +import org.junit.Assert; +import org.junit.Test; + +public class SslSenderTrustStoreHolderTest { + + @Test + public void testGetInstance() { + SslSenderTrustStoreHolder instance = SslSenderTrustStoreHolder.getInstance(); + SslSenderTrustStoreHolder instance2 = SslSenderTrustStoreHolder.getInstance(); + Assert.assertEquals(instance, instance2); + } +} From 01c54c3960bc32ca063877fb602588862adbcefe Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Sat, 30 Nov 2024 10:55:55 +0530 Subject: [PATCH 3/8] handle certificate in http connection by loading it to the trust store --- .../synapse/deployers/LocalEntryDeployer.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java index ab6df62101..f7d652a5db 100644 --- a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java +++ b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java @@ -21,16 +21,34 @@ import org.apache.axiom.om.OMElement; import org.apache.axis2.deployment.DeploymentException; +import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.io.FileUtils; +import org.apache.synapse.SynapseConstants; import org.apache.synapse.config.Entry; import org.apache.synapse.config.xml.EntryFactory; import org.apache.synapse.config.xml.EntrySerializer; import org.apache.synapse.config.xml.MultiXMLConfigurationBuilder; +import org.apache.synapse.transport.dynamicconfigurations.KeyStoreReloaderHolder; +import org.apache.synapse.transport.nhttp.config.SslSenderTrustStoreHolder; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.util.Iterator; import java.util.Properties; +import javax.xml.namespace.QName; + /** * Handles the LocalEntry deployment and undeployment tasks * @@ -39,6 +57,10 @@ public class LocalEntryDeployer extends AbstractSynapseArtifactDeployer { private static Log log = LogFactory.getLog(LocalEntryDeployer.class); + private static final String RESOURCES_IDENTIFIER = "resources:"; + private static final String CONVERTED_RESOURCES_IDENTIFIER = "gov:mi-resources" + File.separator; + private static final String HTTP_CONNECTION_IDENTIFIER = "http.init"; + private static final String CERTIFICATE_EXTENSION = ".crt"; @Override public String deploySynapseArtifact(OMElement artifactConfig, String fileName, @@ -66,6 +88,7 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, } log.info("LocalEntry named '" + e.getKey() + "' has been deployed from file : " + fileName); + handleHttpConnectorCertificates(artifactConfig); return e.getKey(); } else { handleSynapseArtifactDeploymentError("LocalEntry Deployment Failed. The artifact " + @@ -79,6 +102,66 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, return null; } + private void handleHttpConnectorCertificates(OMElement element) throws DeploymentException { + + OMElement httpInitElement = + element.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE, HTTP_CONNECTION_IDENTIFIER)); + if (httpInitElement != null) { + Iterator childElementIterator = httpInitElement.getChildElements(); + while (childElementIterator.hasNext()) { + OMElement childElement = (OMElement) childElementIterator.next(); + String childElementValue = childElement.getText(); + String transformedElementValue = getTransformedElementValue(childElementValue); + if (transformedElementValue.endsWith(CERTIFICATE_EXTENSION)) { + loadCertificateFileToStore(transformedElementValue); + } + } + } + } + + private void loadCertificateFileToStore(String certificateFileResourceKey) throws DeploymentException { + + String certificateFilePath = getSynapseConfiguration().getRegistry().getRegistryEntry(certificateFileResourceKey).getName(); + File certificateFile = new File(certificateFilePath); + String certificateAlias = certificateFile.getName().split("\\.")[0]; + try { + FileInputStream certificateFileInputStream = FileUtils.openInputStream(new File(certificateFilePath)); + SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); + KeyStore sslSenderTrustStore = sslSenderTrustStoreHolder.getKeyStore(); + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Certificate certificate = certificateFactory.generateCertificate(certificateFileInputStream); + sslSenderTrustStore.setCertificateEntry(certificateAlias, certificate); + + FileOutputStream fileOutputStream = new FileOutputStream(sslSenderTrustStoreHolder.getLocation()); + sslSenderTrustStore.store(fileOutputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + + FileInputStream fileInputStream = new FileInputStream(sslSenderTrustStoreHolder.getLocation()); + InputStream dest = IOUtils.toBufferedInputStream(fileInputStream); + fileInputStream.close(); + sslSenderTrustStore.load(dest, sslSenderTrustStoreHolder.getPassword().toCharArray()); + dest.close(); + + sslSenderTrustStoreHolder.setKeyStore(sslSenderTrustStore); + KeyStoreReloaderHolder.getInstance().reloadAllKeyStores(); + } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * Transforms the given element value if it indicates a resource file. + * + * @param elementValue the value of the element to be transformed + * @return the transformed element value + */ + private String getTransformedElementValue(String elementValue) { + String transformedElementValue = elementValue.trim(); + if (transformedElementValue.startsWith(RESOURCES_IDENTIFIER)) { + transformedElementValue = transformedElementValue.replace(RESOURCES_IDENTIFIER, CONVERTED_RESOURCES_IDENTIFIER); + } + return transformedElementValue; + } + @Override public String updateSynapseArtifact(OMElement artifactConfig, String fileName, String existingArtifactName, Properties properties) { From 2056ce22b746c929177e338fe891a2e630c804b1 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Tue, 3 Dec 2024 09:58:54 +0530 Subject: [PATCH 4/8] add license headers --- .../dynamicconfigurations/IKeyStoreLoader.java | 17 +++++++++++++++++ .../dynamicconfigurations/KeyStoreReloader.java | 17 +++++++++++++++++ .../KeyStoreReloaderHolder.java | 17 +++++++++++++++++ .../config/SslSenderTrustStoreHolderTest.java | 17 +++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java index 6f8d8c0220..11977260ef 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/IKeyStoreLoader.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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.apache.synapse.transport.dynamicconfigurations; import org.apache.axis2.AxisFault; diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java index e907f9d761..d91356226c 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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.apache.synapse.transport.dynamicconfigurations; import org.apache.axis2.AxisFault; diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java index 9e7b19e3db..810b456f27 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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.apache.synapse.transport.dynamicconfigurations; import java.util.ArrayList; diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java index e220083b19..1fa0b8818c 100644 --- a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. 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.apache.synapse.transport.nhttp.config; import org.junit.Assert; From b5e89c8c935b1003986664de74c78a40485506c0 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Tue, 3 Dec 2024 10:31:29 +0530 Subject: [PATCH 5/8] use try catch with resources --- .../synapse/deployers/LocalEntryDeployer.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java index f7d652a5db..b7457bdd0d 100644 --- a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java +++ b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java @@ -124,27 +124,29 @@ private void loadCertificateFileToStore(String certificateFileResourceKey) throw String certificateFilePath = getSynapseConfiguration().getRegistry().getRegistryEntry(certificateFileResourceKey).getName(); File certificateFile = new File(certificateFilePath); String certificateAlias = certificateFile.getName().split("\\.")[0]; - try { - FileInputStream certificateFileInputStream = FileUtils.openInputStream(new File(certificateFilePath)); + try (FileInputStream certificateFileInputStream = FileUtils.openInputStream(new File(certificateFilePath))) { SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); KeyStore sslSenderTrustStore = sslSenderTrustStoreHolder.getKeyStore(); + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); Certificate certificate = certificateFactory.generateCertificate(certificateFileInputStream); sslSenderTrustStore.setCertificateEntry(certificateAlias, certificate); - FileOutputStream fileOutputStream = new FileOutputStream(sslSenderTrustStoreHolder.getLocation()); - sslSenderTrustStore.store(fileOutputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + try (FileOutputStream fileOutputStream = new FileOutputStream(sslSenderTrustStoreHolder.getLocation())) { + sslSenderTrustStore.store(fileOutputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + } - FileInputStream fileInputStream = new FileInputStream(sslSenderTrustStoreHolder.getLocation()); - InputStream dest = IOUtils.toBufferedInputStream(fileInputStream); - fileInputStream.close(); - sslSenderTrustStore.load(dest, sslSenderTrustStoreHolder.getPassword().toCharArray()); - dest.close(); + try ( + FileInputStream fileInputStream = new FileInputStream(sslSenderTrustStoreHolder.getLocation()); + InputStream bufferedInputStream = IOUtils.toBufferedInputStream(fileInputStream) + ) { + sslSenderTrustStore.load(bufferedInputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + } sslSenderTrustStoreHolder.setKeyStore(sslSenderTrustStore); KeyStoreReloaderHolder.getInstance().reloadAllKeyStores(); } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException e) { - throw new RuntimeException(e); + throw new DeploymentException("Failed to load certificate file to store: " + certificateFilePath, e); } } From e2e29bfe37673d600a806454439c871c3115ba84 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Tue, 3 Dec 2024 10:47:59 +0530 Subject: [PATCH 6/8] update throwing exceptions --- .../transport/dynamicconfigurations/KeyStoreReloader.java | 8 ++------ .../dynamicconfigurations/KeyStoreReloaderHolder.java | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java index d91356226c..a077b35174 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloader.java @@ -38,12 +38,8 @@ private void registerListener(ParameterInclude transportOutDescription) { KeyStoreReloaderHolder.getInstance().addKeyStoreLoader(this); } - public void update() { + public void update() throws AxisFault { - try { - keyStoreLoader.loadKeyStore(transportOutDescription); - } catch (AxisFault e) { - throw new RuntimeException(e); - } + keyStoreLoader.loadKeyStore(transportOutDescription); } } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java index 810b456f27..dbfbe984e6 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/dynamicconfigurations/KeyStoreReloaderHolder.java @@ -17,6 +17,8 @@ */ package org.apache.synapse.transport.dynamicconfigurations; +import org.apache.axis2.AxisFault; + import java.util.ArrayList; import java.util.List; @@ -37,7 +39,7 @@ public void addKeyStoreLoader(KeyStoreReloader keyStoreLoader) { keyStoreLoaders.add(keyStoreLoader); } - public void reloadAllKeyStores() { + public void reloadAllKeyStores() throws AxisFault { for (KeyStoreReloader keyStoreLoader : keyStoreLoaders) { keyStoreLoader.update(); } From 8cf0e929ffd762934359067f332742b25311fa74 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Tue, 3 Dec 2024 10:49:23 +0530 Subject: [PATCH 7/8] add assert message --- .../transport/nhttp/config/SslSenderTrustStoreHolderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java index 1fa0b8818c..4389f5fd17 100644 --- a/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java +++ b/modules/transports/core/nhttp/src/test/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolderTest.java @@ -26,6 +26,6 @@ public class SslSenderTrustStoreHolderTest { public void testGetInstance() { SslSenderTrustStoreHolder instance = SslSenderTrustStoreHolder.getInstance(); SslSenderTrustStoreHolder instance2 = SslSenderTrustStoreHolder.getInstance(); - Assert.assertEquals(instance, instance2); + Assert.assertEquals("Instances should be the same.", instance, instance2); } } From 7a2806cb1e31f490818db2ac9d231885cd0f2889 Mon Sep 17 00:00:00 2001 From: chathurangaj Date: Wed, 4 Dec 2024 22:15:12 +0530 Subject: [PATCH 8/8] separate loading certificate to jks and getting updated ssl --- .../synapse/deployers/LocalEntryDeployer.java | 48 +++++++++++-------- .../config/SslSenderTrustStoreHolder.java | 5 ++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java index b7457bdd0d..97539f8094 100644 --- a/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java +++ b/modules/core/src/main/java/org/apache/synapse/deployers/LocalEntryDeployer.java @@ -88,7 +88,7 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, } log.info("LocalEntry named '" + e.getKey() + "' has been deployed from file : " + fileName); - handleHttpConnectorCertificates(artifactConfig); + handleSSLSenderCertificates(artifactConfig); return e.getKey(); } else { handleSynapseArtifactDeploymentError("LocalEntry Deployment Failed. The artifact " + @@ -102,7 +102,7 @@ public String deploySynapseArtifact(OMElement artifactConfig, String fileName, return null; } - private void handleHttpConnectorCertificates(OMElement element) throws DeploymentException { + private void handleSSLSenderCertificates(OMElement element) throws DeploymentException { OMElement httpInitElement = element.getFirstChildWithName(new QName(SynapseConstants.SYNAPSE_NAMESPACE, HTTP_CONNECTION_IDENTIFIER)); @@ -113,40 +113,50 @@ private void handleHttpConnectorCertificates(OMElement element) throws Deploymen String childElementValue = childElement.getText(); String transformedElementValue = getTransformedElementValue(childElementValue); if (transformedElementValue.endsWith(CERTIFICATE_EXTENSION)) { - loadCertificateFileToStore(transformedElementValue); + loadCertificateFileToSSLSenderTrustStore(transformedElementValue); + loadUpdatedSSL(); } } } } - private void loadCertificateFileToStore(String certificateFileResourceKey) throws DeploymentException { + private void loadCertificateFileToSSLSenderTrustStore(String certificateFileResourceKey) throws DeploymentException { String certificateFilePath = getSynapseConfiguration().getRegistry().getRegistryEntry(certificateFileResourceKey).getName(); File certificateFile = new File(certificateFilePath); String certificateAlias = certificateFile.getName().split("\\.")[0]; - try (FileInputStream certificateFileInputStream = FileUtils.openInputStream(new File(certificateFilePath))) { - SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); - KeyStore sslSenderTrustStore = sslSenderTrustStoreHolder.getKeyStore(); + SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); + if (sslSenderTrustStoreHolder.isValid()) { + try (FileInputStream certificateFileInputStream = FileUtils.openInputStream(new File(certificateFilePath))) { + KeyStore sslSenderTrustStore = sslSenderTrustStoreHolder.getKeyStore(); - CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); - Certificate certificate = certificateFactory.generateCertificate(certificateFileInputStream); - sslSenderTrustStore.setCertificateEntry(certificateAlias, certificate); + CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); + Certificate certificate = certificateFactory.generateCertificate(certificateFileInputStream); + sslSenderTrustStore.setCertificateEntry(certificateAlias, certificate); - try (FileOutputStream fileOutputStream = new FileOutputStream(sslSenderTrustStoreHolder.getLocation())) { - sslSenderTrustStore.store(fileOutputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + try (FileOutputStream fileOutputStream = new FileOutputStream(sslSenderTrustStoreHolder.getLocation())) { + sslSenderTrustStore.store(fileOutputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + } + } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException e) { + throw new DeploymentException("Failed to load certificate file to store: " + certificateFilePath, e); } + } + } + private void loadUpdatedSSL() throws DeploymentException { + SslSenderTrustStoreHolder sslSenderTrustStoreHolder = SslSenderTrustStoreHolder.getInstance(); + KeyStore sslSenderTrustStore = sslSenderTrustStoreHolder.getKeyStore(); + if (sslSenderTrustStoreHolder.isValid()) { try ( - FileInputStream fileInputStream = new FileInputStream(sslSenderTrustStoreHolder.getLocation()); - InputStream bufferedInputStream = IOUtils.toBufferedInputStream(fileInputStream) + FileInputStream fileInputStream = new FileInputStream(sslSenderTrustStoreHolder.getLocation()); + InputStream bufferedInputStream = IOUtils.toBufferedInputStream(fileInputStream) ) { sslSenderTrustStore.load(bufferedInputStream, sslSenderTrustStoreHolder.getPassword().toCharArray()); + sslSenderTrustStoreHolder.setKeyStore(sslSenderTrustStore); + KeyStoreReloaderHolder.getInstance().reloadAllKeyStores(); + } catch (IOException | CertificateException | NoSuchAlgorithmException e) { + throw new DeploymentException("Failed to load updated SSL configuration from the trust store at: " + sslSenderTrustStoreHolder.getLocation(), e); } - - sslSenderTrustStoreHolder.setKeyStore(sslSenderTrustStore); - KeyStoreReloaderHolder.getInstance().reloadAllKeyStores(); - } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException e) { - throw new DeploymentException("Failed to load certificate file to store: " + certificateFilePath, e); } } diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java index cb7ef8884c..5177acbb46 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/SslSenderTrustStoreHolder.java @@ -83,4 +83,9 @@ public void setType(String type) { public String getType() { return this.type; } + + public boolean isValid() { + return keyStore != null && location != null && !location.isEmpty() && + password != null && !password.isEmpty(); + } }