Skip to content

Commit

Permalink
refactor: add IRSA as first precedent for aws client creds (#202)
Browse files Browse the repository at this point in the history
* refactor: add IRSA as first precedent for aws client creds

* chore: changelogs

* refactor: cleanup irsa instantiation

* refactor: cleaner kms instantiation

* fix: add debug logging for IRSA failures

* refactor: move kms_client inside try_from_signer_conf
  • Loading branch information
prestwich authored Jun 17, 2022
1 parent 6252b77 commit 0527cb8
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 34 deletions.
40 changes: 19 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions agents/processor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Unreleased

- refactor: processor now uses global AWS client when proof pushing is enabled
- prevent processor from retrying messages it has previously attempted to
process
- improve prove/process tracing
Expand Down
3 changes: 2 additions & 1 deletion agents/processor/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,8 @@ impl NomadAgent for Processor {
// if we have a bucket, add a task to push to it
if let Some(config) = &self.config {
info!(bucket = %config.bucket, "Starting S3 push tasks");
tasks.push(Pusher::new(self.core.home.name(), &config.bucket, db.clone()).spawn())
let pusher = Pusher::new(self.core.home.name(), &config.bucket, db.clone()).await;
tasks.push(pusher.spawn())
}

// find the first task to shut down. Then cancel all others
Expand Down
5 changes: 3 additions & 2 deletions agents/processor/src/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ impl std::fmt::Debug for Pusher {

impl Pusher {
/// Instantiate a new pusher with a region
pub fn new(name: &str, bucket: &str, db: NomadDB) -> Self {
pub async fn new(name: &str, bucket: &str, db: NomadDB) -> Self {
let region: Region = Default::default(); // loads from aws env
let client = S3Client::new(region.clone());
let client =
S3Client::new_with_client(nomad_core::aws::get_client().await.clone(), region.clone());
Self {
name: name.to_owned(),
bucket: bucket.to_owned(),
Expand Down
7 changes: 5 additions & 2 deletions agents/watcher/src/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,12 @@ impl NomadAgent for Watcher {

let core = settings.as_ref().try_into_core("watcher").await?;

Ok(Self::new(
let signer =
Signers::try_from_signer_conf(&settings.base.attestation_signer.expect("signer"))
.await?,
.await?;

Ok(Self::new(
signer,
settings.agent.interval,
connection_managers,
core,
Expand Down
4 changes: 2 additions & 2 deletions chains/nomad-ethereum/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ macro_rules! wrap_with_signer {
#[macro_export]
macro_rules! tx_submitter_local {
($base_provider:expr, $signer_conf:ident) => {{
let signer = Signers::try_from_signer_conf(&$signer_conf).await?;
let signer = nomad_core::Signers::try_from_signer_conf(&$signer_conf).await?;
let signing_provider: Arc<_> = wrap_with_signer!($base_provider.clone(), signer);
TxSubmitter::new(signing_provider.into())
}};
Expand All @@ -166,7 +166,7 @@ macro_rules! tx_submitter_local {
#[macro_export]
macro_rules! tx_submitter_gelato {
($base_provider:expr, $gelato_conf:ident) => {{
let signer = Signers::try_from_signer_conf(&$gelato_conf.sponsor).await?;
let signer = nomad_core::Signers::try_from_signer_conf(&$gelato_conf.sponsor).await?;
let sponsor = signer.clone();
let chain_id = $base_provider.get_chainid().await?.as_usize();
let signing_provider: Arc<_> = wrap_with_signer!($base_provider.clone(), signer); // kludge: only using signing provider for type consistency with TxSubmitter::Local
Expand Down
1 change: 1 addition & 0 deletions nomad-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

### Unreleased

- refactor: Add IRSA credentials to client instantiation
- implement `Encode` and `Decode` for `bool`
- adds a changelog
3 changes: 2 additions & 1 deletion nomad-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ prometheus = "0.12.0"
bytes = { version = "1", features = ["serde"]}
rusoto_core = "0.48.0"
rusoto_kms = "0.48.0"
rusoto_credential = "0.47.0"
rusoto_credential = "0.48.0"
once_cell = "1.8.0"
num = { version="0", features=["serde"] }

accumulator = { path = "../accumulator" }
nomad-types = { path = "../nomad-types" }
nomad-xyz-configuration = { path = "../configuration" }
rusoto_sts = "0.48.0"

[dev-dependencies]
tokio = { version = "1.0.1", features = ["rt", "time", "macros"] }
Expand Down
70 changes: 70 additions & 0 deletions nomad-core/src/aws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use once_cell::sync::OnceCell;
use rusoto_core::{
credential::{AutoRefreshingProvider, ProvideAwsCredentials},
Client, HttpClient,
};
use rusoto_kms::KmsClient;
use rusoto_sts::WebIdentityProvider;

static CLIENT: OnceCell<Client> = OnceCell::new();
static KMS_CLIENT: OnceCell<KmsClient> = OnceCell::new();

// Try to get an irsa provider
#[tracing::instrument]
async fn try_irsa_provider() -> Option<AutoRefreshingProvider<WebIdentityProvider>> {
let irsa_provider = WebIdentityProvider::from_k8s_env();

// if there are no IRSA credentials this will error
let result = irsa_provider.credentials().await;

if result.is_err() {
tracing::debug!(error = %result.as_ref().unwrap_err(), "Error in irsa provider instantiation");
}

result
.ok()
.and_then(|_| AutoRefreshingProvider::new(irsa_provider).ok())
}

/// Get a shared AWS client with credentials
///
/// Credential precedence is as follows
/// 1. IRSA
/// 2. IAM
/// 3. environment
/// 4. Conf file
pub async fn get_client() -> &'static Client {
// init exactly once
if CLIENT.get().is_none() {
// try IRSA first
let client = match try_irsa_provider().await {
Some(credentials_provider) => {
let dispatcher = HttpClient::new().unwrap();
Client::new_with(credentials_provider, dispatcher)
}
// if the IRSA provider returned no creds, use the default
// credentials chain
None => Client::shared(),
};

if CLIENT.set(client).is_err() {
panic!("unable to set Client")
};
}

CLIENT.get().expect("just init")
}

/// Get a shared KMS client
pub async fn get_kms_client() -> &'static KmsClient {
if KMS_CLIENT.get().is_none() {
let client = get_client().await.clone();

let kms = KmsClient::new_with_client(client, Default::default());

if KMS_CLIENT.set(kms).is_err() {
panic!("unable to set KmsClient")
};
}
KMS_CLIENT.get().expect("just init")
}
3 changes: 3 additions & 0 deletions nomad-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

pub use accumulator;

/// AWS global state and init
pub mod aws;

/// DB related utilities
pub mod db;

Expand Down
7 changes: 2 additions & 5 deletions nomad-core/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ use ethers::{
signers::{AwsSignerError, LocalWallet, Signer},
};
use nomad_xyz_configuration::agent::SignerConf;
use once_cell::sync::Lazy;
use rusoto_kms::KmsClient;

static KMS_CLIENT: Lazy<KmsClient> = Lazy::new(|| KmsClient::new(Default::default()));

/// Error types for Signers
#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -62,7 +58,8 @@ impl Signers {
match conf {
SignerConf::HexKey(key) => Ok(Self::Local(key.as_ref().parse()?)),
SignerConf::Aws { id } => {
let signer = AwsSigner::new(&KMS_CLIENT, id, 0).await?;
let kms_client = crate::aws::get_kms_client().await;
let signer = AwsSigner::new(kms_client, id, 0).await?;
Ok(Self::Aws(signer))
}
SignerConf::Node => bail!("Node signer"),
Expand Down

0 comments on commit 0527cb8

Please sign in to comment.