Skip to content

Commit

Permalink
fix(rds): proxy cannot connect to cluster/instance (#12953)
Browse files Browse the repository at this point in the history
By default, when creating a Proxy,
we were not creating a Security Group for it,
and because of that, the Proxy could not connect to the Cluster/Instance.

See docs at: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
skinny85 committed Feb 15, 2021
1 parent c0944d2 commit 4b0abbc
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 10 deletions.
16 changes: 13 additions & 3 deletions packages/@aws-cdk/aws-rds/lib/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class ProxyTarget {
/**
* Bind this target to the specified database proxy.
*/
public bind(_: DatabaseProxy): ProxyTargetConfig {
public bind(proxy: DatabaseProxy): ProxyTargetConfig {
const engine: IEngine | undefined = this.dbInstance?.engine ?? this.dbCluster?.engine;

if (!engine) {
Expand All @@ -84,6 +84,10 @@ export class ProxyTarget {
throw new Error(`Engine '${engineDescription(engine)}' does not support proxies`);
}

// allow connecting to the Cluster/Instance from the Proxy
this.dbCluster?.connections.allowDefaultPortFrom(proxy, 'Allow connections to the database Cluster from the Proxy');
this.dbInstance?.connections.allowDefaultPortFrom(proxy, 'Allow connections to the database Instance from the Proxy');

return {
engineFamily,
dbClusters: this.dbCluster ? [this.dbCluster] : undefined,
Expand Down Expand Up @@ -402,7 +406,13 @@ export class DatabaseProxy extends DatabaseProxyBase
secret.grantRead(role);
}

this.connections = new ec2.Connections({ securityGroups: props.securityGroups });
const securityGroups = props.securityGroups ?? [
new ec2.SecurityGroup(this, 'ProxySecurityGroup', {
description: 'SecurityGroup for Database Proxy',
vpc: props.vpc,
}),
];
this.connections = new ec2.Connections({ securityGroups });

const bindResult = props.proxyTarget.bind(this);

Expand All @@ -424,7 +434,7 @@ export class DatabaseProxy extends DatabaseProxyBase
idleClientTimeout: props.idleClientTimeout?.toSeconds(),
requireTls: props.requireTLS ?? true,
roleArn: role.roleArn,
vpcSecurityGroupIds: props.securityGroups?.map(_ => _.securityGroupId),
vpcSecurityGroupIds: cdk.Lazy.list({ produce: () => this.connections.securityGroups.map(_ => _.securityGroupId) }),
vpcSubnetIds: props.vpc.selectSubnets(props.vpcSubnets).subnetIds,
});

Expand Down
64 changes: 60 additions & 4 deletions packages/@aws-cdk/aws-rds/test/integ.proxy.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,37 @@
}
}
},
"dbInstanceSecurityGroupfromawscdkrdsproxydbProxyProxySecurityGroupA345AFE5IndirectPortE3621D4F": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties": {
"IpProtocol": "tcp",
"Description": "Allow connections to the database Instance from the Proxy",
"FromPort": {
"Fn::GetAtt": [
"dbInstance4076B1EC",
"Endpoint.Port"
]
},
"GroupId": {
"Fn::GetAtt": [
"dbInstanceSecurityGroupA58A00A3",
"GroupId"
]
},
"SourceSecurityGroupId": {
"Fn::GetAtt": [
"dbProxyProxySecurityGroup16E727A7",
"GroupId"
]
},
"ToPort": {
"Fn::GetAtt": [
"dbInstance4076B1EC",
"Endpoint.Port"
]
}
}
},
"dbInstanceSecret032D3661": {
"Type": "AWS::SecretsManager::Secret",
"Properties": {
Expand Down Expand Up @@ -429,6 +460,7 @@
"Ref": "dbInstanceSubnetGroupD062EC9E"
},
"Engine": "postgres",
"EngineVersion": "11.5",
"MasterUsername": {
"Fn::Join": [
"",
Expand Down Expand Up @@ -508,6 +540,22 @@
]
}
},
"dbProxyProxySecurityGroup16E727A7": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SecurityGroup for Database Proxy",
"SecurityGroupEgress": [
{
"CidrIp": "0.0.0.0/0",
"Description": "Allow all outbound traffic by default",
"IpProtocol": "-1"
}
],
"VpcId": {
"Ref": "vpcA2121C38"
}
}
},
"dbProxy3B89EAF2": {
"Type": "AWS::RDS::DBProxy",
"Properties": {
Expand All @@ -522,7 +570,6 @@
],
"DBProxyName": "dbProxy",
"EngineFamily": "POSTGRESQL",
"RequireTLS": true,
"RoleArn": {
"Fn::GetAtt": [
"dbProxyIAMRole662F3AB8",
Expand All @@ -536,6 +583,15 @@
{
"Ref": "vpcPrivateSubnet2Subnet7031C2BA"
}
],
"RequireTLS": true,
"VpcSecurityGroupIds": [
{
"Fn::GetAtt": [
"dbProxyProxySecurityGroup16E727A7",
"GroupId"
]
}
]
}
},
Expand All @@ -545,6 +601,7 @@
"DBProxyName": {
"Ref": "dbProxy3B89EAF2"
},
"TargetGroupName": "default",
"ConnectionPoolConfigurationInfo": {
"ConnectionBorrowTimeout": 30,
"MaxConnectionsPercent": 50
Expand All @@ -553,9 +610,8 @@
{
"Ref": "dbInstance4076B1EC"
}
],
"TargetGroupName": "default"
]
}
}
}
}
}
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-rds/test/integ.proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const stack = new cdk.Stack(app, 'aws-cdk-rds-proxy');
const vpc = new ec2.Vpc(stack, 'vpc', { maxAzs: 2 });

