ACL access abilities for Azure Containers and Blobs - azure

I am looking at using azure Containers and Blobs to store images and videos for my website. I found http://msdn.microsoft.com/en-us/library/windowsazure/dd179354.aspx which talks about the different ALC settings but it did not answer one of my questions. If a Container/Blob are set to "No public read access" the site says that only the account owner can read the data. Would this mean that people could not access it by the URL but my MVC Web App hosted on an Azure VM would be able to access it via URL?

Please bear with me if the answer sounds a bit preachy & unnecessary lengthy :)
Essentially each resource (Blob Container, Blob) in Windows Azure has a unique URL and is accessible via REST API (thus accessible over http/https protocol). Wit ACL, you basically tell storage service whether or not to honor the request sent to serve the resource. To read more about authentication mechanism, you may find this link useful: http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx.
When you set the ACL as No public read access, you're instructing storage service not to honor any anonymous requests. Only authenticated requests will be honored. To create an authenticated request, you would require your account name and key and create an authorization header which gets passed along with the request to access the request. If this authorization header is not present in your request, the request will be rejected.
So long story short, to answer your question even your MVC application won't be able to access the blob via URL unless that authorization header is included in the request. One possibility would be to explore Shared Access Signature (SAS) functionality in blob storage. This would give time-bound restricted permissions to blobs in your storage. So what you would do is create a SAS URL for your blob in your MVC app using your account name and key and use that SAS URL in the application.
To further explain the concept of ACL, let's say you have a blob container called mycontainer and it has a blob called myblob.txt in a storage account named myaccount. For listing blobs in the container, the container URL would be http://myaccount.blob.core.windows.net/mycontainer?restype=container&comp=list and the blob URL would be http://myaccount.blob.core.windows.net/mycontainer/myblob.txt. Following will be the behavior when you try to access these URLs directly through the browser with different ACL:
No public read access
Container URL - Error
Blob URL - Error
Public read access for blobs only
Container URL - Error
Blob URL - Success (will download the blob)
Full public read access
Container URL - Success (will show an XML document containing information about all blobs in the container)
Blob URL - Success (will download the blob)

Related

Azure - Blob Storage - Mixing Custom Domain with SAS

