2

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

Piotr Perak
  • 10,718
  • 9
  • 49
  • 86
  • 1
    FYI - removed the SAS tag as I don't think this relates to the software SAS. – Reeza Jul 07 '20 at 19:18
  • 1
    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. – Jim Xu Jul 08 '20 at 05:06
  • @JimXu it is assigned `Storage Blob Data Contributor` role. I added request in response in my post. After this I also removed those ENV variables to try out `SharedTokenCacheCredential` (my account also is assigned correct role) but I receive same error. – Piotr Perak Jul 08 '20 at 06:23
  • 1
    According to the response you provide, it seems that the expire date is out of 7 days. Please update code as `blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(6))`; – Jim Xu Jul 08 '20 at 06:59
  • @JimXu It worked! Thanks. But can you explain to me where do you see it? – Piotr Perak Jul 08 '20 at 07:48
  • According to response body error message, it says `2020-07-15T06:17:35Z2020-07-15T06:17:35Z` and the request body is `2020-07-15T06:17:35Z`,. thereforI think the expire may be out of 7 days. But the expire time must be a time within 7 days. Otherwise, it will return error. – Jim Xu Jul 08 '20 at 08:10

1 Answers1

1

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();

enter image description here

Jim Xu
  • 21,610
  • 2
  • 19
  • 39
  • But documentation says this: `UserDelegationKey key = await blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(7));` - which is not 7 days btw because you get `DateTimeOffset.UtcNow` twice. And it works on Azure and not on local machine. What's the difference? – Piotr Perak Jul 08 '20 at 08:15
  • 1
    @PiotrPerak it may that your local region and Azure storage data center region are different. When you send the request to Azure storage data center, the time is done some process. – Jim Xu Jul 08 '20 at 08:23
  • It's probably this. When I changed to `DateTimeOffset.UtcNow.AddDays(7).AddHours(-2) ` it also works. – Piotr Perak Jul 08 '20 at 08:28