AWS Secrets Manager 如何使用 AWS KMS - AWS Secrets Manager
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

AWS Secrets Manager 如何使用 AWS KMS

AWS Secrets Manager 是一项 AWS 服务,可加密和存储您的密钥,以透明方式解密密钥并将明文密钥返回给您。专门设计用于存储定期变化且不应硬编码或以明文形式存储在应用程序中的应用程序密钥,如登录凭证。作为对硬编码凭证或表查找的替代,您的应用程序调用了 Secrets Manager。

Secrets Manager 还支持定期轮换与常用数据库关联的密钥的功能。Secrets Manager 始终在存储新轮换的密钥之前对其进行加密。

Secrets Manager 与 AWS Key Management Service (AWS KMS) 集成,以使用受 AWS KMScustomer master key () 保护的唯一CMK数据密钥对每个密钥的每个版本进行加密。这种集成可根据从不会使 AWS KMS 处于未加密状态的加密密钥来保护您的密钥。它还使您能够在 CMK 上设置自定义权限并审核用于生成、加密和解密保护密钥的数据密钥的操作。

保护密钥值

为了保护密钥,Secrets Manager 会对密钥中的密钥值 进行加密。

在 Secrets Manager 中,密钥密钥值(也称为受保护的密钥文本加密的密钥数据)和相关的元数据及版本信息组成。密钥值可以是最多包含 65,536 个字节的任何字符串或二进制数据,但通常由一组包含服务器或数据库登录信息的名称/值对组成。

Secrets Manager 始终在存储密钥之前对整个密钥值进行加密。每当您获取或更改密钥值时,Secrets Manager 都会以透明方式解密密钥值。您不能选择启用或禁用加密。Secrets Manager 使用 AWS KMS 来加密和解密密钥值。

加密和解密密钥

为了保护密钥,Secrets Manager 将信封加密与 AWS KMS customer master keys () 和CMKs数据密钥结合使用来保护每个密钥值。每当密钥中的密钥值更改时,Secrets Manager 便会生成新的数据密钥来保护它。数据密钥在 AWS KMS CMK 下加密,并存储在密钥的元数据中,如下图所示。要解密密钥,Secrets Manager 必须首先使用 CMK 中的 AWS KMS 解密已加密的数据密钥。


        加密某个密钥版本中的密钥值

每个密钥一个AWS KMSCMK

每个密钥与一个 AWS 托管或客户托管 customer master key (CMK) 关联。客户托管的 CMKs 允许授权用户通过策略和授权来控制对 CMK的访问、管理自动轮换以及使用导入的密钥材料。

重要

Secrets Manager 仅支持 CMKs。不能使用非对称 CMK 来加密您的密钥。有关确定 CMK 是对称还是非对称的帮助,请参阅确定对称和非对称 CMKs

在创建新密钥时,您可以在账户和区域中指定任何对称客户托管的 CMK,或者指定 AWS 托管的 CMK(用于 Secrets Manager、aws/secretsmanager)。 如果未指定 CMK,或者选择控制台默认值 DefaultEncryptionKey,Secrets Manager 将创建 aws/secretsmanager CMK(如果它不存在)并将其与密钥关联。您可以为账户中的每个密钥使用相同的 CMK 或不同的 CMKs。

您可以随时在 CMK 控制台中或使用 Secrets ManagerUpdateSecret 操作更改密钥的 。更改 CMK 时,Secrets Manager 不会在新的 CMK 下重新加密现有密钥值。但是,下次密钥值更改时,Secrets Manager 会在新的 CMK 下对其进行加密。

要查找与密钥关联的CMK,请使用 ListSecretsDescribeSecret 操作。当密钥与适用于 AWS 的 CMK 托管 Secrets Manager (aws/secretsmanager) 关联时,这些操作不会返回 CMK 标识符。

Secrets Manager 不使用 CMK 直接加密密钥值。相反,它使用 CMK 生成并加密唯一数据密钥,并使用数据密钥来加密密钥值。

每个密钥值的唯一数据密钥

