Search code examples
amazon-web-servicesamazon-rdsamazon-iam

AWS/IAM Policy for RDS snapshot management?


I'm working on a script to automatically take an RDS snapshot every day and give it a name based on an appropriate pattern (e.g. mydb-snapshot-20141031). The script itself is pretty straightforward but I ran into issues trying to lock things down so that if the key pair associated with the script is compromised, the attacker can only damage my snapshots and not the database itself.

Searching the web and looking at the RDS IAM policy guide hasn't turned up much to help me (at least not that I've been able to reproduce) so I'm hoping someone here has solved this before (or can understand that manual better than I can). Here's what I want:

  • Permission to make a snapshot of database instance named "mydb"
  • Permission to write snapshots matching mydb-snapshot-*
  • Permission to delete snapshots matching mydb-snapshot-*

Here's what I'm trying to protect against:

  • I don't want this user to be able to interact with any part of AWS outside of RDS
  • I don't want this user to be able to actually alter any of my RDS instances, including "mydb"
  • I don't want this user to be able to alter snapshots which do not match mydb-snapshot-*

Maybe this can't be done (I can't find documentation for a "delete" companion to the rds:CreateDBSnapshot policy). It would be nice if the DeleteDBSnapshot documentation actually included a list of permissions required to use it.


Solution

  • I eventually found the DeleteDBSnapshot permission but later realized that what I really wanted to do was restrict actions to a specific DB Instance Identifier, which I am now convinced is not possible because of how the AWS commands actually work. Thus, you must create a policy that looks something like this:

    {
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "rds:AddTagsToResource",
            "rds:DeleteDBSnapshot"
          ],
          "Condition": {
            "streq": {
              "rds:snapshot-tag/MY_TAG_KEY": [
                "MY_TAG_VALUE"
              ]
            }
          },
          "Resource": "arn:aws:rds:us-west-2::snapshot:mydb-snapshot-*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "rds:ListTagsForResource",
            "rds:CreateDBSnapshot"
          ],
          "Resource": "arn:aws:rds:us-west-2:*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "rds:DescribeDBSnapshots"
          ],
          "Resource": "*"
        }
      ]
    }
    

    A few notes/caveats:

    • For most commands related to snapshots, the Resource property of the policy is a check against DBSnapshotIdentifier, but for CreateDBSnapshot it appears to refer to DBInstanceIdentifier (RDS database name).
    • DescribeDBSnapshots always operates globally so it must also be granted on all resource values. You can't even restrict this by region.
    • ListTagsForResource throws a permissions error if you try to restrict it to the full snapshot resource path.
    • You don't need it, but I've included an example Condition block for those who wish to further (or alternately) restrict by tags. As with limiting by Resource, ListTagsForResource and CreateDBSnapshot do not work if you try to limit them to specific tags.

    This solves my primary concern of limiting the damage if keys attached to this policy are compromised -- the attacker could only delete my rolling snapshots, not any manually-created snapshots or the database instances themselves. Unfortunately, it still allows the creation of an unlimited number of snapshots in the specific zone, but there doesn't seem to be any way at all to restrict CreateDBSnapshot.