

# 将基于属性的访问权限控制与 DynamoDB 结合使用
<a name="attribute-based-access-control"></a>

[基于属性的访问权限控制（ABAC）](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)是一种授权策略，它根据基于身份的策略或其它 AWS 策略（例如基于资源的策略和组织 IAM 策略）中的[标签条件](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.html)来定义访问权限。可以将标签附加到 DynamoDB 表，然后根据基于标签的条件来对这些表进行评估。与表关联的索引会继承您添加到表的标签。最多可以为每个 DynamoDB 表添加 50 个标签。表中所有标签支持的最大大小为 10 KB。有关为 DynamoDB 资源添加标签和为限制添加标签的更多信息，请参阅[在 DynamoDB 中为资源添加标签](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Tagging.Operations.html)和 [DynamoDB 中的标签限制](Tagging.md#TaggingRestrictions)。

有关使用标签控制对 AWS 资源的访问权限的更多信息，请参阅《IAM 用户指南》中的以下主题：
+ [什么是适用于 AWS 的 ABAC](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)
+ [使用标签控制对 AWS 资源的访问](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_tags.html)

使用 ABAC，可以为团队和应用程序强制使用不同的访问级别，以便使用更少的策略对 DynamoDB 表执行操作。可以在 IAM 策略的[条件元素](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html)中指定一个标签，来控制对 DynamoDB 表或索引的访问权限。这些条件决定了 IAM 主体、用户或角色对 DynamoDB 表和索引拥有的访问级别。当 IAM 主体向 DynamoDB 提出访问请求时，将根据 IAM 策略中的标签条件评估资源和身份的标签。此后，只有在满足标签条件时，该策略才会生效。这使您能够创建可有效说明以下内容之一的 IAM 策略：
+ *支持用户仅管理那些具有标签（键为 `X` 和值为 `Y`）的资源*。
+ *拒绝所有用户访问用键 `X` 标记的资源*。

例如，可以创建一个策略，仅在表具有以下标签键值对时才支持用户更新该表：`"environment": "staging"`。可以使用 [aws:ResourceTag](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourcetag) 条件键，基于附加到表的标签来支持或拒绝访问该表。

可以在创建策略时包括基于属性的条件，也可以稍后使用 AWS 管理控制台、AWS API、AWS Command Line Interface（AWS CLI）、AWS SDK 或 AWS CloudFormation 来包括这些条件。

以下示例支持对名为 `MusicTable` 的表执行 [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html) 操作，前提是该表包含名称为 `environment` 和值为 `production` 的标签键。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateItem"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/MusicTable",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/environment": "production"
        }
      }
    }
  ]
}
```

------

**Topics**
+ [为什么应该使用 ABAC？](#why-use-abac)
+ [使用 DynamoDB 实施 ABAC 的条件键](#condition-keys-implement-abac)
+ [将 ABAC 与 DynamoDB 结合使用的注意事项](#abac-considerations)
+ [在 DynamoDB 中启用 ABAC](abac-enable-ddb.md)
+ [将 ABAC 与 DynamoDB 表和索引结合使用](abac-implementation-ddb-tables.md)
+ [将 ABAC 与 DynamoDB 表和索引结合使用的示例](abac-example-use-cases.md)
+ [排除 DynamoDB 表和索引的常见 ABAC 错误](abac-troubleshooting.md)

## 为什么应该使用 ABAC？
<a name="why-use-abac"></a>
+ **更简单的策略管理：**您使用的策略将更少，因为您不必创建不同的策略来定义每个 IAM 主体的访问级别。
+ **可扩展的访问权限控制：**使用 ABAC 可以更轻松地扩展访问权限控制，因为您不必在创建新的 DynamoDB 资源时更新策略。可以使用标签来向包含的标签与资源标签匹配的 IAM 主体授予访问权限。您可以加入新的 IAM 主体或 DynamoDB 资源，并应用适当的标签来自动授予必要的权限，而不必进行任何策略更改。
+ **精细的权限管理：**最佳实践是在创建策略时[授予最低权限](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)。使用 ABAC，您可以为 IAM 主体创建标签，并使用它们来授予对与 IAM 主体上的标签匹配的特定操作和资源的访问权限。
+ **与公司目录保持一致：**可以将标签与公司目录中的现有员工属性进行映射，以使访问权限控制策略与组织结构保持一致。

## 使用 DynamoDB 实施 ABAC 的条件键
<a name="condition-keys-implement-abac"></a>

可以在 AWS 策略中使用以下条件键来控制对 DynamoDB 表和索引的访问级别：
+ [aws:ResourceTag/tag-key](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourcetag)：根据 DynamoDB 表或索引上的标签键值对是否与策略中的标签键和值匹配来控制访问权限。此条件键与对现有表或索引进行操作的所有 API 相关。

  对这些 `dynamodb:ResourceTag` 条件的评估就像您没有为资源附加任何标签一样。
+ [aws:RequestTag/tag-key](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requesttag)：支持将在请求中传递的标签键值对与您在策略中指定的标签对进行比较。此条件键与包含标签作为请求有效载荷一部分的 API 相关。这些 API 包括 [CreateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html) 和 [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html)。
+ [aws:TagKeys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-tagkeys)：将请求中的标签键与您在策略中指定的键进行比较。此条件键与包含标签作为请求有效载荷一部分的 API 相关。这些标签包括 `CreateTable`、`TagResource` 和 `UntagResource`。

## 将 ABAC 与 DynamoDB 结合使用的注意事项
<a name="abac-considerations"></a>

在将 ABAC 与 DynamoDB 表或索引结合使用时，以下注意事项适用：
+ DynamoDB Streams 不支持添加标签和 ABAC。
+ DynamoDB 备份不支持添加标签和 ABAC。要将 ABAC 用于备份，建议您使用 [AWS Backup](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html)。
+ 标签不会保留在还原的表中。您需要先向还原的表添加标签，然后才能在策略中使用基于标签的条件。

# 在 DynamoDB 中启用 ABAC
<a name="abac-enable-ddb"></a>

对于大多数 AWS 账户，ABAC 在默认情况下处于启用状态。使用 [DynamoDB 控制台](https://console.aws.amazon.com/dynamodb/)，可以确认是否为您的账户启用了 ABAC。为此，请确保使用具有 [dynamodb:GetAbacStatus](#required-permissions-abac) 权限的角色打开 DynamoDB 控制台。然后，打开 DynamoDB 控制台的**设置**页面。

如果您未看到**基于属性的访问权限控制**卡片，或者该卡片的状态显示为**打开**，则表示为您的账户启用了 ABAC。但是，如果您看到**基于属性的访问权限控制**卡片的状态为**关闭**（如下图所示），则表示未为您的账户启用 ABAC。

## 基于属性的访问权限控制 - 未启用
<a name="abac-disabled-image"></a>

![\[DynamoDB 控制台上显示基于属性的访问权限控制卡片的设置页面。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/ddb-console-settings-page.png)


对于那些在基于身份的策略或其它策略中指定的基于标签的条件仍需要审计的 AWS 账户，尚未启用 ABAC。如果未为您的账户启用 ABAC，则会评估策略中用于对 DynamoDB 表或索引执行操作的基于标签的条件，就好像您的资源或 API 请求不存在任何标签一样。为您的账户启用 ABAC 后，将根据附加到您的表或 API 请求的标签，来评估您账户的策略中基于标签的条件。

要为您的账户启用 ABAC，我们建议您首先按照[策略审计](#policy-audit-for-abac)一节中所述来审计您的策略。然后，在您的 IAM 策略中包含 [ABAC 所需的权限](#required-permissions-abac)。最后，执行[在控制台中启用 ABAC](#abac-enable-console) 中介绍的步骤，以便在当前区域中为您的账户启用 ABAC。启用 ABAC 后，可以在选择加入后接下来的七个日历日内选择退出。

**Topics**
+ [在启用 ABAC 之前审计策略](#policy-audit-for-abac)
+ [启用 ABAC 所需的 IAM 权限](#required-permissions-abac)
+ [在控制台中启用 ABAC](#abac-enable-console)

## 在启用 ABAC 之前审计策略
<a name="policy-audit-for-abac"></a>

在为您的账户启用 ABAC 之前，请审计您的策略，以确认您账户的策略中可能存在的基于标签的条件已按预期设置。在启用 ABAC 后，审计您的策略将有助于避免因 DynamoDB 工作流程的授权变更而出现意外。要查看将基于属性的条件与标签结合使用的示例，以及实施 ABAC 之前和之后的行为，请参阅[将 ABAC 与 DynamoDB 表和索引结合使用的示例使用案例示例](abac-example-use-cases.md)。

## 启用 ABAC 所需的 IAM 权限
<a name="required-permissions-abac"></a>

您需要 `dynamodb:UpdateAbacStatus` 权限才能在当前区域中为您的账户启用 ABAC。要确认是否为您的账户启用了 ABAC，您还必须拥有 `dynamodb:GetAbacStatus` 权限。有了此权限，您就可以查看任何区域中账户的 ABAC 状态。除了访问 DynamoDB 控制台所需的权限外，您还需要这些权限。

以下 IAM 策略授予在当前区域中为账户启用 ABAC 和查看其状态的权限。

```
{
"version": "2012-10-17", 		 	 	 &TCX5-2025-waiver;
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:UpdateAbacStatus",
                "dynamodb:GetAbacStatus"
             ],
            "Resource": "*"
        }
    ]
}
```

## 在控制台中启用 ABAC
<a name="abac-enable-console"></a>

1. 登录 AWS 管理控制台，并打开 DynamoDB 控制台：[https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)。

1. 从顶部导航窗格中，选择要为其启用 ABAC 的区域。

1. 在左侧导航窗格中，选择**设置**。

1. 在**设置**页面上，执行以下操作：

   1. 在**基于属性的访问权限控制**卡片中，选择**启用**。

   1. 在**确认基于属性的访问权限控制设置**框中，选择**启用**以确认您的选择。

      这将为当前区域启用 ABAC，并且**基于属性的访问权限控制**卡片将显示状态**打开**。

      如果您想在控制台上启用 ABAC 后选择退出，可以在选择加入后的七个日历日内选择退出。要选择退出，请在**设置**页面上的**基于属性的访问权限控制**卡片中选择**禁用**。
**注意**  
更新 ABAC 的状态是一项异步操作。如果未立即评估策略中的标签，则可能需要等待一些时间，因为应用更改是最终一致的。

# 将 ABAC 与 DynamoDB 表和索引结合使用
<a name="abac-implementation-ddb-tables"></a>

以下步骤显示如何使用 ABAC 设置权限。在此示例场景中，您将向 DynamoDB 表添加标签，并使用包含基于标签的条件的策略创建一个 IAM 角色。然后，您将通过匹配标签条件来测试 DynamoDB 表支持的权限。

**Topics**
+ [步骤 1：向 DynamoDB 表添加标签](#abac-add-table-tags)
+ [步骤 2：使用包含基于标签的条件的策略创建 IAM 角色](#abac-create-iam-role)
+ [步骤 3：测试支持的权限](#abac-test-permissions)

## 步骤 1：向 DynamoDB 表添加标签
<a name="abac-add-table-tags"></a>

可以使用 AWS 管理控制台、AWS API、AWS Command Line Interface（AWS CLI）或 AWS SDK 或 AWS CloudFormation 向新的或现有的 DynamoDB 表添加标签。例如，以下 [tag-resource](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/tag-resource.html) CLI 命令向名为 `MusicTable` 的表添加一个标签。

```
aws dynamodb tag-resource —resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/MusicTable —tags Key=environment,Value=staging
```

## 步骤 2：使用包含基于标签的条件的策略创建 IAM 角色
<a name="abac-create-iam-role"></a>

使用 [aws:ResourceTag/tag-key](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourcetag) 条件键[创建 IAM 策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html#access_policies_create-json-editor)，以便将在 IAM 策略中指定的标签键值对与附加到表中的键值对进行比较。如果表中包含标签键值对 `"environment": "staging"`，则以下示例策略支持用户在这些表中放置或更新项目。如果表没有指定的标签键值对，则这些操作将被拒绝。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/environment": "staging"
                }
            }
        }
    ]
}
```

