Securely Connecting to Private RDS Instances Using AWS Verified Access

AWS Verified Access provides secure access to private applications and resources without requiring a virtual private network (VPN). Previously, it only supported HTTP(S)-based applications, such as applications running behind internal Application Load Balancers. During AWS re:Invent 2024, AWS introduced a new AWS Verified Access feature that enables support for non-HTTP(S) applications and resources, including private RDS instances, EC2 instances, and more.
In this post, I will explain how to use AWS Verified Access non-HTTP(S) endpoints to access a private RDS instance without using a VPN.
Prerequisites
- Enable the AWS IAM Identity Center in the AWS Region that you are working in.
- VPC with private subnets
- RDS instance running in a private subnet
Steps
- Configure the trust provider
- Create a Verified Access instance
- Attach trust provider to the instance
- Create a Verified Access Group
- Create a Verified Access RDS endpoint
- Testing
- Troubleshooting
Configure the Trust Provider
A trust provider is a service that provides information about users and devices. AWS Verified Access supports both AWS and third-party trust providers. In this example, I use “AWS IAM Identity Center” as the trust provider. Therefore, users created in the IAM Identity Center will be able to access the RDS instance.
resource "aws_verifiedaccess_trust_provider" "trust_provider" {
description = "IAM trust provider"
policy_reference_name = "iam" #Refer to this name in the policy document
trust_provider_type = "user"
user_trust_provider_type = "iam-identity-center"
tags = {
Name = "Iam Identity Center"
}
}

Create a Verified Access Instance
An AWS Verified Access instance is an AWS resource that manages the trust providers and Verified Access groups.
resource "aws_verifiedaccess_instance" "this" {
description = "AVA instance"
tags = {
Name = "AVA Instance"
}
}
Attach Trust Provider to the Instance
resource "aws_verifiedaccess_instance_trust_provider_attachment" "this" {
verifiedaccess_instance_id = aws_verifiedaccess_instance.this.id
verifiedaccess_trust_provider_id = aws_verifiedaccess_trust_provider.trust_provider.id
}

Create a Verified Access Group
An AWS Verified Access group is a collection of Verified Access endpoints and a group-level Verified Access policy. In this example, we use a simple policy that checks the format of an IAM user’s email address.
resource "aws_verifiedaccess_group" "this" {
verifiedaccess_instance_id = aws_verifiedaccess_instance.this.id
policy_document = <<-EOT
permit(principal, action, resource)
when {
context.iam.user.email.address like "*@gmail.com"
};
EOT
tags = {
Name = "AVA Group"
}
depends_on = [
aws_verifiedaccess_instance_trust_provider_attachment.this
]
}

Create a Verified Access RDS Endpoint
A Verified Access endpoint is a regional resource that defines the application for which Verified Access grants access. In this example, AWS Verified Access grants access to a RDS instance running in a private subnet.
Note that in the RDS security group, you need to allow traffic from the Verified Access endpoint. To do this, add the Verified Access security group ID as an allowed source in the RDS security group.
Set up RDS MySQL Instance
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~>6.9.0"
identifier = var.identifier
engine = var.engine
engine_version = var.engine_version
family = var.family
major_engine_version = var.major_engine_version
instance_class = var.instance_class
username = var.username
manage_master_user_password = var.manage_master_user_password
manage_master_user_password_rotation = var.manage_master_user_password_rotation
iam_database_authentication_enabled = var.iam_database_authentication_enabled
db_subnet_group_name = var.db_subnet_group_name
vpc_security_group_ids = var.vpc_security_group_ids
allocated_storage = var.allocated_storage
deletion_protection = false
skip_final_snapshot = true
storage_encrypted = false
multi_az = false
}

Create Verified Access Endpoint
Note that the Terraform aws_verifiedaccess_endpoint
resource currently does not support TCP-based endpoints. Therefore, I manually created the AWS Verified Access endpoint for RDS.



Testing
Follow the instructions below to test connectivity. You can download the complete code from this GitHub repository.
Download the AWS Verified Access connectivity client
To test connectivity, we first need to install the Verified Access connectivity client. You can download that from this link
Export the client configuration file
- Go to the Amazon VPC console at https://console.aws.amazon.com/vpc/.
- In the navigation pane, choose Verified Access instances.
- Select the Verified Access instance.
- Choose Actions, Export client configuration file.

Test the connection
- Copy client configuration file to the below location
- Windows —
C:\ProgramData\Connectivity Client
- macOS —
/Library/Application\ Support/Connectivity\ Client
2. Ensure that the client configuration is owned by root (macOS) or Admin (Windows).
3. Open the Connectivity Client and follow the authentication steps.
4. After authentication, you can access the RDS using the DNS name provided by Verified Access.



5. Copy the DNS name from the Endpoint details.

Access from terminal
Use the username and password you set for the RDS instance.

Access from MySQLWorkbench GUI client

Troubleshooting
I encountered an issue while testing this but was able to resolve it using the following steps.
Error
Unknown MySQL server host ‘vae-08b704b4bfd3b663d.vai-0e81031ee5b5da2ae.prod.verified-access.us-east-1.amazonaws.com’ (8)
If you have successfully signed in using the Verified Access client, you should see an IPv6 route entry on your local machine. However, in my case, it was not created initially.

Solution on Mac
- Go to Settings -> Network -> Wi-Fi
- Click on the Details
- Select TCP/IP
- Change Configure IPv6 to Automatically
Enable CloudWatch logs
You can enable CloudWatch logs for other issues.
