When you call API operations to manage cloud resources by using Alibaba Cloud SDKs, you must configure valid credential information. The Alibaba Cloud Credentials tool provides powerful features that allow you to obtain and manage access credentials with ease. This topic describes how to use the Credentials tool to configure various types of credentials such as the default credential, AccessKey pairs, or Security Token Service (STS) tokens. This topic also describes the order based on which the Credentials tool obtains the default credential. You can develop a thorough knowledge of configuring and managing credentials in Alibaba Cloud SDKs. This ensures that you can perform operations on cloud resources in an efficient and secure manner.
Background information
A credential is a set of information that is used to prove the identity of a user. When you log on to the system, you must use a valid credential to complete identity authentication. The following types of credentials are commonly used:
An AccessKey pair of an Alibaba Cloud account or a Resource Access Management (RAM) user. An AccessKey pair is permanently valid and consists of an AccessKey ID and an AccessKey secret.
An STS token of a RAM role. An STS token is a temporary credential. You can specify a validity period and access permissions for an STS token. For more information, see What is STS?
A bearer token. It is used for identity authentication and authorization.
Prerequisites
Go 1.10.x or later is installed.
Alibaba Cloud SDK V2.0 is installed. For more information, see Use the Alibaba Cloud SDKs for Go in an IDE.
Install the Credentials tool
Run the
go get
command to install Alibaba Cloud Credentials for Go.
$ go get -u github.com/aliyun/credentials-go
If you use the
dep
tool to manage dependencies for Go, run the following command to install Alibaba Cloud Credentials for Go:
$ dep ensure -add github.com/aliyun/credentials-go
Use the latest version of the Credentials tool to ensure that all types of credentials are supported.
Initialize a Credentials client
You can use one of the following methods to initialize a Credentials client based on your business requirements:
If you use a plaintext AccessKey pair in a project, the AccessKey pair may be leaked due to improper permission management on the code repository. This may threaten the security of all resources within the account to which the AccessKey pair belongs. We recommend that you store the AccessKey pair in environment variables or configuration files.
Method 1: Use the default credential provider chain
If you do not specify a method to initialize a Credentials client, the default credential provider chain is used. For more information, see the Default credential provider chain section of this topic.
package main
import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
)
func main() {
// Do not specify a method to initialize a Credentials client.
config := new(credentials.Config)
credential, err := credentials.NewCredential(config)
}
Call example
Method 2: Use an AccessKey pair
You can create an AccessKey pair that is used to call API operations for your Alibaba Cloud account or a RAM user. For more information, see Create an AccessKey pair. Then, you can use the AccessKey pair to initialize a Credentials client.
An Alibaba Cloud account has full permissions on resources within the account. AccessKey pair leaks of an Alibaba Cloud account pose critical threats to the system.
Therefore, we recommend that you use an AccessKey pair of a RAM user that is granted permissions based on the principle of least privilege to initialize a Credentials client.
import (
"fmt"
"os"
"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
}
accessKeyId, err := akCredential.GetAccessKeyId()
accessSecret, err := akCredential.GetAccessKeySecret()
credentialType := akCredential.GetType()
fmt.Println(accessKeyId, accessSecret, credentialType)
}
Call example
Method 3: Use an STS token
You can call the AssumeRole operation of STS as a RAM user to obtain an STS token. You can specify the maximum validity period of the STS token. The following example shows how to initialize a Credentials client by using an STS token. The example does not show how to obtain an STS token.
package main
import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
"os"
)
func main() {
config := new(credentials.Config).
SetType("sts").
// Obtain the AccessKey ID from the environment variable.
SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
// Obtain the AccessKey secret from the environment variable.
SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")).
// Obtain the STS token from the environment variable.
SetSecurityToken(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN"))
stsCredential, err := credentials.NewCredential(config)
if err != nil {
return
}
accessKeyId, err := stsCredential.GetAccessKeyId()
accessSecret, err := stsCredential.GetAccessKeySecret()
securityToken, err := stsCredential.GetSecurityToken()
credentialType := stsCredential.GetType()
fmt.Println(accessKeyId, accessSecret, securityToken, credentialType)
}
Call example
Method 4: Use an AccessKey pair and a RAM role
The underlying logic of this method is to use an STS token to initialize a Credentials client. After you specify the ARN of a RAM role, the Credentials tool can obtain an STS token from STS. You can also use the SetPolicy
method to limit the permissions of the RAM role.
package main
import (
"fmt"
"os"
"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")).
// Specify the ARN of the RAM role to be assumed. Example: acs:ram::123456789012****:role/adminrole. You can configure the ARN as the ALIBABA_CLOUD_ROLE_ARN environment variable.
SetRoleArn("<RoleArn>").
// Specify the role session name. You can configure the role session name as the ALIBABA_CLOUD_ROLE_SESSION_NAME environment variable.
SetRoleSessionName("<RoleSessionName>").
// Optional. Specify limited permissions for the RAM role. Example: {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}.
SetPolicy("<Policy>").
SetRoleSessionExpiration(3600)
arnCredential, err := credentials.NewCredential(config)
if err != nil {
return
}
accessKeyId, err := arnCredential.GetAccessKeyId()
accessSecret, err := arnCredential.GetAccessKeySecret()
securityToken, err := arnCredential.GetSecurityToken()
credentialType := arnCredential.GetType()
fmt.Println(accessKeyId, accessSecret, securityToken, credentialType)
}
Call example
Method 5: Use the RAM role of an ECS instance
The underlying logic of this method is to use an STS token to initialize a Credentials client. The Credentials tool automatically obtains the RAM role attached to an ECS instance and uses the metadata server of ECS to obtain an STS token. The STS token is then used to initialize a Credentials client. You can also attach a RAM role to an elastic container instance or a worker node in an Container Service for Kubernetes cluster.
package main
import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
)
func main() {
config := new(credentials.Config).
SetType("ecs_ram_role").
// Optional. Specify the name of the RAM role of the ECS instance. If you do not specify this parameter, its value is automatically obtained. To reduce the number of requests, we recommend that you specify this parameter. You can configure the RAM role name as the ALIBABA_CLOUD_ECS_METADATA environment variable.
SetRoleName("<RoleName>")
ecsCredential, err := credentials.NewCredential(config)
if err != nil {
return
}
accessKeyId, err := ecsCredential.GetAccessKeyId()
accessSecret, err := ecsCredential.GetAccessKeySecret()
securityToken, err := ecsCredential.GetSecurityToken()
credentialType := ecsCredential.GetType()
fmt.Println(accessKeyId, accessSecret, securityToken, credentialType)
}
Call example
Method 6: Use the RAM role of an OIDC IdP
After you attach a RAM role to a worker node in an Container Service for Kubernetes, applications in the pods on the worker node can use the metadata server to obtain an STS token the same way in which applications on ECS instances do. However, if an untrusted application is deployed on the worker node, such as an application that is submitted by your customer and whose code is unavailable to you, you may not want the application to use the metadata server to obtain an STS token of the RAM role attached to the worker node. To ensure the security of cloud resources and enable untrusted applications to securely obtain required STS tokens, you can use the RAM Roles for Service Accounts (RRSA) feature to grant minimum necessary permissions to an application. In this case, the ACK cluster creates a service account OpenID Connect (OIDC) token file, associates the token file with a pod, and then injects relevant environment variables into the pod. Then, the Credentials tool uses the environment variables to call the AssumeRoleWithOIDC operation of STS and obtains an STS token of the RAM role. For more information about the RRSA feature, see Use RRSA to authorize different pods to access different cloud services.
The following environment variables are injected into the pod:
ALIBABA_CLOUD_ROLE_ARN: the ARN of the RAM role.
ALIBABA_CLOUD_OIDC_PROVIDER_ARN: the ARN of the OIDC identity provider (IdP)
ALIBABA_CLOUD_OIDC_TOKEN_FILE: the path of the OIDC token file.
package main
import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
"os"
)
func main() {
config := new(credentials.Config).
SetType("oidc_role_arn").
// Specify the ARN of the OIDC IdP by specifying the ALIBABA_CLOUD_OIDC_PROVIDER_ARN environment variable.
SetOIDCProviderArn(os.Getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN")).
// Specify the path of the OIDC token file by specifying the ALIBABA_CLOUD_OIDC_TOKEN_FILE environment variable.
SetOIDCTokenFilePath(os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE")).
// Specify the ARN of the RAM role by specifying the ALIBABA_CLOUD_ROLE_ARN environment variable.
SetRoleArn(os.Getenv("ALIBABA_CLOUD_ROLE_ARN")).
// Specify the role session name by specifying the ALIBABA_CLOUD_ROLE_SESSION_NAME environment variable.
SetRoleSessionName(os.Getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME")).
// Optional. Specify limited permissions for the RAM role. Example: {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}.
SetPolicy("<Policy>").
// Specify the validity period of the session.
SetRoleSessionExpiration(3600)
oidcCredential, err := credentials.NewCredential(config)
if err != nil {
return
}
accessKeyId, err := oidcCredential.GetAccessKeyId()
accessKeySecret, err := oidcCredential.GetAccessKeySecret()
token, err := oidcCredential.GetSecurityToken()
fmt.Println(accessKeyId, accessKeySecret, token)
}
Call example
Method 7: Use a URI
The underlying logic of this method is to use an STS token to initialize a Credentials client. The Credentials tool uses the uniform resource identifier (URI) that you provide to obtain an STS token. The STS token is then used to initialize a Credentials client.
package main
import (
"github.com/aliyun/credentials-go/credentials"
)
func main() {
config := new(credentials.Config).
SetType("credentials_uri").
// Specify the URI of the credential in the http://local_or_remote_uri/ format. You can configure the URI as the ALIBABA_CLOUD_CREDENTIALS_URI environment variable.
SetCredentialsUri("<CredentialsUri>")
uriCredential, err := credentials.NewCredential(config)
}
Call example
Method 8: Use a bearer token
Only Cloud Call Center allows you to use a bearer token to initialize a Credentials client.
package main
import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
)
func main() {
config := new(credentials.Config).
SetType("bearer").
// Specify the bearer token.
SetBearerToken("<BearerToken>")
bearerCredential, err := credentials.NewCredential(config)
if err != nil {
return
}
bearerToken := bearerCredential.GetBearerToken()
credentialType := bearerCredential.GetType()
fmt.Println(bearerToken, credentialType)
}
Call example
Default credential provider chain
If you want to use different types of credentials in the development and production environments of your application, you generally need to obtain the environment information from the code and write code branches to obtain different credentials for the development and production environments. The default credential provider chain of the Credentials tool allows you to use the same code to obtain credentials for different environments based on configurations independent of the application. If you use NewCredential()
to initialize a Credentials client without specifying an initialization method, the Credentials tool obtains the credential information in the following order:
1. Obtain the credential information from environment variables
If no credentials are found in the previous step, the Credentials tool obtains the credential information from environment variables.
If the ALIBABA_CLOUD_ACCESS_KEY_ID (AccessKey ID) and ALIBABA_CLOUD_ACCESS_KEY_SECRET (AccessKey secret) system environment variables are specified, the Credentials tool uses the specified AccessKey pair as the default credential.
If the ALIBABA_CLOUD_ACCESS_KEY_ID (AccessKey ID), ALIBABA_CLOUD_ACCESS_KEY_SECRET (AccessKey secret), and ALIBABA_CLOUD_SECURITY_TOKEN (STS token) system environment variables are specified, the Credentials tool uses the specified STS token as the default credential.
2. Obtain the credential information by using the RAM role of an OIDC IdP
If no credentials are found in the previous step, the Credentials tool obtains the values of the following environment variables:
ALIBABA_CLOUD_ROLE_ARN: the ARN of the RAM role.
ALIBABA_CLOUD_OIDC_PROVIDER_ARN: the ARN of the OIDC IdP.
ALIBABA_CLOUD_OIDC_TOKEN_FILE: the path of the OIDC token file.
If the preceding three environment variables are specified, the Credentials tool uses the environment variables to call the AssumeRoleWithOIDC operation of STS to obtain an STS token as the default credential.
3. Obtain the credential information from a configuration file
If no credentials are found in the previous step, the Credentials tool obtains the credential information from a configuration file. The path of the configuration file varies based on the operating system:
Linux: ~/.alibabacloud/credentials
Windows: C:\Users\USER_NAME\.alibabacloud\credentials
You can also specify the configuration file path by configuring the ALIBABA_CLOUD_CREDENTIALS_FILE environment variable. If the configuration file exists, the application initializes a Credentials client by using the credential information that is specified by default in the configuration file. You can also modify the ALIBABA_CLOUD_PROFILE environment variable to specify a different credential. For example, you can set the ALIBABA_CLOUD_PROFILE environment variable to client1.
Configuration example:
[default]
enable=true
type=access_key
access_key_id=<ALIBABA_CLOUD_ACCESS_KEY_ID>
access_key_secret=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
[client1]
enable=true
type=ecs_ram_role
role_name=<ecs_ram_role_name>
[client2]
enable=true
type=ram_role_arn
policy=<policy>
access_key_id=<ALIBABA_CLOUD_ACCESS_KEY_ID>
access_key_id=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
role_arn=<ram_role_arn>
role_session_name=<role_session_name>
[client3]
enable=true
type=oidc_role_arn
policy=<policy>
oidc_provider_arn=<ALIBABA_CLOUD_ACCESS_KEY_ID>
oidc_token_file_path=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
role_arn=<ram_role_arn>
role_session_name=<role_session_name>
4. Obtain the credential information by using the RAM role of an ECS instance
If no credentials are found in the previous step, the Credentials tool obtains the value of the ALIBABA_CLOUD_ECS_METADATA environment variable that specifies the RAM role name of an ECS instance. If the RAM role exists, the application obtains an STS token of the RAM role as the default credential by using the metadata server of ECS.
5. Obtain the credential information based on a URI
If no credentials are found in the previous step, the Credentials tool obtains the value of the ALIBABA_CLOUD_CREDENTIALS_URI environment variable that specifies the URI of the credential. If the URI of the credential exists, the application uses the URI of the credential to obtain an STS token as the default credential.
Protect credential information
Credential leaks may expose the system to attacks. This is one of the main threats to cloud services. To prevent the leaks of plaintext credential information and reduce security risks, you can use the following solutions:
We recommend that you use the RAM role of an ECS instance or an STS token.
We recommend that you use the default credential provider chain and record the credential information in environment variables or a configuration file.
To use an explicit initialization method to initialize a Credentials client, we recommend that you use system properties or environment variables to record the credential information and obtain the credential information by using the
os.Getenv
method.
import (
"fmt"
"os"
"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
}
accessKeyId, err := akCredential.GetAccessKeyId()
accessSecret, err := akCredential.GetAccessKeySecret()
credentialType := akCredential.GetType()
fmt.Println(accessKeyId, accessSecret, credentialType)
}
Switch between credentials
You can use the following method to use different credentials to call different API operations in your application:
Use multiple Credentials clients
Initialize multiple Credentials clients to pass different credentials to different request clients.
package main
import (
credentials "github.com/aliyun/credentials-go/credentials"
"os"
)
func main() {
config1 := new(credentials.Config).
SetType("access_key").
SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
akCredential, err1 := credentials.NewCredential(config1)
config2 := new(credentials.Config).
SetType("sts").
SetAccessKeyId(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")).
SetAccessKeySecret(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")).
SetSecurityToken(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN"))
akCredential, err2 := credentials.NewCredential(config2)
}