背景 阿里云账号分为主账号(用户)和子账号(用户)两类,主账号为注册阿里云时的账号,其权限为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控制台 。oos 选择2台实例,在操作菜单下选择更多 > 实例设置 > 编辑标签。 单击新建标签,输入标签键 和标签值,单击确定。 本文中标签键设为TagKey,标签值设为TagValue。oos 单击确定。 打开实例列表栏,在搜索框中输入TagKey:TagValue,单击放大镜图标。 oos 确认搜索结果为刚刚打标签TagKey:TagValue的实例。 oos 创建OOS模版 使用阿里云主账号(或管理员账号)登录到运维编排控制台 。 单击我的模版,单击创建模版,选取空白模版,单击YAML。 本文中模版格式选择YAML。 oos 将附件中YAML的模版内容复制到空白模版中(若您对实例分组的标签键值不是TagKey:TagValue,请根据实际情况对模版中TagKey和TagValue进行修改)。
oos
模版任务如下,请确认模版将执行的任务。
验证指定标签下是否存在实例。 根据标签下是否存在停止的实例选择后续任务。 如果标签下存在停止的实例,则启动这些实例。 为标签下所有实例安装云助手。 在标签下所有实例中运行Shell命令。 填写模板名称,单击创建模版 。 本文中,模版名称设为TestOperatingByGroups。oos
在我的模版栏,可查看成功创建的模版TestOperatingByGroups。 创建子账号(用户) 使用阿里云主账号(或管理员账号)登录RAM控制台 在左侧导航栏的人员管理菜单下,单击用户 > 新建用户。 输入登录名称及显示名称。 本文中的登录名称及显示名称均设为subUser1ForOOS。 勾选控制台密码登录,单击自定义登录密码并填写要设置的子账号密码。 oos 单击确定。 在用户栏中可查看成功创建的新账号。oos 创建自定义权限策略 使用阿里云主账号登录RAM控制台 在左侧导航栏的权限管理菜单下,单击权限策略管理。 单击新建权限策略。 创建第一条策略用来管理OOS资源操作。 填写策略名称和备注。 本文中策略名称设置为OOSResourceManage。 配置模式选择脚本配置,并将下述的第一段JSON策略样例拷贝到策略内容区域,并根据实际情况进行修改(将JSON中所有以$为前缀的变量名替换掉)。 将第一段JSON中的$AliyunMasterAccountID、$RegionID、$TemplateName1修改为您所使用的阿里云主账号ID、OOS及ECS资源所在地域ID(本文中为cn-hangzhou)、允许子账号可执行的模版名称(本文中为TestOperatingByGroups。))。 oos 操作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 操作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 单击确定。 单击完成。 执行OOS模版 使用主账号(或管理员账号)登录RAM概览,在右侧获取子账号登录地址。 oos 退出主账号(或管理员账号)的登录,访问刚获取的子账号登录地址,登录子账号。 本文中登录的子账号为subUser1ForOOS。oos 登录成功后,进入运维编排控制台 。 单击我的模版,找到TestOperatingByGroups模版,单击创建执行。oos 单击 下一步,设置参数。 设置参数。 commandContent 将要执行的shell命令。 rateControl 模版执行时任务循环的并发速率及最大失败任务数。oos 单击 下一步,确认,单击创建执行。 在执行管理中可查看刚刚创建的执行。 若创建执行成功,且执行状态处于运行中,则表示命令已开始执行。 当执行状态转换为成功时,则表示命令执行成功。 如需了解执行细节,单击该执行的详情,查看执行日志。 权限策略的补充验证 OOS模版执行成功后,表示子账号subUser1ForOOS的权限策略支持模版TestOperatingByGroups执行需要的权限,也可在OOS控制台验证子账号无法执行未授权的模版。另外,若想验证子账号无法对标签以外实例的操作,可在登录子账号subUser1ForOOS后,通过Open Api 调试台对可操作API权限进行验证。
附件:OOS模版- - -在某标签下的所有ECS实例中执行命令 模板内容(YAML格式) 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 }}' 模板内容(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 }}" } } }
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。