Checking RDS connection behavior by security group pattern

TOC

Configure to check security group for RDS

Check the security group to be applied to RDS.

When accessing RDS from EC2, the key point is the security group; just like EC2 instances, you can apply security groups to RDS as well.

Security groups control the access that traffic has in and out of a DB instance…

By default, network access is disabled for a DB instance. You can specify rules in a security group that allow access from an IP address range, port, or security group.

Controlling access with security groups

As mentioned above, an EC2 instance will not be able to access RDS unless the security group is properly configured. In this article, we will prepare three patterns regarding the security group to be set for RDS, and check their operation.

Environment

Diagram of checking RDS connection by security gorup pattern.

In one of the private subnets, place an EC2 instance. The instance will act as a client that accesses the RDS as described below. The instance will be based on an AMI of the latest version of Amazon Linux2.

Create an RDS instance of type MySQL. 3 patterns are provided to clarify the relationship between RDS and security groups. All settings except for the security group should be the same.

  • No security group setting
  • Apply a security group that does not have a single inbound communication to allow.
  • Apply a security group that allows MySQL communication (3306/tpc)

Create a VPC endpoint for S3, to install a client to connect to the MySQL instance.

In order to see how the RDS connection behavior changes depending on the security group, we will follow the steps below.

  1. enable VPC flow logging on the private subnet where the EC2 instance and RDS instance are placed.
  2. remotely access the EC2 instance and attempt to access the three RDS instances..
  3. Check the access results and the flow log at the time of access.

CloudFormation template files

We will build the above configuration using CloudFormation.

The CloudFormation template is placed at the following URL

https://github.com/awstut-an-r/awstut-soa/tree/main/05/001

Template points

We will cover the key points of each template file to configure this architecture.

Create security group for RDS

Identify the security group to be applied to the RDS instance.

Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-InstanceSecurityGroup"
      GroupDescription: Deny All.
      VpcId: !Ref VPC

  RDSDenySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-RDSDenySecurityGroup"
      GroupDescription: Deny All.
      VpcId: !Ref VPC

  RDSAllowSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-RDSAllowSecurityGroup"
      GroupDescription: Allow MySQL.
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref MySQLPort
          ToPort: !Ref MySQLPort
          SourceSecurityGroupId: !Ref InstanceSecurityGroup
Code language: YAML (yaml)

There are three types of security groups that can be applied to RDS instances.

A VPC security group controls access to DB instances and EC2 instances inside a VPC.

A DB security group controls access to EC2-Classic DB instances that are not in a VPC.

An EC2-Classic security group controls access to an EC2 instance.

Controlling access with security groups

In this case, we will create and apply a VPC security group to the RDS instances that are installed in a regular VPC.

The first security group that we will define (InstanceSecurityGroup) is the one that will be applied to the EC2 instance; we will not set the SecurityGroupIngress property. Do not set the SecurityGroupIngress property, because in this configuration, no inbound communication to the Ec2 instance will occur.

The second one (RDSDenySecurityGroup) is a security group for RDS instances. The SecurityGroupIngress property is not set here either.

The third one (RDSAllowSecurityGroup) is also for RDS instances. For this one, set the SecurityGroupIngress property to allow MySQL communication (3306/tcp). Also, by specifying the aforementioned security group for EC2 instances as the sender, only access from EC2 instances will be allowed.

Define MySQL client installation process in UserData

Check the EC2 instance. The point is the initialization process of the instance with user data.

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref PrivateSubnet1
          GroupSet:
            - !Ref InstanceSecurityGroup
      UserData: !Base64 |
        #!/bin/bash -xe
        yum update -y
        yum install -y mariadb
Code language: YAML (yaml)

The role of the EC2 instance in this case is to act as a client to access a MySQL-type RDS instance, so we need to install a MySQL client.

For Amazon Linux 2, the MySQL client can be installed from the mariadb package. The package can be obtained from Amazon Linux repositories built on S3 buckets. In this case, the repository is accessed via the VPC endpoint for S3.
For more information on client tools and connection methods for RDS instances, please refer to the following page.

あわせて読みたい
Amazon Linux 2 How to Connect to RDS – ALL Engines 【How to connect to all RDS DB engines from Amazon Linux 2】 As of 2022, RDS offers the following seven DB engines aurora(PostgreSQL) aurora(MySQL) PostgreSQ...

User data is set in the UserData property. In this article, we will describe the process of installing the same client after installing the repository containing the MySQL client.

