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 <tyera@solana.com>
This commit is contained in:
Rachael Pai 2022-04-14 04:35:06 +08:00 committed by GitHub
parent e146e860e2
commit aea17c35ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 12 deletions

View File

@ -16,6 +16,7 @@ use {
}, },
solana_ledger::{blockstore::Blockstore, blockstore_db::AccessType}, solana_ledger::{blockstore::Blockstore, blockstore_db::AccessType},
solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature}, solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature},
solana_storage_bigtable::CredentialType,
solana_transaction_status::{ solana_transaction_status::{
BlockEncodingOptions, ConfirmedBlock, EncodeError, TransactionDetails, BlockEncodingOptions, ConfirmedBlock, EncodeError, TransactionDetails,
UiTransactionEncoding, UiTransactionEncoding,
@ -642,16 +643,18 @@ pub fn bigtable_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) {
instance_name, instance_name,
..solana_storage_bigtable::LedgerStorageConfig::default() ..solana_storage_bigtable::LedgerStorageConfig::default()
}; };
let credential_path = Some(value_t_or_exit!( let credential_path = Some(value_t_or_exit!(
arg_matches, arg_matches,
"reference_credential", "reference_credential",
String String
)); ));
let ref_instance_name = let ref_instance_name =
value_t_or_exit!(arg_matches, "reference_instance_name", String); value_t_or_exit!(arg_matches, "reference_instance_name", String);
let ref_config = solana_storage_bigtable::LedgerStorageConfig { let ref_config = solana_storage_bigtable::LedgerStorageConfig {
read_only: false, read_only: false,
credential_path, credential_type: CredentialType::Filepath(credential_path),
instance_name: ref_instance_name, instance_name: ref_instance_name,
..solana_storage_bigtable::LedgerStorageConfig::default() ..solana_storage_bigtable::LedgerStorageConfig::default()
}; };

View File

