Saturday 30 December 2023

Azure File Share with DefaultAzureCredential in .NET with Azure.Storage.Files.Shares - Is it possible?

 Using DefaultAzureCredential with most of the Azure resources is straight forward and simple with most of the Azure resources with relevant Azure .NET SDKs (We can use nuget packages Azure.Storage.Blobs and Azure.Identity). For example, with storage blob we can easily use DefaultAzureCredential as shown in below code.

    private static BlobServiceClient GetBlobServiceClient(string accountName)
    {
        return new(new Uri($"https://{accountName}.blob.core.windows.net"),
            new DefaultAzureCredential());
    }

However, we cannot simply create ShareClient with .NET SDK Azure.Storage.Files.Shares to use DefaultAzureCredential . as shown below.

ShareClient share = new(new Uri(fileShareUri),
    new DefaultAzureCredential());

With the above setup, we will get runtime errors when we try to perform operations with the Azure file share. As per the GitHub issue here it is not possible to use DefaultAzureCredential with Azure File Share with .NET SDK Azure.Storage.Files.Shares  due to "SMB Files cannot authenticate with a TokenCredential". So is it impossible to use DefaultAzureCredential  to perform operations with an Azure File Share using Azure.Storage.Files.Shares ? Let's look at a wokaround, which can help if desperately need to use DefaultAzureCredential with Azure.Storage.Files.Shares .

We will have to use Azure.ResourceManager.Storage and use it with DefaultAzureCredential to obtain the storage key and then create a StorageSharedKeyCredential to access the file share. This is not an ideal solution, but it makes it possible, to not to store, the access key or connection string of storage account in the application config or in a key vault and use DefaultAzureCredential to access an Azure file share with .NET SDK for Azure files .

So what we need to achive this?

Use below nuget packages 

<PackageReference Include="Azure.Identity" Version="1.10.4" />
    <PackageReference Include="Azure.ResourceManager.Storage" Version="1.2.0" />
    <PackageReference Include="Azure.Storage.Files.Shares" Version="12.17.1" />

Then, obtain the Azure file share storage account resource ID and use ArmClient  with DefaultAzureCredential to recive the storage access key. Then, use a StorageSharedKeyCredential  and create the ShareClient  .


Full example code is shown below.


#region AzureFileShare SDK with Default Azure Creds Try
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Example of Azure file share client SDK try with default Azure creds
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

using Azure.Identity;
using Azure.Storage.Files.Shares.Models;
using Azure.Storage.Files.Shares;
using Azure.Storage;
using Azure.ResourceManager;
using Azure.ResourceManager.Storage;
using Azure.Core;

// -------------This is using connection string we know it works--------------
//string connectionString = "DefaultEndpointsProtocol=https;AccountName=chazfsdeveuw001fsst;AccountKey=storagekey;EndpointSuffix=core.windows.net";
//string shareName = "aksfileshare";
//ShareClient share = new(connectionString, shareName);
// ---------------------------------------------------------------------------


//====================================================================
// Below is the only way to use default Azure creds to work with file share
// SMB Files cannot authenticate with a TokenCredential refer
// https://github.com/Azure/azure-sdk-for-net/issues/17000
//--------------------------------------------------------------------
ArmClient client = new ArmClient(new DefaultAzureCredential());

string resourceId = "/subscriptions/subscriptionid/resourceGroups/ch-azfs-dev-euw-001-rg/providers/Microsoft.Storage/storageAccounts/chazfsdeveuw001fsst";
StorageAccountResource storageAccount = client.GetStorageAccountResource(new ResourceIdentifier(resourceId));

string storageKey = storageAccount.GetKeys().FirstOrDefault().Value;

string fileShareUri = "https://chazfsdeveuw001fsst.file.core.windows.net/aksfileshare";
ShareClient share = new(new Uri(fileShareUri),
    new StorageSharedKeyCredential("chazfsdeveuw001fsst", storageKey));
//====================================================================


// Track the remaining directories to walk, starting from the root
var remaining = new Queue<ShareDirectoryClient>();
remaining.Enqueue(share.GetRootDirectoryClient());
while (remaining.Count > 0)
{
    // Get all of the next directory's files and subdirectories
    ShareDirectoryClient dir = remaining.Dequeue();
    foreach (ShareFileItem item in dir.GetFilesAndDirectories())
    {
        // Print the name of the item
        Console.WriteLine(item.Name);

        // Keep walking down directories
        if (item.IsDirectory)
        {
            remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
        }
    }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#endregion


No comments:

Popular Posts