Search code examples
c#azureasp.net-core-3.1azure-machine-learning-serviceazure-service-principal

How do I use Service Principal authentication with an Azure Machine Learning Pipeline Endpoint in C#?


I'm trying to call an Azure Machine Learning Pipeline Endpoint I've set up using C# & the Machine Learning REST api.

I am certain that I have the Service Principal configured correctly, as I can successfully authenticate & hit the endpoint using the azureml-core python sdk:

sp = ServicePrincipalAuthentication(
    tenant_id=tenant_id,
    service_principal_id=service_principal_id,
    service_principal_password=service_principal_password)
ws =Workspace.get(
    name=workspace_name, 
    resource_group=resource_group, 
    subscription_id=subscription_id, 
    auth=sp)

endpoint = PipelineEndpoint.get(ws, name='MyEndpoint')
endpoint.submit('Test_Experiment')

I'm using the following example in C# to attempt to run my endpoint: https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-pipelines#run-a-published-pipeline-using-c

I'm attempting to fill auth_key with the following code:

var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");

var cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
var auth_key = cred.GetToken(new Azure.Core.TokenRequestContext(new string[] {".default" }));

I receive a 401 (unauthorized).

What am I am doing wrong?

  • UPDATE *

I changed the 'scopes' param in the TokenRequestContext to look like:

var auth_key = cred.GetToken(new Azure.Core.TokenRequestContext(new string[] { "http://DataTriggerApp/.default" }));

http://DataTriggerApp is one of the servicePrincipalNames that shows up when i query my Service Principal from the azure CLI.

Now, when I attempt to use the returned token to call the Machine Learning Pipeline Endpoint, I receive a 403 instead of a 401. Maybe some progress?


Solution

  • Ok, through a lot of trial-and-error I was able to come up with two ways of acquiring a token that allows me to hit my Azure Machine Learning Pipeline Endpoint through the REST api. One uses Microsoft.Identity.Client & one uses Azure.Identity.

    using Microsoft.Identity.Client;
    
    ...
    
    public static async Task<string> GetAccessToken()
    {
          var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
          var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
          var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
    
       
          var app = ConfidentialClientApplicationBuilder.Create(clientId)
                                                    .WithClientSecret(clientSecret)                                                
                                                    .WithAuthority(AzureCloudInstance.AzurePublic, tenantId)
                                                    .Build();
          var result = await app.AcquireTokenForClient(new string[] { "https://ml.azure.com/.default" }).ExecuteAsync();
          return result.AccessToken;
    }
    

    Or:

    using Azure.Identity;
    ...
    
    public static async Task<string> GetAccessToken()
    {
          var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID");
          var clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET");
          var tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID");
    
    
          var cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
          var token =  await cred.GetTokenAsync(new Azure.Core.TokenRequestContext(new string[] { "https://ml.azure.com/.default" }));
          return token.Token;
    }