全部產品
Search
文件中心

Alibaba Cloud SDK:管理訪問憑據

更新時間:Oct 16, 2025

在使用阿里雲SDK時,憑據資訊(例如AccessKey、STS Token等)由Credentials工具統一管理。本文將為您介紹Credentials工具支援的憑據類型及其配置方法,協助您快速掌握Credentials工具的使用。

前提條件

安裝Credentials工具

推薦使用pip安裝。

pip install alibabacloud_credentials

alibabacloud_credentials庫的最新版本資訊請參見alibabacloud-credentials · PyPIGithub,建議使用最新版本,以確保對所有功能的支援。

Credentials工具支援的憑據類型及其配置參數

Credentials工具支援的憑據類型及其配置參數均在alibabacloud_credentials.models模組的Config類中定義。憑據類型由參數type指定,不同的憑據類型所需的配置參數各不相同。下表將詳細介紹type的取值範圍及其支援的配置參數。其中,支援表示必填參數,-表示選擇性參數,不支援表示不支援參數。

說明

未在下表中列出的憑據類型及參數表示不建議繼續使用。

type

access_key

sts

ram_role_arn

ecs_ram_role

oidc_role_arn

credentials_uri

bearer

access_key_id:訪問憑據ID。

支援

支援

支援

不支援

不支援

不支援

不支援

access_key_secret:訪問憑據密鑰。

支援

支援

支援

不支援

不支援

不支援

不支援

security_token:STS Token。

不支援

支援

-

不支援

不支援

不支援

不支援

role_arn:RAM角色的ARN。

不支援

不支援

支援

不支援

支援

不支援

不支援

role_session_name:自訂會話名稱,預設格式為credentials-python-目前時間的時間戳記

不支援

不支援

-

不支援

-

不支援

不支援

role_name:RAM角色名稱。

不支援

不支援

不支援

-

不支援

不支援

不支援

disable_imds_v1:是否強制使用加固模式,預設值為false

不支援

不支援

不支援

-

不支援

不支援

不支援

bearer_token:bearer token。

不支援

不支援

不支援

不支援

不支援

不支援

支援

policy:自訂權限原則。

不支援

不支援

-

不支援

-

不支援

不支援

role_session_expiration:會話到期時間,預設3600秒。

不支援

不支援

-

不支援

-

不支援

不支援

oidc_provider_arn:OIDC供應商ARN。

不支援

不支援

不支援

不支援

支援

不支援

不支援

oidc_token_file_path:OIDC Token檔案路徑。

不支援

不支援

不支援

不支援

支援

不支援

不支援

external_id:角色外部 ID,主要功能是防止混淆代理人問題。更多資訊,請參見使用ExternalId防止混淆代理人問題

不支援

不支援

-

不支援

不支援

不支援

不支援

credentials_uri:憑據的URI。

不支援

不支援

不支援

不支援

不支援

支援

不支援

sts_endpoint:STS的服務存取點,支援VPC服務存取點和公網服務存取點,可選的值請參見服務存取點,預設值為sts.aliyuncs.com

不支援

不支援

-

不支援

-

不支援

不支援

timeout:HTTP請求的讀逾時時間,預設值為5000毫秒。

不支援

不支援

-

-

-

-

不支援

connect_timeout:HTTP請求的連線逾時時間,預設值為10000毫秒。

不支援

不支援

-

-

-

-

不支援

使用Credentials工具

前文已介紹Credentials工具所支援的憑據類型及其配置參數,接下來將通過詳細的程式碼範例進一步說明,您可以根據具體情況選擇適合的使用方式。

重要
  • 在專案中使用明文AccessKey,容易因代碼倉庫許可權管理不當造成AccessKey泄露,會威脅該帳號下所有資源的安全。建議通過環境變數、設定檔等方式儲存AccessKey。

  • 在使用Credentials工具時,建議採用單例模式。這一做法能夠啟用Credentials工具內建的憑據緩衝功能,有效防止因多次調用介面而導致的限流問題,以及因建立多個執行個體而引起的資源浪費問題。詳細資料請參見Session類型憑據自動重新整理機制

方式一:預設憑據鏈

說明

該方式是OpenAPI門戶範例程式碼中預設採用的方式。

在使用Credentials工具時,如果不傳入任何配置參數,Credentials工具將從預設憑據鏈中擷取憑據。在採用此方式時,必須確保在應用程式運行環境中已配置預設憑據鏈支援的任意一種憑據擷取方式。

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models

# 不指定任何配置參數,將從預設憑據鏈中擷取憑據。
credentialsClient = CredentialClient()

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式二:AK

