@@ -47,9 +47,7 @@ use url::Url;
4747
4848pub use crate :: aws:: checksum:: Checksum ;
4949use crate :: aws:: client:: { S3Client , S3Config } ;
50- use crate :: aws:: credential:: {
51- AwsCredential , InstanceCredentialProvider , WebIdentityProvider ,
52- } ;
50+ use crate :: aws:: credential:: { InstanceCredentialProvider , WebIdentityProvider } ;
5351use crate :: client:: header:: header_meta;
5452use crate :: client:: {
5553 ClientConfigKey , CredentialProvider , StaticCredentialProvider ,
@@ -85,7 +83,9 @@ const STRICT_PATH_ENCODE_SET: percent_encoding::AsciiSet = STRICT_ENCODE_SET.rem
8583
8684const STORE : & str = "S3" ;
8785
88- type AwsCredentialProvider = Arc < dyn CredentialProvider < Credential = AwsCredential > > ;
86+ /// [`CredentialProvider`] for [`AmazonS3`]
87+ pub type AwsCredentialProvider = Arc < dyn CredentialProvider < Credential = AwsCredential > > ;
88+ pub use credential:: AwsCredential ;
8989
9090/// Default metadata endpoint
9191static METADATA_ENDPOINT : & str = "http://169.254.169.254" ;
@@ -209,6 +209,13 @@ impl std::fmt::Display for AmazonS3 {
209209 }
210210}
211211
212+ impl AmazonS3 {
213+ /// Returns the [`AwsCredentialProvider`] used by [`AmazonS3`]
214+ pub fn credentials ( & self ) -> & AwsCredentialProvider {
215+ & self . client . config ( ) . credentials
216+ }
217+ }
218+
212219#[ async_trait]
213220impl ObjectStore for AmazonS3 {
214221 async fn put ( & self , location : & Path , bytes : Bytes ) -> Result < ( ) > {
@@ -424,6 +431,8 @@ pub struct AmazonS3Builder {
424431 profile : Option < String > ,
425432 /// Client options
426433 client_options : ClientOptions ,
434+ /// Credentials
435+ credentials : Option < AwsCredentialProvider > ,
427436}
428437
429438/// Configuration keys for [`AmazonS3Builder`]
@@ -879,6 +888,12 @@ impl AmazonS3Builder {
879888 self
880889 }
881890
891+ /// Set the credential provider overriding any other options
892+ pub fn with_credentials ( mut self , credentials : AwsCredentialProvider ) -> Self {
893+ self . credentials = Some ( credentials) ;
894+ self
895+ }
896+
882897 /// Sets what protocol is allowed. If `allow_http` is :
883898 /// * false (default): Only HTTPS are allowed
884899 /// * true: HTTP and HTTPS are allowed
@@ -992,7 +1007,7 @@ impl AmazonS3Builder {
9921007 self . parse_url ( & url) ?;
9931008 }
9941009
995- let region = match ( self . region . clone ( ) , self . profile . clone ( ) ) {
1010+ let region = match ( self . region , self . profile . clone ( ) ) {
9961011 ( Some ( region) , _) => Some ( region) ,
9971012 ( None , Some ( profile) ) => profile_region ( profile) ,
9981013 ( None , None ) => None ,
@@ -1002,76 +1017,74 @@ impl AmazonS3Builder {
10021017 let region = region. context ( MissingRegionSnafu ) ?;
10031018 let checksum = self . checksum_algorithm . map ( |x| x. get ( ) ) . transpose ( ) ?;
10041019
1005- let credentials = match ( self . access_key_id , self . secret_access_key , self . token ) {
1006- ( Some ( key_id) , Some ( secret_key) , token) => {
1007- info ! ( "Using Static credential provider" ) ;
1008- let credential = AwsCredential {
1009- key_id,
1010- secret_key,
1011- token,
1012- } ;
1013- Arc :: new ( StaticCredentialProvider :: new ( credential) ) as _
1014- }
1015- ( None , Some ( _) , _) => return Err ( Error :: MissingAccessKeyId . into ( ) ) ,
1016- ( Some ( _) , None , _) => return Err ( Error :: MissingSecretAccessKey . into ( ) ) ,
1017- // TODO: Replace with `AmazonS3Builder::credentials_from_env`
1018- _ => match (
1019- std:: env:: var ( "AWS_WEB_IDENTITY_TOKEN_FILE" ) ,
1020- std:: env:: var ( "AWS_ROLE_ARN" ) ,
1021- ) {
1022- ( Ok ( token_path) , Ok ( role_arn) ) => {
1023- info ! ( "Using WebIdentity credential provider" ) ;
1024-
1025- let session_name = std:: env:: var ( "AWS_ROLE_SESSION_NAME" )
1026- . unwrap_or_else ( |_| "WebIdentitySession" . to_string ( ) ) ;
1027-
1028- let endpoint = format ! ( "https://sts.{region}.amazonaws.com" ) ;
1029-
1030- // Disallow non-HTTPs requests
1031- let client = self
1032- . client_options
1033- . clone ( )
1034- . with_allow_http ( false )
1035- . client ( ) ?;
1036-
1037- let token = WebIdentityProvider {
1038- token_path,
1039- session_name,
1040- role_arn,
1041- endpoint,
1042- } ;
1043-
1044- Arc :: new ( TokenCredentialProvider :: new (
1020+ let credentials = if let Some ( credentials) = self . credentials {
1021+ credentials
1022+ } else if self . access_key_id . is_some ( ) || self . secret_access_key . is_some ( ) {
1023+ match ( self . access_key_id , self . secret_access_key , self . token ) {
1024+ ( Some ( key_id) , Some ( secret_key) , token) => {
1025+ info ! ( "Using Static credential provider" ) ;
1026+ let credential = AwsCredential {
1027+ key_id,
1028+ secret_key,
10451029 token,
1046- client,
1047- self . retry_config . clone ( ) ,
1048- ) ) as _
1030+ } ;
1031+ Arc :: new ( StaticCredentialProvider :: new ( credential) ) as _
10491032 }
1050- _ => match self . profile {
1051- Some ( profile) => {
1052- info ! ( "Using profile \" {}\" credential provider" , profile) ;
1053- profile_credentials ( profile, region. clone ( ) ) ?
1054- }
1055- None => {
1056- info ! ( "Using Instance credential provider" ) ;
1057-
1058- let token = InstanceCredentialProvider {
1059- cache : Default :: default ( ) ,
1060- imdsv1_fallback : self . imdsv1_fallback . get ( ) ?,
1061- metadata_endpoint : self
1062- . metadata_endpoint
1063- . unwrap_or_else ( || METADATA_ENDPOINT . into ( ) ) ,
1064- } ;
1065-
1066- Arc :: new ( TokenCredentialProvider :: new (
1067- token,
1068- // The instance metadata endpoint is access over HTTP
1069- self . client_options . clone ( ) . with_allow_http ( true ) . client ( ) ?,
1070- self . retry_config . clone ( ) ,
1071- ) ) as _
1072- }
1073- } ,
1074- } ,
1033+ ( None , Some ( _) , _) => return Err ( Error :: MissingAccessKeyId . into ( ) ) ,
1034+ ( Some ( _) , None , _) => return Err ( Error :: MissingSecretAccessKey . into ( ) ) ,
1035+ ( None , None , _) => unreachable ! ( ) ,
1036+ }
1037+ } else if let ( Ok ( token_path) , Ok ( role_arn) ) = (
1038+ std:: env:: var ( "AWS_WEB_IDENTITY_TOKEN_FILE" ) ,
1039+ std:: env:: var ( "AWS_ROLE_ARN" ) ,
1040+ ) {
1041+ // TODO: Replace with `AmazonS3Builder::credentials_from_env`
1042+ info ! ( "Using WebIdentity credential provider" ) ;
1043+
1044+ let session_name = std:: env:: var ( "AWS_ROLE_SESSION_NAME" )
1045+ . unwrap_or_else ( |_| "WebIdentitySession" . to_string ( ) ) ;
1046+
1047+ let endpoint = format ! ( "https://sts.{region}.amazonaws.com" ) ;
1048+
1049+ // Disallow non-HTTPs requests
1050+ let client = self
1051+ . client_options
1052+ . clone ( )
1053+ . with_allow_http ( false )
1054+ . client ( ) ?;
1055+
1056+ let token = WebIdentityProvider {
1057+ token_path,
1058+ session_name,
1059+ role_arn,
1060+ endpoint,
1061+ } ;
1062+
1063+ Arc :: new ( TokenCredentialProvider :: new (
1064+ token,
1065+ client,
1066+ self . retry_config . clone ( ) ,
1067+ ) ) as _
1068+ } else if let Some ( profile) = self . profile {
1069+ info ! ( "Using profile \" {}\" credential provider" , profile) ;
1070+ profile_credentials ( profile, region. clone ( ) ) ?
1071+ } else {
1072+ info ! ( "Using Instance credential provider" ) ;
1073+
1074+ let token = InstanceCredentialProvider {
1075+ cache : Default :: default ( ) ,
1076+ imdsv1_fallback : self . imdsv1_fallback . get ( ) ?,
1077+ metadata_endpoint : self
1078+ . metadata_endpoint
1079+ . unwrap_or_else ( || METADATA_ENDPOINT . into ( ) ) ,
1080+ } ;
1081+
1082+ Arc :: new ( TokenCredentialProvider :: new (
1083+ token,
1084+ // The instance metadata endpoint is access over HTTP
1085+ self . client_options . clone ( ) . with_allow_http ( true ) . client ( ) ?,
1086+ self . retry_config . clone ( ) ,
1087+ ) ) as _
10751088 } ;
10761089
10771090 let endpoint: String ;
0 commit comments