From aea17c35ae725f09bc74ffce09611082354d9b95 Mon Sep 17 00:00:00 2001 From: Rachael Pai Date: Thu, 14 Apr 2022 04:35:06 +0800 Subject: [PATCH] Add a stringified credential option for LedgerStorage (#24314) * add a stringified credential option for LedgerStorage * fix clippy::useless-format warning * change CredentialOption to enum CredentialType * rename credential_option to credential_type * restore LedgerStorage new fn signature * fmt Co-authored-by: Tyera Eulberg --- ledger-tool/src/bigtable.rs | 5 ++++- rpc/src/rpc_service.rs | 3 ++- storage-bigtable/src/access_token.rs | 14 ++++++++++++-- storage-bigtable/src/bigtable.rs | 6 +++--- storage-bigtable/src/lib.rs | 24 +++++++++++++++++++----- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/ledger-tool/src/bigtable.rs b/ledger-tool/src/bigtable.rs index 5c2d8785b3..1d088d1c24 100644 --- a/ledger-tool/src/bigtable.rs +++ b/ledger-tool/src/bigtable.rs @@ -16,6 +16,7 @@ use { }, solana_ledger::{blockstore::Blockstore, blockstore_db::AccessType}, solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}, + solana_storage_bigtable::CredentialType, solana_transaction_status::{ BlockEncodingOptions, ConfirmedBlock, EncodeError, TransactionDetails, UiTransactionEncoding, @@ -642,16 +643,18 @@ pub fn bigtable_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) { instance_name, ..solana_storage_bigtable::LedgerStorageConfig::default() }; + let credential_path = Some(value_t_or_exit!( arg_matches, "reference_credential", String )); + let ref_instance_name = value_t_or_exit!(arg_matches, "reference_instance_name", String); let ref_config = solana_storage_bigtable::LedgerStorageConfig { read_only: false, - credential_path, + credential_type: CredentialType::Filepath(credential_path), instance_name: ref_instance_name, ..solana_storage_bigtable::LedgerStorageConfig::default() }; diff --git a/rpc/src/rpc_service.rs b/rpc/src/rpc_service.rs index 6656a3ba10..740d3bcd32 100644 --- a/rpc/src/rpc_service.rs +++ b/rpc/src/rpc_service.rs @@ -37,6 +37,7 @@ use { native_token::lamports_to_sol, pubkey::Pubkey, }, solana_send_transaction_service::send_transaction_service::{self, SendTransactionService}, + solana_storage_bigtable::CredentialType, std::{ collections::HashSet, net::SocketAddr, @@ -385,7 +386,7 @@ impl JsonRpcService { let bigtable_config = solana_storage_bigtable::LedgerStorageConfig { read_only: !enable_bigtable_ledger_upload, timeout, - credential_path: None, + credential_type: CredentialType::Filepath(None), instance_name: bigtable_instance_name.clone(), }; runtime diff --git a/storage-bigtable/src/access_token.rs b/storage-bigtable/src/access_token.rs index 77840214be..3c2d596cf0 100644 --- a/storage-bigtable/src/access_token.rs +++ b/storage-bigtable/src/access_token.rs @@ -1,6 +1,7 @@ pub use goauth::scopes::Scope; /// A module for managing a Google API access token use { + crate::CredentialType, goauth::{ auth::{JwtClaims, Token}, credentials::Credentials, @@ -8,6 +9,7 @@ use { log::*, smpl_jwt::Jwt, std::{ + str::FromStr, sync::{ atomic::{AtomicBool, Ordering}, {Arc, RwLock}, @@ -27,6 +29,10 @@ fn load_credentials(filepath: Option) -> Result { .map_err(|err| format!("Failed to read GCP credentials from {}: {}", path, err)) } +fn load_stringified_credentials(credential: String) -> Result { + Credentials::from_str(&credential).map_err(|err| format!("{}", err)) +} + #[derive(Clone)] pub struct AccessToken { credentials: Credentials, @@ -36,8 +42,12 @@ pub struct AccessToken { } impl AccessToken { - pub async fn new(scope: Scope, credential_filepath: Option) -> Result { - let credentials = load_credentials(credential_filepath)?; + pub async fn new(scope: Scope, credential_type: CredentialType) -> Result { + let credentials = match credential_type { + CredentialType::Filepath(fp) => load_credentials(fp)?, + CredentialType::Stringified(s) => load_stringified_credentials(s)?, + }; + if let Err(err) = credentials.rsa_key() { Err(format!("Invalid rsa key: {}", err)) } else { diff --git a/storage-bigtable/src/bigtable.rs b/storage-bigtable/src/bigtable.rs index 2e17b60e11..fbd23008a3 100644 --- a/storage-bigtable/src/bigtable.rs +++ b/storage-bigtable/src/bigtable.rs @@ -4,7 +4,7 @@ use { crate::{ access_token::{AccessToken, Scope}, compression::{compress_best, decompress}, - root_ca_certificate, + root_ca_certificate, CredentialType, }, backoff::{future::retry, ExponentialBackoff}, log::*, @@ -125,7 +125,7 @@ impl BigTableConnection { instance_name: &str, read_only: bool, timeout: Option, - credential_path: Option, + credential_type: CredentialType, ) -> Result { match std::env::var("BIGTABLE_EMULATOR_HOST") { Ok(endpoint) => { @@ -148,7 +148,7 @@ impl BigTableConnection { } else { Scope::BigTableData }, - credential_path, + credential_type, ) .await .map_err(Error::AccessToken)?; diff --git a/storage-bigtable/src/lib.rs b/storage-bigtable/src/lib.rs index cdb152991e..2a6e798808 100644 --- a/storage-bigtable/src/lib.rs +++ b/storage-bigtable/src/lib.rs @@ -364,11 +364,17 @@ impl From for TransactionByAddrInfo { pub const DEFAULT_INSTANCE_NAME: &str = "solana-ledger"; +#[derive(Debug)] +pub enum CredentialType { + Filepath(Option), + Stringified(String), +} + #[derive(Debug)] pub struct LedgerStorageConfig { pub read_only: bool, pub timeout: Option, - pub credential_path: Option, + pub credential_type: CredentialType, pub instance_name: String, } @@ -377,7 +383,7 @@ impl Default for LedgerStorageConfig { Self { read_only: true, timeout: None, - credential_path: None, + credential_type: CredentialType::Filepath(None), instance_name: DEFAULT_INSTANCE_NAME.to_string(), } } @@ -397,7 +403,7 @@ impl LedgerStorage { Self::new_with_config(LedgerStorageConfig { read_only, timeout, - credential_path, + credential_type: CredentialType::Filepath(credential_path), ..LedgerStorageConfig::default() }) .await @@ -407,19 +413,27 @@ impl LedgerStorage { let LedgerStorageConfig { read_only, timeout, - credential_path, instance_name, + credential_type, } = config; let connection = bigtable::BigTableConnection::new( instance_name.as_str(), read_only, timeout, - credential_path, + credential_type, ) .await?; Ok(Self { connection }) } + pub async fn new_with_stringified_credential(credential: String) -> Result { + Self::new_with_config(LedgerStorageConfig { + credential_type: CredentialType::Stringified(credential), + ..LedgerStorageConfig::default() + }) + .await + } + /// Return the available slot that contains a block pub async fn get_first_available_block(&self) -> Result> { debug!("LedgerStorage::get_first_available_block request received");