------

## 步骤 3：测试支持的权限
<a name="abac-test-permissions"></a>

1. 将 IAM 策略附加到 AWS 账户中的 IAM 用户或角色。确保您使用的 IAM 主体尚不具有通过其它策略访问 DynamoDB 表的权限。

1. 确保 DynamoDB 表包含值为 `"staging"` 的 `"environment"` 标签键。

1. 对带标签的表执行 `dynamodb:PutItem` 和 `dynamodb:UpdateItem` 操作。如果 `"environment": "staging"` 标签键值对存在，则这些操作应该会成功。

   如果您对没有 `"environment": "staging"` 标签键值对的表执行这些操作，则您的请求将失败，并引发 `AccessDeniedException`。

还可以查看下一节中介绍的其它[示例用例](abac-example-use-cases.md)，以实施 ABAC 并执行更多测试。

# 将 ABAC 与 DynamoDB 表和索引结合使用的示例
<a name="abac-example-use-cases"></a>

以下示例描述了一些使用标签来实现基于属性的条件的用例。

**Topics**
+ [示例 1：使用 aws:ResourceTag 支持操作](#abac-allow-example-resource-tag)
+ [示例 2：使用 aws:RequestTag 支持操作](#abac-allow-example-request-tag)
+ [示例 3：使用 aws:TagKeys 拒绝操作](#abac-deny-example-tag-key)

## 示例 1：使用 aws:ResourceTag 支持操作
<a name="abac-allow-example-resource-tag"></a>

使用 `aws:ResourceTag/tag-key` 条件键，可以将在 IAM 策略中指定的标签键值对与 DynamoDB 表中附加的键值对进行比较。例如，如果 IAM 策略和表中的标签条件匹配，则可以支持执行特定操作，例如 [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。为此，请执行以下步骤：

------
#### [ Using the AWS CLI ]

1. 创建表。以下示例使用 [create-table](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/create-table.html) AWS CLI 命令来创建名为 `myMusicTable` 的表。

   ```
   aws dynamodb create-table \
     --table-name myMusicTable \
     --attribute-definitions AttributeName=id,AttributeType=S \
     --key-schema AttributeName=id,KeyType=HASH \
     --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
     --region us-east-1
   ```

1. 向此表添加标签。以下 [tag-resource](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/tag-resource.html) AWS CLI 命令示例将标签键值对 `Title: ProductManager` 添加到 `myMusicTable`。

   ```
   aws dynamodb tag-resource --region us-east-1 --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable --tags Key=Title,Value=ProductManager
   ```

1. 创建[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)并将其添加到附加了 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 托管式策略的角色，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "dynamodb:PutItem",
         "Resource": "arn:aws:dynamodb:*:*:table/*",
         "Condition": {
           "StringEquals": {
             "aws:ResourceTag/Title": "ProductManager"
           }
         }
       }
     ]
   }
   ```

------

   当附加到表的标签键和值与在策略中指定的标签匹配时，此策略支持对表执行 `PutItem` 操作。

1. 使用在步骤 3 中描述的策略代入该角色。

1. 使用 [put-item](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/put-item.html) AWS CLI 命令将项目放置到 `myMusicTable`。

   ```
   aws dynamodb put-item \
       --table-name myMusicTable --region us-east-1 \
       --item '{
           "id": {"S": "2023"},
           "title": {"S": "Happy Day"},
           "info": {"M": {
               "rating": {"N": "9"},
               "Artists": {"L": [{"S": "Acme Band"}, {"S": "No One You Know"}]},
               "release_date": {"S": "2023-07-21"}
           }}
       }'
   ```

1. 扫描该表，以验证该项目是否已添加到表。

   ```
   aws dynamodb scan --table-name myMusicTable  --region us-east-1
   ```

------
#### [ Using the AWS SDK for Java 2.x ]

1. 创建表。以下示例使用 [CreateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html) API 来创建名为 `myMusicTable` 的表。

   ```
   DynamoDbClient dynamoDB = DynamoDbClient.builder().region(region).build();
   CreateTableRequest createTableRequest = CreateTableRequest.builder()
       .attributeDefinitions(
           Arrays.asList(
               AttributeDefinition.builder()
               .attributeName("id")
               .attributeType(ScalarAttributeType.S)
               .build()
           )
       )
       .keySchema(
           Arrays.asList(
               KeySchemaElement.builder()
               .attributeName("id")
               .keyType(KeyType.HASH)
               .build()
           )
       )
       .provisionedThroughput(ProvisionedThroughput.builder()
           .readCapacityUnits(5L)
           .writeCapacityUnits(5L)
           .build()
       )
       .tableName("myMusicTable")
       .build();
   
   CreateTableResponse createTableResponse = dynamoDB.createTable(createTableRequest);
   String tableArn = createTableResponse.tableDescription().tableArn();
   String tableName = createTableResponse.tableDescription().tableName();
   ```

1. 向此表添加标签。以下示例中的 [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html) API 将标签键值对 `Title: ProductManager` 添加到 `myMusicTable`。

   ```
   TagResourceRequest tagResourceRequest = TagResourceRequest.builder()
       .resourceArn(tableArn)
       .tags(
           Arrays.asList(
               Tag.builder()
               .key("Title")
               .value("ProductManager")
               .build()
           )
       )
       .build();
   dynamoDB.tagResource(tagResourceRequest);
   ```

1. 创建[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)并将其添加到附加了 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 托管式策略的角色，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "dynamodb:PutItem",
         "Resource": "arn:aws:dynamodb:*:*:table/*",
         "Condition": {
           "StringEquals": {
             "aws:ResourceTag/Title": "ProductManager"
           }
         }
       }
     ]
   }
   ```