There are several EC2 instance initialization processes, but this time we will use user data.
User data is set with the UserData property. Describes the process of installing the mariadb package.
For more details on the initialization process of the instance containing the user data, please refer to the following page as well.

あわせて読みたい
Four ways to initialize Linux instance 【Four ways to initialize a Linux instance】 Consider how to perform the initialization process when an EC2 instance is started. We will cover the following ...

Define three patterns of RDS instances

Check the RDS instance.

Resources:
  DBInstance1:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: !Ref DBAllocatedStorage
      AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
      DBInstanceClass: !Ref DBInstanceClass
      DBInstanceIdentifier: dbinstance1
      DBName: !Ref DBName
      DBSubnetGroupName: !Ref DBSubnetGroup
      Engine: !Ref DBEngine
      EngineVersion: !Ref DBEngineVersion
      MasterUsername: !Ref DBMasterUsername
      MasterUserPassword: !Ref DBMasterUserPassword
      #VPCSecurityGroups:

  DBInstance2:
    Type: AWS::RDS::DBInstance
    Properties:
      ...
      VPCSecurityGroups:
        - !Ref RDSDenySecurityGroup

  DBInstance3:
    Type: AWS::RDS::DBInstance
    Properties:
      ...
      VPCSecurityGroups:
        - !Ref RDSAllowSecurityGroup
Code language: YAML (yaml)

We will prepare three RDS instances that are identical in all respects except for the security group settings.

The first instance (DBInstance1) will not have any security group settings.

For the second instance (DBInstance2), in the VPCSecurityGroups property, apply a security group that does not have any inbound communication to allow.

For the third instance (DBInstance3), apply a security group that only allows MySQL communication (3306/tcp).

Store VPC flow logs in CloudWatch Logs

Define the resources related to VPC flow log in soa-05-001-flowlog.yaml.

Resources:
  FlowLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "${Prefix}-FlowLogGroup"

  FlowLogToCloudWatchLogs:
    Type: AWS::EC2::FlowLog
    DependsOn:
      - FlowLogGroup
    Properties:
      DeliverLogsPermissionArn: !GetAtt DeliverLogRole.Arn
      LogDestinationType: cloud-watch-logs
      LogGroupName: !Sub "${Prefix}-FlowLogGroup"
      ResourceId: !Ref VPC
      ResourceType: VPC
      TrafficType: ALL
Code language: YAML (yaml)

VPC Flow Log is a service that can collect network logs within a VPC.

VPC Flow Logs is a feature that enables you to capture information about the IP traffic going to and from network interfaces in your VPC. Flow log data can be published to Amazon CloudWatch Logs or Amazon S3.

VPC Flow Logs

This time, we will distribute VPC flow logs to CloudWatch Logs. As for the scope of collection, we will assume that it is all logs for the entire VPC.

For more information on VPC flow logs, please refer to the following page.

あわせて読みたい
Deliver VPC Flow Logs to S3/CloudWatch Logs 【Configuration to obtain VPC Flow Logs】 Check the VPC Flow Logs. VPC Flow Logs is a service that allows you to obtain traffic information within a VPC. VPC...

Architecting

We will use CloudFormation to build this environment and check its actual behavior.

Create CloudFormation stacks and check resources in stacks

Create a CloudFormation stack.

For more information on how to create stacks and check each stack, please refer to the following page.

あわせて読みたい
CloudFormation’s nested stack 【How to build an environment with a nested CloudFormation stack】 Examine nested stacks in CloudFormation. CloudFormation allows you to nest stacks. Nested ...

After checking the resources for each stack, the information for the main resource created this time is as follows

  • Instance ID: i-0fe6d50e5958523a4
  • Endpoint for DBInstance1: dbinstance1.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
  • DBInstance2 endpoint: dbinstance2.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
  • Endpoint for DBInstance3: dbinstance3.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
  • ENI attached to DBInstance1: eni-085da82d3ccb0f0ad
  • ENI attached to DBInstance2: eni-0acae018ffc56ba56
  • ENI attached to DBInstance3: eni-0e71f2697f24bffbf
  • CloudWatch Logs log group name: soa-05-001-FlowLogGroup

The security groups attached to each DB instance are as follows.

Security groups attached to RDS.

You can also check the ENIs attached to the DB instance from the instance page.

ENIs attached to RDS.

Prep 1 – Accessing with instance via SSM Session Manager

Now that we are ready, we will access the EC2 instance.

