在使用阿里雲SDK調用OpenAPI操作資源時,必須正確配置憑證資訊。Go V1.0 SDK支援多種憑據配置方式,本文詳細闡述了如何配置訪問憑據,以確保安全有效地使用SDK進行開發。
背景資訊
在使用阿里雲SDK進行開發時,需要根據具體的應用情境和授權需求選擇合適的訪問憑據類型,並正確配置和管理這些憑據。通過合理設定環境變數或設定檔,確保SDK能夠正確讀取和使用憑據,從而協助開發人員構建穩定、可靠的應用程式。
前提條件
Go 環境版本必須不低於 1.10.x。
安裝 SDK 核心庫 Core
go get -u github.com/aliyun/alibaba-cloud-sdk-go/sdk
初始化憑據用戶端
方式一:使用預設憑證鏈
當您在初始化憑據用戶端不傳入任何參數時,SDK會使用預設憑據鏈方式初始化用戶端。預設憑據的讀取邏輯請參見預設憑據鏈。
package main
import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/provider"
)
func main() {
config := sdk.NewConfig()
// 不傳參數
credentialsProvider := credentials.NewDefaultCredentialsProvider()
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou。
sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
方式二:使用AK
阿里雲帳號和RAM使用者可以產生用於調用OpenAPI的AccessKey金鑰組,您可以使用該AccessKey初始化用戶端。
由於主帳號AccessKey有資源完全的許可權,一旦泄露風險巨大。建議您使用RAM使用者的AccessKey,並設定定期輪換,建立RAM使用者AccessKey的方法請參見建立AccessKey。
package main
import (
"os"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
config := sdk.NewConfig()
// 這裡通過環境變數擷取RAM使用者的AccessKey ID和AccessKey Secret,以避免寫入程式碼帶來的安全風險
credentialsProvider := credentials.NewStaticAKCredentialsProvider(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou
sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
方式三:使用STS Token
通過Security Token Service(Security Token Service,簡稱 STS),申請臨時安全憑證(Temporary Security Credentials,簡稱 TSC),建立臨時安全用戶端。
package main
import (
"os"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
config := sdk.NewConfig()
// 這裡通過環境變數擷取RAM使用者的AccessKey ID、AccessKey Secret和STS Token,以避免寫入程式碼帶來的安全風險
credentialsProvider := credentials.NewStaticSTSCredentialsProvider(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"), os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN"))
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou。
client, err := sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
方式四:使用AK及RamRoleArn
通過指定RAM角色的ARN(Alibabacloud Resource Name)來初始化用戶端。用戶端在發起請求前,需先通過調用STS服務擷取STS Token。若需限制STS Token的許可權,可使用自訂權限原則.
package main
import (
"os"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
config := sdk.NewConfig()
credentialsProvider := credentials.NewRamRoleArnWithPolicyAndExternalIdCredential(
// os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"):從環境變數中擷取RAM使用者AccessKey ID
os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
// os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"):從環境變數中擷取RAM使用者AccessKey Secret
os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
// "<ROLE_ARN>":指定要扮演的RAM角色的ARN。樣本值:acs:ram::123456789012****:role/adminrole。
"<ROLE_ARN>",
// "<ROLE_SESSION_NAME>":指定角色會話的名稱,用於標識和區分不同的會話。樣本值:alice。
"<ROLE_SESSION_NAME>",
// "<POLICY>":指定一個自訂的授權策略用於限制角色會話的許可權。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}。
"<POLICY>",
// "<EXTERNAL_ID>":指定一個角色外部ID,防止混淆代理人問題。樣本值:abcd1234。
"<EXTERNAL_ID>",
// <ROLE_SESSION_EXPIRATION>:Token 有效期間。樣本值:3600。
"<ROLE_SESSION_EXPIRATION>"
)
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou
client, err := sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
方式五:使用ECS執行個體RAM角色
ECS和ECI執行個體均支援綁定執行個體RAM角色,當在執行個體中使用Credentials工具時,將自動擷取執行個體綁定的RAM角色,並通過訪問中繼資料服務擷取RAM角色的STS Token,以完成憑據用戶端的初始化。
執行個體中繼資料服務器支援加固模式和普通模式兩種訪問方式,Credentials工具預設使用加固模式(IMDSv2)擷取訪問憑據。若使用加固模式時發生異常,您可以通過環境變數ALIBABA_CLOUD_IMDSV1_DISABLED,執行不同的異常處理邏輯:
當值為
false
(預設值)時,會使用普通模式繼續擷取訪問憑據。當值為
true
時,表示只能使用加固模式擷取訪問憑據,會拋出異常。
服務端是否支援IMDSv2,取決於您在伺服器的配置。
關於ECS執行個體中繼資料的介紹,請參見執行個體中繼資料。
如何為ECS和ECI執行個體授予RAM角色,具體操作請參見建立RAM角色並授予給ECS執行個體和為ECI執行個體授予執行個體RAM角色。
package main
import (
"os"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
// 通過ECS執行個體的RAM角色來擷取訪問憑證,從而建立一個阿里雲用戶端
// 它適用於那些需要在ECS執行個體上運行,並且需要訪問其他阿里雲資源的程式
// "<ROLE_NAME>":指定要使用的RAM角色名稱,您可以在環境變數ALIBABA_CLOUD_ECS_METADATA中設定 roleName 預設值。樣本值:alice。
credentialsProvider := credentials.NewECSRAMRoleCredentialsProvider("<ROLE_NAME>")
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou。
client, err := sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
方式六:使用OIDCRoleArn
在Container Service Kubernetes 版中,設定 Worker 節點 RAM 角色後,節點內的 Pod 可以通過中繼資料服務擷取關聯角色的 STS Token。然而,對於不可信的應用(如客戶提交的未公開代碼的應用),直接通過中繼資料服務擷取 STS Token 可能會帶來安全風險。為瞭解決這一問題並實現應用層級的許可權最小化,可以使用 RRSA(RAM Roles for Service Account)功能。這有助於確保雲上資源的安全性,同時允許不可信應用安全地擷取所需的 STS Token。阿里雲容器叢集會為不同的應用Pod建立和掛載相應的服務賬戶OIDC Token檔案,並將相關配置資訊注入到環境變數中,Credentials工具通過擷取環境變數的配置資訊,調用STS服務的AssumeRoleWithOIDC - OIDC角色SSO時擷取扮演角色的臨時身份憑證介面換取綁定角色的STS Token。詳情請參見通過RRSA配置ServiceAccount的RAM許可權實現Pod許可權隔離。注入的環境變數如下:
ALIBABA_CLOUD_ROLE_ARN:RAM角色名稱ARN;
ALIBABA_CLOUD_OIDC_PROVIDER_ARN:OIDC供應商ARN;
ALIBABA_CLOUD_OIDC_TOKEN_FILE:OIDC Token檔案路徑;
package main
import (
"os"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
config := sdk.NewConfig()
// 使用OIDCRoleArn初始化SDK用戶端
oidcProvider, _ := credentials.NewOIDCCredentialsProviderBuilder().
// OIDC供應商ARN,可以通過環境變數ALIBABA_CLOUD_OIDC_PROVIDER_ARN設定OIDCProviderARN
WithOIDCProviderARN(os.Getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN")).
// OIDC Token檔案路徑,可以通過環境變數ALIBABA_CLOUD_OIDC_TOKEN_FILE設定OIDCTokenFilePath
WithOIDCTokenFilePath(os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE")).
// RAM角色名稱ARN,可以通過環境變數ALIBABA_CLOUD_ROLE_ARN設定RoleArn
WithRoleArn(os.Getenv("ALIBABA_CLOUD_ROLE_ARN")).
// "<ROLE_SESSION_NAME>":自訂角色會話名稱。樣本值:alice。
WithRoleSessionName("<ROLE_SESSION_NAME>").
// "<POLICY>":設定更小的權限原則,非必填。樣本值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}。
WithPolicy("<POLICY>").
// <ROLE_SESSION_EXPIRATION>:設定session到期時間。樣本值:3600。
WithDurationSeconds( "<ROLE_SESSION_EXPIRATION>").
Build()
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou。
client, err := sdk.NewClientWithOptions("<REGION_ID>", config, oidcProvider)
// 省略調用API步驟...
}
方式七:使用Bearer Token
目前只有Cloud Call CenterCCC這款產品支援Bearer Token的憑據初始化方式。
package main
import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
)
func main() {
config := sdk.NewConfig()
// <BEARER_TOKEN>是一種認證方式,用於授權訪問API
credentialsProvider := credentials.NewBearerTokenCredentialsProvider("BEARER_TOKEN")
// <REGION_ID>:指定用戶端要訪問的阿里雲地區。樣本值:cn_hangzhou。
client, err := sdk.NewClientWithOptions("<REGION_ID>", config, credentialsProvider)
// 省略調用API步驟...
}
預設憑據鏈
當開發環境與生產環境使用的憑據類型不一致時,常見做法是在代碼中擷取當前環境資訊,編寫擷取不同憑據的分支代碼。藉助Credentials工具的預設憑據鏈,您可以用同一套代碼,通過程式之外的配置來控制不同環境下的憑據擷取方式。當您使用credentials.NewDefaultCredentialsProvider()
初始化憑據用戶端,且不傳入任何參數時,阿里雲SDK將會嘗試按照如下順序尋找相關憑據資訊。
1. 使用環境變數
若不存在優先順序更高的憑據資訊,Credentials工具會優先在環境變數中擷取憑據資訊。
如果系統內容變數ALIBABA_CLOUD_ACCESS_KEY_ID(密鑰Key) 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET(密鑰Value) 不為空白,Credentials工具會優先使用它們作為預設憑據。
如果系統內容變數ALIBABA_CLOUD_ACCESS_KEY_ID(密鑰Key)、ALIBABA_CLOUD_ACCESS_KEY_SECRET(密鑰Value)、ALIBABA_CLOUD_SECURITY_TOKEN(Token)均不為空白,Credentials工具會優先使用STS Token作為預設憑據。
2. 使用OIDC RAM角色
若不存在優先順序更高的憑據資訊,Credentials工具會在環境變數中擷取如下內容:
ALIBABA_CLOUD_ROLE_ARN:RAM角色名稱ARN;
ALIBABA_CLOUD_OIDC_PROVIDER_ARN:OIDC供應商ARN;
ALIBABA_CLOUD_OIDC_TOKEN_FILE:OIDC Token檔案路徑;
若以上三個環境變數都已設定內容,Credentials將會使用變數內容調用STS服務的AssumeRoleWithOIDC - OIDC角色SSO時擷取扮演角色的臨時身份憑證介面換取STS Token作為預設憑據。
3. 使用config.json設定檔
若不存在優先順序更高的憑據資訊,Credentials工具會優先在如下位置尋找config.json檔案是否存在:
Linux系統:~/.aliyun/config.json
Windows系統: C:\Users\USER_NAME\.aliyun\config.json
如果檔案存在,程式將會使用設定檔中current 指定的憑據資訊初始化憑據用戶端。當然,您也可以通過環境變數 ALIBABA_CLOUD_PROFILE 來指定憑據資訊,例如設定 ALIBABA_CLOUD_PROFILE 的值為client1。
在config.json設定檔中每個mode的值代表了不同的憑據資訊擷取方式:
AK:使用使用者的Access Key作為憑據資訊;
RamRoleArn:使用RAM角色的ARN來擷取憑據資訊;
EcsRamRole:利用ECS綁定的RAM角色來擷取憑據資訊;
OIDC:通過OIDC ARN和OIDC Token來擷取憑據資訊;
ChainableRamRoleArn:採用角色鏈的方式,通過指定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":"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
}
]
}
4. ECS執行個體RAM角色
若不存在優先順序更高的憑據資訊,Credentials工具將通過環境變數擷取ALIBABA_CLOUD_ECS_METADATA(ECS執行個體RAM角色名稱)的值。若該變數的值存在,程式將採用加固模式(IMDSv2)訪問ECS的中繼資料服務(Meta Data Server),以擷取ECS執行個體RAM角色的STS Token作為預設憑據資訊。在使用加固模式時若發生異常,將使用普通模式兜底來擷取訪問憑據。您也可以通過設定環境變數ALIBABA_CLOUD_IMDSV1_DISABLED,執行不同的異常處理邏輯:
當值為
false
(預設值)時,會使用普通模式繼續擷取訪問憑據。當值為
true
時,表示只能使用加固模式擷取訪問憑據,會拋出異常。
服務端是否支援IMDSv2,取決於您在伺服器的配置。
5. 使用Credentials工具URI
若不存在優先順序更高的憑據資訊,Credentials工具會在環境變數中擷取ALIBABA_CLOUD_CREDENTIALS_URI,若存在,程式將請求該URI地址,擷取臨時安全憑證作為預設憑據資訊。