URL to access private blob in Azure Storage
Asked Answered
A

3

26

We're just getting started with Azure Storage. In our scenario we upload to private blobs that we later need to access directly from our client app, e.g. images.

Is there a way to address private blobs in Azure Storage with a URL containing the access key?

Sifting through the MS docs all I could find so far is simple URL access via the blob URI, e.g. as given by the URI property of the CloudBlockBlob instance when listing blobs via the .net API.

Naturally accessing this from a web browser fails due to the blob not being public.
However, can we qualify the URL to also include the access key in order to allow authorized clients to access the blob..?

Adhesion answered 3/11, 2017 at 8:0 Comment(9)
Read this: learn.microsoft.com/en-us/azure/storage/common/… It describes the use of tokens to allow access to clients.Exoskeleton
@Exoskeleton Yes, I was wondering about that and it doesn't quite seem to apply: "You can use a SAS when you want to provide access to resources in your storage account to any client not possessing your storage account's access keys" - I do own the access key.Adhesion
If you own the access key, then you must generate a SAS token using it, and then access the file yourself using the SAS token. There are libraries to do a lot of the heavy lifting for you.Sharenshargel
In that case, you can simply use that: learn.microsoft.com/en-us/azure/storage/blobs/…. There are security considerations here though. If you're fine with distributing your storage account access keys to all clients (e.g. your program is for company-internal use) then that's a way to go. If you're not, you should probably create a service between your blob storage and clients, which implements whatever security you need.Exoskeleton
@Sharenshargel ..after checking out the SDKs on github (client will be Objective-C, not C#) it looks like using the library to access Azure Storage will be much less of a hassle. Thanks for the input!Adhesion
@Adhesion If you are building a native app, it is a bit dangerous to embed your storage access key in the program. Someone with the right tools can find it, and then do anything they want with your storage account. Keeping that in mind, the Valet Key pattern is often used here, where your app's back-end authenticates and authorizes the user request, and then returns the URL containing a temporary SAS token, that the client can use.Sharenshargel
@Sharenshargel True - we're obfuscating all URLs and keys in our code.Adhesion
Obfuscating will only make stuff harder to find, but not impossible..Sharenshargel
That's always the case, isn't it..? Might as well receive the key from an API and somebody can attach a debugger to our client app.....Adhesion
S
15

You can generate an SAS URL and token for the private blob. Here's the process for generating this manually in the Azure portal, to test the concept. It will work even if your storage container is private, as it allows temporary, time limited access to the file using a URL that contains a token in it's query string.

Click on your file within the storage container, select the 'Generate SAS' tab, and in the right pane select enter image description here

This will generate a token, and a URL that includes the token, like below:

enter image description here

You can test downloading the URL as a file by using curl. Use the 2nd URL shown in the image above (the one that includes the full token and other parameters in the querystring), then do this (IMPORTANT - the URL must be in double quotes):

curl "<YOUR_URL>" --output myFileName.txt

Tip - this is also a good method for making files available to an Azure VM, if you need to install a file directly on the VM for any reason (I needed to do this to install an SSL certificate), you can generate the URL then curl to download the file, on the VM itself. E.g. connect to the VM first with Bastion or SSH, then use curl to download the file somewhere.

Sympathetic answered 14/1, 2021 at 1:46 Comment(0)
H
7

This is the API for how you read blobs from storage:

https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob

There is no URL-Parameter to pass the access key, only the header value Authorization. So you could do the request manually and e.g. add the resulting data as a base64 encoded image. I would advise against it if at all possible.

You must also be aware that by passing your access key to the client, you are effectively making your blob public anyways. You would be putting your data at more risk than anonymous access, since the access key allows more operations than anonymous access. This would also hold true for your objective-c app, even though its much more obfuscated there. SAS is the way to go there - create a backend service that creates a defined set of SAS tokens for given resources. It is however much more effort than simply obfuscating the full access key somewhere.

See "Features available to anonymous users":

https://learn.microsoft.com/en-us/azure/storage/blobs/storage-manage-access-to-resources

Hornet answered 3/11, 2017 at 8:59 Comment(4)
Thanks for the reply. Using https to talk to Azure Storage should however mitigate the risk, right..?Adhesion
It would only protect the communication between your device and the server. E.g. if you look at the developer console of chrome, you can also see https calls and their headers. Also, if the Url is part of some HTML, it can be viewed by looking at the page source.Hornet
Well, I can see it from Chrome because being the client it's my own communication. A 3rd party cannot. Storing in HTML wouldn't be wise, I agree - URLs will be stored inside our app's binary in an obfuscated way.Adhesion
That is fine, just wanted to point out that the app itself can be attacked/decompiled/... Its probably not worth the effort to do more than what you describe, but I wanted do make sure you were aware. If you create a backend service to generate SAS tokens that are used on the client, you are 100% safe that the client can never get their hands on full access to the storage, because your service can only generate a defined set of tokens. It is however much more effort than simply obfuscating the full access key somewhere.Hornet
O
0

Expanding on @Chris Halcrow.

I had to extend my urls with a few more parameters (*) such as ss=bfqt&srt=sco.

(*) note that the SAS is not a "key" but a set of query params. Then:

curl -X GET -H "x-ms-date: $(date -u)" "https://<ACCOUNT>.blob.core.windows.net/<PATH>/<FILENAME>?<SIGNATURE>"
Outrank answered 18/10, 2023 at 7:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.