From 4a3ba35c1dcda88aedaa23ba48fbca8f1009c594 Mon Sep 17 00:00:00 2001 From: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:26:01 +0100 Subject: [PATCH] Added mTls config for Node-Collector verification Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com> --- OpenTelemetryPlan/05-configuration-reference.md | 4 ++++ cfg/xrpld-example.cfg | 12 ++++++++++++ docs/build/telemetry.md | 2 ++ docs/telemetry-runbook.md | 2 ++ include/xrpl/telemetry/Telemetry.h | 9 +++++++++ src/libxrpl/telemetry/Telemetry.cpp | 6 ++++++ src/libxrpl/telemetry/TelemetryConfig.cpp | 2 ++ 7 files changed, 37 insertions(+) diff --git a/OpenTelemetryPlan/05-configuration-reference.md b/OpenTelemetryPlan/05-configuration-reference.md index 11a7af00f5..c5d39c72d4 100644 --- a/OpenTelemetryPlan/05-configuration-reference.md +++ b/OpenTelemetryPlan/05-configuration-reference.md @@ -86,6 +86,8 @@ enabled=0 | `endpoint` | string | `http://localhost:4318/v1/traces` | OTLP/HTTP collector endpoint | | `use_tls` | bool | `false` | Enable TLS for exporter connection | | `tls_ca_cert` | string | `""` | Path to CA certificate file | +| `tls_client_cert` | string | `""` | Path to node's client certificate (PEM) for mutual TLS; empty = one-way TLS | +| `tls_client_key` | string | `""` | Path to private key (PEM) for `tls_client_cert`; required when it is set | | `sampling_ratio` | float | `1.0` | Sampling ratio (0.0-1.0) | | `batch_size` | uint | `512` | Spans per export batch | | `batch_delay_ms` | uint | `5000` | Max delay before sending batch (ms) | @@ -152,6 +154,8 @@ setupTelemetry( setup.useTls = section.value_or("use_tls", false); setup.tlsCertPath = section.value_or("tls_ca_cert", ""); + setup.tlsClientCertPath = section.value_or("tls_client_cert", ""); + setup.tlsClientKeyPath = section.value_or("tls_client_key", ""); // Sampling setup.samplingRatio = section.value_or("sampling_ratio", 1.0); diff --git a/cfg/xrpld-example.cfg b/cfg/xrpld-example.cfg index 05d1e7a9dc..cddb56bb6d 100644 --- a/cfg/xrpld-example.cfg +++ b/cfg/xrpld-example.cfg @@ -1664,6 +1664,18 @@ validators.txt # Path to a PEM-encoded CA certificate bundle for TLS verification. # Only used when use_tls=1. Default: empty (system CA store). # +# tls_client_cert= +# +# Path to this node's PEM-encoded client certificate, presented to the +# collector for mutual TLS (mTLS). Only used when use_tls=1. Leave empty +# for one-way (server-only) TLS. Default: empty. +# +# tls_client_key= +# +# Path to the PEM-encoded private key for tls_client_cert. Required +# whenever tls_client_cert is set. Only used when use_tls=1. +# Default: empty. +# # sampling_ratio=1.0 # # Head-based sampling ratio using TraceIdRatioBasedSampler. The decision diff --git a/docs/build/telemetry.md b/docs/build/telemetry.md index ed585cb64f..a184fa4ed7 100644 --- a/docs/build/telemetry.md +++ b/docs/build/telemetry.md @@ -139,6 +139,8 @@ trace_ledger=1 | `endpoint` | string | `http://localhost:4318/v1/traces` | OTLP/HTTP collector endpoint | | `use_tls` | int | `0` | Enable TLS for the exporter connection | | `tls_ca_cert` | string | (empty) | Path to CA certificate for TLS | +| `tls_client_cert` | string | (empty) | Client cert (PEM) for mutual TLS; empty = one-way | +| `tls_client_key` | string | (empty) | Private key (PEM) for `tls_client_cert` | | `sampling_ratio` | double | `1.0` | Head-based sampling ratio (`0.0` to `1.0`) | | `batch_size` | uint32 | `512` | Maximum spans per export batch | | `batch_delay_ms` | uint32 | `5000` | Maximum delay (ms) before flushing a batch | diff --git a/docs/telemetry-runbook.md b/docs/telemetry-runbook.md index 52abe23cbe..6e7fe53289 100644 --- a/docs/telemetry-runbook.md +++ b/docs/telemetry-runbook.md @@ -57,6 +57,8 @@ cmake --build --preset default | `max_queue_size` | `2048` | Max spans queued before dropping | | `use_tls` | `0` | Use TLS for exporter connection | | `tls_ca_cert` | (empty) | Path to CA certificate bundle | +| `tls_client_cert` | (empty) | Client cert (PEM) for mutual TLS; empty = one-way TLS | +| `tls_client_key` | (empty) | Private key (PEM) for `tls_client_cert` | ## Span Reference diff --git a/include/xrpl/telemetry/Telemetry.h b/include/xrpl/telemetry/Telemetry.h index 774bee0136..73ca850516 100644 --- a/include/xrpl/telemetry/Telemetry.h +++ b/include/xrpl/telemetry/Telemetry.h @@ -163,6 +163,15 @@ public: /** Path to a CA certificate bundle for TLS verification. */ std::string tlsCertPath; + /** Path to this node's client certificate (PEM), presented to the + collector for mutual TLS. Empty disables client-side auth, in + which case only server (one-way) TLS is used. */ + std::string tlsClientCertPath; + + /** Path to the private key (PEM) for tlsClientCertPath. Required + whenever tlsClientCertPath is set. */ + std::string tlsClientKeyPath; + /** Head-based sampling ratio in [0.0, 1.0]. 1.0 = trace everything. This is a head-based (pre-decision) sampler using TraceIdRatioBasedSampler — the decision to record or drop a diff --git a/src/libxrpl/telemetry/Telemetry.cpp b/src/libxrpl/telemetry/Telemetry.cpp index 251c300d90..31692ee4f5 100644 --- a/src/libxrpl/telemetry/Telemetry.cpp +++ b/src/libxrpl/telemetry/Telemetry.cpp @@ -280,7 +280,13 @@ public: otlp_http::OtlpHttpExporterOptions exporterOpts; exporterOpts.url = setup_.exporterEndpoint; if (setup_.useTls) + { exporterOpts.ssl_ca_cert_path = setup_.tlsCertPath; + // Present a client cert for mutual TLS. When both paths are + // empty the connection falls back to one-way (server) TLS. + exporterOpts.ssl_client_cert_path = setup_.tlsClientCertPath; + exporterOpts.ssl_client_key_path = setup_.tlsClientKeyPath; + } auto exporter = otlp_http::OtlpHttpExporterFactory::Create(exporterOpts); diff --git a/src/libxrpl/telemetry/TelemetryConfig.cpp b/src/libxrpl/telemetry/TelemetryConfig.cpp index b99c5de0b3..98882f7895 100644 --- a/src/libxrpl/telemetry/TelemetryConfig.cpp +++ b/src/libxrpl/telemetry/TelemetryConfig.cpp @@ -59,6 +59,8 @@ setupTelemetry( setup.useTls = section.valueOr("use_tls", 0) != 0; setup.tlsCertPath = section.valueOr("tls_ca_cert", ""); + setup.tlsClientCertPath = section.valueOr("tls_client_cert", ""); + setup.tlsClientKeyPath = section.valueOr("tls_client_key", ""); setup.samplingRatio = section.valueOr("sampling_ratio", 1.0); setup.samplingRatio = std::clamp(setup.samplingRatio, 0.0, 1.0);