Credentials工具將使用您提供的AccessKey作為訪問憑據。

警告

阿里雲帳號(主帳號)擁有資源的全部許可權,AK一旦泄露,會給系統帶來巨大風險,不建議使用。

推薦使用最小化授權的RAM使用者的AK。

import os

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='access_key',
    # 必填參數,此處以從環境變數中擷取AccessKey ID為例
    access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
    # 必填參數,此處以從環境變數中擷取AccessKey Secret為例
    access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
)
credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式三:STS Token

Credentials工具將使用您提供的靜態STS Token作為訪問憑據。

import os

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='sts',
    # 必填參數,此處以從環境變數中擷取AccessKey ID為例
    access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
    # 必填參數,此處以從環境變數中擷取AccessKey Secret為例
    access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
    # 必填參數,此處以從環境變數中擷取臨時SecurityToken為例
    security_token=os.environ.get('ALIBABA_CLOUD_SECURITY_TOKEN')
)
credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式四:AK及RamRoleArn

Credentials工具將使用您提供的AK及RAM角色ARN調用AssumeRole擷取STS Token,並將該STS Token作為訪問憑據。通過此方式擷取的憑據支援自動重新整理,詳情請參見Session類型憑據自動重新整理機制

import os

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='ram_role_arn',
    # 必填參數,此處以從環境變數中擷取AccessKey ID為例
    access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
    # 必填參數,此處以從環境變數中擷取AccessKey Secret為例
    access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
    # 必填參數,要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,支援通過環境變數ALIBABA_CLOUD_ROLE_ARN設定。
    role_arn='<role_arn>',
    # 選擇性參數,角色會話名稱,支援通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定。
    role_session_name='<role_session_name>',
    # 選擇性參數,設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
    policy='<policy>',
    # 選擇性參數,角色外部ID,主要功能是防止混淆代理人問題。
    external_id='<external_id>',
    # 選擇性參數,會話到期時間,預設3600秒。
    role_session_expiration=3600
)

credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式五:ECS執行個體RAM角色

若您的應用程式運行於ECS或ECI執行個體,並且該執行個體已被授予RAM角色,Credentials工具支援通過執行個體中繼資料擷取RAM角色的STS Token作為訪問憑據。通過此方式擷取的憑據支援自動重新整理,詳情請參見Session類型憑據自動重新整理機制

Credentials工具將預設採用加固模式(IMDSv2)訪問ECS執行個體中繼資料。若在加固模式下發生異常,您可以通過參數disable_imds_v1或環境變數 ALIBABA_CLOUD_IMDSV1_DISABLED 來控制異常處理邏輯:

  • 當值為False(預設)時,系統將嘗試切換到普通模式繼續擷取憑據;

  • 當值為True時,表示僅允許使用加固模式擷取憑據,若加固模式訪問失敗則會拋出異常。

服務端是否支援IMDSv2,取決於您在伺服器的配置。

另外,您可以通過配置環境變數ALIBABA_CLOUD_ECS_METADATA_DISABLED=true來關閉執行個體中繼資料的憑據訪問。

說明
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='ecs_ram_role',
    # 選擇性參數,該ECS角色的角色名稱,不填會自動擷取,但是建議加上以減少請求次數,支援通過環境變數ALIBABA_CLOUD_ECS_METADATA設定。
    role_name='<role_name>',
    # 選擇性參數,預設值:False。True:表示強制使用加固模式。False:系統將首先嘗試在加固模式下擷取憑據。如果失敗,則會切換到普通模式(IMDSv1)進行嘗試
    disable_imds_v1=True
)

credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式六:OIDCRoleArn

若您使用OIDC認證協議,並已建立OIDC身份供應商的RAM角色,您可以通過Credentials工具傳入OIDC身份供應商ARN、OIDC Token及RAM角色ARN,系統將自動調用STS服務的AssumeRoleWithOIDC介面擷取RAM角色的STS Token,並將該STS Token作為訪問憑據。通過此方式擷取的憑據支援自動重新整理,詳情請參見Session類型憑據自動重新整理機制。例如當您的應用程式運行於已啟用RRSA功能的ACK叢集中時,Credentials工具支援通過讀取Pod環境變數中的OIDC配置資訊,調用AssumeRoleWithOIDC介面擷取服務角色的STS Token,從而利用該STS Token訪問阿里雲相關服務。

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='oidc_role_arn',
    # 必填參數,RAM角色ARN,支援通過環境變數ALIBABA_CLOUD_ROLE_ARN設定。
    role_arn='<role_arn>',
    # 必填參數,OIDC身份供應商ARN,支援通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定。
    oidc_provider_arn='<oidc_provider_arn>',
    # 必填參數,OIDC Token檔案路徑,支援通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定。
    oidc_token_file_path='<oidc_token_file_path>',
    # 選擇性參數,角色會話名稱,支援通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定。
    role_session_name='<role_session_name>',
    # 選擇性參數,設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
    policy='<policy>',
    # 選擇性參數,設定session到期時間,預設3600秒。
    role_session_expiration=3600
)
credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式七:URI憑據

