# 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. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

- 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:

     **Mac**

     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.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-windows-amd64-bin.zip
     Unzip 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.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

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

To install a Teleport Agent on your Linux server:

The recommended installation method is the cluster install script. It will select the correct version, edition, and installation mode for your cluster.

1. Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https\://).

2. Run your cluster's install script:

   ```
   $ curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
   ```

## 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

**Instance Metadata Service**

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](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).

**Kubernetes IRSA**

Refer to [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) 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.

**Environment Variables**

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>

```

Have multiple sources of AWS credentials?

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](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/) 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:

**DocumentDB**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DocumentDBDiscovery",
            "Effect": "Allow",
            "Action": "rds:DescribeDBClusters",
            "Resource": "*"
        }
    ]
}

```

| Statement             | Purpose                              |
| --------------------- | ------------------------------------ |
| `DocumentDBDiscovery` | Discover Amazon DocumentDB Clusters. |

**DynamoDB**

Database discovery is not available for DynamoDB.

Manual database registration?

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](https://goteleport.com/docs/enroll-resources/database-access/reference/configuration.md) for more information.

**ElastiCache**

```
{
    "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": "*"
        }
    ]
}

```

| Statement                  | Purpose                                                                                |
| -------------------------- | -------------------------------------------------------------------------------------- |
| `ElastiCacheDiscovery`     | Discover ElastiCache replication groups.                                               |
| `ElastiCacheFetchMetadata` | Import AWS tags and additional metadata for each database as Teleport database labels. |

**ElastiCache Serverless**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ElastiCacheServerlessDiscovery",
            "Effect": "Allow",
            "Action": "elasticache:DescribeServerlessCaches",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheServerlessFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeSubnets",
                "elasticache:ListTagsForResource"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement                            | Purpose                                                                           |
| ------------------------------------ | --------------------------------------------------------------------------------- |
| `ElastiCacheServerlessDiscovery`     | Discover ElastiCache Serverless caches.                                           |
| `ElastiCacheServerlessFetchMetadata` | Import AWS tags and other metadata for each database as Teleport database labels. |

**Keyspaces**

Database discovery is not available for Keyspaces.

Manual database registration?

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](https://goteleport.com/docs/enroll-resources/database-access/reference/configuration.md) for more information.

**MemoryDB**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "MemoryDBDiscovery",
            "Effect": "Allow",
            "Action": "memorydb:DescribeClusters",
            "Resource": "*"
        },
        {
            "Sid": "MemoryDBFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "memorydb:DescribeSubnetGroups",
                "memorydb:ListTags"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement               | Purpose                                                                                |
| ----------------------- | -------------------------------------------------------------------------------------- |
| `MemoryDBDiscovery`     | Discover MemoryDB databases.                                                           |
| `MemoryDBFetchMetadata` | Import AWS tags and additional metadata for each database as Teleport database labels. |

**Opensearch**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "OpenSearchDiscovery",
            "Effect": "Allow",
            "Action": [
                "es:DescribeDomains",
                "es:ListDomainNames"
            ],
            "Resource": "*"
        },
        {
            "Sid": "OpenSearchFetchMetadata",
            "Effect": "Allow",
            "Action": "es:ListTags",
            "Resource": "*"
        }
    ]
}

```

| Statement                 | Purpose                                                               |
| ------------------------- | --------------------------------------------------------------------- |
| `OpenSearchDiscovery`     | Discover OpenSearch domains.                                          |
| `OpenSearchFetchMetadata` | Import each discovered domain's AWS tags as Teleport database labels. |

**RDS**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSDiscovery",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBClusters",
                "rds:DescribeDBInstances"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement      | Purpose                                     |
| -------------- | ------------------------------------------- |
| `RDSDiscovery` | Discover 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.

**RDS Proxy**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSProxyDiscovery",
            "Effect": "Allow",
            "Action": "rds:DescribeDBProxies",
            "Resource": "*"
        },
        {
            "Sid": "RDSProxyFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBProxyEndpoints",
                "rds:ListTagsForResource"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement               | Purpose                                                                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RDSProxyDiscovery`     | Discover RDS Proxies and register each proxy's default endpoint as a Teleport database.                                                            |
| `RDSProxyFetchMetadata` | Fetch metadata for discovered proxies to import AWS resource tags as Teleport database labels and register custom endpoints as Teleport databases. |

