全部產品
Search
文件中心

Alibaba Cloud SDK:管理訪問憑證

更新時間:Dec 20, 2025

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

背景資訊

憑據是指使用者證明其身份的一組資訊。使用者在系統中進行登入時,需要提供正確的憑據才能驗證身份。常見的憑據類型有:

  1. 阿里雲主帳號和RAM使用者的永久憑據 AccessKey(簡稱AK)是由AccessKey ID和AccessKey Secret組成的金鑰組。

  2. 阿里雲RAM角色的STS臨時訪問Token,簡稱STS Token。它是可以自訂時效和存取權限的臨時身份憑據,詳情請參見什麼是STS

  3. Bearer Token。它是一種身分識別驗證和授權的令牌類型。

前提條件

安裝Credentials工具

如果已安裝Credentials工具,可跳過本步驟。建議使用最新版本的Credentials依賴包,以確保全面支援所有憑據類型。您可以在Credentials中查看所有發行版本的資訊。

Credentials 工具可通過以下任意方式安裝:

  • 方式一:使用go get下載安裝:

    $ go get -u github.com/aliyun/credentials-go
  • 方式二:如果您使用dep來管理依賴包,您可以使用以下命令:

    dep ensure -add github.com/aliyun/credentials-go

Credentials工具配置參數介紹

Credentials工具的配置參數定義在github.com/aliyun/credentials-go/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:自訂會話名稱,預設格式為credentials-go-目前時間的時間戳記

×

×

-

×

-

×

×

RoleName:RAM角色名稱。

×

×

×

-

×

×

×

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

×

×

×

-

×

×

×

BearerToken:bearer token。

×

×

×

×

×

×

Policy:自訂權限原則。

×

×

-

×

-

×

×

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

×

×

-

×

-

×

×

OIDCProviderArn:OIDC供應商ARN。

×

×

×

×

×

×

OIDCTokenFilePath:OIDC Token檔案路徑。

×

×

×

×

×

×

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

×

×

-

×

×

×

×

Url:憑證的URI,該參數需通過SetURLCredential(v string)賦值。

×

×

×

×

×

×

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

×

×

-

×

-

×

×

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

×

×

-

-

-

-

×

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

×

×

-

-

-

-

×

初始化憑據用戶端

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

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

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

方式一:使用預設憑據鏈

當您在初始化憑據用戶端不傳入任何參數時,Credentials會使用預設憑據鏈方式初始化用戶端。預設憑據的讀取邏輯請參見預設憑據鏈

package main

import (
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	// 不指定參數或者傳入nil
	credential, err := credentials.NewCredential(nil)
	
	config := &openapi.Config{}
        config.Credential = credential
        // 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本
}

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	// 使用預設憑證初始化Credentials Client。
	credentialClient, _err := credentials.NewCredential(nil)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式二:使用AK

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

警告

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

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

import (
	"fmt"
	"os"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	config := new(credentials.Config).
		SetType("access_key").
		SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
		SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))

	akCredential, err := credentials.NewCredential(config)
	if err != nil {
		return
	}
	
	config := &openapi.Config{}
        config.Credential = akCredential
        // 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本
}

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
	"os"
)

