From 93ed7e7f137a5f50d496a1e4abe4a59d7d7e99c5 Mon Sep 17 00:00:00 2001 From: themanforfree Date: Tue, 6 Feb 2024 21:20:47 +0800 Subject: [PATCH 1/4] feat: support certificate authentication Signed-off-by: themanforfree --- Cargo.lock | 103 ++++++++++++++++++- crates/xline/Cargo.toml | 1 + crates/xline/src/server/auth_server.rs | 5 +- crates/xline/src/server/auth_wrapper.rs | 8 +- crates/xline/src/server/kv_server.rs | 33 ++---- crates/xline/src/server/lease_server.rs | 6 +- crates/xline/src/server/lock_server.rs | 11 +- crates/xline/src/server/maintenance.rs | 7 +- crates/xline/src/server/mod.rs | 1 + crates/xline/src/storage/auth_store/store.rs | 29 ++++++ workspace-hack/Cargo.toml | 2 +- 11 files changed, 149 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75b829687..12b58c7ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,6 +263,16 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bcder" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627747a6774aab38beb35990d88309481378558875a41da1a4b2e373c906ef0" +dependencies = [ + "bytes", + "smallvec", +] + [[package]] name = "benchmark" version = "0.1.0" @@ -506,6 +516,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-foundation" version = "0.9.4" @@ -712,6 +728,16 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1154,6 +1180,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hmac" version = "0.12.1" @@ -1384,7 +1416,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ "base64 0.21.7", - "pem", + "pem 1.1.1", "ring 0.16.20", "serde", "serde_json", @@ -2006,6 +2038,16 @@ dependencies = [ "base64 0.13.1", ] +[[package]] +name = "pem" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +dependencies = [ + "base64 0.21.7", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2612,6 +2654,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + [[package]] name = "simple_asn1" version = "0.6.2" @@ -2690,6 +2741,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "strsim" version = "0.10.0" @@ -3714,6 +3775,25 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "x509-certificate" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66534846dec7a11d7c50a74b7cdb208b9a581cad890b7866430d438455847c85" +dependencies = [ + "bcder", + "bytes", + "chrono", + "der", + "hex", + "pem 3.0.3", + "ring 0.17.7", + "signature", + "spki", + "thiserror", + "zeroize", +] + [[package]] name = "xline" version = "0.6.1" @@ -3771,6 +3851,7 @@ dependencies = [ "utils", "uuid", "workspace-hack", + "x509-certificate", "xline-client", "xline-test-utils", "xlineapi", @@ -3886,6 +3967,26 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "zstd-sys" version = "2.0.9+zstd.1.5.5" diff --git a/crates/xline/Cargo.toml b/crates/xline/Cargo.toml index 9980e4405..90d1a2536 100644 --- a/crates/xline/Cargo.toml +++ b/crates/xline/Cargo.toml @@ -71,6 +71,7 @@ tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } utils = { path = "../utils", features = ["parking_lot"] } uuid = { version = "1.1.2", features = ["v4"] } workspace-hack = { version = "0.1", path = "../../workspace-hack" } +x509-certificate = "0.23.1" xlineapi = { path = "../xlineapi" } [build-dependencies] diff --git a/crates/xline/src/server/auth_server.rs b/crates/xline/src/server/auth_server.rs index 5b32298cd..1a43249e5 100644 --- a/crates/xline/src/server/auth_server.rs +++ b/crates/xline/src/server/auth_server.rs @@ -65,10 +65,7 @@ where where T: Into, { - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_store.verify(&token)?), - None => None, - }; + let auth_info = self.auth_store.try_get_auth_info_from_request(&request)?; let request = request.into_inner().into(); let cmd = Command::new_with_auth_info(request.keys(), request, auth_info); let res = self.client.propose(&cmd, None, use_fast_path).await??; diff --git a/crates/xline/src/server/auth_wrapper.rs b/crates/xline/src/server/auth_wrapper.rs index cdbc57d27..2522ae6be 100644 --- a/crates/xline/src/server/auth_wrapper.rs +++ b/crates/xline/src/server/auth_wrapper.rs @@ -13,10 +13,7 @@ use tracing::debug; use xlineapi::command::Command; use super::xline_server::CurpServer; -use crate::{ - server::auth_server::get_token, - storage::{storage_api::StorageApi, AuthStore}, -}; +use crate::storage::{storage_api::StorageApi, AuthStore}; /// Auth wrapper pub(crate) struct AuthWrapper @@ -55,8 +52,7 @@ where "AuthWrapper received propose request: {}", request.get_ref().propose_id() ); - if let Some(token) = get_token(request.metadata()) { - let auth_info = self.auth_store.verify(&token)?; + if let Some(auth_info) = self.auth_store.try_get_auth_info_from_request(&request)? { let mut command: Command = request .get_ref() .cmd() diff --git a/crates/xline/src/server/kv_server.rs b/crates/xline/src/server/kv_server.rs index 2d1ea9881..725e5d2d2 100644 --- a/crates/xline/src/server/kv_server.rs +++ b/crates/xline/src/server/kv_server.rs @@ -1,5 +1,4 @@ use std::{ - fmt::Debug, sync::{ atomic::{AtomicU64, Ordering}, Arc, @@ -20,10 +19,7 @@ use xlineapi::{ AuthInfo, ResponseWrapper, }; -use super::{ - auth_server::get_token, - barriers::{IdBarrier, IndexBarrier}, -}; +use super::barriers::{IdBarrier, IndexBarrier}; use crate::{ metrics, revision_check::RevisionCheck, @@ -114,7 +110,7 @@ where use_fast_path: bool, ) -> Result<(CommandResponse, Option), tonic::Status> where - T: Into + Debug, + T: Into, { let request = request.into(); let cmd = Command::new_with_auth_info(request.keys(), request, auth_info); @@ -214,10 +210,7 @@ where self.kv_storage.compacted_revision(), self.kv_storage.revision(), )?; - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let range_required_revision = range_req.revision; let is_serializable = range_req.serializable; let request = RequestWrapper::from(request.into_inner()); @@ -252,10 +245,7 @@ where let put_req: &PutRequest = request.get_ref(); put_req.validation()?; debug!("Receive grpc request: {:?}", put_req); - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let is_fast_path = true; let (cmd_res, sync_res) = self .propose(request.into_inner(), auth_info, is_fast_path) @@ -284,10 +274,7 @@ where let delete_range_req = request.get_ref(); delete_range_req.validation()?; debug!("Receive grpc request: {:?}", delete_range_req); - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let is_fast_path = true; let (cmd_res, sync_res) = self .propose(request.into_inner(), auth_info, is_fast_path) @@ -321,10 +308,7 @@ where self.kv_storage.compacted_revision(), self.kv_storage.revision(), )?; - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let res = if txn_req.is_read_only() { debug!("TxnRequest is read only"); let is_serializable = txn_req.is_serializable(); @@ -367,10 +351,7 @@ where let current_revision = self.kv_storage.revision(); let req = request.get_ref(); req.check_revision(compacted_revision, current_revision)?; - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let physical = req.physical; let request = RequestWrapper::from(request.into_inner()); let cmd = Command::new_with_auth_info(request.keys(), request, auth_info); diff --git a/crates/xline/src/server/lease_server.rs b/crates/xline/src/server/lease_server.rs index 98cd16d93..63db2c559 100644 --- a/crates/xline/src/server/lease_server.rs +++ b/crates/xline/src/server/lease_server.rs @@ -20,7 +20,6 @@ use xlineapi::{ execute_error::ExecuteError, }; -use super::auth_server::get_token; use crate::{ id_gen::IdGenerator, metrics, @@ -131,10 +130,7 @@ where where T: Into, { - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_storage.verify(&token)?), - None => None, - }; + let auth_info = self.auth_storage.try_get_auth_info_from_request(&request)?; let request = request.into_inner().into(); let keys = { if let RequestWrapper::LeaseRevokeRequest(ref req) = request { diff --git a/crates/xline/src/server/lock_server.rs b/crates/xline/src/server/lock_server.rs index d04f1f623..8c7f6b334 100644 --- a/crates/xline/src/server/lock_server.rs +++ b/crates/xline/src/server/lock_server.rs @@ -15,7 +15,6 @@ use xlineapi::{ AuthInfo, EventType, }; -use super::auth_server::get_token; use crate::{ id_gen::IdGenerator, rpc::{ @@ -227,10 +226,7 @@ where request: tonic::Request, ) -> Result, tonic::Status> { debug!("Receive LockRequest {:?}", request); - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_store.verify(&token)?), - None => None, - }; + let auth_info = self.auth_store.try_get_auth_info_from_request(&request)?; let lock_req = request.into_inner(); let lease_id = if lock_req.lease == 0 { self.lease_grant(auth_info.clone()).await? @@ -304,10 +300,7 @@ where request: tonic::Request, ) -> Result, tonic::Status> { debug!("Receive UnlockRequest {:?}", request); - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_store.verify(&token)?), - None => None, - }; + let auth_info = self.auth_store.try_get_auth_info_from_request(&request)?; let header = self.delete_key(&request.get_ref().key, auth_info).await?; Ok(tonic::Response::new(UnlockResponse { header })) } diff --git a/crates/xline/src/server/maintenance.rs b/crates/xline/src/server/maintenance.rs index 17741e8ea..b662b3fb2 100644 --- a/crates/xline/src/server/maintenance.rs +++ b/crates/xline/src/server/maintenance.rs @@ -13,7 +13,7 @@ use xlineapi::{ RequestWrapper, }; -use super::{auth_server::get_token, command::CommandExecutor}; +use super::command::CommandExecutor; use crate::{ header_gen::HeaderGenerator, rpc::{ @@ -95,10 +95,7 @@ where where T: Into + Debug, { - let auth_info = match get_token(request.metadata()) { - Some(token) => Some(self.auth_store.verify(&token)?), - None => None, - }; + let auth_info = self.auth_store.try_get_auth_info_from_request(&request)?; let request = request.into_inner().into(); let cmd = Command::new_with_auth_info(request.keys(), request, auth_info); let res = self.client.propose(&cmd, None, use_fast_path).await??; diff --git a/crates/xline/src/server/mod.rs b/crates/xline/src/server/mod.rs index 2a87cb0b7..cb52839fd 100644 --- a/crates/xline/src/server/mod.rs +++ b/crates/xline/src/server/mod.rs @@ -21,5 +21,6 @@ mod watch_server; /// Xline server mod xline_server; +pub(crate) use self::auth_server::get_token; pub(crate) use self::maintenance::MAINTENANCE_SNAPSHOT_CHUNK_SIZE; pub use self::xline_server::XlineServer; diff --git a/crates/xline/src/storage/auth_store/store.rs b/crates/xline/src/storage/auth_store/store.rs index 4c6e6b848..f741de4f3 100644 --- a/crates/xline/src/storage/auth_store/store.rs +++ b/crates/xline/src/storage/auth_store/store.rs @@ -16,6 +16,7 @@ use pbkdf2::{ password_hash::{PasswordHash, PasswordVerifier}, Pbkdf2, }; +use tonic::transport::Certificate; use utils::parking_lot_lock::RwLockMap; use xlineapi::{ command::{CommandResponse, KeyRange, SyncResponse}, @@ -44,6 +45,7 @@ use crate::{ AuthenticateResponse, DeleteRangeRequest, LeaseRevokeRequest, Permission, PutRequest, RangeRequest, Request, RequestOp, RequestWrapper, Role, TxnRequest, Type, User, }, + server::get_token, storage::{ auth_store::backend::AuthStoreBackend, db::WriteOp, @@ -131,6 +133,25 @@ where } } + /// Try get auth info from tonic request + pub(crate) fn try_get_auth_info_from_request( + &self, + request: &tonic::Request, + ) -> Result, tonic::Status> { + if let Some(token) = get_token(request.metadata()) { + let auth_info = self.verify(&token)?; + return Ok(Some(auth_info)); + } + if let Some(cn) = get_cn(request) { + let auth_info = AuthInfo { + username: cn, + auth_revision: self.revision(), + }; + return Ok(Some(auth_info)); + } + Ok(None) + } + /// create permission cache fn create_permission_cache(&self) -> Result<(), ExecuteError> { let mut permission_cache = PermissionCache::new(); @@ -1140,6 +1161,14 @@ where } } +/// Get common name from tonic request +fn get_cn(request: &tonic::Request) -> Option { + let chain = request.peer_certs()?; + let cert_der = chain.first()?; + let cert = x509_certificate::X509Certificate::from_der(cert_der.as_ref()).ok()?; + cert.subject_common_name() +} + #[cfg(test)] mod test { use std::collections::HashMap; diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 2c6ee90a2..e30062fb1 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -52,7 +52,7 @@ itertools = { version = "0.11" } libc = { version = "0.2", features = ["extra_traits"] } log = { version = "0.4", default-features = false, features = ["std"] } memchr = { version = "2" } -syn = { version = "2", features = ["extra-traits", "full", "visit-mut"] } +syn = { version = "2", features = ["extra-traits", "full", "visit", "visit-mut"] } tokio = { version = "1", features = ["fs", "io-std", "io-util", "macros", "net", "rt-multi-thread", "signal", "sync", "time"] } ### END HAKARI SECTION From db48e7a6a5a8ca70cd47cc7a110f97c0aab316e3 Mon Sep 17 00:00:00 2001 From: themanforfree Date: Wed, 7 Feb 2024 22:19:36 +0800 Subject: [PATCH 2/4] test: add basic tls tests Signed-off-by: themanforfree --- Cargo.lock | 1 + crates/utils/src/config.rs | 11 ++- crates/utils/src/lib.rs | 24 ----- crates/xline-client/src/lib.rs | 1 + crates/xline-test-utils/Cargo.toml | 1 + crates/xline-test-utils/src/lib.rs | 106 +++++++++++++++------- crates/xline/src/server/xline_server.rs | 1 + crates/xline/tests/it/auth_test.rs | 14 +-- crates/xline/tests/it/cluster_test.rs | 4 +- crates/xline/tests/it/kv_test.rs | 2 +- crates/xline/tests/it/lease_test.rs | 2 +- crates/xline/tests/it/main.rs | 1 + crates/xline/tests/it/maintenance_test.rs | 2 +- crates/xline/tests/it/tls_test.rs | 96 ++++++++++++++++++++ 14 files changed, 196 insertions(+), 70 deletions(-) create mode 100644 crates/xline/tests/it/tls_test.rs diff --git a/Cargo.lock b/Cargo.lock index 12b58c7ca..c72cad1dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3886,6 +3886,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "futures", "madsim-tokio", "rand", "utils", diff --git a/crates/utils/src/config.rs b/crates/utils/src/config.rs index 3b197cb77..2c92f5e4b 100644 --- a/crates/utils/src/config.rs +++ b/crates/utils/src/config.rs @@ -183,7 +183,7 @@ impl ClusterConfig { peer_advertise_urls: Vec, client_listen_urls: Vec, client_advertise_urls: Vec, - members: HashMap>, + peers: HashMap>, is_leader: bool, curp: CurpConfig, client_config: ClientConfig, @@ -196,7 +196,7 @@ impl ClusterConfig { peer_advertise_urls, client_listen_urls, client_advertise_urls, - peers: members, + peers, is_leader, curp_config: curp, client_config, @@ -986,6 +986,13 @@ impl TlsConfig { client_key_path, } } + + /// Whether the server tls is enabled + #[must_use] + #[inline] + pub fn server_tls_enabled(&self) -> bool { + self.server_cert_path.is_some() && self.server_key_path.is_some() + } } /// Xline metrics push protocol diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 5cb3a8501..b7677a871 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -210,30 +210,6 @@ pub fn timestamp() -> u64 { .as_secs() } -/// Certs for tests -pub mod certs { - /// Server certificate - #[inline] - #[must_use] - pub fn server_cert() -> &'static [u8] { - include_bytes!("../../../fixtures/server.crt") - } - - /// Server private key - #[inline] - #[must_use] - pub fn server_key() -> &'static [u8] { - include_bytes!("../../../fixtures/server.key") - } - - /// CA certificate - #[inline] - #[must_use] - pub fn ca_cert() -> &'static [u8] { - include_bytes!("../../../fixtures/ca.crt") - } -} - /// Create a new endpoint from addr /// # Errors /// Return error if addr or tls config is invalid diff --git a/crates/xline-client/src/lib.rs b/crates/xline-client/src/lib.rs index e1bf11c5b..edb6ad244 100644 --- a/crates/xline-client/src/lib.rs +++ b/crates/xline-client/src/lib.rs @@ -234,6 +234,7 @@ impl Client { let channel = Self::build_channel(addrs.clone(), options.tls_config.as_ref()).await?; let curp_client = Arc::new( CurpClientBuilder::new(options.client_config, false) + .tls_config(options.tls_config) .discover_from(addrs) .await? .build::() diff --git a/crates/xline-test-utils/Cargo.toml b/crates/xline-test-utils/Cargo.toml index 7beae2e63..2a0927c75 100644 --- a/crates/xline-test-utils/Cargo.toml +++ b/crates/xline-test-utils/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" [dependencies] anyhow = "1.0.75" clap = { version = "4.4.4", features = ["derive"] } +futures = "0.3.30" rand = "0.8.5" tokio = { version = "0.2.23", package = "madsim-tokio", features = [ "rt-multi-thread", diff --git a/crates/xline-test-utils/src/lib.rs b/crates/xline-test-utils/src/lib.rs index 52a3517d5..f01af427b 100644 --- a/crates/xline-test-utils/src/lib.rs +++ b/crates/xline-test-utils/src/lib.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, env::temp_dir, iter, path::PathBuf, sync::Arc}; +use futures::future::join_all; use rand::{distributions::Alphanumeric, thread_rng, Rng}; use tokio::{ net::TcpListener, @@ -7,6 +8,7 @@ use tokio::{ task::block_in_place, time::{self, Duration}, }; +use tonic::transport::ClientTlsConfig; use utils::config::{ default_quota, AuthConfig, ClusterConfig, CompactConfig, EngineConfig, InitialClusterState, LogConfig, MetricsConfig, StorageConfig, TlsConfig, TraceConfig, XlineServerConfig, @@ -26,6 +28,8 @@ pub struct Cluster { configs: Vec, /// Xline servers servers: Vec>, + /// Client tls config + client_tls_config: Option, /// Client of cluster client: Option, } @@ -59,13 +63,15 @@ impl Cluster { TcpListener::bind("0.0.0.0:0").await.unwrap(), )); } + let server_tls_enabled = configs.iter().any(|c| c.tls().server_tls_enabled()); + let scheme = if server_tls_enabled { "https" } else { "http" }; let all_members_client_urls = listeners .iter() - .map(|l| l.0.local_addr().unwrap().to_string()) + .map(|l| format!("{scheme}://{}", l.0.local_addr().unwrap())) .collect(); let all_members_peer_urls = listeners .iter() - .map(|l| l.1.local_addr().unwrap().to_string()) + .map(|l| format!("{scheme}://{}", l.1.local_addr().unwrap())) .collect(); Self { listeners, @@ -73,17 +79,24 @@ impl Cluster { all_members_client_urls, configs, servers: Vec::new(), + client_tls_config: None, client: None, } } + /// set cluster client tls config + pub fn set_client_tls_config(&mut self, client_tls_config: ClientTlsConfig) { + self.client_tls_config = Some(client_tls_config); + } + /// Start `Cluster` pub async fn start(&mut self) { + let mut futs = Vec::new(); for (i, config) in self.configs.iter().enumerate() { let name = format!("server{}", i); let (xline_listener, curp_listener) = self.listeners.remove(0); - let self_client_url = xline_listener.local_addr().unwrap().to_string(); - let self_peer_url = curp_listener.local_addr().unwrap().to_string(); + let self_client_url = self.get_client_url(i); + let self_peer_url = self.get_peer_url(i); let config = Self::merge_config( config, name, @@ -99,23 +112,29 @@ impl Cluster { InitialClusterState::New, ); - let server = XlineServer::new( - config.cluster().clone(), - config.storage().clone(), - *config.compact(), - config.auth().clone(), - config.tls().clone(), - ) - .await - .unwrap(); + let server = Arc::new( + XlineServer::new( + config.cluster().clone(), + config.storage().clone(), + *config.compact(), + config.auth().clone(), + config.tls().clone(), + ) + .await + .unwrap(), + ); + self.servers.push(Arc::clone(&server)); - let result = server - .start_from_listener(xline_listener, curp_listener) - .await; - if let Err(e) = result { - panic!("Server start error: {e}"); - } + futs.push(async move { + let result = server + .start_from_listener(xline_listener, curp_listener) + .await; + if let Err(e) = result { + panic!("Server start error: {e}"); + } + }); } + join_all(futs).await; // Sleep 30ms, wait for the server to start time::sleep(Duration::from_millis(300)).await; } @@ -134,12 +153,14 @@ impl Cluster { ) { let idx = self.all_members_peer_urls.len(); let name = format!("server{}", idx); - let self_client_url = xline_listener.local_addr().unwrap().to_string(); - let self_peer_url = curp_listener.local_addr().unwrap().to_string(); + let server_tls_enabled = base_config.tls().server_tls_enabled(); + let scheme = if server_tls_enabled { "https" } else { "http" }; + let self_client_url = format!("{scheme}://{}", xline_listener.local_addr().unwrap()); + let self_peer_url = format!("{scheme}://{}", curp_listener.local_addr().unwrap()); self.all_members_client_urls.push(self_client_url.clone()); self.all_members_peer_urls.push(self_peer_url.clone()); - let members = self + let peers = self .all_members_peer_urls .clone() .into_iter() @@ -154,7 +175,7 @@ impl Cluster { name, self_client_url, self_peer_url, - members, + peers, false, InitialClusterState::Existing, ); @@ -179,12 +200,29 @@ impl Cluster { /// Create or get the client with the specified index pub async fn client(&mut self) -> &mut Client { if self.client.is_none() { - let client = Client::connect( - self.all_members_client_urls.clone(), - ClientOptions::default(), - ) - .await - .unwrap_or_else(|e| { + let opts = if let Some(ref ctf) = self.client_tls_config { + ClientOptions::default().with_tls_config(ctf.clone()) + } else { + ClientOptions::default() + }; + let client = Client::connect(self.all_members_client_urls.clone(), opts) + .await + .unwrap_or_else(|e| { + panic!("Client connect error: {:?}", e); + }); + self.client = Some(client); + } + self.client.as_mut().unwrap() + } + + /// Create or get the client with the specified index + pub async fn client2(&mut self, tls_config: ClientTlsConfig) -> &mut Client { + let opts = ClientOptions::default().with_tls_config(tls_config); + let urls = self.all_members_client_urls.clone(); + println!("urls: {:?}", urls); + + if self.client.is_none() { + let client = Client::connect(urls, opts).await.unwrap_or_else(|e| { panic!("Client connect error: {:?}", e); }); self.client = Some(client); @@ -200,10 +238,14 @@ impl Cluster { .collect() } - pub fn get_client_urls(&self, idx: usize) -> String { + pub fn get_client_url(&self, idx: usize) -> String { self.all_members_client_urls[idx].clone() } + pub fn get_peer_url(&self, idx: usize) -> String { + self.all_members_peer_urls[idx].clone() + } + pub fn all_client_addrs(&self) -> Vec { self.all_members_client_urls.clone() } @@ -242,7 +284,7 @@ impl Cluster { name: String, client_url: String, peer_url: String, - members: HashMap>, + peers: HashMap>, is_leader: bool, initial_cluster_state: InitialClusterState, ) -> XlineServerConfig { @@ -253,7 +295,7 @@ impl Cluster { vec![peer_url], vec![client_url.clone()], vec![client_url], - members, + peers, is_leader, old_cluster.curp_config().clone(), *old_cluster.client_config(), diff --git a/crates/xline/src/server/xline_server.rs b/crates/xline/src/server/xline_server.rs index a6277d517..64118d068 100644 --- a/crates/xline/src/server/xline_server.rs +++ b/crates/xline/src/server/xline_server.rs @@ -523,6 +523,7 @@ impl XlineServer { let client = Arc::new( CurpClientBuilder::new(*self.cluster_config.client_config(), false) + .tls_config(self.client_tls_config.clone()) .cluster_version(self.cluster_info.cluster_version()) .all_members(self.cluster_info.all_members_peer_urls()) .bypass(self.cluster_info.self_id(), curp_server.clone()) diff --git a/crates/xline/tests/it/auth_test.rs b/crates/xline/tests/it/auth_test.rs index 27804a088..2370ddb8d 100644 --- a/crates/xline/tests/it/auth_test.rs +++ b/crates/xline/tests/it/auth_test.rs @@ -54,7 +54,7 @@ async fn test_auth_token_with_disable() -> Result<(), Box> { enable_auth(client).await?; let authed_client = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("root", "123"), ) .await?; @@ -117,13 +117,13 @@ async fn test_kv_authorization() -> Result<(), Box> { enable_auth(client).await?; let u1_client = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("u1", "123"), ) .await? .kv_client(); let u2_client = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("u2", "123"), ) .await? @@ -175,13 +175,13 @@ async fn test_no_root_user_do_admin_ops() -> Result<(), Box> { set_user(client, "u", "123", "r", &[], &[]).await?; enable_auth(client).await?; let user_client = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("u", "123"), ) .await? .auth_client(); let root_client = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("root", "123"), ) .await? @@ -212,14 +212,14 @@ async fn test_auth_wrong_password() -> Result<(), Box> { enable_auth(client).await?; let result = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("root", "456"), ) .await; assert!(result.is_err()); let result = Client::connect( - vec![cluster.get_client_urls(0)], + vec![cluster.get_client_url(0)], ClientOptions::default().with_user("root", "123"), ) .await; diff --git a/crates/xline/tests/it/cluster_test.rs b/crates/xline/tests/it/cluster_test.rs index 22100bf42..e10458233 100644 --- a/crates/xline/tests/it/cluster_test.rs +++ b/crates/xline/tests/it/cluster_test.rs @@ -41,9 +41,9 @@ async fn xline_add_node() -> Result<(), Box> { let kv_client = client.kv_client(); _ = kv_client.put(PutRequest::new("key", "value")).await?; let new_node_peer_listener = TcpListener::bind("0.0.0.0:0").await?; - let new_node_peer_urls = vec![new_node_peer_listener.local_addr()?.to_string()]; + let new_node_peer_urls = vec![format!("http://{}", new_node_peer_listener.local_addr()?)]; let new_node_client_listener = TcpListener::bind("0.0.0.0:0").await?; - let new_node_client_urls = vec![new_node_client_listener.local_addr()?.to_string()]; + let new_node_client_urls = vec![format!("http://{}", new_node_client_listener.local_addr()?)]; let add_req = MemberAddRequest::new(new_node_peer_urls.clone(), false); let add_res = cluster_client.member_add(add_req).await?; assert_eq!(add_res.members.len(), 4); diff --git a/crates/xline/tests/it/kv_test.rs b/crates/xline/tests/it/kv_test.rs index 0cc79a598..7f4751081 100644 --- a/crates/xline/tests/it/kv_test.rs +++ b/crates/xline/tests/it/kv_test.rs @@ -171,7 +171,7 @@ async fn test_range_redirect() -> Result<(), Box> { let mut cluster = Cluster::new(3).await; cluster.start().await; - let addr = cluster.get_client_urls(1); + let addr = cluster.get_client_url(1); let kv_client = Client::connect([addr], ClientOptions::default()) .await? .kv_client(); diff --git a/crates/xline/tests/it/lease_test.rs b/crates/xline/tests/it/lease_test.rs index 0dd85ab93..2eb20274b 100644 --- a/crates/xline/tests/it/lease_test.rs +++ b/crates/xline/tests/it/lease_test.rs @@ -45,7 +45,7 @@ async fn test_lease_expired() -> Result<(), Box> { async fn test_lease_keep_alive() -> Result<(), Box> { let mut cluster = Cluster::new(3).await; cluster.start().await; - let non_leader_ep = cluster.get_client_urls(1); + let non_leader_ep = cluster.get_client_url(1); let client = cluster.client().await; let res = client diff --git a/crates/xline/tests/it/main.rs b/crates/xline/tests/it/main.rs index 0656f1419..751fb18e3 100644 --- a/crates/xline/tests/it/main.rs +++ b/crates/xline/tests/it/main.rs @@ -4,4 +4,5 @@ mod kv_test; mod lease_test; mod lock_test; mod maintenance_test; +mod tls_test; mod watch_test; diff --git a/crates/xline/tests/it/maintenance_test.rs b/crates/xline/tests/it/maintenance_test.rs index 7edce626b..c99cc0495 100644 --- a/crates/xline/tests/it/maintenance_test.rs +++ b/crates/xline/tests/it/maintenance_test.rs @@ -30,7 +30,7 @@ async fn test_snapshot_and_restore() -> Result<(), Box> { let _ignore = client.put(PutRequest::new("key", "value")).await?; tokio::time::sleep(Duration::from_millis(100)).await; // TODO: use `propose_index` and remove this sleep after we finished our client. let mut maintenance_client = - Client::connect(vec![cluster.get_client_urls(0)], ClientOptions::default()) + Client::connect(vec![cluster.get_client_url(0)], ClientOptions::default()) .await? .maintenance_client(); let mut stream = maintenance_client.snapshot().await?; diff --git a/crates/xline/tests/it/tls_test.rs b/crates/xline/tests/it/tls_test.rs new file mode 100644 index 000000000..1f71558de --- /dev/null +++ b/crates/xline/tests/it/tls_test.rs @@ -0,0 +1,96 @@ +use std::{fs, iter, path::PathBuf}; + +use test_macros::abort_on_panic; +use tonic::transport::{Certificate, ClientTlsConfig, Identity}; +use utils::config::{ + AuthConfig, ClusterConfig, CompactConfig, LogConfig, StorageConfig, TlsConfig, TraceConfig, + XlineServerConfig, +}; +use xline_client::types::kv::PutRequest; +use xline_test_utils::Cluster; + +#[tokio::test(flavor = "multi_thread")] +#[abort_on_panic] +async fn test_basic_tls() { + let mut cluster = Cluster::new_with_configs(basic_tls_configs(3)).await; + cluster.set_client_tls_config(basic_tls_client_config()); + cluster.start().await; + + let client = cluster.client().await; + let res = client.kv_client().put(PutRequest::new("foo", "bar")).await; + assert!(res.is_ok()); +} + +#[tokio::test(flavor = "multi_thread")] +#[abort_on_panic] +async fn test_mtls() { + let mut cluster = Cluster::new_with_configs(mtls_configs(3)).await; + cluster.set_client_tls_config(mtls_client_config()); + cluster.start().await; + + let client = cluster.client().await; + let res = client.kv_client().put(PutRequest::new("foo", "bar")).await; + assert!(res.is_ok()); +} + +fn basic_tls_client_config() -> ClientTlsConfig { + ClientTlsConfig::default().ca_certificate(Certificate::from_pem( + fs::read("../../fixtures/ca.crt").unwrap(), + )) +} + +fn mtls_client_config() -> ClientTlsConfig { + ClientTlsConfig::default() + .ca_certificate(Certificate::from_pem( + fs::read("../../fixtures/ca.crt").unwrap(), + )) + .identity(Identity::from_pem( + fs::read("../../fixtures/client.crt").unwrap(), + fs::read("../../fixtures/client.key").unwrap(), + )) +} + +fn configs_with_tls_config(size: usize, tls_config: TlsConfig) -> Vec { + iter::repeat(tls_config) + .map(|tls_config| { + XlineServerConfig::new( + ClusterConfig::default(), + StorageConfig::default(), + LogConfig::default(), + TraceConfig::default(), + AuthConfig::default(), + CompactConfig::default(), + tls_config, + ) + }) + .take(size) + .collect() +} + +fn basic_tls_configs(size: usize) -> Vec { + configs_with_tls_config( + size, + TlsConfig::new( + None, + Some(PathBuf::from("../../fixtures/server.crt")), + Some(PathBuf::from("../../fixtures/server.key")), + Some(PathBuf::from("../../fixtures/ca.crt")), + None, + None, + ), + ) +} + +fn mtls_configs(size: usize) -> Vec { + configs_with_tls_config( + size, + TlsConfig::new( + Some(PathBuf::from("../../fixtures/ca.crt")), + Some(PathBuf::from("../../fixtures/server.crt")), + Some(PathBuf::from("../../fixtures/server.key")), + Some(PathBuf::from("../../fixtures/ca.crt")), + Some(PathBuf::from("../../fixtures/client.crt")), + Some(PathBuf::from("../../fixtures/client.key")), + ), + ) +} From c01af08647d0e04f5df753ed8119c329a7c0061b Mon Sep 17 00:00:00 2001 From: themanforfree Date: Thu, 8 Feb 2024 10:34:16 +0800 Subject: [PATCH 3/4] test: add certificate authenticate tests Signed-off-by: themanforfree --- Cargo.lock | 1 + crates/utils/src/lib.rs | 9 ++ crates/xline-test-utils/Cargo.toml | 1 + crates/xline-test-utils/private.pem | 28 ------ crates/xline-test-utils/public.pem | 9 -- crates/xline-test-utils/src/lib.rs | 80 +++++++++++------ crates/xline/src/server/xline_server.rs | 52 ++++++++--- crates/xline/src/storage/auth_store/store.rs | 6 +- crates/xline/tests/it/auth_test.rs | 40 +-------- crates/xline/tests/it/tls_test.rs | 95 +++++++++++++++----- fixtures/client.crt | 20 ----- fixtures/client.key | 28 ------ fixtures/root_client.crt | 20 +++++ fixtures/root_client.key | 28 ++++++ fixtures/u1_client.crt | 20 +++++ fixtures/u1_client.key | 28 ++++++ fixtures/u2_client.crt | 20 +++++ fixtures/u2_client.key | 28 ++++++ scripts/certgen.sh | 28 ++++-- 19 files changed, 347 insertions(+), 194 deletions(-) delete mode 100644 crates/xline-test-utils/private.pem delete mode 100644 crates/xline-test-utils/public.pem delete mode 100644 fixtures/client.crt delete mode 100644 fixtures/client.key create mode 100644 fixtures/root_client.crt create mode 100644 fixtures/root_client.key create mode 100644 fixtures/u1_client.crt create mode 100644 fixtures/u1_client.key create mode 100644 fixtures/u2_client.crt create mode 100644 fixtures/u2_client.key diff --git a/Cargo.lock b/Cargo.lock index c72cad1dc..f0372d0fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3889,6 +3889,7 @@ dependencies = [ "futures", "madsim-tokio", "rand", + "tonic 0.10.2", "utils", "workspace-hack", "xline", diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index b7677a871..46b1ebab0 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -198,6 +198,7 @@ pub mod tokio_lock; /// utils for pass span context pub mod tracing; +use ::tracing::debug; pub use parser::*; /// Get current timestamp in seconds @@ -219,6 +220,14 @@ pub fn build_endpoint( addr: &str, tls_config: Option<&ClientTlsConfig>, ) -> Result { + debug!( + "connect to {addr}{}", + if tls_config.is_some() { + " with tls_config" + } else { + "" + } + ); let scheme_str = addr.split_once("://").map(|(scheme, _)| scheme); let endpoint = match scheme_str { Some(_scheme) => Endpoint::from_str(addr)?, diff --git a/crates/xline-test-utils/Cargo.toml b/crates/xline-test-utils/Cargo.toml index 2a0927c75..733b6c0c5 100644 --- a/crates/xline-test-utils/Cargo.toml +++ b/crates/xline-test-utils/Cargo.toml @@ -23,6 +23,7 @@ tokio = { version = "0.2.23", package = "madsim-tokio", features = [ "net", "signal", ] } +tonic = "0.10.2" utils = { path = "../utils", features = ["parking_lot"] } workspace-hack = { version = "0.1", path = "../../workspace-hack" } xline = { path = "../xline" } diff --git a/crates/xline-test-utils/private.pem b/crates/xline-test-utils/private.pem deleted file mode 100644 index a88842602..000000000 --- a/crates/xline-test-utils/private.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnAxxSXJYWZCKr -6f6j0HRUwkhX/0+GXjEclWoLA5+KZAuWMSu8bz6X+IScv4vNwORlGSWOnrz+8mb2 -I0F6teVZWfWFqsnyWk7IxM+h9yTg7aY/8685YfWTL7fpWq1/3Fniz4QbsYFuzB1V -gaZ5fD2CSYIKzSD+qVSlXF25JDFHV7b2OdHrX0UKZOTWY/VE//STt+PJKdX9R3pl -kGwAzJIkkcAZy0vhvqT3ASTgXchNeN8wGYYb3YirkqIsQB5Xcs1R1W+yz+IrVa6/ -0WMcyE6qtJPZ0lviyT0nHV/pZjXuD4B0aja/1fk/HmXDPMjpK1BuCBTStM/KlcrA -oAxo+YDhAgMBAAECggEAIyJhY+Y8YMuCC753JkklH+ubQn/gX/kSxduc6mJBvuBb -G6aOd97DQT8zzrHxHEDXC3ml0AIO6mdeR6uVC9aWQBzPrOYIA+cBqfTVZVJTvMnh -7pQ6KY01F1izjPDZjQtzEWbseNL30rI3/ZP/zJDZc745EEKlDU3cE8mBogA+Ka6w -GLozT9qQf8knBrtzxH6SvrZpfaRlP95is82b4IuPhqYdG7dVYFTALE1MyVrCbS4Y -KytjNLgwp1bIQtWrzMebBGoiU+DvDcRY8zvOfFupDwpYCt3p1aU5wyYYdr74esV7 -jjqHj89Ua65JHJ3XnMAaMc4dHM2FsGqMsOv/DDKInQKBgQDawckQEekx0QuP3eJP -GWdZ87oc+FVjDe3bYhAnCf/yXRJoqcs5vr1m1yCXFfsjbQFYHWXR9AUtNn5HCwOZ -zoT1Mv96fXBVGQORgzvlUWS43uKpfIPDVv2I6ZcKSIQAGOgcWYvmBDhYqPHgmx3o -VSrNGWtLdyw3rD1J6O+1RwtbiwKBgQDDchmY59EXBiTvlyT3Qjl0vZFMHa+TElbh -ikNtYltbUHtamOXZzpdk/KA7X2dYi0QpVfbbpfP/ly5lYvgZwl8h90Obopru+ACM -ndlKBfNQYArmWY6bJ2CwF7j1aTCCHZuVuX6/pzFVStRcssn15uoVaIyKd/MhJzLF -S3ertQkSwwKBgAniMYRhWsjeaghQ/RWXzzyYL3N5oNn92h5MWvB4mjDIFbnW2hC8 -1m/cDmPlIVijZyklAuGuhcFaMfBhxgLf+s/dQv+0xSuDGs8rP7yHpeZYY6NGtelQ -d9oEu8dCKXybo3kMbq6wyB7xWyRLvdkuZ+WmXVumgb/uL0K0nIfzMscrAoGAeA1e -K845YSslBQaSbk7/e/X1iguyDWT2eRO01zvTYgPNwZipl2CPHjkPM2km0fy5oaps -N/94IUd7+EsSmsAKL5LytGbtRFyR+c376rw8+OIFz/iy4BsQCRqJQjWa1lHZf96x -PIg2hW2xhD9OTv3IS94sdeG4NmUdipMQryhEqoECgYEAkvXOg66IAVTrO6qgoyl5 -42oufa/QE+qOAYoQEpmx3SZx6tMkycfAQqUHYcXhW1HNjyGbbg/sl13yddnPQqig -+ObtQNSIqGZWCc/HIqM//pPI3MHPhWARMOmAbk0I1mT0QKhuFfSugV2xb1Dj/Rvf -0VdB8txY+5Wz6zP1F2g46gM= ------END PRIVATE KEY----- diff --git a/crates/xline-test-utils/public.pem b/crates/xline-test-utils/public.pem deleted file mode 100644 index 4c52eb652..000000000 --- a/crates/xline-test-utils/public.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApwMcUlyWFmQiq+n+o9B0 -VMJIV/9Phl4xHJVqCwOfimQLljErvG8+l/iEnL+LzcDkZRkljp68/vJm9iNBerXl -WVn1harJ8lpOyMTPofck4O2mP/OvOWH1ky+36Vqtf9xZ4s+EG7GBbswdVYGmeXw9 -gkmCCs0g/qlUpVxduSQxR1e29jnR619FCmTk1mP1RP/0k7fjySnV/Ud6ZZBsAMyS -JJHAGctL4b6k9wEk4F3ITXjfMBmGG92Iq5KiLEAeV3LNUdVvss/iK1Wuv9FjHMhO -qrST2dJb4sk9Jx1f6WY17g+AdGo2v9X5Px5lwzzI6StQbggU0rTPypXKwKAMaPmA -4QIDAQAB ------END PUBLIC KEY----- diff --git a/crates/xline-test-utils/src/lib.rs b/crates/xline-test-utils/src/lib.rs index f01af427b..e1bfd24de 100644 --- a/crates/xline-test-utils/src/lib.rs +++ b/crates/xline-test-utils/src/lib.rs @@ -14,6 +14,10 @@ use utils::config::{ LogConfig, MetricsConfig, StorageConfig, TlsConfig, TraceConfig, XlineServerConfig, }; use xline::server::XlineServer; +use xline_client::types::auth::{ + AuthRoleAddRequest, AuthRoleGrantPermissionRequest, AuthUserAddRequest, + AuthUserGrantRoleRequest, Permission, PermissionType, +}; pub use xline_client::{types, Client, ClientOptions}; /// Cluster @@ -28,8 +32,6 @@ pub struct Cluster { configs: Vec, /// Xline servers servers: Vec>, - /// Client tls config - client_tls_config: Option, /// Client of cluster client: Option, } @@ -79,16 +81,10 @@ impl Cluster { all_members_client_urls, configs, servers: Vec::new(), - client_tls_config: None, client: None, } } - /// set cluster client tls config - pub fn set_client_tls_config(&mut self, client_tls_config: ClientTlsConfig) { - self.client_tls_config = Some(client_tls_config); - } - /// Start `Cluster` pub async fn start(&mut self) { let mut futs = Vec::new(); @@ -200,34 +196,27 @@ impl Cluster { /// Create or get the client with the specified index pub async fn client(&mut self) -> &mut Client { if self.client.is_none() { - let opts = if let Some(ref ctf) = self.client_tls_config { - ClientOptions::default().with_tls_config(ctf.clone()) - } else { - ClientOptions::default() - }; - let client = Client::connect(self.all_members_client_urls.clone(), opts) - .await - .unwrap_or_else(|e| { - panic!("Client connect error: {:?}", e); - }); + let client = Client::connect( + self.all_members_client_urls.clone(), + ClientOptions::default(), + ) + .await + .unwrap_or_else(|e| { + panic!("Client connect error: {:?}", e); + }); self.client = Some(client); } self.client.as_mut().unwrap() } /// Create or get the client with the specified index - pub async fn client2(&mut self, tls_config: ClientTlsConfig) -> &mut Client { - let opts = ClientOptions::default().with_tls_config(tls_config); - let urls = self.all_members_client_urls.clone(); - println!("urls: {:?}", urls); - - if self.client.is_none() { - let client = Client::connect(urls, opts).await.unwrap_or_else(|e| { + pub async fn client_with_tls_config(&mut self, client_tls_config: ClientTlsConfig) -> Client { + let opts = ClientOptions::default().with_tls_config(client_tls_config); + Client::connect(self.all_members_client_urls.clone(), opts) + .await + .unwrap_or_else(|e| { panic!("Client connect error: {:?}", e); - }); - self.client = Some(client); - } - self.client.as_mut().unwrap() + }) } pub fn all_members_client_urls_map(&self) -> HashMap { @@ -349,3 +338,36 @@ fn random_id() -> String { .map(char::from) .collect() } + +pub async fn set_user( + client: &Client, + name: &str, + password: &str, + role: &str, + key: &[u8], + range_end: &[u8], +) -> Result<(), Box> { + let client = client.auth_client(); + client + .user_add(AuthUserAddRequest::new(name).with_pwd(password)) + .await?; + client.role_add(AuthRoleAddRequest::new(role)).await?; + client + .user_grant_role(AuthUserGrantRoleRequest::new(name, role)) + .await?; + if !key.is_empty() { + client + .role_grant_permission(AuthRoleGrantPermissionRequest::new( + role, + Permission::new(PermissionType::Readwrite, key).with_range_end(range_end), + )) + .await?; + } + Ok(()) +} + +pub async fn enable_auth(client: &Client) -> Result<(), Box> { + set_user(client, "root", "123", "root", &[], &[]).await?; + client.auth_client().auth_enable().await?; + Ok(()) +} diff --git a/crates/xline/src/server/xline_server.rs b/crates/xline/src/server/xline_server.rs index 64118d068..25f7a54da 100644 --- a/crates/xline/src/server/xline_server.rs +++ b/crates/xline/src/server/xline_server.rs @@ -635,28 +635,58 @@ impl XlineServer { async fn read_tls_config( tls_config: &TlsConfig, ) -> Result<(Option, Option)> { - let client_tls_config = - if let Some(ca_cert_path) = tls_config.client_ca_cert_path().as_ref() { - let ca = Certificate::from_pem(fs::read(ca_cert_path).await?); - Some(ClientTlsConfig::new().ca_certificate(ca)) - } else { - None - }; + let client_tls_config = match ( + tls_config.client_ca_cert_path().as_ref(), + tls_config.client_cert_path().as_ref(), + tls_config.client_key_path().as_ref(), + ) { + (Some(ca_path), Some(cert_path), Some(key_path)) => { + let ca = fs::read(ca_path).await?; + let cert = fs::read(cert_path).await?; + let key = fs::read(key_path).await?; + Some( + ClientTlsConfig::new() + .ca_certificate(Certificate::from_pem(ca)) + .identity(Identity::from_pem(cert, key)), + ) + } + (Some(ca_path), None, None) => { + let ca = fs::read(ca_path).await?; + Some(ClientTlsConfig::new().ca_certificate(Certificate::from_pem(ca))) + } + (_, Some(_), None) | (_, None, Some(_)) => { + return Err(anyhow!( + "client_cert_path and client_key_path must be both set" + )) + } + _ => None, + }; let server_tls_config = match ( + tls_config.server_ca_cert_path().as_ref(), tls_config.server_cert_path().as_ref(), tls_config.server_key_path().as_ref(), ) { - (Some(cert_path), Some(key_path)) => { + (Some(ca_path), Some(cert_path), Some(key_path)) => { + let ca = fs::read(ca_path).await?; + let cert = fs::read_to_string(cert_path).await?; + let key = fs::read_to_string(key_path).await?; + Some( + ServerTlsConfig::new() + .client_ca_root(Certificate::from_pem(ca)) + .identity(Identity::from_pem(cert, key)), + ) + } + (None, Some(cert_path), Some(key_path)) => { let cert = fs::read_to_string(cert_path).await?; let key = fs::read_to_string(key_path).await?; Some(ServerTlsConfig::new().identity(Identity::from_pem(cert, key))) } - (None, None) => None, - _ => { + (_, Some(_), None) | (_, None, Some(_)) => { return Err(anyhow!( - "server_cert_path and server_key_path must be both set" + "client_cert_path and client_key_path must be both set" )) } + _ => None, }; Ok((client_tls_config, server_tls_config)) } diff --git a/crates/xline/src/storage/auth_store/store.rs b/crates/xline/src/storage/auth_store/store.rs index f741de4f3..347e0df47 100644 --- a/crates/xline/src/storage/auth_store/store.rs +++ b/crates/xline/src/storage/auth_store/store.rs @@ -16,7 +16,6 @@ use pbkdf2::{ password_hash::{PasswordHash, PasswordVerifier}, Pbkdf2, }; -use tonic::transport::Certificate; use utils::parking_lot_lock::RwLockMap; use xlineapi::{ command::{CommandResponse, KeyRange, SyncResponse}, @@ -108,7 +107,7 @@ where } /// Get enabled of Auth store - pub(super) fn is_enabled(&self) -> bool { + pub(crate) fn is_enabled(&self) -> bool { self.enabled.load(AtomicOrdering::Relaxed) } @@ -138,6 +137,9 @@ where &self, request: &tonic::Request, ) -> Result, tonic::Status> { + if !self.is_enabled() { + return Ok(None); + } if let Some(token) = get_token(request.metadata()) { let auth_info = self.verify(&token)?; return Ok(Some(auth_info)); diff --git a/crates/xline/tests/it/auth_test.rs b/crates/xline/tests/it/auth_test.rs index 2370ddb8d..2692ffaa4 100644 --- a/crates/xline/tests/it/auth_test.rs +++ b/crates/xline/tests/it/auth_test.rs @@ -6,12 +6,9 @@ use utils::config::{ TraceConfig, XlineServerConfig, }; use xline_test_utils::{ + enable_auth, set_user, types::{ - auth::{ - AuthRoleAddRequest, AuthRoleDeleteRequest, AuthRoleGrantPermissionRequest, - AuthUserAddRequest, AuthUserGetRequest, AuthUserGrantRoleRequest, Permission, - PermissionType, - }, + auth::{AuthRoleDeleteRequest, AuthUserAddRequest, AuthUserGetRequest}, kv::{PutRequest, RangeRequest}, }, Client, ClientOptions, Cluster, @@ -228,39 +225,6 @@ async fn test_auth_wrong_password() -> Result<(), Box> { Ok(()) } -async fn set_user( - client: &Client, - name: &str, - password: &str, - role: &str, - key: &[u8], - range_end: &[u8], -) -> Result<(), Box> { - let client = client.auth_client(); - client - .user_add(AuthUserAddRequest::new(name).with_pwd(password)) - .await?; - client.role_add(AuthRoleAddRequest::new(role)).await?; - client - .user_grant_role(AuthUserGrantRoleRequest::new(name, role)) - .await?; - if !key.is_empty() { - client - .role_grant_permission(AuthRoleGrantPermissionRequest::new( - role, - Permission::new(PermissionType::Readwrite, key).with_range_end(range_end), - )) - .await?; - } - Ok(()) -} - -async fn enable_auth(client: &Client) -> Result<(), Box> { - set_user(client, "root", "123", "root", &[], &[]).await?; - client.auth_client().auth_enable().await?; - Ok(()) -} - fn configs_with_auth(size: usize) -> Vec { iter::repeat_with(|| { ( diff --git a/crates/xline/tests/it/tls_test.rs b/crates/xline/tests/it/tls_test.rs index 1f71558de..527b305c1 100644 --- a/crates/xline/tests/it/tls_test.rs +++ b/crates/xline/tests/it/tls_test.rs @@ -1,22 +1,24 @@ use std::{fs, iter, path::PathBuf}; +use etcd_client::ConnectOptions; use test_macros::abort_on_panic; use tonic::transport::{Certificate, ClientTlsConfig, Identity}; use utils::config::{ - AuthConfig, ClusterConfig, CompactConfig, LogConfig, StorageConfig, TlsConfig, TraceConfig, - XlineServerConfig, + AuthConfig, ClusterConfig, CompactConfig, LogConfig, MetricsConfig, StorageConfig, TlsConfig, + TraceConfig, XlineServerConfig, }; use xline_client::types::kv::PutRequest; -use xline_test_utils::Cluster; +use xline_test_utils::{enable_auth, set_user, Cluster}; #[tokio::test(flavor = "multi_thread")] #[abort_on_panic] async fn test_basic_tls() { let mut cluster = Cluster::new_with_configs(basic_tls_configs(3)).await; - cluster.set_client_tls_config(basic_tls_client_config()); cluster.start().await; - let client = cluster.client().await; + let client = cluster + .client_with_tls_config(basic_tls_client_config()) + .await; let res = client.kv_client().put(PutRequest::new("foo", "bar")).await; assert!(res.is_ok()); } @@ -25,29 +27,58 @@ async fn test_basic_tls() { #[abort_on_panic] async fn test_mtls() { let mut cluster = Cluster::new_with_configs(mtls_configs(3)).await; - cluster.set_client_tls_config(mtls_client_config()); cluster.start().await; - let client = cluster.client().await; + let client = cluster + .client_with_tls_config(mtls_client_config("root")) + .await; let res = client.kv_client().put(PutRequest::new("foo", "bar")).await; assert!(res.is_ok()); } -fn basic_tls_client_config() -> ClientTlsConfig { - ClientTlsConfig::default().ca_certificate(Certificate::from_pem( - fs::read("../../fixtures/ca.crt").unwrap(), - )) -} +#[tokio::test(flavor = "multi_thread")] +#[abort_on_panic] +async fn test_certificate_authenticate() { + let mut cluster = Cluster::new_with_configs(mtls_configs(3)).await; + cluster.start().await; -fn mtls_client_config() -> ClientTlsConfig { - ClientTlsConfig::default() - .ca_certificate(Certificate::from_pem( - fs::read("../../fixtures/ca.crt").unwrap(), - )) - .identity(Identity::from_pem( - fs::read("../../fixtures/client.crt").unwrap(), - fs::read("../../fixtures/client.key").unwrap(), - )) + let root_client = cluster + .client_with_tls_config(mtls_client_config("root")) + .await; + enable_auth(&root_client).await.unwrap(); + + let addr = cluster.get_client_url(0); + let mut etcd_u2_client = etcd_client::Client::connect( + [addr], + Some(ConnectOptions::new().with_tls(mtls_client_config("u2"))), + ) + .await + .unwrap(); + let res = etcd_u2_client.put("foa", "bar", None).await; + assert!(res.is_err()); + let u1_client = cluster + .client_with_tls_config(mtls_client_config("u1")) + .await; + let res = u1_client + .kv_client() + .put(PutRequest::new("foo", "bar")) + .await; + assert!(res.is_err()); + + set_user(&root_client, "u1", "123", "r1", b"foo", &[]) + .await + .unwrap(); + set_user(&root_client, "u2", "123", "r2", b"foa", &[]) + .await + .unwrap(); + + let res = etcd_u2_client.put("foa", "bar", None).await; + assert!(res.is_ok()); + let res = u1_client + .kv_client() + .put(PutRequest::new("foo", "bar")) + .await; + assert!(res.is_ok()); } fn configs_with_tls_config(size: usize, tls_config: TlsConfig) -> Vec { @@ -61,12 +92,19 @@ fn configs_with_tls_config(size: usize, tls_config: TlsConfig) -> Vec ClientTlsConfig { + ClientTlsConfig::default().ca_certificate(Certificate::from_pem( + fs::read("../../fixtures/ca.crt").unwrap(), + )) +} + fn basic_tls_configs(size: usize) -> Vec { configs_with_tls_config( size, @@ -81,6 +119,17 @@ fn basic_tls_configs(size: usize) -> Vec { ) } +fn mtls_client_config(name: &str) -> ClientTlsConfig { + ClientTlsConfig::default() + .ca_certificate(Certificate::from_pem( + fs::read("../../fixtures/ca.crt").unwrap(), + )) + .identity(Identity::from_pem( + fs::read(format!("../../fixtures/{name}_client.crt")).unwrap(), + fs::read(format!("../../fixtures/{name}_client.key")).unwrap(), + )) +} + fn mtls_configs(size: usize) -> Vec { configs_with_tls_config( size, @@ -89,8 +138,8 @@ fn mtls_configs(size: usize) -> Vec { Some(PathBuf::from("../../fixtures/server.crt")), Some(PathBuf::from("../../fixtures/server.key")), Some(PathBuf::from("../../fixtures/ca.crt")), - Some(PathBuf::from("../../fixtures/client.crt")), - Some(PathBuf::from("../../fixtures/client.key")), + Some(PathBuf::from("../../fixtures/root_client.crt")), + Some(PathBuf::from("../../fixtures/root_client.key")), ), ) } diff --git a/fixtures/client.crt b/fixtures/client.crt deleted file mode 100644 index 01f9937cb..000000000 --- a/fixtures/client.crt +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgIUMZLpA3uyobcdSCkiD69HmT3Bd44wDQYJKoZIhvcNAQEL -BQAwDTELMAkGA1UEAwwCY2EwHhcNMjQwMTA3MTMxMjU5WhcNMzQwMTA0MTMxMjU5 -WjARMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC3qOWWsEgOywxEjbUIbrXag1DiifyXwE3Nhk81YUuoJ1qM0otX7TDLbSvb -sJdF2Us8nvVqxpnL96e6Ez5tOfz6MMCwscL8Z8Hwww/aCf2+nPlh/vOhqerN6rqR -+DzUOLDejP09nyH4OI6AsatVvn1gaSa+GZws1nj2qt7g7e4vFetQTwDI+TOmayqh -mjsfMRt/7INGrNLZPAqx2VUkVDonaSLdZJKS23UIHQXsHZ9rEnsWC6SwwKdyJ4Hm -Vw1P8yvgNawGv/WQoTUXTT/NdBwOwFiQ5ahl5Lb7tojMLzm2UeV4aok++w5WJB3T -Rdbw7mXyypAe4ViIPbG1gOM1atJlAgMBAAGjgZQwgZEwDgYDVR0PAQH/BAQDAgWg -MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAgBgNVHREEGTAXgglsb2Nh -bGhvc3SHBH8AAAGHBAAAAAAwHQYDVR0OBBYEFLQylaXlVoHK/04BZxaGtLGmN4LX -MB8GA1UdIwQYMBaAFPzHZyv/ULvDt5jwK7NmgPRHsD0YMA0GCSqGSIb3DQEBCwUA -A4IBAQA+a2M2W6kzliDMlHOmmGdqIgVHyCXIdkYUC/du4hJQgykRJ1o/A/oJmUyH -jWM2ZbZVXnS7GdfxT7zOHKhRiwPUGW6g76rExT+Iy8+Wo/WeY4obtwFvFiIoGdbv -dG1zXaiCtJoTnNShnz+q0VhsVKDaIW/H6vlwLP+KSMQXOZug5/N0DvfZyq8lbAfj -rKr16jl4sLonXXNXS9d+84HxrGHUmoAtylvvAsfaII09D/hUpkqMu6LDeuhLRdv1 -NjeAS0hDgWTffDXxzReI/M8FqbE0+zxNe4FADLujItTyyzm1x9gaNnhEKS3CPZRN -XJiug7z4LEf8+QAHM41YqV8KOWNh ------END CERTIFICATE----- diff --git a/fixtures/client.key b/fixtures/client.key deleted file mode 100644 index cf0868de5..000000000 --- a/fixtures/client.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC3qOWWsEgOywxE -jbUIbrXag1DiifyXwE3Nhk81YUuoJ1qM0otX7TDLbSvbsJdF2Us8nvVqxpnL96e6 -Ez5tOfz6MMCwscL8Z8Hwww/aCf2+nPlh/vOhqerN6rqR+DzUOLDejP09nyH4OI6A -satVvn1gaSa+GZws1nj2qt7g7e4vFetQTwDI+TOmayqhmjsfMRt/7INGrNLZPAqx -2VUkVDonaSLdZJKS23UIHQXsHZ9rEnsWC6SwwKdyJ4HmVw1P8yvgNawGv/WQoTUX -TT/NdBwOwFiQ5ahl5Lb7tojMLzm2UeV4aok++w5WJB3TRdbw7mXyypAe4ViIPbG1 -gOM1atJlAgMBAAECggEAAJsu5fuifEkvw8P0HBTXzzrt3WGNWbTxTMxB05FP61bR -xnwuCaEM0o8Qr9ImUqK7NfqZBltM1TQ8bz7TkQ9HAdLgivkrx8HWZZYtBsUa2DsU -D8dT0X9eHE8fcRLc2aOSieAhDFUfitsOlnS0oiteaG6Jy+Ms/laMQy3RROudgEvd -cqg3Khl/bqjKY72b8rEPn/hLEDhcqPMviU+Zn4oaB9YJzOm1aYGAN1DEHJvEP1Le -RVMunFBvpBDBLSpexGbTqPCIWclWnk99oYKlOmQBdE2AAa1Qmh8K8RcIUiibfl8y -YCpCBQdvekZeeILbpV4El8sKtNxWVuIzrBnDU7yYAQKBgQDTaEGHL6mkBPDi1eEs -Y763BZ1bgPfl3ci9loHkzt+WVrioi+LvKMueLcrv/unhH9J7CNQ4TIVL35FE/S8E -jiNKU2lziVrHurXYydvK1EQwLsfqyKBZSw+Ep6p56rFBKw882fzV8dGRadPoCVLC -36ikn15/I+7yd8f6jiiDRbDcZQKBgQDeZk77XlUNloWRUYorEMT799CQk5QiUZ6O -LpsEJSLLZIseOkEkM3rN7cRrOYm8rVeo+s5Kv4y+rWusNksBmYYGJbA1QWfNKiTj -3xfH5aX2sRfaiPYszFO2zZv0/DnH9ssZWzMVO1xj7EpuNRgm2+x4NtautAIoys9U -Mv3NH5u+AQKBgD3BDqM2wQ8wgk1AvO4ClQtRkI3SNpfnGWSIOplj9NwtqPNTKY9D -E3e5WLaSeC9S5GEcSyHG+IkZXY4Rh1KFUrm7c+pUDTiaydPx40p0hxasE6n5wR1U -V8wgTiQe8nhe46ya4Mh+QwF/MG9vicVzIAg2pZvuGzao1rnSHPN7wBYhAoGAcwJP -R9iRfVRgwDR9kiW66F5QAeP/j/vLVdWuHmeh5bKZ6sjPVQw2LnYNxDFeFC9EDMOe -mLMT8qs16jmtcidVUqp8xB2Ns2Be8WQ2JQ6SU89i+YUoYSRNClSrmPYyX0E16Gfs -M8ed0KKqHvHgCoBiegxJ2tCF6Vhv/Sfdbg0xegECgYAHeT/5ChFov9UNsvtX+6Po -y7s93cT8V4YYhjngDRj+E6uW5McPNwL+gyk0UV892lwriAwoBa+YDMiISV74F412 -Hh4R6mdBhDAcggdqMQc7ewwDYMgtSjteDSJ0jYyVqHgX023gIivxi7YZw0GdB+3O -CNKda8If9TEtUy4TD8Y5qQ== ------END PRIVATE KEY----- diff --git a/fixtures/root_client.crt b/fixtures/root_client.crt new file mode 100644 index 000000000..d95b9d893 --- /dev/null +++ b/fixtures/root_client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPzCCAiegAwIBAgIUSfB3FqdIGUJJcelUrsRG0ctY9AcwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCY2EwHhcNMjQwMjA4MDE1MDQ2WhcNMzQwMjA1MDE1MDQ2 +WjAPMQ0wCwYDVQQDDARyb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAsJvXvzxxWqL9k5lDiKsZExegcwZssXbtKs/9IpphIdnJtKxL0sYZMVLDgFxG +yvGbB7W2u4z/DEfPwT2yH6D67Yq2igZDDSB6TfD5EkZ0K0IFI3YBvMd55K+1+Ofe +rL5OXJ0p8UYUAjVnhUvq12RrQN4w4pywb1cv1+XATLO1pYRjxkxy+csk8BxudMyb +Vq4CiCYTnhPjCu4FOW9ecZYWMHRYkZ92Z85f5QeEd29xGz9/zgEw3NEYAyjJt0HZ +Ye3cS9j5PR+WOjAAEorKleD/Yr0sqdFJa5LSwjzJhqexgGTAe43UV+jpvk8PN8sH +ZTcNmKrR4KQ4mqV+QWjaiNwgDQIDAQABo4GUMIGRMA4GA1UdDwEB/wQEAwIFoDAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwIAYDVR0RBBkwF4IJbG9jYWxo +b3N0hwR/AAABhwQAAAAAMB0GA1UdDgQWBBS17ALmZXD0x059Sxa4/nR5mq43/jAf +BgNVHSMEGDAWgBT8x2cr/1C7w7eY8CuzZoD0R7A9GDANBgkqhkiG9w0BAQsFAAOC +AQEAgV0SvYUgtPbykIJnT2YH8bQUabEwX37/nJbIRTK/K+vknI6QXGfVf7tZlYrN +8wSMy6thEhlJnoU8CMsN+dp9iyt13kZypE+4R05AdU6QLeD2L0mKFrUvSxRFhoVo +Zsc0AhBdVFpDPylMiWohVLrglgKrsdpQVLzePs107ep3GOYlX7Tm1q4OPCvbwewi ++EP5wwFpEakiOg3eK/zbJX3tqDBVEARfskuSVyxAqN+xLO9nSehfGbkER20PWQyR +fgGoJOR098J033ogylo0z6HbAXMqD+sS8Q4ndURBu4+Q8pjd/mTjDWzyhU0vbTHn +Hz2s9I5v9wsrYlyQr84YKZBRQw== +-----END CERTIFICATE----- diff --git a/fixtures/root_client.key b/fixtures/root_client.key new file mode 100644 index 000000000..6e21d5d5a --- /dev/null +++ b/fixtures/root_client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwm9e/PHFaov2T +mUOIqxkTF6BzBmyxdu0qz/0immEh2cm0rEvSxhkxUsOAXEbK8ZsHtba7jP8MR8/B +PbIfoPrtiraKBkMNIHpN8PkSRnQrQgUjdgG8x3nkr7X4596svk5cnSnxRhQCNWeF +S+rXZGtA3jDinLBvVy/X5cBMs7WlhGPGTHL5yyTwHG50zJtWrgKIJhOeE+MK7gU5 +b15xlhYwdFiRn3Znzl/lB4R3b3EbP3/OATDc0RgDKMm3Qdlh7dxL2Pk9H5Y6MAAS +isqV4P9ivSyp0UlrktLCPMmGp7GAZMB7jdRX6Om+Tw83ywdlNw2YqtHgpDiapX5B +aNqI3CANAgMBAAECggEACXPh7ZCq4YbJS0HgCTvdLPYuBpIQtcPviEPXIOfB7Kmn +P+Yb7dVgClGLeL6XpGufmF9Lv0iZ6xqZ3lYyxzoazCWJRSR2KMj0+uB7uFRwidMw +CriZebT0i36zHvYsJzNNZuwbj1gooICiwJHyaSJtEi0CUVLBJ8hzHVtk+kYBIjF3 +ydwBVP8QNXlUsXc+0zfvEvlzcEiT8QbdOUNs/eQZVbBjXlcyp0w3gH7RglKbS4zh +JRvbko5ndYeBoDnl3uVH7Gy+YbByEXyiZ09r4vOMmp3SoDVzb62uJvz2nNfo1tn7 +2PADFBJ870tGDS9czidlHF1Os+X2cX3UetqUUBcKQQKBgQDJ6H/GF5rI0Ai6GTkr +0DqpCu7CNGiHNYXpPid2/Kys1xiceZMCOwv2FTbkTZCPU5jETvTWOQbmIec1eqQt +RzwqkWf9pGO3kSdXZlPYIx1MVRjdozml/0wlo8CVe+J3VUbAiTpoSj09xyKgJoE+ +bcsj/gRkBXfAxz6pe/DhIwaxzQKBgQDf7Dp2Lxm9K14wHL5Ye+d1qqUklc23at5E +E1E6I7tTXFWU9ZQSWAKiGfDGB9EBxU2bqLhpkhygRNdz9kv2c2RK5qM1QbdhgJsM +jTXbMd7c11lgMTndeFiRqnRsZdAbOTvVqOFn7H7qXLY3Krp8rn+nIr908EV+c8IP +TqHxy53nQQKBgE9x/0y3nvzi9nwbTqaRsXMwTQ/3RSXmhoFnJmooM91yaUmwgIrB +Jwy1/jpI1te+gf7EPoxINhG5R1uAnTb/r4nkWvGvjFj/cWZvahBCiNWvKjCTeCx7 +zr+EtlNbQpnH4SYDGQtOIti7EUHIxNQGqYbI/XtJt3wQKfTQQtCjUpAFAoGAD/dn +H8AyBKQP/jw+ck67bU9yoQ4xce+j05TRCOU9WS9PRuTP3xL5dReGbIhoJcksxHme +VKC/e8oM1s7sEbGeqByT7Js3+TLTW2zCN1PyASs1yz8XUixfnFtcG9KSqS5GjvCQ +yfk5/3oG4B4i1/sVTRSUNEFhoyeb4b2InJYZN0ECgYEAgodPz7ub5ZlTHonwM7yc +PVRUShRevI2xe9XvpyzYhy2KGv/IxGr8XAxyBmH7cl8VbZW98nA0jKDLk4LjvEg3 +ki0R83ve4xVxISDHXnXkWyYy2Zn3F2ZDeSGx1rjXwTYOnEkRWmk+U0+J7CtmL+uJ +itBsAsAc/N6Ou9xamMO4ohA= +-----END PRIVATE KEY----- diff --git a/fixtures/u1_client.crt b/fixtures/u1_client.crt new file mode 100644 index 000000000..ab7ac4e35 --- /dev/null +++ b/fixtures/u1_client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPTCCAiWgAwIBAgIUPNdbG6JyVpNanAE4Jxz0Zc7uhdkwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCY2EwHhcNMjQwMjA4MDE1MDQ3WhcNMzQwMjA1MDE1MDQ3 +WjANMQswCQYDVQQDDAJ1MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AOrk6fzfKC56niK9aP0AgdWwfw7h0xEHS4IUY3qQvUglaG1QMjCItlXwXsdYVBa3 +Wasdavy+8H5KS77VTaX4fdQzFmzAmd5odGI34/S59Be72+uvFREiUH2DKC37ilAl +eBHEHyeXPcLxZQujvLMt1i3S3HQ+NCKia+llURcEd7mE9omP1YiVRukBLCeT3LHe +fkNwCdeZH/VbNh7GyoxN87kaaCPv9y224WYGw/Bpg+vu0QSTrrS2vx7lgwUdgXVs +ktZD0dini8+gxiub6R2KKhdBJof3IlHw8O8PPCIHDSyADslHxoIrkW2rwlcmYBhe +AEQKq3TnCJZQ6y/OXMI9vqMCAwEAAaOBlDCBkTAOBgNVHQ8BAf8EBAMCBaAwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCAGA1UdEQQZMBeCCWxvY2FsaG9z +dIcEfwAAAYcEAAAAADAdBgNVHQ4EFgQU2xBZdDwcNrOiQ12fpGvTKJmMX0wwHwYD +VR0jBBgwFoAU/MdnK/9Qu8O3mPArs2aA9EewPRgwDQYJKoZIhvcNAQELBQADggEB +AIfy9lqvQ6vV5Ja1p7Xa2j85cLrHwqRu9PMYCQTRCKS/A48UggwtZ0wgkMNhDAUf +4iiwPGe3EUY6ax3SPazSavrsYgF944ZjshiRutaKawEi5F4w8KF01TsI5q6ckOQL +m03mer14Mq4oZ5OZO5RFjQN4aN/8cIaz88tMXZyKAxYnU5o7jUtCUiWRdt7en+gl +A2ULMIG27rDuDQDGYdu4T/mnjMu54pKoYbh4GKOoePll6OMHqpCOu3t0WT5FGzmR +37lFLFIjtzPunqxgtm4UixjRzPL8uxGbBdkMwRWtSrw43wPb2zzyvhKwoS8FyK8h +RLUoOh38z/WdXYwvbaLIoPo= +-----END CERTIFICATE----- diff --git a/fixtures/u1_client.key b/fixtures/u1_client.key new file mode 100644 index 000000000..dab4a7531 --- /dev/null +++ b/fixtures/u1_client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq5On83yguep4i +vWj9AIHVsH8O4dMRB0uCFGN6kL1IJWhtUDIwiLZV8F7HWFQWt1mrHWr8vvB+Sku+ +1U2l+H3UMxZswJneaHRiN+P0ufQXu9vrrxURIlB9gygt+4pQJXgRxB8nlz3C8WUL +o7yzLdYt0tx0PjQiomvpZVEXBHe5hPaJj9WIlUbpASwnk9yx3n5DcAnXmR/1WzYe +xsqMTfO5Gmgj7/cttuFmBsPwaYPr7tEEk660tr8e5YMFHYF1bJLWQ9HYp4vPoMYr +m+kdiioXQSaH9yJR8PDvDzwiBw0sgA7JR8aCK5Ftq8JXJmAYXgBECqt05wiWUOsv +zlzCPb6jAgMBAAECggEASetf90QC0R2lRil1MKlIMocodPZ8BY/WI0lnRNrnthyP +kFb8dGmRd9n8+Z7CV6O7hC3tzTwJUrTuwU8+8EwSzQSGuhKiWWtltMMB6bHbLtzf +iHvAlXPHALiVnGLcU/x2nKCrbTobJY3xzofoijqSfDkvRyWMIpoae4h2zFeLlcW3 +rTBWpPITz7JTl7/oxLaoXccLFQEIUUwxVjecV4ZbLQZaWwtzdCric6lxEc+IXq09 +jzHQMRU6mwqlTn6qM1qNGPDD+h5ze23X+RQ5YxZRaMJ5yjtyVcz74+Po02aqbeAR +W4Los+4zxsjLwKgWESgpQlEIigX+8Wy0khEPnBWpAQKBgQDvVVdbTWzggHgaPaZb +A0uEHrN5LqvDrJODveMmlmQgtUZkUFTqkPi+d1Cx+thtCU4vHkux74cqsMMZl7Sz +rjqbMd97rLBL8WpKP6a5Ws9LQxjHW/JZJgHrfoz5ryADHOzZLs6hv8QVUm3MaOet +I2DODQqUJ86vvVHJCeU6j3l3qwKBgQD7QG8+lZzfIyWHXK1Z52HCer0/4JWcZ4H0 +SPIbVQLQlvl1m+yxqBVwmsC8a4eg791A057I5hY2SexjKD79OCRCEz0//dwSEQn0 +Y12fFiWp0CMtKiqQKCstWRN6wvIwIuhretegZ46Dl2lsYTBQ7kIuT7KzEVVn2XKl +cLbdtyt86QKBgQCS+i7ulCrT6DFZtBiQdgKPPadsOTwkq7vfwOJZlSwiZhC3lBnB +/4uytGVrF6iHtZo9F3bW7Elu7ySxd9fyLIIzQrqDIfcWfEiRFmvWEq2RA8CY1Z+M +Heo56/q5b1HSd5YAfl1JOhI6IefqC1aTnlFZ2OpxN80XYcVzF8+dWfT3hwKBgQDA +6uPACT7PcnwxaG7OlkRRAM9pSbd2xV9aQ9xqMiccJKBctqHSc34q3RhaVLJqV2Lq +kNLd7RVnD/HK3S8oXUAx3/XqubCNyrl7BgTvzyCSN/eaiULvN3iXtEqpuyAc5+DQ +Dh2c04bw8YSILEPeEGOOjbFnn0qVl7hY4af3q9pfaQKBgHv1gFa8myukZpN8YoxD +rLMUBD1gpeTSjVAhqIUFjo4yRO/gfLz+c2ImLetZzSvIyExEUa07bH47Jy4U+CbV +1sZ3AKiJcoI/bAR9+G8ol7j/SXAHpcZl+v/8cAlQLg9njy8TV8J2iWd1vdMIwLa2 +064UOsO11uIdTJ+TFbmJYvI2 +-----END PRIVATE KEY----- diff --git a/fixtures/u2_client.crt b/fixtures/u2_client.crt new file mode 100644 index 000000000..45d63f837 --- /dev/null +++ b/fixtures/u2_client.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPTCCAiWgAwIBAgIUHlpAGnA7JzeANDHScWspJJI34IUwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCY2EwHhcNMjQwMjA4MDE1MDQ3WhcNMzQwMjA1MDE1MDQ3 +WjANMQswCQYDVQQDDAJ1MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMZG9a04m4N4HAlsfi5DJC796rSrEmnXiXMZltoTjTtwCYihR2aUNiJui/vujlEA +x/qyo1d5ryRmnRL5pAXwYtf+wjvUEVyx+6omaS3PbB+f0HdlQR/GvDzoSvhg3/dZ +7LW952RHSSTkC3HTb9LM2bYmbEkeAH4aUzLKtUCzQmth7Qzwu/SsALjWoIC7kCZN +i4Ba3ONwtO03nF8Kr3Dzg6HGTxEK3X9aWf+qaVIgJJZfeX7FZFh21liDcbXahAux +yhgPycxsQ/Fkip2JRPCw6K7k2SdesuvnuDE+tWJfDRlZUcXiXNEE1PxgUN9fr8d3 +DTyM1Vu0OMioCoSCwvZ6iBMCAwEAAaOBlDCBkTAOBgNVHQ8BAf8EBAMCBaAwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCAGA1UdEQQZMBeCCWxvY2FsaG9z +dIcEfwAAAYcEAAAAADAdBgNVHQ4EFgQU9dQyV9zQfB6LhFz3qarACKXk6GIwHwYD +VR0jBBgwFoAU/MdnK/9Qu8O3mPArs2aA9EewPRgwDQYJKoZIhvcNAQELBQADggEB +AEiENIrVfgkFSkWhVY7bYmv7GvV4I0/xkXvt3YkWqB1TRlT0w74c7C6uJHgqYuGo +c21iu1h64PD0hjE9QryGV4Y9Ph9kwOSSrP4LIisRJfH84F3bBpJlglsJ3cp/6fb0 +5yizQIomMey/W2SHdbAEsFccMbuJiD/LM/ei8BWzYsFcalMnzeNf4b7JvcB+yNjR +DVAehsYorEkjOYsGBYfMNMud8N0PQqLHQcUHp+eWqBZBGunUXBEERs5RgZaVG6+q +5ZrKyqYES2PtvndcaQAIc97ChS3uQa02exaW9h5H0KuWmBwMvrbrNR4aS1dgRkWN +UUiEGX3p+uQpKc3YYi+lMv4= +-----END CERTIFICATE----- diff --git a/fixtures/u2_client.key b/fixtures/u2_client.key new file mode 100644 index 000000000..75e547f7a --- /dev/null +++ b/fixtures/u2_client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGRvWtOJuDeBwJ +bH4uQyQu/eq0qxJp14lzGZbaE407cAmIoUdmlDYibov77o5RAMf6sqNXea8kZp0S ++aQF8GLX/sI71BFcsfuqJmktz2wfn9B3ZUEfxrw86Er4YN/3Wey1vedkR0kk5Atx +02/SzNm2JmxJHgB+GlMyyrVAs0JrYe0M8Lv0rAC41qCAu5AmTYuAWtzjcLTtN5xf +Cq9w84Ohxk8RCt1/Wln/qmlSICSWX3l+xWRYdtZYg3G12oQLscoYD8nMbEPxZIqd +iUTwsOiu5NknXrLr57gxPrViXw0ZWVHF4lzRBNT8YFDfX6/Hdw08jNVbtDjIqAqE +gsL2eogTAgMBAAECggEALyzo/UrvrWsheJiIuSceb9PYSR4+5lHzESCwhLiMLO0u +R4TgAScYbj7RLaMH13wRGLPyKzj3k/iaPM6K2SLl0bB6tFNzwhNS5pv3AIBOoIOc +zRuZUB8v4GoAlHIwN6D8sg06BeD0JUPg+TcubwBweGdR8l+iDF7lFrumPnuoPPYH +g+txdPWdmFcd50eLLqvxjnBtr4v4CGk/DDQucBjfX4YjUfImRx1uwyV60fKdGrGs +24oGFzZLj/yGSn6tbszHc+ndag+ukE7KVroY9lCxwMKDcIco6SDcuuXBoGrm181m +SlYGC1a0Sui2meLGDKSnm4HQD8E8hCPsvEq2lsUuyQKBgQDhm7G0B901izxcZSZZ ++Ba9kUIybcrek3XV57UXXl76Mp6zelHazFiZxqk99Sj0AgKAxV76E9iHZBYSnnPs +TegqC29eBkYB8/3gaqwNyQRN4gXn0ptE9RT15tXfiuCJLiO8USOk0FJRQ2hTOni4 +Mk+XteB13ay8z1bowr0tvEYB3QKBgQDg/LskWo7z7WoXvaZ5s+Jhmq1btGKdMdMf +A/KRnapMhK+t+aGUNEzldvokqGGK0nmDRN6lvsaNPRcXoAuO5p1gI/vUNS4k9rJj +gyfSfeOJdK/8KoLRqeTesnTYK5ObkKVN4SltVFUz7D2oqB0pqnxI6q6+hkx/4AbL +fsOdYQUqrwKBgBBJSAPCCZMC8SGOX71g7mtS4B9504pLxNbjOixssJiJLPGx49TS +qZa4Q6FoYEN1Ha8kEF4nLptfe0Ru0dl+KkNWvfxgoY8kiPA5YyA/oaLprRl2F6Vb +t96kgk333YupnATNKrCMJVUec5qGfw50+0/tXj3D+eNLaG+3FycFD1y1AoGBAKcZ +rlji1Ze/9nMpjVKI0xORET6yLCf6UIaRpQCX7FsmlWCOrn5nldE726+MS94SUuO3 +K/JITimqfNM0MEFzcOFt+GT1Fo+nlnioedQxYeS+gNK2NDFKkM0CGBxRyTDabpv4 +Jo+n+hw1UtpH+lju4Z46h4zELF8xYXqUbO8flvnLAoGBAJR8Ydn53dnUvo85pbWt +AOd/75/vmim8a09J6aXkb8r+AT2cXIR8IImssxh7qaiICDCGeM1tMfEWVvL2bxYh +Q5nYDWf/gloZuST1DvRdGd1ZDouQsZfHZWRdWoBBmKFNFNB3qWYCAMenXZompdsS +hHmdRI1y9mCB+77usYvx23xo +-----END PRIVATE KEY----- diff --git a/scripts/certgen.sh b/scripts/certgen.sh index 060947ecd..2c57986a3 100755 --- a/scripts/certgen.sh +++ b/scripts/certgen.sh @@ -8,9 +8,17 @@ SERVER_KEY=${DIR}/certs/server.key SERVER_CSR=${DIR}/certs/server.csr SERVER_CRT=${DIR}/certs/server.crt -CLIENT_KEY=${DIR}/certs/client.key -CLIENT_CSR=${DIR}/certs/client.csr -CLIENT_CRT=${DIR}/certs/client.crt +ROOT_CLIENT_KEY=${DIR}/certs/root_client.key +ROOT_CLIENT_CSR=${DIR}/certs/root_client.csr +ROOT_CLIENT_CRT=${DIR}/certs/root_client.crt + +U1_CLIENT_KEY=${DIR}/certs/u1_client.key +U1_CLIENT_CSR=${DIR}/certs/u1_client.csr +U1_CLIENT_CRT=${DIR}/certs/u1_client.crt + +U2_CLIENT_KEY=${DIR}/certs/u2_client.key +U2_CLIENT_CSR=${DIR}/certs/u2_client.csr +U2_CLIENT_CRT=${DIR}/certs/u2_client.crt OPENSSL_CONF=${DIR}/certs/openssl.conf @@ -41,6 +49,14 @@ EOF [ -f ${SERVER_CSR} ] || openssl req -new -key ${SERVER_KEY} -subj "/CN=server" -out ${SERVER_CSR} -config ${OPENSSL_CONF} || exit 1 [ -f ${SERVER_CRT} ] || openssl x509 -req -in ${SERVER_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${SERVER_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 -[ -f ${CLIENT_KEY} ] || openssl genrsa -out ${CLIENT_KEY} 2048 || exit 1 -[ -f ${CLIENT_CSR} ] || openssl req -new -key ${CLIENT_KEY} -subj "/CN=client" -out ${CLIENT_CSR} -config ${OPENSSL_CONF} || exit 1 -[ -f ${CLIENT_CRT} ] || openssl x509 -req -in ${CLIENT_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${CLIENT_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 +[ -f ${ROOT_CLIENT_KEY} ] || openssl genrsa -out ${ROOT_CLIENT_KEY} 2048 || exit 1 +[ -f ${ROOT_CLIENT_CSR} ] || openssl req -new -key ${ROOT_CLIENT_KEY} -subj "/CN=root" -out ${ROOT_CLIENT_CSR} -config ${OPENSSL_CONF} || exit 1 +[ -f ${ROOT_CLIENT_CRT} ] || openssl x509 -req -in ${ROOT_CLIENT_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${ROOT_CLIENT_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 + +[ -f ${U1_CLIENT_KEY} ] || openssl genrsa -out ${U1_CLIENT_KEY} 2048 || exit 1 +[ -f ${U1_CLIENT_CSR} ] || openssl req -new -key ${U1_CLIENT_KEY} -subj "/CN=u1" -out ${U1_CLIENT_CSR} -config ${OPENSSL_CONF} || exit 1 +[ -f ${U1_CLIENT_CRT} ] || openssl x509 -req -in ${U1_CLIENT_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${U1_CLIENT_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 + +[ -f ${U2_CLIENT_KEY} ] || openssl genrsa -out ${U2_CLIENT_KEY} 2048 || exit 1 +[ -f ${U2_CLIENT_CSR} ] || openssl req -new -key ${U2_CLIENT_KEY} -subj "/CN=u2" -out ${U2_CLIENT_CSR} -config ${OPENSSL_CONF} || exit 1 +[ -f ${U2_CLIENT_CRT} ] || openssl x509 -req -in ${U2_CLIENT_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${U2_CLIENT_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 From 9ea486b084740ba30880d196f8c1369ebd9da5c1 Mon Sep 17 00:00:00 2001 From: themanforfree Date: Wed, 6 Mar 2024 10:44:47 +0800 Subject: [PATCH 4/4] chore: rename server_cert to peer_cert Signed-off-by: themanforfree --- crates/utils/src/config.rs | 36 ++++++++++++------------- crates/xline/src/server/xline_server.rs | 10 +++---- crates/xline/src/utils/args.rs | 12 ++++----- scripts/certgen.sh | 18 ++++++++----- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/crates/utils/src/config.rs b/crates/utils/src/config.rs index 2c92f5e4b..f6e5383bb 100644 --- a/crates/utils/src/config.rs +++ b/crates/utils/src/config.rs @@ -945,16 +945,16 @@ impl AuthConfig { #[non_exhaustive] #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Getters, Default)] pub struct TlsConfig { - /// The CA certificate file used by server to verify client certificates + /// The CA certificate file used by peer to verify client certificates #[getset(get = "pub")] - pub server_ca_cert_path: Option, - /// The public key file used by server + pub peer_ca_cert_path: Option, + /// The public key file used by peer #[getset(get = "pub")] - pub server_cert_path: Option, - /// The private key file used by server + pub peer_cert_path: Option, + /// The private key file used by peer #[getset(get = "pub")] - pub server_key_path: Option, - /// The CA certificate file used by client to verify server certificates + pub peer_key_path: Option, + /// The CA certificate file used by client to verify peer certificates #[getset(get = "pub")] pub client_ca_cert_path: Option, /// The public key file used by client @@ -970,17 +970,17 @@ impl TlsConfig { #[must_use] #[inline] pub fn new( - server_ca_cert_path: Option, - server_cert_path: Option, - server_key_path: Option, + peer_ca_cert_path: Option, + peer_cert_path: Option, + peer_key_path: Option, client_ca_cert_path: Option, client_cert_path: Option, client_key_path: Option, ) -> Self { Self { - server_ca_cert_path, - server_cert_path, - server_key_path, + peer_ca_cert_path, + peer_cert_path, + peer_key_path, client_ca_cert_path, client_cert_path, client_key_path, @@ -991,7 +991,7 @@ impl TlsConfig { #[must_use] #[inline] pub fn server_tls_enabled(&self) -> bool { - self.server_cert_path.is_some() && self.server_key_path.is_some() + self.peer_cert_path.is_some() && self.peer_key_path.is_some() } } @@ -1237,8 +1237,8 @@ mod tests { auth_private_key = './private_key.pem' [tls] - server_cert_path = './cert.pem' - server_key_path = './key.pem' + peer_cert_path = './cert.pem' + peer_key_path = './key.pem' client_ca_cert_path = './ca.pem' [metrics] @@ -1344,8 +1344,8 @@ mod tests { assert_eq!( config.tls, TlsConfig { - server_cert_path: Some(PathBuf::from("./cert.pem")), - server_key_path: Some(PathBuf::from("./key.pem")), + peer_cert_path: Some(PathBuf::from("./cert.pem")), + peer_key_path: Some(PathBuf::from("./key.pem")), client_ca_cert_path: Some(PathBuf::from("./ca.pem")), ..Default::default() } diff --git a/crates/xline/src/server/xline_server.rs b/crates/xline/src/server/xline_server.rs index 25f7a54da..b92a25ec9 100644 --- a/crates/xline/src/server/xline_server.rs +++ b/crates/xline/src/server/xline_server.rs @@ -662,9 +662,9 @@ impl XlineServer { _ => None, }; let server_tls_config = match ( - tls_config.server_ca_cert_path().as_ref(), - tls_config.server_cert_path().as_ref(), - tls_config.server_key_path().as_ref(), + tls_config.peer_ca_cert_path().as_ref(), + tls_config.peer_cert_path().as_ref(), + tls_config.peer_key_path().as_ref(), ) { (Some(ca_path), Some(cert_path), Some(key_path)) => { let ca = fs::read(ca_path).await?; @@ -682,9 +682,7 @@ impl XlineServer { Some(ServerTlsConfig::new().identity(Identity::from_pem(cert, key))) } (_, Some(_), None) | (_, None, Some(_)) => { - return Err(anyhow!( - "client_cert_path and client_key_path must be both set" - )) + return Err(anyhow!("peer_cert_path and peer_key_path must be both set")) } _ => None, }; diff --git a/crates/xline/src/utils/args.rs b/crates/xline/src/utils/args.rs index 98997023f..85377682b 100644 --- a/crates/xline/src/utils/args.rs +++ b/crates/xline/src/utils/args.rs @@ -193,13 +193,13 @@ pub struct ServerArgs { quota: Option, /// Server ca certificate path, used to verify client certificate #[clap(long)] - server_ca_cert_path: Option, + peer_ca_cert_path: Option, /// Server certificate path #[clap(long)] - server_cert_path: Option, + peer_cert_path: Option, /// Server private key path #[clap(long)] - server_key_path: Option, + peer_key_path: Option, /// Client ca certificate path, used to verify server certificate #[clap(long)] client_ca_cert_path: Option, @@ -315,9 +315,9 @@ impl From for XlineServerConfig { auto_compactor_cfg, ); let tls = TlsConfig::new( - args.server_ca_cert_path, - args.server_cert_path, - args.server_key_path, + args.peer_ca_cert_path, + args.peer_cert_path, + args.peer_key_path, args.client_ca_cert_path, args.client_cert_path, args.client_key_path, diff --git a/scripts/certgen.sh b/scripts/certgen.sh index 2c57986a3..51cb57c73 100755 --- a/scripts/certgen.sh +++ b/scripts/certgen.sh @@ -1,21 +1,27 @@ #!/usr/bin/bash -x DIR=$(cd $(dirname $0); pwd) +# root ca key and cert CA_KEY=${DIR}/certs/ca.key CA_CRT=${DIR}/certs/ca.crt -SERVER_KEY=${DIR}/certs/server.key -SERVER_CSR=${DIR}/certs/server.csr -SERVER_CRT=${DIR}/certs/server.crt +# the peer key and cert +PEER_KEY=${DIR}/certs/peer.key +PEER_CSR=${DIR}/certs/peer.csr +PEER_CRT=${DIR}/certs/peer.crt + +# the client key and cert of user "root" ROOT_CLIENT_KEY=${DIR}/certs/root_client.key ROOT_CLIENT_CSR=${DIR}/certs/root_client.csr ROOT_CLIENT_CRT=${DIR}/certs/root_client.crt +# the client key and cert of user "u1" U1_CLIENT_KEY=${DIR}/certs/u1_client.key U1_CLIENT_CSR=${DIR}/certs/u1_client.csr U1_CLIENT_CRT=${DIR}/certs/u1_client.crt +# the client key and cert of user "u2" U2_CLIENT_KEY=${DIR}/certs/u2_client.key U2_CLIENT_CSR=${DIR}/certs/u2_client.csr U2_CLIENT_CRT=${DIR}/certs/u2_client.crt @@ -45,9 +51,9 @@ EOF [ -f ${CA_CRT} ] || openssl req -x509 -new -nodes -key ${CA_KEY} -subj "/CN=ca" -days ${DAYS} -out ${CA_CRT} || exit 1 -[ -f ${SERVER_KEY} ] || openssl genrsa -out ${SERVER_KEY} 2048 || exit 1 -[ -f ${SERVER_CSR} ] || openssl req -new -key ${SERVER_KEY} -subj "/CN=server" -out ${SERVER_CSR} -config ${OPENSSL_CONF} || exit 1 -[ -f ${SERVER_CRT} ] || openssl x509 -req -in ${SERVER_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${SERVER_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 +[ -f ${PEER_KEY} ] || openssl genrsa -out ${PEER_KEY} 2048 || exit 1 +[ -f ${PEER_CSR} ] || openssl req -new -key ${PEER_KEY} -subj "/CN=peer" -out ${PEER_CSR} -config ${OPENSSL_CONF} || exit 1 +[ -f ${PEER_CRT} ] || openssl x509 -req -in ${PEER_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -CAcreateserial -out ${PEER_CRT} -days ${DAYS} -extensions v3_req -extfile ${OPENSSL_CONF} || exit 1 [ -f ${ROOT_CLIENT_KEY} ] || openssl genrsa -out ${ROOT_CLIENT_KEY} 2048 || exit 1 [ -f ${ROOT_CLIENT_CSR} ] || openssl req -new -key ${ROOT_CLIENT_KEY} -subj "/CN=root" -out ${ROOT_CLIENT_CSR} -config ${OPENSSL_CONF} || exit 1