-1

I'm running ASP.NET Core application (.Net Core 3.0) and have referenced nuGet package Microsoft.Azure.Management.WebSites. It seems like there are half a dozen ways to connect to Azure and I'm hoping that is the correct one for my environment.

I'm attempting to instantiate a WebSiteManagementClient so that I can modify some AppService settings (scale service plan up/down). To that end, I need an instance of ServiceClientCredentials. I can't seem to find a way to get the proper credentials together.

I've followed several different articles, all of them advocate a different method.

What's the easiest way to get authenticated against the Azure Management SDK?

Ideally, avoiding Azure Active Directory. I've attempted multiple times trying to set up an App Registration with the appropriate permissions, and I can't seem to get it together.

The app connecting and making the change will be an ASP.NET website running in Azure itself, if it makes a difference.

Thanks in advance!

Code so far:

  using Microsoft.Azure.Management.WebSites;

  var credentials = await GetCredentials();  // <-- ???
  WebSiteManagementClient client = new WebSiteManagementClient(credentials);
  client.SubscriptionId = "xxx-xxx-xxxx-xxxx";
user1142433
  • 1,413
  • 3
  • 17
  • 34

2 Answers2

0

Try this :

static void Main(string[] args)
{
    string tenantId = "<your tenant ID>";
    string clientId = "<your azure ad app ID>";
    string clientSecret = "<azure ad app secret>";
    string subscriptionId = "<your subscription ID>";


    WebSiteManagementClient client = new WebSiteManagementClient(GetCredsFromServicePrincipal(tenantId, clientId, clientSecret));
    client.SubscriptionId = subscriptionId;

    foreach (var ap in client.app.List()) {
        Console.WriteLine(ap.Id);
    }

}


private static TokenCredentials GetCredsFromServicePrincipal(String tenantId,String clientId, String clientSecret)
{
    var authority = @"https://login.microsoftonline.com/" + tenantId;
    var authContext = new AuthenticationContext(authority);
    var credential = new ClientCredential(clientId, clientSecret);
    var authResult = authContext.AcquireTokenAsync("https://management.azure.com", credential).GetAwaiter().GetResult();
    return new TokenCredentials(authResult.AccessToken);
}

Result (list all website ids): enter image description here As this sample use ServicePrincipal to access your azure website resources, so you should grant associated permissions it in your subscription "Access control (IAM)" balde, such as assigning "website contributor" and "web plan contributor" to it so it has permission to manage your website resources . Hope it helps.

Stanley Gong
  • 11,522
  • 1
  • 8
  • 16
0

The new Azure.Identity library seems to be the recommended way for authenticating services within Azure. In particular the DefaultAzureCredentials() class works seamlessly in local development scenarios and in deployed code without having to make any code changes.

This is easy to use with the newer management SDKs (the ones with names like Azure.ResourceManager...) because we can just write new DefaultAzureCredentials() and pass that to the management SDK when creating a new client.

Unfortunately, the older management SDKs (the ones with names like Microsoft.Azure.Management...) do not integrate with Azure.Identity "out-of-the-box". They also do not plan to add support for Azure.Identity to these older APIs because they are instead focusing on porting everything to the newer versions.

However, not every resource in Azure has a new version management API yet and so in some cases you're stuck using the old ones. Fortunately, there is a relatively straight forward way to bridge the gap and still use Azure.Identity with those older APIs.

There's a GitHub repo which contains an example of how to achieve this. I think it's by one of the developers on the Microsoft team, but isn't officially supported by Microsoft. There is no NuGet package for it and they recommend just copying the bits you need.

I actually found that the code in that sample repo was overly complex for my needs and in my case that all I needed was this. Note, I've copied this from my F# project without testing it, so I might have made a mistake in the conversion to C#, but hopefully it's close enough that you get the idea.

class AzureIdentityFluentCredentialAdapter : AzureCredentials
{
    public AzureIdentityFluentCredentialAdapter(string tenantId)
        : base(default(DeviceCredentialInformation), tenantId, AzureEnvironment.AzureGlobalCloud)
    {
    }

    public override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var creds = DefaultAzureCredential() // Use the new Azure.Identity library to get access tokens

        var accessToken = await creds.GetTokenAsync(
            new TokenRequestContent(new [] { "https://management.azure.com/.default" }), 
            cancellationToken);

        return await TokenCredentials(accessToken.Token)
            .ProcessHttpRequestAsync(request, cancellationToken);
    }
}

This example doesn't do any token caching, but for my purposes I wasn't too bothered about this. It's also hardcoded the scope that I request the token for because I knew I was only going to be using this with the Azure management API.

Choc13
  • 796
  • 7
  • 23