Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimal KMS permissions to copy a database snapshot

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

like image 410
svenwltr Avatar asked Aug 22 '17 15:08

svenwltr


People also ask

How do you take snapshots from RDS?

To create a DB snapshotSign in to the AWS Management Console and open the Amazon RDS console at https://console.aws.amazon.com/rds/ . In the navigation pane, choose Databases. In the list of DB instances, choose the DB instance for which you want to take a snapshot. For Actions, choose Take snapshot.

How do I copy a RDS snapshot from one region to another?

To copy your encrypted snapshot to a different AWS Region, simply select the destination region during the Copy Snapshot operation on the AWS Management Console or via the AWS Command Line Interface. You do not need to do anything differently to gain the benefits of incremental copies.

How long does it take to restore an RDS snapshot?

Restoring from the Snapshot takes 25 minutes! 25 minutes for the restore is too long considering users are forced to stay in read only mode for all this period and that our DB size is less than 10 mb at the moment. I am wondering if this restore time is the usual time for Amazon RDS or if we are doing something wrong.

How do I copy a RDS snapshot to another AWS account?

Choose Snapshots from the navigation pane. From the Snapshots pane, choose the Shared with Me tab. Select the DB snapshot that was shared. Choose Actions, and then choose Copy Snapshot to copy the snapshot into the same AWS Region and with a KMS key from the target account.


2 Answers

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(" ")' 
like image 176
svenwltr Avatar answered Oct 02 '22 19:10

svenwltr


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!

like image 27
Aloysio Carvalho Avatar answered Oct 02 '22 19:10

Aloysio Carvalho