Minimal KMS permissions to copy a database snapshot
Asked Answered
S

7

38

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

Schock answered 22/8, 2017 at 15:1 Comment(8)
Can you add --debug to the aws rds command and post?Fania
I added the debug output from the actual HTTP request.Schock
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/AWSKeyManagementServicePowerUserFania
I didn't find any matching Policy. Unfortunatly AWSKeyManagementServicePowerUser is far from a minimal permission set.Schock
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.Fania
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).Schock
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 sameFania
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)Donovan
S
72

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(" ")'
Schock answered 25/8, 2017 at 12:55 Comment(1)
Worth noting that you need these for both the source KMS key and the target KMS key.Phonography
D
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!

Differ answered 22/10, 2019 at 21:46 Comment(3)
I stumbled upon this bug as well, lost 3 hours. Thank you for the tip !Abode
worth noting that RDS will only work with symmetric key. Asymmetric keys will not work, but you won't have a clear message.Abode
@Ka.This was the fix for me, thanks! AWS error message was very vagueAnthill
V
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.

Venial answered 24/3, 2021 at 15:12 Comment(0)
G
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
Gamb answered 10/4, 2018 at 18:56 Comment(1)
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).Donovan
L
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/

Lithotomy answered 15/3, 2023 at 19:55 Comment(0)
L
0

I was trying to copy db cluster snapshot (mostly Aurora clusters would use that) from one region to another using boto3 and I went through all the answers but I was simply getting the same error as mentioned in the question. We cannot specify destination region of snapshot in parameter of copy_db_cluster_snapshot API in boto3.

So I am writing this so that whoever faces issue with copy_db_cluster_snapshot method to copy it to another region can follow this guide.

I had a Lambda function and the code would look like below:
Destination region of snapshot = us-west-2
Source region of snapshot = us-east-1

Below points are important:

  1. The boto3.client should have destination region mentioned so that the request goes to destination region when you check in cloud trail.
  2. The kms-key-id should be of the kms in destination region
  3. SourceDBClusterSnapshotIdentifier - It should have full snapshot arn of the snapshot to be copied.
    def copy_to_other_region_lambda_handler(event, context):
        client = boto3.client('rds','us-west-2')
        response = client.copy_db_cluster_snapshot(
            SourceDBClusterSnapshotIdentifier='arn:aws:rds:us-east-1:account-id:cluster-snapshot:source',
            TargetDBClusterSnapshotIdentifier='target-snapshot',
            CopyTags=True,
            SourceRegion='us-east-1',
            KmsKeyId='arn:aws:kms:us-west-2:account-id:key/key-id'
        )
Lundeen answered 29/9, 2023 at 14:55 Comment(0)
G
0

this is the policy you have to use for your kms key of the source vault.

{  
"Version": "2012-10-17",  
"Id": "cab-kms-key",  
"Statement": [{  
        "Sid": "Enable IAM User Permissions",  
        "Effect": "Allow",  
        "Principal": {  
            "AWS": "arn:aws:iam::SourceAccountID:root"  
        },  
        "Action": "kms:*",  
        "Resource": "*"  
    },  
    {  
        "Sid": "Allow use of the key",  
        "Effect": "Allow",  
        "Principal": {  
            "AWS": [  
                "arn:aws:iam::SourceAccountID:root",  
                "arn:aws:iam::DestinationAccountID:root"  
            ]  
        },  
        "Action": [  
            "kms:DescribeKey",  
            "kms:Encrypt",  
            "kms:Decrypt",  
            "kms:ReEncrypt*",  
            "kms:GenerateDataKey*"  
        ],  
        "Resource": "*"  
    },  
    {  
        "Sid": "Allow attachment of persistent resources",  
        "Effect": "Allow",  
        "Principal": {  
            "AWS": [  
                "arn:aws:iam::SourceAccountID:root",  
                "arn:aws:iam::DestinationAccountID:root"  
            ]  
        },  
        "Action": [  
            "kms:CreateGrant",  
            "kms:ListGrants",  
            "kms:RevokeGrant"  
        ],  
        "Resource": "*",  
        "Condition": {  
            "Bool": {  
                "kms:GrantIsForAWSResource": "true"  
            }  
        }  
    }  
]  

}

worked well in my case. I found it here: https://repost.aws/knowledge-center/backup-cross-account-copy-error

Greg answered 26/1 at 19:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.