AWS Key Management Service
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

Amazon DynamoDB 如何使用 AWS KMS

Amazon DynamoDB 是一种完全托管的可扩展式 NoSQL 数据库服务。DynamoDB 与 AWS Key Management Service (AWS KMS) 集成以支持静态加密服务器端加密功能。

利用静态加密,DynamoDB 可以透明方式对 DynamoDB 表中的所有客户数据进行加密,包括其主键及本地和全局二级索引,只要该表已保存到磁盘。(如果表具有排序键,则标记范围边界的一些排序键将以明文形式存储在表元数据中。) 当您访问表时,DynamoDB 会以透明方式解密表数据。您无需更改应用程序即可使用或管理加密表。

此外,在将 DynamoDB 流全局表备份保存到持久性媒体时,静态加密可以保护这些对象。有关本主题中表的语句也适用于这些对象。

将对所有 DynamoDB 表进行加密。没有为新表或现有表启用或禁用加密的选项。默认情况下,在 DynamoDB 服务账户中的 AWS 拥有的客户主密钥 (CMK) 下对所有表进行加密。不过,您可以选择用于在账户中的适用于 DynamoDB 的 AWS 托管 CMK 下对部分或所有表进行加密的选项。静态加密不支持客户托管 CMK

注意

在 2018 年 11 月之前,静态加密是一项可选功能,它仅支持适用于 DynamoDB 的 AWS 托管 CMK。如果已在任一 DynamoDB 表上启用静态加密,这些表将继续在 AWS 托管 CMK 下进行加密,除非您使用 AWS 管理控制台或 UpdateTable 操作来切换到 AWS 拥有的 CMK。

适用于 DynamoDB 的客户端加密

除了属于服务器端加密 功能的静态加密以外,AWS 还提供 Amazon DynamoDB 加密客户端。此客户端加密 库使您能够在将表数据提交到 DynamoDB 之前对该数据进行保护。利用服务器端加密,您的数据可通过 HTTPS 连接在传输中进行加密,在 DynamoDB 终端节点进行解密,然后在存储在 DynamoDB 中之前重新进行加密。客户端加密在 DynamoDB 中为数据从其源到存储提供端到端保护。

您可以将 DynamoDB 加密客户端 与静态加密结合使用。为了帮助您决定此策略是否适用于您的 DynamoDB 数据,请参阅 Amazon DynamoDB 加密客户端 开发人员指南 中的客户端或服务器端加密?

使用 CMK 和数据密钥

DynamoDB 静态加密功能使用一个 AWS KMS 客户主密钥 (CMK) 和一个数据密钥层次结构来保护您的表数据。在将 DynamoDB 流、全局表和备份写入持久性媒体时,DynamoDB 使用相同的密钥层次结构来保护这些对象 。

客户主密钥 (CMK)

静态加密功能在 AWS KMS 客户主密钥 (CMK) 下保护 DynamoDB 表。默认情况下,它使用 AWS 托管 CMK,但 DynamoDB 支持用于在 AWS 账户中的适用于 DynamoDB (aws/dynamodb) 的 AWS 托管 CMK下对部分或所有表进行加密的选项。您可以在创建或更新表时为表选择 CMK,并且可以为每个表做出不同的选择。静态加密功能不支持使用客户托管的 CMK

如果您需要以下任意功能,请使用 AWS 托管 CMK:

  • 您可以查看 CMK 及其密钥策略。(您无法更改密钥策略。)

  • 您可以通过在 AWS CloudTrail 日志中检查针对 AWS KMS 的 DynamoDB API 调用来审计 DynamoDB 表的加密和解密。

不过,AWS 拥有的 CMK 是免费的。对于每个 API 调用,AWS 托管 CMK 会产生费用

可通过以下方式随时更改表的 CMK:在 DynamoDB 控制台中或使用 UpdateTable 操作。在更改 CMK 时,DynamoDB 会生成新的表密钥。然后,它使用新的表密钥来重新加密数据加密密钥。

无论您选择哪种 CMK,使用 CMK 创建表密钥的过程都是相同的。

表密钥

DynamoDB 对表使用 CMK 来生成和加密表的唯一数据密钥(也称作表密钥)。该表密钥将在加密表的生命周期内保留。

表密钥用作密钥加密密钥。DynamoDB 使用此表密钥来保护用于加密表数据的数据加密密钥。DynamoDB 会为表中的每个底层结构生成唯一的数据加密密钥,但多个表项目可能受相同的数据加密密钥的保护。


              使用静态加密对 DynamoDB 表进行加密

