4

I need to create a VPC + RDS Postgres DB + RDS Proxy with private subnets, I'm setting up everything with CloudFormation using serverless.

I'm able to configure everything except the RDS Proxy, when I run serverless deploy the deployment hangs when creating the Target group and eventually shows a timeout error.

This is what I see in the AWS Console, even if I do the full process manually:

enter image description here

When I run aws rds describe-db-proxy-targets --db-proxy-name so-proxy-rds-db-proxy this is what I get:

{
    "Targets": [
        {
            "Endpoint": "so-proxy-rds-db.csy8ozys6dtv.us-west-2.rds.amazonaws.com",
            "RdsResourceId": "so-proxy-rds-db",
            "Port": 5432,
            "Type": "RDS_INSTANCE",
            "Role": "READ_WRITE",
            "TargetHealth": {
                "State": "UNAVAILABLE",
                "Reason": "AUTH_FAILURE",
                "Description": "Proxy does not have any registered credentials"
            }
        }
    ]
}

However I'm able to see them in the Secrets Manager. This is the reproducible configuration:

service: so-proxy-rds

frameworkVersion: "=2.49.0"
variablesResolutionMode: 20210326
configValidationMode: error

provider:
  name: aws
  runtime: nodejs14.x
  region: us-west-2
  versionFunctions: false
  memorySize: 1024
  timeout: 30

resources:
  Resources:    
    VPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: 10.0.0.0/16
        EnableDnsSupport: true
        EnableDnsHostnames: true
        Tags:
          - Key: Name
            Value: vpc
          
    PrivateSubnetA:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: 
          Ref: VPC
        CidrBlock: 10.0.2.0/24
        AvailabilityZone:       
          Fn::Select: 
            - 0
            - Fn::GetAZs: ""
        Tags:
          - Key: Name
            Value: private-A

    PrivateSubnetB:
      Type: AWS::EC2::Subnet
      Properties:
        VpcId: 
          Ref: VPC
        CidrBlock: 10.0.3.0/24
        AvailabilityZone:       
          Fn::Select: 
            - 1
            - Fn::GetAZs: ""
        Tags:
          - Key: Name
            Value: private-B

    PrivateRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId: 
          Ref: VPC
        Tags:
        - Key: Name
          Value: private
    
    PrivateSubnetARouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: 
          Ref: PrivateSubnetA
        RouteTableId: 
          Ref: PrivateRouteTable

    PrivateSubnetBRouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId: 
          Ref: PrivateSubnetB
        RouteTableId: 
          Ref: PrivateRouteTable
      
    OpenSecurityGroup:
      Type: AWS::EC2::SecurityGroup
      Properties: 
        GroupDescription: 'Open firewall'
        GroupName: ${self:service}-open
        SecurityGroupEgress: 
          - CidrIp: 0.0.0.0/0
            IpProtocol: "-1"
        SecurityGroupIngress: 
          - CidrIp: 0.0.0.0/0
            IpProtocol: "-1"
        VpcId: 
          Ref: VPC

    DBSubnetGroup:
      Type: AWS::RDS::DBSubnetGroup
      Properties:
        DBSubnetGroupDescription: DB subnet group
        SubnetIds:
          - Ref: PrivateSubnetA
          - Ref: PrivateSubnetB

    PostgresDB:
      Type: AWS::RDS::DBInstance
      Properties:
        DBInstanceIdentifier: db
        DBName: test_db
        AllocatedStorage: 20
        DBInstanceClass: db.t2.micro
        DBSubnetGroupName: 
          Ref: DBSubnetGroup
        Engine: postgres
        EngineVersion: 11.12 # only up to version 11 supports proxy
        MasterUsername: test_user
        MasterUserPassword: test_pass
        PubliclyAccessible: false
        VPCSecurityGroups:
          - Ref: OpenSecurityGroup
      DeletionPolicy: Delete

    ProxySecretValues:
      Type: 'AWS::SecretsManager::Secret'
      Properties:
        Name: proxy-secrets
        SecretString: '{"username":"test_user","password":"test_pass"}'

    DBProxy:
      Type: AWS::RDS::DBProxy
      Properties:
        DBProxyName: db-proxy
        EngineFamily: POSTGRESQL
        RoleArn:
          Fn::GetAtt:
            - DBProxyRole
            - Arn
        Auth:
          - AuthScheme: SECRETS
            IAMAuth: DISABLED
            SecretArn:
              Ref: ProxySecretValues
        VpcSubnetIds:
          - Ref: PrivateSubnetA
          - Ref: PrivateSubnetB
        VpcSecurityGroupIds:
          - Ref: OpenSecurityGroup

    DBProxyTargetGroup:
      Type: "AWS::RDS::DBProxyTargetGroup"
      Properties:
        DBInstanceIdentifiers:
          - Ref: PostgresDB
        DBProxyName: 
          Ref: DBProxy
        TargetGroupName: default

    DBProxyRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - "rds.amazonaws.com"
              Action:
                - "sts:AssumeRole"
        ManagedPolicyArns:
          - Ref: DBProxyPolicy
        RoleName: db-proxy-role

    DBProxyPolicy:
      Type: "AWS::IAM::ManagedPolicy"
      Properties:
        ManagedPolicyName: db-proxy-policy
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - "secretsmanager:*"
              Resource: '*'
            - Effect: Allow
              Action:
                - "kms:*"
              Resource: '*'

Any help is greatly appreciated, thanks.

jtoberon
  • 8,706
  • 1
  • 35
  • 48
marcos
  • 4,473
  • 1
  • 10
  • 24
  • 1
    I had this exact same error but the message was slightly misleading in my case. I looked in the CloudWatch logs (search log groups for "proxy" with "exact match" ticked) and I saw a better message regarding the underlying error (which in my case was "Credentials couldn't be retrieved. The IAM role provided with the ARN "xxx" couldn't be assumed. Make sure that this IAM role is set up correctly for this use") – Andy Mar 21 '22 at 16:41

2 Answers2

1

I dont see the role for roleArn entry declared in your "DBProxy" resource.

See the documentation:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxy.html?icmpid=docs_cfn_console_designer

Take note of the "RoleArn" in the CF snippet below:

"Resources": {
    "TestDBProxy": {
        "Type": "AWS::RDS::DBProxy",
        "Properties": {
            "DebugLogging": true,
            "DBProxyName": {
                "Ref": "ProxyName"
            },
            "EngineFamily": "MYSQL",
            "IdleClientTimeout": 120,
            "RequireTLS": true,
            "RoleArn": {
                "Ref": "BootstrapSecretReaderRoleArn"
            },
            "Auth": [
                {
                    "AuthScheme": "SECRETS",
                    "SecretArn": {
                        "Ref": "BootstrapProxySecretArn"
                    },
                    "IAMAuth": "DISABLED"
                }
            ],
            "VpcSubnetIds": {
                "Fn::Split": [
                    ",",
                    {
                        "Ref": "SubnetIds"
                    }
                ]
            }
        }
    }
Dharman
  • 30,962
  • 25
  • 85
  • 135
Billy D
  • 57
  • 1
  • 6
0

I'm unable to replicate the same error you had but I had the same error msg and managed to resolve it by going to Cloudwatch service and search for 'rds/proxy' log group. you will able to get a more granular error message. The output for aws rds describe-db-proxy-targets --db-proxy-name so-proxy-rds-db-proxy was very misleading. In my case, I never gave rds permission to assume my proxy role. It can be quickly fixed with

  Statement:
    - Effect: Allow
      Principal:
        Service:
          - "rds.amazonaws.com"
      Action:
        - "sts:AssumeRole" 

hope this will be helpful.