const dbInstance = new rds.DatabaseInstance(stack, 'dbInstance', {
engine: rds.DatabaseInstanceEngine.POSTGRES,
engine: rds.DatabaseInstanceEngine.postgres({
version: rds.PostgresEngineVersion.VER_11_5,
}),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MEDIUM),
credentials: rds.Credentials.fromUsername('master', {
excludeCharacters: '"@/\\',
Expand Down
24 changes: 22 additions & 2 deletions packages/@aws-cdk/aws-rds/test/test.proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@ export = {
},
],
}));

// THEN
expect(stack).to(haveResourceLike('AWS::RDS::DBProxyTargetGroup', {
DBProxyName: {
Ref: 'ProxyCB0DFB71',
Expand All @@ -138,6 +136,22 @@ export = {
DBInstanceIdentifiers: ABSENT,
TargetGroupName: 'default',
}));
expect(stack).to(haveResourceLike('AWS::EC2::SecurityGroupIngress', {
IpProtocol: 'tcp',
Description: 'Allow connections to the database Cluster from the Proxy',
FromPort: {
'Fn::GetAtt': ['DatabaseB269D8BB', 'Endpoint.Port'],
},
GroupId: {
'Fn::GetAtt': ['DatabaseSecurityGroup5C91FDCB', 'GroupId'],
},
SourceSecurityGroupId: {
'Fn::GetAtt': ['ProxyProxySecurityGroupC42FC3CE', 'GroupId'],
},
ToPort: {
'Fn::GetAtt': ['DatabaseB269D8BB', 'Endpoint.Port'],
},
}));

test.done();
},
Expand Down Expand Up @@ -205,6 +219,7 @@ export = {
engine: rds.DatabaseClusterEngine.auroraPostgres({
version: rds.AuroraPostgresEngineVersion.VER_9_6_11,
}),
port: 5432,
});

new rds.DatabaseProxy(stack, 'Proxy', {
Expand All @@ -221,6 +236,10 @@ export = {
'my-cluster',
],
}));
expect(stack).to(haveResourceLike('AWS::EC2::SecurityGroup', {
GroupDescription: 'SecurityGroup for Database Proxy',
VpcId: { Ref: 'VPCB9E5F0B4' },
}));

test.done();
},
Expand Down Expand Up @@ -294,6 +313,7 @@ export = {
'cluster611F8AFF',
'clusterSecretAttachment69BFCEC4',
'clusterSecretE349B730',
'clusterSecurityGroupfromproxyProxySecurityGroupA80F0525IndirectPortA13E5F3D',
'clusterSecurityGroupF441DCEA',
'clusterSubnets81E3593F',
],
Expand Down

0 comments on commit 4b0abbc

Please sign in to comment.