OOS操作ECS分组资源的权限策略管理
更新时间:2019-11-15 12:18:25
背景
阿里云账号分为主账号(用户)和子账号(用户)两类,主账号为注册阿里云时的账号,其权限为root,出于安全考虑,建议实际操作时采用子账号。而操作员工的职责不同,不同子账号需要的权限也不同。此时,子账号权限策略的有效管理就很重要。
本文将介绍下,当某员工通过子账号,使用运维编排服务(OOS)执行某模版,来完成一些例行运维任务时,如何既使子账号顺利完成相应操作,又最大程度保障账号的安全。
场景介绍
某公司账号下购买了若干台ECS实例,其中2台被打上标签TagKey:TagValue进行了分组,某员工甲被分配的子账号为subUser1ForOOS,甲定期通过该账号在OOS中执行一个模版T,模版执行的任务是对标签TagKey:TagValue分组下的ECS实例批量执行shell指令。即该员工具有对模版T的只读和执行权限,以及有模版任务涉及API(如RunCommand)的操作权限,且可操作的API仅对标签TagKey:TagValue分组下的实例有效。
解决方案
为满足上述场景,权限管理要分两方面,即OOS资源操作和ECS资源操作。
OOS方面权限策略包括对模版的只读权限、对模版T的执行权限、对执行的查询权限。
ECS方面权限策略为对标签TagKey:TagValue下实例的操作权限,且操作权限仅限于模版中涉及的API。
以上的权限策略成功创建后,将其授权给员工甲使用的RAM子用户即可(或具有员工甲相同职责的用户组)。
操作步骤
步骤如下
- ECS实例的分组
- 创建OOS模版
- 创建子账号(用户)
- 创建自定义权限策略
- 为子账号授权
- 子账号执行OOS模版
- 权限策略的补充验证
ECS实例的分组
- 使用阿里云主账号(或管理员账号)登录到ECS控制台 。

- 选择2台实例,在操作菜单下选择更多 > 实例设置 > 编辑标签。
- 单击新建标签,输入标签键 和标签值,单击确定。
本文中标签键设为TagKey,标签值设为TagValue。
- 单击确定。
- 打开实例列表栏,在搜索框中输入TagKey:TagValue,单击放大镜图标。

- 确认搜索结果为刚刚打标签TagKey:TagValue的实例。

创建OOS模版
- 使用阿里云主账号(或管理员账号)登录到运维编排控制台 。
- 单击我的模版,单击创建模版,选取空白模版,单击YAML。
本文中模版格式选择YAML。
将附件中YAML的模版内容复制到空白模版中(若您对实例分组的标签键值不是TagKey:TagValue,请根据实际情况对模版中TagKey和TagValue进行修改)。

模版任务如下,请确认模版将执行的任务。
- 验证指定标签下是否存在实例。
- 根据标签下是否存在停止的实例选择后续任务。
- 如果标签下存在停止的实例,则启动这些实例。
- 为标签下所有实例安装云助手。
- 在标签下所有实例中运行Shell命令。
填写模板名称,单击创建模版 。
本文中,模版名称设为TestOperatingByGroups。
- 在我的模版栏,可查看成功创建的模版TestOperatingByGroups。
创建子账号(用户)
- 使用阿里云主账号(或管理员账号)登录RAM控制台
- 在左侧导航栏的人员管理菜单下,单击用户 > 新建用户。
- 输入登录名称及显示名称。
本文中的登录名称及显示名称均设为subUser1ForOOS。 - 勾选控制台密码登录,单击自定义登录密码并填写要设置的子账号密码。

- 单击确定。
- 在用户栏中可查看成功创建的新账号。

