使用资源目录管理操作旗下账户的概念验证CLI

暗香疏影 创作者

我们一般情况下会把运维账号和业务账号分开,然而又不太可能在每个账号下建立RAM账号管理。而是使用资源目录把各个账号都邀请进来,然后利用角色扮演的方式实现控制对应账号下的资源。作为概念验证,我是直接使用CLI来实现,而不是通过写代码SDK接口实现。下面我先分享3个使用临时凭证的卓越架构:

通过FC函数角色实现临时凭证的获取和使用
通过ECS实例角色实现临时凭证的获取和使用
通过容器服务RRSA实现临时凭证的获取和使用

通过主账号授权

通过管理账号的RAM用户扮演成员RAM角色的方式登录阿里云控制台

这个文档实际上是直接使用主账号(资源目录的管理账号)AK/SK来实现角色扮演。下面我们多出一步,是先由资源目录下B账号扮演为管理账号,然后再去扮演C账号去操作资源。

我们资源目录下账号B,想要获得资源目录下账号C的权限可以通过先角色扮演为主账号A,然后再扮演C。

A账号UID: A0001
B账号UID: B0002
C账号UID: C0003

  1. 首先先在主账号创建角色,角色允许另一云账号(UID:B0002)操作,并授权这个角色以下权限:AliyunSTSAssumeRoleAccess,AliyunResourceDirectoryFullAccess。

  2. 复制好这个角色的ARN路径,例如:acs:ram::A0001:role/rd-allow-assume-root-from-B0002

  3. 在运维部署账号B中创建RAM用户并保存AccessKey ID和AccessKey Secret。

  4. 使用CLI概念验证:

    1
    2
    3
    aliyun configure --mode AK --profile AccountB

    aliyun sts AssumeRole --region cn-beijing --DurationSeconds 3600 --RoleArn acs:ram::A0001:role/rd-allow-assume-root-from-B0002 --RoleSessionName alice

    RoleSessionName是用于审计,你叫什么都可以。
    RoleArn就是填写之前我们在主账号创建角色的ARN。 这个授权是让B账户获取资源目录全部权限,也就是允许资源目录下成员扮演管理账号。 acs:ram::<对应的UID>:role/rd-allow-assume-root-from-B0002
    DurationSeconds就说最长有效期多少秒,实际测试最多只能填3600(1小时)。

输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"AssumedRoleUser": {
"Arn": "acs:ram::A0001:role/rd-allow-assume-root-from-B0002",
"AssumedRoleId": "1111111111111111:alice"
},
"Credentials": {
"AccessKeyId": "STS.f1Aap4ykmxWkQLt7rsb6kZId3",
"AccessKeySecret": "lyQBUVVwySDFxd6eUAYF66GGlC1QWpvvlXpl8zfXgJi",
"Expiration": "2025-03-12T07:32:26Z",
"SecurityToken": "YE1pddbiSFxk436EEgW5lv0rXpUefySwpyiy0HgpJsCcW1bw41JaVFWxFo1EPILJEb6VvbTcd7auetIKho1piiFVJrqDLc24Cwez16I387VW8WeSe7FUocMGvTC32Sjwa3hQ4zDM4hMad4I6pzRiwKaED9llQqK9slrbc9BBU3JirRj0ykvZp9A5XewKAYqXplY7piYGEHKkI5VXQpaDZU1ohGcRYyYSzWCxDZGbHsGaZIE5y5wDDrBz8AJ5uWFLoprVYAWW2bpaEOzEEhG1yYzBBH4zyhA346fgJ3d1fERiwKkDLaxvgFUoumuHdVzvJhhKE9PfsLZoPQdUBuiVfXwxhyzgjbBoucrYdeLhZTURk75xtaaZmsAU0qAyyMuQiDEyt9DRmJqaOKKvDuZRYyOfD6D3fpYomlgxPWXZ15sHpuiEwpYmxiifZs0rPeFpampl1tbui6XVMvh733gWLEutHAZ4Tpz70zxsSewyZfYRMiwoIWV82kbSyrpPdmOoS7oO8eOSzSZYbMF4WvsrvA15PFRDbFhHd3vBSS6Pjzkd63hKZAmc4Z5IWTFTxrxp9ipQSLqbilTfIhkCX7MTHpCoLi0d8rYwDDVzx21t0RlVzAjBs3pKK2hd51qz"
},
"RequestId": "5aa57662-4faa-4d9e-ba32-e9726c715660"
}
  1. 然后我们使用aliyun configure –mode StsToken –profile assume-root-from-B0002将AK/SK和Token保存。

  2. 这时候我们已经在主账号下了,但是我们只有角色扮演和查看资源目录权限,其实是看不到主账号下的内容的。我们接着扮演角色到子账号C上。
    因为是主账号,本身加入资源目录的时候已经自动加了角色(resourcedirectoryaccountaccessrole),允许主账号操作。所以接下来我们:

    1
    aliyun sts AssumeRole --region cn-beijing --DurationSeconds 3600 --RoleSessionName alice --RoleArn acs:ram::C0003:role/resourcedirectoryaccountaccessrole

    然后再继续记录AK/SK和Token,并使用这STS AK密钥方式来登录CLI(也就是实现了扮演角色)。这个时候,你就已经可以DescribeInstances来操作账号C的资源了。
    使用主账号授权的好处是,只要你知道资源目录下UID,就能直接控制。

授权资源目录下B账号操作C或D账号

