pythonazureazure-sdk-python

Is there a safer way to use the WorkloadIdentityCredential Python class in Azure SDK?


I previously was using the ClientSecretCredential class to authenticate with the Azure SDK but the Service principals changed to a workload identity federation model, because of this I switched to using the WorkloadIdentityCredential authentication but this requires the token to be in a file, because of this a create a temporary file for the token but is there a better/more secure way of doing this?

This was the original authentication

credential = ClientSecretCredential(tenant_id = args.tenant, client_id = args.client_id, client_secret = args.client_secret)

This is what I've been using up to now

temp_token_file = "temp_token_file.txt"
with open(temp_token_file, "w") as f:
    f.write(args.oidc_token)    
credential = WorkloadIdentityCredential(tenant_id=args.tenant, client_id=args.client_id, token_file_path=temp_token_file) 

Solution

  • Typically, environments that support for WorkloadIdentityCredential (such as Azure Kubernetes Service) will have the necessary environment variables set/injected for the credential to be used (AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_FEDERATED_TOKEN_FILE). The token in the file denoted by AZURE_FEDERATED_TOKEN_FILE is short-lived, and only accessible from inside the Azure environment. If your enviornment supports it, then you can just use WorkloadIdentityCredential without any parameters:

    from azure.identity import WorkloadIdentityCredential
    
    credential = WorkloadIdentityCredential()
    

    However, since it seems you may be running this in Azure Pipelines, AzurePipelineCredential is generally recommended, provided you did the necessary configuration. More info here, and example usage:

    from azure.identity import AzurePipelinesCredential
    
    
    service_connection_id = os.environ.get("AZURESUBSCRIPTION_SERVICE_CONNECTION_ID")
    client_id = os.environ.get("AZURESUBSCRIPTION_CLIENT_ID")
    tenant_id = os.environ.get("AZURESUBSCRIPTION_TENANT_ID")
    system_access_token = os.environ.get("SYSTEM_ACCESSTOKEN")
    if service_connection_id and client_id and tenant_id and system_access_token:
        credential = AzurePipelinesCredential(
            tenant_id=tenant_id,
            client_id=client_id,
            service_connection_id=service_connection_id,
            system_access_token=system_access_token,
        )