Skip to content

Multi Profile Handling

Philip Helger edited this page Oct 22, 2024 · 11 revisions

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).

General considerations

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)

Sending considerations

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 the IPModeResolver to do the job. So if you use a custom IPModeResolver, please make sure to use the correct AS4 profile there.
  • .httpClientFactory(...), .httpRetrySettings(...)and .customHttpPoster(...) to define HTTP specific settings

Receiving considerations

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 and https://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

Security Considerations

Keystore Considerations

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.

Truststore Considerations

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).

Different URL and Same Servlet

In this scenario each AS4 profile is required to have it's own public URL but is handled by the same servlet.

Solution in v2.x

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.

Solution in v3.x (work in progress)

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 in AS4RequestHandler
    • The goal is to have the customizations work with all technologies and not just Servlets
    • Customizing the AS4RequestHandler from within the AS4XServletHandler can be done via an instance of IAS4ServletRequestHandlerCustomizer
    • 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(...) and setCryptoFactory(...) to customize the AS4CryptoFactory per request
    • setPModeResolver(...) for the PMode resolver to be used per request
    • setIncomingSecurityConfiguration(...) to define the AS4SigningParams, AS4CryptParams and IAS4DecryptParameterModifier 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 an AS4ErrorMessage in case the processing failed