Skip to content

Commit

Permalink
test: add certificate authenticate tests
Browse files Browse the repository at this point in the history
Signed-off-by: themanforfree <[email protected]>
  • Loading branch information
themanforfree committed Feb 27, 2024
1 parent db48e7a commit c01af08
Show file tree
Hide file tree
Showing 19 changed files with 347 additions and 194 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions crates/utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -219,6 +220,14 @@ pub fn build_endpoint(
addr: &str,
tls_config: Option<&ClientTlsConfig>,
) -> Result<Endpoint, tonic::transport::Error> {
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)?,
Expand Down
1 change: 1 addition & 0 deletions crates/xline-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
28 changes: 0 additions & 28 deletions crates/xline-test-utils/private.pem

This file was deleted.

9 changes: 0 additions & 9 deletions crates/xline-test-utils/public.pem

This file was deleted.

80 changes: 51 additions & 29 deletions crates/xline-test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,8 +32,6 @@ pub struct Cluster {
configs: Vec<XlineServerConfig>,
/// Xline servers
servers: Vec<Arc<XlineServer>>,
/// Client tls config
client_tls_config: Option<ClientTlsConfig>,
/// Client of cluster
client: Option<Client>,
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<usize, String> {
Expand Down Expand Up @@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
set_user(client, "root", "123", "root", &[], &[]).await?;
client.auth_client().auth_enable().await?;
Ok(())
}
52 changes: 41 additions & 11 deletions crates/xline/src/server/xline_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,28 +635,58 @@ impl XlineServer {
async fn read_tls_config(
tls_config: &TlsConfig,
) -> Result<(Option<ClientTlsConfig>, Option<ServerTlsConfig>)> {
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))
}
Expand Down
6 changes: 4 additions & 2 deletions crates/xline/src/storage/auth_store/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -138,6 +137,9 @@ where
&self,
request: &tonic::Request<T>,
) -> Result<Option<AuthInfo>, 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));
Expand Down
40 changes: 2 additions & 38 deletions crates/xline/tests/it/auth_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -228,39 +225,6 @@ async fn test_auth_wrong_password() -> Result<(), Box<dyn Error>> {
Ok(())
}

async fn set_user(
client: &Client,
name: &str,
password: &str,
role: &str,
key: &[u8],
range_end: &[u8],
) -> Result<(), Box<dyn Error>> {
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<dyn Error>> {
set_user(client, "root", "123", "root", &[], &[]).await?;
client.auth_client().auth_enable().await?;
Ok(())
}

fn configs_with_auth(size: usize) -> Vec<XlineServerConfig> {
iter::repeat_with(|| {
(
Expand Down
Loading

0 comments on commit c01af08

Please sign in to comment.