使用 IAM 策略条件进行精细访问控制
在 DynamoDB 中授予权限时,可以指定确定权限策略如何生效的条件。
概述
在 DynamoDB 中,您可以在使用 IAM 策略授予权限时指定条件(请参阅适用于 Amazon DynamoDB 的 Identity and Access Management)。例如,您可以:
-
授予权限,允许用户只读访问表或二级索引的特定项目和属性。
-
根据用户身份授予权限,允许用户只写访问表的特定属性。
在 DynamoDB 中,您可以使用条件键在 IAM 策略中指定条件,如以下部分中的使用案例所示。
注意
有些 AWS 服务也支持基于标签的条件,但 DynamoDB 不支持。
权限使用案例
除了对 DynamoDB API 操作的权限进行控制外,您还可以控制对单个的数据项目和属性的访问。例如,您可以执行以下操作:
-
对表授予权限,但根据特定主键值限制对该表中特定项目的访问。例如,在游戏社交网络应用程序中,所有用户的游戏数据均存储在一个表中,但是用户不能访问不归自己所有的数据项目,如下图所示:
-
隐藏信息,仅向用户显示属性的子集。例如,根据用户位置显示附近机场航班数据的应用程序。航空公司名称、到达和起飞时间以及航班号均会显示。但是,飞行员姓名或乘客数量之类的属性会被隐藏,如下图所示:
要实现如此精细的访问控制,您可以编写 IAM 权限策略,用于指定访问安全凭证和相关权限的条件。然后,将该策略应用于您使用 IAM 控制台创建的 用户、组或角色。您的 IAM 策略可以对表中单个项目的访问和项目中属性的访问实施单独控制,也可以同时控制。
您可以视情况使用 Web 联合身份验证控制使用 Login with Amazon、Facebook 或 Google 进行身份验证的用户访问。有关更多信息,请参阅 使用 Web 身份联合验证。
您可以使用 IAM Condition
元素实现精细的访问控制策略。通过向权限策略添加 Condition
元素,您可以根据特定业务要求允许或拒绝对 DynamoDB 表和索引中的项目和属性的访问。
例如,支持玩家从各种不同的游戏中进行选择并参与的移动游戏应用程序。该应用程序使用名为 GameScores
的 DynamoDB 表跟踪高分数以及其他用户数据。表中的每个项目都会以用户 ID 和用户所玩游戏名称唯一标识。GameScores
表具有一个由分区键 (UserId
) 和排序键 (GameTitle
) 组成的主键。用户只能访问与他们的用户 ID 关联的游戏数据。用户要想玩游戏,必须属于名为 GameRole
的 IAM 角色,该角色挂载了一项安全策略。
要管理此应用程序中的用户权限,您可以编写如下所示的权限策略:
{ "Version":"2012-10-17", "Statement":[ { "Sid":"AllowAccessToOnlyItemsMatchingUserID", "Effect":"Allow", "Action":[ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:LeadingKeys":[ "${www.amazon.com:user_id}" ], "dynamodb:Attributes":[ "UserId", "GameTitle", "Wins", "Losses", "TopScore", "TopScoreDateTime" ] }, "StringEqualsIfExists":{ "dynamodb:Select":"SPECIFIC_ATTRIBUTES" } } } ] }
除了授予权限以允许对 GameScores
表(Resource
元素)执行特定 DynamoDB 操作(Action
元素)外,Condition
元素还可使用以下特定于 DynamoDB 的条件键来限制相关权限:
-
dynamodb:LeadingKeys
- 此条件键只允许用户访问分区键值与其用户 ID 匹配的项目。此 ID(即${www.amazon.com:user_id}
)是替代变量。有关替代变量的更多信息,请参阅 使用 Web 身份联合验证。 -
dynamodb:Attributes
- 此条件键用于限制对特定属性的访问,这样,只有权限策略中列出的操作才能返回这些属性的值。此外,StringEqualsIfExists
子句可确保应用程序必须始终提供要执行操作的特定属性列表,并且应用程序无法请求所有属性。
评估 IAM 策略时,结果始终是 true(允许访问)或 false(拒绝访问)。如果 Condition
元素的任何部分为 false,则整个策略评估为 false,并且访问会被拒绝。
重要
如果您使用 dynamodb:Attributes
,则必须为策略中列出的表和所有二级索引指定所有主键和索引键属性名称。否则,DynamoDB 无法使用这些键属性执行所请求的操作。
IAM 策略文档只能包含以下 Unicode 字符:水平制表符(U+0009)、换行符(U+000A)、回车符(U+000D)以及 U+0020 到 U+00FF 范围内的字符。
指定条件:使用条件键
AWS 为支持通过 IAM 进行访问控制的所有 AWS 服务提供了一组预定义条件键(AWS 范围内的条件键)。例如,您可以先使用 aws:SourceIp
条件键检查请求者的 IP 地址,然后再允许执行操作。有关更多信息和 AWS 范围条件键的列表,请参阅 IAM 用户指南中的可用条件键。
下表显示了适用于 DynamoDB 的、DynamoDB 服务特定的条件键。
DynamoDB 条件键 | 描述 |
---|---|
dynamodb:LeadingKeys |
表示表的第一个键属性,即分区键。键名称 |
dynamodb:Select |
表示
|
dynamodb:Attributes |
表示请求中的属性名称列表或从请求返回的属性。
|
dynamodb:ReturnValues |
表示请求的
|
dynamodb:ReturnConsumedCapacity |
表示请求的
|
限制用户访问权限
很多 IAM 权限策略只允许用户访问分区键值与用户标识符匹配的表中的项目。例如,前面提到的游戏应用程序通过这种方式限制访问,使得用户只能访问与他们的用户 ID 关联的游戏数据。IAM 替换变量 ${www.amazon.com:user_id}
、${graph.facebook.com:id}
和 ${accounts.google.com:sub}
包含适用于 Login with Amazon、Facebook 和 Google 的用户标识符。要了解应用程序如何登录身份提供商并获取标识符,请参阅使用 Web 身份联合验证。
注意
以下部分中的每个示例均将 Effect
子句设置为 Allow
,并且仅指定允许的操作、资源和参数。只允许访问 IAM 策略中明确列出的项目。
在某些情况下,可以重新编写这些策略以使其成为基于拒绝的策略,即将 Effect
子句设置为 Deny
并转换策略中的所有逻辑。然而,我们建议您避免对 DynamoDB 使用基于拒绝的策略,这是因为与基于允许的策略相比,它们难以编写正确。此外,将来对 DynamoDB API 的更改(或对现有 API 的更改)可能会导致基于拒绝的策略失效。
策略示例:使用条件实现精细访问控制
此部分介绍了几项可对 DynamoDB 表和索引实现精细访问控制的策略。
注意
所有示例都使用 us-west-2 区域和虚构的账户 ID。
本视频介绍 DynamoDB 中使用 IAM 策略条件进行的精细访问控制。
1:授予权限以限制访问具有特定分区键值的项目
以下权限策略用于授予允许对 GamesScore
表执行一组 DynamoDB 操作的权限。它使用的是 dynamodb:LeadingKeys
条件键,仅限制对分区键值与此应用程序的 Login with Amazon 唯一用户 ID 匹配的项目 UserID
执行用户操作。
重要
列出的操作不包括对 Scan
的权限,这是因为无论主键是什么,Scan
都会返回所有项目。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"FullAccessToUserItems", "Effect":"Allow", "Action":[ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:LeadingKeys":[ "${www.amazon.com:user_id}" ] } } } ] }
注意
当使用策略变量时,您必须在策略中明确指定版本 2012-10-17
。访问策略语言的默认版本 2008-10-17
不支持策略变量。
要实现只读访问,您可以取消能修改数据的所有操作。在以下策略中,只有提供只读访问权限的操作才会包含在条件中。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"ReadOnlyAccessToUserItems", "Effect":"Allow", "Action":[ "dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:LeadingKeys":[ "${www.amazon.com:user_id}" ] } } } ] }
重要
如果您使用 dynamodb:Attributes
,则必须为策略中列出的表和所有二级索引指定所有主键和索引键属性名称。否则,DynamoDB 无法使用这些键属性执行所请求的操作。
2:授予权限以限制访问表中的特定属性
以下权限策略通过添加 dynamodb:Attributes
条件键,只允许访问两个特定属性。这些属性可以在条件写入或扫描筛选条件中进行读取、写入或评估。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"LimitAccessToSpecificAttributes", "Effect":"Allow", "Action":[ "dynamodb:UpdateItem", "dynamodb:GetItem", "dynamodb:Query", "dynamodb:BatchGetItem", "dynamodb:Scan" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:Attributes":[ "UserId", "TopScore" ] }, "StringEqualsIfExists":{ "dynamodb:Select":"SPECIFIC_ATTRIBUTES", "dynamodb:ReturnValues":[ "NONE", "UPDATED_OLD", "UPDATED_NEW" ] } } } ] }
注意
该策略采用了允许列表方法,允许访问指定的属性集。您也可以编写禁止访问其他属性的等效策略。我们不建议采用此拒绝列表方法。用户可以遵循 Wikipedia 中描述的最小权限原则(网址为 http://en.wikipedia.org/wiki/Principle_of_least_privilege
此策略不允许 PutItem
、DeleteItem
或 BatchWriteItem
。这些操作总是会替换整个旧项目,这样用户就可以删除他们不能访问的属性的原有值。
权限策略中的 StringEqualsIfExists
子句可确保满足以下要求:
-
如果用户指定了
Select
参数,则其值必须为SPECIFIC_ATTRIBUTES
。这项要求会防止 API 操作返回未授权的属性,例如来自索引投影的属性。 -
如果用户指定了
ReturnValues
参数,则其值必须为NONE
、UPDATED_OLD
或UPDATED_NEW
。之所以这样要求是因为UpdateItem
操作还会执行隐式读取操作在替换之前验证项目是否存在,并会根据需要返回之前的属性值。这种ReturnValues
限制方法可以确保用户只能读取或写入允许的属性。 -
StringEqualsIfExists
子句可以确保在允许的操作上下文中每个请求只能使用Select
或ReturnValues
参数中的一个。
以下是该策略的一些变化:
-
要只允许读取操作,您可以从允许的操作列表中将
UpdateItem
删除。由于剩余的操作都不接受ReturnValues
,您可以将ReturnValues
从条件中删除。您也可以将StringEqualsIfExists
更改为StringEquals
,这是因为Select
参数始终有一个值(除非另行指定,否则为ALL_ATTRIBUTES
)。 -
要只允许写入操作,您可以将
UpdateItem
以外的所有元素从允许的操作列表中删除。由于UpdateItem
不使用Select
参数,您可以将Select
从条件中删除。您还必须将StringEqualsIfExists
更改为StringEquals
,这是因为ReturnValues
参数始终有一个值(除非另行指定,否则为NONE
)。 -
要允许名称与某种模式匹配的所有属性,请使用
StringLike
而不是StringEquals
,并使用多字符模式匹配通配符 (*)。
3:授予权限以阻止更新特定属性
以下权限策略用于限制用户访问以仅更新由 dynamodb:Attributes
条件键标识的特定属性。StringNotLike
条件使用 dynamodb:Attributes
条件键来阻止应用程序更新特定属性。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"PreventUpdatesOnCertainAttributes", "Effect":"Allow", "Action":[ "dynamodb:UpdateItem" ], "Resource":"arn:aws:dynamodb:us-west-2:123456789012:table/GameScores", "Condition":{ "ForAllValues:StringNotLike":{ "dynamodb:Attributes":[ "FreeGamesAvailable", "BossLevelUnlocked" ] }, "StringEquals":{ "dynamodb:ReturnValues":[ "NONE", "UPDATED_OLD", "UPDATED_NEW" ] } } } ] }
请注意以下几点:
-
与其他写入操作一样,
UpdateItem
操作也需要对项目拥有读取权限才能在更新前后返回值。在该策略中,您可以通过指定dynamodb:ReturnValues
条件键,将操作限制为只能访问允许更新的属性。条件键在请求中限制了ReturnValues
以便仅指定NONE
、UPDATED_OLD
或UPDATED_NEW
,且不包括ALL_OLD
或ALL_NEW
。 -
PutItem
和DeleteItem
操作会替换整个项目,从而允许应用程序修改任何属性。因此,在限制应用程序只能更新特定属性时,您不应向这些 API 授予权限。
4:授予权限以仅查询索引中的投影属性
以下权限策略通过使用 dynamodb:Attributes
条件键,允许对二级索引 (TopScoreDateTimeIndex
) 执行查询。该策略还会将查询限制为只能请求已投影到索引中的特定属性。
要让应用程序在查询中指定属性列表,该策略还需要指定 dynamodb:Select
条件键以要求 DynamoDB Query
操作的 Select
参数为 SPECIFIC_ATTRIBUTES
。属性列表仅限为使用 dynamodb:Attributes
条件键提供的特定列表。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"QueryOnlyProjectedIndexAttributes", "Effect":"Allow", "Action":[ "dynamodb:Query" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/index/TopScoreDateTimeIndex" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:Attributes":[ "TopScoreDateTime", "GameTitle", "Wins", "Losses", "Attempts" ] }, "StringEquals":{ "dynamodb:Select":"SPECIFIC_ATTRIBUTES" } } } ] }
以下是类似的权限策略,但是查询请求的所有属性必须已投影到索引中。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"QueryAllIndexAttributes", "Effect":"Allow", "Action":[ "dynamodb:Query" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/index/TopScoreDateTimeIndex" ], "Condition":{ "StringEquals":{ "dynamodb:Select":"ALL_PROJECTED_ATTRIBUTES" } } } ] }
5:授予权限以限制访问特定属性和分区键值
以下权限策略允许对表和表索引(已在 Resource
元素中指定)执行特定 DynamoDB 操作(已在 Action
元素中指定)。该策略使用 dynamodb:LeadingKeys
条件键来限制权限,以仅访问分区键值与用户的 Facebook ID 匹配的项目。
{ "Version":"2012-10-17", "Statement":[ { "Sid":"LimitAccessToCertainAttributesAndKeyValues", "Effect":"Allow", "Action":[ "dynamodb:UpdateItem", "dynamodb:GetItem", "dynamodb:Query", "dynamodb:BatchGetItem" ], "Resource":[ "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores", "arn:aws:dynamodb:us-west-2:123456789012:table/GameScores/index/TopScoreDateTimeIndex" ], "Condition":{ "ForAllValues:StringEquals":{ "dynamodb:LeadingKeys":[ "${graph.facebook.com:id}" ], "dynamodb:Attributes":[ "attribute-A", "attribute-B" ] }, "StringEqualsIfExists":{ "dynamodb:Select":"SPECIFIC_ATTRIBUTES", "dynamodb:ReturnValues":[ "NONE", "UPDATED_OLD", "UPDATED_NEW" ] } } } ] }
请注意以下几点:
-
编写策略 (
UpdateItem
) 允许的操作只能修改attribute-A
或attribute-B
。 -
由于该策略允许
UpdateItem
,应用程序可以插入新项目,而隐藏属性在新项目中将为空。如果将这些属性投影到TopScoreDateTimeIndex
中,该策略还能够防止导致从表中获取数据的查询。 -
应用程序只能读取
dynamodb:Attributes
中列出的属性。实施此策略后,应用程序必须在读取请求中将Select
参数设置为SPECIFIC_ATTRIBUTES
,并且只能请求允许列表中的属性。对于写入请求,应用程序不能将ReturnValues
设置为ALL_OLD
或ALL_NEW
,也不能基于任何其他属性执行条件写入操作。