-
Notifications
You must be signed in to change notification settings - Fork 48
Multi Profile Handling
This page describes the best practices for dealing with multi AS4 profiles (like Peppol and CEF) in parallel.
Generally it makes a difference if you are sending or receiving. Additionally, not all profiles can easily be combined out of the box (e.g. BDEW has specific requirements).
The following aspects need to be considered when dealing with multi AS4 profiles and may be different:
- Key material (key store and trust store)
- AS4 profile ID
- PMode parameters and requirements
- http/https settings (TLS, timeouts etc.)
- Validations on the message integrity
- Validations based on the chosen AS4 profile (e.g. Peppol-specifics)
Most AS4 profile come with its own special sender builder (via the phase4-{profile}-client
module).
As the sending of the document can usually be triggered without additional context,
all required parameters may simply be provided to the builder directly and will apply to sending exactly that instance:
-
.cryptoFactory(...)
,.cryptoFactorySign(...)
and.cryptoFactoryCrypt (...)
to define key store and trust store for signing and/or encryption -
.pmode(...)
or.pmodeResolver(...)
to set the PMode parameters/templates -
.as4Profile(...)
to set the AS4 profile ID (since v2.8.2) - please note: implicitly uses theIPModeResolver
to do the job. So if you use a customIPModeResolver
, please make sure to use the correct AS4 profile there. -
.httpClientFactory(...)
,.httpRetrySettings(...)
and.customHttpPoster(...)
to define HTTP specific settings
For receiving, the setup is a bit more tricky. The following aspects need to be considered on top of the general aspects mentioned above:
- Verify that the receiver is really handled by the receiving AP (e.g. in Peppol)
There are some general decisions to be made to handle multiple profiles on reception:
- Use a different host name/path (aka Request URL) for each profile (e.g.
https://example.org/as4/peppol
andhttps://example.org/as4/cef
)- This is the recommended way to handle multiple different AS4 profiles
- Handle each Request URL by a different Servlet (or comparable) - that's the easiest way, because it just means configuring each Servlet once statically for each profile
- This does not to be described explicitly, it should be straight forward
- Handle each Request URL by the same Servlet (or comparable) - than some kind of differentiation is needed per reception, based on the request URL (or the proxied request URL)
- This is described below in more detail
- Use the same request URL for each profile and differentiate based on the message content
- This is not recommended because it becomes more difficult, especially if not just UserMessages are exchanged but also PullRequests. Also the different requirements on signing and encryption may further complicate the correct determination of the profile to be used.
- Also some AS4 profiles mandate the usage of specific HTTP/TLS settings, which is easiest to configure per domain name
- This option is not described further
The keystore contains the private key. The keystore or its contents must never be shared with anyone. In a multi-profile scenario, a separate private key may be needed for each AS4 profile.
The private key from the keystore is needed to sign outgoing messages and to decrypt incoming messages, so it is needed for both sending and receiving messages.
Therefore it is critical, that the correct keystore configuration is provided via the selected IAS4CryptoFactory
for sending and receiving.
Multiple private keys for multiple AS4 profiles may be managed in a single keystore, but the "alias" (the key into the keystore) may be different for each supported profile. If you like, you can also use multiple keystores - one for each supported AS4 profile.
The truststore contains all the needed public keys that are considered trustworthy. A truststore is technically also a "key store" but its contents are different. Because the truststore contains only public keys, it might be shared and copied, as long as the integrity of the truststore is guaranteed.
It is recommended to setup a different truststore for each AS4 profile and configure it via the selected IAS4CryptoFactory
.
Assume the following scenario where multiple profiles would share a single truststore, and a phase4 setup supporting the two AS4 profiles "A" and "B":
A message for AS4 profile "A" was (whysoever) signed with a certificate suitable for AS4 profile "B".
If both public keys would be in the same truststore, the incoming message might get accidentally accepted
(assuming no further checks on application side are performed).
In this scenario each AS4 profile is required to have it's own public URL but is handled by the same servlet.
Note: the description in this section refers to the Servlet based implementation as used when run as a Spring Boot application or inside a common Java Application server. This section does not apply to other deployment scenarios like AWS Lambdas.
The expected way to handle this scenario, is to provide an implementation of class AS4XServletHandler.IHandlerCustomizer
and pass it via
setHandlerCustomizer
into the instance of AS4XServletHandler
that's running the AS4 Servlet.
This allows you to call the setters in the AS4RequestHandler
.
However to customize the CryptoFactory based on the request URL you need to overwrite AS4XServletHandler.handleRequest(IRequestWebScopeWithoutResponse, UnifiedResponse)
and
make the call to the other handleRequest
method manually.
Version 3 of phase4 tried to simply the process of supporting multiple profiles in one application.
Additionally, the same customization options are available for all users of AS4RequestHandler
.
Major steps taken were:
- Remove all the customizations from
AS4XServletHandler
and do it all inAS4RequestHandler
- The goal is to have the customizations work with all technologies and not just Servlets
- Customizing the
AS4RequestHandler
from within theAS4XServletHandler
can be done via an instance ofIAS4ServletRequestHandlerCustomizer
- Less needs for
Supplier
objects and instead use direct objects - leads to simpler coder
- Class
AS4RequestHandler
has the possibility to customize the following things:-
setCryptoFactorySign(...)
,setCryptoFactoryCrypt(...)
andsetCryptoFactory(...)
to customize the AS4CryptoFactory per request -
setPModeResolver(...)
for the PMode resolver to be used per request -
setIncomingSecurityConfiguration(...)
to define theAS4SigningParams
,AS4CryptParams
andIAS4DecryptParameterModifier
per request -
setIncomingReceiverConfiguration(...)
to define the receiver endpoint address per request -
setIncomingProfileSelector(...)
to define the AS4 profile per request -
setLocale(...)
to define the local of messages (if supported) per request -
setIncomingDumper(...)
to define a specific incoming dumper per request - if none is used, the globally configured one is used -
setOutgoingDumper(...)
to define a specific outgoing dumper per request - if none is used, the globally configured one is used -
setRetryCallback(...)
to define a special callback that is invoked, when sending an asynchronous response requires a retry -
setProcessorSupplier(...)
to define a list of SPI implementations to be invoked for each valid received message -
setErrorConsumer(...)
to define a specific consumer for anAS4ErrorMessage
in case the processing failed
-
My personal Coding Styleguide | It is appreciated if you star the GitHub project if you like it.