复制数据库快照的最低 KMS 权限

Posted

技术标签:

【中文标题】复制数据库快照的最低 KMS 权限【英文标题】:Minimal KMS permissions to copy a database snapshot 【发布时间】:2018-01-30 22:44:02 【问题描述】:

我正在尝试设置使用 KMS 加密密钥执行aws rds copy-db-snapshot 的最低权限:

$ aws rds copy-db-snapshot --source-db-snapshot-identifier rds-backup-share-
mysql --target-db-snapshot-identifier rds-backup-share-mysql-reencrypted --kms-key-id <kms-arn>

&lt;&gt; 中的所有内容都被我剥离并包含有效值。)

不幸的是,我收到了这个错误:

An error occurred (KMSKeyNotAccessibleFault) when calling the CopyDBSnapshot operation: The target snapshot KMS key [<kms-arn>] does not exist, is not enabled or you do not have permissions to access it.

目前我允许这些操作:

  "Action": [
    "kms:ReEncrypt*",
    "kms:ListKeys",
    "kms:ListAliases",
    "kms:GenerateDataKey*",
    "kms:Encrypt",
    "kms:DescribeKey",
    "kms:Decrypt"
  ],

如果我用kms:*code替换它就可以了,所以一定是权限问题。

我试图通过 CloudTrail 找出正确的权限,但它只包含同样无用的错误消息。

所以我的实际问题:

CopyDBSnapshot 的最低 KMS 权限是多少? 是否有一种通用的方法来确定所需的权限?通过谷歌搜索所需的权限来浪费我的时间总是很痛苦。

编辑:这是启用--debug的日志输出的底部:

2017-08-22 17:15:37,521 - MainThread - botocore.endpoint - DEBUG - Sending http request: <PreparedRequest [POST]>
2017-08-22 17:15:37,522 - MainThread - botocore.vendored.requests.packages.urllib3.connectionpool - INFO - Starting new HTTPS connection (1): rds.eu-west-1.amazonaws.com
2017-08-22 17:15:37,927 - MainThread - botocore.vendored.requests.packages.urllib3.connectionpool - DEBUG - "POST / HTTP/1.1" 400 437
2017-08-22 17:15:37,934 - MainThread - botocore.parsers - DEBUG - Response headers: 'x-amzn-requestid': 'c097fe4e-874c-11e7-a56a-9d1acedaf516', 'content-type': 'text/xml', 'content-length': '437', 'date': 'Tue, 22 Aug 2017 15:15:37 GMT', 'connection': 'close'
2017-08-22 17:15:37,936 - MainThread - botocore.parsers - DEBUG - Response body:
b'<ErrorResponse xmlns="http://rds.amazonaws.com/doc/2014-10-31/">\n  <Error>\n    <Type>Sender</Type>\n    <Code>KMSKeyNotAccessibleFault</Code>\n    <Message>The target snapshot KMS key [<kms-arn>] does not exist, is not enabled or you do not have permissions to access it. </Message>\n  </Error>\n  <RequestId>c097fe4e-874c-11e7-a56a-9d1acedaf516</RequestId>\n</ErrorResponse>\n'
2017-08-22 17:15:37,938 - MainThread - botocore.hooks - DEBUG - Event needs-retry.rds.CopyDBSnapshot: calling handler <botocore.retryhandler.RetryHandler object at 0x7f9c7ce84860>
2017-08-22 17:15:37,939 - MainThread - botocore.retryhandler - DEBUG - No retry needed.
2017-08-22 17:15:37,952 - MainThread - awscli.clidriver - DEBUG - Exception caught in main()
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/awscli/clidriver.py", line 200, in main
    return command_table[parsed_args.command](remaining, parsed_args)
  File "/usr/lib/python3.6/site-packages/awscli/clidriver.py", line 338, in __call__
    return command_table[parsed_args.operation](remaining, parsed_globals)
  File "/usr/lib/python3.6/site-packages/awscli/clidriver.py", line 508, in __call__
    call_parameters, parsed_globals)
  File "/usr/lib/python3.6/site-packages/awscli/clidriver.py", line 627, in invoke
    client, operation_name, parameters, parsed_globals)
  File "/usr/lib/python3.6/site-packages/awscli/clidriver.py", line 639, in _make_client_call
    **parameters)
  File "/usr/lib/python3.6/site-packages/botocore/client.py", line 310, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/lib/python3.6/site-packages/botocore/client.py", line 599, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.KMSKeyNotAccessibleFault: An error occurred (KMSKeyNotAccessibleFault) when calling the CopyDBSnapshot operation: The target snapshot KMS key [<kms-arn>] does not exist, is not enabled or you do not have permissions to access it. 
