Navigating Access Challenges in Kubernetes-Based Infrastructure
Sep 19
Virtual
Register Today
Teleport logoTry For Free
Fork me on GitHub

Teleport

AWS Database Discovery

Teleport can be configured to discover AWS-hosted databases automatically and register them with your Teleport cluster.

In this guide, we will show you how to set-up AWS database auto-discovery.

How it works

Teleport database auto-discovery involves two components:

  1. The Teleport Discovery Service that watches for new databases or changes to previously discovered databases. It dynamically registers each discovered database as a db resource in your Teleport cluster. It does not need connectivity to the databases it discovers.
  2. The Teleport Database Service that monitors the dynamic db resources registered by the Discovery Service. It proxies communications between users and the database.

Prerequisites

  • A running Teleport cluster version 16.2.1 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool.

    Visit Installation for instructions on downloading tctl and tsh.

  • An AWS account with permissions to create and attach IAM policies.
  • A host to run the Teleport Discovery Service.
  • A host to run the Teleport Database Service.
  • One or more databases hosted on AWS.

Step 1/8. Install Teleport

Install Teleport on the host(s) that will run the Teleport Discovery Service and Teleport Database Service.

The Database Service needs network connectivity to databases, whereas the Discovery Service does not.

Install Teleport on your Linux server:

  1. Assign edition to one of the following, depending on your Teleport edition:

    EditionValue
    Teleport Enterprise Cloudcloud
    Teleport Enterprise (Self-Hosted)enterprise
    Teleport Community Editionoss
  2. Get the version of Teleport to install. If you have automatic agent updates enabled in your cluster, query the latest Teleport version that is compatible with the updater:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/automaticupgrades/channel/default/version | sed 's/v//')"

    Otherwise, get the version of your Teleport cluster:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/ping | jq -r '.server_version')"
  3. Install Teleport on your Linux server:

    curl https://cdn.teleport.dev/install-v16.2.1.sh | bash -s ${TELEPORT_VERSION} edition

    The installation script detects the package manager on your Linux server and uses it to install Teleport binaries. To customize your installation, learn about the Teleport package repositories in the installation guide.

Step 2/8. Discovery Service IAM permissions

Grant the Discovery Service access to credentials that it can use to authenticate to AWS.

  • If you are running the Discovery Service on an EC2 instance, you may use the EC2 Instance Metadata Service method
  • If you are running the Discovery Service in Kubernetes, you can use IAM Roles for Service Accounts (IRSA)
  • Otherwise, you must use environment variables

Teleport will detect when it is running on an EC2 instance and use the Instance Metadata Service to fetch credentials.

The EC2 instance should be configured to use an EC2 instance profile. For more information, see: Using Instance Profiles.

Refer to IAM Roles for Service Accounts (IRSA) to set up an OIDC provider in AWS and configure an AWS IAM role that allows the pod's service account to assume the role.

Teleport's built-in AWS client reads credentials from the following environment variables:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION

When you start the Discovery Service, the service reads environment variables from a file at the path /etc/default/teleport. Obtain these credentials from your organization. Ensure that /etc/default/teleport has the following content, replacing the values of each variable:

AWS_ACCESS_KEY_ID=00000000000000000000
AWS_SECRET_ACCESS_KEY=0000000000000000000000000000000000000000
AWS_DEFAULT_REGION=<YOUR_REGION>

Teleport's AWS client loads credentials from different sources in the following order:

  • Environment Variables
  • Shared credentials file
  • Shared configuration file (Teleport always enables shared configuration)
  • EC2 Instance Metadata (credentials only)

While you can provide AWS credentials via a shared credentials file or shared configuration file, you will need to run the Discovery Service with the AWS_PROFILE environment variable assigned to the name of your profile of choice.

If you have a specific use case that the instructions above do not account for, consult the documentation for the AWS SDK for Go for a detailed description of credential loading behavior.

Grant AWS IAM permissions

Attach the following AWS IAM permissions to the Discovery Service AWS IAM role:

Database Type

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DocumentDBDiscovery",
            "Effect": "Allow",
            "Action": "rds:DescribeDBClusters",
            "Resource": "*"
        }
    ]
}
StatementPurpose
DocumentDBDiscoveryDiscover Amazon DocumentDB Clusters.

Database discovery is not available for DynamoDB.

To register a DynamoDB database with your Teleport cluster, you must configure the database manually via static config or dynamic db resource.

See the database access reference for more information.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ElastiCacheDiscovery",
            "Effect": "Allow",
            "Action": "elasticache:DescribeReplicationGroups",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "elasticache:DescribeCacheClusters",
                "elasticache:DescribeCacheSubnetGroups",
                "elasticache:ListTagsForResource"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
ElastiCacheDiscoveryDiscover ElastiCache replication groups.
ElastiCacheFetchMetadataImport AWS tags and additional metadata for each database as Teleport database labels.

Database discovery is not available for Keyspaces.

To register a Keyspaces database with your Teleport cluster, you must configure the database manually via static config or dynamic db resource.

See the database access reference for more information.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "MemoryDBDiscovery",
            "Effect": "Allow",
            "Action": "memorydb:DescribeClusters",
            "Resource": "*"
        },
        {
            "Sid": "MemoryDBFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "memorydb:DescribeSubnetGroups",
                "memorydb:ListTags"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
MemoryDBDiscoveryDiscover MemoryDB databases.
MemoryDBFetchMetadataImport AWS tags and additional metadata for each database as Teleport database labels.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "OpenSearchDiscovery",
            "Effect": "Allow",
            "Action": [
                "es:DescribeDomains",
                "es:ListDomainNames"
            ],
            "Resource": "*"
        },
        {
            "Sid": "OpenSearchFetchMetadata",
            "Effect": "Allow",
            "Action": "es:ListTags",
            "Resource": "*"
        }
    ]
}
StatementPurpose
OpenSearchDiscoveryDiscover OpenSearch domains.
OpenSearchFetchMetadataImport each discovered domain's AWS tags as Teleport database labels.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSDiscovery",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBClusters",
                "rds:DescribeDBInstances"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RDSDiscoveryDiscover RDS instances and Aurora clusters.

