Terraform Database Auto-Discovery
This guide shows you how to use Terraform to configure Teleport to discover Amazon databases and deploy a Teleport Database Service on Amazon Elastic Container Service (ECS) to provide access to those databases.
Teleport Terraform modules currently support the following Amazon databases:
- RDS Aurora
- RDS MySQL
- RDS Postgres
How it works
The teleport-discovery-aws Terraform module creates AWS IAM resources, an
AWS OIDC integration,
and a Teleport discovery_config that the
Teleport Discovery Service uses to discover databases in AWS.
Teleport Cloud runs the Discovery Service for you. For a self-hosted Teleport
cluster, you run a Discovery Service with a discovery_group that matches the
group configured by the module.
The teleport-db-agent-aws Terraform module deploys a Teleport Database Service
as an ECS service.
The module creates an ECS cluster and service, task IAM roles, CloudWatch log
group, security group, and Teleport IAM join token. By default, the Database
Service selects discovered databases in the same AWS account, region, and VPC.
The Discovery Service only needs to be able to reach the Teleport Proxy and the AWS API - it does not need network access to the databases.
The Database Service must be able to reach:
- The Teleport cluster's public proxy endpoint
- The AWS database endpoints
Prerequisites
-
A running Teleport cluster accessible at a hostname with a valid TLS certificate. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.
-
The
tctlandtshclients.Installing
tctlandtshclients-
Determine the version of your Teleport cluster. The
tctlandtshclients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at/v1/webapi/findand use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:- Mac/Linux
- Windows - Powershell
TELEPORT_DOMAIN=teleport.example.com:443TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"$TELEPORT_DOMAIN = "teleport.example.com:443"$TELEPORT_VERSION = (Invoke-RestMethod -Uri "https://${TELEPORT_DOMAIN}/v1/webapi/find").server_version -
Follow the instructions for your platform to install
tctlandtshclients:- Mac
- Windows - Powershell
- Linux
Download the signed macOS .pkg installer for Teleport, which includes the
tctlandtshclients:curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkgIn Finder double-click the
pkgfile to begin installation.dangerUsing Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.
curl.exe -O https://cdn.teleport.dev/teleport-v$TELEPORT_VERSION-windows-amd64-bin.zipUnzip the archive and move the `tctl` and `tsh` clients to your %PATH%
NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
All of the Teleport binaries in Linux installations include the
tctlandtshclients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our installation page.curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gztar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gzcd teleportsudo ./installTeleport binaries have been copied to /usr/local/bin
Connecting with TLS routing disabled
This guide's commands assume your Teleport cluster uses TLS routing (
proxy_listener_mode: multiplex), where thetctlandtshclients reach every Teleport service through the Proxy Service's web address on port443. If you're not sure whether this applies to your cluster, check with whoever manages it.If your cluster uses separate listener ports instead, adjust ports as follows:
-
tshcommands (e.g.,tsh login --proxy=...): continue using the Proxy Service web address on port3080(or443if behind a load balancer). Do not change these to port3025. -
Direct
tctlor Auth Service API commands: use port3025for the Auth Service gRPC listener:tctl status --auth-server=teleport.example.com:3025
-
- Terraform
1.5.7or later. - An AWS account containing at least one RDS or Aurora database.
- A VPC and at least one subnet in which to deploy the Database Service.
- AWS credentials for the AWS Terraform provider.
- Teleport credentials for the Teleport Terraform provider. For a local Terraform run, follow the Teleport Terraform provider local demo.
This guide deploys the Database Service to the same AWS account, region, and VPC
as the databases. To access databases in other AWS accounts, configure
database_service_resources and the required cross-account IAM roles instead
of using the module's default resource matcher.
Step 1/6. Prepare the Discovery Service
- Teleport Cloud
- Self-hosted
Teleport Cloud runs a Discovery Service in the cloud-discovery-group group.
No Discovery Service installation is required.
Install Teleport on a host that can reach your Teleport Proxy Service. The host needs network access to the AWS API, but it does not need network access to any databases.
To install Teleport binaries on your Linux server, the recommended installation method is the cluster install script. This script is served by your Teleport cluster's Proxy Service and automatically selects the correct version, edition, and installation mode to match your cluster.
-
Remove any existing Teleport binaries on your system:
sudo rm -f /usr/local/bin/{tsh,teleport,tctl,tbot,fdpass-teleport,teleport-update} -
Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https://).
-
Run your cluster's install script:
curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
Create a join token for the Discovery Service:
The Discovery Service requires a valid join token to join your Teleport cluster.
Run the following tctl command and save the token output in /tmp/token
on the server that will run the Discovery Service:
tctl tokens add --type=discovery --format=textabcd123-insecure-do-not-use-this
Create /etc/teleport.yaml on the host. Assign
teleport.example.com:443 to the public address of your Teleport
Proxy Service:
version: v3
teleport:
join_params:
token_name: "/tmp/token"
method: token
proxy_server: "teleport.example.com:443"
auth_service:
enabled: false
proxy_service:
enabled: false
ssh_service:
enabled: false
discovery_service:
enabled: true
discovery_group: "aws-databases"
Start the Discovery Service. The instructions depend on how you installed the Discovery Service and whether your system supports systemd:
- Package Manager
- TAR Archive
- No systemd
Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Discovery Service, enable and start Teleport:
sudo systemctl enable teleportsudo systemctl start teleport
You can check the status of the Discovery Service with systemctl status teleport
and view its logs with journalctl -fu teleport.
Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Discovery Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:
sudo teleport install systemd -o /etc/systemd/system/teleport.servicesudo systemctl enable teleportsudo systemctl start teleport
You can check the status of the Discovery Service with systemctl status teleport
and view its logs with journalctl -fu teleport.
On the host where you will run the Discovery Service, start Teleport:
sudo teleport start --config=/etc/teleport.yaml
Teleport runs in the foreground and outputs logs for the services it is running.
Step 2/6. Configure the Terraform providers
Configure the AWS Terraform provider with the region containing the VPC and databases.
Add the AWS and Teleport providers to your Terraform configuration:
terraform {
required_version = ">= 1.5.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
teleport = {
source = "terraform.releases.teleport.dev/gravitational/teleport"
version = "~> 18.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
provider "teleport" {}
Configure the Teleport Terraform provider with credentials for your cluster. For a local Terraform run, log in to Teleport and export credentials for the provider from the same shell in which you will run Terraform:
tsh logineval "$(tctl terraform env)"
For CI/CD and other remote execution environments, follow Using the Teleport Terraform Provider to configure Machine ID or workload identity credentials.
Step 3/6. Configure the Terraform modules
Add both modules and a security group ingress rule to your Terraform configuration.
- Teleport Cloud
- Self-hosted
module "aws_discovery" {
source = "terraform.releases.teleport.dev/teleport/discovery/aws"
version = "~> 18.0"
teleport_proxy_public_addr = "example.teleport.sh:443"
teleport_discovery_group_name = "cloud-discovery-group"
aws_matchers = [{
types = ["rds"]
regions = ["us-east-1"]
tags = { "*" = ["*"] }
}]
}
module "teleport_db_agent" {
source = "terraform.releases.teleport.dev/teleport/db-agent/aws"
version = "~> 18.0"
teleport_proxy_public_addr = "example.teleport.sh:443"
vpc_id = "vpc-0123456789abcdef0"
ecs_service_subnets = [
"subnet-0123456789abcdef0",
"subnet-abcdef01234567890",
]
allow_database_modification = true
database_types_for_default_iam_policy = ["rds"]
}
resource "aws_vpc_security_group_ingress_rule" "teleport_db_agent" {
security_group_id = "sg-0123456789abcdef0"
referenced_security_group_id = module.teleport_db_agent.security_group_id
ip_protocol = "-1"
}
module "aws_discovery" {
source = "terraform.releases.teleport.dev/teleport/discovery/aws"
version = "~> 19.0"
teleport_proxy_public_addr = "teleport.example.com:443"
teleport_discovery_group_name = "aws-databases"
aws_matchers = [{
types = ["rds"]
regions = ["us-east-1"]
tags = { "*" = ["*"] }
}]
}
module "teleport_db_agent" {
source = "terraform.releases.teleport.dev/teleport/db-agent/aws"
version = "~> 19.0"
teleport_proxy_public_addr = "teleport.example.com:443"
vpc_id = "vpc-0123456789abcdef0"
ecs_service_subnets = [
"subnet-0123456789abcdef0",
"subnet-abcdef01234567890",
]
allow_database_modification = true
database_types_for_default_iam_policy = ["rds"]
}
resource "aws_vpc_security_group_ingress_rule" "teleport_db_agent" {
security_group_id = "sg-0123456789abcdef0"
referenced_security_group_id = module.teleport_db_agent.security_group_id
ip_protocol = "-1"
}
Replace the VPC, subnet, security group, and region values with
values for your AWS environment. If the databases use different security
groups, create one aws_vpc_security_group_ingress_rule resource for
each security group.
The discovery module's aws_matchers input controls which databases are
registered with Teleport. The example discovers all RDS and Aurora databases in
the configured region. Replace the wildcard tags selector to restrict
discovery to databases with specific AWS tags.
The database-agent module's default resource matcher selects registered
databases with account-id, region, and vpc-id labels matching the AWS
account, region, and VPC in which the ECS service runs.
Setting database_types_for_default_iam_policy = ["rds"] adds permissions to
describe RDS databases and connect with IAM authentication. Set
allow_database_modification = true to also allow the Database Service to
enable IAM database authentication. The default policy grants these RDS actions
against all applicable resources. To restrict the permissions for a production
deployment, pass a policy document to ecs_task_role_inline_policy. Statements
with the RDSAutoEnableIAMAuth, RDSConnect, and RDSFetchMetadata SIDs
override the corresponding default statements.
The discovery module uses an AWS OIDC integration by default. The public proxy
address of a self-hosted cluster must be reachable over HTTPS so AWS can use it
as an OIDC identity provider. If the proxy is not publicly reachable, configure
discovery_service_iam_credential_source to use an AWS IAM role available to
the Discovery Service instead.
AWS permits only one IAM OIDC provider for a given provider URL in an account.
If the account already has an IAM OIDC provider for this Teleport cluster, set
create_aws_iam_openid_connect_provider = false in the discovery module.
Step 4/6. Apply the Terraform configuration
Initialize Terraform and review the plan:
terraform initterraform apply
The discovery module should plan the following resources:
- An AWS IAM role and policy for RDS discovery.
- An AWS IAM OIDC provider and Teleport AWS OIDC integration.
- A Teleport
discovery_configfor the selected RDS databases.
The database-agent module should plan the following resources:
- An ECS cluster, task definition, and service.
- ECS task and execution IAM roles.
- A CloudWatch log group.
- A security group that permits outbound traffic.
- A Teleport IAM join token restricted to the ECS task role.
The plan should also include the inbound rule for the RDS security group. Review the plan carefully, then approve it.
The ECS service runs two Database Service tasks by default. The tasks join the Teleport cluster with their AWS IAM identity, so the module does not store a secret join token in the ECS task definition.
Step 5/6. Verify database discovery
The Discovery Service registers matched databases as Teleport db resources.
List the registered databases:
tctl get db
The Discovery Service adds the teleport.dev/origin: cloud label to each
database that it registers. Verify that the output contains RDS databases from
the configured AWS account and region.
If expected databases are missing, check the discovery integration in the Teleport Web UI under Zero Trust Access > Integrations, then refer to the Discovery Service troubleshooting section.
Step 6/6. Verify the Database Service
After the ECS tasks start and match the registered databases, they create
short-lived Teleport db_server resources. List the databases served by the
Database Service:
tctl db ls teleport.dev/origin=cloud,teleport.dev/cloud=AWS,region=us-east-1
If the command lists the expected RDS databases, auto-discovery and the Database Service are configured correctly.
If tctl get db lists a database but tctl db ls does not, open the
Amazon ECS console and inspect
the task logs in the CloudWatch log group.
Also verify the VPC route, RDS security group rule, resource labels, and ECS task
IAM permissions. Refer to Database Service
troubleshooting for additional checks.
This guide configures RDS auto-discovery and deploys the Database Service. It does not provision database users or configure Teleport RBAC for those users. Follow the appropriate guide in Enroll AWS Databases before connecting to a database.
Next steps
- Learn how the Database Service uses Dynamic Registration.
- Connect to a database.
- Configure access to AWS databases in external AWS accounts.
Troubleshooting
Inspect AWS discovery status
Run tctl discovery status to check the state of dynamic Discovery Service
configurations, when each Discovery Service instance last reported, and the latest
AWS enrollment totals:
tctl discovery status --cloud=aws
The following example shows a healthy configuration that discovered and enrolled two resources:
Discovery config example-discovery:
Discovery group: production
Status: healthy
Last run: 1 minute ago
Service (00000000-0000-0000-0000-000000000000):
Poll interval: 5 minutes
Last update: 1 minute ago
example-integration:
AWS RDS:
Previous sync: 1 minute ago (took 12s)
Result: 2 found, 2 enrolled, 0 failed
A persistent error or not reporting yet status, a message that no Discovery
Service instances are running, or a nonzero failed count indicates a discovery
or enrollment problem.
The command reports dynamic discovery_config resources. It does not include
static discovery matchers configured in teleport.yaml.
See tctl discovery status
for the full flag reference.
Discovery Service troubleshooting
First, check if any databases have been discovered.
To do this, you can use the tctl get db command and check if the
expected databases have already been registered with your Teleport
cluster.
If some databases do not appear in the list, check if the Discovery Service selector matches the missing databases' provider labels or tags, or check the Discovery Service logs for permission errors.
Check that the Discovery Service is running with credentials for the intended AWS environment. To discover resources in another account or project, grant its principal access to the target account or project.
Check if there is more than one Discovery Service instance running:
tctl inventory status --connected
If you are running multiple Discovery Service instances, you must ensure that
each service is configured with the same discovery_group value if they are
watching the same cloud databases or a different value if they are
watching different cloud databases. If this is not configured
correctly, a typical symptom is db resources being
intermittently deleted from your Teleport cluster's registry.
Database Service troubleshooting
Databases do not appear in tctl db ls
If the tctl get db command returns the discovered databases you expect, but
the tctl db ls command does not include them, check that you have set the
db_service.resources section correctly, for example:
db_service:
enabled: true
resources:
- labels:
"env": "prod"
If the section is correctly configured, but databases still do not appear,
check that you have the correct permissions to list databases in Teleport.
You should have a Teleport role that matches the database labels and allows
the "read" and "list" verbs for db and db_server objects.
Here's an example that grants those permissions for every database in your
cluster:
kind: role
version: v6
metadata:
name: view-all-databases
spec:
allow:
db_labels:
'*': '*'
rules:
- resources: [db_server, db]
verbs: [read, list]
Errors when connecting to a database
This section assumes you have already provisioned a database user and configured Teleport RBAC for that database user by following the appropriate database enrollment guide.
If there are connection errors when you try to connect to a database, then
first check if there are multiple db_server heartbeat resources for the target
database: tctl get db_server/yourDatabaseName.
If there are, it means that multiple Teleport Database Service instances are
proxying the database - this is an HA setup that will complicate
troubleshooting.
Teleport will choose one of those Database Service instances at random to proxy
the connection and if one of them can't reach the database endpoint or lacks
permissions, then you will see random connection errors.
Even if connection errors are consistent, you should scale down or reconfigure
your Teleport Database Service instances such that only one matches the target db
while you are troubleshooting errors.
Verify that there is only one db_server with tctl get db_server/yourDatabaseName
and then try the connection again.
Check the Teleport Database Service logs with DEBUG level logging enabled and look for network or permissions errors.
Refer to the Database Service troubleshooting guide for more general troubleshooting steps.
The enrollment guide for your database may provide more specific troubleshooting information.