但是有没有可能我完全不希望主账号创建角色,而是在C账号,D账号等其他资源目录账号创建角色并授权B账号查看或者操作呢?

我们先忽略掉如何批量给资源目录下的账号创建角色问题,直接B–>C同样也是可行的。不过授权角色上,不同于管理账号授权,我们只需要授权想让B账号看到什么或者操作什么即可,比如ECS Full Access。
我们只需要在对应账号创建角色,并授权允许对应的权限即可。

1
2
3
acs:ram::UIDC0003:role/allow-access-from-B0002

aliyun sts AssumeRole --region cn-beijing --DurationSeconds 3600 --RoleArn acs:ram::UIDC0003:role/allow-access-from-B0002 --RoleSessionName alice

获得AK/SK和STS Token后,我们就能扮演C账号来管理了。

Python 角色扮演概念验证

将从B账号扮演C账号,然后列出C账号ECS资源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import os
import sys

from typing import List

from alibabacloud_sts20150401.client import Client as Sts20150401Client
from alibabacloud_ecs20140526.client import Client as Ecs20140526Client

from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_sts20150401 import models as sts_20150401_models
from alibabacloud_ecs20140526 import models as ecs_20140526_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from alibabacloud_credentials.client import Client as CredClient
from alibabacloud_tea_rpc.models import Config


class Sample:
def __init__(self):
pass

@staticmethod
def create_sts_client() -> Sts20150401Client:
"""
使用AK&SK初始化STS Client
@return: Sts20150401Client
"""
config = open_api_models.Config(
access_key_id='AAAAAAAAA',
access_key_secret='BBBBBBBBBBBBB'
)
# STS Endpoint 请参考 https://api.aliyun.com/product/Sts
config.endpoint = f'sts.cn-beijing.aliyuncs.com'
return Sts20150401Client(config)

@staticmethod
def create_ecs_client(access_key_id: str, access_key_secret: str, security_token: str) -> Ecs20140526Client:
"""
使用临时凭证初始化ECS Client
@param access_key_id: 临时 AccessKey ID
@param access_key_secret: 临时 AccessKey Secret
@param security_token: STS Token
@return: Ecs20140526Client
"""
config = open_api_models.Config(
access_key_id=access_key_id,
access_key_secret=access_key_secret,
security_token=security_token
)
# ECS Endpoint 请参考 https://api.aliyun.com/product/Ecs
config.endpoint = f'ecs.cn-beijing.aliyuncs.com'
return Ecs20140526Client(config)

@staticmethod
def assume_role(client: Sts20150401Client) -> dict:
"""
调用 AssumeRole 获取临时凭证
@param client: Sts20150401Client
@return: 包含临时凭证的字典
"""
request = sts_20150401_models.AssumeRoleRequest(
role_arn='acs:ram::UIDC0003:role/allow-from-B0002', # 替换为你的角色 ARN
role_session_name='alice' # 替换为你的会话名称
)
runtime = util_models.RuntimeOptions()
response = client.assume_role_with_options(request, runtime)
credentials = response.body.credentials

sts_result = {
'AccessKeyId': credentials.access_key_id,
'AccessKeySecret': credentials.access_key_secret,
'SecurityToken': credentials.security_token
}

print("Temporary Credentials:", sts_result) # 添加的调试打印语句

return sts_result

@staticmethod
def describe_ecs_instances(client: Ecs20140526Client) -> List[dict]:
"""
查询 ECS 实例信息
@param client: Ecs20140526Client
@return: ECS 实例列表
"""
request = ecs_20140526_models.DescribeInstancesRequest(
region_id='cn-beijing'
)
runtime = util_models.RuntimeOptions()
response = client.describe_instances_with_options(request, runtime)
instances = []
for instance in response.body.instances.instance:
private_ip = instance.vpc_attributes.private_ip_address.ip_address[
0] if instance.vpc_attributes and instance.vpc_attributes.private_ip_address.ip_address else "N/A"
instances.append({
'InstanceId': instance.instance_id,
'InstanceName': instance.instance_name,
'PrivateIP': private_ip,
'Status': instance.status
})
return instances

def main():
try:
# 初始化 STS 客户端
sts_client = Sample.create_sts_client()

# 获取临时凭证
credentials = Sample.assume_role(sts_client)

# 使用临时凭证初始化 ECS 客户端
ecs_client = Sample.create_ecs_client(
access_key_id=credentials['AccessKeyId'],
access_key_secret=credentials['AccessKeySecret'],
security_token=credentials['SecurityToken']
)

# 查询 ECS 实例信息
instances = Sample.describe_ecs_instances(ecs_client)

# 打印 ECS 实例信息
print("ECS Instances:")
for instance in instances:
print(f"Instance ID: {instance['InstanceId']}")
print(f"Instance Name: {instance['InstanceName']}")
print(f"Private IP: {instance['PrivateIP']}")
print(f"Status: {instance['Status']}")
print("-" * 40)

except Exception as e:
print(f"Error: {e}")


if __name__ == '__main__':
main()

  • 标题: 使用资源目录管理操作旗下账户的概念验证CLI
  • 作者: 暗香疏影
  • 创建于 : 2025-03-12 22:23:00
  • 更新于 : 2025-03-12 22:25:54
  • 链接: https://blog.23ikr.com/2025/03/12/2025-03-12-ram-resource-directory-ststoken/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
使用资源目录管理操作旗下账户的概念验证CLI