When configured to discover RDS databases, the Teleport Discovery Service will attempt to discover both RDS instances and Aurora clusters. The rds:DescribeDBInstances permission is used to find RDS instances, but it is also used to find additional information about discovered Aurora clusters, so you should include this permission even if you only have Aurora clusters to discover. If you don't want Aurora cluster discovery, then you can omit the rds:DescribeDBClusters permission.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSProxyDiscovery",
            "Effect": "Allow",
            "Action": "rds:DescribeDBProxies",
            "Resource": "*"
        },
        {
            "Sid": "RDSProxyFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBProxyEndpoints",
                "rds:ListTagsForResource"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RDSProxyDiscoveryDiscover RDS Proxies and register each proxy's default endpoint as a Teleport database.
RDSProxyFetchMetadataFetch metadata for discovered proxies to import AWS resource tags as Teleport database labels and register custom endpoints as Teleport databases.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftDiscovery",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}
StatementPurpose
RedshiftDiscoveryDiscover Amazon Redshift Clusters.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftServerlessDiscovery",
            "Effect": "Allow",
            "Action": "redshift-serverless:ListWorkgroups",
            "Resource": "*"
        },
        {
            "Sid": "RedshiftServerlessFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "redshift-serverless:ListEndpointAccess",
                "redshift-serverless:ListTagsForResource"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RedshiftServerlessDiscoveryDiscover Redshift Serverless Workgroups.
RedshiftServerlessFetchMetadataFetch metadata for discovered workgroups to import AWS tags as Teleport database labels and register any VPC endpoints as Teleport databases.

Step 3/8. Deploy the Discovery Service

Create a Teleport config file

Create a teleport.yaml config file on the host that will run the Discovery Service. You can leave the discovery_group aws-example value as-is or change it to something you find more descriptive.

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

This config file enables the discovery_service and configures it to join the Teleport cluster. It also sets the Discovery Service's discovery_group. We will configure the discovery_group aws-example dynamically in a later step, so that we can control the Discovery Service's configuration without restarting the Discovery Service.

Discovery Service exposes a configuration parameter - discovery_service.discovery_group - that allows you to group discovered resources into different sets. This parameter is used to prevent Discovery Agents watching different sets of cloud resources from colliding against each other and deleting resources created by another services.

When running multiple Discovery Services, you must ensure that each service is configured with the same discovery_group value if they are watching the same cloud resources or a different value if they are watching different cloud resources.

It is possible to run a mix of configurations in the same Teleport cluster meaning that some Discovery Services can be configured to watch the same cloud resources while others watch different resources. As an example, a 4-agent high availability configuration analyzing data from two different cloud accounts would run with the following configuration.

  • 2 Discovery Services configured with discovery_group: "prod" polling data from Production account.
  • 2 Discovery Services configured with discovery_group: "staging" polling data from Staging account.

Generate a join token

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=text
abcd123-insecure-do-not-use-this

For users with a lot of infrastructure in AWS, or who might create or recreate many instances, consider alternative methods for joining new EC2 instances running Teleport:

Start the Discovery Service

Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Discovery Service.

On the host where you will run the Discovery Service, enable and start Teleport:

sudo systemctl enable teleport
sudo systemctl start teleport

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.service
sudo systemctl enable teleport
sudo systemctl start teleport

You can check the status of the Discovery Service with systemctl status teleport and view its logs with journalctl -fu teleport.

Step 4/8. Discovery group config

Create a file aws-example-discovery-config.yaml and save it on a host where you can use tctl.

Database Type

version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["docdb"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"

Database discovery is not available for DynamoDB.

To register a DynamoDB database with your Teleport cluster, you must configure the database manually via static config or dynamic db resource.

See the database access reference for more information.

version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["elasticache"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"

Database discovery is not available for Keyspaces.

To register a Keyspaces database with your Teleport cluster, you must configure the database manually via static config or dynamic db resource.

See the database access reference for more information.

version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["memorydb"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"
version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["opensearch"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"
version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["rds"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"
version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["rdsproxy"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"
version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["redshift"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"
version: v1
kind: "discovery_config"
metadata:
  name: "example"
spec:
  # Only Discovery services in this discovery_group will use the matchers from
  # this dynamic config.
  discovery_group: aws-example
  aws:
    # Database types. Valid options are:
    # 'docdb' - discovers and registers Amazon DocumentDB databases.
    # 'elasticache' - discovers Amazon ElastiCache Redis databases.
    # 'memorydb' - discovers Amazon MemoryDB Redis databases.
    # 'opensearch' - discovers Amazon OpenSearch Redis databases.
    # 'rds' - discovers Amazon RDS and Aurora databases.
    # 'rdsproxy' - discovers Amazon RDS Proxy databases.
    # 'redshift' - discovers Amazon Redshift databases.
    # 'redshift-serverless' - discovers Amazon Redshift Serverless databases.
  - types: ["redshift-serverless"]
    regions: ["us-east-1"]
    # AWS tags to match where "*" is a wildcard.
    # You can use "*": "*" to match all database resource tags.
    tags:
      "env": "prod" # this example matches only databases tagged with env=prod.
    # Optionally assume an AWS IAM role before calling the AWS API to discover
    # databases.
    assume_role:
      role_arn: "" # "arn:aws:iam::123456789012:role/example-role"
      # Optional AWS external ID that the Database Service will use to assume
      # a role in an external AWS account.
      external_id: "" # "example-external-id"

Create the discovery_config:

tctl create aws-example-discovery-config.yaml

The Discovery Service we configured earlier is in the same discovery_group as this discovery_config and will begin using the discovery_config to discover AWS databases. Once it discovers databases, the Discovery Service will register them as db resources in your Teleport cluster.

A Teleport db resource represents the specification of a database that a Teleport Database Service can then use to provide access to the database. When a Database Service instance matches the db resource via label selectors, it will begin to heartbeat the database by regularly creating short-lived db_server resources in your Teleport cluster. Tools like tsh db ls and tctl db ls will only display db_server resources, i.e. databases that a Database Service instance is providing access to.

Step 5/8. List registered databases

Before we set-up the Database Service to provide access to discovered databases, we should check that the Discovery Service is actually discovering databases.

You can list dynamically registered databases with tctl. The Discovery Service adds the label teleport.dev/origin: cloud to every database it registers with your Teleport cluster.

Verify that the Discovery Service has registered db resources for databases that you expect it to have discovered:

tctl get db

Or check for a specific database:

tctl get db/<database-name>

Refer to Discovery Service troubleshooting if you do not see db resources corresponding to databases that you think should be discovered.

Each discovered database's name will have additional identifying information appended to it to ensure uniqueness. That additional info may include:

  • endpoint type (e.g. "reader" endpoint)
  • matcher type
  • AWS region
  • AWS account ID.

For example, if an RDS Aurora database named "my-postgres" is discovered in AWS account "123456789012" in region us-east-1, it would be named "my-postgres-rds-aurora-us-east-1-123456789012" in Teleport.

A discovered database also has a shorter display name that consists of only the AWS database name and the endpoint type, for example "my-postgres" or "my-postgres-reader". Either the full name or the display name can be used for tctl and tsh commands, but if the display name is ambiguous, then you will have to use the full name.

You can override the database name by applying the TeleportDatabaseName AWS tag to the AWS database resource - this is used as the db name verbatim, i.e. additional identifying information will not be appended to it.

Step 6/8. Database Service IAM permissions

Grant the Database Service access to credentials that it can use to authenticate to AWS.

  • If you are running the Database Service on an EC2 instance, you may use the EC2 Instance Metadata Service method
  • If you are running the Database Service in Kubernetes, you can use IAM Roles for Service Accounts (IRSA)
  • Otherwise, you must use environment variables

Teleport will detect when it is running on an EC2 instance and use the Instance Metadata Service to fetch credentials.

The EC2 instance should be configured to use an EC2 instance profile. For more information, see: Using Instance Profiles.

Refer to IAM Roles for Service Accounts (IRSA) to set up an OIDC provider in AWS and configure an AWS IAM role that allows the pod's service account to assume the role.

Teleport's built-in AWS client reads credentials from the following environment variables:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION

When you start the Database Service, the service reads environment variables from a file at the path /etc/default/teleport. Obtain these credentials from your organization. Ensure that /etc/default/teleport has the following content, replacing the values of each variable:

AWS_ACCESS_KEY_ID=00000000000000000000
AWS_SECRET_ACCESS_KEY=0000000000000000000000000000000000000000
AWS_DEFAULT_REGION=<YOUR_REGION>

Teleport's AWS client loads credentials from different sources in the following order:

  • Environment Variables
  • Shared credentials file
  • Shared configuration file (Teleport always enables shared configuration)
  • EC2 Instance Metadata (credentials only)

While you can provide AWS credentials via a shared credentials file or shared configuration file, you will need to run the Database Service with the AWS_PROFILE environment variable assigned to the name of your profile of choice.

If you have a specific use case that the instructions above do not account for, consult the documentation for the AWS SDK for Go for a detailed description of credential loading behavior.

Create an AWS IAM role for the Database Service and attach the following permissions:

Database Type

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DocumentDBConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        },
        {
            "Sid": "DocumentDBCheckDomainURL",
            "Effect": "Allow",
            "Action": "rds:DescribeDBClusters",
            "Resource": "*"
        }
    ]
}
StatementPurpose
DocumentDBConnectAsIAMRoleAssume an IAM role to connect to a DocumentDB cluster with IAM authentication.
DocumentDBCheckDomainURLValidate a domain's URL if it was auto-discovered by the Discovery Service.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DynamoDBConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        },
        {
            "Sid": "DynamoDBSessionTagging",
            "Effect": "Allow",
            "Action": "sts:TagSession",
            "Resource": [
                "*"
            ]
        }
    ]
}
StatementPurpose
DynamoDBConnectAsIAMRoleAssume an IAM role to forward requests to DynamoDB.
DynamoDBSessionTaggingTag assumed role sessions if tags are specified in the Teleport database configuration under aws.session_tags.

The session tagging permissions are only required if you have configured tags under the aws.session_tags section of your Teleport database configuration.

ElastiCache supports IAM authentication for Redis engine version 7.0 or above. This is the recommended way to configure Teleport access to ElastiCache.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ElastiCacheDescribeUsers",
            "Effect": "Allow",
            "Action": "elasticache:DescribeUsers",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheConnect",
            "Effect": "Allow",
            "Action": "elasticache:Connect",
            "Resource": [
                "arn:aws:elasticache:us-east-2:aws-account-id:replicationgroup:replication-group",
                "arn:aws:elasticache:us-east-2:aws-account-id:user:*"
            ]
        }
    ]
}
StatementPurpose
ElastiCacheDescribeUsersDetermine whether a user is compatible with IAM authentication.
ElastiCacheConnectConnect using IAM authentication.