每当您创建或更改密钥中的密钥值时,Secrets Manager 都会使用与该密钥关联的 CMK 生成并加密一个唯一的 256 位高级加密标准 (AES) 对称数据密钥。Secrets Manager 使用明文数据密钥在 AWS KMS 外部加密密钥值,然后将其从内存中删除。它将数据密钥的加密副本存储在密钥的元数据中。

该密钥值最终受 CMK 保护,它永远不会使 AWS KMS 处于未加密状态。Secrets Manager 必须先让 AWS KMS 解密已加密的数据密钥,然后它才能解密该密钥。

加密密钥值

为了对密钥中的密钥值加密,Secrets Manager 使用以下过程。

  1. Secrets Manager 使用密钥的 AWS KMS 的 ID 和 256 位 AES 对称密钥的请求调用 GenerateDataKeyCMK 操作。AWS KMS 返回明文数据密钥以及使用 CMK加密的该数据密钥的副本。

  2. Secrets Manager 使用明文数据密钥和高级加密标准 (AES) 算法在 AWS KMS 之外对密钥值加密。然后,它将尽快从内存中删除明文密钥。

  3. Secrets Manager 将加密的数据密钥存储在密钥的元数据中,使其可用于解密密钥值。但是,任何 Secrets Manager APIs 均不会返回加密的密钥或加密的数据密钥。

解密密钥值

要解密已加密的密钥值,Secrets Manager 必须先解密已加密的数据密钥。由于数据密钥是使用 CMK 中的密钥的 AWS KMS 加密的,因此,Secrets Manager 必须向 AWS KMS 发出请求。

对已加密的密钥值解密:

  1. Secrets Manager 调用 AWS KMS Decrypt 操作并传入已加密的数据密钥。

  2. AWS KMS 使用密钥的 CMK 解密数据密钥。它将返回明文数据密钥。

  3. Secrets Manager 使用该明文数据密钥来解密密钥值。然后,它会尽快从内存中删除数据密钥。

使用 AWS KMS CMK

Secrets Manager 使用与密钥关联的 customer master key (CMK) 为每个密钥值生成数据密钥。Secrets Manager 还会使用 CMK 在需要解密加密的密钥值时解密该数据密钥。可在 AWS CloudTrail 事件、Amazon CloudWatch Logs 和审核跟踪中跟踪请求和响应。

以下 Secrets Manager 操作将触发使用 AWS KMS CMK 的请求。

GenerateDataKey

Secrets Manager 调用 AWS KMS GenerateDataKey 操作来响应以下 Secrets Manager 操作。

  • CreateSecret – 如果新密钥包含密钥值,则 Secrets Manager 请求新数据密钥来对其加密。

  • PutSecretValue– Secrets Manager 请求新的数据密钥来加密指定的密钥值。

  • UpdateSecret – 如果更新更改了密钥值,Secrets Manager 将请求新的数据密钥来对新密钥值加密。

注意

RotateSecret 操作不会调用 ,因为它不会更改密钥值。GenerateDataKey但是,如果 RotateSecret 调用的 Lambda 函数更改了密钥值,则其调用 PutSecretValue 操作时将触发 GenerateDataKey 请求。

Decrypt

为对加密的密钥值解密,Secrets Manager 将调用 AWS KMS Decrypt 操作,来对密钥中的已加密数据密钥解密。然后,它使用明文数据密钥来对已加密密钥值解密。

Secrets Manager 将调用 Decrypt 操作来响应以下 Secrets Manager 操作。

  • GetSecretValue – 先解密密钥值,然后再将其返回给调用方。Secrets Manager

  • PutSecretValue 和 UpdateSecret – 大多数 PutSecretValueUpdateSecret 请求不会触发 Decrypt 操作。但是,当 PutSecretValueUpdateSecret 请求尝试更改现有密钥版本中的密钥值时,Secrets Manager 将对现有密钥值解密并将其与请求中的密钥值比较,以确认两者是否相同。此操作可确保 Secrets Manager 操作为幂等操作。

验证对 CMK 的访问权限

