How to Link EC2 Security Groups to PostgreSQL RDS Instances in AWS VPC


2 views

When working with PostgreSQL RDS instances in AWS VPC environments, many developers encounter a puzzling limitation: the inability to directly reference EC2 security groups as inbound rule sources during security group configuration. This becomes particularly frustrating when you need to allow access from auto-scaled EC2 instances behind an ELB.

The AWS RDS console interface shows only three source options for inbound rules: "Anywhere", "Custom IP", and "My IP". The dropdown doesn't allow manual entry, making it impossible to reference your EC2 security group through the UI. The documentation hint about EC2-Classic format (accountID/securityGroup) is misleading for VPC environments.

While the console UI doesn't support this directly, you can absolutely link security groups between EC2 and PostgreSQL RDS through these methods:

Using AWS CLI


aws rds modify-db-instance \
--db-instance-identifier your-postgres-instance \
--vpc-security-group-ids sg-12345678 sg-87654321 \
--apply-immediately

Using AWS SDK (Python Boto3)


import boto3

rds = boto3.client('rds')
response = rds.modify_db_instance(
    DBInstanceIdentifier='your-postgres-instance',
    VpcSecurityGroupIds=[
        'sg-12345678',  # Your existing RDS security group
        'sg-87654321'   # Your EC2 instances' security group
    ],
    ApplyImmediately=True
)
  • Both security groups must be in the same VPC
  • You need proper IAM permissions to modify RDS instances
  • Changes might cause a brief connection interruption
  • For production environments, consider using blue/green deployments

If managing infrastructure as code:


resource "aws_db_instance" "postgresql" {
  identifier           = "your-postgres-instance"
  engine               = "postgres"
  instance_class       = "db.t3.micro"
  allocated_storage    = 20
  
  vpc_security_group_ids = [
    aws_security_group.rds.id,
    aws_security_group.ec2_instances.id
  ]
  
  # Other required parameters...
}

After applying changes, verify connectivity from your EC2 instances:


psql -h your-rds-endpoint.rds.amazonaws.com -U postgres -d postgres

Remember that you'll also need to:

  1. Configure proper database user permissions
  2. Set up the correct subnet routing
  3. Ensure network ACLs allow the traffic

When working with AWS RDS PostgreSQL in a VPC environment, you'll notice the security group interface differs from EC2-Classic. The console's source dropdown initially shows limited options (Anywhere, Custom IP, and My IP), but the functionality exists through alternative methods.

Before proceeding, ensure:

  • Your EC2 instances and RDS instance reside in the same VPC
  • Both resources use VPC security groups (not EC2-Classic)
  • You have AmazonRDSFullAccess or equivalent permissions

The most reliable method is using AWS CLI:


# First, identify your security group IDs
aws ec2 describe-security-groups --query 'SecurityGroups[?GroupName==EC2-SG-Name].GroupId' --output text
aws rds describe-db-instances --db-instance-identifier your-postgres-db --query 'DBInstances[0].VpcSecurityGroups[0].VpcSecurityGroupId' --output text

# Authorize EC2 security group access to RDS
aws ec2 authorize-security-group-ingress \
    --group-id [RDS-SG-ID] \
    --protocol tcp \
    --port 5432 \
    --source-group [EC2-SG-ID]

For infrastructure-as-code deployments:


Resources:
  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "RDS PostgreSQL Security Group"
      VpcId: !Ref YourVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432
          SourceSecurityGroupId: !Ref EC2SecurityGroup

  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "EC2 Auto Scaling Group Security"
      VpcId: !Ref YourVPC

If connectivity fails after configuration:

  • Verify network ACLs aren't blocking traffic between subnets
  • Check that the RDS instance's publicly_accessible parameter is set to false
  • Confirm both security groups exist in the same AWS region

For complex architectures with multiple layers:


# Allow traffic from EC2 to RDS through intermediate SG
aws ec2 authorize-security-group-ingress \
    --group-id [RDS-SG-ID] \
    --protocol tcp \
    --port 5432 \
    --source-group [App-SG-ID]
    
aws ec2 authorize-security-group-ingress \
    --group-id [App-SG-ID] \
    --protocol tcp \
    --port 80 \
    --source-group [Web-SG-ID]

Remember that security group rules are stateful - responses are automatically allowed regardless of any outbound rules.