This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-rust.git
The following commit(s) were added to refs/heads/main by this push:
new e1426421 [core] Read s3.session-token with the same precedence as the
access key (#1156)
e1426421 is described below
commit e14264219ea51c0b07988e1eeabe02c4c693fdf8
Author: ump45nose <[email protected]>
AuthorDate: Mon Oct 19 20:13:52 2026 +0800
[core] Read s3.session-token with the same precedence as the access key
(#1156)
---
crates/paimon/src/io/storage_s3.rs | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/crates/paimon/src/io/storage_s3.rs
b/crates/paimon/src/io/storage_s3.rs
index 7aaaa0c3..96e4abaf 100644
--- a/crates/paimon/src/io/storage_s3.rs
+++ b/crates/paimon/src/io/storage_s3.rs
@@ -41,6 +41,11 @@ const S3_ACCESS_KEY: &str = "s3.access-key";
/// Compatible with paimon-java's `s3.secret-key` / `fs.s3a.secret.key`.
const S3_SECRET_KEY: &str = "s3.secret-key";
+/// Configuration key for S3 session token.
+///
+/// Compatible with paimon-java's `s3.session-token` / `fs.s3a.session.token`.
+const S3_SESSION_TOKEN: &str = "s3.session-token";
+
/// Configuration key for S3 path-style access.
///
/// When set to `true`, uses path-style URLs (`https://s3.endpoint/bucket`)
@@ -69,6 +74,7 @@ const JAVA_CONFIG_PREFIXES: &[&str] = &["fs.s3a.", "s3a.",
"s3."];
const KEY_ALIASES: &[(&str, &str)] = &[
("s3.access.key", "s3.access-key"),
("s3.secret.key", "s3.secret-key"),
+ ("s3.session.token", "s3.session-token"),
("s3.path.style.access", "s3.path-style-access"),
];
@@ -100,7 +106,7 @@ pub(crate) fn s3_config_parse(props: HashMap<String,
String>) -> Result<S3Config
cfg.region = normalized.get(S3_REGION).cloned();
// Session / assume-role credentials.
- cfg.session_token = normalized.get("s3.session.token").cloned();
+ cfg.session_token = normalized.get(S3_SESSION_TOKEN).cloned();
cfg.role_arn = normalized.get("s3.assumed.role.arn").cloned();
cfg.external_id = normalized.get("s3.assumed.role.externalId").cloned();
cfg.role_session_name =
normalized.get("s3.assumed.role.session.name").cloned();
@@ -280,6 +286,31 @@ mod tests {
assert_eq!(cfg.external_id.as_deref(), Some("ext-id"));
}
+ #[test]
+ fn test_s3_config_parse_session_token_follows_access_key_precedence() {
+ let props = make_props(&[
+ ("s3.access-key", "AK_A"),
+ ("s3.secret-key", "SK_A"),
+ ("s3.session-token", "TOKEN_A"),
+ ("fs.s3a.access.key", "AK_B"),
+ ("fs.s3a.secret.key", "SK_B"),
+ ("fs.s3a.session.token", "TOKEN_B"),
+ ]);
+
+ let cfg = s3_config_parse(props).unwrap();
+ assert_eq!(cfg.access_key_id.as_deref(), Some("AK_A"));
+ assert_eq!(cfg.secret_access_key.as_deref(), Some("SK_A"));
+ assert_eq!(cfg.session_token.as_deref(), Some("TOKEN_A"));
+ }
+
+ #[test]
+ fn test_s3_config_parse_hadoop_session_token() {
+ let props = make_props(&[("fs.s3a.session.token", "TOKEN")]);
+
+ let cfg = s3_config_parse(props).unwrap();
+ assert_eq!(cfg.session_token.as_deref(), Some("TOKEN"));
+ }
+
#[test]
fn test_s3_config_parse_sse() {
let props = make_props(&[("s3.sse.type", "aws:kms"), ("s3.sse.key",
"my-kms-key-id")]);