@ -37,6 +37,7 @@ use {
native_token::lamports_to_sol, pubkey::Pubkey, native_token::lamports_to_sol, pubkey::Pubkey,
}, },
solana_send_transaction_service::send_transaction_service::{self, SendTransactionService}, solana_send_transaction_service::send_transaction_service::{self, SendTransactionService},
solana_storage_bigtable::CredentialType,
std::{ std::{
collections::HashSet, collections::HashSet,
net::SocketAddr, net::SocketAddr,
@ -385,7 +386,7 @@ impl JsonRpcService {
let bigtable_config = solana_storage_bigtable::LedgerStorageConfig { let bigtable_config = solana_storage_bigtable::LedgerStorageConfig {
read_only: !enable_bigtable_ledger_upload, read_only: !enable_bigtable_ledger_upload,
timeout, timeout,
credential_path: None, credential_type: CredentialType::Filepath(None),
instance_name: bigtable_instance_name.clone(), instance_name: bigtable_instance_name.clone(),
}; };
runtime runtime

View File

@ -1,6 +1,7 @@
pub use goauth::scopes::Scope; pub use goauth::scopes::Scope;
/// A module for managing a Google API access token /// A module for managing a Google API access token
use { use {
crate::CredentialType,
goauth::{ goauth::{
auth::{JwtClaims, Token}, auth::{JwtClaims, Token},
credentials::Credentials, credentials::Credentials,
@ -8,6 +9,7 @@ use {
log::*, log::*,
smpl_jwt::Jwt, smpl_jwt::Jwt,
std::{ std::{
str::FromStr,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
{Arc, RwLock}, {Arc, RwLock},
@ -27,6 +29,10 @@ fn load_credentials(filepath: Option<String>) -> Result<Credentials, String> {
.map_err(|err| format!("Failed to read GCP credentials from {}: {}", path, err)) .map_err(|err| format!("Failed to read GCP credentials from {}: {}", path, err))
} }
fn load_stringified_credentials(credential: String) -> Result<Credentials, String> {
Credentials::from_str(&credential).map_err(|err| format!("{}", err))
}
#[derive(Clone)] #[derive(Clone)]
pub struct AccessToken { pub struct AccessToken {
credentials: Credentials, credentials: Credentials,
@ -36,8 +42,12 @@ pub struct AccessToken {
} }
impl AccessToken { impl AccessToken {
pub async fn new(scope: Scope, credential_filepath: Option<String>) -> Result<Self, String> { pub async fn new(scope: Scope, credential_type: CredentialType) -> Result<Self, String> {
let credentials = load_credentials(credential_filepath)?; 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() { if let Err(err) = credentials.rsa_key() {
Err(format!("Invalid rsa key: {}", err)) Err(format!("Invalid rsa key: {}", err))
} else { } else {

View File

@ -4,7 +4,7 @@ use {
crate::{ crate::{
access_token::{AccessToken, Scope}, access_token::{AccessToken, Scope},
compression::{compress_best, decompress}, compression::{compress_best, decompress},
root_ca_certificate, root_ca_certificate, CredentialType,
}, },
backoff::{future::retry, ExponentialBackoff}, backoff::{future::retry, ExponentialBackoff},
log::*, log::*,
@ -125,7 +125,7 @@ impl BigTableConnection {
instance_name: &str, instance_name: &str,
read_only: bool, read_only: bool,
timeout: Option<Duration>, timeout: Option<Duration>,
credential_path: Option<String>, credential_type: CredentialType,
) -> Result<Self> { ) -> Result<Self> {
match std::env::var("BIGTABLE_EMULATOR_HOST") { match std::env::var("BIGTABLE_EMULATOR_HOST") {
Ok(endpoint) => { Ok(endpoint) => {
@ -148,7 +148,7 @@ impl BigTableConnection {
} else { } else {
Scope::BigTableData Scope::BigTableData
}, },
credential_path, credential_type,
) )
.await .await
.map_err(Error::AccessToken)?; .map_err(Error::AccessToken)?;

View File

@ -364,11 +364,17 @@ impl From<LegacyTransactionByAddrInfo> for TransactionByAddrInfo {
pub const DEFAULT_INSTANCE_NAME: &str = "solana-ledger"; pub const DEFAULT_INSTANCE_NAME: &str = "solana-ledger";
#[derive(Debug)]
pub enum CredentialType {
Filepath(Option<String>),
Stringified(String),
}
#[derive(Debug)] #[derive(Debug)]
pub struct LedgerStorageConfig { pub struct LedgerStorageConfig {
pub read_only: bool, pub read_only: bool,
pub timeout: Option<std::time::Duration>, pub timeout: Option<std::time::Duration>,
pub credential_path: Option<String>, pub credential_type: CredentialType,
pub instance_name: String, pub instance_name: String,
} }
@ -377,7 +383,7 @@ impl Default for LedgerStorageConfig {
Self { Self {
read_only: true, read_only: true,
timeout: None, timeout: None,
credential_path: None, credential_type: CredentialType::Filepath(None),
instance_name: DEFAULT_INSTANCE_NAME.to_string(), instance_name: DEFAULT_INSTANCE_NAME.to_string(),
} }
} }
@ -397,7 +403,7 @@ impl LedgerStorage {
Self::new_with_config(LedgerStorageConfig { Self::new_with_config(LedgerStorageConfig {
read_only, read_only,
timeout, timeout,
credential_path, credential_type: CredentialType::Filepath(credential_path),
..LedgerStorageConfig::default() ..LedgerStorageConfig::default()
}) })
.await .await
@ -407,19 +413,27 @@ impl LedgerStorage {
let LedgerStorageConfig { let LedgerStorageConfig {
read_only, read_only,
timeout, timeout,
credential_path,
instance_name, instance_name,
credential_type,
} = config; } = config;
let connection = bigtable::BigTableConnection::new( let connection = bigtable::BigTableConnection::new(
instance_name.as_str(), instance_name.as_str(),
read_only, read_only,
timeout, timeout,
credential_path, credential_type,
) )
.await?; .await?;
Ok(Self { connection }) Ok(Self { connection })
} }
pub async fn new_with_stringified_credential(credential: String) -> Result<Self> {
Self::new_with_config(LedgerStorageConfig {
credential_type: CredentialType::Stringified(credential),
..LedgerStorageConfig::default()
})
.await
}
/// Return the available slot that contains a block /// Return the available slot that contains a block
pub async fn get_first_available_block(&self) -> Result<Option<Slot>> { pub async fn get_first_available_block(&self) -> Result<Option<Slot>> {
debug!("LedgerStorage::get_first_available_block request received"); debug!("LedgerStorage::get_first_available_block request received");