Getting a blob content using user delegation SAS created using user delegation key - azure

I have created an AAD app as per https://learn.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app.
The access is given to the azure storage account for the AAD app created.
Got the client id and client secret.
To create a user delegation key and user delegation sas, I am using the approach and code as defined in
https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet.
(set environment variables as mentioned in article).
I am able to generate the user delegation key using method GetUserDelegationSasBlob.
The container and blob file is existing one.
Now I am using the method ReadBlobWithSasAsync to read the contents of the blob using the SAS uri as generated above.
But, I get error as below.
This request is not authorized to perform this operation using this
permission. RequestId:5d127eaf-101e-00be-6666-6a3875000000
Time:2019-09-13T19:04:15.4109144Z
Status: 403 (This request is not authorized to perform this operation
using this permission.)
ErrorCode: AuthorizationPermissionMismatch
In another approach, I am generating the user delegation key using rest api.
https://learn.microsoft.com/en-us/rest/api/storageservices/get-user-delegation-key
I am able to get user delegation key in xml format.
I am creating SAS from it as per steps in
https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas
For signature, I am using this code, using StringToSign and secret value as received from delegation key.
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(ToSign);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
String sig= Convert.ToBase64String(hashmessage);
}
I am doing the GET request.
I have tried various set of parameter values, like,
sr: b and c
sks: b and c
sp: racwd and r and rw and few more
skv and sv is 2018-11-09 because this version is required for creating user delegation key.
But the GET api returns the error.
AuthenticationFailed
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the
signature. RequestId:e4bc8f0f-d01e-0046-7367-6af368000000
Time:2019-09-13T19:12:27.7780695Z
Signature fields not well formed.

Try to assign the Storage Blob Data Contributor role to the storage account.
The Reader role is an Azure Resource Manager role that permits users to view storage account resources, but not modify them. It does not provide read permissions to data in Azure Storage, but only to account management resources.
Refer to this article.

Related

How to Fetch Token to access APIM from Function App with Managed identity