创建自定义权限策略
- 使用阿里云主账号登录RAM控制台
- 在左侧导航栏的权限管理菜单下,单击权限策略管理。
- 单击新建权限策略。
创建第一条策略用来管理OOS资源操作。 - 填写策略名称和备注。
本文中策略名称设置为OOSResourceManage。 配置模式选择脚本配置,并将下述的第一段JSON策略样例拷贝到策略内容区域,并根据实际情况进行修改(将JSON中所有以$为前缀的变量名替换掉)。
将第一段JSON中的$AliyunMasterAccountID、$RegionID、$TemplateName1修改为您所使用的阿里云主账号ID、OOS及ECS资源所在地域ID(本文中为cn-hangzhou)、允许子账号可执行的模版名称(本文中为TestOperatingByGroups。))。
操作OOS的策略
该段策略表示:被授权RAM用户具有对$RegionID地域下模版的只读权限、对模版$TemplateName1的执行权限、对$RegionID地域下OOS执行的查询权限。{"Statement": [{"Action": ["oos:StartExecution","oos:List*","oos:Get*"],"Resource": ["acs:oos:$RegionID:$AliyunMasterAccountID:template/$TemplateName1","acs:oos:$RegionID:$AliyunMasterAccountID:execution/*"],"Effect": "Allow"},{"Action": ["oos:List*","oos:Get*"],"Resource": ["acs:oos:$RegionID:$AliyunMasterAccountID:template/*"],"Effect": "Allow"}],"Version": "1"}
单击确定。
- 单击新建权限策略,创建第二条策略用来管理ECS资源操作。
- 填写策略名称和备注。
配置模式选择脚本配置,将下述的第二段JSON策略样例拷贝到策略内容区域,并根据实际情况进行修改(将JSON中所有以$为前缀的变量名替换掉)。
将第二段JSON中的$AliyunMasterAccountID、$TagKey、$TagValue、$RegionID修改为您所使用的阿里云主账号ID、实例所属标签键和标签值(本文中根据ECS实例的分组,键及值应设为TagKey和TagValue)、OOS及ECS资源所在地域ID。(本文中为cn-hangzhou)。
操作ECS的策略
该段策略表示:被授权RAM用户具有对标签$TagKey:$TagValue下实例的操作权限,且仅可操作模版中涉及的API。{"Statement": [{"Effect": "Allow","Action": ["ecs:DescribeInstances","ecs:RebootInstance"],"Resource": "acs:ecs:$RegionID:$AliyunMasterAccountID:instance/*","Condition": {"StringEquals": {"ecs:tag/$TagKey": ["$TagValue"]}}},{"Effect": "Allow","Action": ["ecs:DescribeCloudAssistantStatus","ecs:InstallCloudAssistant"],"Resource": "acs:ecs:*:$AliyunMasterAccountID:instance/*","Condition": {"StringEquals": {"ecs:tag/$TagKey": ["$TagValue"]}}},{"Action": "ecs:DescribeTagKeys","Effect": "Allow","Resource": "*"},{"Action": "ecs:DescribeTags","Effect": "Allow","Resource": "*"},{"Effect": "Deny","Action": ["ecs:DeleteTags","ecs:UntagResources","ecs:CreateTags","ecs:TagResources"],"Resource": "*"},{"Effect": "Allow","Action": ["ecs:RunCommand"],"Resource": "acs:ecs:*:$AliyunMasterAccountID:instance/*","Condition": {"StringEquals": {"ecs:tag/$TagKey": ["$TagValue"]}}},{"Action": ["ecs:RunCommand"],"Resource": ["acs:ecs:*:$AliyunMasterAccountID:command/*"],"Effect": "Allow"},{"Action": ["ecs:DescribeInvocations","ecs:DescribeInvocationResults"],"Resource": ["*"],"Effect": "Allow"}],"Version": "1"}
单击确定。
为子账号(或用户组)授权
- 使用阿里云主账号(或管理员账号)登录RAM控制台。
- 在左侧导航栏的权限管理菜单下,单击授权。
- 单击新增授权。
- 在被授权主体中输入子账号名称(或用户组名称)并选中,在选择权限中选择自定义权限策略,在左侧权限策略名称列表下,单击选择需要授予给子账号(或用户组)的权限策略。
- 本文输入的子账号名称为subUser1ForOOS。
- 本文选择的权限策略名称为OOSResourceManage和ECSResourceManage。
- 在右侧区域框,若撤销对某策略的选择,可单击某条策略的×。

- 单击确定。
- 单击完成。
执行OOS模版
- 使用主账号(或管理员账号)登录RAM概览,在右侧获取子账号登录地址。

