Teleport Authentication with Azure Active Directory (AD)
This guide will cover how to configure Microsoft Azure Active Directory to issue credentials to specific groups of users with a SAML Authentication Connector. When used in combination with role-based access control (RBAC), it allows Teleport administrators to define policies like:
- Only members of the "DBA" Azure AD group can connect to PostgreSQL databases.
- Developers must never SSH into production servers.
The following steps configure an example SAML authentication connector matching Azure AD groups with security roles. You can choose to configure other options.
Prerequisites
Before you get started, you’ll need:
- An Azure AD admin account with access to creating non-gallery applications (P2 License).
- To register one or more users in the directory.
- To create at least two security groups in Azure AD and assign one or more users to each group.
- A Teleport role with access to maintaining
saml
resources. This is available in the defaulteditor
role.
-
A running Teleport cluster. If you want to get started with Teleport, sign up for a free trial.
-
The Enterprise
tctl
admin tool andtsh
client tool version >= 15.4.22, which you can download from your Teleport account workspace or the Teleport Installation Downloads page.
- To check that you can connect to your Teleport cluster, sign in with
tsh login
, then verify that you can runtctl
commands using your current credentials.tctl
is supported on macOS and Linux machines. For example:If you can connect to the cluster and run the$ tsh login --proxy=teleport.example.com [email protected]
$ tctl status
# Cluster teleport.example.com
# Version 15.4.22
# CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678tctl status
command, you can use your current credentials to run subsequenttctl
commands from your workstation. If you host your own Teleport cluster, you can also runtctl
commands on the computer that hosts the Teleport Auth Service for full permissions.
Step 1/3. Configure Azure AD
Create an enterprise application
-
Select Azure AD -> Enterprise Applications
-
Select New application
-
Select Create your own application, enter the application name (for example, Teleport), and select Integrate any other application you don't find in the gallery (Non-gallery).
-
Select Properties under Manage and set Assignment required? to No
Click Save before proceeding to the next step.
Configure SAML
-
Select Single sign-on under Manage and choose SAML
-
Edit the Basic SAML Configuration
-
Enter the URL for your Teleport Proxy Service host in the Entity ID and Reply URL fields:
https://mytenant.teleport.sh:443/v1/webapi/saml/acs/ad
Click Save before proceeding to the next step.
-
In SAML Certificates section, copy the App Federation Metadata URL link and save it for use in our Teleport connector configuration:
Edit attributes & claims
-
Click on Unique User Identifier (Name ID) under Required claim.
-
Change the "name identifier format" to Default. Make sure the source attribute is
user.userprincipalname
. -
Add a group claim to make user security groups available to the connector:
-
(optional) Add a claim that transforms the format of the Azure AD username to lower case, in order to use it inside Teleport roles as the
{{external.username}}
property.Set the Source to "Transformation". In the new panel:
-
Set the Transformation value to "Extract()"
-
Set the Attribute name to
user.userprincipalname
. -
Set the Value to
@
. -
Click "Add Transformation" and set the Transformation to
ToLowercase()
.
-
Step 2/3. Create a SAML connector
Now, create a SAML connector resource using tctl
.
$ tctl sso configure saml --preset ad \
--entity-descriptor https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml\?appid\=b8d06e01... \
--attributes-to-roles http://schemas.microsoft.com/ws/2008/06/identity/claims/groups,41c94563...,dev \
--attributes-to-roles http://schemas.microsoft.com/ws/2008/06/identity/claims/groups,8adac502...,access > azure-connector.yaml
In the example above:
--entity-descriptor
specifies the app federation metadata URL saved in the previous step.- Each
--attributes-to-roles
specifies the name of the schema definition for groups, groups, the UUID of an AD group, and the Teleport role that members of the group will be assigned.
The file azure-connector.yaml
should now resemble the following:
kind: saml
metadata:
name: ad
spec:
acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
attributes_to_roles:
- name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
roles:
- dev
value: 41c94563...
- name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
roles:
- access
value: 8adac502...
audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
cert: ""
display: Microsoft
entity_descriptor: ""
entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
issuer: ""
service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
sso: ""
version: v2
With the connector in place on the cluster, you can test it with tctl
:
$ cat azure-connector.yaml | tctl sso test
Your browser should open and log you in to the Teleport cluster using your Azure AD credentials. If there are any problems, the CLI output will help you debug the connector configuration.
To create the connector using the tctl
tool, run the following command:
$ tctl create -f azure-connector.yaml
Step 3/3. Create a new Teleport role
Create a Teleport role resource that will use external username data from the Azure AD connector to determine which Linux logins to allow on a host.
Create a file called dev.yaml
with the following content:
kind: role
version: v5
metadata:
name: dev
spec:
options:
max_session_ttl: 24h
allow:
# only allow login as either ubuntu or the 'windowsaccountname' claim
logins: [ '{{external["http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]}}', ubuntu ]
node_labels:
access: relaxed
Users with the dev
role are only allowed to log in to nodes with the access: relaxed
Teleport label. They can log in as either ubuntu
or a username that
is passed in from the Azure AD connector using the windowsaccountname
attribute.
The login
{{external["http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]}}
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname
attribute and use that field as an allowed login for each user. Since the name
of the attribute contains characters besides letters, numbers, and underscores,
you must use double quotes ("
) and square brackets ([]
) around the name of
the attribute.
Create the role:
$ tctl create dev.yaml
Enable default SAML authentication
Configure Teleport to use SAML authentication as the default instead of the local user database.
Follow the instructions for your Teleport edition:
- Dynamic Resources (All Editions)
- Static Config (Self-Hosted)
Use tctl
to edit the cluster_auth_preference
value:
$ tctl edit cluster_auth_preference
Set the value of spec.type
to saml
:
kind: cluster_auth_preference
metadata:
...
name: cluster-auth-preference
spec:
...
type: saml
...
version: v2
After you save and exit the editor, tctl
will update the resource:
cluster auth preference has been updated
Update /etc/teleport.yaml
in the auth_service
section and restart the teleport
daemon.
auth_service:
authentication:
type: saml
If you need to log in again before configuring your SAML provider, use the flag --auth=local
Token encryption (Optional)
Azure AD's SAML token encryption encrypts the SAML assertions sent to Teleport during SSO redirect.
Token encryption is an Azure Active Directory premium feature and requires a separate license. Since traffic between Azure AD and the Teleport Proxy Service already uses HTTPS, token encryption is optional. To determine whether you should enable token encryption, read the Azure AD documentation.
Set up Teleport token encryption
Start with generating a public/private key and a certificate. You will set up the public certificate with Azure AD and the private key with Teleport.
$ openssl req -nodes -new -x509 -keyout server.key -out server.cer
If you are modifying the existing connector, write the YAML to a file first:
$ tctl get saml --with-secrets > azure-out.yaml
You will notice that Teleport has generated a signing_key_pair
. This key pair
is used to sign responses.
kind: saml
metadata:
name: ad
spec:
acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
attributes_to_roles:
- name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
roles:
- editor
- access
- auditor
value: '*'
audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
cert: ""
display: Microsoft
entity_descriptor:
entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
issuer: https://sts.windows.net/your-id-here/
service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
signing_key_pair:
cert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
private_key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2
Add assertion_key_pair
using the data from server.key
and server.cer
.
kind: saml
metadata:
name: azure-saml
spec:
acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
attributes_to_roles:
- name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
roles:
- editor
- access
- auditor
value: '*'
audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
cert: ""
display: Microsoft
entity_descriptor:
entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
issuer: https://sts.windows.net/your-id-here/
service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
signing_key_pair:
cert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
private_key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2
Make sure to have the same indentation for all lines of the certificate and key, otherwise Teleport will not parse the YAML file.
After your edits, the file will look like this:
kind: saml
metadata:
name: azure-saml
spec:
acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
attributes_to_roles:
- name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
roles:
- editor
- access
- auditor
value: '*'
audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
cert: ""
display: Microsoft
entity_descriptor:
entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
issuer: https://sts.windows.net/your-id-here/
service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
assertion_key_pair:
cert: |
-----BEGIN CERTIFICATE-----
New CERT
-----END CERTIFICATE-----
private_key: |
-----BEGIN RSA PRIVATE KEY-----
New private key
-----END RSA PRIVATE KEY-----
signing_key_pair:
cert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
private_key: |
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2
Update the connector:
$ tctl create -f azure-connector.yaml
Activate token encryption
- Navigate to Token Encryption:
- Import certificate
- Activate it
If the SSO login with this connector is successful, the encryption works.
Troubleshooting
Troubleshooting SSO configuration can be challenging. Usually a Teleport administrator must be able to:
- Be able to see what SAML/OIDC claims and values are getting exported and passed by the SSO provider to Teleport.
- Be able to see how Teleport maps the received claims to role mappings as defined in the connector.
- For self-hosted Teleport Enterprise clusters, ensure that HTTP/TLS certificates are configured properly for both the Teleport Proxy Service and the SSO provider.
If something is not working, we recommend to:
- Double-check the host names, tokens and TCP ports in a connector definition.
Using the Web UI
If you get "access denied" or other login errors, the number one place to check is the Audit Log. Under the Management area you can access it within the Activity tab in the Teleport Web UI.
Example of a user being denied because the role clusteradmin
wasn't set up:
{
"code": "T1001W",
"error": "role clusteradmin is not found",
"event": "user.login",
"method": "oidc",
"success": false,
"time": "2019-06-15T19:38:07Z",
"uid": "cd9e45d0-b68c-43c3-87cf-73c4e0ec37e9"
}
Teleport does not show the expected Nodes
When Teleport's Auth Service receives a request to list Teleport Nodes (e.g., to
display Nodes in the Web UI or via tsh ls
), it only returns the Nodes that the
current user is authorized to view.
For each Node in the user's Teleport cluster, the Auth Service applies the following checks in order and, if one check fails, hides the Node from the user:
- None of the user's roles contain a
deny
rule that matches the Node's labels. - At least one of the user's roles contains an
allow
rule that matches the Node's labels.
If you are not seeing Nodes when expected, make sure that your user's roles
include the appropriate allow
and deny
rules as documented in the
Teleport Access Controls Reference.
When configuring SSO, ensure that the identity provider is populating each user's
traits correctly. For a user to see a Node in Teleport, the result of populating a
template variable in a role's allow.logins
must match at least one of a user's
traits.logins
.
In this example a user will have usernames ubuntu
, debian
and usernames from the SSO trait logins
for Nodes that have a env: dev
label. If the SSO trait username is bob
then the usernames would include ubuntu
, debian
, and bob
.
kind: role
metadata:
name: example-role
spec:
allow:
logins: ['{{external.logins}}', ubuntu, debian]
node_labels:
'env': 'dev'
version: v5
Single sign-on fails with OIDC
When encountering the error message "Failed to verify JWT: oidc: unable to verify JWT signature: no matching keys", it typically indicates a discrepancy between the algorithm used to sign the JWT token and the algorithm(s) supported by the JSON Web Key Set (JWKS). Specifically, the token might be signed with one algorithm, e.g., HS256, while the JWKS only lists keys for a different algorithm. e.g., RS256. This issue predominantly arises when using identity providers that offer extremely low-level functionality.
Here are some things to check:
- Verify the JWT header specifies the correct signing algorithm. This should match one of the algorithms listed in the keys section of the JWKS endpoint response.
- Ensure the JWKS endpoint is returning all relevant public keys. Sometimes key rotation can cause valid keys to be omitted.
To resolve the issue, align the JWT algorithm header with a supported algorithm in the JWKS. Rotate keys if necessary. Verify the JWKS only publishes the active public keys. With proper configuration, the signature should validate successfully.
Failed to process SAML callback
If you encounter a "Failed to process SAML callback" error, take a look at the audit log.
Special characters are not allowed in resource names. Use a name composed only from
alphanumeric characters, hyphens, and dots: /web/users/ops_example.com#EXT#@opsexample.onmicrosoft.com/params
The error above is caused by a Name ID format that is not compatible with Teleport's naming conventions.
Change the Name ID format to use email instead:
Further reading
- Teleport Configuration Resources Reference
- In the Teleport role we illustrated in this guide,
external
traits are replaced with values from the single sign-on provider that the user used to authenticate to Teleport. For full details on how traits work in Teleport roles, see the Teleport Access Controls Reference.