From f1bcd64d0f7585ae11eb46fe1a3f78375fd7fe97 Mon Sep 17 00:00:00 2001 From: uslon Date: Fri, 1 Mar 2024 18:19:12 +0300 Subject: [PATCH 1/4] use secret string --- ydb/Cargo.toml | 1 + ydb/src/auth_test.rs | 15 +++++++++------ ydb/src/client_common.rs | 3 ++- ydb/src/credentials.rs | 13 +++++++------ ydb/src/grpc_wrapper/auth.rs | 8 +++++--- ydb/src/pub_traits.rs | 6 +++--- 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/ydb/Cargo.toml b/ydb/Cargo.toml index 1f06de5d..7e3a5584 100644 --- a/ydb/Cargo.toml +++ b/ydb/Cargo.toml @@ -27,6 +27,7 @@ prost-types = "0.11.2" pbjson-types = "0.5.1" rand = "0.8" reqwest = {version="0.11", features = ["blocking", "json","rustls"], default-features = false} +secrecy = "0.8.0" serde={version="1.0", features=["derive"]} serde_json="1.0" strum = { version = "0.21", features = ["derive"] } diff --git a/ydb/src/auth_test.rs b/ydb/src/auth_test.rs index c242b67d..4f1acabf 100644 --- a/ydb/src/auth_test.rs +++ b/ydb/src/auth_test.rs @@ -1,3 +1,4 @@ +use secrecy::ExposeSecret; use tracing::trace; use tracing_test::traced_test; @@ -15,10 +16,11 @@ fn auth_success_test() -> YdbResult<()> { let database = uri.path().to_string(); let up_auth = StaticCredentialsAuth::new("root".to_string(), "1234".to_string(), uri, database); - let token_str = up_auth.create_token()?.token; + let token_sec = up_auth.create_token()?.token; + let raw_token = token_sec.expose_secret(); - trace!("got token: `{}'", token_str); - if token_str.is_empty() { + trace!("got token: `{}'", raw_token); + if raw_token.is_empty() { panic!("got the empty token on the presumably successful auth request"); } @@ -34,14 +36,15 @@ async fn auth_async_success_test() -> YdbResult<()> { let database = uri.path().to_string(); let up_auth = StaticCredentialsAuth::new("root".to_string(), "1234".to_string(), uri, database); - let token_str = std::thread::spawn(move || up_auth.create_token()) + let token_sec = std::thread::spawn(move || up_auth.create_token()) .join() .unwrap() .unwrap() .token; + let raw_token = token_sec.expose_secret(); - trace!("got token: `{}'", token_str); - if token_str.is_empty() { + trace!("got token: `{}'", raw_token); + if raw_token.is_empty() { panic!("got the empty token on the presumably successful auth request"); } diff --git a/ydb/src/client_common.rs b/ydb/src/client_common.rs index a5da845a..dad4c740 100644 --- a/ydb/src/client_common.rs +++ b/ydb/src/client_common.rs @@ -2,6 +2,7 @@ use crate::credentials::CredentialsRef; use crate::errors::YdbResult; use crate::pub_traits::TokenInfo; use crate::waiter::Waiter; +use secrecy::SecretString; use std::sync::{Arc, Mutex, RwLock}; use std::time::Instant; use tokio::sync::watch; @@ -40,7 +41,7 @@ impl TokenCache { Ok(token_cache) } - pub(crate) fn token(&self) -> String { + pub(crate) fn token(&self) -> SecretString { let now = Instant::now(); let read = self.0.read().unwrap(); diff --git a/ydb/src/credentials.rs b/ydb/src/credentials.rs index 43343b96..c4d6bc7d 100644 --- a/ydb/src/credentials.rs +++ b/ydb/src/credentials.rs @@ -7,6 +7,7 @@ use crate::grpc_wrapper::runtime_interceptors::MultiInterceptor; use crate::load_balancer::{SharedLoadBalancer, StaticLoadBalancer}; use crate::pub_traits::{Credentials, TokenInfo}; use http::Uri; +use secrecy::{ExposeSecret, SecretString}; use serde::Deserialize; use std::fmt::Debug; use std::ops::Add; @@ -125,7 +126,7 @@ impl Credentials for CommandLineYcToken { fn debug_string(&self) -> String { let token_describe: String = match self.create_token() { Ok(token_info) => { - let token = token_info.token; + let token = token_info.token.expose_secret(); let desc: String = if token.len() > 20 { format!( "{}..{}", @@ -238,7 +239,7 @@ impl Credentials for GCEMetadata { pub struct StaticCredentialsAuth { username: String, - password: String, + password: SecretString, database: String, endpoint: Uri, } @@ -261,17 +262,17 @@ impl StaticCredentialsAuth { let raw_request = RawLoginRequest { operation_params: TimeoutSettings::default().operation_params(), user: self.username.clone(), - password: self.password.clone(), + password: self.password.expose_secret().clone(), }; - let raw_result = auth_client.login(raw_request).await?; - Ok(raw_result.token) + let raw_response = auth_client.login(raw_request).await?; + Ok(raw_response.token) } pub fn new(username: String, password: String, endpoint: Uri, database: String) -> Self { Self { username, - password, + password: SecretString::new(password), database, endpoint, } diff --git a/ydb/src/grpc_wrapper/auth.rs b/ydb/src/grpc_wrapper/auth.rs index 389e3896..0ad33bea 100644 --- a/ydb/src/grpc_wrapper/auth.rs +++ b/ydb/src/grpc_wrapper/auth.rs @@ -4,6 +4,7 @@ use crate::grpc_wrapper::runtime_interceptors::{ GrpcInterceptor, InterceptorError, InterceptorRequest, InterceptorResult, RequestMetadata, }; use http::HeaderValue; +use secrecy::ExposeSecret; pub(crate) struct AuthGrpcInterceptor { db_name: HeaderValue, @@ -34,9 +35,10 @@ impl GrpcInterceptor for AuthGrpcInterceptor { _metadata: &mut RequestMetadata, mut req: InterceptorRequest, ) -> InterceptorResult { - let token = self.token_cache.token(); - let token = HeaderValue::from_str(token.as_str()).map_err(|err| { - InterceptorError::custom(format!("received bad token (len={}): {}", token.len(), err)) + let token_secret = self.token_cache.token(); + let token_string = token_secret.expose_secret(); + let token = HeaderValue::from_str(token_string.as_str()).map_err(|err| { + InterceptorError::custom(format!("received bad token (len={}): {}", token_string.len(), err)) })?; req.headers_mut() diff --git a/ydb/src/pub_traits.rs b/ydb/src/pub_traits.rs index 51296408..1fb8230a 100644 --- a/ydb/src/pub_traits.rs +++ b/ydb/src/pub_traits.rs @@ -1,5 +1,5 @@ - use crate::errors::YdbResult; +use secrecy::SecretString; use std::fmt::{Debug, Formatter}; use std::ops::Add; use std::time::{Duration, Instant}; @@ -8,14 +8,14 @@ pub(crate) const DEFAULT_TOKEN_RENEW_INTERVAL: Duration = Duration::from_secs(36 #[derive(Debug, Clone)] pub struct TokenInfo { - pub(crate) token: String, + pub(crate) token: SecretString, pub(crate) next_renew: Instant, } impl TokenInfo { pub(crate) fn token(token: String) -> Self { Self { - token, + token: SecretString::new(token), next_renew: Instant::now().add(DEFAULT_TOKEN_RENEW_INTERVAL), } } From b8ec35871c79121533cf06eb3de405e07fc9852a Mon Sep 17 00:00:00 2001 From: uslon Date: Mon, 4 Mar 2024 13:43:25 +0300 Subject: [PATCH 2/4] use earlist possible secrecy crate version --- ydb/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ydb/Cargo.toml b/ydb/Cargo.toml index 7e3a5584..5ece5cbb 100644 --- a/ydb/Cargo.toml +++ b/ydb/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "Apache-2.0" description = "Crate contains generated low-level grpc code from YDB API protobuf, used as base for ydb crate" repository = "https://github.com/ydb-platform/ydb-rs-sdk/tree/master/ydb" -rust-version = "1.56" +rust-version = "1.60" [features] force-exhaustive-all=[] # The feature disable all non_exhaustive attributes in ydb public interface. @@ -27,7 +27,7 @@ prost-types = "0.11.2" pbjson-types = "0.5.1" rand = "0.8" reqwest = {version="0.11", features = ["blocking", "json","rustls"], default-features = false} -secrecy = "0.8.0" +secrecy = "0.4.1" serde={version="1.0", features=["derive"]} serde_json="1.0" strum = { version = "0.21", features = ["derive"] } From 0b696fc48be4c396fd77eb5c5e966e340480542b Mon Sep 17 00:00:00 2001 From: uslon Date: Wed, 6 Mar 2024 10:24:32 +0300 Subject: [PATCH 3/4] update rust version --- .github/workflows/rust-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index 73798a92..c011ccb7 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false matrix: - rust_version: [ "1.56.0", "1.74.0" ] + rust_version: [ "1.60.0", "1.74.0" ] services: ydb: From 2a36a582d428884b51b42af64bea4de5dfa8b6ae Mon Sep 17 00:00:00 2001 From: uslon Date: Wed, 6 Mar 2024 10:26:03 +0300 Subject: [PATCH 4/4] update rust version --- .github/workflows/rust-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index c011ccb7..f55dc5a5 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -63,6 +63,6 @@ jobs: run: cargo test --verbose --workspace -- --include-ignored - name: Linter - if: matrix.rust_version != '1.56.0' + if: matrix.rust_version != '1.60.0' run: | cargo clippy --workspace --all-targets -- -D warnings