You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/12/17 08:45:15 UTC
[camel] 04/05: [CAMEL-12605] Refactored AS2 Server connection to
accept decryption key.
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch sandbox/camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 9ca79898a006f9f8b24f1ba5bf7d7c5f7a10b5b7
Author: William Collins <pu...@gmail.com>
AuthorDate: Fri Dec 14 15:55:06 2018 -0500
[CAMEL-12605] Refactored AS2 Server connection to accept decryption key.
---
.../component/as2/api/AS2ServerConnection.java | 18 ++--
.../AS2MessageDispositionNotificationEntity.java | 6 +-
...spositionNotificationMultipartReportEntity.java | 6 +-
.../component/as2/api/entity/EntityParser.java | 9 +-
.../component/as2/api/protocol/ResponseMDN.java | 6 +-
.../camel/component/as2/api/util/MicUtils.java | 10 +-
.../camel/component/as2/api/AS2MessageTest.java | 54 +++--------
.../camel/component/as2/api/util/MicUtilsTest.java | 2 +-
components/camel-as2/camel-as2-component/pom.xml | 12 +--
.../src/main/docs/as2-component.adoc | 2 +-
.../camel/component/as2/AS2Configuration.java | 10 +-
.../as2/internal/AS2ConnectionHelper.java | 2 +-
.../as2/AS2ClientManagerIntegrationTest.java | 15 +--
.../as2/AS2ServerManagerIntegrationTest.java | 104 +++++++++++++++++++--
.../as2/springboot/AS2ComponentConfiguration.java | 10 +-
15 files changed, 168 insertions(+), 98 deletions(-)
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
index 12c1132..09b1061 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
@@ -66,14 +66,15 @@ public class AS2ServerConnection {
int port,
AS2SignatureAlgorithm signatureAlgorithm,
Certificate[] signingCertificateChain,
- PrivateKey signingPrivateKey)
+ PrivateKey signingPrivateKey,
+ PrivateKey decryptingPrivateKey)
throws IOException {
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);
serversocket = new ServerSocket(port);
// Set up HTTP protocol processor for incoming connections
final HttpProcessor inhttpproc = initProtocolProcessor(as2Version, originServer, serverFqdn, port,
- signatureAlgorithm, signingCertificateChain, signingPrivateKey);
+ signatureAlgorithm, signingCertificateChain, signingPrivateKey, decryptingPrivateKey);
reqistry = new UriHttpRequestHandlerMapper();
@@ -163,6 +164,7 @@ public class AS2ServerConnection {
} catch (final IOException ex) {
LOG.error("I/O error: {}", ex.getMessage());
} catch (final HttpException ex) {
+ ex.printStackTrace();
LOG.error("Unrecoverable HTTP protocol violation: {}", ex.getMessage());
} finally {
try {
@@ -182,6 +184,7 @@ public class AS2ServerConnection {
private AS2SignatureAlgorithm signingAlgorithm;
private Certificate[] signingCertificateChain;
private PrivateKey signingPrivateKey;
+ private PrivateKey decryptingPrivateKey;
public AS2ServerConnection(String as2Version,
String originServer,
@@ -189,7 +192,8 @@ public class AS2ServerConnection {
Integer serverPortNumber,
AS2SignatureAlgorithm signingAlgorithm,
Certificate[] signingCertificateChain,
- PrivateKey signingPrivateKey)
+ PrivateKey signingPrivateKey,
+ PrivateKey decryptingPrivateKey)
throws IOException {
this.as2Version = Args.notNull(as2Version, "as2Version");
this.originServer = Args.notNull(originServer, "userAgent");
@@ -198,9 +202,10 @@ public class AS2ServerConnection {
this.signingAlgorithm = signingAlgorithm;
this.signingCertificateChain = signingCertificateChain;
this.signingPrivateKey = signingPrivateKey;
+ this.decryptingPrivateKey = decryptingPrivateKey;
listenerThread = new RequestListenerThread(this.as2Version, this.originServer, this.serverFqdn,
- this.serverPortNumber, this.signingAlgorithm, this.signingCertificateChain, this.signingPrivateKey);
+ this.serverPortNumber, this.signingAlgorithm, this.signingCertificateChain, this.signingPrivateKey, this.decryptingPrivateKey);
listenerThread.setDaemon(true);
listenerThread.start();
}
@@ -240,10 +245,11 @@ public class AS2ServerConnection {
int port,
AS2SignatureAlgorithm signatureAlgorithm,
Certificate[] signingCertificateChain,
- PrivateKey signingPrivateKey) {
+ PrivateKey signingPrivateKey,
+ PrivateKey decryptingPrivateKey) {
return HttpProcessorBuilder.create().add(new ResponseContent(true)).add(new ResponseServer(originServer))
.add(new ResponseDate()).add(new ResponseConnControl()).add(new ResponseMDN(as2Version, serverFqdn,
- signatureAlgorithm, signingCertificateChain, signingPrivateKey))
+ signatureAlgorithm, signingCertificateChain, signingPrivateKey, decryptingPrivateKey))
.build();
}
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/AS2MessageDispositionNotificationEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/AS2MessageDispositionNotificationEntity.java
index 71e323c..f6eb364 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/AS2MessageDispositionNotificationEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/AS2MessageDispositionNotificationEntity.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.as2.api.entity;
import java.io.IOException;
import java.io.OutputStream;
+import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -76,7 +77,8 @@ public class AS2MessageDispositionNotificationEntity extends MimeEntity {
String[] warningFields,
Map<String, String> extensionFields,
String charset,
- boolean isMainBody) throws HttpException {
+ boolean isMainBody,
+ PrivateKey decryptingPrivateKey) throws HttpException {
setMainBody(isMainBody);
setContentType(ContentType.create(AS2MimeType.MESSAGE_DISPOSITION_NOTIFICATION, charset));
@@ -87,7 +89,7 @@ public class AS2MessageDispositionNotificationEntity extends MimeEntity {
this.originalMessageId = HttpMessageUtils.getHeaderValue(request, AS2Header.MESSAGE_ID);
- this.receivedContentMic = MicUtils.createReceivedContentMic(request);
+ this.receivedContentMic = MicUtils.createReceivedContentMic(request, decryptingPrivateKey);
this.reportingUA = HttpMessageUtils.getHeaderValue(response, AS2Header.SERVER);
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/DispositionNotificationMultipartReportEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/DispositionNotificationMultipartReportEntity.java
index 4706ae6..fd68a3e 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/DispositionNotificationMultipartReportEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/DispositionNotificationMultipartReportEntity.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.as2.api.entity;
+import java.security.PrivateKey;
import java.util.Map;
import org.apache.camel.component.as2.api.AS2Charset;
@@ -49,7 +50,8 @@ public class DispositionNotificationMultipartReportEntity extends MultipartRepor
Map<String, String> extensionFields,
String charset,
String boundary,
- boolean isMainBody)
+ boolean isMainBody,
+ PrivateKey decryptingPrivateKey)
throws HttpException {
super(charset, isMainBody, boundary);
removeHeaders(AS2Header.CONTENT_TYPE);
@@ -58,7 +60,7 @@ public class DispositionNotificationMultipartReportEntity extends MultipartRepor
addPart(buildPlainTextReport(request, response, dispositionMode, dispositionType, dispositionModifier,
failureFields, errorFields, warningFields, extensionFields));
addPart(new AS2MessageDispositionNotificationEntity(request, response, dispositionMode, dispositionType,
- dispositionModifier, failureFields, errorFields, warningFields, extensionFields, charset, false));
+ dispositionModifier, failureFields, errorFields, warningFields, extensionFields, charset, false, decryptingPrivateKey));
}
public String getMainMessageContentType() {
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
index eb45639..9652f5e9 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
@@ -422,6 +422,11 @@ public final class EntityParser {
public static void parseAS2MessageEntity(HttpMessage message) throws HttpException {
if (EntityUtils.hasEntity(message)) {
HttpEntity entity = Args.notNull(EntityUtils.getMessageEntity(message), "message entity");
+
+ if (entity instanceof MimeEntity) {
+ // already parsed
+ return;
+ }
try {
// Determine Content Type of Message
@@ -1138,8 +1143,8 @@ public final class EntityParser {
break;
}
case AS2MimeType.APPLICATION_PKCS7_MIME: {
- if (contentType.getParameter("mime-type").equals("compressed-data")) {
- throw new HttpException("Failed to extract EDI payload: invalid mime type '" + contentType.getParameter("mime-type") + "' for AS2 enveloped entity");
+ if (!"compressed-data".equals(contentType.getParameter("smime-type"))) {
+ throw new HttpException("Failed to extract EDI payload: invalid mime type '" + contentType.getParameter("smime-type") + "' for AS2 enveloped entity");
}
ApplicationPkcs7MimeCompressedDataEntity compressedDataEntity = (ApplicationPkcs7MimeCompressedDataEntity) entity;
ediEntity = extractEdiPayloadFromCompressedEntity(compressedDataEntity);
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/protocol/ResponseMDN.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/protocol/ResponseMDN.java
index 14a4109..eacb22c 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/protocol/ResponseMDN.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/protocol/ResponseMDN.java
@@ -59,13 +59,15 @@ public class ResponseMDN implements HttpResponseInterceptor {
private AS2SignatureAlgorithm signingAlgorithm;
private Certificate[] signingCertificateChain;
private PrivateKey signingPrivateKey;
+ private PrivateKey decryptingPrivateKey;
- public ResponseMDN(String as2Version, String serverFQDN, AS2SignatureAlgorithm signingAlgorithm, Certificate[] signingCertificateChain, PrivateKey signingPrivateKey) {
+ public ResponseMDN(String as2Version, String serverFQDN, AS2SignatureAlgorithm signingAlgorithm, Certificate[] signingCertificateChain, PrivateKey signingPrivateKey, PrivateKey decryptingPrivateKey) {
this.as2Version = as2Version;
this.serverFQDN = serverFQDN;
this.signingAlgorithm = signingAlgorithm;
this.signingCertificateChain = signingCertificateChain;
this.signingPrivateKey = signingPrivateKey;
+ this.decryptingPrivateKey = decryptingPrivateKey;
}
@Override
@@ -100,7 +102,7 @@ public class ResponseMDN implements HttpResponseInterceptor {
String boundary = EntityUtils.createBoundaryValue();
DispositionNotificationMultipartReportEntity multipartReportEntity = new DispositionNotificationMultipartReportEntity(
request, response, DispositionMode.AUTOMATIC_ACTION_MDN_SENT_AUTOMATICALLY,
- AS2DispositionType.PROCESSED, null, null, null, null, null, AS2Charset.US_ASCII, boundary, true);
+ AS2DispositionType.PROCESSED, null, null, null, null, null, AS2Charset.US_ASCII, boundary, true, decryptingPrivateKey);
DispositionNotificationOptions dispositionNotificationOptions = DispositionNotificationOptionsParser
.parseDispositionNotificationOptions(
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/MicUtils.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/MicUtils.java
index 8eb66b1..c3da303 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/MicUtils.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/MicUtils.java
@@ -19,21 +19,17 @@ package org.apache.camel.component.as2.api.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
import org.apache.camel.component.as2.api.AS2Charset;
import org.apache.camel.component.as2.api.AS2Header;
import org.apache.camel.component.as2.api.AS2MicAlgorithm;
-import org.apache.camel.component.as2.api.AS2MimeType;
-import org.apache.camel.component.as2.api.entity.ApplicationEDIEntity;
-import org.apache.camel.component.as2.api.entity.ApplicationPkcs7MimeCompressedDataEntity;
import org.apache.camel.component.as2.api.entity.DispositionNotificationOptions;
import org.apache.camel.component.as2.api.entity.DispositionNotificationOptionsParser;
import org.apache.camel.component.as2.api.entity.EntityParser;
-import org.apache.camel.component.as2.api.entity.MultipartSignedEntity;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
-import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,7 +79,7 @@ public final class MicUtils {
}
}
- public static ReceivedContentMic createReceivedContentMic(HttpEntityEnclosingRequest request) throws HttpException {
+ public static ReceivedContentMic createReceivedContentMic(HttpEntityEnclosingRequest request, PrivateKey decryptingPrivateKey) throws HttpException {
String dispositionNotificationOptionsString = HttpMessageUtils.getHeaderValue(request, AS2Header.DISPOSITION_NOTIFICATION_OPTIONS);
if (dispositionNotificationOptionsString == null) {
@@ -97,7 +93,7 @@ public final class MicUtils {
return null;
}
- HttpEntity entity = EntityParser.extractEdiPayload(request, null);
+ HttpEntity entity = EntityParser.extractEdiPayload(request, decryptingPrivateKey);
byte[] content = EntityUtils.getContent(entity);
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
index b9d336a..b8369f5 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2MessageTest.java
@@ -140,14 +140,17 @@ public class AS2MessageTest {
private AS2SignedDataGenerator gen;
- private KeyPair issueKP;
- private X509Certificate issueCert;
+ private static KeyPair issueKP;
+ private static X509Certificate issueCert;
- private KeyPair signingKP;
- private X509Certificate signingCert;
- private List<X509Certificate> certList;
+ private static KeyPair signingKP;
+ private static X509Certificate signingCert;
+ private static List<X509Certificate> certList;
+
+ @BeforeClass
+ public static void setUpOnce() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
- private void setupKeysAndCertificates() throws Exception {
//
// set up our certificates
//
@@ -170,38 +173,11 @@ public class AS2MessageTest {
certList.add(signingCert);
certList.add(issueCert);
-
- }
-
- @BeforeClass
- public static void setUpOnce() throws Exception {
- Security.addProvider(new BouncyCastleProvider());
-
- //
- // set up our certificates
- //
- KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
-
- kpg.initialize(1024, new SecureRandom());
-
- String issueDN = "O=Punkhorn Software, C=US";
- KeyPair issueKP = kpg.generateKeyPair();
- X509Certificate issueCert = Utils.makeCertificate(issueKP, issueDN, issueKP, issueDN);
-
- //
- // certificate we sign against
- //
- String signingDN = "CN=William J. Collins, E=punkhornsw@gmail.com, O=Punkhorn Software, C=US";
- KeyPair signingKP = kpg.generateKeyPair();
- X509Certificate signingCert = Utils.makeCertificate(signingKP, signingDN, issueKP, issueDN);
-
- List<X509Certificate> certList = new ArrayList<>();
-
- certList.add(signingCert);
- certList.add(issueCert);
+
+ KeyPair decryptingKP = signingKP;
testServer = new AS2ServerConnection(AS2_VERSION, "MyServer-HTTP/1.1", SERVER_FQDN, TARGET_PORT, AS2SignatureAlgorithm.SHA256WITHRSA,
- certList.toArray(new Certificate[0]), signingKP.getPrivate());
+ certList.toArray(new Certificate[0]), signingKP.getPrivate(), decryptingKP.getPrivate());
testServer.listen("*", new HttpRequestHandler() {
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context)
@@ -227,8 +203,6 @@ public class AS2MessageTest {
public void setUp() throws Exception {
Security.addProvider(new BouncyCastleProvider());
- setupKeysAndCertificates();
-
// Create and populate certificate store.
JcaCertStore certs = new JcaCertStore(certList);
@@ -703,7 +677,7 @@ public class AS2MessageTest {
DispositionNotificationMultipartReportEntity mdn = new DispositionNotificationMultipartReportEntity(request,
response, DispositionMode.AUTOMATIC_ACTION_MDN_SENT_AUTOMATICALLY, AS2DispositionType.PROCESSED,
dispositionModifier, failureFields, errorFields, warningFields, extensionFields, null, "boundary",
- true);
+ true, null);
// Send MDN
HttpCoreContext httpContext = mdnManager.send(mdn, RECIPIENT_DELIVERY_ADDRESS);
@@ -730,7 +704,7 @@ public class AS2MessageTest {
assertArrayEquals("Unexpected value for Error Fields", errorFields, mdnEntity.getErrorFields());
assertArrayEquals("Unexpected value for Warning Fields", warningFields, mdnEntity.getWarningFields());
assertEquals("Unexpected value for Extension Fields", extensionFields, mdnEntity.getExtensionFields());
- ReceivedContentMic expectedMic = MicUtils.createReceivedContentMic(request);
+ ReceivedContentMic expectedMic = MicUtils.createReceivedContentMic(request, null);
ReceivedContentMic mdnMic = mdnEntity.getReceivedContentMic();
assertEquals("Unexpected value for Recieved Content Mic", expectedMic.getEncodedMessageDigest(),
mdnMic.getEncodedMessageDigest());
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/MicUtilsTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/MicUtilsTest.java
index 5cbaba7..e14c511 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/MicUtilsTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/MicUtilsTest.java
@@ -99,7 +99,7 @@ public class MicUtilsTest {
basicEntity.setContentType(CONTENT_TYPE_VALUE);
request.setEntity(basicEntity);
- ReceivedContentMic receivedContentMic = MicUtils.createReceivedContentMic(request);
+ ReceivedContentMic receivedContentMic = MicUtils.createReceivedContentMic(request, null);
assertNotNull("Failed to create Received Content MIC");
LOG.debug("Digest Algorithm: " + receivedContentMic.getDigestAlgorithmId());
assertEquals("Unexpected digest algorithm value", EXPECTED_MESSAGE_DIGEST_ALGORITHM, receivedContentMic.getDigestAlgorithmId());
diff --git a/components/camel-as2/camel-as2-component/pom.xml b/components/camel-as2/camel-as2-component/pom.xml
index 86c2c5e..37af503 100644
--- a/components/camel-as2/camel-as2-component/pom.xml
+++ b/components/camel-as2/camel-as2-component/pom.xml
@@ -155,11 +155,7 @@
<apiName>client</apiName>
<proxyClass>org.apache.camel.component.as2.api.AS2ClientManager</proxyClass>
<fromJavadoc>
- <excludeMethods>createSigningGenerator</excludeMethods>
- <excludeMethods>createEncryptingGenerator</excludeMethods>
- <excludeMethods>createCompressorGenerator</excludeMethods>
- <excludeMethods>createEncryptor</excludeMethods>
- <excludeMethods>createCompressor</excludeMethods>
+ <excludeMethods>createSigningGenerator|createEncryptingGenerator|createCompressorGenerator|createEncryptor|createCompressor</excludeMethods>
</fromJavadoc>
<nullableOptions>
<nullableOption>ediMessageTransferEncoding</nullableOption>
@@ -171,7 +167,6 @@
<nullableOption>signedReceiptMicAlgorithms</nullableOption>
<nullableOption>encryptingAlgorithm</nullableOption>
<nullableOption>encryptingCertificateChain</nullableOption>
- <nullableOption>encryptingPrivateKey</nullableOption>
</nullableOptions>
</api>
<api>
@@ -181,7 +176,10 @@
<excludeMethods>stopListening|handleMDNResponse</excludeMethods>
</fromJavadoc>
<excludeConfigNames>handler</excludeConfigNames>
- </api>
+<!-- <nullableOptions>
+ <nullableOption>decryptingPrivateKey</nullableOption>
+ </nullableOptions>
+ --> </api>
</apis>
<!-- Specify global values for all APIs here, these are overridden at API level
<substitutions/>
diff --git a/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc b/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
index 0c1180c..7ff1595 100644
--- a/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
+++ b/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
@@ -82,12 +82,12 @@ with the following path and query parameters:
| *as2Version* (common) | The version of the AS2 protocol. | 1.1 | String
| *clientFqdn* (common) | The Client Fully Qualified Domain Name (FQDN). Used in message ids sent by endpoint. | camel.apache.org | String
| *compressionAlgorithm* (common) | The algorithm used to compress EDI message. | | AS2Compression Algorithm
+| *decryptingPrivateKey* (common) | The key used to encrypt the EDI message. | | PrivateKey
| *dispositionNotificationTo* (common) | The value of the Disposition-Notification-To header. Assigning a value to this parameter requests a message disposition notification (MDN) for the AS2 message. | | String
| *ediMessageTransferEncoding* (common) | The transfer encoding of EDI message. | | String
| *ediMessageType* (common) | The content type of EDI message. One of application/edifact, application/edi-x12, application/edi-consent | | ContentType
| *encryptingAlgorithm* (common) | The algorithm used to encrypt EDI message. | | AS2EncryptionAlgorithm
| *encryptingCertificateChain* (common) | The chain of certificates used to encrypt EDI message. | | Certificate[]
-| *encryptingPrivateKey* (common) | The key used to encrypt the EDI message. | | PrivateKey
| *from* (common) | The value of the From header of AS2 message. | | String
| *inBody* (common) | Sets the name of a parameter to be passed in the exchange In Body | | String
| *methodName* (common) | *Required* What sub operation to use for the selected operation | | String
diff --git a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
index c92b50e..57ac5ba 100644
--- a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
+++ b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
@@ -118,7 +118,7 @@ public class AS2Configuration {
private Certificate[] encryptingCertificateChain;
@UriParam
- private PrivateKey encryptingPrivateKey;
+ private PrivateKey decryptingPrivateKey;
public AS2ApiName getApiName() {
return apiName;
@@ -452,14 +452,14 @@ public class AS2Configuration {
this.encryptingCertificateChain = signingCertificateChain;
}
- public PrivateKey getEncryptingPrivateKey() {
- return encryptingPrivateKey;
+ public PrivateKey getDecryptingPrivateKey() {
+ return decryptingPrivateKey;
}
/**
* The key used to encrypt the EDI message.
*/
- public void setEncryptingPrivateKey(PrivateKey signingPrivateKey) {
- this.encryptingPrivateKey = signingPrivateKey;
+ public void setDecryptingPrivateKey(PrivateKey signingPrivateKey) {
+ this.decryptingPrivateKey = signingPrivateKey;
}
}
diff --git a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/internal/AS2ConnectionHelper.java b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/internal/AS2ConnectionHelper.java
index bc1fff5..908eef7 100644
--- a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/internal/AS2ConnectionHelper.java
+++ b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/internal/AS2ConnectionHelper.java
@@ -64,7 +64,7 @@ public final class AS2ConnectionHelper {
if (serverConnection == null) {
serverConnection = new AS2ServerConnection(configuration.getAs2Version(), configuration.getServer(),
configuration.getServerFqdn(), configuration.getServerPortNumber(), configuration.getSigningAlgorithm(),
- configuration.getSigningCertificateChain(), configuration.getSigningPrivateKey());
+ configuration.getSigningCertificateChain(), configuration.getSigningPrivateKey(), configuration.getDecryptingPrivateKey());
serverConnections.put(configuration.getServerPortNumber(), serverConnection);
}
return serverConnection;
diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientManagerIntegrationTest.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientManagerIntegrationTest.java
index 9f83ea2..a52747f 100644
--- a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientManagerIntegrationTest.java
+++ b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientManagerIntegrationTest.java
@@ -161,6 +161,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
private X509Certificate issueCert;
private KeyPair signingKP;
+ private KeyPair decryptingKP;
private X509Certificate signingCert;
private List<X509Certificate> certList;
private AS2SignedDataGenerator gen;
@@ -299,8 +300,6 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
headers.put("CamelAS2.encryptingAlgorithm", AS2EncryptionAlgorithm.AES128_CBC);
// parameter type is java.security.cert.Certificate[]
headers.put("CamelAS2.encryptingCertificateChain", certList);
- // parameter type is java.security.PrivateKey
- headers.put("CamelAS2.encryptingPrivateKey", signingKP.getPrivate());
final org.apache.http.protocol.HttpCoreContext result = requestBodyAndHeaders("direct://SEND", EDI_MESSAGE, headers);
@@ -312,7 +311,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
assertNotNull("Request body", entity);
assertTrue("Request body does not contain ApplicationPkcs7Mime entity", entity instanceof ApplicationPkcs7MimeEnvelopedDataEntity);
- MimeEntity envelopeEntity = ((ApplicationPkcs7MimeEnvelopedDataEntity)entity).getEncryptedEntity(signingKP.getPrivate());
+ MimeEntity envelopeEntity = ((ApplicationPkcs7MimeEnvelopedDataEntity)entity).getEncryptedEntity(decryptingKP.getPrivate());
assertTrue("Enveloped entity is not an EDI entity", envelopeEntity instanceof ApplicationEDIEntity);
String ediMessage = ((ApplicationEDIEntity)envelopeEntity).getEdiMessage();
assertEquals("EDI message is different", EDI_MESSAGE.replaceAll("[\n\r]", ""), ediMessage.replaceAll("[\n\r]", ""));
@@ -437,7 +436,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
assertEquals("Unexpected value for disposition type", AS2DispositionType.PROCESSED, messageDispositionNotificationEntity.getDispositionType());
ReceivedContentMic receivedContentMic = messageDispositionNotificationEntity.getReceivedContentMic();
- ReceivedContentMic computedContentMic = MicUtils.createReceivedContentMic((HttpEntityEnclosingRequest)request);
+ ReceivedContentMic computedContentMic = MicUtils.createReceivedContentMic((HttpEntityEnclosingRequest)request, decryptingKP.getPrivate());
assertEquals("Received content MIC does not match computed", computedContentMic.getEncodedMessageDigest(), receivedContentMic.getEncodedMessageDigest());
}
@@ -524,7 +523,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
assertEquals("Unexpected value for disposition type", AS2DispositionType.PROCESSED, messageDispositionNotificationEntity.getDispositionType());
ReceivedContentMic receivedContentMic = messageDispositionNotificationEntity.getReceivedContentMic();
- ReceivedContentMic computedContentMic = MicUtils.createReceivedContentMic((HttpEntityEnclosingRequest)request);
+ ReceivedContentMic computedContentMic = MicUtils.createReceivedContentMic((HttpEntityEnclosingRequest)request, decryptingKP.getPrivate());
assertEquals("Received content MIC does not match computed", computedContentMic.getEncodedMessageDigest(), receivedContentMic.getEncodedMessageDigest());
}
@@ -564,7 +563,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
DispositionNotificationMultipartReportEntity mdn = new DispositionNotificationMultipartReportEntity(request,
response, DispositionMode.AUTOMATIC_ACTION_MDN_SENT_AUTOMATICALLY, AS2DispositionType.PROCESSED,
dispositionModifier, failureFields, errorFields, warningFields, extensionFields, null, "boundary",
- true);
+ true, serverSigningKP.getPrivate());
// Send MDN
@SuppressWarnings("unused")
@@ -648,7 +647,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
private static void receiveTestMessages() throws IOException {
serverConnection = new AS2ServerConnection(AS2_VERSION, ORIGIN_SERVER_NAME,
- SERVER_FQDN, PARTNER_TARGET_PORT, AS2SignatureAlgorithm.SHA256WITHRSA, serverCertList.toArray(new Certificate[0]), serverSigningKP.getPrivate());
+ SERVER_FQDN, PARTNER_TARGET_PORT, AS2SignatureAlgorithm.SHA256WITHRSA, serverCertList.toArray(new Certificate[0]), serverSigningKP.getPrivate(), serverSigningKP.getPrivate());
serverConnection.listen("/", new RequestHandler());
}
@@ -678,5 +677,7 @@ public class AS2ClientManagerIntegrationTest extends AbstractAS2TestSupport {
certList.add(signingCert);
certList.add(issueCert);
+ // keys used to encrypt/decrypt
+ decryptingKP = signingKP;
}
}
diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerManagerIntegrationTest.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerManagerIntegrationTest.java
index cb58af7..34b598b 100644
--- a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerManagerIntegrationTest.java
+++ b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ServerManagerIntegrationTest.java
@@ -26,19 +26,24 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.as2.api.AS2Charset;
import org.apache.camel.component.as2.api.AS2ClientConnection;
import org.apache.camel.component.as2.api.AS2ClientManager;
+import org.apache.camel.component.as2.api.AS2EncryptionAlgorithm;
import org.apache.camel.component.as2.api.AS2Header;
import org.apache.camel.component.as2.api.AS2MediaType;
import org.apache.camel.component.as2.api.AS2MessageStructure;
+import org.apache.camel.component.as2.api.AS2MimeType;
import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
import org.apache.camel.component.as2.api.AS2SignedDataGenerator;
import org.apache.camel.component.as2.api.entity.ApplicationEDIFACTEntity;
+import org.apache.camel.component.as2.api.entity.ApplicationPkcs7MimeEnvelopedDataEntity;
import org.apache.camel.component.as2.api.entity.ApplicationPkcs7SignatureEntity;
+import org.apache.camel.component.as2.api.entity.MimeEntity;
import org.apache.camel.component.as2.api.entity.MultipartSignedEntity;
import org.apache.camel.component.as2.api.util.SigningUtils;
import org.apache.camel.component.as2.internal.AS2ApiCollection;
@@ -60,6 +65,7 @@ import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -112,14 +118,21 @@ public class AS2ServerManagerIntegrationTest extends AbstractAS2TestSupport {
+ "UNT+23+00000000000117'\n"
+ "UNZ+1+00000000000778'";
- private AS2SignedDataGenerator gen;
+ private static AS2SignedDataGenerator gen;
- private KeyPair issueKP;
- private X509Certificate issueCert;
+ private static KeyPair issueKP;
+ private static X509Certificate issueCert;
- private KeyPair signingKP;
- private X509Certificate signingCert;
- private List<X509Certificate> certList;
+ private static KeyPair signingKP;
+ private static X509Certificate signingCert;
+ private static List<X509Certificate> certList;
+
+ private static KeyPair decryptingKP;
+
+ @BeforeClass
+ public static void setup() throws Exception {
+ setupSigningGenerator();
+ }
@Test
public void receivePlainEDIMessageTest() throws Exception {
@@ -178,7 +191,6 @@ public class AS2ServerManagerIntegrationTest extends AbstractAS2TestSupport {
@Test
public void receiveMultipartSignedMessageTest() throws Exception {
- setupSigningGenerator();
AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN, TARGET_HOST, TARGET_PORT);
AS2ClientManager clientManager = new AS2ClientManager(clientConnection);
@@ -245,8 +257,70 @@ public class AS2ServerManagerIntegrationTest extends AbstractAS2TestSupport {
// Validate Signature
assertTrue("Signature is invalid", signedEntity.isValid());
}
+
+ @Test
+ public void receiveEnvelopedMessageTest() throws Exception {
+ AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN, TARGET_HOST, TARGET_PORT);
+ AS2ClientManager clientManager = new AS2ClientManager(clientConnection);
+
+ clientManager.send(EDI_MESSAGE, REQUEST_URI, SUBJECT, FROM, AS2_NAME, AS2_NAME, AS2MessageStructure.ENCRYPTED,
+ ContentType.create(AS2MediaType.APPLICATION_EDIFACT, AS2Charset.US_ASCII), null, null, null, null,
+ null, DISPOSITION_NOTIFICATION_TO, SIGNED_RECEIPT_MIC_ALGORITHMS, AS2EncryptionAlgorithm.AES128_CBC, certList.toArray(new Certificate[0]));
- private void setupSigningGenerator() throws Exception {
+ MockEndpoint mockEndpoint = getMockEndpoint("mock:as2RcvMsgs");
+ mockEndpoint.expectedMinimumMessageCount(1);
+ mockEndpoint.setResultWaitTime(TimeUnit.MILLISECONDS.convert(30, TimeUnit.SECONDS));
+ mockEndpoint.assertIsSatisfied();
+
+ final List<Exchange> exchanges = mockEndpoint.getExchanges();
+ assertNotNull("listen result", exchanges);
+ assertFalse("listen result", exchanges.isEmpty());
+ LOG.debug("poll result: " + exchanges);
+
+ Exchange exchange = exchanges.get(0);
+ Message message = exchange.getIn();
+ assertNotNull("exchange message", message);
+ BasicHttpContext context = message.getBody(BasicHttpContext.class);
+ assertNotNull("context", context);
+ HttpCoreContext coreContext = HttpCoreContext.adapt(context);
+ HttpRequest request = coreContext.getRequest();
+ assertNotNull("request", request);
+ assertEquals("Unexpected method value", METHOD, request.getRequestLine().getMethod());
+ assertEquals("Unexpected request URI value", REQUEST_URI, request.getRequestLine().getUri());
+ assertEquals("Unexpected HTTP version value", HttpVersion.HTTP_1_1, request.getRequestLine().getProtocolVersion());
+ assertEquals("Unexpected subject value", SUBJECT, request.getFirstHeader(AS2Header.SUBJECT).getValue());
+ assertEquals("Unexpected from value", FROM, request.getFirstHeader(AS2Header.FROM).getValue());
+ assertEquals("Unexpected AS2 version value", AS2_VERSION, request.getFirstHeader(AS2Header.AS2_VERSION).getValue());
+ assertEquals("Unexpected AS2 from value", AS2_NAME, request.getFirstHeader(AS2Header.AS2_FROM).getValue());
+ assertEquals("Unexpected AS2 to value", AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue());
+ assertTrue("Unexpected message id value", request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"));
+ assertEquals("Unexpected target host value", TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue());
+ assertEquals("Unexpected user agent value", USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue());
+ assertNotNull("Date value missing", request.getFirstHeader(AS2Header.DATE));
+ assertNotNull("Content length value missing", request.getFirstHeader(AS2Header.CONTENT_LENGTH));
+ assertTrue("Unexpected content type for message", request.getFirstHeader(AS2Header.CONTENT_TYPE).getValue().startsWith(AS2MimeType.APPLICATION_PKCS7_MIME));
+
+
+ assertTrue("Request does not contain entity", request instanceof BasicHttpEntityEnclosingRequest);
+ HttpEntity entity = ((BasicHttpEntityEnclosingRequest) request).getEntity();
+ assertNotNull("Request does not contain entity", entity);
+ assertTrue("Unexpected request entity type", entity instanceof ApplicationPkcs7MimeEnvelopedDataEntity);
+ ApplicationPkcs7MimeEnvelopedDataEntity envelopedEntity = (ApplicationPkcs7MimeEnvelopedDataEntity) entity;
+ assertTrue("Entity not set as main body of request", envelopedEntity.isMainBody());
+
+ // Validated enveloped part.
+ MimeEntity encryptedEntity = envelopedEntity.getEncryptedEntity(signingKP.getPrivate());
+ assertTrue("Enveloped mime part incorrect type ", encryptedEntity instanceof ApplicationEDIFACTEntity);
+ ApplicationEDIFACTEntity ediEntity = (ApplicationEDIFACTEntity) encryptedEntity;
+ assertTrue("Unexpected content type for enveloped mime part",
+ ediEntity.getContentType().getValue().startsWith(AS2MediaType.APPLICATION_EDIFACT));
+ assertFalse("Enveloped mime type set as main body of request", ediEntity.isMainBody());
+ assertEquals("Unexpected content for enveloped mime part", EDI_MESSAGE.replaceAll("[\n\r]", ""),
+ ediEntity.getEdiMessage().replaceAll("[\n\r]", ""));
+
+ }
+
+ private static void setupSigningGenerator() throws Exception {
Security.addProvider(new BouncyCastleProvider());
setupKeysAndCertificates();
@@ -270,7 +344,7 @@ public class AS2ServerManagerIntegrationTest extends AbstractAS2TestSupport {
}
- private void setupKeysAndCertificates() throws Exception {
+ private static void setupKeysAndCertificates() throws Exception {
//
// set up our certificates
//
@@ -295,9 +369,19 @@ public class AS2ServerManagerIntegrationTest extends AbstractAS2TestSupport {
certList.add(signingCert);
certList.add(issueCert);
+
+ decryptingKP = signingKP;
}
-
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ AS2Component as2Component = (AS2Component) context.getComponent("as2");
+ AS2Configuration configuration = as2Component.getConfiguration();
+ configuration.setDecryptingPrivateKey(decryptingKP.getPrivate());
+ return context;
+ }
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
diff --git a/platforms/spring-boot/components-starter/camel-as2-starter/src/main/java/org/apache/camel/component/as2/springboot/AS2ComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-as2-starter/src/main/java/org/apache/camel/component/as2/springboot/AS2ComponentConfiguration.java
index eda444f..6b66ad7 100644
--- a/platforms/spring-boot/components-starter/camel-as2-starter/src/main/java/org/apache/camel/component/as2/springboot/AS2ComponentConfiguration.java
+++ b/platforms/spring-boot/components-starter/camel-as2-starter/src/main/java/org/apache/camel/component/as2/springboot/AS2ComponentConfiguration.java
@@ -194,7 +194,7 @@ public class AS2ComponentConfiguration
/**
* The key used to encrypt the EDI message.
*/
- private PrivateKey encryptingPrivateKey;
+ private PrivateKey decryptingPrivateKey;
public AS2ApiName getApiName() {
return apiName;
@@ -412,12 +412,12 @@ public class AS2ComponentConfiguration
this.encryptingCertificateChain = encryptingCertificateChain;
}
- public PrivateKey getEncryptingPrivateKey() {
- return encryptingPrivateKey;
+ public PrivateKey getDecryptingPrivateKey() {
+ return decryptingPrivateKey;
}
- public void setEncryptingPrivateKey(PrivateKey encryptingPrivateKey) {
- this.encryptingPrivateKey = encryptingPrivateKey;
+ public void setDecryptingPrivateKey(PrivateKey decryptingPrivateKey) {
+ this.decryptingPrivateKey = decryptingPrivateKey;
}
}
}
\ No newline at end of file