**Redshift**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftDiscovery",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}

```

| Statement           | Purpose                            |
| ------------------- | ---------------------------------- |
| `RedshiftDiscovery` | Discover Amazon Redshift Clusters. |

**Redshift Serverless**

```
{
    "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": "*"
        }
    ]
}

```

| Statement                         | Purpose                                                                                                                                       |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `RedshiftServerlessDiscovery`     | Discover Redshift Serverless Workgroups.                                                                                                      |
| `RedshiftServerlessFetchMetadata` | Fetch 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 Database 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.

---

WARNING

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
```

Alternative methods

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:

- [Configure Teleport to Automatically Enroll EC2 instances](https://goteleport.com/docs/enroll-resources/auto-discovery/servers/ec2-discovery.md)
- [Joining Teleport Services via AWS IAM Role](https://goteleport.com/docs/enroll-resources/agents/aws-iam.md)
- [Joining Teleport Services via AWS EC2 Identity Document](https://goteleport.com/docs/enroll-resources/agents/aws-ec2.md)

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

**Package Manager**

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

```
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

**TAR Archive**

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

**DocumentDB**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**DynamoDB**

Database discovery is not available for DynamoDB.

Manual database registration?

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](https://goteleport.com/docs/enroll-resources/database-access/reference/configuration.md) for more information.

**ElastiCache**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**ElastiCache Serverless**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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-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"

```

**Keyspaces**

Database discovery is not available for Keyspaces.

Manual database registration?

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](https://goteleport.com/docs/enroll-resources/database-access/reference/configuration.md) for more information.

**MemoryDB**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**Opensearch**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**RDS**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**RDS Proxy**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**Redshift**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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"

```

**Redshift Serverless**

Assign aws-example to the name of your discovery group and us-east-1 to the name of an AWS region:

```
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 and Valkey databases.
    # 'elasticache-serverless' - Amazon ElastiCache Serverless Redis or Valkey databases.
    # 'memorydb' - discovers Amazon MemoryDB databases.
    # 'opensearch' - discovers Amazon OpenSearch 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.

---

INFO

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](#discovery-service-troubleshooting) if you do not see `db` resources corresponding to databases that you think should be discovered.

Details

discovered database names

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

**Instance Metadata Service**

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](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).

**Kubernetes IRSA**

Refer to [IAM Roles for Service Accounts (IRSA)](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) 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.

**Environment Variables**

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>

```

Have multiple sources of AWS credentials?

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](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/) for a detailed description of credential loading behavior.

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

**DocumentDB**

Assign aws-account-id to your AWS account ID:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DocumentDBConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/DatabaseUserRole"
            ]
        },
        {
            "Sid": "DocumentDBCheckDomainURL",
            "Effect": "Allow",
            "Action": "rds:DescribeDBClusters",
            "Resource": "*"
        }
    ]
}

```

| Statement                    | Purpose                                                                        |
| ---------------------------- | ------------------------------------------------------------------------------ |
| `DocumentDBConnectAsIAMRole` | Assume an IAM role to connect to a DocumentDB cluster with IAM authentication. |
| `DocumentDBCheckDomainURL`   | Validate a domain's URL if it was auto-discovered by the Discovery Service.    |

**DynamoDB**

Assign aws-account-id to your AWS account ID:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DynamoDBConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/DatabaseUserRole"
            ]
        },
        {
            "Sid": "DynamoDBSessionTagging",
            "Effect": "Allow",
            "Action": "sts:TagSession",
            "Resource": [
                "*"
            ]
        }
    ]
}

```

| Statement                  | Purpose                                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `DynamoDBConnectAsIAMRole` | Assume an IAM role to forward requests to DynamoDB.                                                              |
| `DynamoDBSessionTagging`   | Tag 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**

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

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ElastiCacheFetchMetadata",
            "Effect": "Allow",
            "Action": "elasticache:DescribeReplicationGroups",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheDescribeUsers",
            "Effect": "Allow",
            "Action": "elasticache:DescribeUsers",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheConnect",
            "Effect": "Allow",
            "Action": "elasticache:Connect",
            "Resource": "*"
        }
    ]
}

```

| Statement                  | Purpose                                                                                                         |
| -------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `ElastiCacheFetchMetadata` | Automatically import AWS tags as database labels or find missing information such as the database's AWS region. |
| `ElastiCacheDescribeUsers` | Determine whether a user is compatible with IAM authentication.                                                 |
| `ElastiCacheConnect`       | Connect using IAM authentication.                                                                               |

