VLink 2.0.0
A high-performance communication middleware
Loading...
Searching...
No Matches
ssl_options.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file ssl_options.h
26 * @brief Transport-layer SSL/TLS configuration for VLink communication backends.
27 *
28 * @details
29 * @c SslOptions provides a backend-agnostic way to configure transport-layer
30 * TLS encryption. It works through the @c ssl.* property convention that
31 * every transport backend reads during connection setup:
32 *
33 * | Backend | Native TLS Mechanism |
34 * | ---------- | ------------------------------------------------------------ |
35 * | MQTT | @c MQTTClient_SSLOptions (Paho C), auto @c tcp:// to ssl:// |
36 * | DDS | @c TCPv4TransportDescriptor::tls_config (Fast-DDS) |
37 * | CycloneDDS | @c ddsi_config ssl fields (requires @c DDS_HAS_SSL) |
38 * | Zenoh | @c transport/link/tls config keys (zenoh-c, not zenoh-pico) |
39 *
40 * @par Property Keys
41 * | Property Key | @c SslOptions Field | Description |
42 * | -------------------- | -------------------- | -------------------------------------------- |
43 * | @c ssl.ca | @c ca_file | CA certificate file path (PEM) |
44 * | @c ssl.cert | @c cert_file | Client certificate file path (PEM) |
45 * | @c ssl.key | @c key_file | Client private key file path (PEM) |
46 * | @c ssl.key_password | @c key_password | Private key passphrase |
47 * | @c ssl.verify | @c verify_peer | @c "0" to skip verification; default verify |
48 * | @c ssl.server_name | @c server_name | SNI server name override |
49 * | @c ssl.ciphers | @c ciphers | Cipher suite string (OpenSSL format) |
50 *
51 * @par Environment Variable Defaults
52 * When a property is not set explicitly, the factory reads these environment
53 * variables as lowest-priority defaults (property values always take precedence):
54 *
55 * | Environment Variable | Maps to |
56 * | ---------------------- | ------------------ |
57 * | @c VLINK_SSL_CA | @c ssl.ca |
58 * | @c VLINK_SSL_CERT | @c ssl.cert |
59 * | @c VLINK_SSL_KEY | @c ssl.key |
60 * | @c VLINK_SSL_KEY_PASS | @c ssl.key_password|
61 * | @c VLINK_SSL_VERIFY | @c ssl.verify |
62 * | @c VLINK_SSL_SNI | @c ssl.server_name |
63 * | @c VLINK_SSL_CIPHERS | @c ssl.ciphers |
64 *
65 * @par Auto-detection
66 * SSL is considered valid (enabled) when @c ca_file or @c cert_file is
67 * non-empty. There is no separate @c ssl.enabled flag. When SSL is enabled
68 * on DDS/CycloneDDS, TCP transport is automatically activated because TLS
69 * requires TCP.
70 *
71 * @par Usage
72 * @code
73 * // --- Via Node API ---
74 * Publisher<MyMsg> pub("mqtt://sensor/data");
75 * SslOptions ssl;
76 * ssl.ca_file = "/etc/certs/ca.pem";
77 * ssl.cert_file = "/etc/certs/client.pem";
78 * ssl.key_file = "/etc/certs/client-key.pem";
79 * pub.set_ssl_options(ssl);
80 *
81 * // --- Via set_property ---
82 * pub.set_property("ssl.ca", "/etc/certs/ca.pem");
83 *
84 * // --- Via global property ---
85 * MqttConf::set_global_property("ssl.ca", "/etc/certs/ca.pem");
86 *
87 * // --- Via environment variable ---
88 * // export VLINK_SSL_CA=/etc/certs/ca.pem
89 * @endcode
90 *
91 * @note
92 * - Zenoh-pico (@c VLINK_ENABLE_ZENOH_PICO) does not support TLS; a warning
93 * is logged if SSL properties are present.
94 * - CycloneDDS requires @c DDS_HAS_SSL at compile time; a warning is logged
95 * if SSL properties are present but the feature was not compiled in.
96 */
97
98#pragma once
99
100#include <string>
101
102#include "../base/macros.h"
103#include "./conf.h"
104
105namespace vlink {
106
107/**
108 * @struct SslOptions
109 * @brief Aggregate of SSL/TLS settings for transport-layer encryption.
110 *
111 * @details
112 * Populate the desired fields and pass to @c Node::set_ssl_options(), or
113 * use @c parse_from() / @c parse_to() to convert between @c SslOptions and
114 * the @c ssl.* entries in a @c Conf::PropertiesMap.
115 *
116 * @c is_valid() returns @c true when at least @c ca_file or @c cert_file is
117 * set, which the transport backends interpret as "SSL is enabled".
118 */
120 /**
121 * @brief Whether to verify the server certificate.
122 *
123 * @details
124 * Defaults to @c true. Set to @c false to skip peer verification
125 * (maps to @c ssl.verify = @c "0"). This is useful for development
126 * environments with self-signed certificates, but should remain @c true
127 * in production.
128 */
129 bool verify_peer{true};
130
131 /**
132 * @brief Path to the CA certificate file (PEM format).
133 *
134 * @details
135 * Used by all backends to verify the remote peer. Setting this field
136 * (or its corresponding property @c ssl.ca) is one of the two conditions
137 * that makes @c is_valid() return @c true.
138 */
139 std::string ca_file;
140
141 /**
142 * @brief Path to the client certificate file (PEM format).
143 *
144 * @details
145 * Required for mutual TLS (mTLS) where the server verifies the client.
146 * Setting this field is the other condition that makes @c is_valid()
147 * return @c true.
148 */
149 std::string cert_file;
150
151 /**
152 * @brief Path to the client private key file (PEM format).
153 *
154 * @details
155 * Paired with @c cert_file for mutual TLS. If the key is encrypted,
156 * provide the passphrase via @c key_password.
157 */
158 std::string key_file;
159
160 /**
161 * @brief Passphrase for the encrypted private key.
162 *
163 * @details
164 * Only needed when @c key_file is protected by a passphrase.
165 * Corresponds to property @c ssl.key_password and environment variable
166 * @c VLINK_SSL_KEY_PASS.
167 */
168 std::string key_password;
169
170 /**
171 * @brief Server Name Indication (SNI) override.
172 *
173 * @details
174 * When set, the TLS handshake uses this value as the expected server
175 * name instead of the hostname derived from the connection URL.
176 * Used by MQTT, DDS, and Zenoh backends.
177 */
178 std::string server_name;
179
180 /**
181 * @brief Cipher suite string (OpenSSL format).
182 *
183 * @details
184 * Overrides the default cipher suite selection. The format depends on
185 * the underlying TLS library (typically OpenSSL). Leave empty to use
186 * the backend default.
187 */
188 std::string ciphers;
189
190 /**
191 * @brief Default constructor; all strings are empty, @c verify_peer is @c true.
192 */
193 SslOptions() noexcept = default;
194
195 /**
196 * @brief Default destructor.
197 */
198 ~SslOptions() noexcept = default;
199
200 /**
201 * @brief Returns @c true when the configuration contains enough data to enable TLS.
202 *
203 * @details
204 * TLS is considered valid when at least @c ca_file or @c cert_file is
205 * non-empty. An empty @c SslOptions (no certificates at all) is not valid
206 * and the transport backend will not attempt a TLS connection.
207 *
208 * @return @c true if TLS should be enabled.
209 */
210 bool is_valid() const noexcept;
211
212 /**
213 * @brief Constructs an @c SslOptions by reading @c ssl.* entries from a property map.
214 *
215 * @details
216 * Resolution order (highest priority first):
217 * -# Explicit @c ssl.* entries in @p properties.
218 * -# Environment variables (@c VLINK_SSL_CA, @c VLINK_SSL_CERT, etc.).
219 *
220 * Properties not present in either source retain their default values
221 * (@c verify_peer = @c true, all strings empty).
222 *
223 * @param properties The property map to read from.
224 * @return A fully-resolved @c SslOptions.
225 */
226 static SslOptions parse_from(const Conf::PropertiesMap& properties) noexcept;
227
228 /**
229 * @brief Writes the non-default fields back into a property map as @c ssl.* entries.
230 *
231 * @details
232 * Only non-empty string fields and a @c false @c verify_peer are written.
233 * This is the inverse of @c parse_from() and is used internally by
234 * @c Node::set_ssl_options() to merge SSL settings into the node properties.
235 *
236 * @param properties The property map to write into.
237 */
238 void parse_to(Conf::PropertiesMap& properties) const noexcept;
239};
240
241} // namespace vlink
Abstract transport configuration base class and associated helper macros.
Platform-independent macro definitions for the VLink library.
#define VLINK_EXPORT
Definition macros.h:85