Asigne un rol RAM a una elastic container instance para que las aplicaciones que se ejecutan en la instancia puedan llamar a las API de otros servicios de Alibaba Cloud con credenciales de Security Token Service (STS) rotadas automáticamente, sin almacenar pares de AccessKey en la instancia.
Por qué usar un rol RAM de instancia
Incluir pares de AccessKey directamente en los archivos de configuración genera dos problemas: las credenciales pueden filtrarse y actualizar los permisos exige modificar cada instancia. Los roles RAM de instancia resuelven ambos inconvenientes:
Sin credenciales en disco. Las aplicaciones obtienen tokens STS de corta duración desde los metadatos de la instancia durante la ejecución.
Gestión centralizada de permisos. Para cambiar los recursos a los que accede la instancia, actualice el rol RAM en lugar de modificar la instancia.
Rotación automática de tokens. Los tokens STS caducan y se renuevan automáticamente, lo que limita el alcance de cualquier exposición.
Requisitos previos
Antes de empezar, asegúrese de contar con lo siguiente:
Una cuenta de Alibaba Cloud o un usuario RAM con permisos para invocar
CreateRole,CreatePolicyyAttachPolicyToRoleen RAM, así comoCreateContainerGroupen ECI(Opcional) Si utiliza un usuario RAM para crear la elastic container instance, dicho usuario también debe tener el permiso
ram:PassRolesobre el rol destino
Cómo funciona
Cree un rol RAM de instancia y configure su política de confianza para permitir que ECS lo asuma.
Cree una política de permisos y vincúlela al rol.
(Opcional) Otorgue a un usuario RAM permiso para pasar el rol a una instancia.
Asigne el rol a una elastic container instance mediante
CreateContainerGroup.Obtenga las credenciales STS desde los metadatos de la instancia dentro del pod y utilícelas para llamar a otros servicios de Alibaba Cloud.
Paso 1: Crear un rol RAM de instancia
Invoque CreateRole con los siguientes parámetros:
RoleName: Un nombre descriptivo para el rol. Este ejemplo utiliza
ECIRamRoleTest.AssumeRolePolicyDocument: La política de confianza que otorga a ECS el derecho de asumir este rol.
{
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": [
"ecs.aliyuncs.com"
]
}
}
],
"Version": "1"
}
La entidad de confianza debe establecerse en Elastic Container Instance y el servicio de confianza en Elastic Compute Service (ECS), representado por el principal ecs.aliyuncs.com.
Paso 2: Vincular una política de permisos al rol
2a. Crear una política personalizada
Invoque CreatePolicy con los siguientes parámetros:
PolicyName:
ECIRamRoleTestPolicyPolicyDocument: Los permisos que se otorgarán. El siguiente ejemplo concede acceso de lectura a todos los buckets de Object Storage Service (OSS):
{
"Statement": [
{
"Action": [
"oss:Get*",
"oss:List*"
],
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "1"
}
Siga el principio de privilegio mínimo: otorgue únicamente los permisos que la aplicación realmente necesita.
2b. Vincular la política al rol
Invoque AttachPolicyToRole con los siguientes parámetros:
|
Parámetro |
Valor |
|
|
|
|
|
|
|
|
|
Paso 3 (opcional): Autorizar a un usuario RAM para pasar el rol
Omita este paso si utiliza una cuenta de Alibaba Cloud para crear la elastic container instance.
Si un usuario RAM crea la elastic container instance y asigna el rol, dicho usuario necesita el permiso ram:PassRole sobre ese rol. Sin este permiso, el usuario RAM no puede delegar el rol a la instancia.
Inicie sesión en RAM console con una cuenta de Alibaba Cloud o un usuario RAM con permisos de administrador.
Cree una política personalizada con el siguiente documento y vincúlela al usuario RAM. Para más detalles, consulte Grant permissions to a RAM user.
{
"Statement": [
{
"Effect": "Allow",
"Action": "ram:PassRole",
"Resource": "acs:ram:*:*:role/ECIRamRoleTest"
}
],
"Version": "1"
}
Reemplace ECIRamRoleTest con el nombre real del rol si utilizó uno diferente en el Paso 1.
Paso 4: Asignar el rol a una elastic container instance
Al invocar CreateContainerGroup, establezca el parámetro RamRoleName con el nombre del rol creado en el Paso 1.
Cada elastic container instance admite solo un rol RAM de instancia. Si ya existe un rol asignado, intentar asignar otro devolverá un error.
Paso 5: Obtener y utilizar credenciales STS
Obtener el token STS
Desde el interior del pod, consulte el endpoint de metadatos de la instancia:
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTest
Reemplace ECIRamRoleTest con el nombre real de su rol. La respuesta tiene el siguiente formato:
{
"AccessKeyId": "STS.******",
"AccessKeySecret": "******",
"Expiration": "2023-06-22T19:13:58Z",
"SecurityToken": "******",
"LastUpdated": "2023-06-22T13:13:58Z",
"Code": "Success"
}
|
Campo |
Descripción |
|
|
ID de clave de acceso temporal (con prefijo |
|
|
Secreto de clave de acceso temporal |
|
|
Token de sesión obligatorio junto con AccessKeyId y AccessKeySecret al invocar las API de los servicios |
|
|
Marca de tiempo UTC en la que caduca el token; los tokens STS se actualizan automática y periódicamente |
|
|
Marca de tiempo UTC de la última renovación del token |
|
|
|
Utilizar el token STS para acceder a servicios de Alibaba Cloud
El siguiente ejemplo en Go obtiene credenciales desde los metadatos de la instancia y las usa para listar objetos en un bucket de OSS. Las credenciales se leen desde el endpoint de metadatos, por lo que no hay pares de AccessKey estáticos en el código.
Este ejemplo muestra el patrón de obtención de credenciales. En producción, adapte el código a los requisitos de su aplicación y consulte la documentación del SDK correspondiente al servicio 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
}
}
}
Pasos siguientes
Para gestionar roles y políticas RAM desde la consola en lugar de mediante la API, consulte RAM role overview.
Para controlar qué usuarios RAM pueden crear elastic container instances y asignar roles, consulte Grant permissions to a RAM user.