From 5cf2a17a018c1ee21785ecaf7e66b39f10a6c690 Mon Sep 17 00:00:00 2001 From: yoshidan Date: Wed, 8 May 2024 14:06:43 +0900 Subject: [PATCH 1/4] support poolable connection --- kms/README.md | 2 +- kms/src/client.rs | 58 +++---- kms/src/grpc/apiv1/conn_pool.rs | 33 ++++ kms/src/grpc/apiv1/kms_client.rs | 280 +++++++++++-------------------- kms/src/grpc/apiv1/mod.rs | 5 +- kms/src/lib.rs | 2 +- 6 files changed, 159 insertions(+), 221 deletions(-) create mode 100644 kms/src/grpc/apiv1/conn_pool.rs diff --git a/kms/README.md b/kms/README.md index 6c9b4004..7b1ce037 100644 --- a/kms/README.md +++ b/kms/README.md @@ -63,7 +63,7 @@ google-cloud-kms = "version" async fn run(config: ClientConfig) { // Create client - let mut client = Client::new(config).await.unwrap(); + let client = Client::new(config).await.unwrap(); // Key ring // create diff --git a/kms/src/client.rs b/kms/src/client.rs index 656315af..d34d979e 100644 --- a/kms/src/client.rs +++ b/kms/src/client.rs @@ -1,21 +1,21 @@ use std::ops::{Deref, DerefMut}; -use std::time::Duration; +use std::sync::Arc; #[cfg(feature = "auth")] pub use google_cloud_auth; -use google_cloud_gax::conn::{ConnectionManager, ConnectionOptions, Environment, Error}; +use google_cloud_gax::conn::{ConnectionOptions, Environment, Error}; use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; use google_cloud_token::{NopeTokenSourceProvider, TokenSourceProvider}; +use crate::grpc::apiv1::conn_pool::{ConnectionManager, KMS, SCOPES}; use crate::grpc::apiv1::kms_client::Client as KmsGrpcClient; -use crate::grpc::apiv1::{AUDIENCE, KMS, SCOPES}; #[derive(Debug)] pub struct ClientConfig { - pub kms_endpoint: String, + pub endpoint: String, pub token_source_provider: Box, - pub timeout: Option, - pub connect_timeout: Option, + pub pool_size: Option, + pub connection_option: ConnectionOptions, } #[cfg(feature = "auth")] @@ -54,10 +54,10 @@ impl ClientConfig { impl Default for ClientConfig { fn default() -> Self { Self { - kms_endpoint: KMS.to_string(), + endpoint: KMS.to_string(), token_source_provider: Box::new(NopeTokenSourceProvider {}), - timeout: Some(Duration::from_secs(30)), - connect_timeout: Some(Duration::from_secs(30)), + pool_size: Some(1), + connection_option: ConnectionOptions::default(), } } } @@ -69,22 +69,16 @@ pub struct Client { impl Client { pub async fn new(config: ClientConfig) -> Result { - let conn_options = ConnectionOptions { - timeout: config.timeout, - connect_timeout: config.connect_timeout, - }; - let conn_pool = ConnectionManager::new( - 1, - config.kms_endpoint, - AUDIENCE, + let pool_size = config.pool_size.unwrap_or_default(); + let cm = ConnectionManager::new( + pool_size, + config.endpoint.as_str(), &Environment::GoogleCloud(config.token_source_provider), - &conn_options, + &config.connection_option, ) .await?; - let conn = conn_pool.conn(); - Ok(Self { - kms_client: KmsGrpcClient::new(KeyManagementServiceClient::new(conn)), + kms_client: KmsGrpcClient::new(Arc::new(cm)), }) } } @@ -97,12 +91,6 @@ impl Deref for Client { } } -impl DerefMut for Client { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.kms_client - } -} - #[cfg(test)] mod tests { @@ -155,13 +143,25 @@ mod tests { // list let list_request = ListKeyRingsRequest { parent: create_request.parent.to_string(), - page_size: 0, + page_size: 1, page_token: "".to_string(), filter: "".to_string(), order_by: "".to_string(), }; let list_result = client.list_key_rings(list_request, None).await.unwrap(); - assert!(!list_result.key_rings.is_empty()); + assert_eq!(1, list_result.key_rings.len()); + + let list_request = ListKeyRingsRequest { + parent: create_request.parent.to_string(), + page_size: 1, + page_token: list_result.next_page_token.to_string(), + filter: "".to_string(), + order_by: "".to_string(), + }; + let list_result2 = client.list_key_rings(list_request, None).await.unwrap(); + assert_eq!(1, list_result2.key_rings.len()); + + assert_ne!(list_result.key_rings[0].name, list_result2.key_rings[0].name); } #[tokio::test] diff --git a/kms/src/grpc/apiv1/conn_pool.rs b/kms/src/grpc/apiv1/conn_pool.rs new file mode 100644 index 00000000..2033c204 --- /dev/null +++ b/kms/src/grpc/apiv1/conn_pool.rs @@ -0,0 +1,33 @@ +use google_cloud_gax::conn::{Channel, Environment}; +use google_cloud_gax::conn::{ConnectionManager as GRPCConnectionManager, ConnectionOptions, Error}; +use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; + +pub const AUDIENCE: &str = "https://cloudkms.googleapis.com/"; +pub const KMS: &str = "cloudkms.googleapis.com"; +pub const SCOPES: [&str; 1] = ["https://www.googleapis.com/auth/cloud-platform"]; + +#[derive(Debug)] +pub struct ConnectionManager { + inner: GRPCConnectionManager, +} + +impl ConnectionManager { + pub async fn new( + pool_size: usize, + domain: &str, + environment: &Environment, + conn_options: &ConnectionOptions, + ) -> Result { + Ok(ConnectionManager { + inner: GRPCConnectionManager::new(pool_size, domain, AUDIENCE, environment, conn_options).await?, + }) + } + + pub fn num(&self) -> usize { + self.inner.num() + } + + pub fn conn(&self) -> KeyManagementServiceClient { + KeyManagementServiceClient::new(self.inner.conn()).max_decoding_message_size(i32::MAX as usize) + } +} diff --git a/kms/src/grpc/apiv1/kms_client.rs b/kms/src/grpc/apiv1/kms_client.rs index 6ba2dce1..c2289689 100644 --- a/kms/src/grpc/apiv1/kms_client.rs +++ b/kms/src/grpc/apiv1/kms_client.rs @@ -1,9 +1,11 @@ +use std::sync::Arc; use std::time::Duration; +use crate::grpc::apiv1::conn_pool::ConnectionManager; use google_cloud_gax::conn::Channel; use google_cloud_gax::create_request; use google_cloud_gax::grpc::{Code, Status}; -use google_cloud_gax::retry::{invoke_fn, RetrySetting}; +use google_cloud_gax::retry::{invoke, invoke_fn, RetrySetting}; use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; use google_cloud_googleapis::cloud::kms::v1::CreateCryptoKeyRequest; use google_cloud_googleapis::cloud::kms::v1::CreateCryptoKeyVersionRequest; @@ -36,14 +38,12 @@ fn default_setting() -> RetrySetting { #[derive(Clone)] pub struct Client { - inner: KeyManagementServiceClient, + cm: Arc, } impl Client { - pub fn new(inner: KeyManagementServiceClient) -> Self { - Self { - inner: inner.max_decoding_message_size(i32::MAX as usize), - } + pub fn new(cm: Arc) -> Self { + Self { cm } } /// Generate random bytes @@ -52,25 +52,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn generate_random_bytes( - &mut self, + &self, req: GenerateRandomBytesRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("location={}", req.location), req.clone()); - client - .generate_random_bytes(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("location={}", req.location), req.clone()); + self.cm.conn().generate_random_bytes(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Create crypto key @@ -79,25 +71,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn create_crypto_key( - &mut self, + &self, req: CreateCryptoKeyRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .create_crypto_key(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().create_crypto_key(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Create crypto key version @@ -106,25 +90,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn create_crypto_key_version( - &mut self, + &self, req: CreateCryptoKeyVersionRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .create_crypto_key_version(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().create_crypto_key_version(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Create key ring @@ -133,25 +109,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn create_key_ring( - &mut self, + &self, req: CreateKeyRingRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .create_key_ring(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().create_key_ring(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Destroy crypto key version @@ -160,25 +128,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn destroy_crypto_key_version( - &mut self, + &self, req: DestroyCryptoKeyVersionRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("name={}", req.name), req.clone()); - client - .destroy_crypto_key_version(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().destroy_crypto_key_version(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Get crypto key @@ -187,25 +147,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn get_crypto_key( - &mut self, + &self, req: GetCryptoKeyRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("name={}", req.name), req.clone()); - client - .get_crypto_key(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().get_crypto_key(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Get crypto key version @@ -214,25 +166,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn get_crypto_key_version( - &mut self, + &self, req: GetCryptoKeyVersionRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("name={}", req.name), req.clone()); - client - .get_crypto_key_version(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().get_crypto_key_version(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// Get key ring @@ -240,26 +184,14 @@ impl Client { /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.GetKeyRing /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] - pub async fn get_key_ring( - &mut self, - req: GetKeyRingRequest, - retry: Option, - ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("name={}", req.name), req.clone()); - client - .get_key_ring(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + pub async fn get_key_ring(&self, req: GetKeyRingRequest, retry: Option) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().get_key_ring(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// List crypto key versions @@ -268,25 +200,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn list_crypto_key_versions( - &mut self, + &self, req: ListCryptoKeyVersionsRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .list_crypto_key_versions(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().list_crypto_key_versions(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// List crypto keys @@ -295,25 +219,17 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn list_crypto_keys( - &mut self, + &self, req: ListCryptoKeysRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .list_crypto_keys(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().list_crypto_keys(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } /// List key rings @@ -322,24 +238,16 @@ impl Client { /// #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] pub async fn list_key_rings( - &mut self, + &self, req: ListKeyRingsRequest, retry: Option, ) -> Result { - let setting = retry.unwrap_or_else(default_setting); - - invoke_fn( - Some(setting), - |client| async { - let request = create_request(format!("parent={}", req.parent), req.clone()); - client - .list_key_rings(request) - .await - .map(|s| s.into_inner()) - .map_err(|e| (e, client)) - }, - &mut self.inner, - ) - .await + let action = || async { + let request = create_request(format!("parent={}", req.parent), req.clone()); + self.cm.conn().list_key_rings(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) } } diff --git a/kms/src/grpc/apiv1/mod.rs b/kms/src/grpc/apiv1/mod.rs index ba1fb82e..e9f91738 100644 --- a/kms/src/grpc/apiv1/mod.rs +++ b/kms/src/grpc/apiv1/mod.rs @@ -1,5 +1,2 @@ +pub mod conn_pool; pub mod kms_client; - -pub const AUDIENCE: &str = "https://cloudkms.googleapis.com/"; -pub const KMS: &str = "cloudkms.googleapis.com"; -pub const SCOPES: [&str; 1] = ["https://www.googleapis.com/auth/cloud-platform"]; diff --git a/kms/src/lib.rs b/kms/src/lib.rs index db76758c..557547cb 100644 --- a/kms/src/lib.rs +++ b/kms/src/lib.rs @@ -52,7 +52,7 @@ //! async fn run(config: ClientConfig) { //! //! // Create client -//! let mut client = Client::new(config).await.unwrap(); +//! let client = Client::new(config).await.unwrap(); //! //! // Key ring //! // create From b2b7cc0e164565f42f73fd82700edb14b7495ab5 Mon Sep 17 00:00:00 2001 From: yoshidan Date: Wed, 8 May 2024 14:17:18 +0900 Subject: [PATCH 2/4] add key operation --- kms/src/grpc/apiv1/kms_client.rs | 127 ++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/kms/src/grpc/apiv1/kms_client.rs b/kms/src/grpc/apiv1/kms_client.rs index c2289689..a1bcd78b 100644 --- a/kms/src/grpc/apiv1/kms_client.rs +++ b/kms/src/grpc/apiv1/kms_client.rs @@ -7,7 +7,6 @@ use google_cloud_gax::create_request; use google_cloud_gax::grpc::{Code, Status}; use google_cloud_gax::retry::{invoke, invoke_fn, RetrySetting}; use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; -use google_cloud_googleapis::cloud::kms::v1::CreateCryptoKeyRequest; use google_cloud_googleapis::cloud::kms::v1::CreateCryptoKeyVersionRequest; use google_cloud_googleapis::cloud::kms::v1::CreateKeyRingRequest; use google_cloud_googleapis::cloud::kms::v1::CryptoKey; @@ -25,6 +24,11 @@ use google_cloud_googleapis::cloud::kms::v1::ListCryptoKeysRequest; use google_cloud_googleapis::cloud::kms::v1::ListCryptoKeysResponse; use google_cloud_googleapis::cloud::kms::v1::ListKeyRingsRequest; use google_cloud_googleapis::cloud::kms::v1::ListKeyRingsResponse; +use google_cloud_googleapis::cloud::kms::v1::{ + AsymmetricDecryptRequest, AsymmetricDecryptResponse, AsymmetricSignRequest, AsymmetricSignResponse, + CreateCryptoKeyRequest, DecryptRequest, DecryptResponse, EncryptRequest, EncryptResponse, GetPublicKeyRequest, + MacSignRequest, MacSignResponse, MacVerifyRequest, MacVerifyResponse, PublicKey, +}; fn default_setting() -> RetrySetting { RetrySetting { @@ -250,4 +254,125 @@ impl Client { .await .map(|r| r.into_inner()) } + + /// Encrypt + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.Encrypt + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn encrypt(&self, req: EncryptRequest, retry: Option) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().encrypt(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// Decrypt + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.Decrypt + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn decrypt(&self, req: DecryptRequest, retry: Option) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().decrypt(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// AsymmetricSign + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.AsymmetricSign + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn asymmetric_sign( + &self, + req: AsymmetricSignRequest, + retry: Option, + ) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().asymmetric_sign(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// AsymmetricDecrypt + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.AsymmetricDecrypt + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn asymmetric_decrypt( + &self, + req: AsymmetricDecryptRequest, + retry: Option, + ) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().asymmetric_decrypt(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// MacSign + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.MacSign + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn mac_sign(&self, req: MacSignRequest, retry: Option) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().mac_sign(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// MacVerify + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.MacVerify + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn mac_verify( + &self, + req: MacVerifyRequest, + retry: Option, + ) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().mac_verify(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } + + /// PublicKey + /// + /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.PublicKey + /// + #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] + pub async fn get_public_key( + &self, + req: GetPublicKeyRequest, + retry: Option, + ) -> Result { + let action = || async { + let request = create_request(format!("name={}", req.name), req.clone()); + self.cm.conn().get_public_key(request).await + }; + invoke(Some(retry.unwrap_or_else(default_setting)), action) + .await + .map(|r| r.into_inner()) + } } From 38567f40df41d3b0b93599220d50d04c167a64af Mon Sep 17 00:00:00 2001 From: yoshidan Date: Wed, 8 May 2024 14:30:15 +0900 Subject: [PATCH 3/4] add test --- kms/src/client.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/kms/src/client.rs b/kms/src/client.rs index d34d979e..3b03ec94 100644 --- a/kms/src/client.rs +++ b/kms/src/client.rs @@ -97,7 +97,8 @@ mod tests { use serial_test::serial; use google_cloud_googleapis::cloud::kms::v1::{ - CreateKeyRingRequest, GenerateRandomBytesRequest, GetKeyRingRequest, ListKeyRingsRequest, ProtectionLevel, + AsymmetricSignRequest, CreateKeyRingRequest, DecryptRequest, EncryptRequest, GenerateRandomBytesRequest, + GetKeyRingRequest, ListKeyRingsRequest, ProtectionLevel, }; use crate::client::{Client, ClientConfig}; @@ -194,4 +195,47 @@ mod tests { random_bytes.data ) } + + #[tokio::test] + #[serial] + async fn test_asymmetric_sign() { + let (client, project) = new_client().await; + + let request = AsymmetricSignRequest { + name: format!("projects/{project}/locations/asia-northeast1/keyRings/gcr_test/cryptoKeys/eth-sign/cryptoKeyVersions/1"), + digest: None, + digest_crc32c: None, + data: vec![1,2,3,4,5], + data_crc32c: None, + }; + let signature = client.asymmetric_sign(request.clone(), None).await.unwrap(); + assert!(!signature.signature.is_empty()); + } + + #[tokio::test] + #[serial] + async fn test_encrypt_decrypt() { + let (client, project) = new_client().await; + + let key = format!("projects/{project}/locations/asia-northeast1/keyRings/gcr_test/cryptoKeys/gcr_test"); + let data = [1, 2, 3, 4, 5]; + let request = EncryptRequest { + name: key.clone(), + plaintext: data.to_vec(), + additional_authenticated_data: vec![], + plaintext_crc32c: None, + additional_authenticated_data_crc32c: None, + }; + let encrypted = client.encrypt(request.clone(), None).await.unwrap(); + + let request = DecryptRequest { + name: key, + ciphertext: encrypted.ciphertext.clone(), + additional_authenticated_data: vec![], + ciphertext_crc32c: None, + additional_authenticated_data_crc32c: None, + }; + let raw = client.decrypt(request.clone(), None).await.unwrap(); + assert_eq!(data.to_vec(), raw.plaintext); + } } From 5b2e8839e25005585ecc0bb7444b13b7d42f3001 Mon Sep 17 00:00:00 2001 From: yoshidan Date: Wed, 8 May 2024 14:46:23 +0900 Subject: [PATCH 4/4] add test --- kms/src/client.rs | 49 ++++++++++++++++++++++++++++---- kms/src/grpc/apiv1/kms_client.rs | 31 ++++---------------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/kms/src/client.rs b/kms/src/client.rs index 3b03ec94..35130edd 100644 --- a/kms/src/client.rs +++ b/kms/src/client.rs @@ -1,10 +1,10 @@ -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use std::sync::Arc; #[cfg(feature = "auth")] pub use google_cloud_auth; use google_cloud_gax::conn::{ConnectionOptions, Environment, Error}; -use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; + use google_cloud_token::{NopeTokenSourceProvider, TokenSourceProvider}; use crate::grpc::apiv1::conn_pool::{ConnectionManager, KMS, SCOPES}; @@ -98,7 +98,7 @@ mod tests { use google_cloud_googleapis::cloud::kms::v1::{ AsymmetricSignRequest, CreateKeyRingRequest, DecryptRequest, EncryptRequest, GenerateRandomBytesRequest, - GetKeyRingRequest, ListKeyRingsRequest, ProtectionLevel, + GetKeyRingRequest, GetPublicKeyRequest, ListKeyRingsRequest, MacSignRequest, MacVerifyRequest, ProtectionLevel, }; use crate::client::{Client, ClientConfig}; @@ -118,7 +118,7 @@ mod tests { #[tokio::test] #[serial] async fn test_key_ring() { - let (mut client, project) = new_client().await; + let (client, project) = new_client().await; let key_ring_id = "gcpkmskr1714619260".to_string(); // create @@ -168,7 +168,7 @@ mod tests { #[tokio::test] #[serial] async fn test_generate_random_bytes() { - let (mut client, project) = new_client().await; + let (client, project) = new_client().await; // create let create_request = GenerateRandomBytesRequest { @@ -211,6 +211,16 @@ mod tests { let signature = client.asymmetric_sign(request.clone(), None).await.unwrap(); assert!(!signature.signature.is_empty()); } + #[tokio::test] + #[serial] + async fn test_get_pubkey() { + let (client, project) = new_client().await; + let request = GetPublicKeyRequest{ + name: format!("projects/{project}/locations/asia-northeast1/keyRings/gcr_test/cryptoKeys/eth-sign/cryptoKeyVersions/1"), + }; + let pubkey = client.get_public_key(request.clone(), None).await.unwrap(); + assert!(!pubkey.pem.is_empty()); + } #[tokio::test] #[serial] @@ -226,7 +236,7 @@ mod tests { plaintext_crc32c: None, additional_authenticated_data_crc32c: None, }; - let encrypted = client.encrypt(request.clone(), None).await.unwrap(); + let encrypted = client.encrypt(request, None).await.unwrap(); let request = DecryptRequest { name: key, @@ -238,4 +248,31 @@ mod tests { let raw = client.decrypt(request.clone(), None).await.unwrap(); assert_eq!(data.to_vec(), raw.plaintext); } + + #[tokio::test] + #[serial] + async fn test_mac_sign_verify() { + let (client, project) = new_client().await; + + let key = format!( + "projects/{project}/locations/asia-northeast1/keyRings/gcr_test/cryptoKeys/mac-test/cryptoKeyVersions/1" + ); + let data = [1, 2, 3, 4, 5]; + let request = MacSignRequest { + name: key.clone(), + data: data.to_vec(), + data_crc32c: None, + }; + let signature = client.mac_sign(request, None).await.unwrap(); + + let request = MacVerifyRequest { + name: key, + data: data.to_vec(), + data_crc32c: None, + mac: signature.mac, + mac_crc32c: signature.mac_crc32c, + }; + let raw = client.mac_verify(request, None).await.unwrap(); + assert!(raw.success); + } } diff --git a/kms/src/grpc/apiv1/kms_client.rs b/kms/src/grpc/apiv1/kms_client.rs index a1bcd78b..fa36c490 100644 --- a/kms/src/grpc/apiv1/kms_client.rs +++ b/kms/src/grpc/apiv1/kms_client.rs @@ -2,11 +2,11 @@ use std::sync::Arc; use std::time::Duration; use crate::grpc::apiv1::conn_pool::ConnectionManager; -use google_cloud_gax::conn::Channel; + use google_cloud_gax::create_request; use google_cloud_gax::grpc::{Code, Status}; -use google_cloud_gax::retry::{invoke, invoke_fn, RetrySetting}; -use google_cloud_googleapis::cloud::kms::v1::key_management_service_client::KeyManagementServiceClient; +use google_cloud_gax::retry::{invoke, RetrySetting}; + use google_cloud_googleapis::cloud::kms::v1::CreateCryptoKeyVersionRequest; use google_cloud_googleapis::cloud::kms::v1::CreateKeyRingRequest; use google_cloud_googleapis::cloud::kms::v1::CryptoKey; @@ -25,9 +25,9 @@ use google_cloud_googleapis::cloud::kms::v1::ListCryptoKeysResponse; use google_cloud_googleapis::cloud::kms::v1::ListKeyRingsRequest; use google_cloud_googleapis::cloud::kms::v1::ListKeyRingsResponse; use google_cloud_googleapis::cloud::kms::v1::{ - AsymmetricDecryptRequest, AsymmetricDecryptResponse, AsymmetricSignRequest, AsymmetricSignResponse, - CreateCryptoKeyRequest, DecryptRequest, DecryptResponse, EncryptRequest, EncryptResponse, GetPublicKeyRequest, - MacSignRequest, MacSignResponse, MacVerifyRequest, MacVerifyResponse, PublicKey, + AsymmetricSignRequest, AsymmetricSignResponse, CreateCryptoKeyRequest, DecryptRequest, DecryptResponse, + EncryptRequest, EncryptResponse, GetPublicKeyRequest, MacSignRequest, MacSignResponse, MacVerifyRequest, + MacVerifyResponse, PublicKey, }; fn default_setting() -> RetrySetting { @@ -304,25 +304,6 @@ impl Client { .map(|r| r.into_inner()) } - /// AsymmetricDecrypt - /// - /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.AsymmetricDecrypt - /// - #[cfg_attr(feature = "trace", tracing::instrument(skip_all))] - pub async fn asymmetric_decrypt( - &self, - req: AsymmetricDecryptRequest, - retry: Option, - ) -> Result { - let action = || async { - let request = create_request(format!("name={}", req.name), req.clone()); - self.cm.conn().asymmetric_decrypt(request).await - }; - invoke(Some(retry.unwrap_or_else(default_setting)), action) - .await - .map(|r| r.into_inner()) - } - /// MacSign /// /// https://cloud.google.com/kms/docs/reference/rpc/google.cloud.kms.v1#google.cloud.kms.v1.KeyManagementService.MacSign