Skip to content

ros2_medkit_opcua: add certificate-based OPC-UA authentication (Basic256Sha256) #367

@mfaferek93

Description

@mfaferek93

Context

ros2_medkit_opcua (added in #365) currently connects to OPC-UA servers with Anonymous authentication and SecurityPolicy=None. The plugin logs a warning on startup making this explicit:

OPC-UA security: Anonymous auth, SecurityPolicy=None. Not suitable for untrusted networks.

This is acceptable for isolated LANs, demo environments, and CI testing, but it is not suitable for any deployment where the network between the gateway and the PLC is not fully trusted - which is the normal case in industrial deployments where OPC-UA is deployed alongside safety-critical control traffic.

This issue tracks adding support for certificate-based authentication using Basic256Sha256 (the most widely supported secure OPC-UA profile in industrial PLC servers like Siemens S7, Beckhoff TwinCAT, and Allen-Bradley).

Scope

Code changes

  1. Extend OpcuaClientConfig (include/ros2_medkit_opcua/opcua_client.hpp) with new fields:

    • std::string security_policy - one of None, Basic128Rsa15, Basic256, Basic256Sha256 (default None for backward compat)
    • std::string security_mode - one of None, Sign, SignAndEncrypt (default None)
    • std::string client_cert_path - path to DER or PEM client certificate
    • std::string client_key_path - path to private key
    • std::vector<std::string> trusted_server_certs - optional list of trusted server certificates (or directory)
  2. Wire these through to open62541pp::ClientConfig in OpcuaClient::connect(). The relevant open62541pp APIs are setSecurityPolicy, setCertificate, setPrivateKey, and the trust list configuration.

  3. Handle certificate loading errors gracefully with clear log messages (missing file, wrong format, expired cert, etc.).

  4. Extend the YAML node map schema with a new top-level security: section so configuration is not hardcoded in the plugin parameters.

  5. Environment variable overrides following the existing pattern (OPCUA_CLIENT_CERT, OPCUA_CLIENT_KEY, etc.) for Docker deployment flexibility.

Documentation

  1. Update design/index.rst - replace the Security section with real documentation of the supported profiles and the trust model.
  2. Update README.md with an OPC-UA Security section showing a complete example of running against a PLC with cert auth enabled (certificate generation, trust list, config snippet).
  3. Remove the Security limitations subsection from README once covered, or convert to a Known limitations note listing still-missing features (e.g., username/password, CA chain validation).

Tests

  1. Unit test: parameter loading from YAML into OpcuaClientConfig with all security fields (failure cases for missing cert file, bad profile name).
  2. Unit test: OpcuaClient::connect with a mock OPC-UA server that requires cert auth (requires a fixture server with known cert).
  3. Integration test: new CI job or extension of opcua-plugin.yml that runs OpenPLC configured with cert auth and verifies the plugin connects successfully.

The integration test requires generating a test CA and client certificate during CI setup. This is the main complexity driver of this issue - OpenPLC needs to be configured with a proper trust list, and the test scripts need to create matching client material at runtime.

Acceptance criteria

  • OpcuaClient connects successfully to a server requiring Basic256Sha256 + SignAndEncrypt
  • Config loading rejects malformed cert paths with a clear error
  • New integration test in CI runs against OpenPLC with cert auth enabled
  • Anonymous + None still works for backward compat (existing tests keep passing)
  • Security section in README documents how to enable cert auth end-to-end
  • Startup log messages accurately reflect the selected security mode

Out of scope for this issue

  • Username / password authentication (separate issue)
  • Client certificate generation / rotation inside the plugin
  • Integration with PKI / cert management systems (Hashicorp Vault, etc.)
  • CA chain validation beyond what open62541 provides natively

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions