EC2标签受限资源级权限下,如何允许IAM用户设置Name等自定义标签
我之前处理过类似的EC2标签权限配置场景,结合你提到的Lambda自动打标和基于标签的资源级权限,这里给你一套可行的解决方案——核心是区分系统控制标签(Owner、PrincipalId)和用户自定义标签(Name等)的权限范围,同时确保Lambda的自动打标逻辑不受干扰。
1. 调整IAM权限策略,拆分标签操作权限
你需要在IAM策略里明确区分两种权限:一是允许用户在启动实例时指定自定义标签,二是允许用户对自己的实例修改自定义标签,但禁止触碰系统控制的Owner和PrincipalId标签。
示例1:允许启动实例时指定自定义标签
给用户的RunInstances权限添加标签控制,允许他们指定除Owner、PrincipalId之外的标签,同时通过资源级条件确保最终实例的Owner标签会匹配用户(Lambda会自动补全这个标签):
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": [ "arn:aws:ec2:*:*:instance/*", "arn:aws:ec2:*:*:image/ami-*", "arn:aws:ec2:*:*:subnet/*", "arn:aws:ec2:*:*:security-group/*", "arn:aws:ec2:*:*:key-pair/*" ], "Condition": { "StringEquals": { "ec2:ResourceTag/Owner": "${aws:username}" }, "ForAllValues:StringNotEquals": { "ec2:CreateTag": ["Owner", "PrincipalId"] } } }, // 补充必要的描述类权限 { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:DescribeImages" ], "Resource": "*" } ] }
这里的ForAllValues:StringNotEquals条件限制用户在启动时不能设置Owner和PrincipalId标签,确保这两个标签只能由Lambda来设置。
示例2:允许修改自己实例的自定义标签
添加CreateTags和DeleteTags的权限,允许用户对Owner标签匹配自己的实例操作,但排除系统控制的标签:
{ "Effect": "Allow", "Action": [ "ec2:CreateTags", "ec2:DeleteTags" ], "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringEquals": { "ec2:ResourceTag/Owner": "${aws:username}" }, "ForAllValues:StringNotEquals": { "ec2:TagKey": ["Owner", "PrincipalId"] } } }
这个策略确保用户只能修改自己实例的非系统标签,比如Name、Project等自定义标签。
2. 优化Lambda自动打标逻辑
你的Lambda函数需要在实例创建后立即设置Owner和PrincipalId标签,并且要注意:
- 触发条件设置为EC2的
RunInstances事件,确保实例一创建就打标 - 打标时不要覆盖用户已经设置的其他标签(比如Name),只添加或更新Owner和PrincipalId
示例Lambda代码片段(Python):
import boto3 ec2 = boto3.client('ec2') def lambda_handler(event, context): # 提取实例ID列表 instance_ids = [item['InstanceId'] for item in event['detail']['responseElements']['instancesSet']['items']] # 获取调用RunInstances的IAM用户信息 principal_id = event['detail']['userIdentity']['principalId'] username = event['detail']['userIdentity']['userName'] # 给实例添加系统标签,不影响现有自定义标签 ec2.create_tags( Resources=instance_ids, Tags=[ {'Key': 'Owner', 'Value': username}, {'Key': 'PrincipalId', 'Value': principal_id} ] ) return { 'statusCode': 200, 'body': f"系统标签已添加至实例:{instance_ids}" }
同时要确保Lambda的执行角色拥有ec2:CreateTags权限,资源范围可以设为*或指定EC2实例ARN。
3. 验证权限逻辑
完成配置后,你可以做以下测试:
- 用受限用户启动实例,尝试设置Name标签,同时尝试设置Owner标签,确认Owner标签无法设置,Name标签可以正常添加
- 用该用户修改自己实例的Name标签,确认可以修改;尝试修改Owner标签,确认操作被拒绝
- 查看Lambda日志,确认实例创建后Owner和PrincipalId标签被自动添加
这样就能实现:用户只能访问和操作自己的实例(通过Owner标签限制),同时可以自由设置和修改Name等自定义标签,而Owner和PrincipalId标签由系统自动维护,用户无法触碰。
内容的提问来源于stack exchange,提问作者PicoutputCls

