This is an automated email from the ASF dual-hosted git repository. orpiske pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
commit c057e26f6ca95462eea65d1e7ac69f3a25c77a19 Author: Dmitry Kryukov <d...@ya.ru> AuthorDate: Fri Apr 28 19:44:03 2023 +0300 Refactored test class for Mendelson AS2 resource: moved settings into property file, disabled the test by default --- .../camel/component/as2/MendelsonCertLoader.java | 45 +++---- .../component/as2/MendelsonSslEndpointIT.java | 150 --------------------- .../as2/MendelsonSslEndpointManualTest.java | 128 ++++++++++++++++++ .../src/test/resources/test-server.properties | 46 +++++++ 4 files changed, 196 insertions(+), 173 deletions(-) diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonCertLoader.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonCertLoader.java index 0da4d0d2bb5..c88b6997e9e 100644 --- a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonCertLoader.java +++ b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonCertLoader.java @@ -42,24 +42,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * That's a utility class for preparing Mendelson-specific certificate chain, private key, ssl context + * That's a utility class for preparing Mendelson-specific certificate chain, private key, ssl context. It has no + * mention of paths to Mendelson certificate, keystore and keystore password, but we can't ensure that it works with any + * provided certificate and keystore without modifications. At least due to certificate chain for Mendelson consists of + * the only certificate. */ public class MendelsonCertLoader { private static final Logger LOG = LoggerFactory.getLogger(MendelsonCertLoader.class); - private static final String MENDELSON_CERT = "mendelson/key4.cer"; - private static final String MENDELSON_PRIVATE_KEY = "mendelson/key3.pfx"; - private final List<Certificate> chainAsList = new ArrayList<>(); private PrivateKey privateKey; private SSLContext sslContext; - public void setupSslContext() { + public void setupSslContext(String keyStorePath, String keyStorePassword) { try { - InputStream mendelsonPrivateKeyAsStream = getClass().getClassLoader().getResourceAsStream(MENDELSON_PRIVATE_KEY); - KeyStore keyStore = getKeyStore(mendelsonPrivateKeyAsStream); + InputStream keyStoreAsStream = getClass().getClassLoader().getResourceAsStream(keyStorePath); + KeyStore keyStore = getKeyStore(keyStoreAsStream, keyStorePassword); sslContext = SSLContexts.custom().setKeyStoreType("PKCS12") .loadTrustMaterial(keyStore, new TrustAllStrategy()) .build(); @@ -68,16 +68,16 @@ public class MendelsonCertLoader { } if (sslContext == null) { - throw new IllegalStateException("failed to configure SSL context"); + LOG.error("failed to configure SSL context"); } } - private KeyStore getKeyStore(InputStream inputStream) throws IOException, NoSuchAlgorithmException { - String password = "test"; + private KeyStore getKeyStore(InputStream inputStream, String keyStorePassword) + throws IOException, NoSuchAlgorithmException { KeyStore ks; try { ks = KeyStore.getInstance("PKCS12"); - ks.load(inputStream, password.toCharArray()); + ks.load(inputStream, keyStorePassword.toCharArray()); return ks; } catch (KeyStoreException e) { LOG.error("Failed to create instance of KeyStore", e); @@ -87,26 +87,26 @@ public class MendelsonCertLoader { throw new IllegalStateException("about to return null"); } - public void setupCertificateChain() { + public void setupCertificateChain(String certificatePath, String keyStorePath, String keyStorePassword) { - InputStream mendelsonCertAsStream = getClass().getClassLoader().getResourceAsStream(MENDELSON_CERT); - if (mendelsonCertAsStream == null) { + InputStream certificateAsStream = getClass().getClassLoader().getResourceAsStream(certificatePath); + if (certificateAsStream == null) { //LOG.error("Couldn't read out client certificate as stream."); throw new IllegalStateException("Couldn't read out certificate as stream."); } - InputStream mendelsonPrivateKeyAsStream = getClass().getClassLoader().getResourceAsStream(MENDELSON_PRIVATE_KEY); - if (mendelsonPrivateKeyAsStream == null) { + InputStream keyStoreAsStream = getClass().getClassLoader().getResourceAsStream(keyStorePath); + if (keyStoreAsStream == null) { //LOG.error("Couldn't read out private key as stream."); throw new IllegalStateException("Couldn't read out key storage as stream."); } try { - Certificate mendelsonCert = getCertificateFromStream(mendelsonCertAsStream); - chainAsList.add(mendelsonCert); + Certificate certificate = getCertificateFromStream(certificateAsStream); + chainAsList.add(certificate); //private key - privateKey = getPrivateKeyFromPKCSStream(mendelsonPrivateKeyAsStream); + privateKey = getPrivateKeyFromPKCSStream(keyStoreAsStream, keyStorePassword); } catch (IOException e) { String errMsg @@ -156,9 +156,8 @@ public class MendelsonCertLoader { } //https://stackoverflow.com/questions/18644286/creating-privatekey-object-from-pkcs12 - private PrivateKey getPrivateKeyFromPKCSStream(InputStream inputStream) + private PrivateKey getPrivateKeyFromPKCSStream(InputStream inputStream, String keyStorePassword) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { - String password = "test"; KeyStore ks = null; try { ks = KeyStore.getInstance("PKCS12"); @@ -166,14 +165,14 @@ public class MendelsonCertLoader { LOG.error("Error while getting instance of KeyStore" + e); } try { - ks.load(inputStream, password.toCharArray()); + ks.load(inputStream, keyStorePassword.toCharArray()); } catch (CertificateException e) { LOG.error("Error while loading the certificate" + e); } try { return (PrivateKey) ks.getKey( ks.aliases().nextElement(), - password.toCharArray()); + keyStorePassword.toCharArray()); } catch (KeyStoreException e) { LOG.error("Error while retrieving private key" + e); } catch (UnrecoverableKeyException e) { diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointIT.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointIT.java deleted file mode 100644 index edb689c0e39..00000000000 --- a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointIT.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF 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.camel.component.as2; - -import java.nio.charset.Charset; - -import javax.net.ssl.HostnameVerifier; - -import org.apache.camel.CamelContext; -import org.apache.camel.Exchange; -import org.apache.camel.component.as2.api.AS2EncryptionAlgorithm; -import org.apache.camel.component.as2.api.AS2MessageStructure; -import org.apache.camel.component.as2.api.AS2SignatureAlgorithm; -import org.apache.camel.component.as2.internal.AS2ApiName; -import org.apache.camel.impl.DefaultCamelContext; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Test class for testing connection to a public 3rd party AS2 server Mendelson. This class gives more info for - * camel-as2 connectivity to a remote server compared to HTTPS connection to localhost server. Eventually test method(s) - * will be committed with @Disabled annotation due to they can fail because the mendelson server goes offline or the - * certificate expires. I assume we don't want a build to fail because of such 3rd party connectivity dependency. - * Mendelson page: http://mendelson-e-c.com/as2_testserver - */ -public class MendelsonSslEndpointIT extends AbstractAS2ITSupport { - - private static final Logger LOG = LoggerFactory.getLogger(MendelsonSslEndpointIT.class); - private static HostnameVerifier hostnameVerifier; - - private static final String[] SIGNED_RECEIPT_MIC_ALGORITHMS = new String[] { "sha1", "md5" }; - - private static final String EDI_MESSAGE = "UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778'\n" - + "UNH+00000000000117+INVOIC:D:97B:UN'\n" - + "BGM+380+342459+9'\n" - + "DTM+3:20060515:102'\n" - + "RFF+ON:521052'\n" - + "NAD+BY+792820524::16++CUMMINS MID-RANGE ENGINE PLANT'\n" - + "NAD+SE+005435656::16++GENERAL WIDGET COMPANY'\n" - + "CUX+1:USD'\n" - + "LIN+1++157870:IN'\n" - + "IMD+F++:::WIDGET'\n" - + "QTY+47:1020:EA'\n" - + "ALI+US'\n" - + "MOA+203:1202.58'\n" - + "PRI+INV:1.179'\n" - + "LIN+2++157871:IN'\n" - + "IMD+F++:::Message from Camel AS2 via HTTPS'\n" - + "QTY+47:20:EA'\n" - + "ALI+JP'\n" - + "MOA+203:410'\n" - + "PRI+INV:20.5'\n" - + "UNS+S'\n" - + "MOA+39:2137.58'\n" - + "ALC+C+ABG'\n" - + "MOA+8:525'\n" - + "UNT+23+00000000000117'\n" - + "UNZ+1+00000000000778'\n"; - - private MendelsonCertLoader mendelsonCertLoader; - - @BeforeAll - public void setupTest() { - hostnameVerifier = new NoopHostnameVerifier(); - mendelsonCertLoader = new MendelsonCertLoader(); - mendelsonCertLoader.setupCertificateChain(); - mendelsonCertLoader.setupSslContext(); - } - - @Disabled - @Test - public void testCreateEndpointAndSendViaHTTPS() throws Exception { - CamelContext camelContext = new DefaultCamelContext(); - camelContext.start(); - - org.apache.http.entity.ContentType contentTypeEdifact - = org.apache.http.entity.ContentType.create("application/edifact", (Charset) null); - - String methodName = "send"; - AS2ApiName as2ApiNameClient = AS2ApiName.CLIENT; - - AS2Configuration endpointConfiguration = new AS2Configuration(); - endpointConfiguration.setApiName(as2ApiNameClient); - endpointConfiguration.setMethodName(methodName); - endpointConfiguration.setRequestUri("/as2/HttpReceiver"); - endpointConfiguration.setSignedReceiptMicAlgorithms(SIGNED_RECEIPT_MIC_ALGORITHMS); - - endpointConfiguration.setAs2MessageStructure(AS2MessageStructure.SIGNED_ENCRYPTED); - endpointConfiguration.setSigningAlgorithm(AS2SignatureAlgorithm.SHA3_256WITHRSA); - endpointConfiguration.setEncryptingAlgorithm(AS2EncryptionAlgorithm.DES_EDE3_CBC); - endpointConfiguration.setSigningCertificateChain(mendelsonCertLoader.getChain()); - endpointConfiguration.setSigningPrivateKey(mendelsonCertLoader.getPrivateKey()); - endpointConfiguration.setEncryptingCertificateChain(mendelsonCertLoader.getChain()); - - endpointConfiguration.setAs2Version("1.0"); - endpointConfiguration.setAs2To("mendelsontestAS2"); - endpointConfiguration.setAs2From("mycompanyAS2"); - endpointConfiguration.setEdiMessageType(contentTypeEdifact); - endpointConfiguration.setFrom("dk2kEdi"); - endpointConfiguration.setSubject("mysubject"); - endpointConfiguration.setSigningAlgorithm(AS2SignatureAlgorithm.MD2WITHRSA); - endpointConfiguration.setEdiMessageTransferEncoding("7bit"); - endpointConfiguration.setAttachedFileName("from_camel.txt"); - - endpointConfiguration.setSslContext(mendelsonCertLoader.getSslContext()); - endpointConfiguration.setHostnameVerifier(hostnameVerifier); - - AS2Component as2Component = new AS2Component(); - as2Component.setCamelContext(camelContext); - as2Component.setConfiguration(endpointConfiguration); - as2Component.start(); - - AS2Endpoint endpoint = (AS2Endpoint) as2Component - .createEndpoint("as2://client/send?targetHostName=testas2.mendelson-e-c.com" - + "&targetPortNumber=8444&inBody=ediMessage&requestUri=/as2/HttpReceiver" + - "&ediMessageContentType=application/edifact" + - "&signingAlgorithm=SHA3_256WITHRSA"); - - Assertions.assertEquals("mycompanyAS2", endpoint.getAs2From()); - Assertions.assertEquals("mendelsontestAS2", endpoint.getAs2To()); - Assertions.assertEquals("dk2kEdi", endpoint.getFrom()); - - Exchange out - = camelContext.createProducerTemplate().request(endpoint, - exchange -> exchange.getIn().setBody(EDI_MESSAGE)); - Throwable cause = out.getException(); - Assertions.assertNull(cause); - LOG.debug( - "Sending done, check your message in http://testas2.mendelson-e-c.com:8080/webas2/ Login guest, password guest"); - } -} diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointManualTest.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointManualTest.java new file mode 100644 index 00000000000..5382b74c9cb --- /dev/null +++ b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/MendelsonSslEndpointManualTest.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.camel.component.as2; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.net.ssl.HostnameVerifier; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.component.as2.api.AS2EncryptionAlgorithm; +import org.apache.camel.component.as2.api.AS2MessageStructure; +import org.apache.camel.component.as2.api.AS2SignatureAlgorithm; +import org.apache.camel.component.as2.internal.AS2ApiName; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test class for testing connection to a public 3rd party AS2 server. This class gives more info for camel-as2 + * connectivity to a remote server compared to HTTPS connection to localhost server. Eventually test class will be + * committed with @Disabled annotation due to the test can bring dependency on 3rd party resource. + */ +@Disabled("Run this test manually") +public class MendelsonSslEndpointManualTest extends AbstractAS2ITSupport { + + private static final Logger LOG = LoggerFactory.getLogger(MendelsonSslEndpointManualTest.class); + private static HostnameVerifier hostnameVerifier; + + private MendelsonCertLoader mendelsonCertLoader; + private final Properties props = new Properties(); + + @BeforeAll + public void setupTest() { + InputStream is = MendelsonSslEndpointManualTest.class + .getClassLoader().getResourceAsStream("test-server.properties"); + try { + props.load(is); + } catch (IOException e) { + LOG.error("Failed to load properties from file test_server.properties"); + } + + // NoopHostnameVerifier needed since we connect to non-localhost remote AS2 server + hostnameVerifier = new NoopHostnameVerifier(); + mendelsonCertLoader = new MendelsonCertLoader(); + mendelsonCertLoader.setupCertificateChain(props.getProperty("mendelson.certificate.path"), + props.getProperty("mendelson.keystore.path"), + props.getProperty("mendelson.keystore.password")); + mendelsonCertLoader.setupSslContext(props.getProperty("mendelson.keystore.path"), + props.getProperty("mendelson.keystore.password")); + } + + @Test + public void testCreateEndpointAndSendViaHTTPS() throws Exception { + CamelContext camelContext = new DefaultCamelContext(); + camelContext.start(); + + String methodName = "send"; + AS2ApiName as2ApiNameClient = AS2ApiName.CLIENT; + + AS2Configuration endpointConfiguration = new AS2Configuration(); + endpointConfiguration.setApiName(as2ApiNameClient); + endpointConfiguration.setMethodName(methodName); + + endpointConfiguration.setAs2MessageStructure(AS2MessageStructure.SIGNED_ENCRYPTED); + endpointConfiguration.setSigningAlgorithm(AS2SignatureAlgorithm.SHA3_256WITHRSA); + endpointConfiguration.setEncryptingAlgorithm(AS2EncryptionAlgorithm.DES_EDE3_CBC); + endpointConfiguration.setSigningCertificateChain(mendelsonCertLoader.getChain()); + endpointConfiguration.setSigningPrivateKey(mendelsonCertLoader.getPrivateKey()); + endpointConfiguration.setEncryptingCertificateChain(mendelsonCertLoader.getChain()); + + endpointConfiguration.setAs2Version(props.getProperty("as2.version")); + endpointConfiguration.setAs2To(props.getProperty("as2.as2to")); + endpointConfiguration.setAs2From(props.getProperty("as2.as2from")); + endpointConfiguration.setFrom(props.getProperty("as2.from")); + endpointConfiguration.setSubject(props.getProperty("as2.subject")); + endpointConfiguration.setSigningAlgorithm(AS2SignatureAlgorithm.MD2WITHRSA); + endpointConfiguration.setEdiMessageTransferEncoding(props.getProperty("as2.transfer.encoding")); + endpointConfiguration.setAttachedFileName(props.getProperty("as2.attached.filename")); + + endpointConfiguration.setSslContext(mendelsonCertLoader.getSslContext()); + endpointConfiguration.setHostnameVerifier(hostnameVerifier); + + AS2Component as2Component = new AS2Component(); + as2Component.setCamelContext(camelContext); + as2Component.setConfiguration(endpointConfiguration); + as2Component.start(); + + AS2Endpoint endpoint = (AS2Endpoint) as2Component + .createEndpoint("as2://client/send?targetHostName=" + props.getProperty("as2.remote.host") + + "&targetPortNumber=" + props.getProperty("as2.remote.port") + + "&inBody=ediMessage" + + "&requestUri=" + props.getProperty("as2.remote.uri") + + "&ediMessageContentType=" + props.getProperty("as2.content.type") + + "&signingAlgorithm=" + props.getProperty("as2.signing.algorithm")); + + Exchange out + = camelContext.createProducerTemplate().request(endpoint, + exchange -> exchange.getIn().setBody(props.getProperty("as2.edi.message"))); + Throwable cause = out.getException(); + Assertions.assertNull(cause); + LOG.debug( + "Sending done. If you used Mendelson settings for connection, " + + "you can check your message in http://testas2.mendelson-e-c.com:8080/webas2/ " + + "Login guest, password guest"); + } +} diff --git a/components/camel-as2/camel-as2-component/src/test/resources/test-server.properties b/components/camel-as2/camel-as2-component/src/test/resources/test-server.properties new file mode 100644 index 00000000000..6f4facf288b --- /dev/null +++ b/components/camel-as2/camel-as2-component/src/test/resources/test-server.properties @@ -0,0 +1,46 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF 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. +## --------------------------------------------------------------------------- + +## --------------------------------------------------------------------------- +# This file contains connection settings for HTTPS version of Mendelson public resource - please see port 8444. +# You can check your message in http://testas2.mendelson-e-c.com:8080/webas2/ Login guest, password guest +# Mendelson page: http://mendelson-e-c.com/as2_testserver +# Apache Software Foundation can't be made liable if Mendelson resource goes offline or changes the certificate +# or the credentials or the terms of using. +## --------------------------------------------------------------------------- + +#TODO If you want to test HTTPS connection to Mendelson public resource, please place 'testas2.mendelson-e-c.com' +#TODO instead of 'TBD' in the line below +as2.remote.host=TBD +as2.remote.port=8444 +as2.remote.uri=/as2/HttpReceiver + +mendelson.certificate.path=mendelson/key4.cer +mendelson.keystore.path=mendelson/key3.pfx +mendelson.keystore.password=test + +as2.content.type=application/edifact +as2.subject=mysubject +as2.version=1.0 +as2.as2to=mendelsontestAS2 +as2.as2from=mycompanyAS2 +as2.from=dk2kEdi +as2.transfer.encoding=7bit +as2.attached.filename=from_camel.txt +as2.signing.algorithm=SHA3_256WITHRSA +as2.edi.message=Message from Camel AS2 via HTTPS +