通過封裝STS服務並對外暴露服務的URI,外部服務能夠通過該URI擷取STS Token,從而有效降低AK等敏感資訊的暴露風險。Credentials工具支援通過訪問您所提供的URI來擷取STS Token,並將該STS Token作為訪問憑據。通過此方式擷取的憑據支援自動重新整理,詳情請參見Session類型憑據自動重新整理機制

該URI必須滿足如下條件:

  • 支援GET請求。

  • 響應狀態代碼為200。

  • 響應體為如下的結構:

    {
      "Code": "Success",
      "AccessKeySecret": "yourAccessKeySecret",
      "AccessKeyId": "STS.****************",
      "Expiration": "2021-09-26T03:46:38Z",
      "SecurityToken": "yourSecurityToken"
    }
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='credentials_uri',
    # 必填參數,外部擷取憑據的URI,格式為http://local_or_remote_uri/,支援通過環境變數ALIBABA_CLOUD_CREDENTIALS_URI設定。
    credentials_uri='<credentials_uri>',
)
credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用雲產品 V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

方式八:Bearer Token

目前只有Cloud Call CenterCCC這款產品支援Bearer Token。

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_tea_openapi import models as open_api_models

credentialsConfig = CredentialConfig(
    type='bearer',
    # 必填參數,填入您的Bearer Token
    bearer_token='<BearerToken>',
)
credentialsClient = CredentialClient(credentialsConfig)

credential = credentialsClient.get_credential()
access_key_id = credential.get_access_key_id()
access_key_secret = credential.get_access_key_secret()
security_token = credential.get_security_token()

# 若使用CCC V2.0 SDK 時,使用alibabacloud_tea_openapi.models模組的Config類傳遞credential
config = open_api_models.Config(
    credential=credentialsClient,
    endpoint='<endpoint>'
)
# 省略使用 config 初始化雲產品 client 的代碼...

預設憑據鏈

預設憑據鏈是一種兜底策略,按照內建的憑據尋找順序逐層向下尋找,直至擷取憑據資訊。若所有情況均未成功擷取到憑據資訊,則會拋出CredentialException。以下為尋找順序:

1. 使用環境變數

如果未找到系統屬性中的憑據資訊,Credentials工具會繼續檢查環境變數。

  • 如果 ALIBABA_CLOUD_ACCESS_KEY_ID ALIBABA_CLOUD_ACCESS_KEY_SECRET 均存在且非空,則使用它們作為預設憑據。

  • 如果同時設定了 ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET ALIBABA_CLOUD_SECURITY_TOKEN,則使用STS Token作為預設憑據。

2. 使用OIDC RAM角色

如果仍未擷取到憑據資訊,Credentials工具會檢查以下與OIDC RAM角色相關的環境變數:

  • ALIBABA_CLOUD_ROLE_ARN:RAM角色名稱ARN。

  • ALIBABA_CLOUD_OIDC_PROVIDER_ARN:OIDC供應商ARN。

  • ALIBABA_CLOUD_OIDC_TOKEN_FILE:OIDC Token檔案路徑。

如果以上三個環境變數均存在且非空,Credentials將會使用變數內容調用STS服務的AssumeRoleWithOIDC介面換取STS Token作為預設憑據。

3. 使用設定檔

說明

該功能要求alibabacloud_credentials的版本不低於1.0rc3

如果仍未擷取到憑據資訊,Credentials工具會嘗試從預設路徑載入config.json設定檔,並擷取指定的憑據作為預設憑據。該檔案的預設完整路徑如下:

  • Linux/Mac:~/.aliyun/config.json

  • Windows: C:\Users\USER_NAME\.aliyun\config.json

如果您需要通過此方式配置憑據,您可以使用阿里雲CLI工具配置憑據,或手動在相應路徑下建立config.json設定檔。內容格式樣本如下:

