This is an automated email from the ASF dual-hosted git repository. xuanwo pushed a commit to branch xuanwo/oss-pr4-network-credentials in repository https://gitbox.apache.org/repos/asf/opendal-reqsign.git
commit f23c34d4439a65834621daa39edd0f272de1bdaf Merge: 7378957 3dc1cf1 Author: Xuanwo <[email protected]> AuthorDate: Thu Mar 19 02:55:21 2026 +0800 Merge remote-tracking branch 'origin/main' into xuanwo/oss-pr4-network-credentials # Conflicts: # services/aliyun-oss/README.md # services/aliyun-oss/examples/oss_operations.rs # services/aliyun-oss/src/lib.rs # services/aliyun-oss/src/provide_credential/default.rs services/aliyun-oss/README.md | 64 ++- services/aliyun-oss/examples/oss_operations.rs | 13 +- services/aliyun-oss/src/constants.rs | 1 + services/aliyun-oss/src/lib.rs | 53 +- .../src/provide_credential/assume_role.rs | 640 +++++++++++++++++++++ .../aliyun-oss/src/provide_credential/default.rs | 201 ++++++- services/aliyun-oss/src/provide_credential/mod.rs | 3 + services/aliyun-oss/src/sign_request.rs | 638 +++++++++++++++++++- 8 files changed, 1544 insertions(+), 69 deletions(-) diff --cc services/aliyun-oss/README.md index ee10e66,27582ff..10aefc9 --- a/services/aliyun-oss/README.md +++ b/services/aliyun-oss/README.md @@@ -10,11 -10,10 +10,11 @@@ This crate provides signing support fo ```rust use reqsign_aliyun_oss::{ - AssumeRoleWithOidcCredentialProvider, CredentialsUriCredentialProvider, - AssumeRoleWithOidcCredentialProvider, ConfigFileCredentialProvider, - CredentialsFileCredentialProvider, DefaultCredentialProvider, - EcsRamRoleCredentialProvider, EnvCredentialProvider, - OssProfileCredentialProvider, RequestSigner, StaticCredentialProvider, + AssumeRoleCredentialProvider, AssumeRoleWithOidcCredentialProvider, - ConfigFileCredentialProvider, CredentialsFileCredentialProvider, DefaultCredentialProvider, - EnvCredentialProvider, OssProfileCredentialProvider, RequestSigner, - SigningVersion, StaticCredentialProvider, ++ ConfigFileCredentialProvider, CredentialsFileCredentialProvider, ++ CredentialsUriCredentialProvider, DefaultCredentialProvider, ++ EcsRamRoleCredentialProvider, EnvCredentialProvider, OssProfileCredentialProvider, ++ RequestSigner, SigningVersion, StaticCredentialProvider, }; use reqsign_core::{Context, Result, Signer}; use reqsign_file_read_tokio::TokioFileRead; @@@ -63,8 -63,8 +66,9 @@@ async fn main() -> Result<()> ## Features - - **HMAC-SHA1 Signing**: Complete implementation of Aliyun's signing algorithm - - **Multiple Credential Sources**: Environment variables, OSS profile files, Alibaba shared credential/config files, credentials URI, ECS RAM role metadata, and OIDC-based STS exchange + - **Multiple Credential Sources**: Environment variables, OSS profile files, Alibaba shared credential/config files, AssumeRole, and OIDC-based STS exchange + - **V1 and V4 Signing**: Supports both legacy OSS V1 signatures and Signature V4 ++- **Runtime Credential Sources**: Credentials URI, ECS RAM role metadata, and OIDC-based STS exchange - **STS Support**: Temporary credentials via Security Token Service - **All OSS Operations**: Object, bucket, and multipart operations @@@ -179,6 -158,6 +184,7 @@@ Reads from `~/.aliyun/config.json` by d Override the file path with `ALIBABA_CLOUD_CONFIG_FILE` and the selected profile with `ALIBABA_CLOUD_PROFILE`. Only direct static modes are loaded in this crate today: `AK` and `StsToken`. ++ ### STS AssumeRole with OIDC For Kubernetes/ACK environments: diff --cc services/aliyun-oss/examples/oss_operations.rs index 2ff276d,09b5c6c..3b80205 --- a/services/aliyun-oss/examples/oss_operations.rs +++ b/services/aliyun-oss/examples/oss_operations.rs @@@ -16,10 -16,8 +16,10 @@@ // under the License. use reqsign_aliyun_oss::{ - AssumeRoleWithOidcCredentialProvider, ConfigFileCredentialProvider, - CredentialsFileCredentialProvider, CredentialsUriCredentialProvider, DefaultCredentialProvider, - EcsRamRoleCredentialProvider, EnvCredentialProvider, OssProfileCredentialProvider, - RequestSigner, StaticCredentialProvider, + AssumeRoleCredentialProvider, AssumeRoleWithOidcCredentialProvider, DefaultCredentialProvider, - EnvCredentialProvider, RequestSigner, StaticCredentialProvider, ++ ConfigFileCredentialProvider, CredentialsFileCredentialProvider, ++ CredentialsUriCredentialProvider, EcsRamRoleCredentialProvider, EnvCredentialProvider, ++ OssProfileCredentialProvider, RequestSigner, StaticCredentialProvider, }; use reqsign_core::Result; use reqsign_core::{Context, OsEnv, Signer}; @@@ -64,15 -62,10 +64,16 @@@ async fn main() -> Result<()> StaticCredentialProvider::new("LTAI4GDemoAccessKeyId", "DemoAccessKeySecretForExample"); Signer::new(ctx.clone(), loader, builder) } else { - // Build the default env -> oss_profile -> credentials_file -> config_file -> - // credentials_uri -> ecs_ram_role -> oidc chain. - // Build the default assume_role -> env -> oidc chain explicitly via slot APIs. ++ // Build the default assume_role -> env -> oss_profile -> credentials_file -> ++ // config_file -> credentials_uri -> ecs_ram_role -> oidc chain. let loader = DefaultCredentialProvider::builder() + .assume_role(AssumeRoleCredentialProvider::new()) .env(EnvCredentialProvider::new()) + .oss_profile(OssProfileCredentialProvider::new()) + .credentials_file(CredentialsFileCredentialProvider::new()) + .config_file(ConfigFileCredentialProvider::new()) + .credentials_uri(CredentialsUriCredentialProvider::new()) + .ecs_ram_role(EcsRamRoleCredentialProvider::new()) .oidc(AssumeRoleWithOidcCredentialProvider::new()) .build(); Signer::new(ctx.clone(), loader, builder) diff --cc services/aliyun-oss/src/constants.rs index 82c8ccf,ca20192..590f11d --- a/services/aliyun-oss/src/constants.rs +++ b/services/aliyun-oss/src/constants.rs @@@ -27,14 -27,9 +27,15 @@@ pub const OSS_ACCESS_KEY_SECRET: &str pub const OSS_SESSION_TOKEN: &str = "OSS_SESSION_TOKEN"; pub const OSS_PROFILE: &str = "OSS_PROFILE"; pub const OSS_CREDENTIAL_PROFILES_FILE: &str = "OSS_CREDENTIAL_PROFILES_FILE"; +pub const ALIBABA_CLOUD_CREDENTIALS_URI: &str = "ALIBABA_CLOUD_CREDENTIALS_URI"; +pub const ALIBABA_CLOUD_ECS_METADATA: &str = "ALIBABA_CLOUD_ECS_METADATA"; +pub const ALIBABA_CLOUD_ECS_METADATA_DISABLED: &str = "ALIBABA_CLOUD_ECS_METADATA_DISABLED"; +pub const ALIBABA_CLOUD_ECS_METADATA_SERVICE_ENDPOINT: &str = + "ALIBABA_CLOUD_ECS_METADATA_SERVICE_ENDPOINT"; +pub const ALIBABA_CLOUD_IMDSV1_DISABLED: &str = "ALIBABA_CLOUD_IMDSV1_DISABLED"; pub const ALIBABA_CLOUD_ROLE_ARN: &str = "ALIBABA_CLOUD_ROLE_ARN"; pub const ALIBABA_CLOUD_ROLE_SESSION_NAME: &str = "ALIBABA_CLOUD_ROLE_SESSION_NAME"; + pub const ALIBABA_CLOUD_EXTERNAL_ID: &str = "ALIBABA_CLOUD_EXTERNAL_ID"; pub const ALIBABA_CLOUD_OIDC_PROVIDER_ARN: &str = "ALIBABA_CLOUD_OIDC_PROVIDER_ARN"; pub const ALIBABA_CLOUD_OIDC_TOKEN_FILE: &str = "ALIBABA_CLOUD_OIDC_TOKEN_FILE"; pub const ALIBABA_CLOUD_STS_ENDPOINT: &str = "ALIBABA_CLOUD_STS_ENDPOINT"; diff --cc services/aliyun-oss/src/lib.rs index 82168ca,b10a938..39c4f9d --- a/services/aliyun-oss/src/lib.rs +++ b/services/aliyun-oss/src/lib.rs @@@ -33,10 -33,10 +33,11 @@@ //! //! ```no_run //! use reqsign_aliyun_oss::{ - //! AssumeRoleWithOidcCredentialProvider, CredentialsUriCredentialProvider, + //! AssumeRoleCredentialProvider, AssumeRoleWithOidcCredentialProvider, -//! ConfigFileCredentialProvider, CredentialsFileCredentialProvider, DefaultCredentialProvider, -//! EnvCredentialProvider, OssProfileCredentialProvider, RequestSigner, -//! SigningVersion, StaticCredentialProvider, +//! ConfigFileCredentialProvider, CredentialsFileCredentialProvider, - //! DefaultCredentialProvider, EcsRamRoleCredentialProvider, EnvCredentialProvider, - //! OssProfileCredentialProvider, RequestSigner, StaticCredentialProvider, ++//! CredentialsUriCredentialProvider, DefaultCredentialProvider, ++//! EcsRamRoleCredentialProvider, EnvCredentialProvider, OssProfileCredentialProvider, ++//! RequestSigner, SigningVersion, StaticCredentialProvider, //! }; //! use reqsign_core::{Context, Signer, Result}; //! use reqsign_file_read_tokio::TokioFileRead; @@@ -49,10 -49,10 +50,11 @@@ //! .with_file_read(TokioFileRead::default()) //! .with_http_send(ReqwestHttpSend::default()); //! - //! // Create credential loader with the default env -> OSS profile -> - //! // shared credentials file -> config file -> credentials URI -> - //! // ECS RAM role -> oidc chain. + //! // Create credential loader with the default assume_role -> env -> -//! // OSS profile -> shared credentials file -> config file -> oidc chain. ++//! // OSS profile -> shared credentials file -> config file -> ++//! // credentials URI -> ECS RAM role -> oidc chain. //! let loader = DefaultCredentialProvider::builder() + //! .assume_role(AssumeRoleCredentialProvider::new()) //! .env(EnvCredentialProvider::new()) //! .oss_profile(OssProfileCredentialProvider::new()) //! .credentials_file(CredentialsFileCredentialProvider::new()) @@@ -106,13 -106,8 +110,17 @@@ //! The crate can load credentials from the OSS profile file //! (typically `~/.oss/credentials`). //! +//! ### Credentials URI +//! +//! The crate can load temporary credentials from +//! `ALIBABA_CLOUD_CREDENTIALS_URI`. +//! +//! ### ECS RAM Role +//! ++//! The crate can load temporary credentials from the ECS metadata service. ++//! + //! ### Alibaba Shared Credential and Config Files + //! //! The crate can also load static credentials from Alibaba shared SDK files //! (`~/.alibabacloud/credentials.ini`, `~/.aliyun/credentials.ini`) and the //! Alibaba CLI config file (`~/.aliyun/config.json`). @@@ -168,13 -163,18 +176,20 @@@ //! let loader = DefaultCredentialProvider::builder() //! .no_env() //! .no_oss_profile() +//! .no_credentials_uri() +//! .no_ecs_ram_role() //! .no_credentials_file() //! .no_config_file() - //! .oidc( - //! AssumeRoleWithOidcCredentialProvider::new().with_role_session_name("my-session"), + //! .assume_role( + //! AssumeRoleCredentialProvider::new() + //! .with_base_provider(StaticCredentialProvider::new( + //! "your-access-key-id", + //! "your-access-key-secret", + //! )) + //! .with_role_arn("acs:ram::123456789012:role/example") + //! .with_role_session_name("my-session"), //! ) + //! .no_oidc() //! .build(); //! ``` //! diff --cc services/aliyun-oss/src/provide_credential/default.rs index 871e1a1,9e8b1c0..cacc23e --- a/services/aliyun-oss/src/provide_credential/default.rs +++ b/services/aliyun-oss/src/provide_credential/default.rs @@@ -17,9 -17,9 +17,10 @@@ use crate::Credential; use crate::provide_credential::{ - AssumeRoleWithOidcCredentialProvider, ConfigFileCredentialProvider, - CredentialsFileCredentialProvider, CredentialsUriCredentialProvider, - EcsRamRoleCredentialProvider, EnvCredentialProvider, OssProfileCredentialProvider, + AssumeRoleCredentialProvider, AssumeRoleWithOidcCredentialProvider, - ConfigFileCredentialProvider, CredentialsFileCredentialProvider, EnvCredentialProvider, ++ ConfigFileCredentialProvider, CredentialsFileCredentialProvider, ++ CredentialsUriCredentialProvider, EcsRamRoleCredentialProvider, EnvCredentialProvider, + OssProfileCredentialProvider, }; use reqsign_core::{Context, ProvideCredential, ProvideCredentialChain, Result}; @@@ -27,13 -27,12 +28,14 @@@ /// /// Resolution order: /// - /// 1. Environment variables - /// 2. OSS profile file - /// 3. Alibaba shared credentials file - /// 4. Alibaba CLI config file - /// 5. Credentials URI - /// 6. ECS RAM role metadata - /// 7. Assume Role with OIDC + /// 1. AssumeRole via base AK credentials + /// 2. Environment variables + /// 3. OSS profile file + /// 4. Alibaba shared credentials file + /// 5. Alibaba CLI config file -/// 6. Assume Role with OIDC ++/// 6. Credentials URI ++/// 7. ECS RAM role metadata ++/// 8. Assume Role with OIDC #[derive(Debug)] pub struct DefaultCredentialProvider { chain: ProvideCredentialChain<Credential>, @@@ -88,10 -87,9 +90,11 @@@ impl DefaultCredentialProvider /// Use `slot(provider)` to override a default provider or `no_slot()` to /// remove it from the chain before calling `build()`. pub struct DefaultCredentialProviderBuilder { + assume_role: Option<AssumeRoleCredentialProvider>, env: Option<EnvCredentialProvider>, oss_profile: Option<OssProfileCredentialProvider>, + credentials_uri: Option<CredentialsUriCredentialProvider>, + ecs_ram_role: Option<EcsRamRoleCredentialProvider>, credentials_file: Option<CredentialsFileCredentialProvider>, config_file: Option<ConfigFileCredentialProvider>, oidc: Option<AssumeRoleWithOidcCredentialProvider>, @@@ -100,10 -98,9 +103,11 @@@ impl Default for DefaultCredentialProviderBuilder { fn default() -> Self { Self { + assume_role: Some(AssumeRoleCredentialProvider::new()), env: Some(EnvCredentialProvider::new()), oss_profile: Some(OssProfileCredentialProvider::new()), + credentials_uri: Some(CredentialsUriCredentialProvider::new()), + ecs_ram_role: Some(EcsRamRoleCredentialProvider::new()), credentials_file: Some(CredentialsFileCredentialProvider::new()), config_file: Some(ConfigFileCredentialProvider::new()), oidc: Some(AssumeRoleWithOidcCredentialProvider::new()), @@@ -573,10 -566,9 +621,11 @@@ access_key_secret=shared_secret_ke }); let credential = DefaultCredentialProvider::builder() + .no_assume_role() .no_env() .no_oss_profile() + .no_credentials_uri() + .no_ecs_ram_role() .no_oidc() .build() .provide_credential(&ctx) @@@ -1005,10 -773,9 +1058,11 @@@ }); let credential = DefaultCredentialProvider::builder() + .no_assume_role() .no_env() .no_oss_profile() + .no_credentials_uri() + .no_ecs_ram_role() .oidc(AssumeRoleWithOidcCredentialProvider::new()) .build() .provide_credential(&ctx) @@@ -1019,10 -786,9 +1073,11 @@@ assert_eq!(1, http_send.calls()); let credential = DefaultCredentialProvider::builder() + .no_assume_role() .no_env() .no_oss_profile() + .no_credentials_uri() + .no_ecs_ram_role() .no_oidc() .build() .provide_credential(&ctx)