------

   当附加到表的标签键和值与在策略中指定的标签匹配时，此策略支持对表执行 `PutItem` 操作。

1. 使用在步骤 3 中描述的策略代入该角色。

1. 使用 [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) API 将项目放置到 `myMusicTable`。

   ```
   HashMap<String, AttributeValue> info = new HashMap<>();
   info.put("rating", AttributeValue.builder().s("9").build());
   info.put("artists", AttributeValue.builder().ss(List.of("Acme Band","No One You Know").build());
   info.put("release_date", AttributeValue.builder().s("2023-07-21").build());
   
   HashMap<String, AttributeValue> itemValues = new HashMap<>();
   itemValues.put("id", AttributeValue.builder().s("2023").build());
   itemValues.put("title", AttributeValue.builder().s("Happy Day").build());
   itemValues.put("info", AttributeValue.builder().m(info).build());
   
   
   PutItemRequest putItemRequest = PutItemRequest.builder()
                   .tableName(tableName)
                   .item(itemValues)
                   .build();
   dynamoDB.putItem(putItemRequest);
   ```

1. 扫描该表，以验证该项目是否已添加到表。

   ```
   ScanRequest scanRequest = ScanRequest.builder()
                   .tableName(tableName)
                   .build();
                   
   ScanResponse scanResponse = dynamoDB.scan(scanRequest);
   ```

