IAM policy 元素:变量和标签
在编写策略时,如果您不知道资源或条件键的精确值,可以使用 AWS Identity and Access Management (IAM) policy 变量作为占位符。
注意
如果 AWS 无法解析变量,这可能会导致整个语句无效。例如,如果您使用 aws:TokenIssueTime
变量,只有在请求者(IAM 角色)使用临时凭证进行身份验证时,该变量才会解析为一个值。要防止变量导致无效的语句,请使用 ...IfExists 条件运算符。
简介
在 IAM policy 中,您可通过很多操作为要控制其访问权限的特定资源指定名称。例如,以下策略允许用户为 marketing
项目列出、读取 S3 存储桶 DOC-EXAMPLE-BUCKET
中的对象以及将对象写入该存储桶。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET"], "Condition": {"StringLike": {"s3:prefix": ["marketing/*"]}} }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET/marketing/*"] } ] }
在某些情况下,您在编写策略时可能不知道资源的精确名称。您可能需要概括策略,这样无需为每个用户制作策略的唯一副本即可将该策略用于很多用户。我们建议您创建一个适用于该组中所有用户的单个组策略,而不是为每个用户创建一个单独的策略。
在策略中使用变量
您可以使用策略变量在策略中设置占位符,从而在策略中定义动态值。
变量使用 $
前缀标记,后面跟一对大括号 ({ }
),其中包含请求中值的变量名称。
评估策略时,策略变量将替换为来自请求中传递的条件上下文键的值。变量可用于基于身份的策略、资源策略、服务控制策略、会话策略和 VPC 端点策略。用作权限边界的基于身份的策略也支持策略变量。
全局条件上下文键可用作跨 AWS 服务的请求中的变量。在与 AWS 资源交互时,服务特定条件键也可以用作变量,但仅在针对支持它们的资源发出请求时才可用。有关每种 AWS 服务和资源的可用上下文键列表,请参阅《 服务授权参考》。某些情况下,您无法使用值填充全局条件上下文键。要了解有关每个键的更多信息,请参阅 AWS 全局条件上下文键。
重要
-
密钥名称不区分大小写。例如,
aws:CurrentTime
等同于AWS:currenttime
。 -
您可以使用任何可用的单值条件密钥作为变量。您不能使用多值条件键作为变量。
以下示例显示了 IAM 角色或用户的策略,该策略用策略变量来替代特定资源名称。您可以利用 aws:PrincipalTag
条件键来重复使用此策略。完成策略评估后,仅当存储桶名称以 team
主体标签中的团队名称结尾时,${aws:PrincipalTag/team}
才允许操作。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET"], "Condition": {"StringLike": {"s3:prefix": ["${aws:PrincipalTag/team}/*"]}} }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET/${aws:PrincipalTag/team}/*"] } ] }
该变量使用 $
前缀标记,后跟一对大括号 ({ }
)。在 ${ }
字符内,可以包含想要在策略中使用的请求中的值名称。本页稍后将讨论您可以使用的值。
有关此全局条件键的详细信息,请参阅全局条件键列表中的 aws:PrincipalTag/tag-key。
注意
为了使用策略变量,您必须在语句中包含 Version
元素,而且版本必须设置为支持策略变量的版本。变量是在 2012-10-17
版本中引入的。较早版本的策略语言不支持策略变量。如果您未添加 Version
元素,且没有将它设为相应的版本日期,则系统会将变量 (如 ${aws:username}
) 视为策略中的文字字符串。
Version
策略元素与策略版本不同。Version
策略元素用在策略之中,用于定义策略语言的版本。另一方面,当您更改 IAM 中的客户托管策略时,将创建一个策略版本。已更改的策略不会覆盖现有策略。而是由 IAM 创建新的托管策略版本。要了解 Version
策略元素的更多信息,请参阅IAM JSON 策略元素:Version。要了解策略版本的更多信息,请参阅IAM policy 版本控制。
允许主体从 S3 存储桶中的 /David 路径获取对象的策略如下所示:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3::DOC-EXAMPLE-BUCKET/
David
/*"] }] }
如果将此策略附加到用户 David
,则该用户将获取自己 S3 存储桶中的对象,但您必须为每个用户创建包含该用户名称的单独策略,然后将每个策略附加到各个用户。
通过使用策略变量,您可以创建可重复使用的策略。以下策略允许用户在 aws:PrincipalTag
的标签键值与请求中传递的标签键 owner
值一致时,获取 Amazon S3 存储桶中的对象。
{ "Version": "2012-10-17", "Statement": [{ "Sid": "AllowUnlessOwnedBySomeoneElse", "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": ["*"], "Condition": { "StringEquals": { "s3:ExistingObjectTag/owner": "${aws:PrincipalTag/owner}" } } } ] }
如果您使用策略变量,而不是与此类似的用户名称,则无需为每个单独的用户创建单独的策略。在以下示例中,该策略被附加到一个将由产品经理使用临时安全凭证代入的 IAM 角色。当用户发出添加 Amazon S3 对象的请求时,IAM 将使用当前请求中的 dept
标签值替换 ${aws:PrincipalTag}
变量,然后评估策略。
{ "Version": "2012-10-17", "Statement": [{ "Sid": "AllowOnlyDeptS3Prefix", "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET/${aws:PrincipalTag/dept}/*"], } ] }
作为策略变量的标签
在某些 AWS 服务中,您可以将自己的自定义属性附加到这些服务创建的资源。例如,您可以将标签应用于 Amazon S3 存储桶或者 IAM 用户。这些标签是键值对。您要定义标签键名称以及与该键名称关联的值。例如,您可以创建一个具有 department
键和 Human Resources
值的标签。有关标记 IAM 实体的更多信息,请参阅 标记 IAM 资源。有关标记其他 AWS 服务创建的资源的信息,请参阅该服务的文档。有关使用标签编辑器的信息,请参阅《AWS Management Console 用户指南》中的使用标签编辑器。
您可以标记 IAM 资源来简化对您的 IAM 资源的发现、组织和跟踪。您也可以标记 IAM 身份以控制对资源或标记本身的访问。要了解有关使用标签控制访问的更多信息,请参阅 使用标签控制对 IAM 用户和角色的访问以及他们进行的访问。
您可以使用策略变量的位置
您可以在 Resource
元素中和 Condition
元素的字符串比较中使用策略变量。
资源元素
您可以在 Resource
元素中使用策略变量,但只能在 ARN 的资源部分中使用策略变量。ARN 的这一部分出现在第五个冒号 (:) 之后。不能使用变量来替换 ARN 中第五个冒号之前的部分,例如服务或账户。有关 ARN 格式的更多信息,请参见IAM ARN。
要将 ARN 的一部分替换为标签值,请用 ${ }
将前缀和键名称括起来。例如,以下 Resource 元素将仅指向名称等于请求用户的 department 标签中的值的存储桶。
"Resource":
["arn:aws::s3:::bucket/${aws:PrincipalTag/
department
}"]
许多 AWS 资源使用包含用户创建的名称的 ARN。以下 IAM policy 确保只有 access-project、access-application 和 access-environment 标签值匹配的目标用户才能修改其资源。此外,使用 * 通配符匹配,将可以允许自定义资源名称后缀。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAccessBasedOnArnMatching", "Effect": "Allow", "Action": [ "sns:CreateTopic", "sns:DeleteTopic"], "Resource": ["arn:aws:sns:*:*:${aws:PrincipalTag/
access-project
}-${aws:PrincipalTag/access-application
}-${aws:PrincipalTag/access-environment
}-*" ] } ] }
条件元素
您可以在任何涉及字符串运算符或 ARN 运算符的条件下对 Condition
值使用策略变量。字符串运算符包括 StringEquals
、StringLike
和 StringNotLike
。ARN 运算符包括 ArnEquals
和 ArnLike
。不能将策略变量与其他运算符(如Numeric
、Date
、Boolean
、Binary
、IP Address
或 Null
运算符)一起使用。有关条件运算符的更多信息,请参阅IAM JSON 策略元素:条件运算符。
当引用 Condition
元素表达式中的标签时,请将相关的前缀和标签键用作条件键。然后,使用要在条件值中测试的值。
例如,以下示例策略仅在将标签 costCenter
附加到用户时才允许用户拥有完全访问权限。该标签还必须具有值 12345
或 67890
。如果该标签没有值或具有任何其他值,则请求会失败。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:*user*" ], "Resource": "*", "Condition": { "StringLike": { "iam:ResourceTag/costCenter": [ "12345", "67890" ] } } } ] }
无值的策略变量
当策略变量引用的条件上下文键没有值或不存在于请求的授权上下文中时,该值实际上为空。没有相等或相似的值。在以下情况下,条件上下文键可能不存在于授权上下文中:
-
您在对不支持该条件键的资源的请求中使用服务特定条件上下文键。
-
IAM 主体、会话、资源或请求上的标签不存在。
-
为 AWS 全局条件上下文密钥 中的每个全局条件上下文键列出的其他情况。
当您在 IAM policy 的条件元素中使用没有值的变量时,IAM JSON 策略元素:条件运算符(如 StringEquals
或 StringLike
)不匹配,并且策略声明不生效。
反向条件运算符(如 StringNotEquals
或 StringNotLike
)确实与空值相匹配,因为它们测试的条件键的值不等于或不类似于实际空值。
在下例中,aws:principaltag/Team
必须等于 s3:ExistingObjectTag/Team
才能允许访问。未设置 aws:principaltag/Team
时会被显式拒绝访问。如果将授权上下文中没有值的变量用作策略的 Resource
或 NotResource
元素的一部分,则包含无值的策略变量的资源与任何资源都不匹配。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::/example-bucket/*", "Condition": { "StringNotEquals": { "s3:ExistingObjectTag/Team": "${aws:PrincipalTag/Team}" } } } ] }
可以用于策略变量的请求信息
您可以使用 JSON 策略的 Condition
元素将请求上下文中的键与您在策略中指定的键值进行比较。当您使用策略变量时,AWS 使用请求上下文密钥中的值替换策略中的变量。
主体键值
aws:username
、aws:userid
和 aws:PrincipalType
的值取决于发起请求的主体的类型。例如,可能使用 IAM 用户、IAM 角色或 AWS 账户根用户 的凭证发出请求。以下表为不同类型的主体显示这些键的值。
主体 | aws:username |
aws:userid |
aws:PrincipalType |
---|---|---|---|
AWS 账户根用户 | (不存在) | AWS 账户 ID | Account |
IAM 用户 | IAM 用户名称 |
唯一 ID | User |
联合身份用户 | (不存在) | 账户 :调用者指定的名称 |
FederatedUser |
OIDC 联合用户 有关在使用 Web 联合身份验证时可用的策略键的信息,请参阅AWS OIDC 联合身份验证的可用键。 |
(不存在) |
其中, |
AssumedRole |
SAML 联合身份用户 有关在使用 SAML 联合身份验证时可用的策略键的信息,请参阅唯一标识基于 SAML 的联合中的用户。 |
(不存在) |
其中, |
AssumedRole |
担任的角色 | (不存在) |
其中, |
AssumedRole |
分配给 Amazon EC2 实例的角色 | (不存在) |
其中 |
AssumedRole |
匿名调用者(仅限 Amazon SQS、Amazon SNS 和 Amazon S3) | (不存在) | anonymous |
Anonymous |
对于此表中的项目请注意以下事项:
-
不存在 表示值在当前请求信息中不存在,并且匹配该值的任何尝试都失败并导致语句无效。
-
角色 ID
是在创建时分配给每个角色的唯一标识符。可以使用 AWS CLI 命令显示角色 ID:aws iam get-role --role-name
rolename
-
调用者指定的名称
和调用者指定的角色名称
是进行调用以获取临时凭证时调用进程 (例如应用程序或服务) 传递的名称。 -
ec2-instance-id
是在实例启动时分配给它的值,显示在 Amazon EC2 控制台的 Instances(实例)页面上。您还可以通过运行 AWS CLI 命令来显示实例 ID:aws ec2 describe-instances
联合身份用户的请求中的可用信息
联合身份用户是使用系统而不是 IAM 验证的用户。例如,公司可能拥有调用 AWS 的供内部使用的应用程序。为使用该应用程序的每位公司用户都提供 IAM 身份可能不现实。相反,该公司可能使用具有单一 IAM 身份的代理 (中间层) 应用程序,或该公司可能使用 SAML 身份提供程序 (IdP)。代理应用程序或 SAML IdP 会使用企业网络对单个用户进行身份验证。然后,代理应用程序可使用其 IAM 身份获取单个用户的临时安全凭证。实际上,SAML IdP 可以将身份信息交换为 AWS 临时安全凭证。然后,临时凭证即可用于访问 AWS 资源。
类似地,您可以创建用于移动设备的应用程序,该应用程序需要访问 AWS 资源。在这种情况下,您可以使用 OIDC 联合身份验证,其中应用程序使用知名身份提供者(如 Login with Amazon、Amazon Cognito、Facebook 或 Google)对用户进行身份验证。随后,应用程序可以使用这些提供商提供的用户身份验证信息来获取访问 AWS 资源的临时安全凭证。
使用 OIDC 联合身份验证的推荐方法是利用 Amazon Cognito 和 AWS 移动 SDK。有关更多信息,请参阅下列内容:
特殊字符
有几个特殊预定义策略变量具有固定值,可用于表示字符 (这些字符本身有特殊的含义)。如果这些特殊字符是您尝试匹配的字符串的一部分,而您原样插入这些字符,则不能正确进行解释。例如,在字符串中插入 * 星号会解释为与任何字符匹配的通配符 (而不是解释为文本 *)。这种情况下,可以使用以下预定义策略变量:
-
${*} - 在需要 *(星号)字符的位置使用。
-
${?} - 在需要 ?(问号)字符的位置使用。
-
${$} - 在需要 $(美元符号)字符的位置使用。
在任何可以使用常规策略变量的字符串中,都可以使用这些预定义策略变量。
指定默认值
要向变量添加默认值,请用单引号 (' '
) 括起默认值,并用逗号和空格 (,
) 分隔变量文本和默认值。
例如,如果使用主体标记 team=yellow
,他们可以访问名为 DOC-EXAMPLE-BUCKET-yellow
的 ExampleCorp's
Amazon S3 存储桶。使用此资源的策略可能允许团队成员访问自己的团队存储桶,但不能访问其他团队的存储桶。对于没有团队标签的用户,它将原定设置值设为 company-wide
存储桶名称。这些用户只能访问 DOC-EXAMPLE-BUCKET-company-wide
存储桶,他们可以在其中查看广泛的信息,例如加入团队的说明。
"Resource":"arn:aws:s3:::
DOC-EXAMPLE-BUCKET
-${aws:PrincipalTag/team, 'company-wide
'}"
有关更多信息
欲了解更多有关策略的信息,请参阅: