From 993f9d2aea946972e1e1cd8072acb1d2872a06cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Uzarski?= Date: Wed, 12 Feb 2025 16:44:52 +0100 Subject: [PATCH 1/3] ccm/cluster: add support to enable authentication --- scylla/tests/ccm_integration/ccm/cluster.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scylla/tests/ccm_integration/ccm/cluster.rs b/scylla/tests/ccm_integration/ccm/cluster.rs index 4d14e8d0e..84d621b49 100644 --- a/scylla/tests/ccm_integration/ccm/cluster.rs +++ b/scylla/tests/ccm_integration/ccm/cluster.rs @@ -705,6 +705,15 @@ impl Cluster { self.updateconf(args).await } + /// Enables the `PasswordAuthenticator` for the cluster. + // Consider making it accept an enum in the future. Supported authenticators: + // https://github.com/scylladb/scylladb/blob/529ff3efa57553eef6b0239b03b81581b70fb9ed/db/config.cc#L1045-L1051. + pub(crate) async fn enable_password_authentication(&self) -> Result<(), Error> { + let args = [("authenticator", "PasswordAuthenticator")]; + + self.updateconf(args).await + } + fn get_ccm_env(&self) -> HashMap { let mut env: HashMap = HashMap::new(); env.insert( From d3aa77f6a35080922c1ccd507813154566e0ad6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Uzarski?= Date: Wed, 12 Feb 2025 17:08:01 +0100 Subject: [PATCH 2/3] IT: move authenticate tests to ccm_integration In the next commit I will remove the custom auth CI workflow. --- scylla/tests/ccm_integration/authenticate.rs | 134 +++++++++++++++++++ scylla/tests/ccm_integration/main.rs | 1 + scylla/tests/integration/authenticate.rs | 84 ------------ scylla/tests/integration/main.rs | 1 - 4 files changed, 135 insertions(+), 85 deletions(-) create mode 100644 scylla/tests/ccm_integration/authenticate.rs delete mode 100644 scylla/tests/integration/authenticate.rs diff --git a/scylla/tests/ccm_integration/authenticate.rs b/scylla/tests/ccm_integration/authenticate.rs new file mode 100644 index 000000000..81d02b297 --- /dev/null +++ b/scylla/tests/ccm_integration/authenticate.rs @@ -0,0 +1,134 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use bytes::{BufMut, BytesMut}; +use scylla::authentication::{AuthenticatorProvider, AuthenticatorSession}; +use scylla::errors::AuthError; +use tokio::sync::Mutex; + +use crate::ccm::cluster::{Cluster, ClusterOptions}; +use crate::ccm::{run_ccm_test_with_configuration, CLUSTER_VERSION}; +use crate::common::utils::{setup_tracing, unique_keyspace_name, PerformDDL}; + +fn cluster_1_node() -> ClusterOptions { + ClusterOptions { + name: "cluster_auth_1_node".to_string(), + version: CLUSTER_VERSION.clone(), + nodes: vec![1], + ..ClusterOptions::default() + } +} + +async fn run_ccm_auth_test_cluster_one_node(test: T) +where + T: FnOnce(Arc>) -> TFut, + TFut: std::future::Future, +{ + run_ccm_test_with_configuration( + cluster_1_node, + |cluster| async move { + cluster + .enable_password_authentication() + .await + .expect("Failed to enable password authenticator"); + cluster + }, + test, + ) + .await +} + +#[tokio::test] +#[cfg_attr(not(ccm_tests), ignore)] +async fn authenticate_superuser_cluster_one_node() { + setup_tracing(); + async fn test(cluster: Arc>) { + let cluster = cluster.lock().await; + + tracing::info!( + "Connecting to {:?} with cassandra superuser...", + cluster.nodes().get_contact_endpoints().await + ); + + let session = cluster + .make_session_builder() + .await + .user("cassandra", "cassandra") + .build() + .await + .unwrap(); + let ks = unique_keyspace_name(); + + session.ddl(format!("CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = {{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", ks)).await.unwrap(); + session.use_keyspace(ks, false).await.unwrap(); + session.ddl("DROP TABLE IF EXISTS t;").await.unwrap(); + + tracing::info!("Ok."); + } + + run_ccm_auth_test_cluster_one_node(test).await +} + +struct CustomAuthenticator; + +#[async_trait] +impl AuthenticatorSession for CustomAuthenticator { + async fn evaluate_challenge( + &mut self, + _token: Option<&[u8]>, + ) -> Result>, AuthError> { + Err("Challenges are not expected".to_string()) + } + + async fn success(&mut self, _token: Option<&[u8]>) -> Result<(), AuthError> { + Ok(()) + } +} + +struct CustomAuthenticatorProvider; + +#[async_trait] +impl AuthenticatorProvider for CustomAuthenticatorProvider { + async fn start_authentication_session( + &self, + _authenticator_name: &str, + ) -> Result<(Option>, Box), AuthError> { + let mut response = BytesMut::new(); + let cred = "\0cassandra\0cassandra"; + + response.put_slice(cred.as_bytes()); + + Ok((Some(response.to_vec()), Box::new(CustomAuthenticator))) + } +} + +#[tokio::test] +#[cfg_attr(not(ccm_tests), ignore)] +async fn custom_authentication_cluster_one_node() { + setup_tracing(); + async fn test(cluster: Arc>) { + let cluster = cluster.lock().await; + + tracing::info!( + "Connecting to {:?} with custom authenticator as cassandra superuser...", + cluster.nodes().get_contact_endpoints().await + ); + + let session = cluster + .make_session_builder() + .await + .authenticator_provider(Arc::new(CustomAuthenticatorProvider)) + .build() + .await + .unwrap(); + let ks = unique_keyspace_name(); + + session.ddl(format!("CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = {{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", ks)).await.unwrap(); + session.use_keyspace(ks, false).await.unwrap(); + session.ddl("DROP TABLE IF EXISTS t;").await.unwrap(); + + tracing::info!("Ok."); + } + + run_ccm_auth_test_cluster_one_node(test).await +} diff --git a/scylla/tests/ccm_integration/main.rs b/scylla/tests/ccm_integration/main.rs index d74298f76..3f9373b47 100644 --- a/scylla/tests/ccm_integration/main.rs +++ b/scylla/tests/ccm_integration/main.rs @@ -1,6 +1,7 @@ #[path = "../common/mod.rs"] mod common; +mod authenticate; pub(crate) mod ccm; mod test_example; #[cfg(feature = "ssl")] diff --git a/scylla/tests/integration/authenticate.rs b/scylla/tests/integration/authenticate.rs deleted file mode 100644 index 792d1f1ad..000000000 --- a/scylla/tests/integration/authenticate.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::utils::{setup_tracing, unique_keyspace_name, PerformDDL}; -use async_trait::async_trait; -use bytes::{BufMut, BytesMut}; -use scylla::authentication::{AuthError, AuthenticatorProvider, AuthenticatorSession}; -use std::sync::Arc; - -#[tokio::test] -#[ignore] -async fn authenticate_superuser() { - setup_tracing(); - let uri = std::env::var("SCYLLA_URI").unwrap_or_else(|_| "127.0.0.1:9042".to_string()); - - println!("Connecting to {} with cassandra superuser ...", uri); - - let session = scylla::client::session_builder::SessionBuilder::new() - .known_node(uri) - .user("cassandra", "cassandra") - .build() - .await - .unwrap(); - let ks = unique_keyspace_name(); - - session.ddl(format!("CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = {{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", ks)).await.unwrap(); - session.use_keyspace(ks, false).await.unwrap(); - session.ddl("DROP TABLE IF EXISTS t;").await.unwrap(); - - println!("Ok."); -} - -struct CustomAuthenticator; - -#[async_trait] -impl AuthenticatorSession for CustomAuthenticator { - async fn evaluate_challenge( - &mut self, - _token: Option<&[u8]>, - ) -> Result>, AuthError> { - Err("Challenges are not expected".to_string()) - } - - async fn success(&mut self, _token: Option<&[u8]>) -> Result<(), AuthError> { - Ok(()) - } -} - -struct CustomAuthenticatorProvider; - -#[async_trait] -impl AuthenticatorProvider for CustomAuthenticatorProvider { - async fn start_authentication_session( - &self, - _authenticator_name: &str, - ) -> Result<(Option>, Box), AuthError> { - let mut response = BytesMut::new(); - let cred = "\0cassandra\0cassandra"; - - response.put_slice(cred.as_bytes()); - - Ok((Some(response.to_vec()), Box::new(CustomAuthenticator))) - } -} - -#[tokio::test] -#[ignore] -async fn custom_authentication() { - setup_tracing(); - let uri = std::env::var("SCYLLA_URI").unwrap_or_else(|_| "127.0.0.1:9042".to_string()); - - println!("Connecting to {} with cassandra superuser ...", uri); - - let session = scylla::client::session_builder::SessionBuilder::new() - .known_node(uri) - .authenticator_provider(Arc::new(CustomAuthenticatorProvider)) - .build() - .await - .unwrap(); - let ks = unique_keyspace_name(); - - session.ddl(format!("CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = {{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}", ks)).await.unwrap(); - session.use_keyspace(ks, false).await.unwrap(); - session.ddl("DROP TABLE IF EXISTS t;").await.unwrap(); - - println!("Ok."); -} diff --git a/scylla/tests/integration/main.rs b/scylla/tests/integration/main.rs index d69c0aa0c..a87649ef4 100644 --- a/scylla/tests/integration/main.rs +++ b/scylla/tests/integration/main.rs @@ -1,4 +1,3 @@ -mod authenticate; mod batch; mod consistency; mod cql_collections; From f37c98e87542d6105d6a1203cee571c342691b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Uzarski?= Date: Wed, 12 Feb 2025 17:11:30 +0100 Subject: [PATCH 3/3] ci: remove auth workflow and related dockerfile Auth tests are now run as a part of CCM test suite. --- .github/workflows/authenticate_test.yml | 40 ------------------------ test/cluster/docker-compose-passauth.yml | 28 ----------------- 2 files changed, 68 deletions(-) delete mode 100644 .github/workflows/authenticate_test.yml delete mode 100644 test/cluster/docker-compose-passauth.yml diff --git a/.github/workflows/authenticate_test.yml b/.github/workflows/authenticate_test.yml deleted file mode 100644 index 22eb7079f..000000000 --- a/.github/workflows/authenticate_test.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Authenticate - -on: - push: - branches: - - main - - 'branch-*' - pull_request: - branches: - - '**' - -env: - CARGO_TERM_COLOR: always - RUST_BACKTRACE: full - -jobs: - build: - timeout-minutes: 60 - name: Run Authentication tests - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Update rust toolchain - run: rustup update - - - name: Start the cluster - run: docker compose -f test/cluster/docker-compose-passauth.yml up -d - - - name: Run tests - run: SCYLLA_URI=172.43.0.2 RUST_LOG=trace cargo test --verbose authenticate_superuser -- custom_authentication --ignored - - - name: Stop the cluster - if: ${{ always() }} - run: docker compose -f test/cluster/docker-compose-passauth.yml stop - - - name: Print the cluster logs - if: ${{ always() }} - run: docker compose -f test/cluster/docker-compose-passauth.yml logs diff --git a/test/cluster/docker-compose-passauth.yml b/test/cluster/docker-compose-passauth.yml deleted file mode 100644 index 109e1e1b0..000000000 --- a/test/cluster/docker-compose-passauth.yml +++ /dev/null @@ -1,28 +0,0 @@ -networks: - public: - name: scylla_rust_driver_passauth_public - driver: bridge - ipam: - driver: default - config: - - subnet: 172.43.0.0/24 - -services: - scylla: - networks: - public: - ipv4_address: 172.43.0.2 - image: scylladb/scylla - command: | - --skip-wait-for-gossip-to-settle 0 - --ring-delay-ms 0 - --smp 1 - --memory 512M - --authenticator PasswordAuthenticator - ports: - - "9042:9042" - healthcheck: - test: [ "CMD", "cqlsh", "scylla", "-e", "select * from system.local" ] - interval: 5s - timeout: 5s - retries: 60