------
#### [ Using the 适用于 Python (Boto3) 的 AWS SDK ]

1. 创建表。以下示例使用 [CreateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html) API 来创建名为 `myMusicTable` 的表。

   ```
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 5,
           'WriteCapacityUnits': 5
       },
   )
   
   table_arn = create_table_response['TableDescription']['TableArn']
   ```

1. 向此表添加标签。以下示例中的 [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html) API 将标签键值对 `Title: ProductManager` 添加到 `myMusicTable`。

   ```
   tag_resouce_response = ddb_client.tag_resource(
       ResourceArn=table_arn,
       Tags=[
           {
               'Key': 'Title',
               'Value': 'ProductManager'
           },
       ]
   )
   ```

1. 创建[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)并将其添加到附加了 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 托管式策略的角色，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
           "Effect": "Allow",
           "Action": "dynamodb:PutItem",
           "Resource": "arn:aws:dynamodb:*:*:table/*",
           "Condition": {
               "StringEquals": {
               "aws:ResourceTag/Title": "ProductManager"
               }
           }
           }
       ]
       }
   ```

------

   当附加到表的标签键和值与在策略中指定的标签匹配时，此策略支持对表执行 `PutItem` 操作。

1. 使用在步骤 3 中描述的策略代入该角色。

1. 使用 [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) API 将项目放置到 `myMusicTable`。

   ```
   put_item_response = client.put_item(
       TableName = 'myMusicTable'
       Item = {
           'id': '2023',
           'title': 'Happy Day',
           'info': {
               'rating': '9',
               'artists': ['Acme Band','No One You Know'],
               'release_date': '2023-07-21'
           }
       }
   )
   ```

1. 扫描该表，以验证该项目是否已添加到表。

   ```
   scan_response = client.scan(
       TableName='myMusicTable'
   )
   ```

------

**不带 ABAC**  
如果您未为 AWS 账户启用 ABAC，则 IAM 策略和 DynamoDB 表中的标签条件将不匹配。因此，由于 `AmazonDynamoDBReadOnlyAccess` 策略的效果，`PutItem` 操作将返回 `AccessDeniedException`。

```
An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::123456789012:assumed-role/DynamoDBReadOnlyAccess/Alice is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable because no identity-based policy allows the dynamodb:PutItem action.
```

**带有 ABAC**  
如果您为 AWS 账户启用了 ABAC，则 `put-item` 操作将成功完成，并向表中添加一个新项目。这是因为，如果 IAM 策略和表中的标签条件匹配，则表中的内联策略支持 `PutItem` 操作。

## 示例 2：使用 aws:RequestTag 支持操作
<a name="abac-allow-example-request-tag"></a>

使用 [aws:RequestTag/tag-key](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requesttag) 条件键，可以将在请求中传递的标签键值对与在 IAM 策略中指定的标签对进行比较。例如，您可以支持特定操作，例如 `CreateTable`，如果标签条件不匹配，则使用 `aws:RequestTag`。为此，请执行以下步骤：

------
#### [ Using the AWS CLI ]

1. 创建[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)并将其添加到附加了 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html) AWS 托管式策略的角色，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "StringEquals": {
                       "aws:RequestTag/Owner": "John"
                   }
               }
           }
       ]
   }
   ```

------

1. 创建包含标签键值对 `"Owner": "John"` 的表。

   ```
   aws dynamodb create-table \
   --attribute-definitions AttributeName=ID,AttributeType=S \
   --key-schema AttributeName=ID,KeyType=HASH  \
   --provisioned-throughput ReadCapacityUnits=1000,WriteCapacityUnits=500 \
   --region us-east-1 \
   --tags Key=Owner,Value=John \
   --table-name myMusicTable
   ```

------
#### [ Using the 适用于 Python (Boto3) 的 AWS SDK ]

1. 创建[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)并将其添加到附加了 [AmazonDynamoDBReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBReadOnlyAccess.html) AWS 托管式策略的角色，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "StringEquals": {
                       "aws:RequestTag/Owner": "John"
                   }
               }
           }
       ]
   }
   ```

------

1. 创建包含标签键值对 `"Owner": "John"` 的表。

   ```
   ddb_client = boto3.client('dynamodb')
   
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 1000,
           'WriteCapacityUnits': 500
       },
       Tags=[
           {
               'Key': 'Owner',
               'Value': 'John'
           },
       ],
   )
   ```

------

**不带 ABAC**  
如果您未为 AWS 账户启用 ABAC，则内联策略和 DynamoDB 表中的标签条件将不匹配。因此，`CreateTable` 请求将失败，而不会创建您的表。

```
An error occurred (AccessDeniedException) when calling the CreateTable operation: User: arn:aws:sts::123456789012:assumed-role/Admin/John is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable because no identity-based policy allows the dynamodb:CreateTable action.
```

**带有 ABAC**  
如果您为 AWS 账户启用了 ABAC，则表创建请求将成功完成。由于 `CreateTable` 请求中存在标签键值对 `"Owner": "John"`，因此内联策略支持用户 `John` 执行 `CreateTable` 操作。

## 示例 3：使用 aws:TagKeys 拒绝操作
<a name="abac-deny-example-tag-key"></a>

使用 [aws:TagKeys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-tagkeys) 条件键，可以将请求中的标签键与在 IAM 策略中指定的键进行比较。例如，您可以拒绝特定的操作，例如 `CreateTable`，如果请求中*不* 存在特定的标签键，则使用 `aws:TagKeys`。为此，请执行以下步骤：

------
#### [ Using the AWS CLI ]

1. 将[客户管理型策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)添加到附加了 [AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) AWS 托管式策略的角色中，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Deny",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "Null": {
                       "aws:TagKeys": "false"
                   },
                   "ForAllValues:StringNotEquals": {
                       "aws:TagKeys": "CostCenter"
                   }
               }
           }
       ]
   }
   ```