I have an Azure Storage account that hosts a static web site as explained here. This means the static web site "lives" in a storage container named $web. This web site is accessible via a custom domain. This is currently working as desired. However, there is one file that I want to restrict access to.
There is one file in the $web storage container that I only want individuals to access if a) they have a key and b) it's during a specific time window. My thinking was that I could accomplish this with a Shared Access Signature (SAS). However, while testing this approach, it doesn't seem to work. It seems that everything in the $web storage container is publicly visible whether a SAS has been generated or not. Is this correct?
Is there a way to require that a file in the $web storage container have an SAS? Or, do I need to "host" the file in a separate storage container (thus removing it from my custom domain)?
Thank you.
When visit the files stored in $web container via primary static website endpoint(for example, https://contosoblobaccount.z22.web.core.windows.net/index.html), the files are always be accessible whether the container is public or private. So it doesn't matter the sas token is specified or not.
And the sas token only take effects if the $web container is private access, and people visit it via primary blob service endpoint(For example, https://contosoblobaccount.blob.core.windows.net/$web/index.html).
Please refer to this official doc for more details.
So for your purpose, you should put it in another container with private access.

Getting AuthorizationFailure (403) response on Azure Blob Storage via REST API with SAS Token

After a few days fighting with this issue I have decided to post it here in case someone can help out by giving me some pointers.
I have an Azure Storage Account with a Blob container with encrypted images. The images have been uploaded via PUT request (from a browser) to the Azure Blob Storage REST API, using SAS signature (generated by an Azure VM) and customer provided keys (x-ms-encryption headers). However, when trying to download the images from the Azure VM with a GET request (using curl), I get the following 403 "AuthorizationFailure" error:
<?xml version="1.0" encoding="utf-8”?>
<Error>
<Code>AuthorizationFailure</Code>
<Message>
This request is not authorized to perform this operation.
RequestId:1b203db6-c01e-0013-1553-6adb9b000000
Time:2020-08-04T11:33:42.9494992Z
</Message>
</Error>
Funny thing though, when I perform exactly the same GET request (exactly the same headers) with curl, Postman or the browser from my own local machine and even from other Azure VMs located in different resource groups and different virtual networks, it works as expected and I can successfully download the encrypted image. This confirms that the SAS signature and the headers passed are correctly constructed.
I have reviewed all the configuration of the VM, Network Security Group, Virtual Network and Storage Account in the Azure Portal and compared it with the other VMs that successfully download the images, and all the settings are exactly the same except for:
In the VM that fails to download the image, I'm authorized as a contributor for that VM's resource group only, while in the VM that works I'm the owner of the account.
In the account where I am the owner, Azure has created a new resource group called NetworkWatcherRG, which seems to have no resources attached to it. In the VM that has the problem I do not have access to that resource group, so I ignore whether it has been created by Azure or not, and whether it has any impact on the problem I'm facing.
I would really appreciate any ideas or suggestions on what the issue might be.

How to get download url of a digital file stored in an Azure storage account

After storing a digital file in Azure blob storage, I want to provide a link to that file in my static website (that has no server side code). When a user clicks on that link user should be able to download that digital file to his/her computer. Question: How do you get the url of a digital file stored in Azure blob storage?
Each blob in Azure Storage has a URL of the following format:
https://account.blob.core.windows.net/container/blob
Where:
account is the name of your storage account, container is the name of your blob containerandblob` is the name of your blob.
Now that your requirement is that a user should be prompted to download the file directly without using any server-side code, these are the additional things you would need to do:
Make sure that the blob container's ACL is either set to Blob (recommended) or Public. If you set the ACL to Private, then you would need a Shared Access Signature (SAS) and that would require some server-side code.
Either set the content-type of the blob to application/octet-stream (default content type for any blob in Azure Storage) or set the content-disposition property to attachment; filename="your file name" to force the file download instead of displaying it inside the browser only. Recommended approach is to use content-disposition property.

Limit Azure Blob Access to WebApp

Situation:
We have a web-app on azure, and blob storage, via our web-app we write data into the blob, and currently read that data back out returning it as responses in the web-app.
What we're trying to do:
Trying to find a way to restrict access to the blob so that only our web-app can access it. Currently setting up an IP address in the firewall settings works fine if we have a static IP (we often test running the web app locally from our office and that lets us read/write to the blob just fine). However when we use the IP address of our web app (as read from the cross domain page of the web app) we do not get the same access, and get errors trying to read/write to the blob.
Question:
Is there a way to restrict access to the blob to the web app without having to set up a VPN on azure (too expensive)? I've seen people talk about using SAS to generate time valid links to blob content, and that makes sense for only allowing users to access content via our web-app (which would then deliver them the link), but that doesn't solve the problem of our web-app not being able to write to the blob when not publicly accessible.
Are we just trying to miss-use blobs? or is this a valid way to use them, but you have to do so via the VPN approach?
Another option would be to use Azure AD authentication combined with a managed identity on your App Service.
At the time of writing this feature is still in preview though.
I wrote on article on how to do this: https://joonasw.net/view/azure-ad-authentication-with-azure-storage-and-managed-service-identity.
The key parts:
Enable Managed Identity
Add the generated service principal the necessary role in the storage account/blob container
Change your code to use AAD access tokens acquired with the managed identity instead of access key/SAS token
Acquiring the token using https://www.nuget.org/packages/Microsoft.Azure.Services.AppAuthentication/1.1.0-preview:
private async Task<string> GetAccessTokenAsync()
{
var tokenProvider = new AzureServiceTokenProvider();
return await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/");
}
Reading a blob using the token:
private async Task<Stream> GetBlobWithSdk(string accessToken)
{
var tokenCredential = new TokenCredential(accessToken);
var storageCredentials = new StorageCredentials(tokenCredential);
// Define the blob to read
var blob = new CloudBlockBlob(new Uri($"https://{StorageAccountName}.blob.core.windows.net/{ContainerName}/{FileName}"), storageCredentials);
// Open a data stream to the blob
return await blob.OpenReadAsync();
}
SAS Keys is the correct way to secure and grant access to your Blob Storage. Contrary to your belief, this will work with a private container. Here's a resource you may find helpful:
http://www.siddharthpandey.net/use-shared-access-signature-to-share-private-blob-in-azure/
Please also review Microsoft's guidelines on securing your Blob storage. This addresses many of the concerns you outline and is a must read for any Azure PaaS developer:
https://learn.microsoft.com/en-us/azure/storage/common/storage-security-guide

CDN with Storage Account

I create the the Storage account, CDN Profile and CDN endpoint from powershell. But adding images to the storage account is a manual process after creating all azure components. Now we have the issue that images are not showing up in page. When I try to access the CDN image url directly, I get this error
The requested URI does not represent any resource on the server
But I can access the content directly by using blob storage url to ensure content exist. I tried changing the caching rules , but nothing is working. I have standard verizon cdn profile.
Any suggestions?
Update1 : When I delete the endpoint and recreate the endpoint with all images already loaded in Storage account, everything works fine. Any idea what is the predictable behaviour?
This error happens when you're using a "/" with the root container where the blob is present (sub-folders). for now the "/" are not supported, you can get around it by referencing the root container in the link, ex:
GET https://myaccount.blob.core.windows.net/$root/myphoto
When using the CDN, the format should look like the following:
http://<EndpointName>.azureedge.net/<myPublicContainer>/<BlobName>
There is also a cool tutorial on how to host static sites via blobs and CDN worth checking out: https://blog.lifeishao.com/2017/05/24/serving-your-static-sites-with-azure-blob-and-cdn
Documentation:
You can get more info from these links: https://learn.microsoft.com/en-us/rest/api/storageservices/Working-with-the-Root-Container?redirectedfrom=MSDN
https://learn.microsoft.com/en-us/azure/cdn/cdn-create-a-storage-account-with-cdn

Resources