Protect Azure CLIs with Teleport Application Access
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:
- Create an Azure managed identity for user access and attach it your VM.
- Deploy a Teleport Application Service with an Azure app in your Teleport cluster.
- Assume the managed identity and run
az
commands viatsh
.
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.
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.
-
The
az
CLI tool installed on your workstation. Teleport'stsh
client uses theaz
binary to execute commands. See the Azure documentation for how to install theaz
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.
-
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 identitiesIn 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 runtctl
commands using your current credentials.tctl
is supported on macOS and Linux machines.For example:
$ tsh login --proxy=teleport.example.com --user=email@example.com
$ tctl status
# Cluster teleport.example.com
# Version 15.4.22
# CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678If you can connect to the cluster and run the
tctl 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. 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 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, 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.
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 "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 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:
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
On the host where you will install the Teleport Application Service, 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:
Install Teleport on your Linux server:
-
Assign edition to one of the following, depending on your Teleport edition:
Edition Value Teleport Enterprise Cloud cloud
Teleport Enterprise (Self-Hosted) enterprise
Teleport Community Edition oss
-
Get the version of Teleport to install. If you have automatic agent updates enabled in your cluster, query the latest Teleport version that is compatible with the updater:
$ TELEPORT_DOMAIN=example.teleport.com
$ TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/automaticupgrades/channel/default/version | sed 's/v//')"Otherwise, get the version of your Teleport cluster:
$ TELEPORT_DOMAIN=example.teleport.com
$ TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/ping | jq -r '.server_version')" -
Install Teleport on your Linux server:
$ curl https://cdn.teleport.dev/install-v15.4.22.sh | bash -s ${TELEPORT_VERSION} edition
The installation script detects the package manager on your Linux server and uses it to install Teleport binaries. To customize your installation, learn about the Teleport package repositories in the installation guide.
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: off
proxy_service:
enabled: off
ssh_service:
enabled: off
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
- TAR Archive
On the host where you will run the Teleport Application Service, enable and start Teleport:
$ sudo systemctl enable teleport
$ sudo systemctl start teleport
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 |
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.
- Local Users
- SAML/OIDC Connectors
- All Authentication Methods
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, pasting in the URI of the Azure identity you copied earlier
as the value of --set-azure-identities
:
$ 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
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
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
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
- GitHub
- SAML
- OIDC
-
Retrieve your local user's roles as a comma-separated list:
$ ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")')
-
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" -
Sign out of the Teleport cluster and sign in again to assume the new role.
-
Retrieve your
github
authentication connector:$ tctl get github/github --with-secrets > github.yaml
Note that the
--with-secrets
flag adds the value ofspec.signing_key_pair.private_key
to thegithub.yaml
file. Because this key contains a sensitive value, you should remove the github.yaml file immediately after updating the resource. -
Edit
github.yaml
, addingazure-cli-access
to theteams_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 -
Apply your changes:
$ tctl create -f github.yaml
-
Sign out of the Teleport cluster and sign in again to assume the new role.
-
Retrieve your
saml
configuration resource:$ tctl get --with-secrets saml/mysaml > saml.yaml
Note that the
--with-secrets
flag adds the value ofspec.signing_key_pair.private_key
to thesaml.yaml
file. Because this key contains a sensitive value, you should remove the saml.yaml file immediately after updating the resource. -
Edit
saml.yaml
, addingazure-cli-access
to theattributes_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 -
Apply your changes:
$ tctl create -f saml.yaml
-
Sign out of the Teleport cluster and sign in again to assume the new role.
-
Retrieve your
oidc
configuration resource:$ tctl get oidc/myoidc --with-secrets > oidc.yaml
Note that the
--with-secrets
flag adds the value ofspec.signing_key_pair.private_key
to theoidc.yaml
file. Because this key contains a sensitive value, you should remove the oidc.yaml file immediately after updating the resource. -
Edit
oidc.yaml
, addingazure-cli-access
to theclaims_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 -
Apply your changes:
$ tctl create -f oidc.yaml
-
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
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
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
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.
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 and Access Request plugins.
- Consult the Azure documentation for information about Azure managed identities and how to manage user-assigned managed identities.
- See the Azure
documentation
for the full list of
az
CLI commands. - For full details on how Teleport populates the
internal
andexternal
traits we illustrated in the Teleport roles within this guide, see the Teleport Access Controls Reference.