# Database Access with Azure Cache for Redis

Teleport can provide secure access to Azure Cache for Redis via the [Teleport Database Service](https://goteleport.com/docs/enroll-resources/database-access.md). This allows for fine-grained access control through [Teleport's RBAC](https://goteleport.com/docs/enroll-resources/database-access/rbac.md).

In this guide, you will:

1. Configure your Azure Cache for Redis database with Microsoft Entra ID-based authentication.
2. Add the database to your Teleport cluster.
3. Connect to the database via Teleport.

## How it works

The Teleport Database Service proxies traffic between Teleport users and Azure Cache for Redis. When a user connects to the database via Teleport, the Database Service obtains an access token from Microsoft Entra ID and authenticates to Azure as a principal with permissions to manage the database.

**Self-Hosted**

![Enroll Azure Cache for Redis with a Self-Hosted Teleport Cluster](/docs/assets/images/redis-self-hosted-6f21c72d5567168f23f0f842d93f7b9f.png)

**Teleport Enterprise Cloud**

![Enroll Azure Cache for Redis with a Cloud-Hosted Teleport Cluster](/docs/assets/images/redis-cloud-29605f97f546da5d99c52512d0347189.png)

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

* Deployed Azure Redis server or Azure Redis Enterprise cluster.
* Azure administrative privileges to manage service principals and access controls.
* A host, e.g., an Azure VM instance, where you will run the Teleport Database Service.
* `redis-cli` version `6.2` or newer installed and added to your system's `PATH` environment variable.
* To check that you can connect to your Teleport cluster, sign in with `tsh login`, then verify that you can run `tctl` commands using your current credentials. For example, run the following command, assigning teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username:
  ```
  $ tsh login --proxy=teleport.example.com --user=email@example.com
  $ tctl status
  Cluster  teleport.example.com
  Version  19.0.0-dev
  CA pin   sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
  ```
  If you can connect to the cluster and run the `tctl status` command, you can use your current credentials to run subsequent `tctl` commands from your workstation. If you host your own Teleport cluster, you can also run `tctl` commands on the computer that hosts the Teleport Auth Service for full permissions.

## Step 1/5. Create a Teleport user

---

TIP

To modify an existing user to provide access to the Database Service, see [Database Access Controls](https://goteleport.com/docs/enroll-resources/database-access/rbac.md)

---

**Teleport Community Edition**

Create a local Teleport user with the built-in `access` role:

```
$ tctl users add \
  --roles=access \
  --db-users="*" \
  --db-names="*" \
  alice
```

**Teleport Enterprise/Enterprise Cloud**

Create a local Teleport user with the built-in `access` and `requester` roles:

```
$ tctl users add \
  --roles=access,requester \
  --db-users="*" \
  --db-names="*" \
  alice
```

| Flag         | Description                                                                                                                              |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `--roles`    | List of roles to assign to the user. The builtin `access` role allows them to connect to any database server registered with Teleport.   |
| `--db-users` | List of database usernames the user will be allowed to use when connecting to the databases. A wildcard allows any user.                 |
| `--db-names` | List of logical databases (aka schemas) the user will be allowed to connect to within a database server. A wildcard allows any database. |

---

WARNING

Database names are only enforced for PostgreSQL, MongoDB, and Cloud Spanner databases.

---

For more detailed information about database access controls and how to restrict access see [RBAC](https://goteleport.com/docs/enroll-resources/database-access/rbac.md) documentation.

## Step 2/5. Create a Database Service configuration

Install Teleport on the host where you will run the Teleport Database Service:

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

Create the Database Service configuration, specifying a region like this:

**Self-Hosted**

```
$ sudo teleport db configure create \
  -o file \
  --proxy=tele.example.com:443 \
  --token=/tmp/token \
  --azure-redis-discovery=eastus
```

**Teleport Enterprise Cloud**

```
$ sudo teleport db configure create \
  -o file \
  --proxy=teleport.example.com:443 \
  --token=/tmp/token \
  --azure-redis-discovery=eastus
```

The command will generate a Database Service configuration with Azure Cache for Redis auto-discovery enabled in the `eastus` region and place it at the `/etc/teleport.yaml` location.

---

TIP

Use `--azure-redis-discovery=*` to discover databases in all regions. In addition to the region, you can optionally specify `--azure-resource-group=<resource-group-name>`, `--azure-subscription=<subscription-id>`, or `--labels=<key>=<value>` to further customize the scopes of the auto-discovery.

---

## Step 3/5. Configure IAM permissions for Teleport

The Teleport Database Service needs Azure IAM permissions to:

- Discover and register Azure Cache for Redis databases.
- Retrieve Redis access keys to authenticate with the databases.

### Configure an Azure service principal

There are a couple of ways for the Teleport Database Service to access Azure resources:

- The Database Service can run on an Azure VM with attached managed identity. This is the recommended way of deploying the Database Service in production since it eliminates the need to manage Azure credentials.
- The Database Service can be registered as a Microsoft Entra ID application (via "App registrations") and configured with its credentials. This is only recommended for development and testing purposes since it requires Azure credentials to be present in the Database Service's environment.

**Using managed identity**

Go to the [Managed Identities](https://portal.azure.com/#browse/microsoft.managedidentity%2fuserassignedidentities) page in your Azure portal and click *Create* to create a new user-assigned managed identity:

![Managed identities](/docs/assets/images/managed-identities@2x-db5917e6ecdac0bed024d29bb9aa963d.png)

Pick a name and resource group for the new identity and create it:

![New identity](/docs/assets/images/new-identity-174be1add2247ac946b5d4961e3aa597.png)

Take note of the created identity's *Client ID*:

![Created identity](/docs/assets/images/created-identity-c26a469f21613027ef899b1b6674e74b.png)

Next, navigate to the Azure VM that will run your Database Service instance and add the identity you've just created to it:

![VM identity](/docs/assets/images/vm-identity-8438ee8159c2272640d9c5ec50706653.png)

Attach this identity to all Azure VMs that will be running the Database Service.

**Using app registrations**

---

NOTE

Registering the Database Service as a Microsoft Entra ID application is suitable for test and development scenarios, or if your Database Service does not run on an Azure VM. For production scenarios prefer to use the managed identity approach.

---

Go to the [App registrations](https://portal.azure.com/#blade/microsoft_aad_iam/activedirectorymenublade/registeredapps) page of Microsoft Entra ID and click on *New registration*:

![App registrations](/docs/assets/images/app-registrations@2x-a69dc84c4caccb1152df850ea6590a1e.png)

Pick a name (e.g. *DatabaseService*) and register a new application. Once the app has been created, take note of its *Application (client) ID* and click on *Add a certificate or secret*:

![Registered app](/docs/assets/images/registered-app@2x-17343162e785824c8c15205d6cf97b6f.png)

Create a new client secret that the Database Service agent will use to authenticate with the Azure API:

![Registered app secrets](/docs/assets/images/registered-app-secrets@2x-3e754c49f06eeaf6c14af3b9d5067e67.png)

The Teleport Database Service uses Azure SDK's default credential provider chain to look for credentials. Refer to [Azure SDK Authorization](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization) to pick a method suitable for your use-case. For example, to use environment-based authentication with a client secret, the Database Service should have the following environment variables set:

```
export AZURE_TENANT_ID=
export AZURE_CLIENT_ID=
export AZURE_CLIENT_SECRET=
```

### Create a custom role

Teleport requires `<resource-type>/read` permissions for discovery and `<resource-type>/listKeys/action` permissions for authentication with the Redis servers, but Teleport only needs permissions for the resource types you have.

Here is a sample role definition allowing Teleport to read and list keys for both Azure Redis and Azure Redis Enterprise:

```
{
    "properties": {
        "roleName": "TeleportDiscovery",
        "description": "Allows Teleport to discover Azure Cache For Redis databases and list keys",
        "assignableScopes": [
            "/subscriptions/11111111-2222-3333-4444-555555555555"
        ],
        "permissions": [
            {
                "actions": [
                    "Microsoft.Cache/redis/read",
                    "Microsoft.Cache/redis/listKeys/action",
                    "Microsoft.Cache/redisEnterprise/read",
                    "Microsoft.Cache/redisEnterprise/databases/read",
                    "Microsoft.Cache/redisEnterprise/databases/listKeys/action"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            }
        ]
    }
}

```

The `assignableScopes` field above includes a subscription `/subscriptions/<subscription>`, allowing the role to be assigned at any resource scope within that subscription or the subscription scope itself. If you want to further limit the `assignableScopes`, you can use a resource group `/subscriptions/<subscription>/resourceGroups/<group>` or a management group `/providers/Microsoft.Management/managementGroups/<group>` instead.

Now go to the [Subscriptions](https://portal.azure.com/#view/microsoft_azure_billing/subscriptionsblade) page and select a subscription.

Click on *Access control (IAM)* in the subscription and select *Add > Add custom role*: ![IAM custom role](/docs/assets/images/add-custom-role@2x-9b486170e269494f0a84ad7af362a346.png)

In the custom role creation page, click the *JSON* tab and click *Edit*, then paste the JSON example and replace the subscription in `assignableScopes` with your own subscription id: ![Create JSON role](/docs/assets/images/redis-create-role-from-json-1b64d97398f21d5213be588a9d867d7a.png)

### Create a role assignment for the Teleport Database Service principal

To grant Teleport permissions, the custom role you created must be assigned to the Teleport service principal - either the managed identity or the app registration you created earlier.

Navigate to the resource scope where you want to make the role assignment. Click *Access control (IAM)* and select *Add > Add role assignment*. Choose the custom role you created as the role and the Teleport service principal as a member.

![Assign role](/docs/assets/images/create-role-assignment@2x-4d66bbc72319151aed2fa0e7cbd4bf2d.png)

---

AZURE ROLE ASSIGNMENTS

The role assignment should be at a high enough scope to allow the Teleport Database Service to discover all matching databases. See [Identify the needed scope](https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-steps#step-3-identify-the-needed-scope) for more information about Azure scopes and creating role assignments.

---

## Step 4/5. Start the Database Service

Configure the Teleport 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 Teleport Database Service.

**Package Manager**

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

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

**TAR Archive**

On the host where you will run the Teleport 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 Teleport Database Service with `systemctl status teleport` and view its logs with `journalctl -fu teleport`.

## Step 5/5. Connect

Log in to your Teleport cluster. Your Azure Cache for Redis databases should appear in the list of available databases:

**Self-Hosted**

```
$ tsh login --proxy=teleport.example.com --user=alice
$ tsh db ls
Name                      Description                              Allowed Users Labels  Connect 
------------------------- ---------------------------------------- ------------- ------- ------- 
my-azure-redis            Azure Redis server in East US            [*]           ...
my-azure-redis-enterprise Azure Redis Enterprise server in East US [*]           ...
```

**Teleport Enterprise Cloud**

```
$ tsh login --proxy=mytenant.teleport.sh --user=alice
$ tsh db ls
Name                      Description                              Allowed Users Labels  Connect 
------------------------- ---------------------------------------- ------------- ------- ------- 
my-azure-redis            Azure Redis server in East US            [*]           ...
my-azure-redis-enterprise Azure Redis Enterprise server in East US [*]           ...
```

---

OVERRIDE DEFAULT DATABASE NAME

By default, Teleport uses the name of the Azure Cache for Redis resource as the database name. You can override the database name by applying the `TeleportDatabaseName` Azure tag to the resource. The value of the tag will be used as the database name.

---

To retrieve credentials for a database and connect to it:

```
$ tsh db connect my-azure-redis
```

Note that the Teleport Database Service will retrieve the access key and authenticate with the Redis server on the backend automatically. Therefore, the `AUTH <access-key>` command is **not required** here once connected.

To log out of the database and remove credentials:

```
$ tsh db logout my-azure-redis
```

## Troubleshooting

### No credential providers error

If you see the error `DefaultAzureCredential: failed to acquire a token.` in Database Service logs then Teleport is not detecting the required credentials to connect to the Azure SDK. Check whether the credentials have been applied in the machine running the Teleport Database Service and restart the Teleport Database Service. Refer to [Azure SDK Authorization](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization) for more information.

### Timeout errors

The Teleport Database Service needs connectivity to your database endpoints. That may require enabling inbound traffic on the database from the Database Service on the same VPC or routing rules from another VPC. Using the `nc` program you can verify connections to databases:

```
$ nc -zv server-name.postgres.database.azure.com 5432
Connection to server-name.postgres.database.azure.com 5432 port [tcp/postgresql] succeeded!
```

## Next steps

- Learn how to [restrict access](https://goteleport.com/docs/enroll-resources/database-access/rbac.md) to certain users and databases.

* View the [High Availability (HA)](https://goteleport.com/docs/enroll-resources/agents/high-availability.md) guide.

- Take a look at the YAML configuration [reference](https://goteleport.com/docs/enroll-resources/database-access/reference/configuration.md).

* See the full CLI [reference](https://goteleport.com/docs/enroll-resources/database-access/reference/cli.md).

## Further reading

- [Understand Azure Role Definitions - AssignableScopes](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-definitions#assignablescopes)
- [Azure RBAC custom roles](https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles)
