I’ve previously posted about how to add Azure Table Storage clients via dependency injection for which I created my own extension methods using SAS tokens as MSI authentication wasn’t available.

Happily MSI authentication for Azure Table Storage is now available (though pretty poorly documented) so a guide on how to implement it is below and an example can be found here.

The package Microsoft.Extensions.Azure has been updated to now include a AddTableServiceClient extension which injects a TableServiceClient. This can be called in the ConfigureServices method of your Program file like so.

// Set AZURE_TENANT_ID enviroment variable to the tenant ID that contains the resource
// Only needed for when debugging locally
Environment.SetEnvironmentVariable("AZURE_TENANT_ID", configuration["AZURE_TENANT_ID"]);

// Add table storage client
serviceCollection.AddAzureClients(builder =>
{
	// Add a storage account client
	builder.AddTableServiceClient(new Uri(configuration["TableStorageUri"]));

	// Select the appropriate credentials based on enviroment
	builder.UseCredential(new DefaultAzureCredential());
});

Like when using DefaultAzureCredential to access other resources if you’re authenticating locally using a Visual Studio token and the resource is in a different tenant to your user account you’ll need to set an enviroment variable called AZURE_TENAT_ID to tell DefaultAzureCredential where to authenticate. When running in Azure this is available by default in the enviroment so MSI authentication will work just fine without explicitly setting it.

Another thing to note is that the user must be granted the role “Storage Table Data Contributor” even if they are already a contribuator to the storage account. This is also the case for access to blobs using the relevant extension.

The injected TableServiceClient can then be accessed throughout the project like so.

public class App
{
	private readonly TableServiceClient _tableServiceClient;
	private readonly ILogger<App> _logger;

	public App(TableServiceClient tableServiceClient, ILoggerFactory loggerFactory)
	{
		_logger = loggerFactory.CreateLogger<App>();
		_tableServiceClient = tableServiceClient;
	}

	public async Task RunAsync()
	{
		TableClient tableClient = _tableServiceClient.GetTableClient("Stores");
		var store = await tableClient.GetEntityAsync<StoreEntity>("0006", "1");
	}
}

1 Comment

rok · 13 October 2023 at 12:03 pm

Very nice.

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *