Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7d58004
Fix possible panic in case broken protocol
azat Dec 24, 2023
f641bec
Add ability to use rustls over native-tls
azat Dec 24, 2023
0fefc0d
ci: use image from clickhouse/clickhouse-server (over yandex)
azat Dec 25, 2023
68569c5
ci: add configuration with native-tls
azat Dec 25, 2023
b6109f7
ci: start docker manually without services
azat Dec 25, 2023
85fa003
ci: add rustls build
azat Dec 25, 2023
5eb9819
ci: run all tests over secure connection for TLS builds
azat Dec 25, 2023
dd827bd
ci: increase timeout for native-tls (sometimes 500ms is not enough)
azat Dec 25, 2023
5750ab6
Fix test_many_connection for TLS
azat Dec 25, 2023
c9c11b7
ci: enable full stacktraces on CI (to sched some light on timeout pro…
azat Dec 25, 2023
f7ef075
ci: increase timeout for native-tls one more time (attempt to fix tes…
azat Dec 25, 2023
9fb0d8b
Rename tls feature into _tls
azat Dec 25, 2023
0b48f7f
Add backward compatiblity for tls feature (alias for native-tls now)
azat Dec 25, 2023
464b886
Load root certificates for rustls
azat Jan 23, 2024
e47ba33
Merge pull request #208 from azat-rust/fix-panic
suharev7 Mar 31, 2024
abfe517
Merge pull request #209 from azat-rust/rustls
suharev7 Jul 16, 2024
dceebe1
Ensure that Hello packet correctly received
azat Apr 15, 2025
0e67ce2
Properly handle terminated connection by the server
azat Apr 15, 2025
6d42f41
Fix test_size_of expectation (the size should be 64 with alignment)
azat Apr 15, 2025
af660a8
ci: set CLICKHOUSE_SKIP_USER_SETUP to avoid restricting default user
azat Apr 15, 2025
437c4af
Merge branch 'fix-panic-on-hello' into next
azat Apr 15, 2025
829f595
ci: simplify TLS jobs
azat Apr 18, 2025
f27a36d
ci: disable fail-fast for matrix (plus it is how it works before)
azat Apr 18, 2025
f7395a3
ci: temporary enable CI for next branch
azat Apr 18, 2025
525644d
Fix typo (s/DER/PEM/)
azat Apr 18, 2025
4a19933
Add ability to specify certificate
azat Apr 18, 2025
0f913fb
Fix CaUsedAsEndEntity error
azat Apr 18, 2025
b394d6f
ci: generate TLS certificates on the host for client
azat Apr 18, 2025
32051ad
Rename certificate to ca_certificate
azat Apr 18, 2025
0ed5046
Implement mTLS for rustls
azat Apr 18, 2025
0dfa42b
ci: add mTLS
azat Apr 18, 2025
7272327
Add mTLS support for native-tls
azat Apr 18, 2025
6059960
Refactor mTLS support
azat Apr 19, 2025
1463a3b
Update README about TLS features
azat Apr 19, 2025
32ca7b6
Revert "ci: temporary enable CI for next branch"
azat Apr 19, 2025
20cc321
Merge branch 'mTLS-upstream' into next
azat Apr 19, 2025
e5c3345
Add ability to change client name
azat Apr 27, 2025
d21237d
Merge branch 'client-name' into next
azat Apr 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,66 @@ on:

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1

jobs:
build:

runs-on: ubuntu-latest

services:
clickhouse:
image: yandex/clickhouse-server
image: clickhouse/clickhouse-server
ports:
- 9000:9000

env:
CLICKHOUSE_SKIP_USER_SETUP: 1
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose

build-tls:
strategy:
fail-fast: false
matrix:
feature:
- tls-native-tls
- tls-rustls
database_url:
# for TLS we need skip_verify for self-signed certificate
- tcp://localhost:9440?skip_verify=true
# we don't need skip_verify when we pass CA cert
- tcp://localhost:9440?ca_certificate=tls/ca.pem
# mTLS
- tcp://tls@localhost:9440?ca_certificate=tls/ca.pem&client_certificate=tls/client.crt&client_private_key=tls/client.key
runs-on: ubuntu-latest
env:
# NOTE: not all tests "secure" aware, so let's define DATABASE_URL explicitly
# NOTE: sometimes for native-tls default connection_timeout (500ms) is not enough, interestingly that for rustls it is OK.
DATABASE_URL: ${{ matrix.database_url }}&compression=lz4&ping_timeout=2s&retry_timeout=3s&secure=true&connection_timeout=5s
steps:
- uses: actions/checkout@v3
- name: Generate TLS certificates
run: |
extras/ci/generate_certs.sh tls
# NOTE:
# - we cannot use "services" because they are executed before the steps, i.e. repository checkout.
# - "job.container.network" is empty, hence "host"
# - github actions does not support YAML anchors (sigh)
- name: Run clickhouse-server
run: docker run
-v ./extras/ci/overrides.xml:/etc/clickhouse-server/config.d/overrides.xml
-v ./extras/ci/users-overrides.yaml:/etc/clickhouse-server/users.d/overrides.yaml
-v ./tls:/etc/clickhouse-server/tls
-e CLICKHOUSE_SKIP_USER_SETUP=1
--network host
--name clickhouse
--rm
--detach
--publish 9440:9440
clickhouse/clickhouse-server
- name: Build
run: cargo build --features ${{ matrix.feature }} --verbose
- name: Run tests
run: cargo test --features ${{ matrix.feature }} --verbose
22 changes: 21 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ exclude = ["tests/*", "examples/*"]

[features]
default = ["tokio_io"]
tls = ["tokio-native-tls", "native-tls"]
_tls = [] # meta feature for the clickhouse-rs generic TLS code
tls = ["tls-native-tls"] # backward compatibility
tls-native-tls = ["tokio-native-tls", "native-tls", "_tls"]
tls-rustls = ["tokio-rustls", "rustls", "rustls-pemfile", "webpki-roots", "_tls"]
async_std = ["async-std"]
tokio_io = ["tokio"]

Expand Down Expand Up @@ -67,6 +70,22 @@ optional = true
version = "^0.3"
optional = true

[dependencies.rustls]
version = "0.22.1"
optional = true

[dependencies.rustls-pemfile]
version = "2.0"
optional = true

[dependencies.tokio-rustls]
version = "0.25.0"
optional = true

[dependencies.webpki-roots]
version = "*"
optional = true

[dependencies.chrono]
version = "^0.4"
default-features = false
Expand All @@ -76,6 +95,7 @@ features = ["std"]
env_logger = "^0.10"
pretty_assertions = "1.3.0"
rand = "^0.8"
uuid = { version = "^1.4", features = [ "v4" ] }

[dev-dependencies.tokio]
version = "^1.32"
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,13 @@ for the most common use cases. The following features are available.

- `tokio_io` *(enabled by default)* — I/O based on [Tokio](https://tokio.rs/).
- `async_std` — I/O based on [async-std](https://async.rs/) (doesn't work together with `tokio_io`).
- `tls` — TLS support (allowed only with `tokio_io`).
- `tls` — TLS support (allowed only with `tokio_io` and one of TLS libraries, under `tls-rustls` or `tls-native-tls` features).

### TLS

- `skip_verify` - do not verify the server certificate (**insecure**)
- `ca_certificate` - instead of `skip_verify` it is better to pass CA certificate explicitly (in case of self-signed certificates).
- `client_certificate`/`client_private_key` - authentication using TLS certificates (mTLS) (see [ClickHouse documentation](https://clickhouse.com/docs/operations/external-authenticators/ssl-x509) for more info)

## Example

Expand Down
4 changes: 2 additions & 2 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ async fn execute(database_url: String) -> Result<(), Box<dyn Error>> {
Ok(())
}

#[cfg(all(feature = "tokio_io", not(feature = "tls")))]
#[cfg(all(feature = "tokio_io", not(feature = "_tls")))]
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let database_url =
env::var("DATABASE_URL").unwrap_or_else(|_| "tcp://localhost:9000?compression=lz4".into());
execute(database_url).await
}

#[cfg(all(feature = "tokio_io", feature = "tls"))]
#[cfg(all(feature = "tokio_io", feature = "_tls"))]
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let database_url = env::var("DATABASE_URL")
Expand Down
52 changes: 52 additions & 0 deletions extras/ci/generate_certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash

out=$1 && shift
mkdir -p "$out"
cd "$out"

#
# CA
#
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.pem -subj "/C=US/ST=DevState/O=DevOrg/CN=MyDevCA"

#
# server
#
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/C=US/ST=DevState/O=DevOrg/CN=localhost"

cat > server.ext <<EOL
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
EOL

openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.crt -days 825 -sha256 -extfile server.ext
openssl verify -CAfile ca.pem server.crt

#
# client
#
cat > client.ext <<EOL
basicConstraints=CA:FALSE
keyUsage = digitalSignature
extendedKeyUsage = clientAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
EOL

openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/C=US/ST=DevState/O=DevOrg/CN=MyClient"
openssl x509 -req -in client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.crt -days 3650 -sha256 -extfile client.ext
openssl verify -CAfile ca.pem client.crt

# server needs access to those
chmod 644 ca.pem server.key server.crt
19 changes: 19 additions & 0 deletions extras/ci/overrides.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<clickhouse>
<openSSL>
<server>
<certificateFile>/etc/clickhouse-server/tls/server.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-server/tls/server.key</privateKeyFile>
<caConfig>/etc/clickhouse-server/tls/ca.pem</caConfig>
<verificationMode>relaxed</verificationMode>
<loadDefaultCAFile>true</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
</server>
</openSSL>
<tcp_port_secure>9440</tcp_port_secure>

<logger>
<console>1</console>
</logger>
</clickhouse>
6 changes: 6 additions & 0 deletions extras/ci/users-overrides.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
users:
tls:
ssl_certificates:
subject_alt_name:
- DNS:localhost
12 changes: 5 additions & 7 deletions src/client_info.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
use crate::binary::Encoder;

pub static CLIENT_NAME: &str = "Rust SQLDriver";

pub const CLICK_HOUSE_REVISION: u64 = 54429; // DBMS_MIN_REVISION_WITH_SETTINGS_SERIALIZED_AS_STRINGS
pub const CLICK_HOUSE_DBMSVERSION_MAJOR: u64 = 1;
pub const CLICK_HOUSE_DBMSVERSION_MINOR: u64 = 1;

pub fn write(encoder: &mut Encoder) {
encoder.string(CLIENT_NAME);
pub fn write(encoder: &mut Encoder, client_name: &str) {
encoder.string(client_name);
encoder.uvarint(CLICK_HOUSE_DBMSVERSION_MAJOR);
encoder.uvarint(CLICK_HOUSE_DBMSVERSION_MINOR);
encoder.uvarint(CLICK_HOUSE_REVISION);
}

pub fn description() -> String {
pub fn description(client_name: &str) -> String {
format!(
"{CLIENT_NAME} {CLICK_HOUSE_DBMSVERSION_MAJOR}.{CLICK_HOUSE_DBMSVERSION_MINOR}.{CLICK_HOUSE_REVISION}",
"{client_name} {CLICK_HOUSE_DBMSVERSION_MAJOR}.{CLICK_HOUSE_DBMSVERSION_MINOR}.{CLICK_HOUSE_REVISION}",
)
}

#[test]
fn test_description() {
assert_eq!(
description(),
description("Rust SQLDriver"),
format!(
"Rust SQLDriver {}.{}.{}",
CLICK_HOUSE_DBMSVERSION_MAJOR, CLICK_HOUSE_DBMSVERSION_MINOR, CLICK_HOUSE_REVISION
Expand Down
Loading