You can reduce the scope of the `ElastiCacheConnect` statement by updating it to only allow specific ElastiCache clusters and IAM users. The resource ARN you can specify has the following formats:

```
arn:aws:elasticache:{Region}:{AccountID}:replicationgroup:{ReplicationGroup}
arn:aws:elasticache:{Region}:{AccountID}:user:{UserName}
```

See [Authenticating with IAM for ElastiCache](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth-iam.html) for more information.

**ElastiCache Serverless**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ElastiCacheServerlessFetchMetadata",
            "Effect": "Allow",
            "Action": "elasticache:DescribeServerlessCaches",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheServerlessDescribeUsers",
            "Effect": "Allow",
            "Action": "elasticache:DescribeUsers",
            "Resource": "*"
        },
        {
            "Sid": "ElastiCacheServerlessConnect",
            "Effect": "Allow",
            "Action": "elasticache:Connect",
            "Resource": "*"
        }
    ]
}

```

| Statement                            | Purpose                                                         |
| ------------------------------------ | --------------------------------------------------------------- |
| `ElastiCacheServerlessFetchMetadata` | Automatically import AWS metadata about the database.           |
| `ElastiCacheServerlessDescribeUsers` | Determine whether a user is compatible with IAM authentication. |
| `ElastiCacheServerlessConnect`       | Connect using IAM authentication.                               |

Details

You can reduce the scope of the `ElastiCacheServerlessConnect` statement by updating it to only allow specific ElastiCache Serverless caches and IAM users. The resource ARN you can specify has the following formats:

```
arn:aws:elasticache:{Region}:{AccountID}:serverlesscache:{CacheName}
arn:aws:elasticache:{Region}:{AccountID}:user:{UserName}
```

See [Authenticating with IAM for ElastiCache](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth-iam.html) for more information.

**Keyspaces**

Assign aws-account-id to your AWS account ID:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "KeyspacesConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/DatabaseUserRole"
            ]
        }
    ]
}

```

| Statement                   | Purpose                                              |
| --------------------------- | ---------------------------------------------------- |
| `KeyspacesConnectAsIAMRole` | Assume an IAM role to forward requests to Keyspaces. |

**MemoryDB**

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": "MemoryDBFetchMetadata",
            "Effect": "Allow",
            "Action": "memorydb:DescribeClusters",
            "Resource": "*"
        },
        {
            "Sid": "MemoryDBDescribeUsers",
            "Effect": "Allow",
            "Action": "memorydb:DescribeUsers",
            "Resource": "*"
        },
        {
            "Sid": "MemoryDBConnect",
            "Effect": "Allow",
            "Action": "memorydb:Connect",
            "Resource": "*"
        }
    ]
}

```

| Statement               | Purpose                                                                                                         |
| ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `MemoryDBFetchMetadata` | Automatically import AWS tags as database labels or find missing information such as the database's AWS region. |
| `MemoryDBDescribeUsers` | Determine whether a user is compatible with IAM authentication.                                                 |
| `MemoryDBConnect`       | Connect using IAM authentication.                                                                               |

You can reduce the scope of the `MemoryDBConnect` statement by updating it to only allow specific MemoryDB clusters and IAM users. The resource ARN you can specify has the following formats:

```
arn:aws:memorydb:{Region}:{AccountID}:cluster:{ClusterName}
arn:aws:memorydb:{Region}:{AccountID}:user:{UserName}
```

See [Authenticating with IAM for MemoryDB](https://docs.aws.amazon.com/memorydb/latest/devguide/auth-iam.html) for more information.

**Opensearch**

Assign aws-account-id to your AWS account ID:

```
{
    "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/DatabaseUserRole"
            ]
        }
    ]
}

```

| Statement                    | Purpose                                                                     |
| ---------------------------- | --------------------------------------------------------------------------- |
| `OpenSearchCheckDomainURL`   | Validate a domain's URL if it was auto-discovered by the Discovery Service. |
| `OpenSearchConnectAsIAMRole` | Assume an IAM role to forward requests to OpenSearch.                       |

**RDS**

```
{
    "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": "*"
        }
    ]
}

