This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 7604a83ec8 [Feature][Zeta] Support environment-variable object storage 
credential (#12885)
7604a83ec8 is described below

commit 7604a83ec802a0b148e98e557fb9184c48127988
Author: zhiweiniu <[email protected]>
AuthorDate: Sun Oct 25 05:34:13 2026 +0000

    [Feature][Zeta] Support environment-variable object storage credential 
(#12885)
---
 docs/en/engines/zeta/checkpoint-storage.md         |  63 ++++++
 docs/en/engines/zeta/hybrid-cluster-deployment.md  |  21 +-
 .../engines/zeta/separated-cluster-deployment.md   |  21 +-
 docs/en/engines/zeta/state-storage-and-recovery.md |   2 +
 .../en/getting-started/kubernetes/configuration.md |  66 ++++++-
 docs/zh/engines/zeta/checkpoint-storage.md         |  57 ++++++
 docs/zh/engines/zeta/hybrid-cluster-deployment.md  |  16 +-
 .../engines/zeta/separated-cluster-deployment.md   |  16 +-
 docs/zh/engines/zeta/state-storage-and-recovery.md |   2 +
 .../zh/getting-started/kubernetes/configuration.md |  66 ++++++-
 .../checkpoint-storage-hdfs/pom.xml                |  17 +-
 .../EnvironmentCredentialConfigurationTest.java    | 220 +++++++++++++++++++++
 .../imap-storage-plugins/imap-storage-file/pom.xml |  13 +-
 .../EnvironmentCredentialConfigurationTest.java    | 130 ++++++++++++
 14 files changed, 683 insertions(+), 27 deletions(-)

diff --git a/docs/en/engines/zeta/checkpoint-storage.md 
b/docs/en/engines/zeta/checkpoint-storage.md
index b3db813485..d366382f62 100644
--- a/docs/en/engines/zeta/checkpoint-storage.md
+++ b/docs/en/engines/zeta/checkpoint-storage.md
@@ -43,6 +43,27 @@ seatunnel:
 
 Notice: namespace must end with "/".
 
+#### Credentials from environment variables
+
+Object storage credentials can be supplied by the cloud SDK from environment 
variables. Set
+the corresponding credential provider key and do not put static access keys or 
secret keys in
+`seatunnel.yaml`:
+
+| `storage.type` | Credential provider key | Provider class | Environment 
variables |
+| --- | --- | --- | --- |
+| `s3` | `fs.s3a.aws.credentials.provider` | 
`com.amazonaws.auth.EnvironmentVariableCredentialsProvider` | 
`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, optional `AWS_SESSION_TOKEN` |
+| `oss` | `fs.oss.credentials.provider` | 
`com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider` | 
`OSS_ACCESS_KEY_ID`, `OSS_ACCESS_KEY_SECRET`, optional `OSS_SESSION_TOKEN` |
+| `cos` | `fs.cosn.credentials.provider` | 
`org.apache.hadoop.fs.cosn.auth.EnvironmentVariableCredentialsProvider` | 
`COSN_SECRET_ID`, `COSN_SECRET_KEY` |
+
+The environment variables and provider implementations are fixed by the 
underlying Hadoop
+filesystem and cloud SDK. Inject the variables into every SeaTunnel process 
that accesses
+checkpoint storage. Existing static credential and cloud-native identity 
configurations remain
+supported.
+
+GCS uses Application Default Credentials instead of a credential provider key. 
Configure
+`GOOGLE_APPLICATION_CREDENTIALS` with a mounted key file when needed, or rely 
on Workload Identity
+and other ADC mechanisms.
+
 #### OSS
 
 Aliyun OSS based hdfs-file you can refer [Hadoop OSS 
Docs](https://hadoop.apache.org/docs/stable/hadoop-aliyun/tools/hadoop-aliyun/index.html)
 to config oss.
@@ -70,6 +91,24 @@ seatunnel:
           fs.oss.endpoint: endpoint address
 ```
 
+To use credentials from environment variables, remove `fs.oss.accessKeyId` and
+`fs.oss.accessKeySecret` and select the environment variable provider. 
`OSS_ACCESS_KEY_ID` and
+`OSS_ACCESS_KEY_SECRET` must be available to every master and worker:
+
+```yaml
+seatunnel:
+  engine:
+    checkpoint:
+      storage:
+        type: hdfs
+        plugin-config:
+          namespace: /seatunnel/checkpoint/
+          storage.type: oss
+          oss.bucket: oss://your-bucket
+          fs.oss.endpoint: oss-cn-hangzhou.aliyuncs.com
+          fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
 For additional reading on the Hadoop Credential Provider API, you can see: 
[Credential Provider 
API](https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html).
 
 For Aliyun OSS Credential Provider implements, you can see: [Auth Credential 
Providers](https://github.com/aliyun/aliyun-oss-java-sdk/tree/master/src/main/java/com/aliyun/oss/common/auth)
@@ -102,6 +141,18 @@ seatunnel:
           fs.cosn.bucket.region: your-region
 ```
 
+To use credentials from environment variables, remove the static `secretId` 
and `secretKey`
+entries and configure:
+
+```yaml
+          storage.type: cos
+          cos.bucket: cosn://your-bucket
+          fs.cosn.bucket.region: your-region
+          fs.cosn.credentials.provider: 
org.apache.hadoop.fs.cosn.auth.EnvironmentVariableCredentialsProvider
+```
+
+`COSN_SECRET_ID` and `COSN_SECRET_KEY` must be available to every master and 
worker.
+
 For additional reading on the Hadoop Credential Provider API, you can see: 
[Credential Provider 
API](https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html).
 
 For additional COS configuration, you can see: [Tencent Hadoop-COS 
Docs](https://doc.fincloud.tencent.cn/tcloud/Storage/COS/846365/hadoop)
@@ -188,6 +239,18 @@ seatunnel:
 
 ```
 
+To read credentials from environment variables instead, remove 
`fs.s3a.access.key` and
+`fs.s3a.secret.key` and configure:
+
+```yaml
+                  storage.type: s3
+                  s3.bucket: s3a://your-bucket
+                  fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider
+```
+
+`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` must be available to every 
master and worker.
+Temporary credentials additionally use `AWS_SESSION_TOKEN`.
+
 If you used `InstanceProfileCredentialsProvider`, which supports use of 
instance profile credentials if running in an EC2 VM, you can check 
[iam-roles-for-amazon-ec2](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html).
 You can config like this:
 
diff --git a/docs/en/engines/zeta/hybrid-cluster-deployment.md 
b/docs/en/engines/zeta/hybrid-cluster-deployment.md
index e6cb31935d..abf1489d11 100644
--- a/docs/en/engines/zeta/hybrid-cluster-deployment.md
+++ b/docs/en/engines/zeta/hybrid-cluster-deployment.md
@@ -364,14 +364,24 @@ map:
            fs.oss.endpoint: OSS endpoint
 ```
 
+To use OSS credentials from environment variables, remove `fs.oss.accessKeyId` 
and
+`fs.oss.accessKeySecret` and add:
+
+```yaml
+           fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+The provider reads `OSS_ACCESS_KEY_ID` and `OSS_ACCESS_KEY_SECRET`, plus 
optional
+`OSS_SESSION_TOKEN`.
+
 Notice: When using OSS, make sure that the following jars are in the lib 
directory.
 
 The `seatunnel-shade-hadoop3-uber` JAR comes from the [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) project, which provides a 
shaded (package-relocated) version of the Hadoop client. All third-party 
classes are relocated under `org.apache.seatunnel.shade.*` to avoid classpath 
conflicts with SeaTunnel's own dependencies. The version follows the 
`${library.version}-${seatunnel.shade.version}` format (e.g., `3.1.4-3.0.0`). 
Refer to the actual JAR file name in your SeaT [...]
 
 ```
-aliyun-sdk-oss-3.13.2.jar
-hadoop-aliyun-3.3.6.jar
-jdom2-2.0.6.jar
+aliyun-sdk-oss-3.4.1.jar
+hadoop-aliyun-3.1.4.jar
+jdom-1.1.jar
 netty-buffer-4.1.89.Final.jar
 netty-common-4.1.89.Final.jar
 
seatunnel-shade-hadoop3-uber-${seatunnel.shade.hadoop.version}-${seatunnel.shade.version}.jar
@@ -405,6 +415,11 @@ map:
          fs.s3a.aws.credentials.provider: 
org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider
 ```
 
+For environment-variable credentials, remove `fs.s3a.access.key` and 
`fs.s3a.secret.key` and use
+`fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider`.
+The provider reads `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, plus 
optional
+`AWS_SESSION_TOKEN`.
+
 Notice: When using S3, make sure that the following jars are in the lib 
directory.
 
 Both JARs come from the [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) project:
diff --git a/docs/en/engines/zeta/separated-cluster-deployment.md 
b/docs/en/engines/zeta/separated-cluster-deployment.md
index a04d6f8074..6eee00d7c7 100644
--- a/docs/en/engines/zeta/separated-cluster-deployment.md
+++ b/docs/en/engines/zeta/separated-cluster-deployment.md
@@ -316,14 +316,24 @@ map:
         fs.oss.endpoint: OSS endpoint
 ```
 
+To use OSS credentials from environment variables, remove `fs.oss.accessKeyId` 
and
+`fs.oss.accessKeySecret` and add:
+
+```yaml
+        fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+The provider reads `OSS_ACCESS_KEY_ID` and `OSS_ACCESS_KEY_SECRET`, plus 
optional
+`OSS_SESSION_TOKEN`.
+
 Notice: When using OSS, make sure that the following jars are in the lib 
directory.
 
 The `seatunnel-shade-hadoop3-uber` JAR comes from the [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) project, which provides a 
shaded (package-relocated) version of the Hadoop client. All third-party 
classes are relocated under `org.apache.seatunnel.shade.*` to avoid classpath 
conflicts with SeaTunnel's own dependencies. The version follows the 
`${library.version}-${seatunnel.shade.version}` format (e.g., `3.1.4-3.0.0`). 
Refer to the actual JAR file name in your SeaT [...]
 
 ```
-aliyun-sdk-oss-3.13.2.jar
-hadoop-aliyun-3.3.6.jar
-jdom2-2.0.6.jar
+aliyun-sdk-oss-3.4.1.jar
+hadoop-aliyun-3.1.4.jar
+jdom-1.1.jar
 netty-buffer-4.1.89.Final.jar
 netty-common-4.1.89.Final.jar
 
seatunnel-shade-hadoop3-uber-${seatunnel.shade.hadoop.version}-${seatunnel.shade.version}.jar
@@ -356,6 +366,11 @@ map:
          fs.s3a.aws.credentials.provider: 
org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider
 ```
 
+For environment-variable credentials, remove `fs.s3a.access.key` and 
`fs.s3a.secret.key` and use
+`fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider`.
+The provider reads `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, plus 
optional
+`AWS_SESSION_TOKEN`.
+
 Notice: When using S3, make sure that the following jars are in the lib 
directory.
 
 Both JARs come from the [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) project:
diff --git a/docs/en/engines/zeta/state-storage-and-recovery.md 
b/docs/en/engines/zeta/state-storage-and-recovery.md
index 526fd50b0b..b0a7460cb1 100644
--- a/docs/en/engines/zeta/state-storage-and-recovery.md
+++ b/docs/en/engines/zeta/state-storage-and-recovery.md
@@ -60,6 +60,8 @@ seatunnel:
           # fs.s3a.endpoint: https://s3.amazonaws.com
           # fs.s3a.access.key: <your-access-key>
           # fs.s3a.secret.key: <your-secret-key>
+          # Environment credentials:
+          # fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider
 ```
 
 ### Checkpoint retention and cleanup
diff --git a/docs/en/getting-started/kubernetes/configuration.md 
b/docs/en/getting-started/kubernetes/configuration.md
index f3faa557d5..94a9888866 100644
--- a/docs/en/getting-started/kubernetes/configuration.md
+++ b/docs/en/getting-started/kubernetes/configuration.md
@@ -283,7 +283,20 @@ properties:
 
 Alibaba Cloud OSS uses Hadoop OSS configuration and selects the target bucket 
with `oss.bucket`. Set `fs.oss.endpoint` to the actual endpoint of the bucket 
region, private cloud, or OSS-compatible service.
 
-The default Hadoop Aliyun OSS credential provider reads `fs.oss.accessKeyId` 
and `fs.oss.accessKeySecret`. Temporary credentials can additionally set 
`fs.oss.securityToken`. It does not provide a default environment-variable 
credential chain like Hadoop S3A, so credentials injected from Kubernetes 
Secret as environment variables are not used automatically.
+The default Hadoop Aliyun OSS credential provider reads `fs.oss.accessKeyId` 
and `fs.oss.accessKeySecret`. Temporary credentials can additionally set 
`fs.oss.securityToken`. To read credentials from environment variables and 
avoid rendering them into the ConfigMap, select the OSS SDK environment 
variable provider:
+
+```yaml
+properties:
+  type: hdfs
+  namespace: /seatunnel/imap
+  clusterName: seatunnel-cluster
+  storage.type: oss
+  oss.bucket: oss://seatunnel-bucket
+  fs.oss.endpoint: https://oss-<region>.aliyuncs.com
+  fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+The provider reads the fixed environment variables `OSS_ACCESS_KEY_ID` and 
`OSS_ACCESS_KEY_SECRET`, plus `OSS_SESSION_TOKEN` for temporary credentials. 
Inject them into every Master and Worker Pod.
 
 ```yaml
 hazelcast:
@@ -304,12 +317,59 @@ hazelcast:
           fs.oss.accessKeySecret: YOUR_ACCESS_KEY_SECRET
 ```
 
-If you do not want to render OSS credentials into the final ConfigMap, use 
Hadoop credential provider for `fs.oss.accessKeyId` and 
`fs.oss.accessKeySecret`, or set `fs.oss.credentials.provider` to a custom 
provider. The custom provider must implement the Aliyun OSS SDK 
`com.aliyun.oss.common.auth.CredentialsProvider` interface and must be 
available in the SeaTunnel image.
+If you do not want to render OSS credentials into the final ConfigMap, use the 
environment variable provider shown above, a Hadoop credential provider, or a 
custom `fs.oss.credentials.provider` implementation. A custom provider must 
implement the Aliyun OSS SDK `com.aliyun.oss.common.auth.CredentialsProvider` 
interface and must be available in the SeaTunnel image.
+
+#### Inject credentials from Kubernetes Secrets
+
+Kubernetes injects Secret values into the container process environment when 
the Pod starts. The values are not written to the Docker image, and SeaTunnel 
does not need a Dockerfile `ENV` entry. Inject the credentials into every 
Master and Worker container that can access checkpoint or IMap storage.
+
+If the Secret keys already use the fixed provider variable names, use 
`envFrom`:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+  name: seatunnel-oss-credentials
+type: Opaque
+stringData:
+  OSS_ACCESS_KEY_ID: your-access-key
+  OSS_ACCESS_KEY_SECRET: your-secret-key
+  OSS_SESSION_TOKEN: your-session-token # omit for permanent credentials
+---
+spec:
+  template:
+    spec:
+      containers:
+        - name: seatunnel
+          envFrom:
+            - secretRef:
+                name: seatunnel-oss-credentials
+```
+
+If the Secret uses different key names, map them explicitly so the provider 
receives the fixed names:
+
+```yaml
+containers:
+  - name: seatunnel
+    env:
+      - name: OSS_ACCESS_KEY_ID
+        valueFrom:
+          secretKeyRef:
+            name: seatunnel-oss-credentials
+            key: access-key
+      - name: OSS_ACCESS_KEY_SECRET
+        valueFrom:
+          secretKeyRef:
+            name: seatunnel-oss-credentials
+            key: secret-key
+```
+
+Do not set a prefix on `envFrom`, because the provider expects the exact 
variable names shown above. Environment variables in a running container do not 
update when the Secret changes; restart or roll out the StatefulSet after 
rotating credentials.
 
 When `backup-count: 1` is used, at least 2 Master replicas are required to 
store IMap backup replicas.
 
 :::caution Warning
-Do not commit real access keys or secret keys to ConfigMaps or Git 
repositories. Kubernetes does not resolve `secretKeyRef` inside ConfigMap file 
content. SeaTunnel and Hazelcast must read a final, usable YAML configuration. 
In production, generate the final ConfigMap through Helm, Kustomize, External 
Secrets, CI/CD, or the image build process, or use credential mechanisms 
actually supported by the underlying filesystem, such as Hadoop credential 
provider, AWS SDK environment variable pr [...]
+Do not commit real access keys or secret keys to ConfigMaps or Git 
repositories. Kubernetes does not resolve `secretKeyRef` inside ConfigMap file 
content. SeaTunnel and Hazelcast must read a final, usable YAML configuration. 
In production, generate the final ConfigMap through Helm, Kustomize, External 
Secrets, CI/CD, or the image build process, or use credential mechanisms 
actually supported by the underlying filesystem, such as Hadoop credential 
provider, AWS SDK environment variable pr [...]
 :::
 
 When S3 or OSS is used, the SeaTunnel image must also contain the 
corresponding Hadoop filesystem implementation and dependencies, such as Hadoop 
AWS/AWS SDK or Hadoop Aliyun/OSS SDK. Checkpoint storage and IMap MapStore can 
use the same object storage service, but use different `namespace` prefixes, 
for example `/seatunnel/checkpoint/` and `/seatunnel/imap`.
diff --git a/docs/zh/engines/zeta/checkpoint-storage.md 
b/docs/zh/engines/zeta/checkpoint-storage.md
index 4e87f108a4..b1f58ade27 100644
--- a/docs/zh/engines/zeta/checkpoint-storage.md
+++ b/docs/zh/engines/zeta/checkpoint-storage.md
@@ -41,6 +41,23 @@ seatunnel:
 
 注意: namespace必须以"/"结尾。
 
+#### 使用环境变量提供凭据
+
+对象存储凭据可以由云 SDK 从环境变量读取。配置对应的凭据 Provider,并且不要在
+`seatunnel.yaml` 中写入 Access Key 或 Secret Key:
+
+| `storage.type` | 凭据 Provider 配置项 | Provider 类 | 环境变量 |
+| --- | --- | --- | --- |
+| `s3` | `fs.s3a.aws.credentials.provider` | 
`com.amazonaws.auth.EnvironmentVariableCredentialsProvider` | 
`AWS_ACCESS_KEY_ID`、`AWS_SECRET_ACCESS_KEY`,临时凭据可选 `AWS_SESSION_TOKEN` |
+| `oss` | `fs.oss.credentials.provider` | 
`com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider` | 
`OSS_ACCESS_KEY_ID`、`OSS_ACCESS_KEY_SECRET`,临时凭据可选 `OSS_SESSION_TOKEN` |
+| `cos` | `fs.cosn.credentials.provider` | 
`org.apache.hadoop.fs.cosn.auth.EnvironmentVariableCredentialsProvider` | 
`COSN_SECRET_ID`、`COSN_SECRET_KEY` |
+
+环境变量名和 Provider 实现由底层 Hadoop 文件系统和云 SDK 固定。请将环境变量注入所有访问
+检查点存储的 SeaTunnel 进程。原有的静态凭据和云平台原生身份认证方式仍然兼容。
+
+GCS 不使用上述凭据 Provider 配置项,而是使用 Application Default Credentials。需要密钥文件时
+可设置 `GOOGLE_APPLICATION_CREDENTIALS`,也可以使用 Workload Identity 等 ADC 机制。
+
 #### OSS
 
 阿里云OSS是基于hdfs-file,所以你可以参考[Hadoop 
OSS文档](https://hadoop.apache.org/docs/stable/hadoop-aliyun/tools/hadoop-aliyun/index.html)来配置oss.
@@ -68,6 +85,24 @@ seatunnel:
           fs.oss.endpoint: endpoint address
 ```
 
+如果要使用环境变量提供凭据,请删除 `fs.oss.accessKeyId` 和 `fs.oss.accessKeySecret`,并选择
+环境变量 Provider。`OSS_ACCESS_KEY_ID` 和 `OSS_ACCESS_KEY_SECRET` 必须对所有 master 和
+worker 可见:
+
+```yaml
+seatunnel:
+  engine:
+    checkpoint:
+      storage:
+        type: hdfs
+        plugin-config:
+          namespace: /seatunnel/checkpoint/
+          storage.type: oss
+          oss.bucket: oss://your-bucket
+          fs.oss.endpoint: oss-cn-hangzhou.aliyuncs.com
+          fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
 有关Hadoop Credential Provider API的更多信息,请参见: [Credential Provider 
API](https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html).
 
 阿里云OSS凭证提供程序实现见: 
[验证凭证提供](https://github.com/aliyun/aliyun-oss-java-sdk/tree/master/src/main/java/com/aliyun/oss/common/auth)
@@ -100,6 +135,17 @@ seatunnel:
           fs.cosn.bucket.region: your-region
 ```
 
+如果要使用环境变量提供凭据,请删除静态的 `secretId` 和 `secretKey`,并配置:
+
+```yaml
+          storage.type: cos
+          cos.bucket: cosn://your-bucket
+          fs.cosn.bucket.region: your-region
+          fs.cosn.credentials.provider: 
org.apache.hadoop.fs.cosn.auth.EnvironmentVariableCredentialsProvider
+```
+
+`COSN_SECRET_ID` 和 `COSN_SECRET_KEY` 必须对所有 master 和 worker 可见。
+
 有关Hadoop Credential Provider API的更多信息,请参见: [Credential Provider 
API](https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/CredentialProviderAPI.html).
 
 腾讯云COS相关配置可参考:[Tencent 
Hadoop-COS文档](https://doc.fincloud.tencent.cn/tcloud/Storage/COS/846365/hadoop)
@@ -186,6 +232,17 @@ seatunnel:
 
 ```
 
+如果要从环境变量读取凭据,请删除 `fs.s3a.access.key` 和 `fs.s3a.secret.key`,并配置:
+
+```yaml
+                  storage.type: s3
+                  s3.bucket: s3a://your-bucket
+                  fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider
+```
+
+`AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 必须对所有 master 和 worker 可见;使用临时
+凭据时还需要配置 `AWS_SESSION_TOKEN`。
+
 如果您使用`InstanceProfileCredentialsProvider`,它支持在EC2 
VM中运行时使用实例配置文件凭据,您可以检查[iam-roles-for-amazon-ec2](https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html).
 您可以这样配置:
 
diff --git a/docs/zh/engines/zeta/hybrid-cluster-deployment.md 
b/docs/zh/engines/zeta/hybrid-cluster-deployment.md
index 72c1cbeba4..8cac9840a8 100644
--- a/docs/zh/engines/zeta/hybrid-cluster-deployment.md
+++ b/docs/zh/engines/zeta/hybrid-cluster-deployment.md
@@ -360,14 +360,24 @@ map:
            fs.oss.endpoint: OSS endpoint
 ```
 
+如果要通过环境变量提供 OSS 凭据,请删除 `fs.oss.accessKeyId` 和
+`fs.oss.accessKeySecret`,并增加:
+
+```yaml
+           fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+该 Provider 读取 `OSS_ACCESS_KEY_ID` 和 `OSS_ACCESS_KEY_SECRET`,临时凭据还可使用
+`OSS_SESSION_TOKEN`。
+
 注意:使用OSS 时,确保 lib目录下有这几个jar。
 
 其中 `seatunnel-shade-hadoop3-uber` 来自 [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) 项目,它是对 Hadoop 客户端的 
shaded(包重定位)版本,所有第三方类被重定位到 `org.apache.seatunnel.shade.*` 下,避免与 SeaTunnel 
自身的依赖产生类路径冲突。版本号格式为 `${library.version}-${seatunnel.shade.version}`(例如 
`3.1.4-3.0.0`),具体版本请参考 SeaTunnel 发行包中实际包含的 JAR 文件名。
 
 ```
-aliyun-sdk-oss-3.13.2.jar
-hadoop-aliyun-3.3.6.jar
-jdom2-2.0.6.jar
+aliyun-sdk-oss-3.4.1.jar
+hadoop-aliyun-3.1.4.jar
+jdom-1.1.jar
 netty-buffer-4.1.89.Final.jar
 netty-common-4.1.89.Final.jar
 
seatunnel-shade-hadoop3-uber-${seatunnel.shade.hadoop.version}-${seatunnel.shade.version}.jar
diff --git a/docs/zh/engines/zeta/separated-cluster-deployment.md 
b/docs/zh/engines/zeta/separated-cluster-deployment.md
index 2930dacf06..ed0300d5cf 100644
--- a/docs/zh/engines/zeta/separated-cluster-deployment.md
+++ b/docs/zh/engines/zeta/separated-cluster-deployment.md
@@ -321,14 +321,24 @@ map:
         fs.oss.endpoint: OSS endpoint
 ```
 
+如果要通过环境变量提供 OSS 凭据,请删除 `fs.oss.accessKeyId` 和
+`fs.oss.accessKeySecret`,并增加:
+
+```yaml
+        fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+该 Provider 读取 `OSS_ACCESS_KEY_ID` 和 `OSS_ACCESS_KEY_SECRET`,临时凭据还可使用
+`OSS_SESSION_TOKEN`。
+
 注意:使用OSS 时,确保 lib目录下有这几个jar。
 
 其中 `seatunnel-shade-hadoop3-uber` 来自 [Apache SeaTunnel 
Shade](https://github.com/apache/seatunnel-shade) 项目,它是对 Hadoop 客户端的 
shaded(包重定位)版本,所有第三方类被重定位到 `org.apache.seatunnel.shade.*` 下,避免与 SeaTunnel 
自身的依赖产生类路径冲突。版本号格式为 `${library.version}-${seatunnel.shade.version}`(例如 
`3.1.4-3.0.0`),具体版本请参考 SeaTunnel 发行包中实际包含的 JAR 文件名。
 
 ```
-aliyun-sdk-oss-3.13.2.jar
-hadoop-aliyun-3.3.6.jar
-jdom2-2.0.6.jar
+aliyun-sdk-oss-3.4.1.jar
+hadoop-aliyun-3.1.4.jar
+jdom-1.1.jar
 netty-buffer-4.1.89.Final.jar
 netty-common-4.1.89.Final.jar
 
seatunnel-shade-hadoop3-uber-${seatunnel.shade.hadoop.version}-${seatunnel.shade.version}.jar
diff --git a/docs/zh/engines/zeta/state-storage-and-recovery.md 
b/docs/zh/engines/zeta/state-storage-and-recovery.md
index 5eba3601dd..840dd109f0 100644
--- a/docs/zh/engines/zeta/state-storage-and-recovery.md
+++ b/docs/zh/engines/zeta/state-storage-and-recovery.md
@@ -58,6 +58,8 @@ seatunnel:
           # fs.s3a.endpoint: https://s3.amazonaws.com
           # fs.s3a.access.key: <your-access-key>
           # fs.s3a.secret.key: <your-secret-key>
+          # 环境变量凭据:
+          # fs.s3a.aws.credentials.provider: 
com.amazonaws.auth.EnvironmentVariableCredentialsProvider
 ```
 
 ### Checkpoint 保留与清理
diff --git a/docs/zh/getting-started/kubernetes/configuration.md 
b/docs/zh/getting-started/kubernetes/configuration.md
index 426b67994c..35a1e210df 100644
--- a/docs/zh/getting-started/kubernetes/configuration.md
+++ b/docs/zh/getting-started/kubernetes/configuration.md
@@ -283,7 +283,20 @@ properties:
 
 阿里云 OSS 使用 Hadoop OSS 配置,并通过 `oss.bucket` 指定目标 bucket。`fs.oss.endpoint` 需要按 
bucket 所在地域、专有云或兼容 OSS 服务的实际地址填写。
 
-Hadoop Aliyun OSS 的默认凭据 provider 读取 
`fs.oss.accessKeyId`、`fs.oss.accessKeySecret`,临时凭据可额外配置 
`fs.oss.securityToken`。它没有像 Hadoop S3A 一样的默认环境变量认证链,因此 Kubernetes Secret 
注入成环境变量后不会自动生效。
+Hadoop Aliyun OSS 的默认凭据 provider 读取 
`fs.oss.accessKeyId`、`fs.oss.accessKeySecret`,临时凭据可额外配置 
`fs.oss.securityToken`。如果要从环境变量读取凭据并且不把凭据渲染到 ConfigMap 中,可以选择 OSS SDK 的环境变量 
provider:
+
+```yaml
+properties:
+  type: hdfs
+  namespace: /seatunnel/imap
+  clusterName: seatunnel-cluster
+  storage.type: oss
+  oss.bucket: oss://seatunnel-bucket
+  fs.oss.endpoint: https://oss-<region>.aliyuncs.com
+  fs.oss.credentials.provider: 
com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider
+```
+
+该 provider 固定读取环境变量 `OSS_ACCESS_KEY_ID` 和 `OSS_ACCESS_KEY_SECRET`,使用临时凭据时还会读取 
`OSS_SESSION_TOKEN`。请将这些变量注入每个 Master 和 Worker Pod。
 
 ```yaml
 hazelcast:
@@ -304,12 +317,59 @@ hazelcast:
           fs.oss.accessKeySecret: YOUR_ACCESS_KEY_SECRET
 ```
 
-如果不希望把 OSS 凭据渲染到最终 ConfigMap,可以使用 Hadoop credential provider 存储 
`fs.oss.accessKeyId`、`fs.oss.accessKeySecret`,或通过 `fs.oss.credentials.provider` 
指定自定义 provider。自定义 provider 需要实现 Aliyun OSS SDK 的 
`com.aliyun.oss.common.auth.CredentialsProvider`,并在 SeaTunnel 镜像中可被加载。
+如果不希望把 OSS 凭据渲染到最终 ConfigMap,可以使用上面的环境变量 provider、Hadoop credential 
provider,或通过 `fs.oss.credentials.provider` 指定自定义 provider。自定义 provider 需要实现 
Aliyun OSS SDK 的 `com.aliyun.oss.common.auth.CredentialsProvider`,并在 SeaTunnel 
镜像中可被加载。
+
+#### 从 Kubernetes Secret 注入凭据
+
+Kubernetes 会在 Pod 启动时将 Secret 的值注入容器进程的环境变量。凭据不会写入 Docker 镜像,也不需要配置 Dockerfile 
的 `ENV`。需要为所有可能访问检查点或 IMap 存储的 Master 和 Worker 容器注入凭据。
+
+如果 Secret 的 key 已经使用固定的环境变量名,可以直接使用 `envFrom`:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+  name: seatunnel-oss-credentials
+type: Opaque
+stringData:
+  OSS_ACCESS_KEY_ID: your-access-key
+  OSS_ACCESS_KEY_SECRET: your-secret-key
+  OSS_SESSION_TOKEN: your-session-token # 永久凭据不需要这一项
+---
+spec:
+  template:
+    spec:
+      containers:
+        - name: seatunnel
+          envFrom:
+            - secretRef:
+                name: seatunnel-oss-credentials
+```
+
+如果 Secret 使用了其他 key 名称,需要显式映射为 Provider 要求的固定变量名:
+
+```yaml
+containers:
+  - name: seatunnel
+    env:
+      - name: OSS_ACCESS_KEY_ID
+        valueFrom:
+          secretKeyRef:
+            name: seatunnel-oss-credentials
+            key: access-key
+      - name: OSS_ACCESS_KEY_SECRET
+        valueFrom:
+          secretKeyRef:
+            name: seatunnel-oss-credentials
+            key: secret-key
+```
+
+不要给 `envFrom` 设置 `prefix`,因为 Provider 只会读取上面列出的固定变量名。Secret 
更新后,运行中容器的环境变量不会自动变化;轮换凭据后需要重启或触发 StatefulSet 滚动更新。
 
 `backup-count: 1` 时,Master 至少需要 2 个副本,才能保存 IMap 备份副本。
 
 :::caution 注意
-不要把真实 access key、secret key 直接提交到 ConfigMap 或 Git 仓库。Kubernetes 不会在 ConfigMap 
文件内容中解析 `secretKeyRef`,SeaTunnel/Hazelcast 读取到的必须是最终可用的 YAML 配置。生产环境建议通过 
Helm、Kustomize、External Secrets、CI/CD 或镜像构建流程生成最终 ConfigMap,或者使用 Hadoop 
credential provider、AWS SDK 环境变量 provider、云厂商凭据链、挂载凭据文件等底层文件系统真正支持的凭据方式,并确保所有 
Master Pod 具有相同的对象存储读写权限。
+不要把真实 access key、secret key 直接提交到 ConfigMap 或 Git 仓库。Kubernetes 不会在 ConfigMap 
文件内容中解析 `secretKeyRef`,SeaTunnel/Hazelcast 读取到的必须是最终可用的 YAML 配置。生产环境建议通过 
Helm、Kustomize、External Secrets、CI/CD 或镜像构建流程生成最终 ConfigMap,或者使用 Hadoop 
credential provider、AWS SDK 环境变量 provider、云厂商凭据链、挂载凭据文件等底层文件系统真正支持的凭据方式,并确保所有 
Master 和 Worker Pod 具有相同的对象存储读写权限。
 :::
 
 如果使用 S3 或 OSS,SeaTunnel 镜像中还需要包含对应 Hadoop 文件系统实现及其依赖,例如 Hadoop AWS/AWS SDK 或 
Hadoop Aliyun/OSS SDK。Checkpoint 存储和 IMap MapStore 可以使用同一个对象存储服务,但建议使用不同的 
`namespace` 前缀,例如 `/seatunnel/checkpoint/` 和 `/seatunnel/imap`。
diff --git 
a/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/pom.xml
 
b/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/pom.xml
index 6ff5eb0915..fc437af994 100644
--- 
a/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/pom.xml
+++ 
b/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/pom.xml
@@ -31,7 +31,10 @@
     <name>SeaTunnel : Engine : Storage : Checkpoint Storage Plugins : 
HDFS</name>
 
     <properties>
-        <hadoop-aliyun.version>3.0.0</hadoop-aliyun.version>
+        <hadoop-aliyun.version>3.1.4</hadoop-aliyun.version>
+        <hadoop-cos.version>3.4.1</hadoop-cos.version>
+        <aws-java-sdk.version>1.11.271</aws-java-sdk.version>
+        <aliyun.sdk.oss.version>3.4.1</aliyun.sdk.oss.version>
     </properties>
 
     <dependencies>
@@ -50,19 +53,25 @@
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-aws</artifactId>
-            <version>3.1.4</version>
+            <version>${hadoop-aws.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>com.amazonaws</groupId>
             <artifactId>aws-java-sdk-bundle</artifactId>
-            <version>1.11.271</version>
+            <version>${aws-java-sdk.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-cos</artifactId>
-            <version>3.4.1</version>
+            <version>${hadoop-cos.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.sdk.oss.version}</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
diff --git 
a/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/src/test/java/org/apache/seatunnel/engine/checkpoint/storage/hdfs/common/EnvironmentCredentialConfigurationTest.java
 
b/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/src/test/java/org/apache/seatunnel/engine/checkpoint/storage/hdfs/common/EnvironmentCredentialConfigurationTest.java
new file mode 100644
index 0000000000..c3cde70e4b
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-storage/checkpoint-storage-plugins/checkpoint-storage-hdfs/src/test/java/org/apache/seatunnel/engine/checkpoint/storage/hdfs/common/EnvironmentCredentialConfigurationTest.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.seatunnel.engine.checkpoint.storage.hdfs.common;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.aliyun.oss.AliyunOSSUtils;
+import org.apache.hadoop.fs.cosn.CosNUtils;
+import org.apache.hadoop.fs.s3a.AWSCredentialProviderList;
+import org.apache.hadoop.fs.s3a.S3AUtils;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+import org.junit.jupiter.api.parallel.ResourceLock;
+
+import com.aliyun.oss.common.auth.Credentials;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
+import com.amazonaws.auth.AWSSessionCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static 
com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
+
+/**
+ * Tests mutate process-wide environment variables through {@code 
SystemLambda}. {@code SAME_THREAD}
+ * keeps the methods in this class sequential, and the shared resource lock 
keeps other environment-
+ * mutating test classes from running concurrently.
+ */
+@Execution(ExecutionMode.SAME_THREAD)
+@ResourceLock("system-environment")
+public class EnvironmentCredentialConfigurationTest {
+
+    private static final String S3_PROVIDER_KEY = 
"fs.s3a.aws.credentials.provider";
+    private static final String S3_ENV_PROVIDER =
+            "com.amazonaws.auth.EnvironmentVariableCredentialsProvider";
+
+    private static final String OSS_PROVIDER_KEY = 
"fs.oss.credentials.provider";
+    private static final String OSS_ENV_PROVIDER =
+            
"com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider";
+
+    private static final String COS_PROVIDER_KEY = 
"fs.cosn.credentials.provider";
+    private static final String COS_ENV_PROVIDER =
+            
"org.apache.hadoop.fs.cosn.auth.EnvironmentVariableCredentialsProvider";
+
+    private static final String S3_ACCESS_KEY = "test-s3-access-key";
+    private static final String S3_SECRET_KEY = "test-s3-secret-key";
+    private static final String S3_SESSION_TOKEN = "test-s3-session-token";
+
+    private static final String OSS_ACCESS_KEY = "test-oss-access-key";
+    private static final String OSS_SECRET_KEY = "test-oss-secret-key";
+    private static final String OSS_SESSION_TOKEN = "test-oss-session-token";
+
+    private static final String COS_SECRET_ID = "test-cos-secret-id";
+    private static final String COS_SECRET_KEY = "test-cos-secret-key";
+
+    @Test
+    public void testS3EnvironmentCredentialProviderIsPassedThrough() throws 
Exception {
+        Map<String, String> config = new HashMap<>();
+        config.put("s3.bucket", "s3a://seatunnel-checkpoint");
+        config.put(S3_PROVIDER_KEY, S3_ENV_PROVIDER);
+
+        Configuration hadoopConf =
+                
FileConfiguration.valueOf("S3").getConfiguration().buildConfiguration(config);
+
+        Assertions.assertEquals(S3_ENV_PROVIDER, 
hadoopConf.get(S3_PROVIDER_KEY));
+        Assertions.assertNull(hadoopConf.get("fs.s3a.access.key"));
+        Assertions.assertNull(hadoopConf.get("fs.s3a.secret.key"));
+    }
+
+    @Test
+    public void testOssEnvironmentCredentialProviderIsPassedThrough() throws 
Exception {
+        Map<String, String> config = new HashMap<>();
+        config.put("oss.bucket", "oss://seatunnel-checkpoint");
+        config.put("fs.oss.endpoint", "oss-cn-hangzhou.aliyuncs.com");
+        config.put(OSS_PROVIDER_KEY, OSS_ENV_PROVIDER);
+
+        Configuration hadoopConf =
+                
FileConfiguration.valueOf("OSS").getConfiguration().buildConfiguration(config);
+
+        Assertions.assertEquals(OSS_ENV_PROVIDER, 
hadoopConf.get(OSS_PROVIDER_KEY));
+        Assertions.assertNull(hadoopConf.get("fs.oss.accessKeyId"));
+        Assertions.assertNull(hadoopConf.get("fs.oss.accessKeySecret"));
+    }
+
+    @Test
+    public void testCosEnvironmentCredentialProviderIsPassedThrough() throws 
Exception {
+        Map<String, String> config = new HashMap<>();
+        config.put("cos.bucket", "cosn://seatunnel-checkpoint");
+        config.put("fs.cosn.bucket.region", "ap-shanghai");
+        config.put(COS_PROVIDER_KEY, COS_ENV_PROVIDER);
+
+        Configuration hadoopConf =
+                
FileConfiguration.valueOf("COS").getConfiguration().buildConfiguration(config);
+
+        Assertions.assertEquals(COS_ENV_PROVIDER, 
hadoopConf.get(COS_PROVIDER_KEY));
+        Assertions.assertNull(hadoopConf.get("fs.cosn.userinfo.secretId"));
+        Assertions.assertNull(hadoopConf.get("fs.cosn.userinfo.secretKey"));
+    }
+
+    /**
+     * Guards that the provider classes are present on the test classpath; the 
tests below verify
+     * that they actually read the environment variables.
+     */
+    @Test
+    public void testEnvironmentCredentialProviderClassesAreOnTestClasspath() {
+        Assertions.assertDoesNotThrow(() -> Class.forName(S3_ENV_PROVIDER));
+        Assertions.assertDoesNotThrow(() -> Class.forName(OSS_ENV_PROVIDER));
+        Assertions.assertDoesNotThrow(() -> Class.forName(COS_ENV_PROVIDER));
+    }
+
+    @Test
+    public void testS3EnvironmentProviderReadsConfiguredValues() throws 
Exception {
+        withEnvironmentVariable("AWS_ACCESS_KEY_ID", S3_ACCESS_KEY)
+                .and("AWS_SECRET_ACCESS_KEY", S3_SECRET_KEY)
+                .and("AWS_SESSION_TOKEN", S3_SESSION_TOKEN)
+                .execute(
+                        () -> {
+                            Map<String, String> config = new HashMap<>();
+                            config.put("s3.bucket", 
"s3a://seatunnel-checkpoint");
+                            config.put(S3_PROVIDER_KEY, S3_ENV_PROVIDER);
+                            Configuration hadoopConf =
+                                    FileConfiguration.valueOf("S3")
+                                            .getConfiguration()
+                                            .buildConfiguration(config);
+
+                            try (AWSCredentialProviderList providers =
+                                    S3AUtils.createAWSCredentialProviderSet(
+                                            
URI.create("s3a://seatunnel-checkpoint"), hadoopConf)) {
+                                AWSSessionCredentials credentials =
+                                        Assertions.assertInstanceOf(
+                                                AWSSessionCredentials.class,
+                                                providers.getCredentials());
+
+                                Assertions.assertEquals(
+                                        S3_ACCESS_KEY, 
credentials.getAWSAccessKeyId());
+                                Assertions.assertEquals(
+                                        S3_SECRET_KEY, 
credentials.getAWSSecretKey());
+                                Assertions.assertEquals(
+                                        S3_SESSION_TOKEN, 
credentials.getSessionToken());
+                            }
+                        });
+    }
+
+    @Test
+    public void testOssEnvironmentProviderReadsConfiguredValues() throws 
Exception {
+        withEnvironmentVariable("OSS_ACCESS_KEY_ID", OSS_ACCESS_KEY)
+                .and("OSS_ACCESS_KEY_SECRET", OSS_SECRET_KEY)
+                .and("OSS_SESSION_TOKEN", OSS_SESSION_TOKEN)
+                .execute(
+                        () -> {
+                            Map<String, String> config = new HashMap<>();
+                            config.put("oss.bucket", 
"oss://seatunnel-checkpoint");
+                            config.put("fs.oss.endpoint", 
"oss-cn-hangzhou.aliyuncs.com");
+                            config.put(OSS_PROVIDER_KEY, OSS_ENV_PROVIDER);
+                            Configuration hadoopConf =
+                                    FileConfiguration.valueOf("OSS")
+                                            .getConfiguration()
+                                            .buildConfiguration(config);
+
+                            CredentialsProvider provider =
+                                    AliyunOSSUtils.getCredentialsProvider(
+                                            
URI.create("oss://seatunnel-checkpoint"), hadoopConf);
+                            Assertions.assertInstanceOf(
+                                    
EnvironmentVariableCredentialsProvider.class, provider);
+                            Credentials credentials = 
provider.getCredentials();
+
+                            Assertions.assertEquals(OSS_ACCESS_KEY, 
credentials.getAccessKeyId());
+                            Assertions.assertEquals(
+                                    OSS_SECRET_KEY, 
credentials.getSecretAccessKey());
+                            Assertions.assertEquals(
+                                    OSS_SESSION_TOKEN, 
credentials.getSecurityToken());
+                        });
+    }
+
+    @Test
+    public void testCosEnvironmentProviderReadsConfiguredValues() throws 
Exception {
+        withEnvironmentVariable("COSN_SECRET_ID", COS_SECRET_ID)
+                .and("COSN_SECRET_KEY", COS_SECRET_KEY)
+                .execute(
+                        () -> {
+                            Map<String, String> config = new HashMap<>();
+                            config.put("cos.bucket", 
"cosn://seatunnel-checkpoint");
+                            config.put("fs.cosn.bucket.region", "ap-shanghai");
+                            config.put(COS_PROVIDER_KEY, COS_ENV_PROVIDER);
+                            Configuration hadoopConf =
+                                    FileConfiguration.valueOf("COS")
+                                            .getConfiguration()
+                                            .buildConfiguration(config);
+
+                            COSCredentials credentials =
+                                    CosNUtils.createCosCredentialsProviderSet(
+                                                    
URI.create("cosn://seatunnel-checkpoint"),
+                                                    hadoopConf)
+                                            .getCredentials();
+
+                            Assertions.assertEquals(COS_SECRET_ID, 
credentials.getCOSAccessKeyId());
+                            Assertions.assertEquals(COS_SECRET_KEY, 
credentials.getCOSSecretKey());
+                        });
+    }
+}
diff --git 
a/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/pom.xml
 
b/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/pom.xml
index cb7bf09e26..cea7b72349 100644
--- 
a/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/pom.xml
+++ 
b/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/pom.xml
@@ -32,7 +32,8 @@
 
     <properties>
         <!-- Imap storage dependency package  -->
-        <hadoop-aliyun.version>3.0.0</hadoop-aliyun.version>
+        <hadoop-aliyun.version>3.1.4</hadoop-aliyun.version>
+        <aliyun.sdk.oss.version>3.4.1</aliyun.sdk.oss.version>
         <json-smart.version>2.4.7</json-smart.version>
         <netty-buffer.version>4.1.60.Final</netty-buffer.version>
     </properties>
@@ -91,28 +92,30 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
         <dependency>
             <groupId>net.minidev</groupId>
             <artifactId>json-smart</artifactId>
             <version>${json-smart.version}</version>
             <scope>provided</scope>
         </dependency>
-
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-aws</artifactId>
             <version>${hadoop-aws.version}</version>
             <scope>provided</scope>
         </dependency>
-
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-buffer</artifactId>
             <version>${netty-buffer.version}</version>
             <scope>provided</scope>
         </dependency>
-
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.sdk.oss.version}</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 
 </project>
diff --git 
a/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/src/test/java/org/apache/seatunnel/engine/imap/storage/file/config/EnvironmentCredentialConfigurationTest.java
 
b/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/src/test/java/org/apache/seatunnel/engine/imap/storage/file/config/EnvironmentCredentialConfigurationTest.java
new file mode 100644
index 0000000000..a22260100d
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-storage/imap-storage-plugins/imap-storage-file/src/test/java/org/apache/seatunnel/engine/imap/storage/file/config/EnvironmentCredentialConfigurationTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.seatunnel.engine.imap.storage.file.config;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.aliyun.oss.AliyunOSSUtils;
+import org.apache.hadoop.fs.s3a.AWSCredentialProviderList;
+import org.apache.hadoop.fs.s3a.S3AUtils;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+import org.junit.jupiter.api.parallel.ResourceLock;
+
+import com.aliyun.oss.common.auth.Credentials;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
+import com.amazonaws.auth.AWSSessionCredentials;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static 
com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
+
+/**
+ * Tests mutate process-wide environment variables through {@code 
SystemLambda}. {@code SAME_THREAD}
+ * keeps the methods in this class sequential, and the shared resource lock 
keeps other environment-
+ * mutating test classes from running concurrently.
+ */
+@Execution(ExecutionMode.SAME_THREAD)
+@ResourceLock("system-environment")
+public class EnvironmentCredentialConfigurationTest {
+
+    private static final String S3_PROVIDER_KEY = 
"fs.s3a.aws.credentials.provider";
+    private static final String S3_ENV_PROVIDER =
+            "com.amazonaws.auth.EnvironmentVariableCredentialsProvider";
+
+    private static final String OSS_PROVIDER_KEY = 
"fs.oss.credentials.provider";
+    private static final String OSS_ENV_PROVIDER =
+            
"com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider";
+
+    private static final String S3_ACCESS_KEY = "imap-s3-access-key";
+    private static final String S3_SECRET_KEY = "imap-s3-secret-key";
+    private static final String S3_SESSION_TOKEN = "imap-s3-session-token";
+
+    private static final String OSS_ACCESS_KEY = "imap-oss-access-key";
+    private static final String OSS_SECRET_KEY = "imap-oss-secret-key";
+    private static final String OSS_SESSION_TOKEN = "imap-oss-session-token";
+
+    @Test
+    public void testS3EnvironmentProviderReadsConfiguredValues() throws 
Exception {
+        withEnvironmentVariable("AWS_ACCESS_KEY_ID", S3_ACCESS_KEY)
+                .and("AWS_SECRET_ACCESS_KEY", S3_SECRET_KEY)
+                .and("AWS_SESSION_TOKEN", S3_SESSION_TOKEN)
+                .execute(
+                        () -> {
+                            Map<String, String> config = new HashMap<>();
+                            config.put("s3.bucket", "s3a://seatunnel-imap");
+                            config.put(S3_PROVIDER_KEY, S3_ENV_PROVIDER);
+                            Configuration hadoopConf =
+                                    FileConfiguration.valueOf("S3")
+                                            .getConfiguration()
+                                            .buildConfiguration(config);
+
+                            try (AWSCredentialProviderList providers =
+                                    S3AUtils.createAWSCredentialProviderSet(
+                                            
URI.create("s3a://seatunnel-imap"), hadoopConf)) {
+                                AWSSessionCredentials credentials =
+                                        Assertions.assertInstanceOf(
+                                                AWSSessionCredentials.class,
+                                                providers.getCredentials());
+
+                                Assertions.assertEquals(
+                                        S3_ACCESS_KEY, 
credentials.getAWSAccessKeyId());
+                                Assertions.assertEquals(
+                                        S3_SECRET_KEY, 
credentials.getAWSSecretKey());
+                                Assertions.assertEquals(
+                                        S3_SESSION_TOKEN, 
credentials.getSessionToken());
+                            }
+                        });
+    }
+
+    @Test
+    public void testOssEnvironmentProviderReadsConfiguredValues() throws 
Exception {
+        withEnvironmentVariable("OSS_ACCESS_KEY_ID", OSS_ACCESS_KEY)
+                .and("OSS_ACCESS_KEY_SECRET", OSS_SECRET_KEY)
+                .and("OSS_SESSION_TOKEN", OSS_SESSION_TOKEN)
+                .execute(
+                        () -> {
+                            Map<String, String> config = new HashMap<>();
+                            config.put("oss.bucket", "oss://seatunnel-imap");
+                            config.put("fs.oss.endpoint", 
"oss-cn-hangzhou.aliyuncs.com");
+                            config.put(OSS_PROVIDER_KEY, OSS_ENV_PROVIDER);
+                            Configuration hadoopConf =
+                                    FileConfiguration.valueOf("OSS")
+                                            .getConfiguration()
+                                            .buildConfiguration(config);
+
+                            CredentialsProvider provider =
+                                    AliyunOSSUtils.getCredentialsProvider(
+                                            
URI.create("oss://seatunnel-imap"), hadoopConf);
+                            Assertions.assertInstanceOf(
+                                    
EnvironmentVariableCredentialsProvider.class, provider);
+                            Credentials credentials = 
provider.getCredentials();
+
+                            Assertions.assertEquals(OSS_ACCESS_KEY, 
credentials.getAccessKeyId());
+                            Assertions.assertEquals(
+                                    OSS_SECRET_KEY, 
credentials.getSecretAccessKey());
+                            Assertions.assertEquals(
+                                    OSS_SESSION_TOKEN, 
credentials.getSecurityToken());
+                        });
+    }
+}

Reply via email to