35

I am trying to setup minimal permissions for doing aws rds copy-db-snapshot with a KMS encryption key:

$ 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>

(Everything within <> is stripped out by me and contains valid values.)

Unfortunately I get this error:

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.

Currently I allow these actions:

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

It works if I replace it with kms:*{code}, so it must be a permission issue.

I tried to figure out the correct permissions with CloudTrail, but it just contains the same unhelpful error message.

So my actual questions:

  • What are the minimal KMS permissions for CopyDBSnapshot?
  • Is there a generic way to figure out the required permissions? It is always a pain to waste my time by googling the required permissions.

Edit: This is the is the bottom part of the log output with --debug enabled:

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: I did a cross-post to the AWS forum: https://forums.aws.amazon.com/thread.jspa?messageID=801745

svenwltr
  • 17,002
  • 12
  • 56
  • 68
  • Can you add --debug to the aws rds command and post? – Rodrigo Murillo Aug 22 '17 at 15:13
  • I added the debug output from the actual HTTP request. – svenwltr Aug 22 '17 at 15:23
  • Have you tried a managed policy as an alternative to specifying your own? Try to add the following policy to the role: See `arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser` – Rodrigo Murillo Aug 24 '17 at 12:58
  • I didn't find any matching Policy. Unfortunatly `AWSKeyManagementServicePowerUser` is far from a minimal permission set. – svenwltr Aug 24 '17 at 13:03
  • It is a AWS managed policy. My idea was to confirm if it works and reduce from there. It is more minimal than kms:* and in that way can be used as a basis for further reduction of unnecessary permissions. – Rodrigo Murillo Aug 24 '17 at 14:48
  • Yes, trial-and-error is a way to solve this problem. I was hoping that someone already knows the answer or give me a hint how to debug this better. Maybe AWS has an awesome hidden documentation somewhere (haha) which I didn't found yet. It's not the first time this kind of problem appears. Unfortunately I looks like I have to figure this out by myself (again). – svenwltr Aug 24 '17 at 15:24
  • I know I do the same drill each time. ;-) My current thinking it to look for a managed policy first, then work it from there. But there is no canonical reference for permissions based on operation it seems. I'm interested also on this particular case. Post if you find a solution I will do the same – Rodrigo Murillo Aug 24 '17 at 15:29
  • Perhaps AWS has changed something, but when invoking `copy_db_snapshot` via `boto3` (python API bindings), I only needed the `kms:ReEncrypt` permission in the destination region. This may be because I use a customer-managed key in the source region and an AWS-managed key in the destination (within the same AWS account) – mxmader Jun 19 '19 at 03:25

5 Answers5

64

Now, I figured it out by trial and error. Since I don't like to do the same task more than once, I automated it (see script below).

This are the required permissions for copying a RDS snapshot:

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

This is the script I used. Maybe it is useful for other people which have a similar problem. It is hacked together, so don't expect it to work out of the box.

#!/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(" ")'
svenwltr
  • 17,002
  • 12
  • 56
  • 68
9

I found another root cause for this, and another solution:

Just create, then delete, a RDS in the target region!

AWS RDS simply refused to copy a snapshot, no matter what I did to key policies, UNTIL I created a small, automatic RDS. Now any key works "out-of-box", even new ones without any policy change!

3

Aside from the permissions from the other answers, make sure to use a symmetric encryption key. AWS errors are not clear on what they mean and that very same error message is used when you are trying to do something with an asymmetric key that should be done with a symmetric one.

ErvalhouS
  • 4,178
  • 1
  • 22
  • 38
2

I'm also doing a copy of an RDS database snapshot, but using Powershell and my database is MS SQL. I'm getting the same error:

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

I ended up here with my searches, checking my profile, credentials, roles, etc... but all seems good.

My mistake was not specifying the region in the Copy-RDSDBSnapshot (in Powershell; equivalent to copy-db-snapshot in CLI). Since I'm copying across regions for a Disaster Recovery scenario, I must specify the KmsKeyId of the target Region (as it will defer from the source Region). The source region us-east-1 is my default region, so executing this didn't work, it failed with the error above, since i'm not specify anything, it runs in my default region us-east-1 and therefore it can't find the us-west-2 key, just as the error say, it "does not exist" in that region, it's nothing to do with permissions:

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

Adding the so called "Common Parameter" Region did the trick:

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
Thierry_S
  • 1,526
  • 16
  • 25
  • In your case, requiring `Region` for the CLI invocation to work is expected given 1) it's possible that your default region in your profile is not `us-west-2` 2) you reference `us-west-2` in the value of `KmsKeyId` and the context of the command is seemingly to "copy a snapshot from a source". For consistency, I copy EC2 EBS snapshots in the same manner (targeting the destination region from the `boto3` client in my case). – mxmader Jun 19 '19 at 03:29
2

If this is a one time event (possibly copying/cloning a RDS from another account) and you are willing to use AWS console here are the steps:

  1. Go to the account that the snapshot exists (source) and go to KMS , create a customized kms (it's important to add the target account/destination account) for this KMS enter image description here
  2. Go to RDS console , Snapshots --> select the snapshot --> click actions (top right corner) -->Copy snapshot (make sure you use the new KMS key you created NOT the default)
  3. Once the new snapshot becomes available , go to Snapshots--> select the new created snapshot --> Actions --> share snapshot -->add the target/destination account
  4. Go to target account , click -->shared with me enter image description here
  5. Go to actions (on target/destination account still) and click -->create copy snapshot
  6. Once it finishes , go to Actions and Restore Snapshot

Full credit to AWS documentation https://aws.amazon.com/premiumsupport/knowledge-center/share-encrypted-rds-snapshot-kms-key/

grepit
  • 21,260
  • 6
  • 105
  • 81