See Authenticating with IAM for ElastiCache for more information.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "KeyspacesConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        }
    ]
}
StatementPurpose
KeyspacesConnectAsIAMRoleAssume an IAM role to forward requests to Keyspaces.

MemoryDB supports IAM authentication for Redis engine version 7.0 or above. This is the recommended way to configure Teleport access to MemoryDB.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "MemoryDBDescribeUsers",
            "Effect": "Allow",
            "Action": "memorydb:DescribeUsers",
            "Resource": "*"
        },
        {
            "Sid": "MemoryDBConnect",
            "Effect": "Allow",
            "Action": "memorydb:Connect",
            "Resource": [
                "arn:aws:memorydb:us-east-2:aws-account-id:replicationgroup:replication-group",
                "arn:aws:memorydb:us-east-2:aws-account-id:user:*"
            ]
        }
    ]
}
StatementPurpose
MemoryDBDescribeUsersDetermine whether a user is compatible with IAM authentication.
MemoryDBConnectConnect using IAM authentication.

See Authenticating with IAM for MemoryDB for more information.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "OpenSearchCheckDomainURL",
            "Effect": "Allow",
            "Action": "es:DescribeDomains",
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "OpenSearchConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        }
    ]
}
StatementPurpose
OpenSearchCheckDomainURLValidate a domain's URL if it was auto-discovered by the Discovery Service.
OpenSearchConnectAsIAMRoleAssume an IAM role to forward requests to OpenSearch.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSAutoEnableIAMAuth",
            "Effect": "Allow",
            "Action": [
                "rds:ModifyDBCluster",
                "rds:ModifyDBInstance"
            ],
            "Resource": "*"
        },
        {
            "Sid": "RDSConnect",
            "Effect": "Allow",
            "Action": "rds-db:connect",
            "Resource": "*"
        },
        {
            "Sid": "RDSFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBClusters",
                "rds:DescribeDBInstances"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RDSAutoEnableIAMAuthAutomatically enable IAM auth on RDS instances and Aurora clusters.
RDSConnectGenerate an IAM authentication token to connect to a database.
RDSFetchMetadataAutomatically import AWS tags as database labels or find missing information such as the database's AWS region.

The Teleport Database Service uses rds:ModifyDBInstance and rds:ModifyDBCluster to automatically enable IAM authentication on RDS instances and Aurora clusters, respectively. You can omit the RDSAutoEnableIAMAuth permissions if IAM authentication is already enabled on your databases.

The rds-db:connect permission is required to connect to databases. You can reduce the scope of the permission to only allow specific databases, regions, or users. The resource ARN has the following format:

arn:aws:rds-db:{Region}:{AccountID}:dbuser:{ResourceID}/{UserName}

Refer to Creating and using an IAM policy for IAM database access for more information about the rds-db:connect permission grant syntax.

Databases discovered by the Teleport Discovery Service should be registered with complete metadata, so you can also omit the RDSFetchMetadata permissions if all of your AWS databases are being auto-discovered.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSProxyConnect",
            "Effect": "Allow",
            "Action": "rds-db:connect",
            "Resource": "*"
        },
        {
            "Sid": "RDSProxyFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBProxies",
                "rds:DescribeDBProxyEndpoints"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RDSProxyConnectGenerate an IAM authentication token to connect to a database.
RDSProxyFetchMetadataAutomatically import AWS tags as database labels or find missing information such as the database's AWS region.

The rds-db:connect permission is required to connect to databases. You can reduce the scope of the permission to only allow specific databases, regions, or users. The resource ARN has the following format:

arn:aws:rds-db:{Region}:{AccountID}:dbuser:{ResourceID}/{UserName}

Refer to Creating and using an IAM policy for IAM database access for more information about the rds-db:connect permission grant syntax.

Databases discovered by the Teleport Discovery Service should be registered with complete metadata, so you can also omit the RDSProxyFetchMetadata permissions if all of your AWS databases are being auto-discovered.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftConnectAsDBUser",
            "Effect": "Allow",
            "Action": "redshift:GetClusterCredentials",
            "Resource": "*"
        },
        {
            "Sid": "RedshiftConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        },
        {
            "Sid": "RedshiftFetchMetadata",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}
StatementPurpose
RedshiftConnectAsDBUserConnect to a database as an existing database user.
RedshiftConnectAsIAMRoleAssume an IAM role to connect to a database with permissions mapped into the database 1:1 from the role's IAM permissions.
RedshiftFetchMetadataAutomatically import AWS tags as database labels or find missing information such as the database's AWS region.

You can reduce the scope of the RedshiftConnectAsDBUser statement by updating it to only allow specific users, databases, and database groups. The resource ARN you can specify has the following formats:

arn:aws:redshift:{Region}:{AccountID}:dbuser:{ClusterName}/{UserName}arn:aws:redshift:{Region}:{AccountID}:dbname:{ClusterName}/{DatabaseName}arn:aws:redshift:{Region}:{AccountID}:dbgroup:{ClusterName}/{DatabaseGroupName}

See Create an IAM role or user with permissions to call GetClusterCredentials for more information about the redshift:GetClusterCredentials permission grant syntax.

You can authenticate as an existing database user or as an IAM role that will be automatically mapped into the database. The corresponding IAM statement is only required for the method(s) you want to use. If an IAM role names the Database Service's identity as a trusted principal, and both identities are in the same AWS account, then the RedshiftConnectAsIAMRole statement can also be omitted.

Databases discovered by the Teleport Discovery Service should be registered with complete metadata, so you can also omit the RedshiftFetchMetadata permissions if all of your AWS databases are being auto-discovered.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftServerlessConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/{{ dbUserRole }}"
            ]
        },
        {
            "Sid": "RedshiftServerlessFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "redshift-serverless:GetEndpointAccess",
                "redshift-serverless:GetWorkgroup"
            ],
            "Resource": "*"
        }
    ]
}
StatementPurpose
RedshiftServerlessFetchMetadataAutomatically import AWS tags as database labels or find missing information such as the database's AWS region.
RedshiftServerlessConnectAsIAMRoleAssume an IAM role to connect as a database user.

