Configuring Workload Identity and Azure Federated Credentials
We're actively looking for design partners to help us shape the future of Teleport Workload Identity and would love to hear your feedback.
Teleport Workload Identity issues flexible short-lived identities in JWT format. Azure Federated Credentials allows you to use these JWTs to authenticate to Azure services.
This can be useful in cases where a machine needs to securely authenticate with Azure services without the use of a long-lived credential. This is because the machine can authenticate with Teleport without using any shared secrets by using one of our delegated join methods.
In this guide, we'll configure Teleport Workload Identity and Azure to allow our workload to authenticate to the Azure Blob Storage and upload content to a container.
How it works
This implementation differs from using the Teleport Application Service to protect Azure APIs in a few ways:
- Requests to Azure are not proxied through the Teleport Proxy Service, meaning reduced latency but also less visibility, as these requests will not be recorded in Teleport's audit log.
- Workload Identity works with any Azure client, including the command-line tool but also their SDKs.
- Using the Teleport Application Service to access Azure does not work with Machine ID and therefore cannot be used when a machine needs to authenticate with Azure.
Prerequisites
-
A running Teleport cluster version 17.0.0-dev 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.Visit Installation for instructions on downloading
tctl
andtsh
.
- 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. For example:If you can connect to the cluster and run the$ tsh login --proxy=teleport.example.com [email protected]
$ tctl status
# Cluster teleport.example.com
# Version 17.0.0-dev
# CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678tctl 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. tbot
must already be installed and configured on the host where the workloads which need to access Teleport Workload Identity will run. For more information, see the deployment guides.- An Azure resource group and subscription you wish to grant the workload access to.
Issuing JWT SVIDs with Teleport Workload Identity requires at least Teleport version 16.4.3.
Deciding on a SPIFFE ID structure
Within Teleport Workload Identity, all identities are represented using a
SPIFFE ID. This is a URI that uniquely identifies the entity that the identity
represents. The scheme is always spiffe://
, and the host will be the name of
your Teleport cluster. The structure of the path of this URI is up to you.
For the purposes of this guide, we will be granting access to Azure to the
spiffe://example.teleport.sh/svc/example-service
SPIFFE ID.
If you have already deployed Teleport Workload Identity, then you will already have a SPIFFE ID structure in place. If you have not, then you will need to decide on a structure for your SPIFFE IDs.
If you are only using Teleport Workload Identity with AWS OIDC Federation, you may structure your SPIFFE IDs so that they explicitly specify the Azure user-managed identity they are allowed to assume. However, it often makes more sense to name the workload or person that will use the SPIFFE ID. See the best practices guide for further advice.
Step 1/4. Configure Azure
To configure Azure to accept Workload Identity JWT SVIDs as authentication, you'll need to create an identity to represent that workload within Azure, configure that identity to accept JWT SVIDs issued by your Teleport Cluster as a federated credential, and then grant that identity the necessary permissions within Azure using a role assignment.
Create a user-managed identity
First, you'll create a user-managed identity to represent the workload within Azure.
- Browse to the "Managed Identities" section of the Azure Portal.
- Select "Create" to open the "Create User Assigned Managed Identity" form.
- Select your resource group and subscription.
- Enter a unique name for your identity that describes the workload it will represent. In our example, we will use "example-service".
- Select "Review + create".
You now need to record some key information about the created user-managed identity to be used in future steps.
Browse to the "Properties" section on the created user-managed identity and note down the "Client Id" and "Tenant Id", these values will both be UUIDs.
Create a federated credential
Next, you need to configure a federated credential for the user-managed identity. This will configure Azure to accept JWT SVIDs issued by your Teleport cluster as a form of authentication for this user-managed identity.
- Browse to your user-managed identity in the Azure Portal and select the "Federated credentials" page from the "Settings" section.
- Select "Add Credential" to open the "Add Federated Credential" form.
- Select "Other" for the "Federated credential scenario".
- Enter the address of your Teleport Proxy service followed by
/workload-identity
for the "Issuer URL", for examplehttps://example.teleport.sh/workload-identity
. - Enter the SPIFFE ID you have decided on for the workload in the
"Subject identifier" field. For example,
spiffe://example.teleport.sh/svc/example-service
. This will control which JWT SVIDs issued by Teleport Workload Identity will be accepted for this user-managed identity. - Enter a unique, identifiable name for the federated credential. For example,
example-teleport-sh-svc-example-service
. - Click "Add".
Create a storage account and container
For the purposes of this guide, you'll create a storage account and container for your workload to authenticate to. You can skip this step if you already have resources you wish to grant the workload access to.
First, create a storage account:
- Browse to the "Storage accounts" section of the Azure Portal and select the "Create" button to open the "Create a storage account" form.
- Select your resource group and subscription.
- Enter a unique, identifiable name for the storage account. Record this as
you will need it later. In our examples we will use
examplestorageaccount
. - Select a region and select "Azure Blob Storage" for the "Primary Service" field.
- Click "Create".
Now, you can create a storage container:
- Browse to the "Storage accounts" section of the Azure Portal and select the storage account you created.
- Browse to the "Containers" section beneath the "Data storage" section.
- Select "Add container" to open the "New container" form.
- Enter a unique, identifiable name for the container. Record this as you will
need it later. In our examples we will use
examplecontainer
.
Create a role assignment
Finally, you need to grant the user-managed identity the necessary permissions for your workload to perform the actions it needs to within Azure.
When creating a role assignment in Azure, it can be scoped to different levels:
- Subscription (to grant access to any resource within the subscription)
- Resource Group (to grant access to any resource within the resource group)
- Resource (to grant access to a specific resource)
For the purposes of this guide, we will grant the user-managed identity the
Storage Blob Data Owner
role with the scope of the storage account you have
created.
- Browse to the "Storage accounts" section of the Azure Portal and select the storage account you created.
- Browse to "Access control (IAM)" in the sidebar, then select "Add" and "Add role assignment".
- Under "Role" select "Storage Blob Data Owner".
- Under "Members", for "Assign access to" select "Managed identity" and then press "Select members".
- For "Managed identity", select "User-assigned managed identity" and then search for and select the user-managed identity you created earlier.
- Click "Review + assign" and save your changes.
Step 2/4. Configure Teleport RBAC
Now we need to configure Teleport to allow a JWT to be issued containing the SPIFFE ID we have chosen.
Create role.yaml
with the following content:
kind: role
version: v6
metadata:
name: my-workload-azure
spec:
allow:
spiffe:
- path: /svc/example-service
Replace:
my-workload-azure
with a descriptive name for the role./svc/example-service
with the path part of the SPIFFE ID you have chosen.
Apply this role to your Teleport cluster using tctl
:
$ tctl create -f role.yaml
You now need to assign this role to the bot:
$ tctl bots update my-bot --add-roles my-workload-azure
Step 3/4. Issue Workload Identity JWTs
You'll now configure tbot
to issue and renew the short-lived JWT SVIDs for
your workload. It'll write the JWT as a file on disk, where you can then
configure Azure clients and SDKs to read it.
Take your already deployed tbot
service and configure it to issue SPIFFE SVIDs
by adding the following to the tbot
configuration file:
outputs:
- type: spiffe-svid
destination:
type: directory
path: /opt/workload-identity
svid:
path: /svc/example-service
jwts:
- audience: api://AzureADTokenExchange
file_name: azure-jwt
Replace:
- /opt/workload-identity with the directory where you want the JWT to be written.
- /svc/example-service with the SPIFFE ID you have chosen.
Restart your tbot
service to apply the new configuration. You should see a
file created at /opt/workload-identity/azure-jwt
containing the JWT.
Step 4/4. Configure the Azure CLIs and SDKs
You can now use the issued JWT SVID to authenticate to Azure. How this is configured varies between the Azure CLI and Azure SDK.
Configuring Azure CLI
To use the JWT SVID to authenticate with the Azure CLI, you perform log-in specifying the JWT and the client and tenant ID of the user-managed identity you created. This performs an initial exchange of the JWT SVID for an Azure access token, which is then cached by the CLI until the access token expires.
Run the following, inserting the client and tenant id you recorded in the first step:
$ az login \
--federated-token $(cat /opt/workload-identity/azure-jwt) \
--service-principal \
-u <user-managed-identity-client-id> \
-t <user-managed-identity-tenant-id>
You should see a message indicating that this has succeeded.
You can now test this has succeeded by uploading a file to the Azure Blob Storage container:
$ echo "testing 1,2,3..." > test.txt
# Upload a test file. Replace the name of the account and container with those
# you selected earlier.
$ az storage blob upload \
--auth login \
--account-name examplestorageaccount \
--container-name examplecontainer \
--name test.txt \
--file ./test.txt
# Check that the file has been uploaded. Replace the name of teh account and
# container with those you selected earlier.
$ az storage blob list \
--auth login \
--output table \
--account-name examplestorageaccount \
--container-name examplecontainer
Configuring Azure SDKs
The Azure SDKs support a set of environment variables to configure them to use the federated credential for authentication with the issued JWT SVID:
AZURE_CLIENT_ID
: The client ID of the user-managed identity.AZURE_TENANT_ID
: The tenant ID of the user-managed identity.AZURE_FEDERATED_TOKEN_FILE
: The path to the JWT SVID file, for example/opt/workload-identity/azure-jwt
.
You can also explicitly configure the SDK to use the federated credential, this will vary language-to-language.
Next steps
- Azure Workload Identity Federation: The official Azure documentation for Workload Identity Federation.
- Workload Identity Overview: Overview of Teleport Workload Identity.
- JWT SVID Overview: Overview of the JWT SVIDs issued by Teleport Workload Identity.
- Best Practices: Best practices for using Workload Identity in Production.
- Read the configuration reference to explore all the available configuration options.