
Azure database auto-discovery is available starting from Teleport 10.2
. Database
access for Azure PostgreSQL/MySQL flexible servers is available starting from
Teleport 12.0
.
This guide will help you to set up secure access and connect through Teleport to Azure PostgreSQL and MySQL servers.

Prerequisites
-
A running Teleport cluster. For details on how to set this up, see one of our Getting Started guides.
-
The
tctl
admin tool andtsh
client tool version >= 13.0.3.tctl versionTeleport v13.0.3 go1.20
tsh versionTeleport v13.0.3 go1.20
See Installation for details.
-
A running Teleport Enterprise cluster. For details on how to set this up, see our Enterprise Getting Started guide.
-
The Enterprise
tctl
admin tool andtsh
client tool version >= 13.0.3, which you can download by visiting your Teleport account.tctl versionTeleport Enterprise v13.0.3 go1.20
tsh versionTeleport v13.0.3 go1.20
Please use the latest version of Teleport Enterprise documentation.
- Deployed Azure Database for PostgreSQL or MySQL server.
- Azure Active Directory administrative privileges.
- A host, e.g., an Azure VM instance, where you will run the Teleport Database Service.
- Make sure you can connect to Teleport. Log in to your cluster using
tsh
, then usetctl
remotely:tsh login --proxy=teleport.example.com [email protected]tctl statusCluster teleport.example.com
Version 13.0.3
CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
You can run subsequent
tctl
commands in this guide on your local machine.For full privileges, you can also run
tctl
commands on your Auth Service host.
Step 1/5. Install the Teleport Database Service
The Database Service requires a valid auth token to connect to the cluster. Generate
one by running the following command against your Teleport Auth Service and save
it in /tmp/token
on the node that will run the Database Service:
tctl tokens add --type=db
Install Teleport on the host where you will run the Teleport Database Service:
Use the appropriate commands for your environment to install your package.
Teleport Edition
Download Teleport's PGP public key
sudo curl https://apt.releases.teleport.dev/gpg \-o /usr/share/keyrings/teleport-archive-keyring.ascSource variables about OS version
source /etc/os-releaseAdd the Teleport APT repository for v13. You'll need to update this
file for each major release of Teleport.
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] \https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} stable/v13" \| sudo tee /etc/apt/sources.list.d/teleport.list > /dev/nullsudo apt-get updatesudo apt-get install teleport
Source variables about OS version
source /etc/os-releaseAdd the Teleport YUM repository for v13. You'll need to update this
file for each major release of Teleport.
sudo yum-config-manager --add-repo "$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/stable/v13/teleport.repo")"sudo yum install teleportTip: Add /usr/local/bin to path used by sudo (so 'sudo tctl users add' will work as per the docs)
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" > /etc/sudoers.d/secure_path
Source variables about OS version
source /etc/os-releaseAdd the Teleport YUM repository for v13. You'll need to update this
file for each major release of Teleport.
Use the dnf config manager plugin to add the teleport RPM repo
sudo dnf config-manager --add-repo "$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/stable/v13/teleport.repo")"Install teleport
sudo dnf install teleportTip: Add /usr/local/bin to path used by sudo (so 'sudo tctl users add' will work as per the docs)
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" > /etc/sudoers.d/secure_path
In the example commands below, update $SYSTEM_ARCH
with the appropriate
value (amd64
, arm64
, or arm
). All example commands using this variable
will update after one is filled out.
curl https://get.gravitational.com/teleport-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gz.sha256<checksum> <filename>
curl -O https://cdn.teleport.dev/teleport-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzshasum -a 256 teleport-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzVerify that the checksums match
tar -xvf teleport-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzcd teleportsudo ./install
Download Teleport's PGP public key
sudo curl https://apt.releases.teleport.dev/gpg \-o /usr/share/keyrings/teleport-archive-keyring.ascSource variables about OS version
source /etc/os-releaseAdd the Teleport APT repository for v13. You'll need to update this
file for each major release of Teleport.
echo "deb [signed-by=/usr/share/keyrings/teleport-archive-keyring.asc] \https://apt.releases.teleport.dev/${ID?} ${VERSION_CODENAME?} stable/v13" \| sudo tee /etc/apt/sources.list.d/teleport.list > /dev/nullsudo apt-get updatesudo apt-get install teleport-ent
For FedRAMP/FIPS-compliant installations, install the teleport-ent-fips
package instead:
sudo apt-get install teleport-ent-fips
Source variables about OS version
source /etc/os-releaseAdd the Teleport YUM repository for v13. You'll need to update this
file for each major release of Teleport.
sudo yum-config-manager --add-repo "$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/stable/v13/teleport.repo")"sudo yum install teleport-entTip: Add /usr/local/bin to path used by sudo (so 'sudo tctl users add' will work as per the docs)
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" > /etc/sudoers.d/secure_path
For FedRAMP/FIPS-compliant installations, install the teleport-ent-fips
package instead:
sudo yum install teleport-ent-fips
Source variables about OS version
source /etc/os-releaseAdd the Teleport YUM repository for v13. You'll need to update this
file for each major release of Teleport.
Use the dnf config manager plugin to add the teleport RPM repo
sudo dnf config-manager --add-repo "$(rpm --eval "https://yum.releases.teleport.dev/$ID/$VERSION_ID/Teleport/%{_arch}/stable/v13/teleport.repo")"Install teleport
sudo dnf install teleport-entTip: Add /usr/local/bin to path used by sudo (so 'sudo tctl users add' will work as per the docs)
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" > /etc/sudoers.d/secure_path
For FedRAMP/FIPS-compliant installations, install the teleport-ent-fips
package instead:
sudo dnf install teleport-ent-fips
In the example commands below, update $SYSTEM_ARCH
with the appropriate
value (amd64
, arm64
, or arm
). All example commands using this variable
will update after one is filled out.
curl https://get.gravitational.com/teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gz.sha256<checksum> <filename>
curl -O https://cdn.teleport.dev/teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzshasum -a 256 teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzVerify that the checksums match
tar -xvf teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-bin.tar.gzcd teleport-entsudo ./install
For FedRAMP/FIPS-compliant installations of Teleport Enterprise, package URLs will be slightly different:
curl https://get.gravitational.com/teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-fips-bin.tar.gz.sha256<checksum> <filename>
curl -O https://cdn.teleport.dev/teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-fips-bin.tar.gzshasum -a 256 teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-fips-bin.tar.gzVerify that the checksums match
tar -xvf teleport-ent-v13.0.3-linux-$SYSTEM_ARCH-fips-bin.tar.gzcd teleport-entsudo ./install
Please use the latest version of Teleport Enterprise documentation.
Create the Database Service configuration.
-
Specify the region for your database(s) in
--azure-postgres-discovery
. -
Replace the
--proxy
value with your Teleport proxy address or Teleport cloud URI (e.g.mytenant.teleport.sh:443
):teleport db configure create \ -o file \ --proxy=teleport.example.com:443 \ --token=/tmp/token \ --azure-postgres-discovery=eastus
-
Specify the region for your database(s) in
--azure-mysql-discovery
. -
Replace the
--proxy
value with your Teleport proxy address or Teleport cloud URI (e.g.mytenant.teleport.sh:443
):teleport db configure create \ -o file \ --proxy=teleport.example.com:443 \ --token=/tmp/token \ --azure-mysql-discovery=eastus
Run the following command on your Database Service host:
teleport db configure create \ -o file \ --proxy=teleport.example.com:443 \ --token=/tmp/token \ --azure-mysql-discovery=eastus \ --azure-postgres-discovery=eastus
This will create two types
entities in teleport.yaml
, one for each database
type. This is useful if you want different regions, tags, or labels for each
database type.
Alternatively, you can edit teleport.yaml
to include both database types in a
single entry:
db_service:
azure:
- types: ["mysql", "postgres"]
...
This command will generate a Database Service configuration with Azure MySQL/Postgres
database auto-discovery enabled in the eastus
region and place it at the
/etc/teleport.yaml
location.
Create a Teleport role
On your workstation logged in to your Teleport cluster with tsh
, define a new
role to provide access to your Azure database. Create a file called azure-database-role.yaml
with the following content:
version: v6
kind: role
metadata:
name: azure-database-access
spec:
allow:
db_labels:
'engine':
- "Microsoft.DBforMySQL/servers"
- "Microsoft.DBforMySQL/flexibleServers"
- "Microsoft.DBforPostgreSQL/servers"
- "Microsoft.DBforPostgreSQL/flexibleServers"
db_names:
- '*'
db_users:
- teleport
Flag | Description |
---|---|
--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. |
--db-labels | List of labels assigned to the database the user will be able to access. A wildcard entry allows any database. |
Save this file and apply it to your Teleport cluster:
tctl create -f azure-database-role.yamlrole 'azure-database-role.yaml' has been created
Assign the azure-database-access
role to your Teleport user by running the following
commands, depending on whether you authenticate as a local Teleport user or via
the github
, saml
, or oidc
authentication connectors:
Retrieve your local user's configuration resource:
tctl get users/$(tsh status -f json | jq -r '.active.username') > out.yaml
Edit out.yaml
, adding azure-database-access
to the list of existing roles:
roles:
- access
- auditor
- editor
+ - azure-database-access
Apply your changes:
tctl create -f out.yaml
Retrieve your github
configuration resource:
tctl get github/github --with-secrets > github.yaml
Edit github.yaml
, adding azure-database-access
to the
teams_to_roles
section. The team you will map to this role will depend on how
you have designed your organization's RBAC, but it should be the smallest team
possible within your organization. This team must also include your user.
Here is an example:
teams_to_roles:
- organization: octocats
team: admins
roles:
- access
+ - azure-database-access
Apply your changes:
tctl create -f github.yaml
Note the --with-secrets
flag in the tctl get
command. This adds the value of
spec.signing_key_pair.private_key
to github.yaml
. This is a sensitive value,
so take precautions when creating this file and remove it after updating the resource.
Retrieve your saml
configuration resource:
tctl get --with-secrets saml/mysaml > saml.yaml
Edit saml.yaml
, adding azure-database-access
to the
attributes_to_roles
section. The attribute you will map to this role will
depend on how you have designed your organization's RBAC, but it should be the
smallest group possible within your organization. This group must also include
your user.
Here is an example:
attributes_to_roles:
- name: "groups"
value: "my-group"
roles:
- access
+ - azure-database-access
Apply your changes:
tctl create -f saml.yaml
Note the --with-secrets
flag in the tctl get
command. This adds the value of
spec.signing_key_pair.private_key
to saml.yaml
. This is a sensitive value,
so take precautions when creating this file and remove it after updating the resource.
Retrieve your oidc
configuration resource:
tctl get oidc/myoidc --with-secrets > oidc.yaml
Edit oidc.yaml
, adding azure-database-access
to the
claims_to_roles
section. The claim you will map to this role will depend on
how you have designed your organization's RBAC, but it should be the smallest
group possible within your organization. This group must also include your
user.
Here is an example:
claims_to_roles:
- name: "groups"
value: "my-group"
roles:
- access
+ - azure-database-access
Apply your changes:
tctl create -f oidc.yaml
Note the --with-secrets
flag in the tctl get
command. This adds the value of
spec.signing_key_pair.private_key
to oidc.yaml
. This is a sensitive value,
so take precautions when creating this file and remove it after updating the resource.
Log out of your Teleport cluster and log in again to assume the new role.
Step 3/6. Configure Azure service principal
To authenticate with PostgreSQL or MySQL databases, Teleport Database Service needs to obtain access tokens from Azure AD.
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 an Azure AD application (via AD's "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.
Go to the Managed Identities page in your Azure portal and click Create to create a new user-assigned managed identity:

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

Take note of the created identity's Client ID:

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

Attach this identity to all Azure VMs that will be running the Database Service.
Registering the Database Service as Azure AD 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 the the App registrations page of your Azure Active Directory and click on New registration:

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:

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

The Teleport Database Service uses Azure SDK's default credential provider chain to look for credentials. Refer to 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=
Step 4/6. Configure IAM permissions for Teleport
Create a custom role
Teleport needs Azure IAM permissions to discover and register MySQL and PostgreSQL databases. Create a role with assignable scope(s) that include all databases that Teleport should discover. For example:
{
"properties": {
"roleName": "TeleportDiscovery",
"description": "Allows Teleport to discover MySQL and PostgreSQL databases",
"assignableScopes": [
"/subscriptions/11111111-2222-3333-4444-555555555555"
],
"permissions": [
{
"actions": [
"Microsoft.DBforMySQL/servers/read",
"Microsoft.DBforPostgreSQL/servers/read",
"Microsoft.DBforMySQL/flexibleServers/read",
"Microsoft.DBforPostgreSQL/flexibleServers/read"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
]
}
}
This role definition allows Teleport to discover MySQL and PostgreSQL databases, but Teleport only needs permissions for the database types you have. The assignable scopes include a subscription, so the role can be assigned at any resource scope within that subscription, or assigned using the subscription scope itself.
Custom roles, unlike Azure built-in roles, can not have a root assignable scope. The highest assignable scope that can be used in a custom role is subscription scope. Using a management group scope is currently an Azure preview feature, and only allows for a single management group in the "assignableScopes" of a role definition. See Azure RBAC custom roles for more information.
Go to the Subscriptions page and select a subscription.
Click on Access control (IAM) in the subscription and select Add > Add custom role:

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

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 for more information about Azure scopes and creating role assignments.
Step 5/6. Create Azure database users
To let Teleport connect to your Azure database authenticating as a service principal, you need to create Azure AD users authenticated by that principal in the database.
Assign Azure AD administrator
Only the Azure AD administrator for the database can connect to it and create Azure AD users.
Go to your database's Authentication page and set the AD admin using the edit button:

Go to your database's Authentication page and set the AD admin by selecting + Add Azure AD Admins:

Go to your database's Active Directory admin page and set the AD admin using the Set admin button:

Only one Azure user (or group) can be set as an Azure AD admin for the database. If the Azure AD admin is removed from the server, all Azure AD logins will be disabled for the server. Adding a new Azure AD admin from the same tenant will re-enable Azure AD logins. Refer to Use Azure Active Directory for authenticating with PostgreSQL for more information.
Connect to the database as an AD admin
Next, you need to connect to your database as the AD admin user.
Use the Azure az
CLI utility to log in as the user that you set as the AD admin,
fetch the access token and use it as a password when connecting to the database:
az login -u [email protected]TOKEN=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken`PGPASSWORD=$TOKEN psql "host=example.postgres.database.azure.com [email protected] sslmode=require dbname=postgres"
az login -u [email protected]TOKEN=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken`PGPASSWORD=$TOKEN psql "host=example.postgres.database.azure.com [email protected]@instance-name sslmode=require dbname=postgres"
az login -u [email protected]TOKEN=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken`mysql -h example.mysql.database.azure.com -P 3306 -u [email protected] --enable-cleartext-plugin --password=$TOKEN
az login -u [email protected]TOKEN=`az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken`mysql -h example.mysql.database.azure.com -P 3306 -u [email protected]@instance-name --enable-cleartext-plugin --password=$TOKEN
Note that the database username must include @instance-name
suffix with the
name of the Azure database instance you're connecting to.
Create AD users
Once connected to the database as AD admin, create database users for the
service principal that Teleport Database Service will be using. Use Client ID
when using managed identities and Application (client) ID
when using app
registrations:
postgres=> SET aad_validate_oids_in_tenant = off;
SET
postgres=> CREATE ROLE teleport WITH LOGIN PASSWORD '11111111-2222-3333-4444-555555555555' IN ROLE azure_ad_user;
CREATE ROLE
postgres=> SELECT * FROM pgaadauth_create_principal_with_oid('teleport', '11111111-2222-3333-4444-555555555555', 'service', false, false);
-------------------------------------
Created role for teleport
(1 row)
mysql> SET aad_auth_validate_oids_in_tenant = OFF;
mysql> CREATE AADUSER 'teleport' IDENTIFIED BY '11111111-2222-3333-4444-555555555555';
Query OK, 0 rows affected (0.92 sec)
The created user may not have access to anything by default so let's grant it some permissions:
GRANT ALL ON `%`.* TO 'teleport'@'%';
You can create multiple database users identified by the same service principal.
Step 6/6. Connect
Log in to your Teleport cluster. Your Azure database should appear in the list of available databases:
tsh login --proxy=teleport.example.com --user=alicetsh db lsName Description Labels
-------- ------------------- -------
azure-db env=dev
To retrieve credentials for a database and connect to it:
tsh db connect --db-user=teleport azure-db
tsh db connect --db-user=teleport --db-name=postgres azure-db
The appropriate database command-line client (psql
, mysql
) should be
available in the PATH
of the machine you're running tsh db connect
from.
To log out of the database and remove credentials:
tsh db logout azure-db
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
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 5432Connection to server-name.postgres.database.azure.com 5432 port [tcp/postgresql] succeeded!
Next steps
- Learn how to restrict access to certain users and databases.
- View the High Availability (HA) guide.
- Take a look at the YAML configuration reference.
- See the full CLI reference.