# Protect Azure CLIs and APIs with Teleport

You can use Teleport to manage access to CLI tools that interact with Azure's APIs. This lets you control access to your infrastructure's management APIs using the same RBAC system that you use to protect your infrastructure itself.

In this guide, you will:

1. Create an Azure managed identity for user access and attach it to your VM.
2. Deploy the Teleport Application Service with an Azure app in your Teleport cluster.
3. Assume the managed identity and run `az` commands via `tsh`.

## How it works

The Teleport Application Service installed on an Azure VM uses managed identities to obtain authentication tokens from Azure. When a user authenticates to Teleport, they can assume one of the respective user-assigned managed identities to execute Azure CLI commands.

You can configure which Teleport users or roles have access to specific Azure identities, giving you control over who can obtain credentials for different levels of access to Azure CLIs.

The Teleport Application Service connects to the Teleport Proxy Service over a reverse tunnel, so you can run the Application Service in a private network and prevent unauthorized access to your organization's Azure identities.

Alternatively, you can use the [Teleport SAML IdP](https://goteleport.com/docs/identity-governance/idps/usage/saml-microsoft-entra-external-id.md)-based integration to manage access to Azure Portal and CLI applications. In this approach, users [interactively sign in](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) to Azure portal and CLI tools, and Azure services tag audit logs on behalf of Teleport user account, providing more visibility into how Teleport users are interacting with Azure. It is also the only supported method to manage access to the Azure portal.

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

* The `az` CLI tool installed on your workstation. Teleport's `tsh` client uses the `az` binary to execute commands. See the [Azure documentation](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) for how to install the `az` CLI on your operating system.

* An Azure VM where you will run the Teleport Application Service. The Azure VM must be running a Linux distribution.

  ---

  AZURE KUBERNETES SERVICE (AKS)

  Note that this guide is also applicable to Azure Kubernetes Service (AKS) deployment with Microsoft Entra pod-managed identities enabled. However, the pod-managed identities feature will be deprecated in September 2024.

  For running Teleport Application Service in AKS with Microsoft Entra Workload ID, see [Azure CLI Access on AKS with Workload ID](https://goteleport.com/docs/enroll-resources/application-access/cloud-apis/azure-aks-workload-id.md).

  ---

* The ability to create a user-assigned Azure managed identity and attach it to your VM. Azure requires three role assignments in your Azure account in order to do this: Managed Identity Contributor, Managed Identity Operator, and Virtual Machine Contributor.

  ---

  USING EXISTING IDENTITIES

  In this guide, we will create a user-assigned managed identity to demonstrate Azure CLI access with Teleport.

  If you have another identity you would like Azure CLI users to assume via Teleport, you can use that instead. In this case, you will not need the Managed Identity Contributor role assignment.

  ---

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

  For example, run the following command, assigning teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username:

  ```
  $ tsh login --proxy=teleport.example.com --user=email@example.com
  $ tctl status
  Cluster  teleport.example.com
  Version  18.7.3
  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. Grant an identity to your VM

In this step, we will create an Azure managed identity and assign it to your Azure VM. The identity we will create will be called `teleport-azure`, and will have permissions to view resources in your Azure account.

You can enable Teleport to grant access to Azure CLIs under any Azure identity. If you have another one you intend to use, you can skip the creation of a new identity.

### Create an Azure managed identity

Visit the [Managed Identities](https://portal.azure.com/#view/hubsextension/browseresource/resourcetype/microsoft.managedidentity%2fuserassignedidentities) 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`.

![Creating an Azure managed
identity](/docs/assets/images/create-identity-971c43f09067078ca10210b3f6e0f98a.png)

Click **Review + create**, then **Create**.

Once creation finishes, click **Go to resource**. On the page for the new identity, click **JSON View**. At the top of the right sidebar, you will see a field called **Resource ID** with a value resembling the following:

```
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/teleport-azure

```

Copy the URI of this identity so you can use it later in this guide.

### Allow the `teleport-azure` identity to view resources

Once you create an Azure identity, authorize it to access resources in your account. In this case, we will authorize your new Azure identity to view resources in its resource group.

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 **Reader**, a built-in role with view-only access to resources.

![Add a role
assignment](/docs/assets/images/add-role-assignment-1e84eea9cf383111f9d36c6af355947f.png)

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.

![Select managed
identities](/docs/assets/images/select-managed-identities-7116e647a05b33040cf817c1f8349b55.png)

Click **Select**, then **Review + assign**.

Verify that your **Role** is "Reader", 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

Now that you have created a managed identity and assigned it a role, attach the identity to your Azure VM so the Teleport Application Service can assume the identity in order to proxy Azure CLI traffic.

In the [Virtual machines view](https://portal.azure.com/#view/hubsextension/browseresource/resourcetype/microsoft.compute%2fvirtualmachines) 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**.

![Add an identity to a
VM](/docs/assets/images/vm-identity-6f6ea73d08ad47d618bdcfb030a1fee2.png)

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:

![Verifying that you added the
identity](/docs/assets/images/verify-id-358e2a026ffddc22128f929743e8f2f8.png)

## Step 2/4. Deploy the Teleport Application Service

In this step, you will run the Teleport Application Service on the Azure VM you assigned the `teleport-azure` identity to.

### Get a join token

Establish trust between your Teleport cluster and your new Application Service instance by creating a join token:

```
$ tctl tokens add --type=app --ttl=1h --format=text
abcd123-insecure-do-not-use-this
```

Assign join-token to your token and, on the host where you will install the Teleport Application Service, run the following command to create a file called `/tmp/token` that consists only of your token:

```
$ echo join-token | sudo tee /tmp/token
```

### Install the Teleport Application Service

Run the following commands on the host where you will install the Teleport Application Service:

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

### Configure the Teleport Application Service

On the host where you will run the Teleport Application Service, create a file at `/etc/teleport.yaml` with the following content:

```
version: v3
teleport:
  join_params:
    token_name: "/tmp/token"
    method: token
  proxy_server: "teleport.example.com:443"
auth_service:
  enabled: false
proxy_service:
  enabled: false
ssh_service:
  enabled: false
app_service:
  enabled: true
  apps:
  - name: azure-cli
    cloud: Azure

```

Edit `/etc/teleport.yaml` to replace `teleport.example.com:443` with the host and port of your Teleport Proxy Service or Teleport Cloud tenant, e.g., `mytenant.teleport.sh:443`.

The `app_service` field configures the Teleport Application Service. Each item within `app_service.apps` is an application configuration.

In this example, we have enabled Azure CLI access by setting `cloud` to `Azure`. With this setting configured, the Application Service will proxy user commands from Azure CLIs by requesting access to Azure's APIs under the user's chosen identity, which works as long as the identity is one of the ones attached to the Application Service host.

### Run the Teleport Application Service

Configure the Teleport Application Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Teleport Application Service.

**Package Manager**

On the host where you will run the Teleport Application Service, enable and start Teleport:

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

**TAR Archive**

On the host where you will run the Teleport Application Service, 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 the Teleport Application Service with `systemctl status teleport` and view its logs with `journalctl -fu teleport`.

## Step 3/4. Enable your user to access Azure CLIs

The next step is to authorize your Teleport user to assume an Azure identity and execute Azure CLI commands via Teleport. You will protect access to this identity using Teleport's RBAC system, where a user's roles determine which Azure managed identities (if any) they can access.

There are two approaches you can take to authorize users to access Azure identities.

| Approach    | Description                                                                                                               | Supported User Types            |
| ----------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| **Dynamic** | A Teleport role includes a template variable that grants a user access to all Azure identities assigned directly to them. | Local users, OIDC, SAML         |
| **Static**  | A Teleport role explicitly specifies the Azure identities a user is allowed to assume.                                    | Local users, OIDC, SAML, GitHub |

---

TIP

We recommend using the dynamic approach, since it scales well as you add Azure identities to your account. If you have configured a Teleport Community Edition cluster to authenticate users using GitHub SSO, you must use the static approach, as OAuth-based GitHub applications do not support custom claims.

---

### Dynamic identities

If you are using the dynamic approach, the approach you choose depends on whether your Teleport user is a local user or an SSO user:

**Local Users**

Create a file called `azure-cli-access.yaml` with the following content:

```
kind: role
version: v5
metadata:
  name: azure-cli-access
spec:
  allow:
    app_labels:
      '*': '*'
    azure_identities:
      - '{{internal.azure_identities}}'

```

When a user with the `azure-cli-access` role authenticates to an Azure CLI via Teleport, the Teleport Auth Service populates the `{{internal.azure_identities}}` template variable with any Azure identities you have assigned to the user.

Assign the `teleport-azure` identity to your Teleport user by running the following command, assigning teleport-user to your Teleport username and pasting in the URI of the Azure identity you copied earlier as the value of azure-identity-uri:

```
$ tctl users update teleport-user \
--set-azure-identities azure-identity-uri
```

This command uses the `--set-azure-identities` flag to add Azure identities to a user. You can assign `--set-azure-identities` to multiple identity URIs, separated by commas.

The identity URIs are Azure resource IDs in the following format:

```
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ManagedIdentity/userAssignedIdentities/IDENTITY_NAME

```

Create the role:

```
$ tctl create -f azure-cli-access.yaml
```

---

TIP

You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

---

**SAML/OIDC Connectors**

In your identity provider, define a custom SAML attribute or OIDC claim called `azure_identities`. Each user's `azure_identities` attribute or claim must be a list of Azure identity URIs, using the following format:

```
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/RESOURCE_GROUP_NAME/providers/Microsoft.ManagedIdentity/userAssignedIdentities/IDENTITY_NAME

```

Create a file called `azure-cli-access.yaml` with the following content:

```
kind: role
version: v5
metadata:
  name: azure-cli-access
spec:
  allow:
    app_labels:
      '*': '*'
    azure_identities:
      - '{{external.azure_identities}}'

```

When a user with the `azure-cli-access` role authenticates to an Azure CLI via Teleport, the Teleport Auth Service populates the `{{external.azure_identities}}` template variable with any Azure identities you have assigned to the user.

Create the role:

```
$ tctl create -f azure-cli-access.yaml
```

---

TIP

You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

---

### Static identities

If you are using static identities, define a role with access to specific Azure identities, which means that Teleport users who assume this role can use those (and only those) identities to execute commands via an Azure CLI.

Create a file called `azure-cli-access.yaml` with the following content:

```
kind: role
version: v5
metadata:
  name: azure-cli-access
spec:
  allow:
    app_labels:
      '*': '*'
    azure_identities:
      - /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/teleport-azure

```

Edit the identity URI in the `azure_identities` field to match the one you copied in Step 1.

This role grants a user access to any Teleport-registered application, such as the `azure-cli` application we defined earlier, and allows that user to assume the `teleport-azure` identity you created earlier.

Create the role:

```
$ tctl create -f azure-cli-access.yaml
```

---

TIP

You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

---

Denying access to Azure identities

You can define a Teleport role that denies a user access to one or more Azure identities. To do so, assign values to the `azure_identities` field within the `spec.deny` section of a `role` resource.

For example, this role denies the user access to all Azure identities:

```
kind: role
version: v5
metadata:
  name: "no-azure-identities"
spec:
  allow:
    app_labels:
      '*': '*'
  deny:
    azure_identities:
      - '*'

```

The `no-azure-identities` role enables the user to access all registered applications, but makes use of the wildcard character (`*`) within the `deny.azure_identities` field to prevent the user from assuming any Azure identity.

Unlike values of `allow.azure_identities`, values of `deny.azure_identities` can include wildcard expressions in addition to the URIs of specific Azure identities.

The Teleport Auth Service gives `deny` rules precedence over `allow` rules when evaluating a user's roles.

Assign the `azure-cli-access` role to your Teleport user by running the appropriate commands for your authentication provider:

**Local User**

1. Retrieve your local user's roles as a comma-separated list:

   ```
   $ ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")')
   ```

2. Edit your local user to add the new role:

   ```
   $ tctl users update $(tsh status -f json | jq -r '.active.username') \
     --set-roles "${ROLES?},azure-cli-access"
   ```

3. Sign out of the Teleport cluster and sign in again to assume the new role.

**GitHub**

1. Open your `github` authentication connector in a text editor:

   ```
   $ tctl edit github/github
   ```

2. Edit the `github` connector, adding `azure-cli-access` to the `teams_to_roles` section.

   The team you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the team must include your user account and should be the smallest team possible within your organization.

   Here is an example:

   ```
     teams_to_roles:
       - organization: octocats
         team: admins
         roles:
           - access
   +       - azure-cli-access

   ```

3. Apply your changes by saving and closing the file in your editor.

4. Sign out of the Teleport cluster and sign in again to assume the new role.

**SAML**

1. Retrieve your `saml` configuration resource:

   ```
   $ tctl get --with-secrets saml/mysaml > saml.yaml
   ```

   Note that the `--with-secrets` flag adds the value of `spec.signing_key_pair.private_key` to the `saml.yaml` file. Because this key contains a sensitive value, you should remove the saml.yaml file immediately after updating the resource.

2. Edit `saml.yaml`, adding `azure-cli-access` to the `attributes_to_roles` section.

   The attribute you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

   Here is an example:

   ```
     attributes_to_roles:
       - name: "groups"
         value: "my-group"
         roles:
           - access
   +       - azure-cli-access

   ```

3. Apply your changes:

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

4. Sign out of the Teleport cluster and sign in again to assume the new role.

**OIDC**

1. Retrieve your `oidc` configuration resource:

   ```
   $ tctl get oidc/myoidc --with-secrets > oidc.yaml
   ```

   Note that the `--with-secrets` flag adds the value of `spec.signing_key_pair.private_key` to the `oidc.yaml` file. Because this key contains a sensitive value, you should remove the oidc.yaml file immediately after updating the resource.

2. Edit `oidc.yaml`, adding `azure-cli-access` to the `claims_to_roles` section.

   The claim you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

   Here is an example:

   ```
     claims_to_roles:
       - name: "groups"
         value: "my-group"
         roles:
           - access
   +       - azure-cli-access

   ```

3. Apply your changes:

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

4. Sign out of the Teleport cluster and sign in again to assume the new role.

## Step 4/4. Use Azure CLIs with Teleport

Now that you have authorized your Teleport user to assume the `teleport-azure` identity, you can use Teleport to authenticate to Azure's APIs and execute commands against it via the `az` CLI.

### List your Azure CLI application

Verify that your Teleport user can see the `azure-cli` application you registered earlier:

```
$ tsh apps ls
Application Description Type Public Address                 Labels
----------- ----------- ---- ------------------------------ -------------------
azure-cli               HTTP azure-cli.teleport.example.com teleport.dev/origin
```

### Log in to use an Azure CLI

Log in to the application, specifying that you would like to assume the `teleport-azure` identity:

```
$ tsh apps login azure-cli --azure-identity teleport-azure
```

This command validates the value of the `--azure-identity` flag against the ones the user is authorized to assume. The value of the flag can either be the full URI of the identity (e.g., the URI you copied earlier in this guide) or the name of the identity, e.g., `teleport-azure`.

A user can omit the `--azure-identity` flag if they are only authorized to access a single Azure identity, but otherwise not including the `--azure-identity` flag will result in an error.

If the command succeeds, you will see information about the user's chosen Azure identity similar to the following:

```
[
  {
    "environmentName": "AzureCloud",
    "homeTenantId": "00000000-0000-0000-0000-000000000000",
    "id": "00000000-0000-0000-0000-000000000000",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Microsoft Azure Sponsorship",
    "state": "Enabled",
    "tenantId": "00000000-0000-0000-0000-000000000000",
    "user": {
      "assignedIdentityInfo": "MSIResource-/subscriptions/0000000000000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/teleport-azure",
      "name": "userAssignedIdentity",
      "type": "servicePrincipal"
    }
  }
]

Logged into Azure app "azure-cli".
Your identity: /subscriptions/0000000000000-0000-0000-000000000000/resourceGroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/teleport-azure
Example Azure CLI command: tsh az vm list

```

### Execute Azure CLI commands

At this point, you can run `az` commands using the Teleport Application Service by prefixing them with `tsh`. To list VMs running in your Azure resource group, for example, run the following command:

```
$ tsh az vm list
```

---

TIP

If you're not seeing the expected VMs at this point, double-check that your Azure managed identity is assigned the "Reader" role at the scope of your resource group.

---

### Use Azure CLI applications without `tsh`

In addition to running `az` commands via `tsh`, you can grant secure access to any CLI application that executes commands against Azure's APIs.

To do this, use `tsh` to start a local proxy that forwards traffic from your CLI application to the Teleport Application Service. The Application Service uses an Azure managed identity to fetch an authentication token from Azure, which your CLI application uses to authenticate requests to Azure's APIs.

To start the local proxy, run the following `tsh` command:

```
$ tsh proxy azure
```

---

TIP

The command `tsh proxy az` is an alias for `tsh proxy azure`.

---

The command will print the address of the local proxy server along with `export` commands for assigning environment variables. Azure CLI applications read these variables in order to request an authentication token for Azure's APIs:

```
Started Azure proxy on http://127.0.0.1:54321.
To avoid port randomization, you can choose the listening port using the --port flag.

Use the following credentials and HTTPS proxy setting to connect to the proxy:

  export AZURE_CONFIG_DIR=/Users/myuser/.tsh/azure/my.teleport.cluster/azure
  export HTTPS_PROXY=http://127.0.0.1:54321
  export HTTP_PROXY=http://127.0.0.1:54321
  export MSI_ENDPOINT=https://azure-msi.teleport.dev/123456789abcdef01234
  export REQUESTS_CA_BUNDLE=/Users/myuser/.tsh/keys/teleport.example.com/myuser-app/teleport.example.com/azure-cli-localca.pem

```

---

WARNING

`tsh proxy azure` runs the local proxy in the foreground, so don't interrupt the process or exit the terminal where you ran the command until you're ready to close the local proxy.

---

Copy the `export` commands and paste them into a second terminal. In that terminal, you can now run your Azure CLI application of choice. For example, you can run the following command to list Azure VMs:

```
$ az vm list
```

Since the `az` CLI requests an authentication token using the `teleport-azure` identity you created earlier, and that identity is authorized to view resources in your resource group, the `az vm list` command will only list VMs in that resource group.

---

INFO

When you run an `az` command via `tsh az`, `tsh` starts the local proxy in the background and uses it to execute the command.

---

## Next steps

- Now that you know how to protect Azure CLI access using Teleport, ensure that your Teleport users can only manage Azure resources temporarily, with no longstanding admin roles for attackers to hijack. View our documentation on [Role Access Requests](https://goteleport.com/docs/identity-governance/access-requests/role-requests.md) and [Access Request plugins](https://goteleport.com/docs/identity-governance/access-requests/plugins.md).
- Consult the Azure documentation for information about [Azure managed identities](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) and how to [manage user-assigned managed identities](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-manage-user-assigned-managed-identities).
- See the [Azure documentation](https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest) for the full list of `az` CLI commands.
- For full details on how Teleport populates the `internal` and `external` traits we illustrated in the Teleport roles within this guide, see the [Access Controls Reference](https://goteleport.com/docs/reference/access-controls/roles.md).