当您建立或更改与密钥关联的 CMK 时,Secrets Manager 将使用指定的 GenerateDataKey 调用 Decrypt 和 CMK 操作。这些调用确认调用方是否有权将 CMK 用于这些操作。Secrets Manager 将放弃这些操作的结果;它不会在任何加密操作中使用这些结果。

您可以识别这些验证调用,因为这些请求中 SecretVersionId 密钥加密上下文的值为 RequestToValidateKeyAccess

注意

过去,Secrets Manager 验证调用不包含加密上下文。在较早的 AWS CloudTrail 日志中可能会找到没有加密上下文的调用。

授权使用CMK

当 Secrets Manager 在加密操作中使用 customer master key (CMK) 时,它代表创建或更改密钥中的密钥值的用户执行操作。

要代表您将 AWS KMS customer master key (CMK) 用于密钥,用户必须拥有以下权限。您可以在 IAM 策略或密钥策略中指定这些所需的权限。

  • kms:GenerateDataKey

  • kms:Decrypt

要仅允许将 CMK 用于源自 Secrets Manager 的请求,您可以将 kms:ViaService 条件密钥secretsmanager.<region>.amazonaws.com 值结合使用。

您还可以将加密上下文中的键或值用作将 CMK 用于加密操作的条件。例如,可在 或密钥策略文档中使用字符串条件运算符IAM,或在授权中使用授权约束

托管 AWS 的密钥策略CMK

仅当 AWS 代表用户发出请求时,适用于 CMK 的 Secrets Manager 托管 CMK 的密钥策略才向用户授予对指定操作使用 Secrets Manager 的权限。密钥策略不允许任何用户直接使用 CMK。

此密钥策略与所有 AWS 托管密钥的策略类似,均由该服务来建立。您无法更改密钥策略,但可以随时查看。有关详细信息,请参阅查看密钥策略

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

  • 仅当 CMK 代表账户中的用户发出请求时,才允许这些用户使用 Secrets Manager 执行加密操作。kms:ViaService 条件密钥可强制实施此限制。

  • 允许 AWS 账户创建 IAM 策略以允许用户查看 CMK 属性和撤销授权。

  • 尽管 Secrets Manager 不使用授权来获取对 CMK 的访问权限,但该策略还允许 Secrets Manager 代表用户为 创建授权,并允许账户CMK撤销任何授权以允许 使用 Secrets Manager。CMK这些是 AWS 托管 CMK的策略文档的标准元素。

以下是 AWS 的 CMK 托管 Secrets Manager 示例的密钥策略。