Access is done through the SSM Session Manager.

$ aws ssm start-session \
--target i-0fe6d50e5958523a4

Starting session with SessionId: root-0539c6fe4b063eeb4
sh-4.2$
Code language: Bash (bash)

I was able to access it successfully.

For more information about SSM Session Manager, please refer to the following

あわせて読みたい
Accessing Linux instance via SSM Session Manager 【Configure Linux instances to be accessed via SSM Session Manager】 We will check a configuration in which an EC2 instance is accessed via SSM Session Manag...

After accessing, check the installation status of the MySQL client, as defined in the user data.

sh-4.2$ sudo yum list installed | grep mysql
mysql-community-client.aarch64        8.0.27-1.el7                   @mysql80-community
mysql-community-client-plugins.aarch64
                                      8.0.27-1.el7                   @mysql80-community
mysql-community-common.aarch64        8.0.27-1.el7                   @mysql80-community
mysql-community-libs.aarch64          8.0.27-1.el7                   @mysql80-community
mysql-community-libs-compat.aarch64   8.0.27-1.el7                   @mysql80-community
mysql80-community-release.noarch      el7-1                          installed  
Code language: Bash (bash)

During instance initialization, you can see that it has been successfully installed.

Prep 2 – Check VPC flow logs delivered to CloudWatch Logs

Check the VPC flow logs that are being delivered at this time.

A stream of VPC flow logs is created for each ENI.

You can see that a log stream is generated for each ENI that exists on the VPC.

From the top of the red box, the streams are DBInstance3, DBInstance2, and DBInstance1.

RDS Connection Test 1 – No Security Group

We will start the test with DB instance 1.

This instance does not have any security group defined.

Before starting the test, use the nslookup command to check the IP address set for the endpoint. This is because when we check the VPC flow logs later, we will use the IP address configured in RDS to search the logs.

sh-4.2$ nslookup dbinstance1.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   dbinstance1.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Address: 10.0.3.213
Code language: Bash (bash)

The address was 10.0.3.213.

Now let’s start the test. Try to access with the installed mysql command.

sh-4.2$ mysql -u testuser -p -h dbinstance1.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'dbinstance1.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com:3306' (110)
Code language: Bash (bash)

It failed. Wait for a while and you will get an error message back.

The VPC flow log for this timing is as follows.

Patterns for not setting security groups for DBInstance.

You can read more about how to look at the VPC flow log in VPC Flow Logs, but you can see that the packets sent to 10.0.3.213:3306 are REJECTed as a result.

From the above, we can see that since the security group is not applied to DB instance 1, all inbound communications are rejected, resulting in an access failure.

RDS Connection Test 2 – No inbound communication to allow

Next, we will perform the test on DB instance 2. The procedure is the same as before.

sh-4.2$ nslookup dbinstance2.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   dbinstance2.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Address: 10.0.3.205
Code language: Bash (bash)
sh-4.2$ mysql -u testuser -p -h dbinstance2.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'dbinstance2.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com:3306' (110)
Code language: Bash (bash)
Patterns in which the security group set for DBInstance is not appropriate.

This one also failed. The flow log also shows that MySQL communication to 10.0.3.205 is denied.

From the above, we can see that not allowing any inbound communication in the security group is equivalent to denying all inbound communication, and the behavior is the same as if we had not set up the security group.

RDS Connection Test 3 – Allow MySQL Communication

Finally, we will run the test against DB instance 3.

sh-4.2$ nslookup dbinstance3.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Server:         10.0.0.2
Address:        10.0.0.2#53

Non-authoritative answer:
Name:   dbinstance3.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Address: 10.0.3.82
Code language: Bash (bash)
sh-4.2$ mysql -u testuser -p -h dbinstance3.cl50iikpthxs.ap-northeast-1.rds.amazonaws.com
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 29
Server version: 8.0.23 Source distribution

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
Code language: Bash (bash)
Patterns with appropriate security groups set for DBInstance.

The access was successful. Checking the flow log, we can see that the packets sent from the EC2 instance to DB instance 3 and the return packets are ACCEPTED.

From the above, we can see that we can access the RDS by applying the appropriate security group according to the database system.

Summary

We created three patterns of RDS instances and checked the differences in behavior depending on the security group.

We found that in order to access the RDS, the appropriate security group must be set according to the database system.

We confirmed that if no security group is applied to RDS, or if a security group is applied that does not allow proper inbound communication, it will not be able to communicate properly.

TOC