I'm creating solution based on this [documentation][1]. I have it almost working as I want to but it works only when deployed to Azure. App Service has Managed Identity configured and it is assigned Storage Blob Data Contributor
role. Is there any way to make it run on my local machine? Currently I need to publish code from VS to Azure and then use Remote debugging to verify how it works.
This is the problematic line:
userDelegationKey key = await blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(7));
I get exception:
Status: 400 (The value for one of the XML nodes is not in the correct format.)
ErrorCode: InvalidXmlNodeValue
I use DefaultAzureCredentials
and in debug I see it has 3 different sources. First of them is EnvironmentCredential
(then ManagedIdentityCredential
and SharedTokenCacheCredential
). So I tried registering application in Azure AD and configured those 3 env variables but it didn't help. Maybe I need to add some specific permissions to this app?
"AZURE_CLIENT_ID": "",
"AZURE_CLIENT_SECRET": "",
"AZURE_TENANT_ID": ""
Or maybe this could somehow work with my account in Azure? If I'm also assigned Storage Blob Data Contributor
role?
EDIT: I captured request and response with Fiddler
Request:
POST https://myaccount.blob.core.windows.net/?restype=service&comp=userdelegationkey HTTP/1.1
Host: myaccount.blob.core.windows.net
x-ms-version: 2019-07-07
x-ms-client-request-id: 23071825-dcf0-4803-a8a9-c44ec38695d5
x-ms-return-client-request-id: true
User-Agent: azsdk-net-Storage.Blobs/12.4.4 (.NET Core 3.1.2; Microsoft Windows 10.0.16299)
Authorization: Bearer Hidden
traceparent: 00-7e23f80250325742853c846211a83d02-6739d4cbc8ef0a46-00
Content-Type: application/xml
Content-Length: 91
<KeyInfo><Start>2020-07-08T06:02:35Z</Start><Expiry>2020-07-15T06:17:35Z</Expiry></KeyInfo>
Response:
HTTP/1.1 400 The value for one of the XML nodes is not in the correct format.
Content-Length: 348
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: ba2fe641-f01e-0065-3eef-54acae000000
x-ms-client-request-id: 23071825-dcf0-4803-a8a9-c44ec38695d5
x-ms-version: 2019-07-07
x-ms-error-code: InvalidXmlNodeValue
Date: Wed, 08 Jul 2020 06:16:14 GMT
<?xml version="1.0" encoding="utf-8"?><Error><Code>InvalidXmlNodeValue</Code><Message>The value for one of the XML nodes is not in the correct format.
RequestId:ba2fe641-f01e-0065-3eef-54acae000000
Time:2020-07-08T06:16:15.7553428Z</Message><XmlNodeName>2020-07-15T06:17:35Z</XmlNodeName><XmlNodeValue>2020-07-15T06:17:35Z</XmlNodeValue></Error>
EDIT 2: It works with help from @JimXu. In addition I was able to make it work with Azure account configured in Visual Studio so I could remove application registration that I created just for this purpose in Azure AD. [1]: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet#example-get-a-user-delegation-sas
If you want to get Azure storage account User Delegation Key, you need to assign Storage Blob Data Contributor
, Storage Blob Data Owner
or Storage Blob Delegator
to the AD application or account. For more details, please refer to the document
Besides, please note that when we get Azure storage account User Delegation Key, we need to provide the expire time. Its value must be a valid date and time within 7 days of the current time. For more details, please refer to here.
For example
string accountName = "jimtestdiag417";
string blobEndpoint = $"https://{accountName}.blob.core.windows.net/";
// Create a new Blob service client with Azure AD credentials.
BlobServiceClient blobClient = new BlobServiceClient(new Uri(blobEndpoint),
new DefaultAzureCredential();
// Get a user delegation key for the Blob service that's valid for seven days.
// to avoid clock skew between the requesting pc and azure servers, please set expire time in future six days
UserDelegationKey key = await blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(6));
// Read the key's properties.
Console.WriteLine("User delegation key properties:");
Console.WriteLine("Key signed start: {0}", key.SignedStartsOn);
Console.WriteLine("Key signed expiry: {0}", key.SignedExpiresOn);
Console.WriteLine("Key signed object ID: {0}", key.SignedObjectId);
Console.WriteLine("Key signed tenant ID: {0}", key.SignedTenantId);
Console.WriteLine("Key signed service: {0}", key.SignedService);
Console.WriteLine("Key signed version: {0}", key.SignedVersion);
Console.WriteLine();