当您首次访问加密表时,DynamoDB 会向 AWS KMS 发送请求以使用 CMK 解密表密钥。然后,它会使用明文表密钥来解密数据加密密钥,并使用明文数据加密密钥解密表数据。

DynamoDB 在 AWS KMS 外部生成、使用和存储表密钥和数据加密密钥。它会借助高级加密标准 (AES) 加密和 256 位加密密钥保护所有密钥。然后,它存储加密密钥及加密数据,以便它们可根据需要用于解密表数据。

表密钥缓存

为了避免针对每个 DynamoDB 操作调用 AWS KMS,DynamoDB 会针对每个连接将明文表密钥缓存在内存中。如果 DynamoDB 在处于不活动状态 5 分钟后获取缓存表密钥的请求,它会向 AWS KMS 发送新请求以解密表密钥。此调用将捕获自上次请求解密表密钥以来对 AWS KMS 或 AWS Identity and Access Management (IAM) 中的 CMK 的访问策略所做的任何更改。

授权使用 AWS 托管 CMK

如果您使用账户中的 AWS 托管 CMK 来保护 DynamoDB 表,则该 CMK 的策略必须向 DynamoDB 提供代表您使用它的权限。适用于 DynamoDB 的 AWS 托管 CMK 的授权上下文包括其密钥策略并授予该委托人使用此策略的权限。

由于 AWS 托管 CMK 在您的账户中,因此,您可以查看其策略和授权。但由于它由 AWS 托管,因此,您无法更改策略。

DynamoDB 无需额外授权即可使用默认的 AWS 拥有的 CMK 来保护您 AWS 账户中的 DynamoDB 表。

CMK 密钥策略

当 DynamoDB 在加密操作中使用适用于 DynamoDB (aws/dynamodb) 的AWS 托管 CMK 时,它将代表正在访问 DynamoDB 资源的用户执行此操作。AWS 托管 CMK 的密钥策略向账户中的所有用户授予对指定操作使用 AWS 托管 CMK 的权限。但是,权限仅在 DynamoDB 代表用户提出请求时才被授予。密钥策略中的 ViaService 条件不允许任何用户使用 AWS 托管 CMK,除非请求是通过 DynamoDB 服务发起的。

与所有 AWS 托管密钥的策略类似,此密钥策略由 AWS 服务建立。您无法更改它,但可以随时查看它。要获取您的账户中的适用于 DynamoDB 的 AWS 托管 CMK 的密钥策略,请使用 GetKeyPolicy 操作。

密钥策略中的策略语句具有以下影响:

  • 仅当 DynamoDB 代表账户中的用户发出请求时,才允许这些用户在加密操作中使用适用于 DynamoDB 的 AWS 托管 CMK。该策略还允许用户为 CMK 创建授权

  • 允许 AWS 账户根用户查看适用于 DynamoDB 的 AWS 托管 CMK 并撤销授权(允许 DynamoDB 使用 CMK)。DynamoDB 使用授权进行持续维护操作。

  • 允许 DynamoDB 执行只读操作来查找账户中的适用于 DynamoDB 的 AWS 托管 CMK。

