Skip to content

[backport camel-4.18.x] CAMEL-25645: camel-milo - let the OPC UA client validate the server certificate against a trust list - #28054

Merged
davsclaus merged 2 commits into
apache:camel-4.18.xfrom
oscerd:backport/27824-to-camel-4.18.x
Oct 18, 2026
Merged

davsclaus merged 2 commits into
apache:camel-4.18.xfrom
oscerd:backport/27824-to-camel-4.18.x

Conversation

@oscerd

@oscerd oscerd commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Backport of #27824, with the test follow-up #27999, onto camel-4.18.x.

Original PRs: #27824 - CAMEL-25645: camel-milo - let the OPC UA client validate the server certificate against a trust list, and #27999 - CAMEL-25645: camel-milo - ServerCertificateValidationTest writes the value before the consumers start
Target branch: camel-4.18.x

CAMEL-25645

What it does

As on main, milo-client and milo-browse validate the certificate of the OPC UA server when the selected endpoint uses a security policy other than None:

  • New options:
    • trustListDirectory: Milo's file based trust list. It checks the chain, the validity period, the revocation status and the application URI. A CA-issued certificate needs a CRL of its CA in the trust list.
    • certificateValidator: a custom validator.
    • trustAllCertificates.
  • Without trust configuration, the client does not connect to such an endpoint, and logs a WARN that says why.
  • The same validator checks the certificate that the user name and password are encrypted with.
  • The last connection failure is the cause of No connected.

Adaptations for camel-4.18.x

The milo client code on this branch differs from main, so this is a hand port of the final state of #27824. It needs a review:

  • @UriParam has no security attribute on this branch, so trustAllCertificates is not marked insecure:ssl. There is no SecurityUtils registry to regenerate, and no catalog doc copies.
  • The user name and password only come from the endpoint URI on this branch (there are no username/password options). The validator is passed to that single UsernameProvider.
  • SubscriptionManager uses synchronized blocks instead of a lock, and MiloClientConfiguration.clone() is the copy constructor, which now copies the new options.
  • The connection cache id does not contain the requested publishing interval. The trust settings are appended to this branch's id.
  • Eclipse Milo 1.1.1 on this branch has every API the change uses.
  • The upgrade guide note for this branch goes into the 4.18 guide on main, in the 4.18.6 section.

Tests

  • camel-milo: 58 tests, 0 failures, 1 skipped (MonitorItemMultiConnectionsCertTest, already @Disabled), including ServerCertificateTrustTest, MiloClientConfigurationTest and the end-to-end ServerCertificateValidationTest.
  • A full reactor build of the branch.

Claude Code on behalf of Andrea Cosentino

🤖 Generated with Claude Code

oscerd and others added 2 commits October 18, 2026 12:15
…ertificate against a trust list

milo-client and milo-browse kept the default certificate validator of the
Eclipse Milo client configuration, which accepts any server certificate, and
had no option to configure trust material.

The client now validates the server certificate whenever the selected
endpoint uses a security policy other than None, with the trust list in
trustListDirectory or the validator in certificateValidator, and does not
connect when neither is configured. trustAllCertificates accepts any server
certificate. The trust list checks the application URI, the validity period
and the revocation status, and a certificate issued by a CA needs a
revocation list of that CA. The same validator checks the certificate that
the user identity token is encrypted with. A missing trust configuration and
a failed certificate or security check are logged at WARN, and the last
connection failure is the cause of the "No connected" exception.

Backport of apache#27824, adapted to camel-4.18.x: @UriParam has no security
attribute on this branch, so trustAllCertificates is not marked
insecure:ssl; the user name and password only come from the endpoint URI;
SubscriptionManager uses synchronized blocks; the connection cache id does
not contain the requested publishing interval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
…value before the consumers start (apache#27999)

Since CAMEL-25626 a consumer also delivers a null value with a Bad status, so
a client that connected before the test wrote Foo received the initial Bad
value of the item as well, and mock:trustAll got 2 messages. The two changes
were merged on main 26 seconds apart and neither PR build ran with the other.

The consumer routes now start after the value is written, as MonitorItemTest
does since CAMEL-25626, so Foo is the first notification of each client.

Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit eb14b16)
@oscerd oscerd added the backport indicate that a Pull request is a backport from a fix from the main branch label Oct 18, 2026
@oscerd
oscerd requested review from davsclaus and gnodet October 18, 2026 11:00

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @oscerd.

This port is adapted, so it was reviewed against 1109759 plus the test fix eb14b16 (#27999), which is folded in here. Each difference from main comes from code or API that camel-4.18.x lacks:

  • trustAllCertificates has no security = "insecure:ssl". The @UriParam on 4.18.x has no security attribute, and the branch has no SecurityUtils or security policy framework. That also explains why the SecurityUtils owner map change is left out. So on 4.18.x trustAllCertificates=true is not reported by a prod profile, but the default is still false and the client still refuses to connect without trust settings.
  • SubscriptionManager passes the validator to the only UsernameProvider the branch has, the one built from the URI user info. Main's explicit username/password provider and its creds.length == 2 ? creds[1] : "" empty-password handling come from CAMEL-23812 (58f5ca7), not from CAMEL-25645, so leaving them out is correct. The identity token check is complete for 4.18.x.
  • lastConnectFailure is set in the branch's synchronized handleConnectionFailure rather than inside main's lock, so the behaviour is the same.
  • toCacheId() and MiloClientConfigurationTest keep the branch's cache id without requestedPublishingInterval. The trust settings appended to it are the same as on main.
  • The catalog doc copies are not touched, because 4.18.x does not mirror component docs into the catalog.

ServerCertificateTrust, the docs and the three tests are the same as on main. Branch Milo is 1.1.1, still on the 1.x API. The generated files are consistent: both component JSON copies are identical, indexes are sequential, the three options show up at component and endpoint level, and the configurers, URI factories, component DSL and endpoint DSL are all regenerated. CI is green. The incremental build ran camel-milo (58 tests, 0 failures), including ServerCertificateValidationTest, ServerCertificateTrustTest (13 tests) and MiloClientConfigurationTest.

The upgrade guide note for this behaviour change (a client that used to connect to a Sign/SignAndEncrypt endpoint without trust settings now refuses to connect) is in #28055 on main, under "Upgrading from 4.18.5 to 4.18.6". That one can be merged once this is in.

LGTM.

Claude Code on behalf of Claus Ibsen

@davsclaus davsclaus added this to the 4.18.6 milestone Oct 18, 2026
@davsclaus davsclaus added the bug Something isn't working label Oct 18, 2026
@davsclaus
davsclaus merged commit 4d958fb into apache:camel-4.18.x Oct 18, 2026
3 checks passed
@oscerd
oscerd deleted the backport/27824-to-camel-4.18.x branch October 19, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport indicate that a Pull request is a backport from a fix from the main branch bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants