Skip to content

Commit 10ffea5

Browse files
committed
Use separate client for credentials
1 parent cd4b25f commit 10ffea5

File tree

3 files changed

+97
-70
lines changed

3 files changed

+97
-70
lines changed

object_store/src/aws/client.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,7 @@ impl S3Client {
230230
}
231231

232232
async fn get_credential(&self) -> Result<Arc<AwsCredential>> {
233-
self.config
234-
.credentials
235-
.get_credential(&self.client, &self.config.retry_config)
236-
.await
233+
self.config.credentials.get_credential().await
237234
}
238235

239236
/// Make an S3 GET request <https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html>

object_store/src/aws/credential.rs

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -243,75 +243,90 @@ fn canonicalize_headers(header_map: &HeaderMap) -> (String, String) {
243243
(signed_headers, canonical_headers)
244244
}
245245

246+
/// Provides credentials for use when signing requests
246247
#[derive(Debug)]
247248
pub enum CredentialProvider {
248-
Static {
249-
credential: Arc<AwsCredential>,
250-
},
251-
/// <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html>
252-
Instance {
253-
cache: TokenCache<Arc<AwsCredential>>,
254-
},
255-
WebIdentity {
256-
cache: TokenCache<Arc<AwsCredential>>,
257-
token: String,
258-
role_arn: String,
259-
session_name: String,
260-
endpoint: String,
261-
},
249+
Static(StaticCredentialProvider),
250+
Instance(InstanceCredentialProvider),
251+
WebIdentity(WebIdentityProvider),
262252
}
263253

264254
impl CredentialProvider {
265-
pub async fn get_credential(
266-
&self,
267-
client: &Client,
268-
retry_config: &RetryConfig,
269-
) -> Result<Arc<AwsCredential>> {
255+
pub async fn get_credential(&self) -> Result<Arc<AwsCredential>> {
270256
match self {
271-
CredentialProvider::Static { credential } => Ok(Arc::clone(credential)),
272-
CredentialProvider::Instance { cache } => {
273-
cache
274-
.get_or_insert_with(|| {
275-
const METADATA_ENDPOINT: &str = "http://169.254.169.254";
276-
instance_creds(client, retry_config, METADATA_ENDPOINT).map_err(
277-
|source| crate::Error::Generic {
278-
store: "S3",
279-
source,
280-
},
281-
)
282-
})
283-
.await
284-
}
285-
CredentialProvider::WebIdentity {
286-
cache,
287-
token,
288-
role_arn,
289-
session_name,
290-
endpoint,
291-
} => {
292-
cache
293-
.get_or_insert_with(|| {
294-
web_identity(
295-
client,
296-
retry_config,
297-
token,
298-
role_arn,
299-
session_name,
300-
endpoint,
301-
)
302-
.map_err(|source| {
303-
crate::Error::Generic {
304-
store: "S3",
305-
source,
306-
}
307-
})
308-
})
309-
.await
310-
}
257+
CredentialProvider::Static(s) => Ok(Arc::clone(&s.credential)),
258+
CredentialProvider::Instance(c) => c.get_credential().await,
259+
CredentialProvider::WebIdentity(c) => c.get_credential().await,
311260
}
312261
}
313262
}
314263

264+
/// A static set of credentials
265+
#[derive(Debug)]
266+
pub struct StaticCredentialProvider {
267+
pub credential: Arc<AwsCredential>,
268+
}
269+
270+
/// Credentials sourced from the instance metadata service
271+
///
272+
/// <https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html>
273+
#[derive(Debug)]
274+
pub struct InstanceCredentialProvider {
275+
pub cache: TokenCache<Arc<AwsCredential>>,
276+
pub client: Client,
277+
pub retry_config: RetryConfig,
278+
}
279+
280+
impl InstanceCredentialProvider {
281+
async fn get_credential(&self) -> Result<Arc<AwsCredential>> {
282+
self.cache
283+
.get_or_insert_with(|| {
284+
const METADATA_ENDPOINT: &str = "http://169.254.169.254";
285+
instance_creds(&self.client, &self.retry_config, METADATA_ENDPOINT)
286+
.map_err(|source| crate::Error::Generic {
287+
store: "S3",
288+
source,
289+
})
290+
})
291+
.await
292+
}
293+
}
294+
295+
/// Credentials sourced using AssumeRoleWithWebIdentity
296+
///
297+
/// <https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html>
298+
#[derive(Debug)]
299+
pub struct WebIdentityProvider {
300+
pub cache: TokenCache<Arc<AwsCredential>>,
301+
pub token: String,
302+
pub role_arn: String,
303+
pub session_name: String,
304+
pub endpoint: String,
305+
pub client: Client,
306+
pub retry_config: RetryConfig,
307+
}
308+
309+
impl WebIdentityProvider {
310+
async fn get_credential(&self) -> Result<Arc<AwsCredential>> {
311+
self.cache
312+
.get_or_insert_with(|| {
313+
web_identity(
314+
&self.client,
315+
&self.retry_config,
316+
&self.token,
317+
&self.role_arn,
318+
&self.session_name,
319+
&self.endpoint,
320+
)
321+
.map_err(|source| crate::Error::Generic {
322+
store: "S3",
323+
source,
324+
})
325+
})
326+
.await
327+
}
328+
}
329+
315330
#[derive(Debug, Deserialize)]
316331
#[serde(rename_all = "PascalCase")]
317332
struct InstanceCredentials {

object_store/src/aws/mod.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use bytes::Bytes;
3636
use chrono::{DateTime, Utc};
3737
use futures::stream::BoxStream;
3838
use futures::TryStreamExt;
39+
use reqwest::Client;
3940
use snafu::{OptionExt, ResultExt, Snafu};
4041
use std::collections::BTreeSet;
4142
use std::ops::Range;
@@ -44,7 +45,10 @@ use tokio::io::AsyncWrite;
4445
use tracing::info;
4546

4647
use crate::aws::client::{S3Client, S3Config};
47-
use crate::aws::credential::{AwsCredential, CredentialProvider};
48+
use crate::aws::credential::{
49+
AwsCredential, CredentialProvider, InstanceCredentialProvider,
50+
StaticCredentialProvider, WebIdentityProvider,
51+
};
4852
use crate::multipart::{CloudMultiPartUpload, CloudMultiPartUploadImpl, UploadPart};
4953
use crate::{
5054
GetResult, ListResult, MultipartId, ObjectMeta, ObjectStore, Path, Result,
@@ -409,13 +413,13 @@ impl AmazonS3Builder {
409413
let credentials = match (self.access_key_id, self.secret_access_key, self.token) {
410414
(Some(key_id), Some(secret_key), token) => {
411415
info!("Using Static credential provider");
412-
CredentialProvider::Static {
416+
CredentialProvider::Static(StaticCredentialProvider {
413417
credential: Arc::new(AwsCredential {
414418
key_id,
415419
secret_key,
416420
token,
417421
}),
418-
}
422+
})
419423
}
420424
(None, Some(_), _) => return Err(Error::MissingAccessKeyId.into()),
421425
(Some(_), None, _) => return Err(Error::MissingSecretAccessKey.into()),
@@ -434,19 +438,30 @@ impl AmazonS3Builder {
434438

435439
let endpoint = format!("https://sts.{}.amazonaws.com", region);
436440

437-
CredentialProvider::WebIdentity {
441+
// Disallow non-HTTPs requests
442+
let client = Client::builder().https_only(true).build().unwrap();
443+
444+
CredentialProvider::WebIdentity(WebIdentityProvider {
438445
cache: Default::default(),
439446
token,
440447
session_name,
441448
role_arn,
442449
endpoint,
443-
}
450+
client,
451+
retry_config: self.retry_config.clone(),
452+
})
444453
}
445454
_ => {
446455
info!("Using Instance credential provider");
447-
CredentialProvider::Instance {
456+
457+
// The instance metadata endpoint is access over HTTP
458+
let client = Client::builder().https_only(false).build().unwrap();
459+
460+
CredentialProvider::Instance(InstanceCredentialProvider {
448461
cache: Default::default(),
449-
}
462+
client,
463+
retry_config: self.retry_config.clone(),
464+
})
450465
}
451466
},
452467
};

0 commit comments

Comments
 (0)