Un rôle RAM est une identité virtuelle dotée d'autorisations spécifiques qu'un pod ECI peut endosser, héritant ainsi des permissions associées. L'attribution d'un rôle permet aux applications exécutées dans le pod d'utiliser les identifiants STS (Security Token Service) pour accéder à d'autres services Alibaba Cloud.
Contexte
Les applications déployées sur des pods ECI utilisent souvent une paire AccessKey issue d'un compte Alibaba Cloud ou d'un utilisateur RAM pour accéder à d'autres services Alibaba Cloud, tels que Object Storage Service (OSS), Virtual Private Cloud (VPC) et ApsaraDB RDS. Par souci de commodité, certains utilisateurs intègrent directement la paire AccessKey dans le pod, par exemple en l'inscrivant en dur dans un fichier de configuration. Cette pratique engendre des risques de sécurité, notamment la fuite d'identifiants, l'octroi de permissions excessives et des difficultés liées à la rotation et à la maintenance des clés.
L'utilisation d'un rôle RAM d'instance élimine la nécessité de stocker une paire AccessKey dans vos pods ECI. Vous pouvez modifier à tout moment les permissions d'un pod ECI en ajustant les stratégies de permissions associées au rôle RAM qui lui est attribué. Cette méthode offre une sécurité et une simplicité accrues. Pour plus d'informations sur les rôles RAM, reportez-vous à Présentation des rôles RAM.
Créer un rôle RAM et accorder des permissions
-
Créez un rôle RAM. Pour des instructions détaillées, reportez-vous à Créer un rôle RAM pour un service Alibaba Cloud de confiance.
Lors de la création du rôle RAM, sélectionnez Alibaba Cloud Service comme type d'entité de confiance et Elastic Compute Service comme service de confiance.

-
Accordez des permissions au rôle RAM.
Créez une stratégie de permissions. Pour des instructions détaillées, reportez-vous à Créer une stratégie personnalisée.
Attachez la stratégie de permissions au rôle RAM. Pour des instructions détaillées, reportez-vous à Accorder des permissions à un rôle RAM.
-
(Facultatif) Autorisez un utilisateur RAM à utiliser le rôle RAM.
Si vous souhaitez qu'un utilisateur RAM puisse attribuer le rôle RAM, vous devez accorder l'autorisation
ram:passRoleà cet utilisateur. La stratégie suivante illustre un exemple où ECIRamRoleTest correspond au nom du rôle RAM que l'utilisateur est autorisé à transmettre.{ "Statement": [ { "Effect": "Allow", "Action": "ram:PassRole", "Resource": "acs:ram:*:*:role/ECIRamRoleTest" } ], "Version": "1" }
Attribuer un rôle RAM à un pod ECI
Lors de la création d'un pod ECI, vous pouvez utiliser l'annotation k8s.aliyun.com/eci-ram-role-name pour attribuer un rôle RAM. Cela permet au pod d'accéder à d'autres services Alibaba Cloud.
Les annotations doivent être ajoutées aux métadonnées dans le fichier de configuration du pod. Par exemple, lors de la création d'un Deployment, vous devez ajouter les annotations dans la section spec.template.metadata.
Les annotations liées à Elastic Container Instance ne sont appliquées qu'à la création du pod. L'ajout ou la modification de ces annotations sur un pod existant n'aura aucun effet.
Le fichier YAML suivant fournit un exemple :
apiVersion: apps/v1
kind: Deployment
metadata:
name: test
labels:
app: test
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
name: test
labels:
app: test
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-ram-role-name : "${your_ram_role_name}" # Assign the RAM role.
spec:
containers:
- name: test
image: registry.cn-shanghai.aliyuncs.com/eci_open/centos:7
command: ["sleep"]
args: ["3600"]
Obtenir un jeton STS
Depuis une instance ECI, vous pouvez accéder à une URL de métadonnées pour récupérer un jeton STS correspondant au rôle RAM attribué. Vous pouvez utiliser ce jeton pour accéder aux ressources selon les permissions du rôle. Le jeton STS est automatiquement actualisé périodiquement.
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/${your_ram_role_name}
Remplacez ${your_ram_role_name} par le nom de votre rôle RAM. Par exemple, si le nom du rôle est ECIRamRoleTest, la commande est la suivante :
curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTest
La réponse contient le jeton STS. La sortie suivante en donne un exemple :
{
"AccessKeyId" : "STS.******",
"AccessKeySecret" : "******",
"Expiration" : "2023-06-22T19:13:58Z",
"SecurityToken" : "******",
"LastUpdated" : "2023-06-22T13:13:58Z",
"Code" : "Success"
}
Accéder aux services cloud avec un jeton STS
L'exemple suivant montre comment utiliser le SDK Go et un jeton STS pour accéder à Object Storage Service (OSS). Dans cet exemple, le code accède à un bucket OSS spécifié et liste tous les objets qu'il contient.
Cet exemple est fourni à titre indicatif. Dans un environnement de production, écrivez votre code en fonction de vos besoins métier spécifiques. Pour plus d'informations, reportez-vous à la documentation du SDK du service Alibaba Cloud auquel vous souhaitez accéder.
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", "Please input oss endpoint, Recommended internal endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
flag.StringVar(&ossBucketName, "bucket", "", "Please input 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("Please input oss endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
}
if ossBucketName == "" {
log.Fatal("Please provide an OSS bucket name.")
}
output, err := exec.Command("curl", securityCredUrl).Output()
if err != nil {
log.Fatalf("Failed to get the RAM role name from the metadata server: %s", err)
}
output, err = exec.Command("curl", securityCredUrl+string(output)).Output()
if err != nil {
log.Fatalf("Failed to get security credentials from the metadata server: %s", err)
}
authServiceIdentity := new(AssumedRoleUserCredentialsWithServiceIdentity)
if err := json.Unmarshal(output, authServiceIdentity); err != nil {
log.Fatalf("Failed to unmarshal to AssumedRoleUserCredentialsWithServiceIdentity: %s", err)
}
// Create an OSS client. In a production environment, you must periodically update the client to prevent access failures due to an expired STS token.
ossClient, err := oss.New(ossEndpoint, authServiceIdentity.AccessKeyId,
authServiceIdentity.AccessKeySecret, oss.SecurityToken(authServiceIdentity.SecurityToken))
if err != nil {
log.Fatalf("Failed to create an OSS client: %s", err)
}
// Get the bucket.
bucket, err := ossClient.Bucket(ossBucketName)
if err != nil {
log.Fatalf("Failed to get bucket %q: %s", ossBucketName, err)
}
// List objects in the bucket.
marker := ""
for {
lsRes, err := bucket.ListObjects(oss.Marker(marker))
if err != nil {
log.Fatalf("Failed to list objects from bucket %q: %s", ossBucketName, err)
}
// Print the listed objects. By default, a maximum of 100 objects are returned at a time.
for _, object := range lsRes.Objects {
log.Println("Object: ", object.Key)
}
if lsRes.IsTruncated {
marker = lsRes.NextMarker
} else {
break
}
}
}