azure-cli icon indicating copy to clipboard operation
azure-cli copied to clipboard

az login support for Azure AD workload identity with Azure Kubernetes Service

Open arsnyder16 opened this issue 2 years ago • 14 comments

Related command az login

Is your feature request related to a problem? Please describe. Currently if using workload identity and azure cli, az login must be specifically configured for login

Describe the solution you'd like similar to az login --identity, maybe something like az login --workflow-identity Describe alternatives you've considered You can work around it currently using az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID

Additional context For the client libraries a specific class is available WorkloadIdentityCredential

More generally it would be nice if az login had a way to use something similar to DefaultAzureCredential which would allow scripts to be more portable depending on execution context

arsnyder16 avatar Jul 10 '23 19:07 arsnyder16

Thank you for opening this issue, we will look into it.

yonzhan avatar Jul 10 '23 19:07 yonzhan

Same issue, thanks for posting a workaround! Hope to see this fixed

RickardTaran avatar Jul 10 '23 23:07 RickardTaran

A similar feature request has been raised for Azure PowerShell: https://github.com/Azure/azure-powershell/issues/22213

  • MSAL Python supported client_assertion with JWT in https://github.com/AzureAD/microsoft-authentication-library-for-python/pull/271
  • Azure CLI supported --federated-token in az login in https://github.com/Azure/azure-cli/pull/19853
  • Azure Identity Python implemented WorkloadIdentityCredential in https://github.com/Azure/azure-sdk-for-python/pull/19902. Azure Identity Python doesn't utilize MSAL for making the token exchange request. Instead, it developed its own implementation.

Supporting workload identity requires reading from these environment variables:

  • AZURE_AUTHORITY_HOST
  • AZURE_CLIENT_ID
  • AZURE_TENANT_ID
  • AZURE_FEDERATED_TOKEN_FILE

(Documented at https://azure.github.io/azure-workload-identity/docs/quick-start.html?highlight=AZURE_FEDERATED_TOKEN_FILE#7-deploy-workload)

The AKS document https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview#microsoft-authentication-library-msal provides samples that directly use MSAL for workload identity authentication. For example, the MSAL Python sample reads values from environment variables first:

https://github.com/Azure/azure-workload-identity/blob/a5fc57dd72e5fe2d85a21072d47eb3aa2b316407/examples/msal-python/main.py#L9-L12

    azure_client_id = os.getenv('AZURE_CLIENT_ID', '')
    azure_tenant_id = os.getenv('AZURE_TENANT_ID', '')
    azure_authority_host = os.getenv('AZURE_AUTHORITY_HOST', '')
    azure_federated_token_file = os.getenv('AZURE_FEDERATED_TOKEN_FILE', '')

Then it uses the same mechanism as Azure CLI - creating ConfidentialClientApplication instance with client_assertion:

https://github.com/Azure/azure-workload-identity/blob/a5fc57dd72e5fe2d85a21072d47eb3aa2b316407/examples/msal-python/token_credential.py#L14-L20

        self.app = ConfidentialClientApplication(
            azure_client_id,
            client_credential={
                'client_assertion': f.read().decode("utf-8")
            },
            authority="{}{}".format(azure_authority_host, azure_tenant_id)
        )

Azure CLI's code:

https://github.com/Azure/azure-cli/blob/21266e02457263420b62fba1c529f69e28852414/src/azure-cli-core/azure/cli/core/auth/msal_authentication.py#L127-L132

The workaround provided in the issue description is the right path. In order for Azure CLI to natively support workload identity, it has to read those environment variables as the workaround does. But, we still need to work with MSAL team to decide whether this logic should be done by Azure CLI or MSAL.

A prerequisite is to support environment credentials first: https://github.com/Azure/azure-cli/issues/10241

jiasli avatar Jul 12 '23 08:07 jiasli

I'm interested in this as well, for the use case i am interested in, it would be to host azure devops agents in a k8s environment and use the workload identity for the service connection vs having to script this out and tightly couple the pipeline tasks to its hosting environment

wba-josh-hetland avatar Sep 14 '23 17:09 wba-josh-hetland

Same issue, thanks for posting a workaround! Hope to see this fixed

OliverKleinBST avatar Feb 08 '24 10:02 OliverKleinBST

Interested in this too. Would be great to have a native implementation of this in Azure CLI.

rikhil-s avatar Feb 27 '24 14:02 rikhil-s

az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID

how to get this federated token using the azure devops pipeline script task ? workload identity works fine with kubernetes , kubectl or helm task in the azure devops. But its not working in the azure cli task.

Veljen avatar Mar 13 '24 05:03 Veljen

az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID

AZURE_FEDERATED_TOKEN_FILE - this env var is injected into the pod if you enable workload identity

PIrojahPerbak avatar Jun 19 '24 09:06 PIrojahPerbak

Will this work in azure devops - AzureCLI@2 task ?

Veljen avatar Jun 21 '24 07:06 Veljen

Will this work in azure devops - AzureCLI@2 task ?

Depends on your configuration - if you have followed the instructions on the workload identity page then it should work: https://azure.github.io/azure-workload-identity/docs/quick-start.html?highlight=AZURE_FEDERATED_TOKEN_FILE#7-deploy-workload.

If you dont mind me asking have you configured workload identity in the agent? Otherwise you might have to enable an oidc auth task in the pipeline

PIrojahPerbak avatar Jun 21 '24 07:06 PIrojahPerbak

My scenario is different here, I have configured workload identity in azure devops service connection.

this kubernetes plugin works fine using this aksinfralab service connection and can deploy the resource in k8s. (this service populating the federated token file in the agentpool)

# - task: Kubernetes@1
#   displayName: 'kubectl apply'
#   inputs:
#     azureSubscriptionEndpoint: 'aksinfralab'
#     azureResourceGroup: 'aks-pipeline'
#     kubernetesCluster: 'aks-lab-pipeline'
#     connectionType: 'Azure Resource Manager'
#     command: 'get'
#     arguments: 'pods'

when comes to azureCli task. I want to use this below. using this service connection I don't see the environment variables populated for the AZURE_FEDERATED_TOKEN_FILE in the agentpool

- task: AzureCLI@2
  displayName: 'Kubeconfig generator'
  inputs:
    azureSubscription: 'aksinfralab'
    scriptType: 'bash'
    addSpnToEnvironment: true
    scriptLocation: 'inlineScript'
    inlineScript: |
      az login --federated-token "$(cat $AZURE_FEDERATED_TOKEN_FILE)" --service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID
      az aks get-credentials --resource-group aks-pipeline --name aks-lab-pipeline -f $(Build.ArtifactStagingDirectory)/kubeconfig-dev
      kubelogin convert-kubeconfig -l workloadidentity --kubeconfig  $(Build.ArtifactStagingDirectory)/kubeconfig-dev


This is AD enabled cluster hence we need to use the kubelogin with any service principal. #agentpool is vm.

Veljen avatar Jun 21 '24 08:06 Veljen

How does this work with the azureSubscription parameter? AKS workload identity will already inject it right, is inputting the subscription in the task not double?

guidojw avatar Aug 07 '24 22:08 guidojw

For anyone interested in logging into the az cli using their own self generated tokens I've written up a series of blog posts on how to get the OIDC documents setup, provision associated azure resources, then login to az cli using the signed client assertion: https://finarne.wordpress.com/2024/07/25/acquire-an-entra-id-token-using-federated-credentials-part-1-oidc-discovery-documents/

colinrippeyfinarne avatar Aug 19 '24 09:08 colinrippeyfinarne

+1

eminwux avatar Aug 25 '24 10:08 eminwux