```

| Statement              | Purpose                                                                                                         |
| ---------------------- | --------------------------------------------------------------------------------------------------------------- |
| `RDSAutoEnableIAMAuth` | Automatically enable IAM auth on RDS instances and Aurora clusters.                                             |
| `RDSConnect`           | Generate an IAM authentication token to connect to a database.                                                  |
| `RDSFetchMetadata`     | Automatically 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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html) 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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html) 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.

**RDS Proxy**

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RDSProxyConnect",
            "Effect": "Allow",
            "Action": "rds-db:connect",
            "Resource": "*"
        },
        {
            "Sid": "RDSProxyFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBProxies",
                "rds:DescribeDBProxyEndpoints"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement               | Purpose                                                                                                         |
| ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `RDSProxyConnect`       | Generate an IAM authentication token to connect to a database.                                                  |
| `RDSProxyFetchMetadata` | Automatically 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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html) 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.

**Redshift**

Assign aws-account-id to your AWS account ID:

```
{
    "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/DatabaseUserRole"
            ]
        },
        {
            "Sid": "RedshiftFetchMetadata",
            "Effect": "Allow",
            "Action": "redshift:DescribeClusters",
            "Resource": "*"
        }
    ]
}

```

| Statement                  | Purpose                                                                                                                    |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `RedshiftConnectAsDBUser`  | Connect to a database as an existing database user.                                                                        |
| `RedshiftConnectAsIAMRole` | Assume an IAM role to connect to a database with permissions mapped into the database 1:1 from the role's IAM permissions. |
| `RedshiftFetchMetadata`    | Automatically 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](https://docs.aws.amazon.com/redshift/latest/mgmt/generating-iam-credentials-role-permissions.html) 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.

**Redshift Serverless**

Assign aws-account-id to your AWS account ID:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftServerlessConnectAsIAMRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::aws-account-id:role/DatabaseUserRole"
            ]
        },
        {
            "Sid": "RedshiftServerlessFetchMetadata",
            "Effect": "Allow",
            "Action": [
                "redshift-serverless:GetEndpointAccess",
                "redshift-serverless:GetWorkgroup"
            ],
            "Resource": "*"
        }
    ]
}

```

| Statement                            | Purpose                                                                                                         |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| `RedshiftServerlessFetchMetadata`    | Automatically import AWS tags as database labels or find missing information such as the database's AWS region. |
| `RedshiftServerlessConnectAsIAMRole` | Assume 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).

---

WARNING

Use more specific label selectors when needed so that a Database Service instance only matches databases it can actually reach. Broad selectors can cause unreachable databases to be registered and lead to connection failures.

---

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](https://goteleport.com/docs/enroll-resources/database-access/reference/labels.md) 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
```

Alternative methods

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:

- [Configure Teleport to Automatically Enroll EC2 instances](https://goteleport.com/docs/enroll-resources/auto-discovery/servers/ec2-discovery.md)
- [Joining Teleport Services via AWS IAM Role](https://goteleport.com/docs/enroll-resources/agents/aws-iam.md)
- [Joining Teleport Services via AWS EC2 Identity Document](https://goteleport.com/docs/enroll-resources/agents/aws-ec2.md)

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

**Package Manager**

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

```
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
```

**TAR Archive**

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](#database-service-troubleshooting) below.

---

NOTE

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](https://goteleport.com/docs/enroll-resources/database-access/enrollment/aws.md) for information about database user provisioning and configuration.

---

## Next

- Learn about [Dynamic Registration](https://goteleport.com/docs/enroll-resources/database-access/guides/dynamic-registration.md) by the Teleport Database Service.
- Get started by [connecting](https://goteleport.com/docs/enroll-resources/database-access/guides.md) your database.
- Connect AWS databases in [external AWS accounts](https://goteleport.com/docs/enroll-resources/database-access/enrollment/aws/aws-cross-account.md).
- Refer to the appropriate guide in [Enroll AWS Databases](https://goteleport.com/docs/enroll-resources/database-access/enrollment/aws.md) for information about database user provisioning and configuration.

## 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: 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 a specific guide in [Enroll AWS Databases](https://goteleport.com/docs/enroll-resources/database-access/enrollment/aws.md).

---

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](https://goteleport.com/docs/enroll-resources/database-access/troubleshooting.md) for more general troubleshooting steps.

Additionally, a guide specific to the type of database in [Enroll AWS Databases](https://goteleport.com/docs/enroll-resources/database-access/enrollment/aws.md). may have more specific troubleshooting information.
