New option for an existing attribute is desired
Fn::GetAtt on a AWS::RDS::DBCluster resource returns DBClusterResourceId for the resource
IAM Database Authentication
https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html
IAM Policy for IAM Database Access
https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.html
DB (RDS, DynamoDB...)
IAM Database Authentication requires us to create an IAM role, as per the link above.
The resource ARN of the user policy needs to follow this pattern
arn:aws:rds-db:region:account-id:dbuser:DbClusterResourceId/db-user-name
Creating a role in CloudFormation is easy, however there is currently no way to extract DbClusterResourceId from a AWS::RDS::DBCluster resource, meaning we have to resort to custom resources.
Because of this limitation, it looks like people have to resort to some workarounds as seen here until CFN supports it: https://stackoverflow.com/questions/42770067/how-do-you-associate-a-iam-role-with-an-aurora-cluster-using-cloudformation
Actually, this looks to be remedied with an update that came out back in August (as mentioned in an update to the StackOverflow answer):
As of August 29, 2019 this is finally supported!
There is a new attribute named AssociatedRoles that takes an array of DBClusterRoles. These are basically an object with a RoleArn and an optional FeatureName which can currently only be s3Import per this reference showing SupportedFeatureNames.member.N.
AssociatedRoles seems to be what you are looking for, as a property of the AWS::RDS::DBCluster resource type, which takes a list of the DBClusterRole property type.
This looks like you would need your CFN to create the IAM Role(s) first, and then reference them in AWS::RDS::DBCluster
Actually, this looks to be remedied with an update that came out back in August (as mentioned in an update to the StackOverflow answer):
As of August 29, 2019 this is finally supported!
There is a new attribute named AssociatedRoles that takes an array of DBClusterRoles. These are basically an object with a RoleArn and an optional FeatureName which can currently only be s3Import per this reference showing SupportedFeatureNames.member.N.AssociatedRoles seems to be what you are looking for, as a property of the
AWS::RDS::DBClusterresource type, which takes a list of the DBClusterRole property type.This looks like you would need your CFN to create the IAM Role(s) first, and then reference them in
AWS::RDS::DBCluster
This is not the same thing. The description of AssociatedRoles reads "Provides a list of the AWS Identity and Access Management (IAM) roles that are associated with the DB cluster. IAM roles that are associated with a DB cluster grant permission for the DB cluster to access other AWS services on your behalf."
What I'm talking about is the opposite; creating roles that allows e.g. a Lambda to connect to an RDS instance using IAM Authentication. You need the DBClusterResourceId to be able to create that role.
I would like to get the cluster ARN for use with the aurora data API
@revmischa for the data API, you can recreate the ARN if you provide the DBClusterIdentifier property like https://github.com/smoketurner/serverless-vpc-plugin/blob/master/example/serverless.yml#L59
I believe in most cases we need CF return RDS cluster ARN, but in RDS IAM authentication case, we need CF able to return DBClusterResourceId, so that we could create IAM role for that RDS resource. Its really inconvenient and tricky that RDS IAM authentication require DBClusterResourceId instead of the common cluster ARN.
https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html
To allow an IAM user or role to connect to your DB cluster, you must create an IAM policy. After that, you attach the policy to an IAM user or role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:us-east-2:1234567890:dbuser:cluster-ABCDEFGHIJKL01234/db_user"
]
}
]
}
Noticed that in sample rule above, currently there is no way to have "DBClusterResourceId", cluster-ABCDEFGHIJKL01234/ via CF....
Workaround to get the DB Clusters ARN in CloudFormation:
Value: Fn::Join: - "" - - !Sub "arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:" - !Select [0, !Split ['.', !GetAtt DBCluster.Endpoint.Address]].Not relevant here.
DBClusterResourceId (which is what this request is about) and DB cluster ARN is not the same thing
Workaround to get the DB Clusters ARN in CloudFormation:
Value: Fn::Join: - "" - - !Sub "arn:aws:rds:${AWS::Region}:${AWS::AccountId}:cluster:" - !Select [0, !Split ['.', !GetAtt DBCluster.Endpoint.Address]].Not revlevant here.
DBClusterResourceId (which is what this request is about) and DB cluster ARN is not the same thing
My bad - deleted comment
Please add this.
We desperately need this too.
Much needed. Thanks!
As a workaround I had to create a custom resource to retrieve this information:
Resources:
CustomLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: RDSDescribe
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- rds:DescribeDBClusters
Resource: '*'
RDSUtilsLambda:
Type: 'AWS::Lambda::Function'
DeletionPolicy: Delete
Properties:
Code:
ZipFile: |
import boto3
import os
import cfnresponse
region = os.environ['AWS_REGION']
client = boto3.client('rds', region_name=region)
def handler(event, context):
responseData = {}
try:
rds_cluster = event['ResourceProperties']['rdsCluster']
clusters = client.describe_db_clusters(DBClusterIdentifier=rds_cluster)
responseData['DbClusterResourceId'] = clusters['DBClusters'][0]['DbClusterResourceId'] # Returns Cluster Resource Id
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
except Exception as e:
cfnresponse.send(event, context, cfnresponse.FAILED, responseData)
Handler: index.handler
Runtime: python3.7
MemorySize: 128
Role: !GetAtt CustomLambdaRole.Arn
Timeout: 30
ClusterResourceIdOutput:
Type: Custom::RDSClusterResourceIdOutput
Properties:
rdsCluster: !Ref RDSCluster
ServiceToken: !GetAtt RDSUtilsLambda.Arn
Region: !Ref "AWS::Region"
UserIAMRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- "ec2.amazonaws.com"
Action:
- sts:AssumeRole
Policies:
- PolicyName: IAMDbAuthentication
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- rds-db:connect
Resource:
- !Sub "arn:aws:rds-db:${AWS::Region}:${AWS::AccountId}:dbuser:${ClusterResourceIdOutput.DbClusterResourceId}/my_nice_user"
Most helpful comment
Please add this.