Atribua uma função RAM a uma elastic container instance para que as aplicações executadas na instância chamarem APIs de outros serviços da Alibaba Cloud com credenciais do Security Token Service (STS) de rotação automática, sem armazenar pares de AccessKey na instância.
Por que usar uma função RAM de instância
Codificar pares de AccessKey em arquivos de configuração gera dois problemas: risco de vazamento de credenciais e necessidade de modificar cada instância para atualizar permissões. As funções RAM de instância resolvem ambas as questões:
Credenciais fora do disco. As aplicações obtêm tokens STS temporários dos metadados da instância durante a execução.
Gestão centralizada de permissões. Para alterar o acesso da instância, atualize a função RAM em vez de modificar a própria instância.
Rotação automática de tokens. Os tokens STS expiram e se renovam automaticamente, limitando o impacto de qualquer exposição acidental.
Pré-requisitos
Antes de começar, verifique se você tem:
Uma conta Alibaba Cloud ou um usuário RAM com permissões para chamar
CreateRole,CreatePolicyeAttachPolicyToRoleno RAM, além deCreateContainerGroupno ECI(Opcional) Se utilizar um usuário RAM para criar a elastic container instance, esse usuário também precisa da permissão
ram:PassRolesobre a função de destino
Como funciona
Crie uma função RAM de instância e configure sua política de confiança para permitir que o ECS a assuma.
Crie uma política de permissões e anexe-a à função.
(Opcional) Conceda a um usuário RAM permissão para passar a função a uma instância.
Atribua a função a uma elastic container instance via
CreateContainerGroup.Obtenha as credenciais STS nos metadados da instância dentro do pod e use-as para chamar outros serviços da Alibaba Cloud.
Etapa 1: Crie uma função RAM de instância
Chame CreateRole com os seguintes parâmetros:
RoleName: Nome descritivo para a função. Este exemplo usa
ECIRamRoleTest.AssumeRolePolicyDocument: Política de confiança que concede ao ECS o direito de assumir esta função.
{
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.aliyuncs.com"
]
}
}
],
"Version": "1"
}
Defina a entidade confiável como Elastic Container Instance e o serviço confiável como Elastic Compute Service (ECS), representado pelo principal ecs.aliyuncs.com.
Etapa 2: Anexar uma política de permissões à função
2a. Criar uma política personalizada
Chame CreatePolicy com os seguintes parâmetros:
PolicyName:
ECIRamRoleTestPolicyPolicyDocument: Permissões a conceder. O exemplo abaixo concede acesso de leitura a todos os buckets do Object Storage Service (OSS):
{
"Statement": [
{
"Action": [
"oss:Get*",
"oss:List*"
],
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "1"
}
Siga o princípio do menor privilégio: conceda apenas as permissões necessárias para a aplicação.
2b. Anexar a política à função
Chame AttachPolicyToRole com os seguintes parâmetros:
|
Parâmetro |
Valor |
|
|
|
|
|
|
|
|
|
Etapa 3 (opcional): Autorizar um usuário RAM a passar a função
Ignore esta etapa se estiver usando uma conta Alibaba Cloud para criar a elastic container instance.
Se um usuário RAM criar a elastic container instance e atribuir a função, ele precisará da permissão ram:PassRole sobre essa função. Sem ela, o usuário RAM não consegue delegar a função à instância.
Faça login no RAM console com uma conta Alibaba Cloud ou um usuário RAM com permissões de administrador.
Crie uma política personalizada com o documento abaixo e anexe-a ao usuário RAM. Para mais detalhes, consulte Conceder permissões a um usuário RAM.
{
"Statement": [
{
"Effect": "Allow",
"Action": "ram:PassRole",
"Resource": "acs:ram:*:*:role/ECIRamRoleTest"
}
],
"Version": "1"
}
Substitua ECIRamRoleTest pelo nome real da função caso tenha usado um nome diferente na Etapa 1.
Etapa 4: Atribuir a função a uma elastic container instance
Ao chamar CreateContainerGroup, defina o parâmetro RamRoleName com o nome da função criada na Etapa 1.
Cada elastic container instance aceita apenas uma função RAM de instância. Se já houver uma função atribuída, tentar atribuir outra retornará um erro.
Etapa 5: Obter e usar credenciais STS
Obter o token STS
De dentro do pod, consulte o endpoint de metadados da instância:
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTest
Substitua ECIRamRoleTest pelo nome real da sua função. A resposta terá o seguinte formato:
{
"AccessKeyId": "STS.******",
"AccessKeySecret": "******",
"Expiration": "2023-06-22T19:13:58Z",
"SecurityToken": "******",
"LastUpdated": "2023-06-22T13:13:58Z",
"Code": "Success"
}
|
Campo |
Descrição |
|
|
ID da chave de acesso temporária (com prefixo |
|
|
Segredo da chave de acesso temporária |
|
|
Token de sessão obrigatório, junto com AccessKeyId e AccessKeySecret, ao chamar APIs de serviços |
|
|
Timestamp UTC de expiração do token; os tokens STS se atualizam automática e regularmente |
|
|
Timestamp UTC da última atualização do token |
|
|
O valor |
Usar o token STS para acessar serviços da Alibaba Cloud
O exemplo abaixo em Go obtém credenciais dos metadados da instância e as usa para listar objetos em um bucket OSS. As credenciais são lidas do endpoint de metadados, eliminando a necessidade de pares de AccessKey estáticos no código.
Este exemplo demonstra o padrão de obtenção de credenciais. Em produção, adapte o código aos requisitos da sua aplicação e consulte a documentação do SDK do serviço de destino.
package main
import (
"encoding/json"
"flag"
"log"
"os/exec"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
const (
securityCredUrl = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
)
var (
ossEndpoint string
ossBucketName string
)
func init() {
flag.StringVar(&ossEndpoint, "endpoint", "oss-cn-hangzhou-internal.aliyuncs.com", "OSS endpoint (internal endpoint recommended, e.g. oss-cn-hangzhou-internal.aliyuncs.com)")
flag.StringVar(&ossBucketName, "bucket", "", "OSS bucket name")
}
type AssumedRoleUserCredentialsWithServiceIdentity struct {
AccessKeyId string `json:"AccessKeyId" xml:"AccessKeyId"`
AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
Expiration string `json:"Expiration" xml:"Expiration"`
SecurityToken string `json:"SecurityToken" xml:"SecurityToken"`
LastUpdated string `json:"LastUpdated" xml:"LastUpdated"`
Code string `json:"Code" xml:"Code"`
}
func main() {
flag.Parse()
if ossEndpoint == "" {
log.Fatal("OSS endpoint is required, e.g. oss-cn-hangzhou-internal.aliyuncs.com")
}
if ossBucketName == "" {
log.Fatal("OSS bucket name is required")
}
output, err := exec.Command("curl", securityCredUrl).Output()
if err != nil {
log.Fatalf("Failed to get RAM role name from metadata server: %s", err)
}
output, err = exec.Command("curl", securityCredUrl+string(output)).Output()
if err != nil {
log.Fatalf("Failed to get STS credentials from metadata server: %s", err)
}
authServiceIdentity := new(AssumedRoleUserCredentialsWithServiceIdentity)
if err := json.Unmarshal(output, authServiceIdentity); err != nil {
log.Fatalf("Failed to parse STS credentials: %s", err)
}
// Create an OSS client using STS credentials. In production, refresh the client
// before the token expires to avoid access failures.
ossClient, err := oss.New(ossEndpoint, authServiceIdentity.AccessKeyId,
authServiceIdentity.AccessKeySecret, oss.SecurityToken(authServiceIdentity.SecurityToken))
if err != nil {
log.Fatalf("Failed to create OSS client: %s", err)
}
// Get the bucket handle.
bucket, err := ossClient.Bucket(ossBucketName)
if err != nil {
log.Fatalf("Failed to get bucket %q: %s", ossBucketName, err)
}
// List objects in the bucket. Up to 100 objects are returned per call by default.
marker := ""
for {
lsRes, err := bucket.ListObjects(oss.Marker(marker))
if err != nil {
log.Fatalf("Failed to list objects in bucket %q: %s", ossBucketName, err)
}
for _, object := range lsRes.Objects {
log.Println("Object:", object.Key)
}
if lsRes.IsTruncated {
marker = lsRes.NextMarker
} else {
break
}
}
}
Próximos passos
Para gerencie funções e políticas RAM no console em vez de usar a API, consulte Visão geral de funções RAM.
Para controlar quais usuários RAM podem criar elastic container instances e atribuir funções, consulte Conceder permissões a um usuário RAM.