I am trying to access APIM from Azure Function and want APIM to authenticate through Managed Identity Token. I have assigned system assigned identity to the function app.I am following this (sample)[https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet#asal] to generate token. In the below line if I give "https://vault.azure.net" to GetAccessTokenAsync method I am getting the token. but I want the audience to be APIM so I provided https://azure-api.net like mentioned in the last line. but I am getting exception. how can I provide the APIM Url to fetch the access token?
using Microsoft.Azure.Services.AppAuthentication;
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://vault.azure.net");
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://azure-api.net");
An Update. I think something wrong with listing the resources. because when I give the proper resource name it says resource doesnt exist in the tenant though I can see the subscription is under the same tenant when I run through az cli.
As I mentioned in the comment, you need to Register an application in Azure AD to represent the API, then you can get the token for it(i.e. with the Application ID URI in the previous link).
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("<Application ID URI>");
Something you need to know:
You can use azureServiceTokenProvider to get the token for https://vault.azure.net, https://managment.azure.com, because they are all the APIs exposed by Microsoft, i.e. azure keyvault rest api and azure management rest api, essentially they are all AD App registered by Microsoft, so if you want to get the token for your own API, you need to register the AD App first to represent the API first.
Also, when you use managed identity to get the token, essentially it uses the client credential flow to get the token, actually the managed identity is a service principal(i.e. enterprise application) managed by azure. Remember to leverage the app role if you need to validate the roles claim when you get the access token.

List Queues/Topics of Azure Service Bus using Rest API with SharedAccessKey

I am trying to list the Queues/Topics in an Azure Service Bus using the REST API.
When I try to connect I just get back a blank feed saying "This is the list of publicly-listed services currently available".
I am using the RootManageSharedAccessKey in the portal (for dev only, I can create a more restricted key later) so it should have all the access rights that I need, I just can't seem to get it to return anything. This documentation seems to suggest that this will work, but there's no actual working examples, just theoretical responses.
I have tried doing a GET request with the signature in the URL like this:
https://myservicebusnamespace.servicebus.windows.net/$Resources/Queues;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=MYSHAREDACCESSKEY
I have also tried doing it like this:
https://myservicebusnamespace.servicebus.windows.net/$Resources
and then setting the Authorization header to
WRAP access_token="MYSHAREDACCESSKEY="
Both times I just get this back
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text">Publicly Listed Services</title>
<subtitle type="text">This is the list of publicly-listed services currently available.</subtitle>
<id>uuid:6a5d438d-1793-451b-be41-XXXXXXXXXXXX;id=XXXXXX</id>
<updated>2020-06-28T13:03:04Z</updated>
<generator>Service Bus 1.1</generator>
</feed>
If I change the url slightly to be:
https://myservicebusnamespace.servicebus.windows.net/$Resources/Queues/
I get a slightly different response back of:
<Error>
<Code>401</Code>
<Detail>claim is empty. TrackingId:c40a2bd2-490d-4b5b-adde-33bc89aa84ff_G36, SystemTracker:myservicebusnamespace.servicebus.windows.net:$Resources/Queues, Timestamp:2020-06-28T13:27:40</Detail>
</Error>
Which seems to suggest that I am not authorised, or I am missing something. If I add an acutual queue name to the end of that url, it goes back to the original response.
I believe there is another way to get this information by using subscription ids and pem keys... using the management urls (https://management.core.windows.net/{subscription ID}/services/ServiceBus/Namespaces/{Namespace}/Topics/)
but this should all be possible using the format above, I just can't figure out the exact format required.
EDIT/UPDATE: If I don't include my auth claim, the result is exactly the same, suggesting that it's not seeing my auth claim or it's invalid. However if I include it, and just make it the token, without the WRAP bit at the start, I get an exception saying
<Error>
<Code>401</Code>
<Detail>MalformedToken: Invalid authorization header: The request is missing WRAP authorization credentials. TrackingId:7be2d7f0-c165-4658-8bf1-ea104c43defc_G28, SystemTracker:NoSystemTracker, Timestamp:2020-06-28T13:33:09</Detail>
</Error>
So it's like it's reading it then ignoring it?
If you want to list queues or topics we can use Azure service bus service rest api or Azure Resource Manager Rest API. For more details, please refer to the following steps
Azure service bus service rest api
Generate SAS token. For more details, please refer to the document
For example, I use python to create sas token
import hmac
import time
import hashlib
import base64
import urllib
sb_name='bowmantest'
// your entity path such as $Resources/topics (list topics) $Resources/queues(list queues)
topic='$Resources/topics'
url=urllib.parse.quote_plus("https://{}.servicebus.windows.net/{}".format(sb_name,topic))
sas_value='' // your share access key
sas_name='RootManageSharedAccessKey' // your share access rule name
expiry = str(int(time.time() + 10000))
to_sign =(url + '\n' + expiry).encode('utf-8')
sas = sas_value.encode('utf-8')
signed_hmac_sha256 = hmac.HMAC(sas, to_sign, hashlib.sha256)
signature = urllib.parse.quote(base64.b64encode(signed_hmac_sha256.digest()))
auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}'
auth=auth_format.format(signature,expiry,sas_name,url)
print(auth)
Call the rest API
1). list Queues
GET https://<namespace name>.servicebus.windows.net/$Resources/queues
Authorization <sas token>
2). List topics
GET https://<namespace name>.servicebus.windows.net/$Resources/topics
Authorization <sas token>
Azure Resource Manager Rest API
create a service principal and assign Azure RABC role to the sp(I use Azure CLI)
az login
#it will create a service principal and assign contributor role to the sp
az ad sp create-for-rbac -n "jonsp2"
Get Azure AD token
POST /{tenant}/oauth2/v2.0/token HTTP/1.1 //Line breaks for clarity
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=<app id>
&scope=https://management.azure.com/.default
&client_secret=<app password>
&grant_type=client_credentials
call the rest API
List Queues
GET https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ServiceBus/namespaces/{namespaceName}/queues?api-version=2017-04-01
Authorization Bearer <AD token>

Unable to Get/Post Blob on Azure Storage via Rest API in C#

Upon successful consumption of Azure Rest api in c# code. I'm able to create, fetch and fetch list of containers but not blob. While accessing or uploading blobs, this gives permission issue and i.e.,
you are not authorized to perform this request with assigned permission
Progress that i have made so far:
Able to create and fetch the container.
Able to fetch the list of all the containers of storage account.
When tries to Get/Put a blob via below source code it give me error:
This request is not authorized to perform this operation using this permission.
string endPointUri = $"{azureApplicationConfiguration.Resource}/{inpContainerName}/{inpBlobName}";
var request = (HttpWebRequest)WebRequest.Create(endPointUri);
request.Method = HTTPMethod.GET.ToString();
request.Headers.Add("Authorization", $"Bearer {sasToken.access_token}");
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R"));
request.Headers.Add("x-ms-version", "2018-03-28");
request.ProtocolVersion = HttpVersion.Version11;
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine(resp.StatusCode.ToString());
Console.ReadKey();
}
The most likely answer is that the SAS token you're using to authenticate does not support object level access. You can confirm this by checking if there is a letter o in the Signed Resource Types srt= parameter in your SAS token. Based on the fact you can list and create containers, I'd guess the current value is srt=sc. To be able to perform GET/PUT operations on a blob as well, you'll need to generate a new SAS token that includes object level permissions, which should give you a token containing srt=sco.
In case you aren't aware of it already, there is a .NET Azure Storage SDK available, which provides a layer of abstraction over the REST API and may save you some time in the long run.