Databases discovered by the Teleport Discovery Service should be registered with complete metadata, so you can also omit the RedshiftServerlessFetchMetadata permissions if all of your AWS databases are being auto-discovered.

Redshift Serverless maps IAM roles to database users. The Teleport Database Service must be able to assume these "access" IAM roles which are granted IAM permissions to generate IAM authentication tokens.

Step 7/8. Deploy the Database Service

Configure database connectivity

Unlike the Discovery Service, the Database Service must have network connectivity to databases to provide access to them for your Teleport cluster. You will need to ensure that several network reachability requirements are met for the Database Service:

  1. The Database Service has a network route to database(s)
  2. The Database Service has a network route to your Teleport cluster
  3. The Database Service security group allows outbound traffic to database(s)
  4. The Database Service security group allows outbound traffic to your Teleport cluster
  5. The database(s) security group(s) allow inbound traffic from the Database Service

In the highly likely case that your databases are deployed in private subnets with strict security group(s) attached to them, you will typically need to deploy a Database Service instance in the same VPC, possibly in the same subnet(s), and with a security group attached to it that the database(s) allow inbound traffic from. The Teleport Database Service will probably need a route to the public internet via an AWS NAT gateway or internet gateway in order to reach your Teleport cluster.

This is not an exhaustive list of network requirements or suggestions, as that will depend on your specific networking setup.