func main() {
	// 使用AK 初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("access_key").
		// 設定為AccessKey ID值。
		SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
		// 設定為AccessKey Secret值。
		SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式三:使用STS Token

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

package main

import (
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
	"os"
)

func main() {
	config := new(credentials.Config).
		SetType("sts").
		// 從環境變數中擷取AccessKey Id。
		SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
		// 從環境變數中擷取AccessKey Secret
		SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")).
		// 從環境變數中擷取STS臨時憑證。
		SetSecurityToken(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN"))

	stsCredential, err := credentials.NewCredential(config)
	if err != nil {
		return
	}
	
	config := &openapi.Config{}
        config.Credential = stsCredential
        // 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本
}

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝Elastic Compute Service SDKSecurity Token Service SDK

package main

import (
	"os"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	sts20150401 "github.com/alibabacloud-go/sts-20150401/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	// 建立STS client,調用AssumeRole擷取STS TOKEN
	stsConfig := &openapi.Config{}
	stsConfig.SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
	stsConfig.SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
	stsConfig.SetEndpoint("sts.cn-hangzhou.aliyuncs.com")
	client, _err := sts20150401.NewClient(stsConfig)
	if _err != nil {
		panic(_err)
	}
	assumeRoleRequest := &sts20150401.AssumeRoleRequest{}
	// 要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
	assumeRoleRequest.SetRoleArn("<RoleArn>")
	// 角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
	assumeRoleRequest.SetRoleSessionName("<RoleSessionName>")
	assumeRoleRequest.SetDurationSeconds(3600)
	result, _err := client.AssumeRole(assumeRoleRequest)
	if _err != nil {
		panic(_err)
	}
	assumeRoleResponseBodyCredentials := result.Body.Credentials

	// 使用STS Token初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("sts").
		SetAccessKeyId(*assumeRoleResponseBodyCredentials.AccessKeyId).
		SetAccessKeySecret(*assumeRoleResponseBodyCredentials.AccessKeySecret).
		SetSecurityToken(*assumeRoleResponseBodyCredentials.SecurityToken)

	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-hangzhou.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式四:使用AK及RamRoleArn

該方式底層實現是STS Token。通過指定RAM角色的ARN(Alibabacloud Resource Name),Credentials工具可以協助開發人員前往STS換取STS Token。您也可以通過為SetPolicy賦值來限制RAM角色到一個更小的許可權集合。

package main

import (
	"fmt"
	"os"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	config := new(credentials.Config).
		SetType("ram_role_arn").
		SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
		SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")).
		// 要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
		SetRoleArn("<RoleArn>").
		// 角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
		SetRoleSessionName("<RoleSessionName>").
		// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
		SetPolicy("<Policy>").
		// 非必填,設定session到期時間。
		SetRoleSessionExpiration(3600).
		// 非必填,角色外部 ID,該參數為外部提供的用於表示角色的參數資訊,主要功能是防止混淆代理人問題。
		SetExternalId("ExternalId").
		// 非必填,預設為sts.aliyuncs.com,建議使用Region化的STS網域名稱,選擇地理位置更接近的Region可以保證網路連通性.
		SetSTSEndpoint("sts.cn-hangzhou.aliyuncs.com")

	arnCredential, err := credentials.NewCredential(config)
	if err != nil {
		return
	}

	config := &openapi.Config{}
        config.Credential = arnCredential
        // 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本
}
說明

ExternalId的更多介紹,請參見使用ExternalId防止混淆代理人問題

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
	"os"
)

func main() {
	// 使用RamRoleArn初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("ram_role_arn").
		// 設定為AccessKey ID值。
		SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
		// 設定為AccessKey Secret值。
		SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")).
		// 要扮演的RAM角色ARN,樣本值:acs:ram::123456789012****:role/adminrole,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
		SetRoleArn("<RoleArn>").
		// 角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
		SetRoleSessionName("<RoleSessionName>").
		// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
		SetPolicy("<Policy>").
		// 設定session到期時間,非必填。
		SetRoleSessionExpiration(3600).
		// 非必填,預設為sts.aliyuncs.com,建議使用Region化的STS網域名稱,選擇地理位置更接近的Region可以保證網路連通性.
		SetSTSEndpoint("sts.cn-hangzhou.aliyuncs.com")
	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式五:使用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中繼資料的憑證訪問。

說明
package main

import (
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
)

func _main(args []*string) {
	// 使用EcsRamRole初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("ecs_ram_role").
		// 選填,該ECS角色的角色名稱,不填會自動擷取,但是建議加上以減少請求次數,可以通過環境變數ALIBABA_CLOUD_ECS_METADATA設定RoleName
		SetRoleName("<RoleName>")
	// 選填,預設值:false。true:表示強制使用加固模式。false:系統將首先嘗試在加固模式下擷取憑據。如果失敗,則會切換到普通模式(IMDSv1)進行嘗試
	// credentialsConfig.SetDisableIMDSv1(true)
	credentialClient, err := credentials.NewCredential(credentialsConfig)
	if err != nil {
		return
	}
	config := &openapi.Config{}
        config.Credential = credentialClient
        // 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本。
}

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credentials "github.com/aliyun/credentials-go/credentials"
)

func main() {
	// 使用EcsRamRole初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("ecs_ram_role").
		// 選填,該ECS角色的角色名稱,不填會自動擷取,但是建議加上以減少請求次數,可以通過環境變數ALIBABA_CLOUD_ECS_METADATA設定RoleName
		SetRoleName("<RoleName>")
	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式六:使用OIDCRoleArn

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

package main

import (
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
	"os"
)

func main() {
	config := new(credentials.Config).
		SetType("oidc_role_arn").
		// OIDC供應商ARN,可以通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定OidcProviderArn
		SetOIDCProviderArn(os.Getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN")).
		// OIDC Token檔案路徑,可以通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定OidcTokenFilePath
		SetOIDCTokenFilePath(os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE")).
		// RAM角色名稱ARN,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
		SetRoleArn(os.Getenv("ALIBABA_CLOUD_ROLE_ARN")).
		// 角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
		SetRoleSessionName(os.Getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME")).
		// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
		SetPolicy("<Policy>").
		// 非必填,設定session到期時間
		SetRoleSessionExpiration(3600).
		// 非必填,預設為sts.aliyuncs.com,建議使用Region化的STS網域名稱,選擇地理位置更接近的Region可以保證網路連通性
		SetSTSEndpoint("sts.cn-hangzhou.aliyuncs.com")
	oidcCredential, err := credentials.NewCredential(config)
	if err != nil {
		return
	}
	
	config := &openapi.Config{}
	config.Credential = oidcCredential
	// 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本。
}

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	"os"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credentials "github.com/aliyun/credentials-go/credentials"
)

func main() {
	// 使用OIDCRoleArn初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("oidc_role_arn").
		// OIDC供應商ARN,可以通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定OidcProviderArn
		SetOIDCProviderArn(os.Getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN")).
		// OIDC Token檔案路徑,可以通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定OidcTokenFilePath
		SetOIDCTokenFilePath(os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE")).
		// RAM角色名稱ARN,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
		SetRoleArn(os.Getenv("ALIBABA_CLOUD_ROLE_ARN")).
		// 角色會話名稱,可以通過環境變數ALIBABA_CLOUD_ROLE_SESSION_NAME設定RoleSessionName
		SetRoleSessionName(os.Getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME")).
		// 設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
		SetPolicy("<Policy>").
		// 設定session到期時間
		SetRoleSessionExpiration(3600)
	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = credentialClient
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式七:使用URI憑據

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

package main

import (
	"github.com/aliyun/credentials-go/credentials"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
)

func main() {
	config := new(credentials.Config).
		SetType("credentials_uri").
                // 憑證的 URI,格式為http://local_or_remote_uri/,可以通過環境變數ALIBABA_CLOUD_CREDENTIALS_URI設定CredentialsUri
		SetURLCredential("<CredentialsUri>")

	uriCredential, err := credentials.NewCredential(config)
	config := &openapi.Config{}
	config.Credential = uriCredential
	// 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本。
}

該地址必須滿足如下條件:

  • 支援GET請求。

  • 響應體為如下的結構:

    {
      "AccessKeySecret": "AccessKeySecret",
      "AccessKeyId": "AccessKeyId",
      "Expiration": "2021-09-26T03:46:38Z",
      "SecurityToken": "SecurityToken"
    }

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credentials "github.com/aliyun/credentials-go/credentials"
)

func main() {
	config := new(credentials.Config).
		SetType("credentials_uri").
		// 憑證的 URI,格式為http://local_or_remote_uri/,可以通過環境變數ALIBABA_CLOUD_CREDENTIALS_URI設定CredentialsUri
		SetURLCredential("<CredentialsUri>")

	uriCredential, _err := credentials.NewCredential(config)
	if _err != nil {
		panic(_err)
	}

	ecsConfig := &openapi.Config{}
	// 配置雲產品服務接入地址(endpoint)。
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	// 使用Credentials配置憑證。
	ecsConfig.Credential = uriCredential
	// 初始化ECS Client。
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	// 初始化DescribeRegions請求。
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	// 初始化運行時配置。
	runtime := &util.RuntimeOptions{}
	// 調用DescribeRegions介面並獲得響應。
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

方式八:使用Bearer Token

目前只有Cloud Call CenterCCC這款產品支援Bearer Token的憑據初始化方式。

package main

import (
	"fmt"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials"
)

func main() {
	config := new(credentials.Config).
		SetType("bearer").
		// 填入您的Bearer Token
		SetBearerToken("<BearerToken>")
	bearerCredential, err := credentials.NewCredential(config)
	if err != nil {
		return
	}
	config := &openapi.Config{}
	config.Credential = bearerCredential
	// 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本。
}

介面調用樣本

本樣本以調用話務中心CCC的GetInstance介面為例,因此需先安裝CCC SDK

package main

import (
	ccc20200701 "github.com/alibabacloud-go/ccc-20200701/v2/client"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	credentials "github.com/aliyun/credentials-go/credentials"
)

func _main() (_err error) {
	// 使用Bearer Token初始化Credentials Client。
	credentialsConfig := new(credentials.Config).
		// 憑證類型。
		SetType("bearer").
		SetBearerToken("<BearerToken>")
	credentialClient, _err := credentials.NewCredential(credentialsConfig)
	if _err != nil {
		return _err
	}

	// 使用Credentials Client初始化CCC Client。
	config := &openapi.Config{}
	config.Endpoint = tea.String("ccc.cn-shanghai.aliyuncs.com") // 配置雲產品服務接入地址(endpoint)。
	config.Credential = credentialClient                         // 使用Credentials配置憑證。
	cccClient, _err := ccc20200701.NewClient(config)
	if _err != nil {
		return _err
	}
	getInstanceRequest := &ccc20200701.GetInstanceRequest{
		InstanceId: tea.String("ccc-test"),
	}
	runtime := &util.RuntimeOptions{}
	response, _err := cccClient.GetInstanceWithOptions(getInstanceRequest, runtime)
	if _err != nil {
		return _err
	}
	panic(response.Body.String())
}

func main() {
	err := _main()
	if err != nil {
		panic(err)
	}
}

方式九:使用CLIProfileCredentialsProvider

阿里雲CLI憑據配置隱藏檔(config.json)中擷取訪問憑據。

package main

import (
	"github.com/aliyun/credentials-go/credentials"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	"github.com/aliyun/credentials-go/credentials/providers"
)

func main() {
	// CLIProfileCredentialsProvider
	provider, err := providers.NewCLIProfileCredentialsProviderBuilder().
	        // 憑據名稱,非必填。支援多種方式配置,優先順序從高到低:顯示指定的profileName -> 使用環境變數ALIBABA_CLOUD_CONFIG_FILE指定的profileName -> 預設讀取config.json中的current.
		WithProfileName("<PROFILE_NAME>"). 
		// 設定檔路徑,必須是一個.json檔案,非必填。支援多種方式配置,優先順序從高到低:顯示指定的profileFile -> 使用環境變數ALIBABA_CLOUD_CONFIG_FILE指定的profileFile -> 預設讀取 ~/.aliyun/config.json.
		WithProfileFile("<PROFILE_FILE_PATH>"). 
		Build()
	if err != nil {
		return
	}
	credential := credentials.FromCredentialsProvider("cli_profile", provider)
	config := &openapi.Config{}
	config.Credential = credential
	// 省略使用config初始化雲產品client部分內容,具體請參見介面調用樣本。
}

您可以通過阿里雲CLI配置憑證,或者手動在以下路徑建立config.json設定檔:

  • Linux系統:~/.aliyun/config.json

  • Windows系統:C:\Users\USER_NAME\.aliyun\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
    },
    {
      "name": "<PROFILE_NAME6>",
      "mode": "CloudSSO",
      "cloud_sso_sign_in_url": "https://******/login",
      "access_token": "eyJraWQiOiJiYzViMzUwYy******",
      "cloud_sso_access_token_expire": 1754316142,
      "cloud_sso_access_config": "ac-00s1******",
      "cloud_sso_account_id": "151266******"
    }
  ]
}

config.json設定檔中可以通過mode指定不同的憑據:

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

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

  • RamRoleArn:使用RAM角色的ARN來擷取憑據資訊;

  • EcsRamRole:利用ECS綁定的RAM角色來擷取憑據資訊;

  • OIDC:通過OIDC ARN和OIDC Token來擷取憑據資訊;

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

  • CloudSSO:雲SSO使用者使用阿里雲CLI擷取的憑據資訊。

    說明

    CloudSSO憑據要求github.com/aliyun/credentials-go的版本不低於1.4.7,且配置內容僅支援通過阿里雲CLI擷取,具體資訊請參見使用CLI登入雲SSO並訪問阿里雲資源

配置完成後,Credentials將根據指定的憑據名稱,選擇對應的憑據初始化憑據用戶端。

介面調用樣本

本樣本以調用Elastic Compute Service的DescribeRegions介面為例,因此需先安裝ECS SDK

package main

import (
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
	"github.com/aliyun/credentials-go/credentials/providers"
)

func main() {
	// CLIProfileCredentialsProvider
	provider, err := providers.NewCLIProfileCredentialsProviderBuilder().
		WithProfileName("SSOProfile"). // 非必填,會預設讀取config.json中的current
		// WithProfileFile("/path/to/config.json"). // 非必填,會預設讀取 ~/.aliyun/config.json
		Build()
	if err != nil {
		return
	}

	credentialClient := credentials.FromCredentialsProvider("cli_profile", provider)

	// 使用Credentials初始化ECS Client。
	ecsConfig := &openapi.Config{}
	ecsConfig.Endpoint = tea.String("ecs.cn-beijing.aliyuncs.com")
	ecsConfig.Credential = credentialClient
	ecsClient, _err := ecs20140526.NewClient(ecsConfig)
	describeInstancesRequest := &ecs20140526.DescribeRegionsRequest{}
	runtime := &util.RuntimeOptions{}
	response, _err := ecsClient.DescribeRegionsWithOptions(describeInstancesRequest, runtime)
	if _err != nil {
		panic(_err)
	}
	panic(response.Body.String())
}

預設憑據鏈

當開發環境與生產環境使用的憑據類型不一致時,常見做法是在代碼中擷取當前環境資訊,編寫擷取不同憑據的分支代碼。藉助Credentials工具的預設憑據鏈,您可以用同一套代碼,通過程式之外的配置來控制不同環境下的憑據擷取方式。當您使用NewCredential()初始化憑據用戶端,且不傳入任何參數時,阿里雲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/Mac系統:~/.aliyun/config.json

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

說明

github.com/aliyun/credentials-go@1.4.4版本起,支援通過環境變數 ALIBABA_CLOUD_CONFIG_FILE 自訂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
        },
        {
            "name": "<PROFILE_NAME6>",
            "mode": "CloudSSO",
            "cloud_sso_sign_in_url": "https://******/login",
            "access_token": "eyJraWQiOiJiYzViMzUwYy******",
            "cloud_sso_access_token_expire": 1754316142,
            "cloud_sso_access_config": "ac-00s1******",
            "cloud_sso_account_id": "151266******"
        },
        {
            "name": "<PROFILE_NAME7>",
            "mode": "OAuth",
            "access_key_id": "<ALIBABA_CLOUD_ACCESS_KEY_ID>",
            "access_key_secret": "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>",
            "sts_token": "<SECURITY_TOKEN>",
            "region_id": "<REGION_ID>",
            "output_format": "json",
            "language": "<zh|en>",
            "sts_expiration": "<STS_EXPIRATION>",
            "oauth_access_token": "<OAUTH_ACCESS_TOKEN>",
            "oauth_refresh_token": "<OAUTH_REFRESH_TOKEN>",
            "oauth_access_token_expire": 1754316142,
            "oauth_site_type": "<CN|EN>"
        }
    ]
}

config.json設定檔中可以通過mode指定不同的憑據:

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

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

  • RamRoleArn:使用RAM角色的ARN來擷取憑據資訊;

  • EcsRamRole:利用ECS綁定的RAM角色來擷取憑據資訊;

  • OIDC:通過OIDC ARN和OIDC Token來擷取憑據資訊;

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

  • OAuth: 使用CLI通過OAuth登入方式來擷取的憑據資訊。

  • CloudSSO:雲SSO使用者使用阿里雲CLI擷取的憑據資訊。

說明
  • OAuth憑據要求github.com/aliyun/credentials-go的版本不低於1.4.8,且配置內容僅支援通過阿里雲CLI擷取,具體資訊請參見使用CLI擷取OAuth憑證

  • CloudSSO憑據要求github.com/aliyun/credentials-go的版本不低於1.4.7,且配置內容僅支援通過阿里雲CLI擷取,具體資訊請參見使用CLI登入雲SSO並訪問阿里雲資源

配置完成後,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,執行不同的異常處理邏輯:

  1. 當值為false時,會使用普通模式繼續擷取訪問憑據。

  2. 當值為true時,表示只能使用加固模式擷取訪問憑據,會拋出異常。

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

另外,您可以通過配置環境變數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確保所擷取的憑據處於可用狀態。

package main

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	ecs20140526 "github.com/alibabacloud-go/ecs-20140526/v7/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/aliyun/credentials-go/credentials"
)

// Credential 單例結構體,用於管理阿里雲憑證執行個體
type Credential struct {
	instance credentials.Credential
	once     sync.Once
}

var credentialInstance = &Credential{}

func GetCredentialInstance() credentials.Credential {
	credentialInstance.once.Do(func() {
		cfg := &credentials.Config{
			Type:                  tea.String("ram_role_arn"),
			AccessKeyId:           tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
			AccessKeySecret:       tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
			RoleArn:               tea.String(os.Getenv("ALIBABA_CLOUD_ROLE_ARN")),
			RoleSessionName:       tea.String("RamRoleArnTest"),
			RoleSessionExpiration: tea.Int(3600),
		}
		var err error
		credentialInstance.instance, err = credentials.NewCredential(cfg)
		if err != nil {
			log.Fatalf("Credential initialization failed: %v", err)
		}
	})
	return credentialInstance.instance
}

// EcsClient 單例結構體,用於管理 ECS 用戶端執行個體
type EcsClient struct {
	instance *ecs20140526.Client
	once     sync.Once
}

var ecsClientInstance = &EcsClient{}

func GetEcsClientInstance(cred credentials.Credential) *ecs20140526.Client {
	ecsClientInstance.once.Do(func() {
		cfg := &openapi.Config{
			Endpoint:   tea.String("ecs.cn-hangzhou.aliyuncs.com"),
			Credential: cred,
		}
		var err error
		ecsClientInstance.instance, err = ecs20140526.NewClient(cfg)
		if err != nil {
			log.Fatalf("ECS client initialization failed: %v", err)
		}
	})
	return ecsClientInstance.instance
}

// 執行主任務
func runTask() {
	cred := GetCredentialInstance()
	credentialModel, err := cred.GetCredential()
	if err != nil {
		log.Printf("Failed to get credential: %v", err)
		return
	}

	fmt.Println(time.Now())
	fmt.Printf("AK ID: %s, AK Secret: %s, STS Token: %s\n",
		*credentialModel.AccessKeyId,
		*credentialModel.AccessKeySecret,
		*credentialModel.SecurityToken)

	ecsClient := GetEcsClientInstance(cred)
	req := &ecs20140526.DescribeRegionsRequest{}
	runtime := &util.RuntimeOptions{}

	resp, err := ecsClient.DescribeRegionsWithOptions(req, runtime)
	if err != nil {
		log.Printf("ECS API call failed: %v", err)
		return
	}

	fmt.Printf("Invoke result: %d\n", *resp.StatusCode)
}

func main() {
	done := make(chan bool)

	// 啟動一個 goroutine 來執行定時任務
	go func() {
		tick := time.NewTicker(1 * time.Second)
		defer tick.Stop()

		executionCount := 0
		delays := []time.Duration{0, 600, 3600, 100} // 延遲時間(秒)

		for {
			select {
			case <-tick.C:
				if executionCount < len(delays) {
					delay := delays[executionCount]
					time.Sleep(delay * time.Second)
					runTask()
					executionCount++
				} else {
					close(done)
					return
				}
			}
		}
	}()

	<-done
	fmt.Println("All tasks completed. Exiting...")
}

image

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

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

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

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

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

相關文檔