在使用阿里雲SDK調用OpenAPI進行資源操作時,正確配置憑證資訊至關重要。阿里雲Credentials工具提供了一整套便捷功能,支援多種憑證類型,包括預設憑證、AccessKey(AK)以及STS令牌等,以協助您高效擷取和管理訪問憑證。本文將詳細介紹各種類型憑證的配置方法以及如何根據優先順序使用預設憑證。通過本文,您將深入理解如何在阿里雲SDK中配置和維護憑證,從而確保對雲資源的操作既高效又具有高度安全性。
背景資訊
憑據是指使用者證明其身份的一組資訊。使用者在系統中進行登入時,需要提供正確的憑據才能驗證身份。常見的憑據類型有:
阿里雲主帳號和RAM使用者的永久憑據 AccessKey(簡稱AK)是由AccessKey ID和AccessKey Secret組成的金鑰組。
阿里雲RAM角色的STS臨時訪問Token,簡稱STS Token。它是可以自訂時效和存取權限的臨時身份憑據,詳情請參見什麼是STS。
Bearer Token。它是一種身分識別驗證和授權的令牌類型。
前提條件
使用Credentials工具要求Node.js 環境版本 >= 8.5.0。
使用V2.0代系的阿里雲SDK,詳情請參見通過IDE使用阿里雲Node.js SDK。
安裝Credentials工具
使用npm下載安裝。
npm install @alicloud/credentials使用最新發行Credentials依賴包,確保所有憑證支援。版本列表請參見Releases · aliyun/credentials-nodejs · GitHub。
Credentials工具配置參數介紹
Credentials工具的配置參數定義在@alicloud/credentials模組的Config 建構函式中,憑據類型由必填參數type指定。確定憑據類型後,需根據該憑據類型選擇相應的參數。下表將詳細介紹type的取值範圍及各類憑據類型所支援的參數。其中,√表示必填參數,-表示選擇性參數,×表示不支援參數。
未在下表中列出的憑據類型及參數表示不建議繼續使用。
type | access_key | sts | ram_role_arn | ecs_ram_role | oidc_role_arn | credentials_uri | bearer |
accessKeyId:訪問憑據ID。 | √ | √ | √ | × | × | × | × |
accessKeySecret:訪問憑據密鑰。 | √ | √ | √ | × | × | × | × |
securityToken:STS Token。 | × | √ | - | × | × | × | × |
roleArn:RAM角色的ARN。 | × | × | √ | × | √ | × | × |
roleSessionName:自訂會話名稱,預設格式為 | × | × | - | × | - | × | × |
roleName:RAM角色名稱。 | × | × | × | - | × | × | × |
disableIMDSv1:是否強制使用加固模式,預設值為 | × | × | × | - | × | × | × |
bearerToken:bearer token。 | × | × | × | × | × | × | √ |
policy:自訂權限原則。 | × | × | - | × | - | × | × |
roleSessionExpiration:會話到期時間,預設3600秒。 | × | × | - | × | - | × | × |
oidcProviderArn:OIDC供應商ARN。 | × | × | × | × | √ | × | × |
oidcTokenFilePath:OIDC Token檔案路徑。 | × | × | × | × | √ | × | × |
externalId:角色外部 ID,主要功能是防止混淆代理人問題。更多資訊,請參見使用ExternalId防止混淆代理人問題。 | × | × | - | × | × | × | × |
credentialsURI:憑證的URI。 | × | × | × | × | × | √ | × |
STSEndpoint:STS的服務存取點,支援VPC服務存取點和公網服務存取點,可選的值請參見服務存取點,預設值為 | × | × | - | × | - | × | × |
timeout:HTTP請求的讀逾時時間,預設值為5000毫秒。 | × | × | - | - | - | - | × |
connectTimeout:HTTP請求的連線逾時時間,預設值為10000毫秒。 | × | × | - | - | - | - | × |
初始化憑據用戶端
Credentials工具支援多種方式初始化憑據用戶端,您可根據實際情況選擇合適的方式進行憑據用戶端初始化。
在專案中使用明文AccessKey,容易因代碼倉庫許可權管理不當造成AccessKey泄露,會威脅該帳號下所有資源的安全。建議通過環境變數、設定檔等方式擷取AccessKey。
在初始化憑據用戶端時建議採用單例模式,這不僅可啟用SDK的憑證緩衝功能,還能有效防止因多次調用介面導致的流量控制問題和效能資源的浪費,詳細資料請參見Session類型憑據自動重新整理機制。
方式一:使用預設憑據鏈
當您在初始化憑據用戶端不傳入任何參數時,Credentials工具會使用預設憑據鏈方式初始化用戶端。預設憑據的讀取邏輯請參見預設憑據鏈。
const Credential = require('@alicloud/credentials');
// 不指定參數
const credentialClient = new Credential.default();
const credential = credentialClient.getCredential();
credential.then(credential => {
console.log(credential);
});
import Credential from '@alicloud/credentials';
const credential = new Credential();
credential.getCredential().then(credential => {
console.log(credential);
});介面調用方法
方式二:使用AK
該方式通過設定AK初始化憑據用戶端,如何擷取AK,請參見建立AccessKey。
阿里雲主帳號擁有資源的全部許可權,AK一旦泄露,會給系統帶來巨大風險,不建議使用。
推薦使用最小化授權的RAM使用者的AK。
const Credential = require('@alicloud/credentials');
const credentialsConfig = new Credential.Config({
// 憑證類型。
type: 'access_key',
// 設定accessKeyId值,此處已從環境變數中擷取accessKeyId為例。
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
// 設定accessKeySecret值,此處已從環境變數中擷取accessKeySecret為例。
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
});
const credentialClient = new Credential.default(credentialsConfig);
import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
// 憑證類型。
type: 'access_key',
// 設定accessKeyId值,此處已從環境變數中擷取accessKeyId為例。
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
// 設定accessKeySecret值,此處已從環境變數中擷取accessKeySecret為例。
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
});
const credentialClient = new Credential(credentialsConfig);介面調用方法
方式三:使用STS Token
該方式是通過設定靜態STS Token的方式初始化憑據。如何擷取STS Token,請參見什麼是STS。以下樣本示範如何使用STS Token初始化憑據用戶端(不包含如何擷取到STS Token的過程)。
const Credential = require('@alicloud/credentials');
const credentialsConfig = new Credential.Config({
type: 'sts',
// 設定accessKeyId值,此處已從環境變數中擷取accessKeyId為例。
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
// 設定accessKeySecret值,此處已從環境變數中擷取accessKeySecret為例。
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
// 設定securityToken值,此處已從環境變數中擷取securityToken為例。
securityToken: process.env.ALIBABA_CLOUD_SECURITY_TOKEN,
});
const cred = new Credential.default(credentialsConfig);import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
// 憑證類型。
type: 'access_key',
// 設定accessKeyId值,此處已從環境變數中擷取accessKeyId為例。
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
// 設定accessKeySecret值,此處已從環境變數中擷取accessKeySecret為例。
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
// 設定securityToken值,此處已從環境變數中擷取securityToken為例。
securityToken: process.env.ALIBABA_CLOUD_SECURITY_TOKEN,
});
const credentialClient = new Credential(credentialsConfig);
介面調用方法
方式四:使用AK及RamRoleArn
該方式底層實現是STS Token。通過指定RAM角色的ARN(Alibabacloud Resource Name),Credentials工具可以協助開發人員前往STS換取STS Token。您也可以通過為policy賦值來限制RAM角色到一個更小的許可權集合。
const Credential = require('@alicloud/credentials');
const credentialsConfig = new Credential.Config({
type: 'ram_role_arn',
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
// 要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定roleArn
roleArn: '<RoleArn>',
// 自訂角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
roleSessionName: '<RoleSessionName>',
// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy: '<Policy>',
roleSessionExpiration: 3600,
});
const cred = new Credential.default(credentialsConfig);import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
type: 'ram_role_arn',
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
// 要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定roleArn
roleArn: '<RoleArn>',
// 自訂角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
roleSessionName: '<RoleSessionName>',
// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy: '<Policy>',
roleSessionExpiration: 3600,
});
const credentialClient = new Credential(credentialsConfig);介面調用方法
方式五:使用ECS執行個體RAM角色
ECS和ECI執行個體均支援綁定執行個體RAM角色,運行於執行個體中的程式可通過Credentials工具自動擷取該角色的STS Token,從而完成憑據用戶端的初始化。
Credentials工具將預設採用加固模式(IMDSv2)訪問ECS的中繼資料服務(Meta Data Server),在使用加固模式時若發生異常,將使用普通模式兜底來擷取訪問憑據。您也可以通過設定參數disableIMDSv1或環境變數ALIBABA_CLOUD_IMDSV1_DISABLE,執行不同的異常處理邏輯:
當值為false(預設)時,會使用普通模式繼續擷取訪問憑據。
當值為true時,表示只能使用加固模式擷取訪問憑據,會拋出異常。
服務端是否支援IMDSv2,取決於您在伺服器的配置。
另外,您可以通過配置環境變數ALIBABA_CLOUD_ECS_METADATA_DISABLED=true來關閉ECS中繼資料的憑證訪問。
使用加固模式擷取臨時身份憑證時,credentials的版本不低於2.3.1。
關於ECS執行個體中繼資料的介紹,請參見執行個體中繼資料。
如何為ECS和ECI執行個體授予RAM角色,具體操作請參見建立RAM角色並授予給ECS執行個體和為ECI執行個體授予執行個體RAM角色。
const Credential = require('@alicloud/credentials');
const credentialsConfig = new Credential.Config({
type: 'ecs_ram_role',
// 選填,該ECS角色的角色名稱,不填會自動擷取,但是建議加上以減少請求次數,可以通過環境變數ALIBABA_CLOUD_ECS_METADATA設定roleName
roleName: '<RoleName>',
// 選填,預設值:false。true:表示強制使用加固模式。false:系統將首先嘗試在加固模式下擷取憑據。如果失敗,則會切換到普通模式(IMDSv1)進行嘗試
// disableIMDSv1: true,
});
const cred = new Credential.default(credentialsConfig);
import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
type: 'ecs_ram_role',
// 選填,該ECS角色的角色名稱,不填會自動擷取,但是建議加上以減少請求次數,可以通過環境變數ALIBABA_CLOUD_ECS_METADATA設定roleName
roleName: '<RoleName>',
// 選填,預設值:false。true:表示強制使用加固模式。false:系統將首先嘗試在加固模式下擷取憑據。如果失敗,則會切換到普通模式(IMDSv1)進行嘗試
// disableIMDSv1: true,
});
const credentialClient = new Credential(credentialsConfig);介面調用方法
方式六:使用OIDCRoleArn
為了避免影響雲上資源的安全,同時又能讓不可信的應用安全地擷取所需的 STS Token,實現應用層級的許可權最小化,您可以使用RRSA(RAM Roles for Service Account)功能。阿里雲容器叢集會為不同的應用Pod建立和掛載相應的服務賬戶OIDC Token檔案,並將相關配置資訊注入到環境變數中,Credentials工具通過擷取環境變數的配置資訊,調用STS服務的AssumeRoleWithOIDC介面換取綁定角色的STS Token。
注入的環境變數如下:
ALIBABA_CLOUD_ROLE_ARN:RAM角色名稱ARN;
ALIBABA_CLOUD_OIDC_PROVIDER_ARN:OIDC供應商ARN;
ALIBABA_CLOUD_OIDC_TOKEN_FILE:OIDC Token檔案路徑;
const Credential = require('@alicloud/credentials');
const credentialsConfig = new Credential.Config({
type: 'oidc_role_arn',
// RAM角色名稱ARN,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定roleArn
roleArn: '<RoleArn>',
// OIDC供應商ARN,可以通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定oidcProviderArn
oidcProviderArn: '<OidcProviderArn>',
// OIDC Token檔案路徑,可以通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定oidcTokenFilePath
oidcTokenFilePath: '<OidcTokenFilePath>',
// 自訂角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定roleSessionName
roleSessionName: '<RoleSessionName>',
// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy: '<Policy>',
// 設定session到期時間
roleSessionExpiration: 3600,
});
const credentialClient = new Credential.default(credentialsConfig);import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
type: 'oidc_role_arn',
// RAM角色名稱ARN,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定roleArn
roleArn: '<RoleArn>',
// OIDC供應商ARN,可以通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定oidcProviderArn
oidcProviderArn: '<OidcProviderArn>',
// OIDC Token檔案路徑,可以通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定oidcTokenFilePath
oidcTokenFilePath: '<OidcTokenFilePath>',
// 自訂角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定roleSessionName
roleSessionName: '<RoleSessionName>',
// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy: '<Policy>',
// 設定session到期時間
roleSessionExpiration: 3600,
});
const credentialClient = new Credential(credentialsConfig);介面調用方法
方式七:使用URI憑據
通過在應用內部封裝STS Token服務並對外提供自訂URI,其他服務僅能通過該URI擷取STS Token,這樣能夠有效降低AK等資訊的暴露風險。Credentials工具支援通過請求該服務的URI來擷取STS Token,從而實現憑據用戶端的初始化。
const Credential = require('@alicloud/credentials');
const config = new Credential.Config({
type: 'credentials_uri',
// 擷取憑證的 URI,格式為http://local_or_remote_uri/,可以通過環境變數ALIBABA_CLOUD_CREDENTIALS_URI設定credentialsUri
credentialsURI: '<CredentialsUri>',
});
const credentialClient = new Credential(config);import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
type: 'credentials_uri',
// 擷取憑證的 URI,格式為http://local_or_remote_uri/,可以通過環境變數ALIBABA_CLOUD_CREDENTIALS_URI設定credentialsUri
credentialsURI: '<CredentialsUri>',
});
const credentialClient = new Credential(credentialsConfig);該地址必須滿足如下條件:
響應狀態代碼為200
響應體為如下的結構
{ "Code": "Success", "AccessKeySecret": "AccessKeySecret", "AccessKeyId": "AccessKeyId", "Expiration": "2021-09-26T03:46:38Z", "SecurityToken": "SecurityToken" }
介面調用方法
方式八:使用Bearer Token
目前只有Cloud Call CenterCCC這款產品支援Bearer Token的憑據初始化方式。
const Credential = require('@alicloud/credentials');
const config = new Credential.Config({
type: 'bearer',
// 填入您的Bearer Token
bearerToken: '<BearerToken>',
});
const credentialClient = new Credential(config);import Credential, { Config } from '@alicloud/credentials';
const credentialsConfig = new Config({
type: 'bearer',
// 填入您的Bearer Token
bearerToken: '<BearerToken>',
});
const credentialClient = new Credential(credentialsConfig);介面調用方法
預設憑據鏈
當您的程式開發環境和生產環境採用不同的憑據類型,常見做法是在代碼中擷取當前環境資訊,編寫擷取不同憑據的分支代碼。藉助Credentials工具的預設憑據鏈,您可以用同一套代碼,通過程式之外的配置來控制不同環境下的憑據擷取方式。當您在不傳入參數的情況下,直接使用new Credential()初始化憑據用戶端時,阿里雲SDK將會嘗試按照如下順序尋找相關憑據資訊。
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. 使用config.json設定檔
如果未找到更高優先順序的憑據資訊,Credentials工具會嘗試載入config.json設定檔。該檔案的預設完整路徑如下:
Linux系統:
~/.aliyun/config.jsonWindows系統:
C:\Users\USER_NAME\.aliyun\config.json
請注意,這些預設路徑不可更改為其他路徑。如果您需要通過此方式配置訪問憑據,您可以手動在相應路徑下建立config.json設定檔,內容格式樣本如下:
{
"current": "default",
"profiles": [
{
"name": "default",
"mode": "AK",
"access_key_id": "<ALIBABA_CLOUD_ACCESS_KEY_ID>",
"access_key_secret": "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>"
},
{
"name": "client",
"mode": "StsToken",
"access_key_id": "<ALIBABA_CLOUD_ACCESS_KEY_ID>",
"access_key_secret": "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>",
"sts_token": "<SECURITY_TOKEN>"
},
{
"name":"client1",
"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":"client2",
"mode":"EcsRamRole",
"ram_role_name":"<RAM_ROLE_ARN>"
},
{
"name":"client3",
"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":"client4",
"mode":"ChainableRamRoleArn",
"source_profile":"<PROFILE_NAME>",
"ram_role_arn":"<ROLE_ARN>",
"ram_session_name":"<ROLE_SESSION_NAME>",
"expired_seconds":3600
}
]
}
在config.json設定檔中可以通過mode指定不同的憑據:
AK:使用使用者的Access Key作為憑據資訊;
StsToken:使用STS Token作為憑據資訊;
RamRoleArn:使用RAM角色的ARN來擷取憑據資訊;
EcsRamRole:利用ECS綁定的RAM角色來擷取憑據資訊;
OIDC:通過OIDC ARN和OIDC Token來擷取憑據資訊;
ChainableRamRoleArn:採用角色鏈的方式,通過指定JSON檔案中的其他憑據,以重新擷取新的憑據資訊。
其中name為憑據名稱,其他參數請根據實際情況修改。
配置完成後,Credentials將根據設定檔中current所指定的憑據名稱,選擇對應的憑據初始化憑據用戶端。此外,還可以通過環境變數ALIBABA_CLOUD_PROFILE指定具體的憑據名稱,例如將ALIBABA_CLOUD_PROFILE的值設定為client1。
4. 使用ECS執行個體RAM角色
如果未找到更高優先順序的憑據資訊,Credentials會嘗試通過ECS執行個體綁定的RAM角色擷取憑據。預設情況下,Credentials會使用加固模式(IMDSv2)訪問ECS的中繼資料服務(Meta Data Server),以擷取ECS執行個體RAM角色的STS Token作為預設憑據資訊。程式會自動訪問ECS的中繼資料服務拿到RoleName資訊,再去擷取憑證,也就是兩次請求。若想減少一次請求,可以直接在環境變數中配置ALIBABA_CLOUD_ECS_METADATA來指定執行個體RAM角色名稱。在使用加固模式時若發生異常,將使用普通模式兜底來擷取訪問憑據。您也可以通過設定環境變數ALIBABA_CLOUD_IMDSV1_DISABLE,執行不同的異常處理邏輯:
當值為false時,會使用普通模式繼續擷取訪問憑據。
當值為true時,表示只能使用加固模式擷取訪問憑據,會拋出異常。
服務端是否支援IMDSv2,取決於您在伺服器的配置。
另外,您可以通過配置環境變數ALIBABA_CLOUD_ECS_METADATA_DISABLED=true來關閉ECS中繼資料的憑證訪問。
關於ECS執行個體中繼資料的介紹,請參見執行個體中繼資料。
如何為ECS和ECI執行個體授予RAM角色,具體操作請參見建立RAM角色並授予給ECS執行個體和為ECI執行個體授予執行個體RAM角色。
5. 使用Credentials工具URI
如果上述方式均未找到有效憑據資訊,Credentials工具會檢查環境變數ALIBABA_CLOUD_CREDENTIALS_URI,如果該變數存在且指向一個有效URI地址,Credentials會向該URI發起HTTP請求,擷取臨時安全憑證作為預設憑據。
Session類型憑據自動重新整理機制
Session類型憑據包含RamRoleArn、ECS執行個體RAM角色、OIDCRoleArn以及URI憑據。該類型憑據Credentials工具中內建了自動重新整理機制,在第一次調用服務擷取訪問憑據之後,Credentials工具會將擷取的訪問憑據儲存到緩衝中。當後續使用訪問憑據時,若當前系統時間仍在緩衝到期時間之前,將自動從緩衝中提取憑據;否則,將重新調用相應服務擷取訪問憑據,並更新緩衝中的值。
針對ECS執行個體RAM角色憑據,Credentials工具會提前15分鐘重新整理緩衝中的值。
下面將採用單例模式建立憑據用戶端,並利用該憑據用戶端初始化雲產品用戶端。隨後,將通過多個時間段調用OpenAPI,以驗證是否使用了內部緩衝,並在緩衝到期後檢驗憑據是否會重新整理。
const Credential = require('@alicloud/credentials');
const Ecs20140526 = require('@alicloud/ecs20140526');
const { Config } = require('@alicloud/openapi-client');
const { RuntimeOptions } = require('@alicloud/tea-util');
// 擷取環境變數
const accessKeyId = process.env.ALIBABA_CLOUD_ACCESS_KEY_ID;
const accessKeySecret = process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET;
const roleArn = process.env.ALIBABA_CLOUD_ROLE_ARN;
/**
* Credential 單例類,用於管理阿里雲憑證執行個體。
*/
class CredentialClient {
constructor() {
if (!CredentialClient.instance) {
var credentialsConfig = new Credential.Config({
type: 'ram_role_arn',
accessKeyId: accessKeyId,
accessKeySecret: accessKeySecret,
roleArn: roleArn,
roleSessionName: 'RoleSessionNameTest',
roleSessionExpiration: 3600,
});
this.credentialsClient = new Credential.default(credentialsConfig);
CredentialClient.instance = this;
}
return CredentialClient.instance;
}
static getInstance() {
return new CredentialClient().credentialsClient;
}
}
/**
* ECS Client 單例類,用於管理 ECS 用戶端執行個體。
*/
class EcsClient {
constructor(credentialClient) {
if (!EcsClient.instance) {
const config = new Config({
endpoint: 'ecs.cn-hangzhou.aliyuncs.com',
credential: credentialClient
});
this.ecsClient = new Ecs20140526.default(config);
EcsClient.instance = this;
}
return EcsClient.instance;
}
static getInstance(credentialClient) {
return new EcsClient(credentialClient).ecsClient;
}
}
/**
* 執行任務邏輯
*/
async function executeTask() {
try {
const credentialClient = CredentialClient.getInstance();
const credential = await credentialClient.getCredential();
console.log(new Date());
console.log(`AK ID: ${credential.accessKeyId}`);
console.log(`AK Secret: ${credential.accessKeySecret}`);
console.log(`STS Token: ${credential.securityToken}`);
// 這裡以調用ECS介面為例驗證憑據是否可用,您可根據實際情況修改
const ecsClient = EcsClient.getInstance(credentialClient);
const request = new Ecs20140526.DescribeRegionsRequest();
const runtime = new RuntimeOptions({});
const response = await ecsClient.describeRegionsWithOptions(request, runtime);
console.log(`Invoke result: ${response.statusCode}`);
} catch (error) {
throw new Error(`ECS client execution failed: ${error.message}`, { cause: error });
}
}
/**
* 使用定時器調度任務執行
*/
function scheduleTasks() {
// 立即執行一次
executeTask();
// 設定後續任務順延強制
setTimeout(executeTask, 600 * 1000); // 第二次:600秒後
setTimeout(executeTask, 4200 * 1000); // 第三次:4200秒後
setTimeout(executeTask, 4300 * 1000); // 第四次:4300秒後
}
// 啟動任務調度
scheduleTasks();
import Credential, { Config as CredentialsConfig } from '@alicloud/credentials';
import Ecs20140526, * as $Ecs20140526 from '@alicloud/ecs20140526';
import { Config } from '@alicloud/openapi-client';
import { RuntimeOptions } from '@alicloud/tea-util';
// 擷取環境變數
const accessKeyId: string | undefined = process.env.ALIBABA_CLOUD_ACCESS_KEY_ID;
const accessKeySecret: string | undefined = process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET;
const roleArn: string | undefined = process.env.ALIBABA_CLOUD_ROLE_ARN;
if (!accessKeyId || !accessKeySecret || !roleArn) {
throw new Error('Missing required environment variables.');
}
/**
* Credential 單例類,用於管理阿里雲憑證執行個體。
*/
class CredentialClient {
private static instance: CredentialClient;
private readonly credentialsClient: InstanceType<typeof Credential>;
private constructor() {
const credentialsConfig = new CredentialsConfig({
type: 'ram_role_arn',
accessKeyId,
accessKeySecret,
roleArn,
roleSessionName: 'RoleSessionNameTest',
roleSessionExpiration: 3600,
});
this.credentialsClient = new Credential(credentialsConfig);
}
static getInstance(): InstanceType<typeof Credential> {
if (!CredentialClient.instance) {
CredentialClient.instance = new CredentialClient();
}
return CredentialClient.instance.credentialsClient;
}
}
/**
* ECS Client 單例類,用於管理 ECS 用戶端執行個體。
*/
class EcsClient {
private static instance: EcsClient;
private readonly ecsClient: InstanceType<typeof Ecs20140526>;
private constructor(credentialClient: InstanceType<typeof Credential>) {
const config = new Config({
endpoint: 'ecs.cn-hangzhou.aliyuncs.com',
credential: credentialClient
});
this.ecsClient = new Ecs20140526(config);
}
static getInstance(credentialClient: InstanceType<typeof Credential>): InstanceType<typeof Ecs20140526> {
if (!EcsClient.instance) {
EcsClient.instance = new EcsClient(credentialClient);
}
return EcsClient.instance.ecsClient;
}
}
/**
* 執行任務邏輯
*/
async function executeTask(): Promise<void> {
try {
const credentialClient = CredentialClient.getInstance();
const credential = await credentialClient.getCredential();
console.log(new Date());
console.log(`AK ID: ${credential.accessKeyId}`);
console.log(`AK Secret: ${credential.accessKeySecret}`);
console.log(`STS Token: ${credential.securityToken}`);
// 這裡以調用ECS介面為例驗證憑據是否可用,您可根據實際情況修改
const ecsClient = EcsClient.getInstance(credentialClient);
const request = new $Ecs20140526.DescribeRegionsRequest();
const runtime = new RuntimeOptions({});
const response = await ecsClient.describeRegionsWithOptions(request, runtime);
console.log(`Invoke result: ${response.statusCode}`);
} catch (error) {
throw new Error(`ECS client execution failed: ${error}`);
}
}
/**
* 使用定時器調度任務執行
*/
function scheduleTasks(): void {
// 立即執行一次
executeTask();
// 設定後續任務順延強制
setTimeout(executeTask, 600 * 1000); // 第二次:600秒後
setTimeout(executeTask, 4200 * 1000); // 第三次:4200秒後
setTimeout(executeTask, 4300 * 1000); // 第四次:4300秒後
}
// 啟動任務調度
scheduleTasks();
根據日誌顯示結果進行分析:
在第一次調用時,由於未緩衝憑據資訊,系統根據配置擷取憑據資訊。擷取到憑據後,憑據資訊被儲存在緩衝中。
第二次調用所使用的憑據資訊與第一次相同,表明第二次調用是從緩衝中提取的憑據資訊。
第三次調用時,由於憑據的到期時間(RoleSessionExpiration)被設定為3600秒,而第三次調用發生在第一次調用之後的4200秒,此時緩衝中的憑據已到期。因此,SDK依據自動重新整理機制重新擷取了新的憑據資訊,並將新擷取的憑據資訊再次儲存於緩衝中。
第四次調用所使用的憑據資訊與第三次重新擷取的憑據資訊一致,這表明緩衝中的憑據在到期後已被更新為新的憑據。
相關文檔
RAM相關的基本概念,請參見基本概念。
如何建立AccessKey,請參見建立AccessKey。
如何通過程式方式建立RAM使用者、AccessKey、RAM角色、權限原則及進行授權等操作,請參見RAM SDK概覽。
如何通過程式方式進行角色扮演,請參見STS SDK概覽。
關於RAM及STS相關的API資訊,請參見API參考。