Search code examples
amazon-web-servicesaws-security-group

Configure interdependent security groups in AWS VPC


In the AWS VPC, I added a security group for the database access that allows any request from a specific CIDR IP on port 3306. This CIDR IP includes private subnets as well as public subnets. A public subnet is allowed so that database can explicitly be connected to developers machines using bastion host (EC2 instance configured on VPC's public subnet and assigned an IP from Amazon's pool of public IPs).

Ideally, services on a private subnet should able to connect to a database.

  1. Rather than defining the network mask from where the connection is allowed in one security group, is there any elegant way to do it (probably by creating two security groups as defined in this AWS document)?
  2. Database should connect only on 3306 port but services should be allowed to use any port for the database access. How to configure a security group to achieve this? For example, one security group that allows requests on only 3306 port (this security group can be attached to the database). And, another security that allows connection to all ports (this security group can be attached to microservices instances). Somehow this microservice security group should be mapped to a database security group in such a way that no matter on what port request is coming from it should in turn call database security group on 3306 port. Can this be done?

Tried something along this line:

DBConnectableSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: ...
      GroupDescription: Allows for connection to the DB cluster.

ServerlessDBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: ...
     GroupDescription: Defines rules for connecting to the DB cluster. 

OutboundRule:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      IpProtocol: tcp
      FromPort: 0
      ToPort: 65535
      DestinationSecurityGroupId: !GetAtt ServerlessDBSecurityGroup.GroupId
      GroupId: !GetAtt DBConnectableSecurityGroup.GroupId

InboundRule:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      IpProtocol: tcp
      FromPort: 3306
      ToPort: 3306
      SourceSecurityGroupId: !GetAtt DBConnectableSecurityGroup.GroupId
      GroupId: !GetAtt ServerlessDBSecurityGroup.GroupId

App-SG -- Inbound Rule

App-SG -- Inbound Rule

DB-SG -- Inbound Rule (source is pointing to App-SG)

DB-SG -- Inbound RUle

App-SG and DB-SG -- Outbound Rule

App-SG -- Outbound Rule

Now I associate App-SG with an application. This application can successfully connect to the database on port 3306 (same as configured in Inbound Rule of DB-SG).

I associate App-SG with another application. This application uses a different port to connect to the database, port 3310. As App-SG allows all ports, I expect this to connect to the database but this does not work and the connection is refused.


Solution

  • The preferred configuration is:

    • A security group on the application resource (App-SG) with appropriate inbound permissions to use the application, and the default All Outbound permissions
    • A security group on the database (DB-SG) that permits inbound connections on the database port from App-SG and All Outbound

    That is, DB-SG specifically references App-SG in its inbound rules. This way, any resource that is associated with App-SG will be allowed to communicate with the database. This method avoids having to specify IP address and CIDR ranges and any new resources that use App-SG will automatically gain access to the database.