Using Locally with the Azure SDK for .NET

Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

Using Locally with the Azure SDK for .NET

The Azure SDK for .NET is Microsoft's set of libraries for working with Azure from your .NET applications. At this time the SDK needs a couple of lines of code to be able to work against Locally.

This guide covers those changes, using a Resource Group as an example - the same configuration works for the other Azure SDK clients too. You can find more examples using the Azure SDK for .NET in the locallybuild/examples repository.

This guide was tested using the following versions of these libraries from NuGet, but newer versions should work too.

  • Azure.Identity - v1.21.0
  • Azure.ResourceManager - v1.14.0
  • Azure.ResourceManager.Resources - v1.12.0

Provisioning a Resource Group

We're going to provision a Resource Group using the SDK Client Azure.ResourceManager.ArmClient.

When constructing an Azure SDK client, there's two things we need to do configure it to work against Locally:

  1. Configure the Environment property to target Locally. This ensures that calls made by the Azure SDK will interact with Locally rather than Azure Public (or another Azure Environment).
  2. Configure the property DisableInstanceDiscovery to true. Instance Discovery is a MSAL service which validates that the Azure Tenant is known by Microsoft, to ensure you don't send your credentials to an unknown third-party. Since Locally is running on your local machine and isn't a Microsoft-hosted service - it's Tenant ID isn't returned by MSAL Instance Discovery, therefore we need to disable it for the Azure SDK to connect.

We're hoping to have the Azure SDK for .NET support Automatic Configuration in the future, but for now these handful of changes need to be made to the Azure SDKs to be able to connect to Locally.

We can set these by manually constructing the ArmClientOptions and DefaultAzureCredential objects:

using Azure;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Resources;

var clientOptions = new ArmClientOptions
{
    // Connect to Locally rather than Azure Public
    Environment = new ArmEnvironment(new Uri("https://localhost:5680"), "https://localhost:5680"),
};
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
    // MSAL Instance Discovery validates that the Tenant is known and hosted by Microsoft, with the
    // intention being to prevent credentials accidentally being sent to a non-Microsoft provided service.
    //
    // Since Locally is running on your local machine (and therefore isn't a Microsoft-hosted service)
    // we need to disable Instance Discovery, else we'll fail to connect.
    DisableInstanceDiscovery = true,
});

Locally provides the Subscription ID as an Environment Variable (AZURE_SUBSCRIPTION_ID), which can can be obtained via:

// Retrieve the default Subscription ID from the Environment Variable provided by Locally
var defaultSubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID")!;

We can use these 3 values when constructing an Azure SDK client, to connect the client to Locally:

// Construct an Azure SDK client targeting Locally
var resourceClient = new ArmClient(credential, defaultSubscriptionId, clientOptions);

At this point the Azure SDK client is a regular Azure SDK client - meaning that any calls should work as normal.

This means that we can create a Resource Group in Locally using the Azure SDK using:

var subscription = await resourceClient.GetDefaultSubscriptionAsync();
var resourceGroupsClient = subscription.GetResourceGroups();

const string resourceGroupName = "rg-from-azure-sdk-for-dotnet";
const string location = "berlin";

var resourceGroup = new ResourceGroupData(location);
var createResult = await resourceGroupsClient.CreateOrUpdateAsync(WaitUntil.Completed, resourceGroupName, resourceGroup);
Console.WriteLine($"Created {createResult.Value.Data.Id}");

We can then run this sample against Locally using:

$ locally run dotnet run

Should you encounter any issues, please take a look at the troubleshooting section.

Complete Example

using Azure;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Resources;

var clientOptions = new ArmClientOptions
{
    // Connect to Locally rather than Azure Public
    Environment = new ArmEnvironment(new Uri("https://localhost:5680"), "https://localhost:5680"),
};
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
    // MSAL Instance Discovery validates that the Tenant is known and hosted by Microsoft, with the
    // intention being to prevent credentials accidentally being sent to a non-Microsoft provided service.
    //
    // Since Locally is running on your local machine (and therefore isn't a Microsoft-hosted service)
    // we need to disable Instance Discovery, else we'll fail to connect.
    DisableInstanceDiscovery = true,
});

// Retrieve the default Subscription ID from the Environment Variable provided by Locally
var defaultSubscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID")!;

// Construct an Azure SDK client targeting Locally
var resourceClient = new ArmClient(credential, defaultSubscriptionId, clientOptions);

var subscription = await resourceClient.GetDefaultSubscriptionAsync();
var resourceGroupsClient = subscription.GetResourceGroups();

// Create a Resource Group using the Azure SDK for .NET
const string resourceGroupName = "rg-from-azure-sdk-for-dotnet";
const string location = "berlin";

var resourceGroup = new ResourceGroupData(location);
var createResult = await resourceGroupsClient.CreateOrUpdateAsync(WaitUntil.Completed, resourceGroupName, resourceGroup);
Console.WriteLine($"Created {createResult.Value.Data.Id}");

Next steps

The Examples include more Azure SDK for .NET samples, and Using Locally in CI shows how to run Locally in your pipeline. Resources like Storage Accounts also get a Data Plane Emulator, which the Azure Storage SDKs can connect to.

Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

A local cloud for you and your agents.

Your Azure infrastructure, running on your machine. Deploy in seconds, break things freely, and ship to Azure when you're ready.