I am writing an Azure function which will update an Azure DNS zone. The function has a Managed Service Identity (MSI) attached to it.
I am able to use the non-fluent SDK to read the current records in the DNS zone. However when I try and do the same thing using the fluent libraries I get the following error:
[07/11/2018 14:36:37] Executed 'Function1' (Failed,Id=8d34472e-956a-4ff3-a1b1-16ea6186934a)
[07/11/2018 14:36:37] System.Private.CoreLib: Exception while executing function: Function1.Microsoft.Azure.Management.ResourceManager.Fluent: Value cannot be null.
[07/11/2018 14:36:37] Parameter name: MSI_ENDPOINT.
So that I can easily test the difference between the two libraries, I have put together a test function.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Rest;
using Microsoft.Azure.Management.Dns;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
namespace UpdateDNS
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "{subscription}/{rg_name}/{zone_name}/{lib}")] HttpRequest req,
string subscription,
string rg_name,
string zone_name,
string lib,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
int count = 0;
dynamic records;
// determine the lib to use to get the dns data
switch (lib)
{
case "fluent":
AzureCredentialsFactory factory = new AzureCredentialsFactory();
MSILoginInformation msi = new MSILoginInformation(MSIResourceType.AppService);
AzureCredentials msiCred = factory.FromMSI(msi, AzureEnvironment.AzureGlobalCloud);
var azureAuth = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders).Authenticate(msiCred);
// set the subscription to work with
var azure = azureAuth.WithSubscription(subscription);
var dnszone = azure.DnsZones.GetByResourceGroup(rg_name, zone_name);
records = dnszone.ListRecordSets();
break;
default:
// get the token from the managed service identity
AzureServiceTokenProvider token_provider = new AzureServiceTokenProvider();
string token = await token_provider.GetAccessTokenAsync("https://management.azure.com");
TokenCredentials token_creds = new TokenCredentials(token);
// create the dns client
DnsManagementClient client = new DnsManagementClient(token_creds);
client.SubscriptionId = subscription;
records = client.RecordSets.ListAllByDnsZone(rg_name, zone_name);
break;
}
foreach (var record in records)
{
Console.WriteLine(record.Name);
count++;
}
return new OkObjectResult($"Records: {count}");
}
}
}
This is an HTTP triggered Azure function and allows the subscription, resource group and DNS zone to be passed in as parameters as well as the library to use.
So in order to test the non-fluent libs I can call the following:
http://localhost:7071/api/ee65837a-8b52-4fed-9820-f2eb0bb11baf/my_rg/my_zone/stable
This will return something like:
Records: 3
However if I try and run the same query but using the fluent libs I get the error as shown above:
http://localhost:7071/api/ee65837a-8b52-4fed-9820-f2eb0bb11baf/my_rg/my_zone/fluent
Am I missing a parameter that needs to be passed in? I am not sure where the 'MSI_ENDPOINT' would be set and what it should be set to. My feeling is that this should be done for me.
The versions of the libraries that are in use are:
Microsoft.Azure.Management.DNS 3.0.1
Microsoft.Azure.Management.Fluent 1.17.0
Microsoft.Azure.Services.AppAuthentication 1.0.3
I am running this locally within Visual Studio which is logged into an account with the appropriate access to Azure.
I am running this locally within Visual Studio which is logged into an account with the appropriate access to Azure.
You don't have Manage Service Identity on your local machine so you could not work well with the first method in local.
As junnas said, you could use Azure Services Authentication Extension
with AzureServiceTokenProvider
which retrieves your account to access to Azure.
For more details, you could refer to this article.
So, firstly you need to do is go to you yourappname.scm.azurewebsites.net
and select Environment
to check if there is MSI_ENDPOINT
variable in it. Which means you have set up MSI successfully.
Secondly, publish the function to Azure and it will work fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With