Create a Teleport config file

Create a teleport.yaml config file on the host that will run the Discovery 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
db_service:
  enabled: true
  resources:
    - labels:
        "account-id": "*"
        "region": "us-east-1"
        "teleport.dev/cloud": "AWS"
        "teleport.dev/origin": "cloud"

This config file enables the db_service and configures it to join the Teleport cluster. The section db_service.resources is a list of label selectors. The Database Service will match db resources that have these labels and begin to heartbeat the databases by regularly creating short-lived db_server resources in your Teleport cluster.

In this case, it will match auto-discovered AWS databases in the us-east-1 region from any AWS account ("*" is a wildcard and it can be used as a label key and/or value). You can make it match more specific databases by adjusting the label selectors.

The AWS tags attached to AWS databases are imported as Teleport db labels in addition to some other identifying metadata. Refer to Database Labels Reference for more information about available database labels.

Generate a join token

The Database 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 Database Service:

tctl tokens add --type=db --format=text
abcd123-insecure-do-not-use-this

For users with a lot of infrastructure in AWS, or who might create or recreate many instances, consider alternative methods for joining new EC2 instances running Teleport:

Start the Database Service

Configure the Database Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Database Service.

On the host where you will run the Database Service, enable and start Teleport:

sudo systemctl enable teleport
sudo systemctl start teleport

