@@ -39,6 +39,7 @@ use reqsign::AwsConfig;
39
39
use reqsign:: AwsCredentialLoad ;
40
40
use reqsign:: AwsDefaultLoader ;
41
41
use reqsign:: AwsV4Signer ;
42
+ use reqsign:: ECSCredentialProvider ;
42
43
use reqwest:: Url ;
43
44
44
45
use super :: core:: * ;
@@ -402,6 +403,58 @@ impl S3Builder {
402
403
self . session_token ( token)
403
404
}
404
405
406
+ /// Set container credentials relative URI for ECS Task IAM roles.
407
+ ///
408
+ /// Used in ECS environments where the base metadata endpoint is known.
409
+ /// Example: "/v2/credentials/my-role-name"
410
+ pub fn container_credentials_relative_uri ( mut self , uri : & str ) -> Self {
411
+ if !uri. is_empty ( ) {
412
+ self . config . container_credentials_relative_uri = Some ( uri. to_string ( ) ) ;
413
+ }
414
+ self
415
+ }
416
+
417
+ /// Set container credentials endpoint for Fargate or custom setups.
418
+ ///
419
+ /// Complete URL for fetching credentials. Used in Fargate environments.
420
+ /// Example: "http://169.254.170.2/v2/credentials/my-role"
421
+ pub fn container_credentials_endpoint ( mut self , endpoint : & str ) -> Self {
422
+ if !endpoint. is_empty ( ) {
423
+ self . config . container_credentials_endpoint = Some ( endpoint. to_string ( ) ) ;
424
+ }
425
+ self
426
+ }
427
+
428
+ /// Set authorization token for container credentials requests.
429
+ ///
430
+ /// Token used for authenticating with the container credentials endpoint.
431
+ pub fn container_authorization_token ( mut self , token : & str ) -> Self {
432
+ if !token. is_empty ( ) {
433
+ self . config . container_authorization_token = Some ( token. to_string ( ) ) ;
434
+ }
435
+ self
436
+ }
437
+
438
+ /// Set path to file containing authorization token for container credentials.
439
+ ///
440
+ /// File should contain the authorization token for ECS credentials endpoint.
441
+ pub fn container_authorization_token_file ( mut self , file_path : & str ) -> Self {
442
+ if !file_path. is_empty ( ) {
443
+ self . config . container_authorization_token_file = Some ( file_path. to_string ( ) ) ;
444
+ }
445
+ self
446
+ }
447
+
448
+ /// Set override for the container metadata URI base endpoint.
449
+ ///
450
+ /// Used to override the default http://169.254.170.2 endpoint, typically for testing.
451
+ pub fn container_metadata_uri_override ( mut self , uri : & str ) -> Self {
452
+ if !uri. is_empty ( ) {
453
+ self . config . container_metadata_uri_override = Some ( uri. to_string ( ) ) ;
454
+ }
455
+ self
456
+ }
457
+
405
458
/// Disable config load so that opendal will not load config from
406
459
/// environment.
407
460
///
@@ -495,6 +548,15 @@ impl S3Builder {
495
548
self
496
549
}
497
550
551
+ /// Check if ECS container credentials configuration is present
552
+ fn has_ecs_config ( & self ) -> bool {
553
+ self . config . container_credentials_endpoint . is_some ( )
554
+ || self . config . container_credentials_relative_uri . is_some ( )
555
+ || self . config . container_authorization_token . is_some ( )
556
+ || self . config . container_authorization_token_file . is_some ( )
557
+ || self . config . container_metadata_uri_override . is_some ( )
558
+ }
559
+
498
560
/// Check if `bucket` is valid
499
561
/// `bucket` must be not empty and if `enable_virtual_host_style` is true
500
562
/// it couldn't contain dot(.) character
@@ -844,6 +906,33 @@ impl Builder for S3Builder {
844
906
loader = Some ( v) ;
845
907
}
846
908
909
+ // If ECS container credentials are configured, use ECSCredentialProvider
910
+ if loader. is_none ( ) && self . has_ecs_config ( ) {
911
+ let mut ecs_provider = ECSCredentialProvider :: new ( ) ;
912
+
913
+ if let Some ( ref endpoint) = self . config . container_credentials_endpoint {
914
+ ecs_provider = ecs_provider. with_endpoint ( endpoint) ;
915
+ }
916
+
917
+ if let Some ( ref relative_uri) = self . config . container_credentials_relative_uri {
918
+ ecs_provider = ecs_provider. with_relative_uri ( relative_uri) ;
919
+ }
920
+
921
+ if let Some ( ref token) = self . config . container_authorization_token {
922
+ ecs_provider = ecs_provider. with_auth_token ( token) ;
923
+ }
924
+
925
+ if let Some ( ref token_file) = self . config . container_authorization_token_file {
926
+ ecs_provider = ecs_provider. with_auth_token_file ( token_file) ;
927
+ }
928
+
929
+ if let Some ( ref uri_override) = self . config . container_metadata_uri_override {
930
+ ecs_provider = ecs_provider. with_metadata_uri_override ( uri_override) ;
931
+ }
932
+
933
+ loader = Some ( Box :: new ( ecs_provider) ) ;
934
+ }
935
+
847
936
// If role_arn is set, we must use AssumeRoleLoad.
848
937
if let Some ( role_arn) = self . config . role_arn {
849
938
// use current env as source credential loader.
0 commit comments