Scaling Privileged Access for Modern Infrastructure: Real-World Insights
Apr 25
Virtual
Register Today
Teleport logoTry For Free
Fork me on GitHub

Teleport

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 in Teleport 12.1+. It 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. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool version >= 15.2.2.

    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 downloading tctl and tsh 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 run tctl commands using your current credentials. tctl is supported on macOS and Linux machines. For example:
    tsh login --proxy=teleport.example.com --user=[email protected]
    tctl status

    Cluster teleport.example.com

    Version 15.2.2

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

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:

IMPORTANT

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')

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.

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!