Azure SAS token AuthorizationResourceTypeMismatch

I have created azure storage account. I have created file storage. I have generated SAS token. when I try to access file using sas token showing error "The remote server returned an error: (403) Forbidden."
I am able to generate SAS token. when I try to access file in file storage throwing exception. I have tried to copy and paste url on browser throws error "
<Error>
<Code>AuthorizationResourceTypeMismatch</Code>
<Message>
This request is not authorized to perform this operation using
this resource type. RequestId:4cbc0cbe-401a-00c2-2edf-
202bc4000000 Time:2019-06-12T05:26:39.4816687Z
</Message>
</Error>"
Code I am using to Generate SAS token
Static string GetAccountSASToken()
SharedAccessAccountPolicy policy = new
SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Read |
SharedAccessAccountPermissions.Write |
SharedAccessAccountPermissions.List,
Services = SharedAccessAccountServices.File,
ResourceTypes = SharedAccessAccountResourceTypes.Service,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Protocols = SharedAccessProtocol.HttpsOnly,
};
Code I am using to access file
XDocument objdoc = XDocument.Load(filepath+ sasToken);
After loading file to XDocument I have to perform some read and write operations.Please help in finding mistake that I am doing
I was encountering the same problem, and the solution from user3404686 (2019-07-13) is correct. After the fact it's much clearer, but when it's still a problem without resolution it can be baffling.
Resource types are authorised independently of each other, rather than there being a hierarchy, ie 'service' does not include 'container' and 'object' authorisations (which was my misunderstanding).
The storageservices API documentation describes how resource type permissions are assigned:
Service (s): Access to service-level APIs (e.g., Get/Set Service Properties, Get Service Stats, List Containers/Queues/Tables/Shares)
Container (c): Access to container-level APIs (e.g., Create/Delete Container, Create/Delete Queue, Create/Delete Table, Create/Delete
Share, List Blobs/Files and Directories)
Object (o): Access to object-level APIs for blobs, queue messages, table entities, and files(e.g. Put Blob, Query Entity, Get Messages,
Create File, etc.)
Further down in the same document, it provides examples of the service, resource type and permissions required for various operations that you may be using, allowing minimum-required-permissions granularity with regard to assigning permissions to a service using the SA token.
After understanding this, the error code AuthorizationResourceTypeMismatch makes more sense - the resource type(s) the SAS token is authorised for, mismatches the resource types you're attempting to access.
In SharedAccessAccountPolicy I have changed
ResourceTypes =SharedAccessAccountResourceTypes.Service to
ResourceTypes = SharedAccessAccountResourceTypes.Object. Then It's working for me.

How do I set the shared access policy for an Azure Queue?

Apparently access to Azure queues can be controlled using a Shared Access Policy. The example here http://msdn.microsoft.com/en-us/library/windowsazure/hh508996 confirms this, but then only provides an example for a blob shared access policy. Does anyone have any references on how the same is achieved for Queues (and Tables)?
You can find the complete sample on the Windows Azure Storage blog: Introducing Table SAS (Shared Access Signature), Queue SAS and update to Blob SAS. Here is the part that assigns the policy to a queue:
// Create the GC queue SAS policy.
QueuePermissions gcQueuePermissions = new QueuePermissions();
SharedAccessQueuePolicy gcQueuePolicy = new SharedAccessQueuePolicy()
{
// Providing the max duration
SharedAccessExpiryTime = DateTime.MaxValue,
// Permission is granted to process queue messages.
Permissions = SharedAccessQueuePermissions.ProcessMessages
};
// Associate the above policy with a signed identifier
gcQueuePermissions.SharedAccessPolicies.Add(
gcPolicySignedIdentifier,
gcQueuePolicy);
// The below call will result in a Set Queue ACL request to be sent to
// Windows Azure Storage in order to store the policy and associate it with the
// "GCAccessPolicy" signed identifier that will be referred to
// by the generated SAS token
this.gcQueue.SetPermissions(gcQueuePermissions);
Does the announcement post for table SAS (especially the SAS token producer portion of the sample) can help you any way? It seems to me the SAS is available on Table and Queues starting with SDK 1.7.

Resources