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

For other methods of joining a Teleport process to a cluster, see [Joining Teleport Services to a Cluster](https://goteleport.com/docs/enroll-resources/agents.md).

## How it works

Under the hood, Teleport processes 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.

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

* An Azure Virtual Machine running Linux with the Teleport binary installed. The Virtual Machine must have a [Managed Identity](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) assigned to it.

* One of the following client tools for managing Teleport resources:

  - The `tctl` CLI, which you can install along with Teleport on your workstation ([documentation](https://goteleport.com/docs/installation.md)) on your workstation.
  - [Teleport Terraform provider](https://goteleport.com/docs/zero-trust-access/infrastructure-as-code/terraform-provider.md)
  - [Teleport Kubernetes operator](https://goteleport.com/docs/zero-trust-access/infrastructure-as-code/terraform-provider.md)

## Step 1/5. 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.

**Azure Portal**

To set up a Managed Identity:

1. Navigate to [Virtual machines view](https://portal.azure.com/#view/hubsextension/browseresource/resourcetype/microsoft.compute%2fvirtualmachines) if you're hosting Teleport on an Azure VM, or navigate to [Virtual machine scale sets view](https://portal.azure.com/#view/hubsextension/browseresource/resourcetype/microsoft.compute%2fvirtualmachinescalesets) if you're hosting Teleport on an Azure VMSS.
2. Select the VM or VMSS hosting your Teleport Service.
3. In the right-side panel, click the **Security/Identity** tab.
4. Under the **Identity** section, select the **System assigned** tab.
5. Toggle the **Status** switch to **On**.
6. Click **Save**.

If you're using VMSS and it is configured with manual upgrade mode, you must update the VM instances for the identity changes to take effect:

- Click the **Instances** tab in the right panel.
- Select the VM instances to update.
- Click **Restart**.

**Azure CLI**

To attach a system-assigned identity to a regular VM, run:

```
$ az vm identity assign --resource-group <resource-group> --name <vm-name>
```

To attach a system-assigned identity to an Azure VMSS, run:

```
$ az vmss identity assign --resource-group <resource-group> --name <vmss-name>
```

If you're using VMSS and it is configured with manual upgrade mode, you must update the VM instances for the identity changes to take effect. Run the following command to propagate the identity change:

```
$ az vmss update-instances --resource-group <resource-group> --name <vmss-name> --instance-ids *
```

## Step 2/5. Create the 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. You can create the token with `tctl` as well as the Teleport Terraform provider or Kubernetes operator.

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.

**tctl**

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

```

Run the following command to create the token:

```
$ tctl create -f token.yaml
```

**Terraform**

Add the following resource to your Terraform configuration, replacing values as indicated:

```
resource "teleport_provision_token" "azure-token" {
  version = "v2"
  metadata = {
    name = "azure-token"
  }

  labels = {
    // This label is added on the Teleport side by default
    "teleport.dev/origin" = "dynamic"
  }

  spec = {
    // use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
    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"]
        },
      ]
    }
  }
}

```

**Kubernetes**

Add the following Kubernetes resource manifest, replacing values as indicated:

```
apiVersion: "resources.teleport.dev/v2"
kind: TeleportProvisionToken
metadata:
  name: "azure-token"
  labels:
    # This label is added on the Teleport side by default
    "teleport.dev/origin": "dynamic"
spec:
  # use the minimal set of roles required (e.g. Node, Proxy, App, Kube, DB, WindowsDesktop)
  roles: [Node]
  # set the join method allowed for this token
  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"]

```

## Step 3/5 Install Teleport

Install Teleport on your Azure Linux VM.

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

## Step 4/5. 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 a user-assigned managed identity.
      # Omit this value when using a system-assigned managed identity.
      client_id: 11111111-1111-1111-1111-111111111111
  proxy_server: teleport.example.com:443
ssh_service:
  enabled: true
auth_service:
  enabled: false
proxy_service:
  enabled: false

```

## Step 5/5. 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**

On the host where you will run your Teleport instance, enable and start Teleport:

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

**TAR Archive**

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!
