[QUERY] DataMovement Required Permissions - Provider Initialized with Credentials does not pass to StorageResource object
Library name and version
Azure.Storage.... 12.1.0
Query/Question
I'm attempting to move blobs to a fileshare, same region, same resource group, storage account. No matter what authentication method I use, it always fails with permissions issues. I want to use DefaultAzureCredential with a managed identity but have also tried a StorageSharedKeyCredential and various SAS scenarios. I've given the managed Identity Ownership. Contributor and tried individual fileshare and blob permission at the resource level. No luck and always the same permission issue. Can someone state exactly which IAM permission need to be granted to the managed identity and at what level to achieve this task?
class Program
{
static async Task Main(string[] args)
{
const string accountName = "sccccc2"; // Replace with your account name
const string blobContainerName = "bccccc2"; // Replace with your container name
const string blobName = "sydc.JPG"; // Replace with your blob name
const string fileShareName = "fdgsdffssfsg1"; // Replace with your file share name
const string filePathInShare = "sydc111.JPG"; // Replace with the file path in the file share
const string accountKey = "s="; // Replace with your account key
try
{
// Use DefaultAzureCredential for authentication (Managed Identity, Service Principal, or Interactive Login)
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
TenantId = "cxvzcxvzcczvcz",
ManagedIdentityClientId = "cxvccccccczvxretetr",
//#if DEBUG
// // This is a temporary workaround to allow local development without managed identity. Remove this block when the issue is resolved.
// ExcludeManagedIdentityCredential = true
//#endif
});
// Step 1: Set up Blob Storage Client with DefaultAzureCredential
var blobServiceClient = new BlobServiceClient(new Uri($"https://{accountName}.blob.core.windows.net"), credential);
var blobContainerClient = blobServiceClient.GetBlobContainerClient(blobContainerName);
var blockBlobClient = blobContainerClient.GetBlockBlobClient(blobName);
// Step 2: Set up File Share Client with DefaultAzureCredential
var shareServiceClient = new ShareServiceClient(new Uri($"https://{accountName}.file.core.windows.net"), credential);
var shareClient = shareServiceClient.GetShareClient(fileShareName);
var shareFileClient = shareClient.GetRootDirectoryClient().GetFileClient(filePathInShare);
// Step 3: Set up transfer options
TransferOptions options = new();
options.ItemTransferCompleted += onItemCompleted;
options.ItemTransferSkipped += onItemSkipped;
options.ItemTransferFailed += onItemFailed;
options.CreationMode = StorageResourceCreationMode.OverwriteIfExists;
var blob = BlobsStorageResourceProvider.FromClient(blockBlobClient);
var share = ShareFilesStorageResourceProvider.FromClient(shareFileClient);
//var azureSasKey = new Azure.Storage.StorageSharedKeyCredential(accountName, accountKey);
// Step 4: Set up the resource providers for Blob and File Share using DefaultAzureCredential
var sharesResource = new ShareFilesStorageResourceProvider(credential);
var blobsResource = new BlobsStorageResourceProvider(credential);
var transferManager = new TransferManager(new TransferManagerOptions());
// Step 5: Perform the transfer from Blob to File Share
var fileTransfer = await transferManager.StartTransferAsync(
sourceResource: await blobsResource.FromBlobAsync(blob.Uri),
destinationResource: await sharesResource.FromFileAsync(share.Uri),
transferOptions: options);
await fileTransfer.WaitForCompletionAsync();
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
private static Task onItemFailed(TransferItemFailedEventArgs e)
{
Console.WriteLine($"Item failed: {e.Exception.Message}");
return Task.CompletedTask;
}
private static Task onItemSkipped(TransferItemSkippedEventArgs e)
{
return Task.CompletedTask;
}
private static Task onItemCompleted(TransferItemCompletedEventArgs e)
{
return Task.CompletedTask;
}
}
Environment
.Net 9
Azure.Identity" Version="1.13.2"
Azure.Storage.Blobs" Version="12.24.0"
Azure.Storage.DataMovement" Version="12.1.0"
Azure.Storage.DataMovement.Blobs" Version="12.1.0"
Azure.Storage.DataMovement.Files.Shares" Version="12.1.0"
Azure.Storage.Files.Shares" Version="12.22.0"
Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.2"
Hello @BC89. I'm an AI assistant for the azure-sdk-for-net repository. I have some suggestions that you can try out while the team gets back to you.
- For data movement between blob storage and file shares using DefaultAzureCredential with a Managed Identity, ensure the identity has permissions on both resource types.
- Blob operations: Grant the Storage Blob Data Contributor role. This role allows read, write, and delete operations on blob containers (or alternatively, the Reader role if only reading is required).
- File share operations: Grant the Storage File Data SMB Share Contributor role. This role is required for read/write/delete operations on file shares.
- These roles should preferably be assigned at the storage account level so that they cover all containers and shares under that account.
- For more details on the built-in roles, see:
The team will get back to you shortly, hopefully this helps in the meantime.
I've tried this and still the same error:
Service request failed.
Status: 403 (This request is not authorized to perform this operation using this permission.)
ErrorCode: AuthorizationPermissionMismatch
Headers:
Transfer-Encoding: chunked
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 7581e186-e01e-0027-46de-986596000000
x-ms-client-request-id: 7960e679-9bdd-4546-9dc2-38abe4f474fd
x-ms-version: 2025-05-05
x-ms-error-code: AuthorizationPermissionMismatch
Access-Control-Allow-Origin: *
Date: Wed, 19 Mar 2025 14:55:27 GMT
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @amnguye @jalauzon-msft @jaschrep-msft @nickliu-msft @seanmcc-msft.
Anything?
Hi, thanks for submitting this issue. Just to clarify, this transfer does not work on any type of authentication you tried (shared key, SAS, and OAuth) or only on OAuth is it not working.
It's possible you may require higher elevated permissions due to copying over properties from blob to share file. Storage Blob Data Owner Storage File Data SMB Share Elevated Contributor
Are you able to enable logging? And show us the logs you got? https://learn.microsoft.com/en-us/dotnet/azure/sdk/logging
I've tried this and still the same error:
Service request failed. Status: 403 (This request is not authorized to perform this operation using this permission.) ErrorCode: AuthorizationPermissionMismatch Headers: Transfer-Encoding: chunked Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: 7581e186-e01e-0027-46de-986596000000 x-ms-client-request-id: 7960e679-9bdd-4546-9dc2-38abe4f474fd x-ms-version: 2025-05-05 x-ms-error-code: AuthorizationPermissionMismatch Access-Control-Allow-Origin: * Date: Wed, 19 Mar 2025 14:55:27 GMT
For this error you got, did you get this from the "onItemFailed(TransferItemFailedEventArgs e)" ? It might be worth it to also print out the stack trace so we can track down exactly what operation is failing here to get this error code.
It doesn't work regardless of the auth method I've tried. What permissions do you want me to try, obviously I can't just guess at them. And yes it's being thrown and caught by TransferItemFailedEventArgs event As for logs, I can print out the stack but can you duplicate in your test suit?
Get Outlook for Androidhttps://aka.ms/AAb9ysg
From: Amanda Nguyen @.> Sent: Monday, March 24, 2025 6:57:04 PM To: Azure/azure-sdk-for-net @.> Cc: Brendan Carroll @.>; Mention @.> Subject: [External Email] Re: [Azure/azure-sdk-for-net] [QUERY] DataMovement Required Permissions (Issue #48992)
From @. 410-316-7820 *** This is an External Email from outside of KCI.***
Hi, thanks for submitting this issue. Just to clarify, this transfer does not work on any type of authentication you tried (shared key, SAS, and OAuth) or only on OAuth is it not working. It's possible you may require higher elevated permissions due to copying over properties fro [https://image-processing-service.us-1.mimecastcybergraph.com/v2/banners?e=tm7eAWVahID9RBgSwPklgann8lYtnL4UqGuzcJhNnl16aiEgj_zIe_5ROa7Y1SLvqp0iki4dETBiQhGAFsEj-3FbZ3txKeY5p1oE-wZsOpcdLljgpV4QqY1zaMv7HEtPyMYLnxbTESVcOvaT0W_iK2ERw-Dx64P9y8e0ilGZkIDspKFsJwxD8ot-nuDJdQ0v2F_sat-rHJgiHLqZuu17mFt4H-6YCLX215n_jXY-KLIb_NeV1lrwTKUyoXwS0RDdsSERg2c8UH10xCt2Z43wd3dws9n-qebtj74vVGo3yWMFp9AG463FGbG0ejawkZnINOaI1-lDW1m404Srpsgink_qGcK_O6NJ8Nwbpz7GayItVLcdP0KiUtFrJcXgiChY]https://report.mimecastcybergraph.com?magiclink=https%3A%2F%2Fapi.services.mimecast.com%2Foauth2%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3Do20nRkVXf7VUVnANkXhoOwGytEwGN0YAlyeDJn7oBTGNl2kN%26state%3DeyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.NjRORM4YqZTgEAQqEyJDO2-oFH-jXXhD82UivSe5dbIDJV9RfPWvjeU2NgH4k_MB2gM7BQP1RCfpntgri1XlSa3PbkzMxrHEweeUAdoQV3FHgHTdSVWKT2nDNQH6RAMiYQAR52QkT3IPK9Hp2TBbZtizfWIy1yVG2tCw58YW3w4O1Cs9ujSIG3ys96JjdiOuHfPjcEZoKS7AxZSXS9UNsbS-TvVLB6TH5txdy-kGMkwCRJhRlTf1xSfXTRAAhlI5LyUKlqnVk6zOZt4hqu_PiFKZtpelmXIIo-BKGpk8X9g1zsix0FFrjrsa8HsS2qYEAQa0eAgmw9K-WRfjqYMWGA.D59eez6_cJSVmvi-.GlpB67aT000s1ZQE137Mu3670LT80NyLR6pljiz-NlhOR8cijDWQK_wtTdkBDv9H3dUd_YHxII5O-XvaSbjbJwrRB2gkseYpj-0iDhT5XOGTttCx_r9T0gXdYMD_NKFeLarLZKf2CTYnhuR8H5H1zARxWjuOeVWxyVUowi0pBifW9LrKoBt6TeWdJ_ZxPfeHALqQqHG-TDByEMMt6xJlAkGQY6l5vttvIRjXP9jqgsPN2uSkJtvuYMmoMrqC35BlQHLrWqiM2jv8OZSSWlvI0H0H_rjOpO_BIs-aFmqLMPi3bunlJ8GfP7hZUR61-H5Va_dSpuHqdjr4mfDfdTovlURfix9sUc2wyt5c-WiVJMjyACboL0J8DrfMkxCHEYvvcERMF4Ze8LBNXryft7hwGQ-JCjWjwBeEzLR2UxNWYghFdDcGLAFvw52flR5yJ1DNdzvdOANkCrXBTMWy_JJbgFwDwlyVd6CsaqccfHMnPABXz_F9n8GqDysYweeJPurz_iHHsZNItkxNgRQM4sednMtUkqMdEiS3PES9KR9Vu1yLiWxqGzDY_K9pJKB7ixkb2ZK8w-oEAu113GepfL13KmxDFI1gdgNOugLlTKqY9QuW9S4NgyL7ekhfuhf49HTtnqPL0qRdd0NZEakzbciF7OyUFDoF8pUa5-3aC4MbpYUvWTFYECx6-CbPRG6EVVejruUjqvl2YQcB9GQ1LfPrlZH0ZK5mfpsoreHIhczhlrczyEh72t456y46mqy2G0-tVBsLjyOrRnrn6TXsb83QYS-PcWfDomsC5RoTVBVSH5R24B8Jb7mxKWKsjDYiCAP2-i3NGgsW0Jnx83Lz8j214rCwVCOSgd_cmwnbsM5oWaTWFqFnWueZWfs-Wg.ELrpDdrrp0fJ4q_UVwklpQ%26redirect_uri%3Dhttps%3A%2F%2Freport.mimecastcybergraph.com%2Fcallback CGBANNERINDICATOR
Hi, thanks for submitting this issue. Just to clarify, this transfer does not work on any type of authentication you tried (shared key, SAS, and OAuth) or only on OAuth is it not working.
It's possible you may require higher elevated permissions due to copying over properties from blob to share file. Storage Blob Data Ownerhttps://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-blob-data-owner Storage File Data SMB Share Elevated Contributorhttps://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-file-data-smb-share-elevated-contributor
Are you able to enable logging? And show us the logs you got? https://learn.microsoft.com/en-us/dotnet/azure/sdk/logginghttps://learn.microsoft.com/en-us/dotnet/azure/sdk/logging
I've tried this and still the same error:
Service request failed. Status: 403 (This request is not authorized to perform this operation using this permission.) ErrorCode: AuthorizationPermissionMismatch
Headers: Transfer-Encoding: chunked Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: 7581e186-e01e-0027-46de-986596000000 x-ms-client-request-id: 7960e679-9bdd-4546-9dc2-38abe4f474fd x-ms-version: 2025-05-05 x-ms-error-code: AuthorizationPermissionMismatch Access-Control-Allow-Origin: * Date: Wed, 19 Mar 2025 14:55:27 GMT
For this error you got, did you get this from the "onItemFailed(TransferItemFailedEventArgs e)" ? It might be worth it to also print out the stack trace so we can track down exactly what operson is failing here to get this error code.
— Reply to this email directly, view it on GitHubhttps://github.com/Azure/azure-sdk-for-net/issues/48992#issuecomment-2749579002, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAZFIMZJSKBYNCCMECJMYDT2WCEUBAVCNFSM6AAAAABZK4RYC6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONBZGU3TSMBQGI. You are receiving this because you were mentioned.Message ID: @.***>
[amnguye]amnguye left a comment (Azure/azure-sdk-for-net#48992)https://github.com/Azure/azure-sdk-for-net/issues/48992#issuecomment-2749579002
Hi, thanks for submitting this issue. Just to clarify, this transfer does not work on any type of authentication you tried (shared key, SAS, and OAuth) or only on OAuth is it not working.
It's possible you may require higher elevated permissions due to copying over properties from blob to share file. Storage Blob Data Ownerhttps://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-blob-data-owner Storage File Data SMB Share Elevated Contributorhttps://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/storage#storage-file-data-smb-share-elevated-contributor
Are you able to enable logging? And show us the logs you got? https://learn.microsoft.com/en-us/dotnet/azure/sdk/logginghttps://learn.microsoft.com/en-us/dotnet/azure/sdk/logging
I've tried this and still the same error:
Service request failed. Status: 403 (This request is not authorized to perform this operation using this permission.) ErrorCode: AuthorizationPermissionMismatch
Headers: Transfer-Encoding: chunked Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-request-id: 7581e186-e01e-0027-46de-986596000000 x-ms-client-request-id: 7960e679-9bdd-4546-9dc2-38abe4f474fd x-ms-version: 2025-05-05 x-ms-error-code: AuthorizationPermissionMismatch Access-Control-Allow-Origin: * Date: Wed, 19 Mar 2025 14:55:27 GMT
For this error you got, did you get this from the "onItemFailed(TransferItemFailedEventArgs e)" ? It might be worth it to also print out the stack trace so we can track down exactly what operson is failing here to get this error code.
— Reply to this email directly, view it on GitHubhttps://github.com/Azure/azure-sdk-for-net/issues/48992#issuecomment-2749579002, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAZFIMZJSKBYNCCMECJMYDT2WCEUBAVCNFSM6AAAAABZK4RYC6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONBZGU3TSMBQGI. You are receiving this because you were mentioned.Message ID: @.***>
Unfortunately I couldn't duplicate your issue in my environment. Our nightly pipelines also have tests for blob to share file (and vice versa) and do not see the issue you see.
I'm asking for logs to further investigate and diagnosis your issue to hopefully unblock you.
Can you point me to the code that demonstrates copying from a BlockBlob to a FileShare?
Stack:
at Azure.Core.HttpPipelineExtensions.ProcessMessageAsync(HttpPipeline pipeline, HttpMessage message, RequestContext requestContext, CancellationToken cancellationToken)
at Azure.Storage.Blobs.BlobRestClient.GetPropertiesAsync(String snapshot, String versionId, Nullable`1 timeout, String leaseId, String encryptionKey, String encryptionKeySha256, String encryptionAlgorithm, String ifTags, RequestConditions requestConditions, RequestContext context)
at Azure.Storage.Blobs.Specialized.BlobBaseClient.GetPropertiesInternal(BlobRequestConditions conditions, Boolean async, RequestContext context, String operationName)
at Azure.Storage.Blobs.Specialized.BlobBaseClient.GetPropertiesAsync(BlobRequestConditions conditions, CancellationToken cancellationToken)
at Azure.Storage.DataMovement.Blobs.BlockBlobStorageResource.GetPropertiesAsync(CancellationToken cancellationToken)
at Azure.Storage.DataMovement.ServiceToServiceJobPart.ProcessPartToChunkAsync()
Can you point me to the code that demonstrates copying from a BlockBlob to a FileShare?
Yup! We have tests here if that's what you're asking for: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.DataMovement.Blobs.Files.Shares/tests/BlockBlobToShareFileTests.cs https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/Azure.Storage.DataMovement/tests/Shared/StartTransferCopyTestBase.cs#L364
Thanks for providing the stack trace. It's failing on a simple Get Properties call on the source Block Blob. So it hasn't yet performed the Copy operation yet.
Can you do a quick check so we can verify permissions?
Keep this part of your code
// Use DefaultAzureCredential for authentication (Managed Identity, Service Principal, or Interactive Login)
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
TenantId = "cxvzcxvzcczvcz",
ManagedIdentityClientId = "cxvccccccczvxretetr",
//#if DEBUG
// // This is a temporary workaround to allow local development without managed identity. Remove this block when the issue is resolved.
// ExcludeManagedIdentityCredential = true
//#endif
});
// Step 1: Set up Blob Storage Client with DefaultAzureCredential
var blobServiceClient = new BlobServiceClient(new Uri($"https://{accountName}.blob.core.windows.net"), credential);
var blobContainerClient = blobServiceClient.GetBlobContainerClient(blobContainerName);
var blockBlobClient = blobContainerClient.GetBlockBlobClient(blobName);
then add
await blockBlobClient.GetPropertiesAsync();
If it throws then we know it's a permissions issue. If it doesn't throw then there's more to be done investigation on my end.
It does not throw an error and all the properties are returned as expected.
var props = await blockBlobClient.GetPropertiesAsync();
Console.WriteLine($"Blob URI: {blockBlobClient.Uri}");
Console.WriteLine($"Blob size: {props.Value.ContentLength}");
Blob URI: https://......blob.core.windows.net/....eve2/1.jpg
Blob size: 7687648
As stated previously, I've also tried with SasCredentials and get the same result. Interestingly with the SasCredential approach the file placeholder is created in the share with the correct size but then copying the content from blob to share throws the same error in the onItemFailled event and we're left a file missing all the content bytes. I don't even get this far with the ManagedIdentity approach.
using Azure;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;
using Azure.Storage.DataMovement;
using Azure.Storage.DataMovement.Blobs;
using Azure.Storage.DataMovement.Files.Shares;
using Azure.Storage.Files.Shares;
using Azure.Storage.Sas;
class Program
{
static async Task Main(string[] args)
{
const string accountName = "gfhgfhgfhve2"; // Replace with your account name
const string blobContainerName = "gfhgfhgfeve2"; // Replace with your container name
const string blobName = "1.jpg"; // Replace with your blob name
const string fileShareName = "45654654654654222a1"; // Replace with your file share name
const string filePathInShare = "1.jpg"; // Replace with the file path in the file share
const string accountKey = "Key"; // Replace with your account key
try
{
// Generate SAS token for Blob
var blobServiceClient = new BlobServiceClient(new Uri($"https://{accountName}.blob.core.windows.net"), new StorageSharedKeyCredential(accountName, accountKey));
var blobContainerClient = blobServiceClient.GetBlobContainerClient(blobContainerName);
var blockBlobClient = blobContainerClient.GetBlockBlobClient(blobName);
var props = await blockBlobClient.GetPropertiesAsync();
Console.WriteLine($"Blob URI: {blockBlobClient.Uri}");
Console.WriteLine($"Blob size: {props.Value.ContentLength}");
var blobSasBuilder = new BlobSasBuilder
{
BlobContainerName = blobContainerName,
BlobName = blobName,
Resource = "b",
ExpiresOn = DateTimeOffset.UtcNow.AddHours(8)
};
blobSasBuilder.SetPermissions(BlobSasPermissions.Read);
var blobSasUri = blockBlobClient.GenerateSasUri(blobSasBuilder);
// Remove SAS token from URI
var blobUriBuilder = new BlobUriBuilder(blobSasUri)
{
Sas = null
};
var blobUriWithoutSas = blobUriBuilder.ToUri();
// Generate SAS token for File Share
var shareServiceClient = new ShareServiceClient(new Uri($"https://{accountName}.file.core.windows.net"), new StorageSharedKeyCredential(accountName, accountKey));
var shareClient = shareServiceClient.GetShareClient(fileShareName);
var shareFileClient = shareClient.GetRootDirectoryClient().GetFileClient(filePathInShare);
var shareSasBuilder = new ShareSasBuilder
{
ShareName = fileShareName,
FilePath = filePathInShare,
Resource = "f",
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
shareSasBuilder.SetPermissions(ShareFileSasPermissions.Write);
var shareSasUri = shareFileClient.GenerateSasUri(shareSasBuilder);
// Remove SAS token from URI
var shareUriBuilder = new ShareUriBuilder(shareSasUri)
{
Sas = null
};
var shareUriWithoutSas = shareUriBuilder.ToUri();
var destinationFileUri = $"{shareClient.Uri}/{filePathInShare}";
// Set up the blob to file share copy options
TransferOptions options = new();
options.ItemTransferCompleted += onItemCompleted;
options.ItemTransferSkipped += onItemSkipped;
options.ItemTransferFailed += onItemFailed;
options.CreationMode = StorageResourceCreationMode.OverwriteIfExists;
var shares = new ShareFilesStorageResourceProvider(new AzureSasCredential(shareSasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(accountName, accountKey)).ToString()));
var blobs = new BlobsStorageResourceProvider(new AzureSasCredential(blobSasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(accountName, accountKey)).ToString()));
var transferManager = new TransferManager(new TransferManagerOptions());
// Perform the transfer from Blob to File Share in chunks
var fileTransfer = await transferManager.StartTransferAsync(
sourceResource: await blobs.FromBlobAsync(blobUriWithoutSas),
destinationResource: await shares.FromFileAsync(new Uri(destinationFileUri)),
transferOptions: options);
await fileTransfer.WaitForCompletionAsync();
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
}
private static Task onItemFailed(TransferItemFailedEventArgs e)
{
Console.WriteLine($"Item failed: {e.Exception.Message}");
return Task.CompletedTask;
}
private static Task onItemSkipped(TransferItemSkippedEventArgs e)
{
return Task.CompletedTask;
}
private static Task onItemCompleted(TransferItemCompletedEventArgs e)
{
return Task.CompletedTask;
}
}
Hi, sorry for the late reply. I am still investigating your issue.
That is interesting that doing a GetProperties call was successful for you with the same credentials as attempting to do a transfer. I haven't been able to reproduce the same error, of AuthorizationPermissionMismatch that you ran into. I've tried some funky stuff but I'm still not able to reproduce the issue.
As for trying using an SAS Credential, it's different due to the fact that you've signed the SAS with a Shared Key and you've set the permissions correctly with the source being Read and the destination being Write. The File Share's Put Range from URL failing is interesting, does it fail with the same Error code of AuthorizationPermissionMismatch ?
I wonder if it has anything to do with how the credential is passed to the provider (though this works on my end)
Could you try passing the blob / share file client to the provider?
Here's an example:
TokenCredential tokenCredential = new DefaultAzureCredential();
var blobServiceClient = new BlobServiceClient(new Uri($"https://{accountName}.blob.core.windows.net"), credential);
var blobContainerClient = blobServiceClient.GetBlobContainerClient(blobContainerName);
var blockBlobClient = blobContainerClient.GetBlockBlobClient(blobName);
var shareServiceClient = new ShareServiceClient(new Uri($"https://{accountName}.file.core.windows.net"), credential);
var shareClient = shareServiceClient.GetShareClient(fileShareName);
var shareFileClient = shareClient.GetRootDirectoryClient().GetFileClient(filePathInShare);
TransferOperation transfer = await transferManager.StartTransferAsync(
BlobsStorageResourceProvider.FromClient(blockBlobClient),
ShareFilesStorageResourceProvider.FromClient(shareFileClient),
transferOptions);
So passing the clients directly to the providers results in the same error, GetProperties on the source works, a file is created in the share but fails on copying the contents.
Server failed to authenticate the request. Please refer to the information in the www-authenticate header.
RequestId:3079940d-a01a-0036-7d0c-a3ff22000000
Time:2025-04-01T13:48:27.2646989Z
Status: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.)
ErrorCode: CannotVerifyCopySource
Additional Information:
CopySourceStatusCode: 401
CopySourceErrorCode: NoAuthenticationInformation
CopySourceErrorMessage: Server failed to authenticate the request. Please refer to the information in the www-authenticate header.
I also wanted to note that this managedIdentity is used throughout the existing application to w/out issue to manipulate all the file in both the share and blob containers using the following:
<PackageReference Include="Azure.Identity" Version="1.13.2" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.24.0" />
<PackageReference Include="Azure.Storage.Files.Shares" Version="12.22.0" />
I sure would like to get this working because the performance of those libraries is just awful with large files, specifically StartCopyAsync and UploadRangeFromUriAsync has very low size capacity (4mb). Kinda stuck.
I can reproduce the same issue as @BC89 .
You can easily reproduce it with the CopyBlobToShare test I found in the source code.
`Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:f2f96c80-101a-000d-63f4-a75956000000 Time:2025-04-07T19:35:34.4792887Z Status: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.) ErrorCode: CannotVerifyCopySource
Additional Information: CopySourceStatusCode: 401 CopySourceErrorCode: NoAuthenticationInformation CopySourceErrorMessage: Server failed to authenticate the request. Please refer to the information in the www-authenticate header.
Content: <Error><Code>CannotVerifyCopySource</Code><Message>Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:f2f96c80-101a-000d-63f4-a75956000000 Time:2025-04-07T19:35:34.4792887Z</Message><CopySourceStatusCode>401</CopySourceStatusCode><CopySourceErrorCode>NoAuthenticationInformation</CopySourceErrorCode><CopySourceErrorMessage>Server failed to authenticate the request. Please refer to the information in the www-authenticate header.</CopySourceErrorMessage></Error>
Headers: x-ms-request-id: f2f96c80-101a-000d-63f4-a75956000000 x-ms-client-request-id: 740feabb-310f-4a0f-adaa-989259011a7c x-ms-version: 2025-05-05 x-ms-copy-source-status-code: 401 x-ms-copy-source-error-code: NoAuthenticationInformation x-ms-error-code: CannotVerifyCopySource Content-Length: 570 Content-Type: application/xml Date: Mon, 07 Apr 2025 19:35:33 GMT Server: Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0`
Or with this code which copies from a FileShare to a Blob Storage
`var credentials = new StorageSharedKeyCredential(_storageAccountName, _storageAccountKey);
var files = new ShareFilesStorageResourceProvider(credentials); var blobs = new BlobsStorageResourceProvider(credentials);
var source = await files.FromFileAsync(new Uri("set a valid file URI here")); var dest = await blobs.FromBlobAsync(new Uri("Set an uri with a valid container and new filename"));
var transferManager = new TransferManager();
var dataTransferOptions = new TransferOptions { CreationMode = StorageResourceCreationMode.OverwriteIfExists }; dataTransferOptions.ItemTransferFailed += DataTransferOption_ItemTransferFailed;
var dataTransfer = await transferManager.StartTransferAsync(source, dest, dataTransferOptions);
await dataTransfer.WaitForCompletionAsync();
if (!dataTransfer.Status.HasCompletedSuccessfully) throw new Exception($"The file wasn't copied to the blob storage.");`
Reading this Known Issue - Copy with a AzureSASCredential
I was expecting the following code to work. But it still does not work.
public async Task CopyFileToBlob(Uri fileUri, Uri blobUri)
{
/* The solution might be a SAS link. There is an example on how to create it with datamovemetn api source code in github. */
var files = new ShareFilesStorageResourceProvider(GenerateShareSasCredential(fileUri));
var blobs = new BlobsStorageResourceProvider(GenerateBlobSasCredential(blobUri));
var source = await files.FromFileAsync(fileUri);
var dest = await blobs.FromBlobAsync(blobUri);
var transferManager = new TransferManager();
var dataTransferOptions = new TransferOptions { CreationMode = StorageResourceCreationMode.OverwriteIfExists };
dataTransferOptions.ItemTransferFailed += DataTransferOption_ItemTransferFailed;
var dataTransfer = await transferManager.StartTransferAsync(source, dest, dataTransferOptions);
await dataTransfer.WaitForCompletionAsync();
if (!dataTransfer.Status.HasCompletedSuccessfully)
throw new Exception($"The file wasn't copied to the blob storage.");
}
public AzureSasCredential GenerateShareSasCredential(Uri uri)
{
var credentials = new StorageSharedKeyCredential(_storageAccountName, _storageAccountKey);
var pathUri = new ShareUriBuilder(uri);
var sas = new ShareSasBuilder(ShareSasPermissions.All, DateTimeOffset.Now.AddHours(1))
{
ShareName = pathUri.ShareName,
FilePath = pathUri.DirectoryOrFilePath,
};
var sasQueryParam = sas.ToSasQueryParameters(credentials);
return new AzureSasCredential(sasQueryParam.Signature);
}
public AzureSasCredential GenerateBlobSasCredential(Uri uri)
{
var credentials = new StorageSharedKeyCredential(_storageAccountName, _storageAccountKey);
var pathUri = new BlobUriBuilder(uri);
var sas = new BlobSasBuilder(BlobContainerSasPermissions.All, DateTimeOffset.Now.AddHours(1))
{
BlobName = pathUri.BlobName,
BlobContainerName = pathUri.BlobContainerName,
};
var sasQueryParam = sas.ToSasQueryParameters(credentials);
return new AzureSasCredential(sasQueryParam.Signature);
}
Could you detail how to implement the suggestion in Know Issue
1- Use BlobsStorageResourceProvider(AzureSasCredential) / ShareFilesStorageResourceProvider(AzureSasCredential) to authenticate and then create StorageResource. 2- Initialize a client with a Uri that has a SAS included in the Uri if you still want to use BlobStorageResourceProvider.FromClient and/or ShareStorageResourceProvider.FromClient.
Thanks!
Very frustrating because I can get the source blob properties, the transfer begins and the file is created in the fileshare showing the correct size but then the implementation fails when pushing the content. It seems to me that permissions must be fine if it's able to get the blob properties and create the shell file in the share. Perhaps the content transfer SAS gets whacked at some point in the internals of the StartTrasferAsync?