Terraform Azure VM Auto-Discovery Configuration
This guide shows you how to use Terraform to configure Teleport and Azure to automatically enroll Azure virtual machines in your Teleport cluster.
How it works
The teleport-discovery-azure Terraform module creates the Azure and Teleport cluster resources necessary to configure the Discovery Service to enable Teleport Azure virtual machine auto-discovery.
The Teleport Discovery Service queries the Azure API to list virtual machines, matching your configured subscriptions, resource groups, and tags. For each virtual machine that it discovers, the Discovery Service uses the Azure Run Command feature to install Teleport on the instance and join it to the cluster as a Teleport-protected server.
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
tctlandtshclients.Installing
tctlandtshclients-
Determine the version of your Teleport cluster. The
tctlandtshclients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at/v1/webapi/findand use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:- Mac/Linux
- Windows - Powershell
TELEPORT_DOMAIN=teleport.example.com:443TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"$TELEPORT_DOMAIN = "teleport.example.com:443"$TELEPORT_VERSION = (Invoke-RestMethod -Uri "https://${TELEPORT_DOMAIN}/v1/webapi/find").server_version -
Follow the instructions for your platform to install
tctlandtshclients:- Mac
- Windows - Powershell
- Linux
Download the signed macOS .pkg installer for Teleport, which includes the
tctlandtshclients:curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkgIn Finder double-click the
pkgfile to begin installation.dangerUsing 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.
curl.exe -O https://cdn.teleport.dev/teleport-v$TELEPORT_VERSION-windows-amd64-bin.zipUnzip 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.
All of the Teleport binaries in Linux installations include the
tctlandtshclients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our installation page.curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gztar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gzcd teleportsudo ./installTeleport binaries have been copied to /usr/local/bin
-
-
Azure virtual machines running a supported Linux distribution.
-
An Azure subscription with permissions to create managed identities, role definitions, and role assignments. See the next step for the full permissions Terraform needs.
-
terraform version
Terraform v1.5.7
-
To check that you can connect to your Teleport cluster, sign in with
tsh login, then verify that you can runtctlcommands 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 protected] to your Teleport username:
tsh login --proxy=teleport.example.com --user=[email protected]tctl statusCluster teleport.example.com
Version 19.0.0-dev
CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
If you can connect to the cluster and run the
tctl statuscommand, you can use your current credentials to run subsequenttctlcommands from your workstation. If you host your own Teleport cluster, you can also runtctlcommands on the computer that hosts the Teleport Auth Service for full permissions.
Step 1/5. Install Teleport to run the Discovery Service
If you already have a running Discovery Service instance, then assign its
discovery_group to discovery-group-name and proceed to
Step 3/5: Use the teleport-discovery-azure Terraform module.
All Teleport Cloud clusters run the Discovery Service for you, so Teleport Cloud subscribers can also skip all of these installation steps.
Install Teleport
If you plan on running the Discovery Service on the same host already running another Teleport service (Auth or Proxy, for example), then you can skip this step.
Install Teleport on a host instance that will run the Discovery Service:
To install Teleport binaries 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.
-
Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https://).
-
Run your cluster's install script:
curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
Configure the Discovery Service
If you are running the Discovery Service on its own host, the service requires a valid invite token to connect to the cluster. Generate one by running the following command against your Teleport Auth Service:
tctl tokens add --type=discovery
Save the generated token in /tmp/token on the host that will run the
Discovery Service.
Discovery Service exposes a configuration parameter - discovery_service.discovery_group -
that allows you to group discovered resources into different sets. This parameter
is used to prevent Discovery Agents watching different sets of cloud resources
from colliding against each other and deleting resources created by another services.
When running multiple Discovery Services, you must ensure that each service is configured
with the same discovery_group value if they are watching the same cloud resources
or a different value if they are watching different cloud resources.
It is possible to run a mix of configurations in the same Teleport cluster meaning that some Discovery Services can be configured to watch the same cloud resources while others watch different resources. As an example, a 4-agent high availability configuration analyzing data from two different cloud accounts would run with the following configuration.
- 2 Discovery Services configured with
discovery_group: "prod"polling data from Production account. - 2 Discovery Services configured with
discovery_group: "staging"polling data from Staging account.
Assign teleport.example.com:443 to the host and port of the Teleport Proxy Service in your cluster, and discovery-group-name to a name that identifies a group of resources that you will enroll:
# teleport.yaml
version: v3
teleport:
join_params:
# token_name can be a literal token string or a path to a file.
# File path is preferable to avoid including a secret in the config file.
token_name: "/tmp/token"
method: token
proxy_server: "teleport.example.com:443"
auth_service:
enabled: false
proxy_service:
enabled: false
ssh_service:
enabled: false
discovery_service:
enabled: true
discovery_group: "discovery-group-name"
Start Teleport
Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Discovery Service.
- Package Manager
- TAR Archive
On the host where you will run the Discovery Service, enable and start Teleport:
sudo systemctl enable teleportsudo systemctl start teleport
On the host where you will run the Discovery Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:
sudo teleport install systemd -o /etc/systemd/system/teleport.servicesudo systemctl enable teleportsudo systemctl start teleport
You can check the status of the Discovery Service with systemctl status teleport
and view its logs with journalctl -fu teleport.
Step 2/5. Set up an identity for discovered VMs
Every Azure VM to be discovered must have an identity assigned to it: either system assigned or user assigned managed identity.
- Azure Portal
- Azure CLI
To set up a Managed Identity:
- Navigate to Virtual machines view if you're hosting Teleport on an Azure VM, or navigate to Virtual machine scale sets view if you're hosting Teleport on an Azure VMSS.
- Select the VM or VMSS hosting your Teleport Service.
- In the right-side panel, click the Security/Identity tab.
- Under the Identity section, select the System assigned tab.
- Toggle the Status switch to On.
- 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.
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 3/5. Use the teleport-discovery-azure Terraform module
Configure AzureRM Terraform provider
Configure the AzureRM Terraform provider and Azure permissions for Terraform to manage Azure resources.
Azure permissions required for AzureRM Terraform provider
The AzureRM Terraform provider will need the following Azure permissions
at the scope where the teleport-discovery-azure module will create resources:
Microsoft.ManagedIdentity/userAssignedIdentities/readMicrosoft.ManagedIdentity/userAssignedIdentities/writeMicrosoft.ManagedIdentity/userAssignedIdentities/deleteMicrosoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/readMicrosoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/writeMicrosoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/deleteMicrosoft.Authorization/roleDefinitions/readMicrosoft.Authorization/roleDefinitions/writeMicrosoft.Authorization/roleDefinitions/deleteMicrosoft.Authorization/roleAssignments/readMicrosoft.Authorization/roleAssignments/writeMicrosoft.Authorization/roleAssignments/delete
Configure Teleport Terraform provider
There are several ways to configure the Teleport Terraform provider depending on how you intend to run Terraform, for example in CI, Spacelift, or some other remote environment, but for a quick start, see the Local Demo guide.
The local demo guide walks through configuring the Teleport Terraform provider with local Teleport credentials, which typically requires logging in with tsh and running a tctl command from the same shell that you use to run terraform commands:
tsh logineval "$(tctl terraform env)"
If you are running Terraform in a remote environment, such as a cloud VM, an on-prem server, or CI/CD pipelines, refer to Using the Teleport Terraform Provider to find the appropriate guide for your use case.
Configure the Terraform module inputs
Add the teleport-discovery-azure module to your Terraform configuration.
- Teleport Cloud
- Self-Hosted
module "azure_discovery" {
source = "terraform.releases.teleport.dev/teleport/discovery/azure"
version = "~> 18.0"
# Required inputs:
# Assign example.teleport.sh:443 to your Teleport cluster's proxy public address in host:port form.
teleport_proxy_public_addr = "example.teleport.sh:443"
# teleport_discovery_group_name must match the discovery group name in your Discovery Service config.
# Teleport Cloud clusters run the Discovery Service in the group name "cloud-discovery-group".
# Do not modify this input unless you intend to run your own Discovery Service.
teleport_discovery_group_name = "cloud-discovery-group"
# Name of an existing Azure Resource Group where Azure resources will be created.
azure_resource_group_name = "my-resource-group"
# Azure region where the managed identity used by the Discovery Service will be created.
azure_managed_identity_location = "eastus"
# Matchers configure which Azure resources the Discovery Service will discover and enroll into Teleport.
azure_matchers = [
{
types = ["vm"]
# subscriptions filters which Azure subscriptions are scanned for VMs.
subscriptions = ["subscription-id"]
# resource_groups filters which resource groups are scanned. The wildcard matches all resource groups.
resource_groups = ["*"]
# regions filters which Azure regions are scanned. The wildcard matches all regions.
regions = ["*"]
# tags filter which VMs are enrolled. The wildcard matches all tags.
tags = { "*" : ["*"] }
}
]
# Optional inputs:
# Apply the additional Azure tag "origin=example" to all Azure resources created by this module
apply_azure_tags = { origin = "example" }
# Apply the additional Teleport label "origin=example" to all Teleport resources created by this module
apply_teleport_resource_labels = { origin = "example" }
}
module "azure_discovery" {
source = "terraform.releases.teleport.dev/teleport/discovery/azure"
version = "~> 19.0"
# Required inputs:
# Edit this input to the host and port of the Teleport Proxy Service in your cluster
teleport_proxy_public_addr = "teleport.example.com:443"
# Assign discovery-group-name to the discovery group name in your Discovery Service config file.
teleport_discovery_group_name = "discovery-group-name"
# Name of an existing Azure Resource Group where Azure resources will be created.
azure_resource_group_name = "my-resource-group"
# Azure region where the managed identity used by the Discovery Service will be created.
azure_managed_identity_location = "eastus"
# Matchers to configure the Discovery Service; used to discover and enroll Azure resources into Teleport.
azure_matchers = [
{
types = ["vm"]
# subscriptions filters which Azure subscriptions are scanned for VMs.
subscriptions = ["subscription-id"]
# resource_groups filters which resource groups are scanned. The wildcard matches all resource groups.
resource_groups = ["*"]
# regions filters which Azure regions are scanned. The wildcard matches all regions.
regions = ["*"]
# tags filter which VMs are enrolled. The wildcard matches all tags.
tags = { "*" : ["*"] }
}
]
# Optional inputs:
# Apply the additional Azure tag "origin=example" to all Azure resources created by this module
apply_azure_tags = { origin = "example" }
# Apply the additional Teleport label "origin=example" to all Teleport resources created by this module
apply_teleport_resource_labels = { origin = "example" }
}
Add a Terraform output for the module so that Terraform will display its outputs:
output "azure_discovery" {
value = module.azure_discovery
}
See the teleport-discovery-azure reference for a complete description of the module inputs and outputs.
Step 4/5. Apply the Terraform module
terraform initterraform apply
Terraform should plan to create the following resources:
- Azure user-assigned managed identity for the Teleport Discovery Service
- Azure federated identity credential for OIDC workload identity federation
- Azure custom role definition with the required VM discovery permissions
- Azure role assignment scoped to the configured subscription(s)
- Teleport
discovery_configcluster resource that configures Teleport for Azure resource discovery - Teleport
integrationcluster resource for Azure OIDC - Teleport
tokencluster resource that allows Teleport nodes to join the cluster using Azure credentials
Review the Terraform plan and confirm the plan actions.
After Terraform finishes applying the plan, it should display the module outputs:
azure_discovery = {
"teleport_discovery_config_name" = "discovery-abcd0123"
"teleport_integration_name" = "discovery-abcd0123"
"teleport_provision_token_name" = "discovery-abcd0123"
"azure_discovery_role_definition" = { ... }
"azure_teleport_discovery_managed_identity" = { ... }
}
The Azure resources should have the following tags:
origin=exampleTeleportCluster=<cluster-name>TeleportIntegration=discovery-abcd0123TeleportIACTool=terraform
The Teleport resources should have the following labels:
origin=exampleteleport.dev/iac-tool=terraform
Step 5/5. Check discovery status
After applying the Terraform module, the Teleport Discovery Service should start to discover Azure VM instances and enroll them in your cluster as protected resources.
It may take a few minutes for virtual machines to be discovered and enrolled.
Navigate to the Teleport Web UI and select Zero Trust Access > Integrations.
By default, the integration created by the teleport-discovery-azure Terraform module is named discovery-<random>.
Click on the integration to review the discovery status.
The integration page provides an overview of how many virtual machines have been discovered and any issues encountered during the discovery process.
Updating module configuration
The module inputs can be changed and re-applied to adjust the Azure discovery integration.
For example, if you had previously used specific Azure regions (rather than the wildcard default for all regions), then you can adjust regions in the Azure matcher to include additional regions for Azure discovery and re-apply the module to start enrolling instances in those regions as well.
azure_matchers = [
{
types = ["vm"]
subscriptions = ["subscription-id"]
resource_groups = ["*"]
- regions = ["eastus"]
+ regions = ["eastus", "westus"]
tags = { "*" : ["*"] }
}
]
Apply Terraform again:
terraform apply
Review the Terraform plan before confirming the changes.
After Terraform finishes applying its plan, the Discovery Service will pick up
the change to the dynamic discovery_config and begin to enroll VMs in the
newly-configured regions.
Troubleshooting
Teleport reports no error but VM does not join
Check your Discovery Service config and make sure that the VM you want to discover matches. In debug mode, Teleport will log the Subscription IDs and names of VMs it discovers.
The Azure run command API does not report the output of commands,
so Teleport has no way of knowing if a command succeeded or failed. Run command
logs can be found on the targeted VM at
/var/log/azure/run-command-handler/handler.log.
Next steps
- Read Joining Nodes via Azure Managed Identity for more information on Azure tokens.
- Full documentation on Azure discovery configuration can be found through the config file reference documentation.