docs/pages/machine-workload-identity/workload-identity/azure-federated-credentials.mdx
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.
This implementation differs from using the Teleport Application Service to protect Azure APIs in a few ways:
(!docs/pages/includes/edition-prereqs-tabs.mdx!)
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.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.
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.
First, you'll create a user-managed identity to represent the workload within Azure.
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.
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.
/workload-identity for the "Issuer URL", for example
https://example.teleport.sh/workload-identity.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.example-teleport-sh-svc-example-service.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:
examplestorageaccount.Now, you can create a storage container:
examplecontainer.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:
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.
Now we need to configure Teleport to allow a JWT to be issued containing the SPIFFE ID we have chosen.
First, you'll create a Workload Identity resource to define the identity and
its characteristics. Create a new file called workload-identity.yaml:
kind: workload_identity
version: v1
metadata:
name: example-workload-identity
labels:
example: getting-started
spec:
spiffe:
id: /svc/example-service
Replace:
example-workload-identity with a descriptive name for the Workload Identity./svc/example-service with the path part of the SPIFFE ID you have chosen.Apply this to your cluster using tctl:
$ tctl create -f workload-identity.yaml
Next, you'll create a role which grants access to this Workload Identity. Create
role.yaml with the following content:
kind: role
version: v6
metadata:
name: example-workload-identity-issuer
spec:
allow:
workload_identity_labels:
example: ["getting-started"]
rules:
- resources:
- workload_identity
verbs:
- list
- read
Replace:
example-workload-identity-issuer with a descriptive name for the role.Apply this role to your Teleport cluster using tctl:
$ tctl create -f role.yaml
(!docs/pages/includes/create-role-using-web.mdx!)
You now need to assign this role to the bot:
$ tctl bots update my-bot --add-roles example-workload-identity-issuer
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:
services:
- type: workload-identity-jwt
destination:
type: directory
path: /opt/workload-identity
selector:
name: example-workload-identity
audiences: ["api://AzureADTokenExchange"]
Replace:
Restart your tbot service to apply the new configuration. You should see a
file created at /opt/workload-identity/jwt_svid containing the JWT.
You can now use the issued JWT SVID to authenticate to Azure. How this is configured varies between the Azure CLI and Azure SDK.
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/jwt_svid) \
--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
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/jwt_svid.You can also explicitly configure the SDK to use the federated credential, this will vary language-to-language.