[ 
https://issues.apache.org/jira/browse/CAMEL-26322?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrea Cosentino updated CAMEL-26322:
-------------------------------------
    Description: 
h3. Background

camel-as2 can request an asynchronous MDN (Message Disposition Notification). 
When one is requested, {{AS2AsynchronousMDNManager.send()}} resolves the 
delivery address from the sender-supplied {{Receipt-Delivery-Option}} URI and 
opens a connection to it.

The {{asyncMdnAllowedHosts}} option on {{AS2Configuration}} (documented today 
as "Comma separated list of host names an asynchronous MDN may be delivered 
to") governs whether the asynchronous MDN is delivered to the resolved address 
and whether the configured MDN credentials ({{mdnUserName}} / {{mdnPassword}} / 
{{mdnAccessToken}}) are attached to it.

h3. Current behaviour

{{send()}} resolves both the host and the port of the delivery address (the 
port via {{uri.getPort()}}, defaulted to 80 or 443 by scheme). The allow-list 
match {{isAllowedHost(String host)}} then compares only the *host*: it splits 
{{asyncMdnAllowedHosts}} on commas and does a case-insensitive equals against 
the host. The resolved port is used to open the socket but is never compared 
against the allow-list. An operator can therefore list a host, but every port 
on that listed host is treated the same, both for delivery and for attaching 
the credentials.

h3. Behaviour after the change

The allow-list match considers the full authority - host *and* port - of the 
resolved delivery address, so the port is checked before the connection is 
opened and before the credentials are attached. Each {{asyncMdnAllowedHosts}} 
entry may carry an optional port in {{host:port}} form. A bare-host entry (for 
example {{partner.example}}) matches only the default port for its scheme (80 
or 443); an operator that receives asynchronous MDNs on a non-default port 
lists it explicitly (for example {{partner.example:8443}}).

h3. Classes involved

* 
{{components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManager.java}}
 - the allow-list match {{isAllowedHost(...)}} (host-only today), the resolved 
{{port}}, and the points where the connection is opened ({{createSocket}}) and 
the credentials are attached ({{addAuthorizationHeader}}).
* 
{{components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java}}
 - the {{asyncMdnAllowedHosts}} option and its description.

h3. Code-level change

* Replace {{isAllowedHost(String host)}} with an authority match that also 
takes the resolved port (for example {{isAllowedAuthority(String host, int 
port)}}): parse each {{asyncMdnAllowedHosts}} entry as {{host[:port]}} and 
compare both the host (case-insensitive) and the port (default-port aware).
* Pass the already-resolved {{port}} into the match, so the single 
{{hostIsAllowed}} decision that gates the connection and the attachment of 
credentials now accounts for the port.
* Update the {{asyncMdnAllowedHosts}} description on {{AS2Configuration}} to 
document the {{host[:port]}} form and the default-port rule, then regenerate 
the catalog/component metadata.

h3. Tests

New JUnit methods in {{AS2AsynchronousMDNManagerDeliveryAddressTest}} (that 
class uses JUnit assertions, so new methods there stay JUnit to match the file):
* a delivery address whose port is outside every allow-list entry is refused;
* a delivery address whose host and port both match an entry is accepted;
* a bare-host entry matches only the default port for its scheme.

Each new test is shown failing against the current code and passing after the 
change.

h3. Documentation

The default-port behaviour above is a change for an operator that today lists a 
bare host and delivers to a non-default port, so add a note to 
{{docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc}} on 
{{main}} describing the {{host[:port]}} matching and the default-port rule.

h3. Additional hardening: require https

The asynchronous MDN delivery scheme is also chosen by the sender, and plain 
http is accepted, so the configured MDN credentials can be delivered over http 
even when the operator intended https. A new opt-in option 
{{asyncMdnRequireHttps}} on {{AS2Configuration}} (default {{false}}) is added: 
when set, an asynchronous MDN whose delivery address does not use https is 
refused before the connection is opened and before the configured credentials 
are attached. The option applies per consumer endpoint, like 
{{asyncMdnAllowedHosts}}. New JUnit tests cover: http refused when the option 
is set, https accepted when it is set, and http still accepted by default.

  was:
h3. Background

camel-as2 can request an asynchronous MDN (Message Disposition Notification). 
When one is requested, {{AS2AsynchronousMDNManager.send()}} resolves the 
delivery address from the sender-supplied {{Receipt-Delivery-Option}} URI and 
opens a connection to it.

The {{asyncMdnAllowedHosts}} option on {{AS2Configuration}} (documented today 
as "Comma separated list of host names an asynchronous MDN may be delivered 
to") governs whether the asynchronous MDN is delivered to the resolved address 
and whether the configured MDN credentials ({{mdnUserName}} / {{mdnPassword}} / 
{{mdnAccessToken}}) are attached to it.

h3. Current behaviour

{{send()}} resolves both the host and the port of the delivery address (the 
port via {{uri.getPort()}}, defaulted to 80 or 443 by scheme). The allow-list 
match {{isAllowedHost(String host)}} then compares only the *host*: it splits 
{{asyncMdnAllowedHosts}} on commas and does a case-insensitive equals against 
the host. The resolved port is used to open the socket but is never compared 
against the allow-list. An operator can therefore list a host, but every port 
on that listed host is treated the same, both for delivery and for attaching 
the credentials.

h3. Behaviour after the change

The allow-list match considers the full authority - host *and* port - of the 
resolved delivery address, so the port is checked before the connection is 
opened and before the credentials are attached. Each {{asyncMdnAllowedHosts}} 
entry may carry an optional port in {{host:port}} form. A bare-host entry (for 
example {{partner.example}}) matches only the default port for its scheme (80 
or 443); an operator that receives asynchronous MDNs on a non-default port 
lists it explicitly (for example {{partner.example:8443}}).

h3. Classes involved

* 
{{components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManager.java}}
 - the allow-list match {{isAllowedHost(...)}} (host-only today), the resolved 
{{port}}, and the points where the connection is opened ({{createSocket}}) and 
the credentials are attached ({{addAuthorizationHeader}}).
* 
{{components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java}}
 - the {{asyncMdnAllowedHosts}} option and its description.

h3. Code-level change

* Replace {{isAllowedHost(String host)}} with an authority match that also 
takes the resolved port (for example {{isAllowedAuthority(String host, int 
port)}}): parse each {{asyncMdnAllowedHosts}} entry as {{host[:port]}} and 
compare both the host (case-insensitive) and the port (default-port aware).
* Pass the already-resolved {{port}} into the match, so the single 
{{hostIsAllowed}} decision that gates the connection and the attachment of 
credentials now accounts for the port.
* Update the {{asyncMdnAllowedHosts}} description on {{AS2Configuration}} to 
document the {{host[:port]}} form and the default-port rule, then regenerate 
the catalog/component metadata.

h3. Tests

New JUnit methods in {{AS2AsynchronousMDNManagerDeliveryAddressTest}} (that 
class uses JUnit assertions, so new methods there stay JUnit to match the file):
* a delivery address whose port is outside every allow-list entry is refused;
* a delivery address whose host and port both match an entry is accepted;
* a bare-host entry matches only the default port for its scheme.

Each new test is shown failing against the current code and passing after the 
change.

h3. Documentation

The default-port behaviour above is a change for an operator that today lists a 
bare host and delivers to a non-default port, so add a note to 
{{docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc}} on 
{{main}} describing the {{host[:port]}} matching and the default-port rule.

        Summary: camel-as2 - scope the async MDN allow-list to host and port, 
and add an option to require https  (was: camel-as2 - match the async MDN 
delivery allow-list on host and port)

> camel-as2 - scope the async MDN allow-list to host and port, and add an 
> option to require https
> -----------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26322
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26322
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-as2
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>             Fix For: 4.24.0
>
>
> h3. Background
> camel-as2 can request an asynchronous MDN (Message Disposition Notification). 
> When one is requested, {{AS2AsynchronousMDNManager.send()}} resolves the 
> delivery address from the sender-supplied {{Receipt-Delivery-Option}} URI and 
> opens a connection to it.
> The {{asyncMdnAllowedHosts}} option on {{AS2Configuration}} (documented today 
> as "Comma separated list of host names an asynchronous MDN may be delivered 
> to") governs whether the asynchronous MDN is delivered to the resolved 
> address and whether the configured MDN credentials ({{mdnUserName}} / 
> {{mdnPassword}} / {{mdnAccessToken}}) are attached to it.
> h3. Current behaviour
> {{send()}} resolves both the host and the port of the delivery address (the 
> port via {{uri.getPort()}}, defaulted to 80 or 443 by scheme). The allow-list 
> match {{isAllowedHost(String host)}} then compares only the *host*: it splits 
> {{asyncMdnAllowedHosts}} on commas and does a case-insensitive equals against 
> the host. The resolved port is used to open the socket but is never compared 
> against the allow-list. An operator can therefore list a host, but every port 
> on that listed host is treated the same, both for delivery and for attaching 
> the credentials.
> h3. Behaviour after the change
> The allow-list match considers the full authority - host *and* port - of the 
> resolved delivery address, so the port is checked before the connection is 
> opened and before the credentials are attached. Each {{asyncMdnAllowedHosts}} 
> entry may carry an optional port in {{host:port}} form. A bare-host entry 
> (for example {{partner.example}}) matches only the default port for its 
> scheme (80 or 443); an operator that receives asynchronous MDNs on a 
> non-default port lists it explicitly (for example {{partner.example:8443}}).
> h3. Classes involved
> * 
> {{components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManager.java}}
>  - the allow-list match {{isAllowedHost(...)}} (host-only today), the 
> resolved {{port}}, and the points where the connection is opened 
> ({{createSocket}}) and the credentials are attached 
> ({{addAuthorizationHeader}}).
> * 
> {{components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java}}
>  - the {{asyncMdnAllowedHosts}} option and its description.
> h3. Code-level change
> * Replace {{isAllowedHost(String host)}} with an authority match that also 
> takes the resolved port (for example {{isAllowedAuthority(String host, int 
> port)}}): parse each {{asyncMdnAllowedHosts}} entry as {{host[:port]}} and 
> compare both the host (case-insensitive) and the port (default-port aware).
> * Pass the already-resolved {{port}} into the match, so the single 
> {{hostIsAllowed}} decision that gates the connection and the attachment of 
> credentials now accounts for the port.
> * Update the {{asyncMdnAllowedHosts}} description on {{AS2Configuration}} to 
> document the {{host[:port]}} form and the default-port rule, then regenerate 
> the catalog/component metadata.
> h3. Tests
> New JUnit methods in {{AS2AsynchronousMDNManagerDeliveryAddressTest}} (that 
> class uses JUnit assertions, so new methods there stay JUnit to match the 
> file):
> * a delivery address whose port is outside every allow-list entry is refused;
> * a delivery address whose host and port both match an entry is accepted;
> * a bare-host entry matches only the default port for its scheme.
> Each new test is shown failing against the current code and passing after the 
> change.
> h3. Documentation
> The default-port behaviour above is a change for an operator that today lists 
> a bare host and delivers to a non-default port, so add a note to 
> {{docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc}} on 
> {{main}} describing the {{host[:port]}} matching and the default-port rule.
> h3. Additional hardening: require https
> The asynchronous MDN delivery scheme is also chosen by the sender, and plain 
> http is accepted, so the configured MDN credentials can be delivered over 
> http even when the operator intended https. A new opt-in option 
> {{asyncMdnRequireHttps}} on {{AS2Configuration}} (default {{false}}) is 
> added: when set, an asynchronous MDN whose delivery address does not use 
> https is refused before the connection is opened and before the configured 
> credentials are attached. The option applies per consumer endpoint, like 
> {{asyncMdnAllowedHosts}}. New JUnit tests cover: http refused when the option 
> is set, https accepted when it is set, and http still accepted by default.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to