Amazon RDS and IAM Policy Notes
As a follow up to Amazon RDS and Tag-Based Permissions, this document digs into an IAM policy that restricts by tag value.
Took a look at the AWS Managed (Predefined) Policies for Amazon RDS, including AmazonRDSFullAccess
(see Using Identity-Based Policies (IAM Policies) for Amazon RDS), which includes Action
rds:*
for Resource
*
.
The following are the general formats for ARNs; the specific components and values used depend on the AWS service. (see Amazon Resource Names (ARNs) and AWS Service Namespaces )
arn:partition:service:region:account-id:resource
arn:partition:service:region:account-id:resourcetype/resource
arn:partition:service:region:account-id:resourcetype:resource
RDS has 11 ARN resource types (see Amazon Resource Names (ARNs) and AWS Service Namespaces).
arn:aws:rds:region:account-id:db:db-instance-name
arn:aws:rds:region:account-id:snapshot:snapshot-name
arn:aws:rds:region:account-id:cluster:db-cluster-name
arn:aws:rds:region:account-id:cluster-snapshot:cluster-snapshot-name
arn:aws:rds:region:account-id:og:option-group-name
arn:aws:rds:region:account-id:pg:parameter-group-name
arn:aws:rds:region:account-id:cluster-pg:cluster-parameter-group-name
arn:aws:rds:region:account-id:secgrp:security-group-name
arn:aws:rds:region:account-id:subgrp:subnet-group-name
arn:aws:rds:region:account-id:es:subscription-name
Each RDS resource type has its own tag name, like db-tag
or cluster-tag
(see Amazon RDS API Permissions: Actions, Resources, and Conditions Reference).
I tried to add StringEqualsIfExists
for each RDS tag type, but fails with duplicate keys for StringEqualsIfExists
.
"Condition": {
"StringEqualsIfExists": {
"rds:db-tag/xx:project-id": "123456"
},
"StringEqualsIfExists": {
"rds:cluster-tag/xx:project-id": "123456"
},
Note: “You cannot use a wildcard in the portion of the ARN that specifies the resource type” (see Amazon Resource Names (ARNs) and AWS Service Namespaces ). Since rds
is service namespace and db
or snapshot
is the resource type, this syntax won’t work.
"Resource": [
"arn:aws:rds:*:*:*:123456-*",
Therefore, you need to wildcard on resource name prefix (assuming all RDS resources are customer nameable vs. generated).
"Resource": [
"arn:aws:rds:*:*:db:123456-*",
"arn:aws:rds:*:*:cluster:123456-*",
"arn:aws:rds:*:*:es:123456-*",
"arn:aws:rds:*:*:og:123456-*",
"arn:aws:rds:*:*:pg:123456-*",
"arn:aws:rds:*:*:cluster-pg:123456-*",
"arn:aws:rds:*:*:secgrp:123456-*",
"arn:aws:rds:*:*:subgrp:123456-*",
"arn:aws:rds:*:*:snapshot:123456-*",
"arn:aws:rds:*:*:cluster-snapshot:123456-*",
"arn:aws:rds:*:*:ri:123456-*"
]
Note: “Policies have a maximum size between 2048 characters and 10,240 characters, depending on what entity the policy is attached to.” (see Grammar of the IAM Policy Language).
{
"Effect": "Allow",
"Action": [
"rds:*"
],
"Resource": [
"arn:aws:rds:*:123456789012:db:*"
],
"Condition": {
"StringEqualsIfExists": {
"rds:db-tag/xx:project-id": "123456"
}
}
},
{
"Effect": "Allow",
"Action": [
"rds:*"
],
"Resource": [
"arn:aws:rds:*:123456789012:cluster:*"
],
"Condition": {
"StringEqualsIfExists": {
"rds:cluster-tag/xx:project-id": "123456"
}
}
},