Implementation:ClickHouse ClickHouse SSLManager InitializeServer
| Knowledge Sources | |
|---|---|
| Domains | Deployment |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Concrete tool for initializing TLS/SSL server and client contexts in ClickHouse through the Poco `SSLManager` singleton, which wraps OpenSSL `SSL_CTX` objects with certificate management, verification callbacks, and cipher configuration.
Description
The `SSLManager` class (declared in `base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h`) is a singleton that manages default SSL contexts for both server and client connections. It provides `initializeServer` and `initializeClient` methods that accept a passphrase handler, an invalid certificate handler, and a pre-configured `Context` object.
The `Context` class (declared in `base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h`) encapsulates an OpenSSL `SSL_CTX` object. It is constructed with a `Usage` enum value specifying the role (client or server, optionally requiring a specific TLS version), along with paths to certificate files, a verification mode, verification chain depth, and a cipher list string.
When `initializeServer` is called, the `SSLManager` stores the provided `Context` as the default server context and registers the passphrase and certificate handlers. Subsequent calls to `defaultServerContext` return this pre-initialized context. If `initializeServer` is never called explicitly, the first call to `defaultServerContext` triggers automatic initialization from the application's XML configuration under the `openSSL.server` prefix.
The `SSLManager` also supports custom named server contexts via `setCustomServerContext` and `getCustomServerContext`, allowing different TLS configurations for different server endpoints (e.g., different ports with different certificates).
Usage
Use `SSLManager::initializeServer` during ClickHouse server startup to configure TLS for incoming connections. Use `SSLManager::initializeClient` to configure TLS for outgoing connections (e.g., distributed queries between nodes, connections to external HTTPS endpoints). Alternatively, rely on automatic configuration by placing TLS parameters in the `<openSSL>` section of `config.xml`.
Code Reference
Source Location
- Repository: ClickHouse
- File:
base/poco/NetSSL_OpenSSL/include/Poco/Net/SSLManager.h(lines 44-352) - File:
base/poco/NetSSL_OpenSSL/include/Poco/Net/Context.h(lines 35-350)
Signature
SSLManager (singleton with server/client initialization):
class SSLManager {
public:
typedef Poco::SharedPtr<PrivateKeyPassphraseHandler> PrivateKeyPassphraseHandlerPtr;
typedef Poco::SharedPtr<InvalidCertificateHandler> InvalidCertificateHandlerPtr;
Poco::BasicEvent<VerificationErrorArgs> ServerVerificationError;
Poco::BasicEvent<VerificationErrorArgs> ClientVerificationError;
Poco::BasicEvent<std::string> PrivateKeyPassphraseRequired;
static SSLManager & instance(); // L166, singleton accessor
void initializeServer(
PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler,
InvalidCertificateHandlerPtr ptrCertificateHandler,
Context::Ptr ptrContext); // L169-172
void initializeClient(
PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler,
InvalidCertificateHandlerPtr ptrHandler,
Context::Ptr ptrContext); // L188-189
Context::Ptr defaultServerContext(); // L205
Context::Ptr defaultClientContext(); // L211
Context::Ptr getCustomServerContext(const std::string & name); // L217
Context::Ptr setCustomServerContext(const std::string & name, Context::Ptr ctx); // L220
void shutdown(); // L251
protected:
static int verifyClientCallback(int ok, X509_STORE_CTX * pStore); // L293
static int verifyServerCallback(int ok, X509_STORE_CTX * pStore); // L298
static int privateKeyPassphraseCallback(char * pBuf, int size, int flag, void * userData); // L303
};
Context (SSL_CTX wrapper):
class Context : public Poco::RefCountedObject {
public:
using Ptr = Poco::AutoPtr<Context>;
enum Usage { // L48-58
CLIENT_USE,
SERVER_USE,
TLSV1_CLIENT_USE,
TLSV1_SERVER_USE,
TLSV1_1_CLIENT_USE,
TLSV1_1_SERVER_USE,
TLSV1_2_CLIENT_USE,
TLSV1_2_SERVER_USE
};
enum VerificationMode { // L60-95
VERIFY_NONE = SSL_VERIFY_NONE,
VERIFY_RELAXED = SSL_VERIFY_PEER,
VERIFY_STRICT = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
VERIFY_ONCE = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE
};
struct Params { // L113-157
std::string privateKeyFile;
std::string certificateFile;
std::string caLocation;
VerificationMode verificationMode; // default: VERIFY_RELAXED
int verificationDepth; // default: 9
bool loadDefaultCAs; // default: false
std::string cipherList; // default: "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH"
std::string dhParamsFile;
std::string ecdhCurve; // default: "prime256v1"
};
Context(Usage usage, const Params & params); // L159
Context(Usage usage,
const std::string & privateKeyFile,
const std::string & certificateFile,
const std::string & caLocation,
VerificationMode verificationMode = VERIFY_RELAXED,
int verificationDepth = 9,
bool loadDefaultCAs = false,
const std::string & cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH"); // L165-173
SSL_CTX * sslContext() const; // L220
Usage usage() const; // L226
bool isForServerUse() const; // L231
VerificationMode verificationMode() const; // L233
void enableSessionCache(bool flag = true); // L236
void enableSessionCache(bool flag, const std::string & sessionIdContext); // L247
void setSessionCacheSize(std::size_t size); // L267
void setSessionTimeout(long seconds); // L282
void disableProtocols(int protocols); // L315
void preferServerCiphers(); // L323
};
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| ptrPassphraseHandler | `PrivateKeyPassphraseHandlerPtr` | No (can be null) | Handler invoked when a passphrase is needed to decrypt the private key. If null, delegates must be registered on `PrivateKeyPassphraseRequired` event. |
| ptrCertificateHandler | `InvalidCertificateHandlerPtr` | No (can be null) | Handler invoked when peer certificate verification fails. If null, delegates must be registered on `ServerVerificationError` or `ClientVerificationError` events. |
| ptrContext | `Context::Ptr` | Yes | Pre-configured SSL context with certificate paths, verification mode, cipher list, and protocol settings. Must be created before calling `initializeServer`. |
| privateKeyFile | `std::string` (in `Params`) | Yes (for server) | Path to PEM-format private key file. |
| certificateFile | `std::string` (in `Params`) | Yes (for server) | Path to PEM-format certificate file. Can be empty if private key file contains both. |
| caLocation | `std::string` (in `Params`) | No | Path to file or directory with CA/root certificates for peer verification. |
| verificationMode | `VerificationMode` (in `Params`) | No | Peer certificate verification policy. Default: `VERIFY_RELAXED`. |
| verificationDepth | `int` (in `Params`) | No | Maximum certificate chain depth. Default: 9. |
| cipherList | `std::string` (in `Params`) | No | OpenSSL cipher list string. Default: `"ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH"`. |
| dhParamsFile | `std::string` (in `Params`) | No | Path to Diffie-Hellman parameters file for forward secrecy. Empty uses defaults. |
| ecdhCurve | `std::string` (in `Params`) | No | ECDH named curve. Default: `"prime256v1"`. |
Outputs
| Name | Type | Description |
|---|---|---|
| Initialized `SSLManager` singleton | `SSLManager &` | The singleton now holds the configured server (or client) context and handlers. Accessible via `SSLManager::instance()`. |
| Default server context | `Context::Ptr` | The configured `Context` object wrapping an OpenSSL `SSL_CTX`, retrievable via `defaultServerContext`. |
| `SSL_CTX` object | `SSL_CTX *` | The underlying OpenSSL context, accessible via `Context::sslContext`. Contains loaded certificates, private keys, verification callbacks, cipher configuration, and session cache settings. |
| Verification callbacks | OpenSSL callbacks | `verifyServerCallback` and `verifyClientCallback` are registered with the `SSL_CTX` to intercept and dispatch certificate verification results through the event system. |
Usage Examples
Programmatic initialization:
#include <Poco/Net/SSLManager.h>
#include <Poco/Net/Context.h>
#include <Poco/Net/RejectCertificateHandler.h>
#include <Poco/Net/KeyConsoleHandler.h>
using namespace Poco::Net;
// Create handlers
SSLManager::PrivateKeyPassphraseHandlerPtr pConsoleHandler = new KeyConsoleHandler(true);
SSLManager::InvalidCertificateHandlerPtr pRejectHandler = new RejectCertificateHandler(true);
// Create server context
Context::Ptr pContext = new Context(
Context::SERVER_USE,
"/etc/clickhouse-server/server.key",
"/etc/clickhouse-server/server.crt",
"/etc/clickhouse-server/ca.pem",
Context::VERIFY_RELAXED,
9,
false,
"ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH"
);
// Initialize the SSLManager singleton
SSLManager::instance().initializeServer(pConsoleHandler, pRejectHandler, pContext);
XML configuration (automatic initialization via config.xml):
<openSSL>
<server>
<privateKeyFile>/etc/clickhouse-server/server.key</privateKeyFile>
<certificateFile>/etc/clickhouse-server/server.crt</certificateFile>
<caConfig>/etc/clickhouse-server/ca.pem</caConfig>
<verificationMode>relaxed</verificationMode>
<verificationDepth>9</verificationDepth>
<loadDefaultCAFile>false</loadDefaultCAFile>
<cipherList>ALL:!ADH:!LOW:!EXP:!MD5:!3DES:@STRENGTH</cipherList>
<preferServerCiphers>true</preferServerCiphers>
<cacheSessions>true</cacheSessions>
<sessionIdContext>clickhouse-server</sessionIdContext>
<disableProtocols>sslv2,sslv3,tlsv1,tlsv1_1</disableProtocols>
<dhParamsFile>/etc/clickhouse-server/dh.pem</dhParamsFile>
<ecdhCurve>prime256v1</ecdhCurve>
<invalidCertificateHandler>
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</server>
</openSSL>