Joining Services via Azure Managed Identity
This guide will explain how to use the Azure join method to configure Teleport instances to join your Teleport cluster without sharing any secrets when they are running in an Azure Virtual Machine.
The Azure join method is available to any Teleport process running in an Azure Virtual Machine. Support for joining a cluster with the Proxy Service behind a layer 7 load balancer or reverse proxy is available in Teleport 13.0+.
For other methods of joining a Teleport process to a cluster, see Joining Teleport Services to a Cluster.
Prerequisites
-
A running Teleport cluster version 15.4.22 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.
-
The
tctl
admin tool andtsh
client tool.On Teleport Enterprise, you must use the Enterprise version of
tctl
, which you can download from your Teleport account workspace. Otherwise, visit Installation for instructions on downloadingtctl
andtsh
for Teleport Community Edition.
- An Azure Virtual Machine running Linux with the Teleport binary installed. The Virtual Machine must have a Managed Identity assigned to it with permission to read virtual machine info.
- 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 --user=email@example.com
$ 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/4. Set up a Managed Identity
Every virtual machine hosting a Teleport process using the Azure method to join
your Teleport cluster needs a Managed Identity assigned to it. The identity
requires the Microsoft.Compute/virtualMachines/read
permission so Teleport can
look up the virtual machine. No other permissions are required.
- Manually create identity
- ARM Template
Create a custom role
Enter the name of your Azure resource group in the Azure Portal search box and visit the page for that resource group. On the left navigation sidebar, click the Access control (IAM) tab. In the row of buttons at the top of the Access control (IAM) panel, click Add > Add custom role.
In the Custom role name field, enter teleport-read-vm
.
Click the Permissions tab, then within the Permissions view, click +Add permissions.
Enter Microsoft.Compute/virtualMachines/read
in the search box. Click the
Microsoft Compute box, then enable Read: Get Virtual Machine. Click
Add.
Click Review + create, then Create.
Create an Azure managed identity
Visit the Managed Identities view in Azure Portal.
Click Create.
Under Subscription, Resource group, and Region, choose the ones that your VM belongs to.
In the Name field, enter teleport-azure
.
Click Review + create, then Create.
Once creation finishes, click Go to resource. On the page for the new identity, copy the value for the Client ID so you can use it later in this guide.
Assign the teleport-read-vm
role to the teleport-azure
identity
Enter the name of your Azure resource group in the Azure Portal search box and visit the page for that resource group. On the left navigation sidebar, click the Access control (IAM) tab. In the row of buttons at the top of the Access control (IAM) panel, click Add > Add role assignment.
Within the Add role assignment screen, click teleport-read-vm.
Scroll to the bottom of the screen and click Next.
Within the Members tab, in the Assign access to field, choose Managed identity. Click Select members.
On the right sidebar, find the Managed identity dropdown menu and select
User-assigned managed identity. Choose the teleport-azure
identity you
created earlier.
Click Select, then Review + assign.
Verify that your Role is teleport-read-vm
, the Scope matches your
chosen resource group, and the Members field includes the teleport-azure
managed identity you created earlier.
Click Review + assign again.
Attach an identity to your Azure VM
In the Virtual machines view of Azure Portal, click on the name of the VM you are using to host the Teleport Application Service.
On the right side panel, click the Identity tab, then within the
Identity view, click the User assigned tab. Click +Add, then select
the teleport-azure
identity. Click Add.
Navigate back to Identity tab in the page for your Azure VM. You should see the new identity listed in the User assigned sub-tab:
As part of authentication, Teleport will be able to do anything allowed by the identity. If you use a managed identity other than the one created in this guide, we strongly recommend limiting its permissions and scope.
Create a file named teleport-create-identity.json
and copy the following into
it:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.5.6.12127",
"templateHash": "2227781763411200690"
}
},
"parameters": {
"roleName": {
"type": "string",
"defaultValue": "teleport-read-vm",
"metadata": {
"description": "Friendly name of the role definition"
}
},
"identityName": {
"type": "string",
"defaultValue": "teleport-azure",
"metadata": {
"description": "Name of the managed identity"
}
}
},
"variables": {
"roleDefName": "[guid(resourceGroup().id, string('Microsoft.Compute/virtualMachines/read'))]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleDefinitions",
"apiVersion": "2022-04-01",
"name": "[variables('roleDefName')]",
"properties": {
"roleName": "[parameters('roleName')]",
"description": "A role to allow reading information about Virtual Machines, to be used for Teleport.",
"type": "customRole",
"permissions": [
{
"actions": [
"Microsoft.Compute/virtualMachines/read"
],
"notActions": []
}
],
"assignableScopes": [
"[resourceGroup().id]"
]
}
},
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[parameters('identityName')]",
"apiVersion": "2018-11-30",
"location": "[resourceGroup().location]"
}
],
"outputs": {
"principalID": {
"type": "string",
"value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identityName'))).principalId]"
},
"clientID": {
"type": "string",
"value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('identityName'))).clientId]"
},
"roleName": {
"type": "string",
"value": "[variables('roleDefName')]"
}
}
}
Then run the following commands to create the custom role and managed identity:
$ DEPLOY_OUTPUT=$(az deployment group create \
--resource-group <your-resource-group> \
--template-file teleport-create-identity.json)
$ PRINCIPAL_ID=$(echo $DEPLOY_OUTPUT | jq -r '.properties.outputs.principalID.value')
$ CLIENT_ID=$(echo $DEPLOY_OUTPUT | jq -r '.properties.outputs.principalID.value')
$ ROLE_NAME=$(echo $DEPLOY_OUTPUT | jq -r '.properties.outputs.roleName.value')
Getting a "command not found" error?
This command requires jq
to be installed on your workstation, which you can do
via the jq
download page.
Next, create another file named teleport-assign-identity.json
and copy the
following into it:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.5.6.12127",
"templateHash": "2227781763411200690"
}
},
"parameters": {
"identityName": {
"type": "string",
"defaultValue": "teleport-azure"
},
"principalId": {
"type": "string"
},
"roleName": {
"type": "string"
},
"vmNames": {
"type": "array"
}
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id)]",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', parameters('roleName'))]",
"principalId": "[parameters('principalId')]"
}
},
{
"apiVersion": "2018-06-01",
"type": "Microsoft.Compute/virtualMachines",
"name": "[parameters('vmNames')[copyIndex('vmcopy')]]",
"location": "[resourceGroup().location]",
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"[resourceID('Microsoft.ManagedIdentity/userAssignedIdentities/',parameters('identityName'))]": {}
}
},
"copy": {
"name": "vmcopy",
"count": "[length(parameters('vmNames'))]"
}
}
]
}
Run the following command to assign your custom role to your managed identity and assign the identity to your virtual machines:
$ az deployment group create \
--resource-group <your-resource-group> \
--template-file teleport-assign-identity.json \
-- parameters principalId="$PRINCIPAL_ID" roleName="$ROLE_NAME" \
vmNames='<list-of-vm-names>'
Use the value of CLIENT_ID
in Step 3.
Step 2/4. Create the Azure joining token
Under the hood, Teleport processes will prove that they are running in your Azure subscription by sending a signed attested data document and access token to the Teleport Auth Service. The VM's identity must match an allow rule configured in your Azure joining token.
Create the following token.yaml
with an allow
rule specifying your Azure
subscription and the resource group that your VM's identity must match.
# token.yaml
kind: token
version: v2
metadata:
# the token name is not a secret because instances must prove that they are
# running in your Azure subscription to use this token
name: azure-token
spec:
# use the minimal set of roles required
roles: [Node]
join_method: azure
azure:
allow:
# specify the Azure subscription which Teleport processes may join from
- subscription: 11111111-1111-1111-1111-111111111111
# multiple allow rules are supported
- subscription: 22222222-2222-2222-2222-222222222222
# resource_groups is optional and allows you to restrict the resource group of
# joining Teleport processes
- subscription: 33333333-3333-3333-3333-333333333333
resource_groups: ["group1", "group2"]
The token name azure-token
is just an example and can be any value you want to
use, as long as you use the same value for join_params.token_name
in Step 3.
Run the following command to create the token:
$ tctl create -f token.yaml
Step 3/4. Configure your Teleport process
The Azure join method can be used for Teleport processes running the SSH, Proxy, Kubernetes, Application, Database, or Desktop Service.
Configure your Teleport process with a custom teleport.yaml
file. Use the
join_params
section with token_name
matching your token created in Step 2
and method: azure
as shown in the following example config:
# /etc/teleport.yaml
version: v3
teleport:
join_params:
token_name: azure-token
method: azure
azure:
# client_id is the client ID of the managed identity created in Step 1.
client_id: 11111111-1111-1111-1111-111111111111
proxy_server: teleport.example.com:443
ssh_service:
enabled: yes
auth_service:
enabled: no
proxy_service:
enabled: no
Step 4/4. Launch your Teleport process
Start Teleport on the Azure VM.
Configure your Teleport instance to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed your Teleport instance.
- Package Manager
- TAR Archive
On the host where you will run your Teleport instance, enable and start Teleport:
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
On the host where you will run your Teleport instance, 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 your Teleport instance with systemctl status teleport
and view its logs with journalctl -fu teleport
.
Confirm that your Teleport process is able to connect to and join your cluster. You're all set!