{
  "current": "<PROFILE_NAME>",
  "profiles": [
    {
      "name": "<PROFILE_NAME>",
      "mode": "AK",
      "access_key_id": "<ALIBABA_CLOUD_ACCESS_KEY_ID>",
      "access_key_secret": "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>"
    },
    {
      "name": "<PROFILE_NAME1>",
      "mode": "StsToken",
      "access_key_id": "<ALIBABA_CLOUD_ACCESS_KEY_ID>",
      "access_key_secret": "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>",
      "sts_token": "<SECURITY_TOKEN>"
    },
    {
      "name":"<PROFILE_NAME2>",
      "mode":"RamRoleArn",
      "access_key_id":"<ALIBABA_CLOUD_ACCESS_KEY_ID>",
      "access_key_secret":"<ALIBABA_CLOUD_ACCESS_KEY_SECRET>",
      "ram_role_arn":"<ROLE_ARN>",
      "ram_session_name":"<ROLE_SESSION_NAME>",
      "expired_seconds":3600
    },
    {
      "name":"<PROFILE_NAME3>",
      "mode":"EcsRamRole",
      "ram_role_name":"<RAM_ROLE_ARN>"
    },
    {
      "name":"<PROFILE_NAME4>",
      "mode":"OIDC",
      "oidc_provider_arn":"<OIDC_PROVIDER_ARN>",
      "oidc_token_file":"<OIDC_TOKEN_FILE>",
      "ram_role_arn":"<ROLE_ARN>",
      "ram_session_name":"<ROLE_SESSION_NAME>",
      "expired_seconds":3600
    },
    {
      "name":"<PROFILE_NAME5>",
      "mode":"ChainableRamRoleArn",
      "source_profile":"<PROFILE_NAME>",
      "ram_role_arn":"<ROLE_ARN>",
      "ram_session_name":"<ROLE_SESSION_NAME>",
      "expired_seconds":3600
    }
  ]
}

參數名稱

參數介紹

current

指定憑據名稱以擷取相應的憑據配置資訊,其值為profiles中參數name的值。預設情況下,系統優先使用環境變數 ALIBABA_CLOUD_PROFILE 指定的憑據名稱;若該環境變數未配置,則將使用current指定的憑據名稱。

profiles

憑據資訊集合。通過參數mode指定憑據的類型:

  • AK:使用使用者的AccessKey作為憑據資訊;

  • StsToken:使用STS Token作為憑據資訊;

  • RamRoleArn:通過RAM使用者扮演RAM角色擷取憑證資訊。

  • EcsRamRole:通過執行個體中繼資料擷取憑據資訊;

  • OIDC:通過OIDC身份供應商ARN、OIDC Token和RAM角色ARN擷取憑據資訊;

  • ChainableRamRoleArn:採用角色鏈的方式,通過source_profile指定profiles中其他憑據的名稱,以重新擷取新的憑據資訊。

4. 使用ECS執行個體RAM角色

如果仍未擷取到憑據資訊,Credentials將嘗試通過執行個體中繼資料擷取授予給該執行個體的RAM角色的STS Token,並將其作為預設憑據。在訪問執行個體中繼資料時,程式會首先擷取授予給當前執行個體的RAM角色名稱,然後再基於該角色擷取對應的STS Token。您也可以通過環境變數 ALIBABA_CLOUD_ECS_METADATA 指定RAM角色名稱,從而減少憑據擷取所需的時間,提升效率。

預設情況下,Credentials 會使用加固模式(IMDSv2)訪問中繼資料。若在加固模式下發生異常,您可以通過環境變數 ALIBABA_CLOUD_IMDSV1_DISABLED 來控制異常處理邏輯:

  • 當值為false(預設)時,系統將嘗試切換到普通模式繼續擷取憑據;

  • 當值為true時,表示僅允許使用加固模式擷取憑據,若加固模式訪問失敗則會拋出異常。

另外,您可以通過配置環境變數ALIBABA_CLOUD_ECS_METADATA_DISABLED=true來關閉ECS中繼資料的憑據訪問。

說明

5. 使用Credentials工具URI

如果仍未擷取到憑據資訊,Credentials工具會檢查環境變數 ALIBABA_CLOUD_CREDENTIALS_URI,如果該變數存在且指向一個有效URI地址,Credentials通過訪問該URI來擷取STS Token作為預設憑據。

Session類型憑據自動重新整理機制

Session類型憑據包含ram_role_arnecs_ram_roleoidc_role_arn以及credentials_uri,該類型憑據在Credentials工具中內建了憑據自動重新整理機制。當憑據用戶端首次擷取憑據後,Credentials工具會將擷取的憑據資訊儲存至緩衝中。在後續使用過程中,同一憑據用戶端執行個體將自動從緩衝中提取憑據;若緩衝中的憑據資訊已到期,則憑據用戶端執行個體將重新擷取憑據,並更新緩衝中的值。