{ "Version" : "2012-10-17", "Id" : "auto-dynamodb-1", "Statement" : [ { "Sid" : "Allow access through Amazon DynamoDB for all principals in the account that are authorized to use Amazon DynamoDB", "Effect" : "Allow", "Principal" : { "AWS" : "*" }, "Action" : [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:CreateGrant", "kms:DescribeKey" ], "Resource" : "*", "Condition" : { "StringEquals" : { "kms:CallerAccount" : "111122223333", "kms:ViaService" : "dynamodb.us-west-2.amazonaws.com" } } }, { "Sid" : "Allow direct access to key metadata to the account", "Effect" : "Allow", "Principal" : { "AWS" : "arn:aws:iam::111122223333:root" }, "Action" : [ "kms:Describe*", "kms:Get*", "kms:List*", "kms:RevokeGrant" ], "Resource" : "*" }, { "Sid" : "Allow DynamoDB Service with service principal name dynamodb.amazonaws.com to describe the key directly", "Effect" : "Allow", "Principal" : { "Service" : "dynamodb.amazonaws.com" }, "Action" : [ "kms:Describe*", "kms:Get*", "kms:List*" ], "Resource" : "*" } ] }

使用授权来授权 DynamoDB

除了密钥策略之外,DynamoDB 使用授权设置适用于 DynamoDB 的 AWS 托管 CMK (aws/dynamodb) 的权限。要查看账户中的 aws/dynamodb CMK 的授权,请使用 ListGrants 操作。DynamoDB 无需授权或任何其他权限即可使用 AWS 拥有的 CMK 来保护表。

DynamoDB 在执行后台系统维护和连续数据保护任务时使用授予权限。它还使用授权来生成表密钥

每个授权特定于一个表。如果该账户包含在同一 AWS 托管 CMK 下加密的多个表,则每个表都有一种授权。该授权受 DynamoDB 加密上下文约束,后者包括表名称和 AWS 账户 ID,而且它还包括在授权不再需要时停用授权的权限。

要创建授权,DynamoDB 将代表创建了加密表的用户调用 CreateGrant。创建授权的权限来自于密钥策略,该策略允许账户用户仅在 DynamoDB 代表授权用户提出请求时对 AWS 托管 CMK 调用 CreateGrant

该密钥策略还允许账户对 AWS 托管 CMK 撤销授权。但是,如果您对某个活动加密表撤销授权,DynamoDB 将无法保护和维护该表。

DynamoDB 加密上下文

加密上下文 是一组包含任意非机密数据的键值对。在请求中包含加密上下文以加密数据时,AWS KMS 以加密方式将加密上下文绑定到加密的数据。要解密数据,您必须传入相同的加密上下文。

DynamoDB 在所有 AWS KMS 加密操作中使用相同的加密上下文。如果您使用 AWS 托管 CMK 保护 DynamoDB 表,则可使用加密上下文来在审计记录和日志中标识 CMK 的使用。它还在日志中以明文形式显示,例如 AWS CloudTrailAmazon CloudWatch Logs

加密上下文还可以用作在策略和授权中进行授权的条件。DynamoDB 使用加密上下文来约束允许访问账户和区域中的 AWS 托管 CMK 的授权

在其请求 AWS KMS 时,DynamoDB 使用具有两个密钥–值对的加密上下文。

"encryptionContextSubset": { "aws:dynamodb:tableName": "Books" "aws:dynamodb:subscriberId": "111122223333" }
  • Table – 第一个密钥–值对用于标识 DynamoDB 正在加密的表。密钥是 aws:dynamodb:tableName。值为表的名称。

    "aws:dynamodb:tableName": "<table-name>"

    例如:

    "aws:dynamodb:tableName": "Books"
  • Account – 第二个密钥–值对标识 AWS 账户。密钥是 aws:dynamodb:subscriberId。该值为账户 ID。

    "aws:dynamodb:subscriberId": "<account-id>"

    例如:

    "aws:dynamodb:subscriberId": "111122223333"

监控 DynamoDB 与 AWS KMS 的交互

如果您使用 AWS 托管 CMK 保护您的 DynamoDB 表,则可使用 AWS CloudTrail 日志跟踪 DynamoDB 代表您发送到 AWS KMS 的请求。

本部分将讨论 GenerateDataKeyDecryptCreateGrant 请求。此外,如果您使用 AWS 托管 CMK 进行静态加密,DynamoDB 将使用 DescribeKey 操作来决定账户和区域中是否有 aws/dynamodb CMK。它还使用 RetireGrant 操作来在您删除表时删除授权。

GenerateDataKey

当您对表启用静态加密时,DynamoDB 会创建一个唯一表密钥。它将 GenerateDataKey 请求发送到指定表 CMK 的 AWS KMS。

记录 GenerateDataKey 操作的事件与以下示例事件类似。该用户是 DynamoDB 服务账户。参数包括 AWS 托管 CMK 的 Amazon 资源名称 (ARN)、需要 256 位密钥的密钥说明符以及标识表和 AWS 账户的加密上下文

{ "eventVersion": "1.05", "userIdentity": { "type": "AWSService", "invokedBy": "dynamodb.amazonaws.com" }, "eventTime": "2018-02-14T00:15:17Z", "eventSource": "kms.amazonaws.com", "eventName": "GenerateDataKey", "awsRegion": "us-west-2", "sourceIPAddress": "dynamodb.amazonaws.com", "userAgent": "dynamodb.amazonaws.com", "requestParameters": { "encryptionContext": { "aws:dynamodb:tableName": "Services", "aws:dynamodb:subscriberId": "111122223333" }, "keySpec": "AES_256", "keyId": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" }, "responseElements": null, "requestID": "229386c1-111c-11e8-9e21-c11ed5a52190", "eventID": "e3c436e9-ebca-494e-9457-8123a1f5e979", "readOnly": true, "resources": [ { "ARN": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", "accountId": "111122223333", "type": "AWS::KMS::Key" } ], "eventType": "AwsApiCall", "recipientAccountId": "111122223333", "sharedEventID": "bf915fa6-6ceb-4659-8912-e36b69846aad" }
Decrypt

当您访问加密的 DynamoDB 表时,DynamoDB 需要解密表密钥,以便它可以解密层次结构中位于其下方的密钥。然后,解密表中的数据。解密表密钥。DynamoDB 向指定表 CMK 的 AWS KMS 发送 Decrypt 请求。

记录 Decrypt 操作的事件与以下示例事件类似。用户是您的 AWS 账户中正在访问表的委托人。参数包括加密表密钥(作为密文 blob)以及标识表和 AWS 账户的加密上下文。AWS KMS 从密文中派生 CMK 的 ID。

{ "eventVersion": "1.05", "userIdentity": { "type": "AssumedRole", "principalId": "AROAIGDTESTANDEXAMPLE:user01", "arn": "arn:aws:sts::111122223333:assumed-role/Admin/user01", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2018-02-14T16:42:15Z" }, "sessionIssuer": { "type": "Role", "principalId": "AROAIGDT3HGFQZX4RY6RU", "arn": "arn:aws:iam::111122223333:role/Admin", "accountId": "111122223333", "userName": "Admin" } }, "invokedBy": "dynamodb.amazonaws.com" }, "eventTime": "2018-02-14T16:42:39Z", "eventSource": "kms.amazonaws.com", "eventName": "Decrypt", "awsRegion": "us-west-2", "sourceIPAddress": "dynamodb.amazonaws.com", "userAgent": "dynamodb.amazonaws.com", "requestParameters": { "encryptionContext": { "aws:dynamodb:tableName": "Books", "aws:dynamodb:subscriberId": "111122223333" } }, "responseElements": null, "requestID": "11cab293-11a6-11e8-8386-13160d3e5db5", "eventID": "b7d16574-e887-4b5b-a064-bf92f8ec9ad3", "readOnly": true, "resources": [ { "ARN": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", "accountId": "111122223333", "type": "AWS::KMS::Key" } ], "eventType": "AwsApiCall", "recipientAccountId": "111122223333" }
CreateGrant

在使用 AWS 托管 CMK 保护 DynamoDB 表时,DynamoDB 将使用授权来允许服务执行连续数据保护与维护和持久性任务。AWS 拥有的 CMK 不需要这些授权。

DynamoDB 创建的授权特定于表。CreateGrant 请求的委托人是创建了表的用户。

记录 CreateGrant 操作的事件与以下示例事件类似。参数包括表的 CMK 的 Amazon 资源名称 (ARN)、被授权委托人和停用委托人(DynamoDB 服务)以及授权涵盖的操作。它还包括要求所有加密操作都使用指定加密上下文的约束。

{ "eventVersion": "1.05", "userIdentity": { "type": "AssumedRole", "principalId": "AROAIGDTESTANDEXAMPLE:user01", "arn": "arn:aws:sts::111122223333:assumed-role/Admin/user01", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2018-02-14T00:12:02Z" }, "sessionIssuer": { "type": "Role", "principalId": "AROAIGDTESTANDEXAMPLE", "arn": "arn:aws:iam::111122223333:role/Admin", "accountId": "111122223333", "userName": "Admin" } }, "invokedBy": "dynamodb.amazonaws.com" }, "eventTime": "2018-02-14T00:15:15Z", "eventSource": "kms.amazonaws.com", "eventName": "CreateGrant", "awsRegion": "us-west-2", "sourceIPAddress": "dynamodb.amazonaws.com", "userAgent": "dynamodb.amazonaws.com", "requestParameters": { "keyId": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", "retiringPrincipal": "dynamodb.us-west-2.amazonaws.com", "constraints": { "encryptionContextSubset": { "aws:dynamodb:tableName": "Books", "aws:dynamodb:subscriberId": "111122223333" } }, "granteePrincipal": "dynamodb.us-west-2.amazonaws.com", "operations": [ "DescribeKey", "GenerateDataKey", "Decrypt", "Encrypt", "ReEncryptFrom", "ReEncryptTo", "RetireGrant" ] }, "responseElements": { "grantId": "5c5cd4a3d68e65e77795f5ccc2516dff057308172b0cd107c85b5215c6e48bde" }, "requestID": "2192b82a-111c-11e8-a528-f398979205d8", "eventID": "a03d65c3-9fee-4111-9816-8bf96b73df01", "readOnly": false, "resources": [ { "ARN": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", "accountId": "111122223333", "type": "AWS::KMS::Key" } ], "eventType": "AwsApiCall", "recipientAccountId": "111122223333" }