Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
d31fc6d
[CAMEL-22557] AS2: Fix configuration isolation and enable port sharin…
brunovg Oct 21, 2025
24577e4
added comment on requestUriPattern. ran mvn formatter:format on camel…
brunovg Oct 22, 2025
e96c252
using ObjectHelper.isNotEmpty to check if requestUriPattern is not empty
brunovg Oct 22, 2025
618d396
removed requestUriPattern declaration on AS2Configuration. requestUri…
brunovg Oct 23, 2025
79580ca
restore security context in AS2ServerConnection to resolve MDN signin…
brunovg Oct 23, 2025
6fe5a4a
[CAMEL-22557] AS2: Fix configuration isolation and enable port sharin…
brunovg Oct 21, 2025
fd67a1b
added comment on requestUriPattern. ran mvn formatter:format on camel…
brunovg Oct 22, 2025
fdc3c10
using ObjectHelper.isNotEmpty to check if requestUriPattern is not empty
brunovg Oct 22, 2025
b9cd21d
removed requestUriPattern declaration on AS2Configuration. requestUri…
brunovg Oct 23, 2025
4014d98
restore security context in AS2ServerConnection to resolve MDN signin…
brunovg Oct 23, 2025
660e170
Initialize AS2ServerConnection in AS2ConnectionHelper using the actua…
brunovg Oct 24, 2025
eb4b3ee
Initialize AS2ServerConnection in AS2ConnectionHelper using the actua…
brunovg Oct 24, 2025
6e82b26
Revert "Initialize AS2ServerConnection in AS2ConnectionHelper using t…
brunovg Oct 24, 2025
ff95019
AS2 unit tests with two consumers
brunovg Oct 27, 2025
dfd89e3
using the right signing private key on createReceivedContentMic method
brunovg Oct 28, 2025
acb3930
Introduce AS2ConsumerConfigInterceptor and ThreadLocal state to enabl…
brunovg Oct 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,7 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.camel.component.as2.api.AS2AsynchronousMDNManager;
import org.apache.camel.component.as2.api.AS2Constants;
import org.apache.camel.component.as2.api.AS2Header;
import org.apache.camel.component.as2.api.AS2ServerManager;
import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
import org.apache.camel.component.as2.api.AS2SignedDataGenerator;
import org.apache.camel.component.as2.api.AS2TransferEncoding;
import org.apache.camel.component.as2.api.InvalidAS2NameException;
import org.apache.camel.component.as2.api.*;
import org.apache.camel.component.as2.api.entity.AS2DispositionModifier;
import org.apache.camel.component.as2.api.entity.AS2DispositionType;
import org.apache.camel.component.as2.api.entity.DispositionMode;
Expand Down Expand Up @@ -85,16 +78,29 @@ public class ResponseMDN implements HttpResponseInterceptor {

private final String as2Version;
private final String serverFQDN;
private final AS2SignatureAlgorithm signingAlgorithm;
private final Certificate[] signingCertificateChain;
private final PrivateKey signingPrivateKey;
private final PrivateKey decryptingPrivateKey;
private final String mdnMessageTemplate;
private final Certificate[] validateSigningCertificateChain;

private AS2SignatureAlgorithm signingAlgorithm;
private Certificate[] signingCertificateChain;
private PrivateKey signingPrivateKey;
private PrivateKey decryptingPrivateKey;
private Certificate[] validateSigningCertificateChain;
private boolean keysAreDynamic = false; // Flag indicating if security keys/certs must be dynamically fetched from the HttpContext

private final Lock lock = new ReentrantLock();
private VelocityEngine velocityEngine;

public ResponseMDN(String as2Version, String serverFQDN, String mdnMessageTemplate) {
this.as2Version = as2Version;
this.serverFQDN = serverFQDN;
if (!StringUtils.isBlank(mdnMessageTemplate)) {
this.mdnMessageTemplate = mdnMessageTemplate;
} else {
this.mdnMessageTemplate = DEFAULT_MDN_MESSAGE_TEMPLATE;
}
this.keysAreDynamic = true;
}

public ResponseMDN(String as2Version, String serverFQDN, AS2SignatureAlgorithm signingAlgorithm,
Certificate[] signingCertificateChain, PrivateKey signingPrivateKey, PrivateKey decryptingPrivateKey,
String mdnMessageTemplate, Certificate[] validateSigningCertificateChain) {
Expand Down Expand Up @@ -126,6 +132,18 @@ public void process(HttpResponse response, EntityDetails entity, HttpContext con
return;
}

if (this.keysAreDynamic) {
// Dynamically load path-specific security material from the HttpContext,
// which was populated by AS2ConsumerConfigInterceptor.
this.signingAlgorithm = (AS2SignatureAlgorithm) context.getAttribute(AS2ServerConnection.AS2_SIGNING_ALGORITHM);
this.signingCertificateChain
= (Certificate[]) context.getAttribute(AS2ServerConnection.AS2_SIGNING_CERTIFICATE_CHAIN);
this.signingPrivateKey = (PrivateKey) context.getAttribute(AS2ServerConnection.AS2_SIGNING_PRIVATE_KEY);
this.decryptingPrivateKey = (PrivateKey) context.getAttribute(AS2ServerConnection.AS2_DECRYPTING_PRIVATE_KEY);
this.validateSigningCertificateChain
= (Certificate[]) context.getAttribute(AS2ServerConnection.AS2_VALIDATE_SIGNING_CERTIFICATE_CHAIN);
}

HttpCoreContext coreContext = HttpCoreContext.adapt(context);

HttpRequest request = coreContext.getAttribute(HttpCoreContext.HTTP_REQUEST, HttpRequest.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.apache.camel.support.component.AbstractApiConsumer;
import org.apache.camel.support.component.ApiConsumerHelper;
import org.apache.camel.support.component.ApiMethod;
import org.apache.camel.support.component.ApiMethodHelper;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntityContainer;
Expand Down Expand Up @@ -98,18 +97,36 @@ protected void doStart() throws Exception {
as2ServerConnection = getEndpoint().getAS2ServerConnection();
apiProxy = new AS2ServerManager(as2ServerConnection);

// invoke the API method to start listening
ApiMethodHelper.invokeMethod(apiProxy, apiMethod, properties);
String uri = properties.computeIfAbsent("requestUriPattern", param -> "/").toString();

// Check if the configuration for this specific URI path has already been registered
// (e.g., by the default "/" fallback or another consumer).
// If not, create and register it now using the endpoint's configured keys/certs.
if (as2ServerConnection.getConfigurationForPath(uri).isEmpty()) {
AS2ServerConnection.AS2ConsumerConfiguration consumerConfig = new AS2ServerConnection.AS2ConsumerConfiguration(
getEndpoint().getSigningAlgorithm(),
getEndpoint().getSigningCertificateChain(),
getEndpoint().getSigningPrivateKey(),
getEndpoint().getDecryptingPrivateKey(),
getEndpoint().getValidateSigningCertificateChain());
as2ServerConnection.registerConsumerConfiguration(uri, consumerConfig);
}

as2ServerConnection.listen(uri, this);
}

@Override
protected void doStop() throws Exception {
super.doStop();

if (apiProxy != null) {
String uri = properties.get("requestUriPattern").toString();
apiProxy.unlisten(uri);
if (as2ServerConnection != null) {
// Resolve the unique URI pattern for this consumer
String uri = properties.computeIfAbsent("requestUriPattern", param -> "/").toString();

// Unregister this consumer from the shared AS2ServerConnection
as2ServerConnection.unlisten(uri);
}

super.doStop();
}

@Override
Expand All @@ -125,8 +142,8 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
ApplicationEntity ediEntity
= HttpMessageUtils.extractEdiPayload(request,
new HttpMessageUtils.DecrpytingAndSigningInfo(
as2ServerConnection.getValidateSigningCertificateChain(),
as2ServerConnection.getDecryptingPrivateKey()));
getEndpoint().getValidateSigningCertificateChain(),
getEndpoint().getDecryptingPrivateKey()));

// Set AS2 Interchange property and EDI message into body of input message.
Exchange exchange = createExchange(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,22 @@ public void setSigningCertificateChain(Certificate[] signingCertificateChain) {
configuration.setSigningCertificateChain(signingCertificateChain);
}

public Certificate[] getValidateSigningCertificateChain() {
return configuration.getValidateSigningCertificateChain();
}

public void setValidateSigningCertificateChain(Certificate[] validateSigningCertificateChain) {
configuration.setValidateSigningCertificateChain(validateSigningCertificateChain);
}

public PrivateKey getDecryptingPrivateKey() {
return configuration.getDecryptingPrivateKey();
}

public void setDecryptingPrivateKey(PrivateKey decryptingPrivateKey) {
configuration.setDecryptingPrivateKey(decryptingPrivateKey);
}

public PrivateKey getSigningPrivateKey() {
return configuration.getSigningPrivateKey();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@ public static AS2ServerConnection createAS2ServerConnection(AS2Configuration con
configuration.getAs2Version(), configuration.getServer(),
configuration.getServerFqdn(), configuration.getServerPortNumber(),
configuration.getSigningAlgorithm(),
configuration.getSigningCertificateChain(), configuration.getSigningPrivateKey(),
configuration.getDecryptingPrivateKey(), configuration.getMdnMessageTemplate(),
configuration.getValidateSigningCertificateChain(), configuration.getSslContext());
configuration.getSigningCertificateChain(),
configuration.getSigningPrivateKey(),
configuration.getDecryptingPrivateKey(),
configuration.getMdnMessageTemplate(),
configuration.getValidateSigningCertificateChain(),
configuration.getSslContext());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
Loading
Loading