說明

對於ecs_ram_role類型憑據,Credentials工具將會在緩衝中的值到期前15分鐘進行提前重新整理。

下面將採用單例模式建立憑據用戶端,通過多個時間段擷取憑據來驗證憑據重新整理機制,並通過調用OpenAPI確保所擷取的憑據處於可用狀態。

import os
import sys
import time
import threading
from functools import wraps
from threading import Lock

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_credentials.models import Config as CredentialConfig
from alibabacloud_ecs20140526.client import Client
from alibabacloud_ecs20140526.models import DescribeRegionsRequest
from alibabacloud_tea_openapi.models import Config as EcsConfig


#
# 單例裝飾器(安全執行緒)
#

def singleton(cls):
    """實現安全執行緒的單例模式"""
    instances = {}
    lock = Lock()

    @wraps(cls)
    def wrapper(*args, **kwargs):
        with lock:
            if cls not in instances:
                instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return wrapper


#
# 單例服務類
#

@singleton
class Credential:
    def __init__(self):
        self._client = self._init_client()

    @staticmethod
    def _init_client() -> CredentialClient:
        try:
            config = CredentialConfig(
                type="ram_role_arn",
                access_key_id=os.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                access_key_secret=os.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
                role_arn=os.getenv("ALIBABA_CLOUD_ROLE_ARN"),
                role_session_name="RamRoleArnTest",
                role_session_expiration=3600,
            )
            return CredentialClient(config)
        except Exception as e:
            raise RuntimeError(f"Credential initialization failed: {e}") from e

    @property
    def client(self) -> CredentialClient:
        return self._client


@singleton
class EcsClient:
    def __init__(self, credential: CredentialClient):
        self._client = self._init_client(credential)

    @staticmethod
    def _init_client(credential: CredentialClient) -> Client:
        try:
            ecs_config = EcsConfig(credential=credential)
            ecs_config.endpoint = 'ecs.cn-hangzhou.aliyuncs.com'
            return Client(ecs_config)
        except Exception as e:
            raise RuntimeError(f"ECS client initialization failed: {e}") from e

    @property
    def client(self) -> Client:
        return self._client


#
# 任務函數
#

def execute_task():
    try:
        # 擷取憑據和ECS用戶端
        credential = Credential().client.get_credential()
        ecs_client = EcsClient(Credential().client).client

        # 列印憑據資訊
        print("Time:", time.strftime("%Y-%m-%d %H:%M:%S"))
        print("AK ID:", credential.access_key_id)
        print("AK Secret:", credential.access_key_secret)
        print("STS Token:", credential.security_token)

        # 調用API查詢Region列表
        request = DescribeRegionsRequest()
        response = ecs_client.describe_regions(request)
        print("Invoke result:", response.to_map()["statusCode"])

    except Exception as e:
        print(f"ECS client execution failed: {e}")
        raise


def schedule_task():
    def run_execute_task():
        try:
            execute_task()
        except Exception as e:
            print(f"Task execution failed: {e}")
        finally:
            nonlocal task_count
            task_count += 1
            if task_count == len(DELAYS):
                print("All tasks completed. Exiting program.")
                sys.exit(0)

    def schedule_execution(delay):
        task_timer = threading.Timer(delay, run_execute_task)
        task_timer.start()
        return task_timer

    # 定時任務延遲定義
    DELAYS = [0, 600, 4200, 4300]
    task_count = 0

    timers = [schedule_execution(delay) for delay in DELAYS]

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Program interrupted by user.")
        for timer in timers:
            timer.cancel()


if __name__ == "__main__":
    schedule_task()

image

根據日誌顯示結果進行分析:

  • 在第一次調用時,由於未緩衝憑據資訊,系統根據配置擷取憑據資訊。擷取到憑據後,憑據資訊被儲存在緩衝中。

  • 第二次調用所使用的憑據資訊與第一次相同,表明第二次調用是從緩衝中提取的憑據資訊。

  • 第三次調用時,由於憑據的到期時間(RoleSessionExpiration)被設定為3600秒,而第三次調用發生在第一次調用之後的4200秒,此時緩衝中的憑據已到期。因此,SDK依據自動重新整理機制重新擷取了新的憑據資訊,並將新擷取的憑據資訊再次儲存於緩衝中。

  • 第四次調用所使用的憑據資訊與第三次重新擷取的憑據資訊一致,這表明緩衝中的憑據在到期後已被更新為新的憑據。

相關文檔