2017-08-22 17:15:37,955 - MainThread - awscli.clidriver - DEBUG - Exiting with rc 255

An error occurred (KMSKeyNotAccessibleFault) when calling the CopyDBSnapshot operation: The target snapshot KMS key [<kms-arn>] does not exist, is not enabled or you do not have permissions to access it.

FTR:我在 AWS 论坛上发帖:https://forums.aws.amazon.com/thread.jspa?messageID=801745

【问题讨论】:

您可以在 aws rds 命令中添加 --debug 并发布吗? 我添加了实际 HTTP 请求的调试输出。 您是否尝试过使用托管策略来替代指定您自己的策略?尝试将以下策略添加到角色:请参阅arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser 我没有找到任何匹配的策略。不幸的是,AWSKeyManagementServicePowerUser 远非最小权限集。 这是一个 AWS 托管策略。我的想法是确认它是否有效并从那里减少。它比 kms:* 更小,因此可以用作进一步减少不必要权限的基础。 【参考方案1】:

除了其他答案的权限外,请确保使用对称加密密钥。 AWS 错误并不清楚它们的含义,并且当您尝试使用非对称密钥执行某些应该使用对称密钥执行的操作时,会使用相同的错误消息。

【讨论】:

【参考方案2】:

我找到了另一个根本原因,以及另一个解决方案:

只需在目标区域创建,然后删除 RDS!

AWS RDS 只是拒绝复制快照,无论我对关键策略做了什么,直到我创建了一个小型的自动 RDS。现在,任何密钥都可以“开箱即用”,即使是没有任何策略更改的新密钥!

【讨论】:

我也偶然发现了这个错误,浪费了 3 个小时。谢谢你的提示! 值得注意的是,RDS 只能使用对称密钥。非对称密钥不起作用,但您不会收到明确的信息。 @Ka。这对我来说是解决办法,谢谢! AWS 错误消息非常模糊【参考方案3】:

我也在制作 RDS 数据库快照的副本,但使用的是 Powershell,而我的数据库是 MS SQL。我遇到了同样的错误:

The target snapshot KMS key [<kms-arn>] does not exist, 
is not enabled or you do not have permissions to access it.

我在这里进行了搜索,检查了我的个人资料、凭据、角色等……但一切似乎都很好。

我的错误是没有在 Copy-RDSDBSnapshot 中指定区域(在 Powershell 中;等效于 CLI 中的 copy-db-snapshot)。由于我为灾难恢复方案跨区域复制,因此我必须指定目标区域的 KmsKeyId(因为它将延迟源区域)。源区域 us-east-1 是我的默认区域,因此执行此操作不起作用,它失败并出现上述错误,因为我没有指定任何内容,它在我的默认区域 us-east-1 中运行,因此它找不到 us-west-2 键,正如错误所说,它在该区域“不存在”,与权限无关:

Copy-RDSDBSnapshot -SourceDBSnapshotIdentifier $dBSnapshotArn `
                   -SourceRegion 'us-east-1' `
                   -TargetDBSnapshotIdentifier $targetSnapshotName `
                   -KmsKeyId 'arn:aws:kms:us-west-2:xxxxx:key/xxxxx' `
                   -CopyTag $true -OptionGroupName 'myOptionGroup'

添加所谓的“通用参数”Region 成功了:

Copy-RDSDBSnapshot -SourceDBSnapshotIdentifier $dBSnapshotArn `
                   -SourceRegion 'us-east-1' `
                   -TargetDBSnapshotIdentifier $targetSnapshotName `
                   -KmsKeyId 'arn:aws:kms:us-west-2:xxxxx:key/xxxxx' `
                   -CopyTag $true -OptionGroupName 'myOptionGroup' `
                   -Region 'us-west-2'  # <-- new line

【讨论】:

在您的情况下,需要 Region 才能使 CLI 调用正常工作,因为 1) 您的配置文件中的默认区域可能不是 us-west-2 2) 您在KmsKeyId 的值,并且命令的上下文似乎是“从源复制快照”。为了保持一致性,我以相同的方式复制 EC2 EBS 快照(在我的例子中,从 boto3 客户端定位目标区域)。【参考方案4】:

现在,我通过反复试验弄明白了。由于我不喜欢多次执行相同的任务,因此我将其自动化(参见下面的脚本)。

这是复制 RDS 快照所需的权限:

["kms:CreateGrant","kms:DescribeKey"]

这是我使用的脚本。也许它对其他有类似问题的人有用。它是一起破解的,所以不要指望它开箱即用。

#!/bin/bash

set -euo pipefail

unknown=(
    kms:CancelKeyDeletion
    kms:CreateAlias
    kms:CreateAlias
    kms:CreateGrant
    kms:CreateKey
    kms:Decrypt
    kms:DeleteAlias
    kms:DeleteAlias
    kms:DescribeKey
    kms:DisableKey
    kms:DisableKeyRotation
    kms:EnableKey
    kms:EnableKeyRotation
    kms:Encrypt
    kms:GenerateRandom
    kms:GenerateDataKey
    kms:GenerateDataKeyWithoutPlaintext
    kms:GetKeyPolicy
    kms:GetKeyRotationStatus
    kms:ListAliases
    kms:ListGrants
    kms:ListKeyPolicies
    kms:ListKeys
    kms:ListRetirableGrants
    kms:PutKeyPolicy
    kms:ReEncryptFrom
    kms:ReEncryptTo
    kms:RetireGrant
    kms:RevokeGrant
    kms:ScheduleKeyDeletion
    kms:UpdateAlias
    kms:UpdateAlias
    kms:UpdateKeyDescription
)
required=()

KEY_ID=86a6300d-38f9-4892-b7a1-d8f821e8438c
export AWS_DEFAULT_OUTPUT=json

function check_copy 
    permissions=$( echo -n "$required[*] $unknown[*]" | jq -R -s 'split(" ")' )

    policy=$( aws kms \
        get-key-policy \
        --key-id $KEY_ID \
        --policy-name default \
      | jq ".Policy" -r \
      | jq ".Statement[1].Action |= $permissions"
    )

    aws kms \
        put-key-policy \
        --key-id $KEY_ID \
        --policy-name default \
        --policy "$policy"

    aws rds \
        delete-db-snapshot \
        --db-snapshot-identifier rds-backup-share-mysql-reencrypted \
        || true

    (
        set -x
        AWS_ACCESS_KEY_ID=XXX \
        AWS_SECRET_ACCESS_KEY=XXX \
        aws rds \
            copy-db-snapshot \
            --source-db-snapshot-identifier rds-backup-share-mysql \
            --target-db-snapshot-identifier rds-backup-share-mysql-reencrypted \
            --kms-key-id alias/rds-snapshot-share \
            || return 1

    aws rds \
        wait db-snapshot-completed \
        --db-snapshot-identifier rds-backup-share-mysql-reencrypted
    ) || return 1

    return 0


check_copy
while [ $#unknown[@] -gt 0 ]
do
    removed=$unknown[0]
    unknown=($unknown[@]:1)

    if ! check_copy
    then
        required+=($removed)
    fi

    echo "Required permissions so far: $required[*]"
    echo "Unknown permissions so far: $unknown[*]"
done

echo -n "Minimal permissions: "
echo -n "$required[*]" | jq -R -s -c 'split(" ")'

【讨论】:

值得注意的是,源 KMS 密钥和目标 KMS 密钥都需要这些。

以上是关于复制数据库快照的最低 KMS 权限的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义服务帐户在 GCP 中创建 VM 时,KMS 权限出现 400 错误

配置用于复制加密对象的源 KMS 密钥

SQL2000发布和复制的问题

以递增方式跨区域复制RDS数据库快照

设置数据库复制时启动快照代理时出现异常

VMWare快照原理(写时复制)?快照保护快照克隆的作用?