Azure Blob Storage - sp is mandatory. Cannot be empty - azure

I am getting error while trying to upload a file to Azure Blob Storage using SAS link. Its an authentication error complaining about empty sp attribute. The wierd thing is Sp element is present in SAS Url.
It cannot be a permission issue as I am able to upload the file using the same SAS URL using ADF.
Url
BlobEndpoint=https://####.blob.core.windows.net/####?sp=racwdl&st=2021-12-08T01:14:01Z&se=2022-02-28T09:14:01Z&spr=https&sv=2020-08-04&sr=c&sig=####
Details of error
Server failed to authenticate the request. Make sure the value of
Authorization header is formed correctly including the signature.
RequestId:ed57ec28-f01e-00a9-79d2-ebcfc2000000
Time:2021-12-08T01:22:40.1147833Z Status: 403 (Server failed to
authenticate the request. Make sure the value of Authorization header
is formed correctly including the signature.) ErrorCode:
AuthenticationFailed
Additional Information: AuthenticationErrorDetail: sp is mandatory.
Cannot be empty
Content: AuthenticationFailedServer
failed to authenticate the request. Make sure the value of
Authorization header is formed correctly including the signature.
RequestId:ed57ec28-f01e-00a9-79d2-ebcfc2000000
Time:2021-12-08T01:22:40.1147833Zsp
is mandatory. Cannot be empty
Headers: x-ms-request-id: ed57ec28-f01e-00a9-79d2-ebcfc2000000
x-ms-error-code: AuthenticationFailed Content-Length: 407
Content-Type: application/xml Date: Wed, 08 Dec 2021 01:22:39 GMT
Server: Microsoft-HTTPAPI/2.0
Code
Stream file = new FileStream(fileToUpload, FileMode.Open);
var blobServiceClient1 = new BlobServiceClient(endpointString);
var containerRef = blobServiceClient1.GetBlobContainerClient("dropoff-commissionstatements");
var blob1 = containerRef.GetBlobClient("TDM_FINAL_102449_13092021_COMMSTMT_AR_TAL_D95337.csv");
string file_extension = Path.GetExtension(fileToUpload);
string filename_withExtension = Path.GetFileName(fileToUpload);
blob1.Upload(file);

Please try by changing your connection string to something like:
BlobEndpoint=https://####.blob.core.windows.net/####; SharedAccessSignature=sp=racwdl&st=2021-12-08T01:14:01Z&se=2022-02-28T09:14:01Z&spr=https&sv=2020-08-04&sr=c&sig=####
For more details, please see this link: https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string#create-a-connection-string-using-a-shared-access-signature.

Related

Azure Log Analytics API returns InvalidAuthorization even though the credentials are correct

The Azure Log Analytics API is returning this message:
{"Error":"InvalidAuthorization","Message":"An invalid signature was specified in the Authorization header"}
Even though the Authorization: SharedKey header is correct.
Turns out the Azure Log Analytics API does not support content type extensions and most modern http clients will generate a request header like this:
Content-Type: application/json; charset=utf-8
This will not work and you will get the cryptic response message above.
Overriding the header to simply:
Content-Type: application/json
Will fix the problem

Simple UploadPage azure blob using pageBlobClient

I am using Premium/Hot, LRS, StorageV2 Azure storage and trying to write a simple string but I keep getting an authentication error.
To generate the SAS URI of the container in the portal, I went to:
storage resource -> containers -> my container -> shared access token -> generate SAS token and URL
// SAS URI of blob container
var sasUriStr = "https://storageaccountname.blob.core.windows.net/containername?sp=r&st=2021-08-10T00:34:00Z&se=2021-08-15T08:34:00Z&spr=https&sv=2020-08-04&sr=c&sig=ABCDEFGH/YJKLMNOP=";
var uri = new Uri(sasUriStr);
var pageBlobClient = new PageBlobClient(uri);
pageBlobClient.UploadPages(new MemoryStream(Encoding.UTF8.GetBytes("hello world")), 0);
Unhandled exception. Azure.RequestFailedException: Server failed to
authenticate the request. Make sure the value of Authorization header
is formed correctly including the signature.
Time:2021-08-12T20:22:44.0905117Z Status: 403 (Server failed to
authenticate the request. Make sure the value of Authorization header
is formed correctly including the signature.) ErrorCode:
AuthenticationFailed
Additional Information: AuthenticationErrorDetail: Signature did not
match. String to sign used was r
I appreciate any help or hint. Thank you
UPDATE:
After adding /blob name to SAS URI I get this error:
Unhandled exception. Azure.RequestFailedException: The value for one of the HTTP headers is not in the correct format.
RequestId:7a741951-401c-00c9-3ce3-8f5076000000
Time:2021-08-13T01:38:13.4585107Z
Status: 400 (The value for one of the HTTP headers is not in the correct format.)
ErrorCode: InvalidHeaderValue
Additional Information:
HeaderName: x-ms-range
HeaderValue: bytes=0-10
Content:
<?xml version="1.0" encoding="utf-8"?>
<Error><Code>InvalidHeaderValue</Code><Message>The value for one of the HTTP headers is not in the correct format.
RequestId:7a741951-401c-00c9-3ce3-8f5076000000
Time:2021-08-13T01:38:13.4585107Z</Message><HeaderName>x-ms-range</HeaderName><HeaderValue>bytes=0-10</HeaderValue></Error>
Headers:
Server: Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0
x-ms-error-code: InvalidHeaderValue
x-ms-request-id: 7a741951-401c-00c9-3ce3-8f5076000000
x-ms-version: 2020-08-04
x-ms-client-request-id: 4366d771-7f70-4bbf-9677-6e9fcf3cb7a1
Date: Fri, 13 Aug 2021 01:38:12 GMT
Content-Length: 327
Content-Type: application/xml
Solution
Please change your code to something like:
var sasUriStr = "https://storageaccountname.blob.core.windows.net/containername?sp=r&st=2021-08-10T00:34:00Z&se=2021-08-15T08:34:00Z&spr=https&sv=2020-08-04&sr=c&sig=ABCDEFGH/YJKLMNOP=";
var uri = new Uri(sasUriStr);
BlobContainerClient containerClient = new BlobContainerClient(uri);
var pageBlobClient = containerClient.GetPageBlobClientCore("page-blob-name");
pageBlobClient.UploadPages(new MemoryStream(Encoding.UTF8.GetBytes("hello world")), 0);
Please ensure that the blob already exists before you use this code.
Problem
The reason you were running into the problem is because you were trying to create a PageBlobClient using a URI representing a blob container SAS. Because of this, Azure Storage service assumed that your blob name is containername and the container is $root. Since the SAS token was obtained for containername blob container and the service used $root blob container for validating the SAS token, you are getting authorization failed error.
By creating a BlobContainerClient using the SAS URL and then creating a PageBlobClient using BlobContainerClient.GetPageBlobClientCore(String) solves the problem.

