O Alibaba Cloud SDK usa a ferramenta Credentials para gerenciar credenciais centralmente, como AccessKey e STS Token. Este tópico descreve os tipos de credenciais compatíveis e seus métodos de configuração.
Pré-requisitos
Python 3.7 ou superior (Política de suporte do Alibaba Cloud SDK).
Alibaba Cloud SDK for Python V2.0 (SDKs V2.0 e V1.0).
Instale a ferramenta Credentials
Instale a ferramenta Credentials com o pip:
pip install alibabacloud_credentials
Versão mais recente do alibabacloud_credentials: alibabacloud-credentials · PyPI | Github. Use a versão mais recente para garantir suporte completo a todos os recursos.
Tipos de credenciais e parâmetros
A classe Config em alibabacloud_credentials.models define os tipos de credenciais e seus respectivos parâmetros. Defina o parâmetro type para selecionar um tipo de credencial. A tabela a seguir lista os parâmetros para cada valor de type: = obrigatório, - = opcional, = não aplicável.
Não use parâmetros fora desta tabela.
|
type |
access_key |
sts |
ram_role_arn |
ecs_ram_role |
oidc_role_arn |
credentials_uri |
bearer |
|
access_key_id: o AccessKey ID. |
|
|
|
|
|
|
|
|
access_key_secret: o segredo do AccessKey. |
|
|
|
|
|
|
|
|
security_token: token do Security Token Service (STS). |
|
|
- |
|
|
|
|
|
role_arn: o Alibaba Cloud Resource Name (ARN) da função do Resource Access Management (RAM). |
|
|
|
|
|
|
|
|
role_session_name: nome personalizado para a sessão. O valor padrão segue o formato |
|
|
- |
|
- |
|
|
|
role_name: especifique o nome da função RAM. |
|
|
|
- |
|
|
|
|
disable_imds_v1: especifique se o modo de segurança reforçada (IMDSv2) deve ser usado obrigatoriamente. Se definido como true, o modo de segurança reforçada (IMDSv2) será utilizado. Valor padrão: |
|
|
|
- |
|
|
|
|
bearer_token: um bearer token. |
|
|
|
|
|
|
|
|
policy: uma política personalizada. |
|
|
- |
|
- |
|
|
|
role_session_expiration: tempo limite da sessão. Valor padrão: 3600. Unidade: segundos. |
|
|
- |
|
- |
|
|
|
oidc_provider_arn: o ARN do provedor de identidade OpenID Connect (OIDC). |
|
|
|
|
|
|
|
|
oidc_token_file_path: o caminho absoluto para o token OIDC. |
|
|
|
|
|
|
|
|
external_id: o ID externo da função. Previne o problema de confused deputy (Usar IDs externos para prevenir o problema de confused deputy). |
|
|
- |
|
|
|
|
|
credentials_uri: a URI da credencial. |
|
|
|
|
|
|
|
|
sts_endpoint: o endpoint do STS. Compatível com endpoints de VPC e Internet. Padrão: |
|
|
- |
|
- |
|
|
|
timeout: tempo limite para requisições de leitura HTTP. Valor padrão: 5000. Unidade: milissegundos. |
|
|
- |
- |
- |
- |
|
|
connect_timeout: tempo limite para requisições de conexão HTTP. Valor padrão: 10000. Unidade: milissegundos. |
|
|
- |
- |
- |
- |
|
Uso da ferramenta Credentials
A seção anterior descreveu os tipos de credenciais e os parâmetros de configuração compatíveis com a ferramenta Credentials. As seções a seguir apresentam exemplos de código sobre como usar a ferramenta. Selecione o método mais adequado ao seu cenário.
Codificar um AccessKey diretamente no projeto gera riscos de segurança. Permissões de repositório mal gerenciadas podem expor todos os recursos da sua conta. Armazene o AccessKey em variáveis de ambiente ou arquivos de configuração.
Use o padrão singleton com a ferramenta Credentials. Esse padrão permite que o cache interno de credenciais da ferramenta evite limitações de taxa devido a chamadas frequentes de API e previne desperdício de recursos causado pela criação de múltiplas instâncias. Para mais informações, consulte Atualização automática de credenciais de sessão.
Método 1: Cadeia de provedores de credenciais padrão
Este é o método padrão usado nos códigos de exemplo do OpenAPI Portal.
Sem parâmetros de configuração, a ferramenta Credentials obtém as credenciais da cadeia de provedores de credenciais padrão. Certifique-se de configurar pelo menos um método da cadeia de provedores de credenciais padrão no seu ambiente de execução.
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
# Do not specify any configuration parameters. Credentials will be retrieved from the default credential provider chain.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 2: Par de AccessKey
A ferramenta Credentials usa o AccessKey fornecido por você como credencial de acesso.
Uma conta Alibaba Cloud (conta raiz) possui permissões totais sobre todos os seus recursos; portanto, um AK exposto representa um risco significativo de segurança. Não use o AK de uma conta raiz.
Use o AK de um usuário RAM com permissões de privilégio mínimo.
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',
# Required. This example shows how to obtain the AccessKey ID from an environment variable.
access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
# Required. This example shows how to obtain the AccessKey secret from an environment variable.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 3: Token STS
A ferramenta Credentials usa o token STS estático fornecido por você como credencial de acesso.
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',
# Required. This example shows how to obtain the AccessKey ID from an environment variable.
access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
# Required. This example shows how to obtain the AccessKey secret from an environment variable.
access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
# Required. This example shows how to obtain the temporary security token from an environment variable.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 4: Par de AccessKey e RamRoleArn
A ferramenta Credentials chama a operação AssumeRole com seu AccessKey e o ARN da função RAM para obter um token STS como credencial de acesso. Essas credenciais são atualizadas automaticamente (Mecanismo de atualização automática para credenciais de sessão).
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',
# Required. This example shows how to obtain the AccessKey ID from an environment variable.
access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
# Required. This example shows how to obtain the AccessKey secret from an environment variable.
access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
# Required. The ARN of the RAM role to assume. Example: acs:ram::123456789012****:role/adminrole. You can set this using the ALIBABA_CLOUD_ROLE_ARN environment variable.
role_arn='<role_arn>',
# Optional. The name of the role session. You can set this using the ALIBABA_CLOUD_ROLE_SESSION_NAME environment variable.
role_session_name='<role_session_name>',
# Optional. A smaller permission policy. Example: {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy='<policy>',
# Optional. The external ID of the role, which is used to prevent the confused deputy problem.
external_id='<external_id>',
# Optional. The session expiration time. The default value is 3600 seconds.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 5: Função RAM de instância ECS
Para instâncias ECS ou ECI com uma função RAM atribuída, a ferramenta Credentials obtém o token STS dos metadados da instância. Essas credenciais são atualizadas automaticamente (Mecanismo de atualização automática para credenciais de sessão).
A ferramenta Credentials usa IMDSv2 por padrão para acessar os metadados. Use o parâmetro disable_imds_v1 ou a variável de ambiente ALIBABA_CLOUD_IMDSV1_DISABLED para controlar o comportamento de fallback:
Se
False(padrão): o sistema alterna para o modo NAT e continua obtendo as credenciais.Se
True: apenas o IMDSv2 é usado. Uma exceção será lançada se o acesso via IMDSv2 falhar.
O suporte ao IMDSv2 depende da configuração do seu servidor.
Você também pode definir a variável de ambiente ALIBABA_CLOUD_ECS_METADATA_DISABLED=true para desabilitar o acesso a credenciais via metadados da instância.
Para atribuir uma função RAM: Criar uma função RAM e concedê-la a uma instância ECS | Atribuir uma função RAM de instância a uma instância ECI.
Ao usar o modo de segurança reforçada para obter credenciais de identidade temporárias, o
alibabacloud_credentialsdeve estar na versão 0.3.6 ou superior.
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',
# Optional. The name of the ECS role. If you do not specify this parameter, the name is automatically retrieved. We recommend that you specify this parameter to reduce the number of requests. You can set this using the ALIBABA_CLOUD_ECS_METADATA environment variable.
role_name='<role_name>',
# Optional. The default value is False. If set to True, the security-hardened mode is forcibly used. If set to False, the system first attempts to retrieve the credential in security-hardened mode. If the attempt fails, the system switches to the normal mode (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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 6: OIDCRoleArn
Após criar uma função RAM para um IdP OIDC, forneça o ARN do IdP OIDC, o token OIDC e o ARN da função RAM à ferramenta Credentials. A ferramenta chama a operação AssumeRoleWithOIDC para obter um token STS como credencial de acesso. Essas credenciais são atualizadas automaticamente (Mecanismo de atualização automática para credenciais de sessão). Para clusters ACK com RRSA habilitado, a ferramenta lê a configuração OIDC das variáveis de ambiente do pod automaticamente.
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',
# Required. The ARN of the RAM role. You can set this using the ALIBABA_CLOUD_ROLE_ARN environment variable.
role_arn='<role_arn>',
# Required. The ARN of the OIDC IdP. You can set this using the ALIBABA_CLOUD_OIDC_PROVIDER_ARN environment variable.
oidc_provider_arn='<oidc_provider_arn>',
# Required. The path of the OIDC token file. You can set this using the ALIBABA_CLOUD_OIDC_TOKEN_FILE environment variable.
oidc_token_file_path='<oidc_token_file_path>',
# Optional. The name of the role session. You can set this using the ALIBABA_CLOUD_ROLE_SESSION_NAME environment variable.
role_session_name='<role_session_name>',
# Optional. A smaller permission policy. Example: {"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"}
policy='<policy>',
# Optional. The session expiration time. The default value is 3600 seconds.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 7: Credencial via URI
Exponha uma URI de serviço STS para permitir que a ferramenta Credentials obtenha tokens STS sem expor AccessKeys. Essas credenciais são atualizadas automaticamente (Mecanismo de atualização automática para credenciais de sessão).
A URI deve atender às seguintes condições:
Suporte a requisições GET.
Retorne um código de status 200.
-
O corpo da resposta tenha a seguinte estrutura:
{ "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',
# Required. The external URI for retrieving credentials. The format is http://local_or_remote_uri/. You can set this using the ALIBABA_CLOUD_CREDENTIALS_URI environment variable.
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()
# If you use a V2.0 SDK for an Alibaba Cloud product, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Método 8: Bearer token
Atualmente, apenas o Alibaba Cloud Call Center (CCC) oferece suporte à autenticação via 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',
# Required. Enter your 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()
# If you use the CCC V2.0 SDK, use the Config class from the alibabacloud_tea_openapi.models module to pass the credential.
config = open_api_models.Config(
credential=credentialsClient,
endpoint='<endpoint>'
)
# ... Code to initialize the product client using the config object is omitted.
Cadeia de provedores de credenciais padrão
A cadeia de provedores de credenciais padrão é um mecanismo de fallback que busca uma credencial verificando uma sequência predefinida de locais. A pesquisa continua até encontrar uma credencial. Se nenhuma credencial for localizada após verificar todos os locais, uma CredentialException será lançada. A ordem de pesquisa é a seguinte:
1. Uso de variáveis de ambiente
Caso nenhuma credencial seja encontrada nas propriedades do sistema, a cadeia de provedores verifica as variáveis de ambiente.
Se ALIBABA_CLOUD_ACCESS_KEY_ID e ALIBABA_CLOUD_ACCESS_KEY_SECRET estiverem presentes e não vazias, a cadeia de provedores as usa como credencial padrão.
Se ALIBABA_CLOUD_ACCESS_KEY_ID, ALIBABA_CLOUD_ACCESS_KEY_SECRET e ALIBABA_CLOUD_SECURITY_TOKEN também estiverem definidas, a cadeia de provedores usa um token STS como credencial padrão.
2. Função RAM de IdP OIDC
Se nenhuma credencial tiver sido encontrada, a cadeia de provedores verifica as seguintes variáveis de ambiente relacionadas a uma função RAM OIDC:
ALIBABA_CLOUD_ROLE_ARN: O ARN da função RAM.
ALIBABA_CLOUD_OIDC_PROVIDER_ARN: O ARN do provedor OIDC.
ALIBABA_CLOUD_OIDC_TOKEN_FILE: O caminho do arquivo do token OIDC.
Se todas as três variáveis de ambiente estiverem presentes e não vazias, a cadeia de provedores usa esses valores para chamar a API AssumeRoleWithOIDC do Security Token Service (STS) e obter um token STS.
3. Uso de arquivos de configuração
Este recurso requer a versão 1.0rc3 ou superior do alibabacloud_credentials.
Se nenhuma credencial tiver sido encontrada, a cadeia de provedores tenta carregar o arquivo de credenciais compartilhadas, config.json, de seu local padrão e usa a credencial especificada no arquivo.
Linux/macOS:
~/.aliyun/config.jsonWindows:
C:\Users\USER_NAME\.aliyun\config.json
Para configurar uma credencial dessa forma, use a Alibaba Cloud CLI ou crie manualmente um arquivo config.json no caminho apropriado. O exemplo a seguir mostra o formato do conteúdo:
{
"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
}
]
}
|
Parâmetro |
Descrição |
|
current |
Especifique o nome da credencial para recuperar a configuração correspondente. O nome da credencial corresponde ao valor do parâmetro |
|
profiles |
Contém uma coleção de configurações de credenciais. O parâmetro
|
4. Função RAM de instância ECS
Se nenhuma credencial tiver sido encontrada, a cadeia de provedores tenta obter um token STS para a função RAM da instância a partir dos metadados da instância. Esse token é então usado como credencial padrão. Para isso, a cadeia primeiro recupera o nome da função RAM atribuída à instância e, em seguida, usa essa função para obter o token STS correspondente. Para reduzir o tempo de obtenção de credenciais e melhorar a eficiência, especifique o nome da função RAM diretamente por meio da variável de ambiente ALIBABA_CLOUD_ECS_METADATA.
Por padrão, a cadeia de provedores acessa os metadados da instância no modo de segurança reforçada (IMDSv2). Se ocorrer uma exceção nesse modo, use a variável de ambiente ALIBABA_CLOUD_IMDSV1_DISABLED para controlar o comportamento de fallback:
Quando o valor é
false(padrão), o sistema tenta alternar para o modo legado para recuperar a credencial.Quando o valor é
true, o modo de segurança reforçada é imposto. Se o acesso falhar neste modo, uma exceção será lançada.
Além disso, impeça que a cadeia de provedores acesse os metadados da instância para obter credenciais definindo a variável de ambiente ALIBABA_CLOUD_ECS_METADATA_DISABLED=true.
Para atribuir uma função RAM: Criar uma função RAM e concedê-la a uma instância ECS | Atribuir uma função RAM de instância a uma instância ECI.
Para obter uma credencial de identidade temporária no modo de segurança reforçada, certifique-se de que a versão do alibabacloud_credentials seja 0.3.6 ou superior.
5. Credenciais baseadas em URI
Se nenhuma credencial tiver sido encontrada, a cadeia de provedores verifica a variável de ambiente ALIBABA_CLOUD_CREDENTIALS_URI. Caso essa variável esteja definida e aponte para uma URI válida, a cadeia acessa a URI para recuperar um token STS.
Mecanismo de atualização automática de credenciais de sessão
Tipos de credenciais de sessão, como ram_role_arn, ecs_ram_role, oidc_role_arn e credentials_uri, oferecem suporte à atualização automática por meio de um mecanismo integrado ao provedor de credenciais. Quando um cliente de credenciais obtém uma credencial pela primeira vez, o provedor a armazena em cache. Nas operações subsequentes, a mesma instância do cliente recupera automaticamente a credencial desse cache. Se a credencial em cache tiver expirado, a instância do cliente busca uma nova e atualiza o cache adequadamente.
Para credenciais do tipo ecs_ram_role, o provedor de credenciais as atualiza proativamente 15 minutos antes da expiração.
O exemplo a seguir usa o padrão singleton para criar um cliente de credenciais. Ele demonstra o mecanismo de atualização obtendo uma credencial em intervalos de tempo diferentes e chamando uma operação OpenAPI para verificar se a credencial está utilizável.
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
#
# Thread-safe singleton decorator
#
def singleton(cls):
"""Implements a thread-safe singleton pattern"""
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 service class
#
@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
#
# Task function
#
def execute_task():
try:
# Get the credential and the ECS client.
credential = Credential().client.get_credential()
ecs_client = EcsClient(Credential().client).client
# Print the credential information.
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)
# Call the API operation to query the list of regions.
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
# Define the delays for the scheduled tasks.
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()

Análise baseada na saída do log:
Na primeira chamada, o cache está vazio. O sistema obtém uma credencial com base na sua configuração e a armazena no cache.
A segunda chamada usa a mesma credencial da primeira, indicando que ela foi recuperada do cache.
Na terceira chamada, a credencial em cache expirou. Seu tempo de expiração (
RoleSessionExpiration) é de 3.600 segundos, mas esta chamada ocorre 4.200 segundos após a primeira. Consequentemente, o mecanismo de atualização automática do SDK busca uma nova credencial e atualiza o cache.A quarta chamada usa a mesma credencial da terceira, confirmando que o cache foi atualizado.
Documentos relacionados
Para uma visão geral dos conceitos básicos do RAM, consulte Conceitos básicos.
Para criar um AccessKey, consulte Criar um AccessKey.
Para criar programaticamente usuários RAM, AccessKeys e funções RAM, definir políticas de permissão e conceder permissões, consulte Visão geral do SDK do RAM.
Para assumir uma função programaticamente, consulte Visão geral do SDK do STS.
Para detalhes sobre as APIs do RAM e STS, consulte a Referência de API.
Melhores práticas para usar credenciais de acesso ao chamar a OpenAPI da Alibaba Cloud