{ "Version" : "2012-10-17", "Id" : "auto-secretsmanager-1", "Statement" : [ { "Sid" : "Allow access through AWS Secrets Manager for all principals in the account that are authorized to use AWS S ecrets Manager", "Effect" : "Allow", "Principal" : { "AWS" : "*" }, "Action" : [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:CreateGrant", "kms:Describ eKey" ], "Resource" : "*", "Condition" : { "StringEquals" : { "kms:ViaService" : "secretsmanager.us-west-2.amazonaws.com", "kms:CallerAccount" : "111122223333" } } },{ "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" : "*" } ] }

Secrets Manager 加密上下文

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

在发送给 的 GenerateDataKeyDecrypt 请求中,AWS KMS 使用具有两个名称Secrets Manager值对的加密上下文来标识密钥及其版本,如以下示例所示。–名称不会变化,但与其组合的加密上下文会因每个密钥值而异。

"encryptionContext": { "SecretARN": "arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3", "SecretVersionId": "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1" }

您可以使用加密上下文在审计记录和日志中标识这些加密操作(例如 AWS CloudTrail 和 Amazon CloudWatch Logs),并将加密上下文用作在策略和授权中进行授权的条件。

Secrets Manager 加密上下文包含两个名称–值对。

  • SecretARN – 第一个名称–值对标识密钥。键为 SecretARN。 该值是密钥的 Amazon 资源名称 (ARN)。

    "SecretARN": "ARN of an Secrets Manager secret"

    例如,如果密钥的 ARN 是 arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3,加密上下文将包括以下对。

    "SecretARN": "arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3"
  • SecretVersionId – 第二个名称–值对标识密钥的版本。键为 SecretVersionId。 该值为版本 ID。

    "SecretVersionId": "<version-id>"

    例如,如果密钥的版本 ID 是 EXAMPLE1-90ab-cdef-fedc-ba987SECRET1,加密上下文将包括以下对。

    "SecretVersionId": "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1"

在为密钥建立或更改 CMK 时,Secrets Manager 向 发送 GenerateDataKeyDecryptAWS KMS 请求,以验证调用方是否有权将 CMK 用于这些操作。它将放弃响应,并且不对密钥值使用这些响应。

在这些验证请求中,SecretARN 的值是密钥的实际 ARN,但 SecretVersionId 值为 RequestToValidateKeyAccess,如以下加密上下文示例中所示。此特殊值可帮助您在日志和审核跟踪中标识验证请求。

"encryptionContext": { "SecretARN": "arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3", "SecretVersionId": "RequestToValidateKeyAccess" }
注意

在过去,Secrets Manager 验证请求不包含加密上下文。在较早的 AWS CloudTrail 日志中可能会找到没有加密上下文的调用。

监控 Secrets Manager 与 AWS KMS 的交互

您可以使用 AWS CloudTrail 和 Amazon CloudWatch Logs 来跟踪 Secrets Manager 代表您向 AWS KMS 发送的请求。

GenerateDataKey

当您在密钥中创建或更改密钥值时,Secrets Manager 将向 发送 GenerateDataKey 请求,该请求指定密钥的 AWS KMS。CMK

记录 GenerateDataKey 操作的事件与以下示例事件类似。该请求由 secretsmanager.amazonaws.com 调用。 参数包括密钥的 CMK的 Amazon 资源名称 (ARN)、需要 256 位密钥的密钥说明符以及标识密钥和版本的加密上下文

{ "eventVersion": "1.05", "userIdentity": { "type": "IAMUser", "principalId": "AROAIGDTESTANDEXAMPLE:user01", "arn": "arn:aws:sts::111122223333:assumed-role/Admin/user01", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2018-05-31T23:23:41Z" } }, "invokedBy": "secretsmanager.amazonaws.com" }, "eventTime": "2018-05-31T23:23:41Z", "eventSource": "kms.amazonaws.com", "eventName": "GenerateDataKey", "awsRegion": "us-west-2", "sourceIPAddress": "secretsmanager.amazonaws.com", "userAgent": "secretsmanager.amazonaws.com", "requestParameters": { "keyId": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab", "keySpec": "AES_256", "encryptionContext": { "SecretARN": "arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3", "SecretVersionId": "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1" } }, "responseElements": null, "requestID": "a7d4dd6f-6529-11e8-9881-67744a270888", "eventID": "af7476b6-62d7-42c2-bc02-5ce86c21ed36", "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" }
Decrypt

每当您获取或更改密钥的密钥值时,Secrets Manager 都会向 发送 DecryptAWS KMS 请求,以对已加密数据密钥进行解密。

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

{ "eventVersion": "1.05", "userIdentity": { "type": "IAMUser", "principalId": "AROAIGDTESTANDEXAMPLE:user01", "arn": "arn:aws:sts::111122223333:assumed-role/Admin/user01", "accountId": "111122223333", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": { "attributes": { "mfaAuthenticated": "false", "creationDate": "2018-05-31T23:36:09Z" } }, "invokedBy": "secretsmanager.amazonaws.com" }, "eventTime": "2018-05-31T23:36:09Z", "eventSource": "kms.amazonaws.com", "eventName": "Decrypt", "awsRegion": "us-west-2", "sourceIPAddress": "secretsmanager.amazonaws.com", "userAgent": "secretsmanager.amazonaws.com", "requestParameters": { "encryptionContext": { "SecretARN": "arn:aws:secretsmanager:us-west-2:111122223333:secret:test-secret-a1b2c3", "SecretVersionId": "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1" } }, "responseElements": null, "requestID": "658c6a08-652b-11e8-a6d4-ffee2046048a", "eventID": "f333ec5c-7fc1-46b1-b985-cbda13719611", "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" }