Skip to main content

Terraform Database Auto-Discovery

Report an Issue

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:

  1. The Teleport cluster's public proxy endpoint
  2. 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 tctl and tsh clients.

    Installing tctl and tsh clients
    1. Determine the version of your Teleport cluster. The tctl and tsh clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at /v1/webapi/find and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

      TELEPORT_DOMAIN=teleport.example.com:443
      TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
    2. Follow the instructions for your platform to install tctl and tsh clients:

      Download the signed macOS .pkg installer for Teleport, which includes the tctl and tsh clients:

      curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg

      In Finder double-click the pkg file to begin installation.

      danger

      Using 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.

    Connecting with TLS routing disabled

    This guide's commands assume your Teleport cluster uses TLS routing (proxy_listener_mode: multiplex), where the tctl and tsh clients reach every Teleport service through the Proxy Service's web address on port 443. 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:

    • tsh commands (e.g., tsh login --proxy=...): continue using the Proxy Service web address on port 3080 (or 443 if behind a load balancer). Do not change these to port 3025.

    • Direct tctl or Auth Service API commands: use port 3025 for the Auth Service gRPC listener:

      tctl status --auth-server=teleport.example.com:3025
  • Terraform 1.5.7 or 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 runs a Discovery Service in the cloud-discovery-group group. No Discovery Service installation is required.

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 login
eval "$(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.

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"
}

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 init
terraform 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_config for 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.

note

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

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

note

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.