- 退出主账号(或管理员账号)的登录,访问刚获取的子账号登录地址,登录子账号。
- 本文中登录的子账号为subUser1ForOOS。

- 本文中登录的子账号为subUser1ForOOS。
- 登录成功后,进入运维编排控制台 。
- 单击我的模版,找到TestOperatingByGroups模版,单击创建执行。

- 单击 下一步,设置参数。
- 设置参数。
- commandContent 将要执行的shell命令。
- rateControl 模版执行时任务循环的并发速率及最大失败任务数。

- 单击 下一步,确认,单击创建执行。
- 在执行管理中可查看刚刚创建的执行。
若创建执行成功,且执行状态处于运行中,则表示命令已开始执行。 - 当执行状态转换为成功时,则表示命令执行成功。
- 如需了解执行细节,单击该执行的详情,查看执行日志。
权限策略的补充验证
OOS模版执行成功后,表示子账号subUser1ForOOS的权限策略支持模版TestOperatingByGroups执行需要的权限,也可在OOS控制台验证子账号无法执行未授权的模版。另外,若想验证子账号无法对标签以外实例的操作,可在登录子账号subUser1ForOOS后,通过Open Api 调试台对可操作API权限进行验证。
附件:OOS模版- - -在某标签下的所有ECS实例中执行命令
- 模板内容(YAML格式)
FormatVersion: OOS-2019-06-01Description:en: Run a specific command in specified ECS instances.zh-cn: 对某些实例执行具体命令。name-en: RunSpecificCommandInSpecifiedInstancesname-zh-cn: 指定的实例上执行具体命令。Parameters:commandContent:Description:en: commandContent.zh-ch: shell指令内容。Type: StringDefault: echo hellorateControl:Description:en: Concurrency rate of task execution.zh-cn: 任务执行的并发比率。Type: JsonAssociationProperty: RateControlDefault:Mode: ConcurrencyMaxErrors: 0Concurrency: 100%Tasks:- Name: CheckInstancesExistInTagAction: 'ACS::CheckFor'Description:en: Check for whether instances exist in specified tag.zh-cn: 验证指定标签下是否存在实例。Properties:Service: ECSAPI: DescribeInstancesParameters:Tags:- Key: TagKeyValue: TagValueNotDesiredValues:- []PropertySelector: Instances.Instance|map(.InstanceId)Outputs:instanceIds:Type: ListValueSelector: 'Instances.Instance[].InstanceId'stoppedInstanceIdsExist:Type: StringValueSelector: >-Instances.Instance[]|select(.Status=="Stopped")|.InstanceId|[.]|all|tostringstoppedInstanceIds:Type: ListValueSelector: 'Instances.Instance[]|select(.Status=="Stopped")|.InstanceId'- Name: whetherStoppedInstancesExistAction: 'ACS::Choice'Description:en: Choose next task by stopped instances exist.zh-cn: 根据标签下是否存在停止的实例选择后续任务。Properties:DefaultTask: installCloudAssistantChoices:- When:'Fn::Equals':- 'true'- '{{ CheckInstancesExistInTag.stoppedInstanceIdsExist }}'NextTask: startInstances- Name: startInstancesAction: 'ACS::ECS::StartInstance'Description:en: Start Instance.zh-cn: 启动标签下停止的实例。Properties:instanceId: '{{ ACS::TaskLoopItem }}'Loop:Items: '{{ CheckInstancesExistInTag.stoppedInstanceIds }}'RateControl: '{{ rateControl }}'- Name: installCloudAssistantAction: 'ACS::ECS::InstallCloudAssistant'Description:en: Install cloud assostant for ECS instances in tag.zh-cn: 给标签下所有实例安装云助手。Properties:instanceId: '{{ ACS::TaskLoopItem }}'Loop:Items: '{{ CheckInstancesExistInTag.instanceIds }}'RateControl: '{{ rateControl }}'- Name: runCommandAction: 'ACS::ECS::RunCommand'Description:en: Run cloud assostant command on ECS instances in tag.zh-cn: 在标签下所有实例中运行云助手命令。Properties:commandContent: '{{ commandContent }}'commandType: RunShellScriptinstanceId: '{{ ACS::TaskLoopItem }}'Loop:Items: '{{ CheckInstancesExistInTag.instanceIds }}'RateControl: '{{ rateControl }}'Outputs:invocationOutputs:AggregateType: 'Fn::ListJoin'AggregateField: invocationOutputOutputs:invocationOutput:Type: StringValueSelector: .invocationOutputOutputs:invocationOutput:Type: ListValue: '{{ runCommand.invocationOutputs }}'
- 模板内容(JSON格式)
{"FormatVersion": "OOS-2019-06-01","Description": {"en": "Run a specific command in specified ECS instances.","zh-cn": "对某些实例执行具体命令。","name-en": "RunSpecificCommandInSpecifiedInstances","name-zh-cn": "指定的实例上执行具体命令。"},"Parameters": {"commandContent": {"Description": {"en": "commandContent.","zh-ch": "shell指令内容。"},"Type": "String","Default": "echo hello"},"rateControl": {"Description": {"en": "Concurrency rate of task execution.","zh-cn": "任务执行的并发比率。"},"Type": "Json","AssociationProperty": "RateControl","Default": {"Mode": "Concurrency","MaxErrors": 0,"Concurrency": "100%"}}},"Tasks": [{"Name": "CheckInstancesExistInTag","Action": "ACS::CheckFor","Description": {"en": "Check for whether instances exist in specified tag.","zh-cn": "验证指定标签下是否存在实例。"},"Properties": {"Service": "ECS","API": "DescribeInstances","Parameters": {"Tags": [{"Key": "TagKey","Value": "TagValue"}]},"NotDesiredValues": [[]],"PropertySelector": "Instances.Instance|map(.InstanceId)"},"Outputs": {"instanceIds": {"Type": "List","ValueSelector": "Instances.Instance[].InstanceId"},"stoppedInstanceIdsExist": {"Type": "String","ValueSelector": "Instances.Instance[]|select(.Status=="Stopped")|.InstanceId|[.]|all|tostring"},"stoppedInstanceIds": {"Type": "List","ValueSelector": "Instances.Instance[]|select(.Status=="Stopped")|.InstanceId"}}},{"Name": "whetherStoppedInstancesExist","Action": "ACS::Choice","Description": {"en": "Choose next task by stopped instances exist.","zh-cn": "根据标签下是否存在停止的实例选择后续任务。"},"Properties": {"DefaultTask": "installCloudAssistant","Choices": [{"When": {"Fn::Equals": ["true","{{ CheckInstancesExistInTag.stoppedInstanceIdsExist }}"]},"NextTask": "startInstances"}]}},{"Name": "startInstances","Action": "ACS::ECS::StartInstance","Description": {"en": "Start Instance.","zh-cn": "启动标签下停止的实例。"},"Properties": {"instanceId": "{{ ACS::TaskLoopItem }}"},"Loop": {"Items": "{{ CheckInstancesExistInTag.stoppedInstanceIds }}","RateControl": "{{ rateControl }}"}},{"Name": "installCloudAssistant","Action": "ACS::ECS::InstallCloudAssistant","Description": {"en": "Install cloud assostant for ECS instances in tag.","zh-cn": "给标签下所有实例安装云助手。"},"Properties": {"instanceId": "{{ ACS::TaskLoopItem }}"},"Loop": {"Items": "{{ CheckInstancesExistInTag.instanceIds }}","RateControl": "{{ rateControl }}"}},{"Name": "runCommand","Action": "ACS::ECS::RunCommand","Description": {"en": "Run cloud assostant command on ECS instances in tag.","zh-cn": "在标签下所有实例中运行云助手命令。"},"Properties": {"commandContent": "{{ commandContent }}","commandType": "RunShellScript","instanceId": "{{ ACS::TaskLoopItem }}"},"Loop": {"Items": "{{ CheckInstancesExistInTag.instanceIds }}","RateControl": "{{ rateControl }}","Outputs": {"invocationOutputs": {"AggregateType": "Fn::ListJoin","AggregateField": "invocationOutput"}}},"Outputs": {"invocationOutput": {"Type": "String","ValueSelector": ".invocationOutput"}}}],"Outputs": {"invocationOutput": {"Type": "List","Value": "{{ runCommand.invocationOutputs }}"}}}