------

1. 代入策略所附加到的角色，然后使用标签键 `Title` 创建表。

   ```
   aws dynamodb create-table \
   --attribute-definitions AttributeName=ID,AttributeType=S \
   --key-schema AttributeName=ID,KeyType=HASH  \
   --provisioned-throughput ReadCapacityUnits=1000,WriteCapacityUnits=500 \
   --region us-east-1 \
   --tags Key=Title,Value=ProductManager \
   --table-name myMusicTable
   ```

------
#### [ Using the 适用于 Python (Boto3) 的 AWS SDK ]

1. 将[客户管理型策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)添加到附加了 [AmazonDynamoDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonDynamoDBFullAccess.html) AWS 托管式策略的角色中，如以下示例所示。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Deny",
               "Action": [
                   "dynamodb:CreateTable",
                   "dynamodb:TagResource"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/*",
               "Condition": {
                   "Null": {
                       "aws:TagKeys": "false"
                   },
                   "ForAllValues:StringNotEquals": {
                       "aws:TagKeys": "CostCenter"
                   }
               }
           }
       ]
   }
   ```

------

1. 代入策略所附加到的角色，然后使用标签键 `Title` 创建表。

   ```
   ddb_client = boto3.client('dynamodb')
   
   create_table_response = ddb_client.create_table(
       AttributeDefinitions=[
           {
               'AttributeName': 'id',
               'AttributeType': 'S'
           },
       ],
       TableName='myMusicTable',
       KeySchema=[
           {
               'AttributeName': 'id',
               'KeyType': 'HASH'
           },
       ],
           ProvisionedThroughput={
           'ReadCapacityUnits': 1000,
           'WriteCapacityUnits': 500
       },
       Tags=[
           {
               'Key': 'Title',
               'Value': 'ProductManager'
           },
       ],
   )
   ```

------

**不带 ABAC**  
如果您未为 AWS 账户启用 ABAC，则 DynamoDB 不会在 `create-table` 命令中将标签键发送到 IAM。`Null` 条件可确保在请求中没有标签键时，条件的计算结果为 `false`。由于 `Deny` 策略不匹配，因此 `create-table` 命令成功完成。

**带有 ABAC**  
如果您为 AWS 账户启用了 ABAC，则在 `create-table` 命令中传递的标签键将传递给 IAM。标签键 `Title` 是根据 `Deny` 策略中存在的基于条件的标签键 `CostCenter` 进行评估的。由于 `StringNotEquals` 运算符的原因，标签键 `Title` 与 `Deny` 策略中存在的标签键不匹配。因此，`CreateTable` 操作将失败，而不会创建表。运行 `create-table` 命令会返回 `AccessDeniedException`。

```
An error occurred (AccessDeniedException) when calling the CreateTable operation: User: arn:aws:sts::123456789012:assumed-role/DynamoFullAccessRole/ProductManager is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:us-east-1:123456789012:table/myMusicTable with an explicit deny in an identity-based policy.
```

# 排除 DynamoDB 表和索引的常见 ABAC 错误
<a name="abac-troubleshooting"></a>

本主题为您在 DynamoDB 表或索引中实施 ABAC 时可能遇到的常见错误和问题提供故障排除建议。

## 策略中服务特定的条件键导致错误
<a name="abac-troubleshooting-service-specific-keys"></a>

服务特定的条件键不被视为有效的条件键。如果您在策略中使用了此类键，则会导致错误。要修复此问题，必须将服务特定的条件键替换为适当的用于在 DynamoDB 中[实施 ABAC 的条件键](attribute-based-access-control.md#condition-keys-implement-abac)。

例如，假设您在执行 [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html) 请求的[内联策略](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#inline-policies)中使用了 `dynamodb:ResourceTag` 条件键。想象一下，请求失败并引发 `AccessDeniedException`。以下示例显示了带有 `dynamodb:ResourceTag` 条件键的错误内联策略。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/*",
            "Condition": {
                "StringEquals": {
                    "dynamodb:ResourceTag/Owner": "John"
                }
            }
        }
    ]
}
```

------

要修复此问题，请将 `dynamodb:ResourceTag` 条件键替换为 `aws:ResourceTag`，如以下示例所示。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Owner": "John"
                }
            }
        }
    ]
}
```

------

## 无法选择退出 ABAC
<a name="abac-troubleshooting-unable-opt-out"></a>

如果通过 支持 为账户启用了 ABAC，将无法通过 DynamoDB 控制台选择退出 ABAC。要选择退出，请联系 [支持](https://console.aws.amazon.com/support)。

*仅当* 满足以下条件时，才能自行选择退出 ABAC：
+ 您使用的是[通过 DynamoDB 控制台选择加入](abac-enable-ddb.md#abac-enable-console)的自助服务方式。
+ 您将在选择加入后的七个日历日内选择退出。