Azure KeyVault 403 Forbidden when using Principal Account to access

I created an Azure KeyVault that I want my App Service to be able to access. From what I can tell, the principal of my App Service should have access to the KeyVault, but I always get the following error when trying to retrieve from it. This happens whether I am running locally in Visual Studio or in Azure.
Service request failed. Status: 403 (Forbidden) Content: {"error":{"code":"Forbidden","message":"The policy requires the caller 'appid=MY_APP_ID;oid=MY_PRINCIPAL_ID_STARTING_WITH_1A5 ;iss=https://sts.windows.net/REDACTED_GUID/' to use on-behalf-of (OBO) flow. For more information on OBO, please see https://go.microsoft.com/fwlink/?linkid=2152310","innererror":{"code":"ForbiddenByPolicy"}}} Headers: Pragma: no-cache x-ms-keyvault-region: westus x-ms-client-request-id: REDACTED x-ms-request-id: REDACTED x-ms-keyvault-service-version: 1.2.236.0 x-ms-keyvault-network-info: conn_type=Ipv4;addr=52.155.40.204;act_addr_fam=InterNetwork; Strict-Transport-Security: REDACTED X-Content-Type-Options: REDACTED Content-Length: 387 Cache-Control: no-cache Content-Type: application/json; charset=utf-8 Date: Wed, 21 Apr 2021 20:10:33 GMT Expires: -1 X-Powered-By: REDACTED
I have looked at the linked KB article and it talks about OAUTH`. I am not trying to use OAUTH, so I don't understand why that is relevant.
Here is the access policy in my KeyVault:
Here is the screenshot from the App Service where I configured a principal.
It clearly says at the bottom that it can be configured to access other resources, so I don't understand why it cannot access KeyVault.
Code used to attempt to access.
var kvUri = "https://" + Properties.Settings.Default.KeyVaultName + ".vault.azure.net";
var credential = new DefaultAzureCredential();
var client = new SecretClient(new Uri(kvUri),credential );
var result = client.GetSecret(secret);
When you set access policy, you need to select service principal with only object id (without app id).
See this similar post answer.

Azure Blob: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)

I have the sas token with write permission but when I am trying to write the blob getting the below error.
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:6c52482f-c01e-001c-5891-b2f06f000000
Time:2020-11-04T10:03:01.6761446Z
Status: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.)
ErrorCode: AuthenticationFailed
Headers:
x-ms-request-id: 6c52482f-c01e-001c-5891-b2f06f000000
x-ms-error-code: AuthenticationFailed
Date: Wed, 04 Nov 2020 10:03:00 GMT
Server: Microsoft-HTTPAPI/2.0
Content-Length: 529
Content-Type: application/xml
Code:
var blobClient = new BlobClient(new Uri(command.AzureBlobContainerTargetUri.AbsoluteUri));
using (var ms = new MemoryStream())
{
LoadStreamWithJson(ms, JsonConvert.SerializeObject(userData));
await blobClient.UploadAsync(ms);
}
command.AzureBlobContainerTargetUri.AbsoluteUri --> sas token uri
userData- some object
The error is always related to your access key as SumanthMarigowda said in the comment. Please regenerate the key in the portal and try with the new one. And check your PC's time, in addition to time check your VPN as well.
I also faced the error when using DefaultAzureCredential(). This is the issue(see the UPDATE) with Python.

Generate user delegation SAS token running locally

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

Resources