On the host where you will run the Database Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:

sudo teleport install systemd -o /etc/systemd/system/teleport.service
sudo systemctl enable teleport
sudo systemctl start teleport

You can check the status of the Database Service with systemctl status teleport and view its logs with journalctl -fu teleport.

Step 8/8. List database servers

To confirm that the Database Service is proxying discovered databases, run the following tctl command:

# adjust these comma-separated filtering labels as needed

tctl db ls teleport.dev/origin=cloud,teleport.dev/cloud=AWS,region=us-east-1,account-id="*"

If you do not see the databases that you expected, then refer to Database Service troubleshooting below.

This guide shows you how to set-up AWS database auto-discovery with a Discovery Service and Database Service, but does not cover database user provisioning.

Additional Teleport RBAC configuration and possibly IAM configuration may also be required to connect to the discovered databases via Teleport.

Refer to the appropriate guide in Enroll AWS Databases for information about database user provisioning and configuration.

Next

Troubleshooting

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 labels match the missing database tags or look into the Discovery Service logs for permission errors.

Check that the Discovery Service is running with credentials for the correct AWS account. It can discover resources in another AWS account, but it must be configured to assume a role in the other AWS account if that's the case.

Check if there is more than one Discovery Services running:

tctl inventory status --connected

If you are running multiple Discovery Services, 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: "yes"
  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 a specific guide in Enroll AWS Databases.

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 Troubleshooting Database Access for more general troubleshooting steps.

Additionally, a guide specific to the type of database in Enroll AWS Databases. may have more specific troubleshooting information.