0

I have a .NET app which uses the WebClient and the SAS token to upload a blob to the container. The default behaviour is that a blob with the same name is replaced/overwritten.

Is there a way to change it on the server, i.e. prevents from replacing the already existing blob?

I've seen the Avoid over-writing blobs AZURE but it is about the client side.

My goal is to secure the server from overwritting blobs.

AFAIK the file is uploaded directly to the container without a chance to intercept the request and check e.g. existence of the blob.

Edited

Let me clarify: My client app receives a SAS token to upload a new blob. However, an evil hacker can intercept the token and upload a blob with an existing name. Because of the default behavior, the new blob will replace the existing one (effectively deleting the good one).

I am aware of different approaches to deal with the replacement on the client. However, I need to do it on the server, somehow even against the client (which could be compromised by the hacker).

Community
  • 1
  • 1

3 Answers3

1

You can issue the SAS token with "create" permissions, and without "write" permissions. This will allow the user to upload blobs up to 64 MB in size (the maximum allowed Put Blob) as long as they are creating a new blob and not overwriting an existing blob. See the explanation of SAS permissions for more information.

  • It turned out that I had an old nuget package for the Azure. Thus I upgraded it to the latest version. After that I was able to see the mentioned Create permission in VS2015, but after publish it the whole service stopped working. In the logs there was an information that the latest working version of the WindowsAzure.Storage package is 3.1.0.1 thus I downgraded the pakage. My service is now working, but I cannot see the Create permission in VS2015. – Mariusz888 Dec 15 '16 at 23:41
  • @Mariusz888 Which logs did you see this statement in? If you are using a component that depends on an old version of the Azure Storage Client then you may need to upgrade that component too. – Michael Roberson - MSFT Dec 17 '16 at 00:20
  • I tried to upgrade all my nuget packages, but I had terrible dependency conflicts. I have solved some of them. This is the list of currently installed packages: http://pastebin.com/MTLDrDMr – Mariusz888 Dec 17 '16 at 09:39
  • It looks like you are using MobileServices, which has been deprecated in favor of the Mobile Apps SDK. See the following for information on how to migrate: https://docs.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-value-prop-migration-from-mobile-services – Michael Roberson - MSFT Dec 19 '16 at 06:59
0

There is no configuration on server side but then you can implement some code using the storage client sdk.

// retrieve reference to a previously created container.
var container = blobClient.GetContainerReference(containerName);
// retrieve reference to a blob.
var blobreference = container.GetBlockBlobReference(blobName);
// if reference exists do nothing
// else upload the blob.

You could do similar using the REST api https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/blob-service-rest-api

GetBlobProperties which will return 404 if blob does not exists.

TusharJ
  • 1,123
  • 2
  • 9
  • 17
0

Is there a way to change it on the server, i.e. prevents from replacing the already existing blob?

Azure Storage Services expose the Blob Service REST API for you to do operations against Blobs. For upload/update a Blob(file), you need invoke Put Blob REST API which states as follows:

The Put Blob operation creates a new block, page, or append blob, or updates the content of an existing block blob. Updating an existing block blob overwrites any existing metadata on the blob. Partial updates are not supported with Put Blob; the content of the existing blob is overwritten with the content of the new blob.

In order to avoid over-writing existing Blobs, you need to explicitly specify the Conditional Headers for your Blob Operations. For a simple way, you could leverage Azure Storage SDK for .NET (which is essentially a wrapper over Azure Storage REST API) to upload your Blob(file) as follows to avoid over-writing Blobs:

try
{
    var container = new CloudBlobContainer(new Uri($"https://{storageName}.blob.core.windows.net/{containerName}{containerSasToken}"));
    var blob = container.GetBlockBlobReference("{blobName}");
    //bool isExist=blob.Exists();
    blob.UploadFromFile("{filepath}", accessCondition: AccessCondition.GenerateIfNotExistsCondition());
}
catch (StorageException se)
{
    var requestResult = se.RequestInformation;
    if(requestResult!=null)
        //409,The specified blob already exists.
        Console.WriteLine($"HttpStatusCode:{requestResult.HttpStatusCode},HttpStatusMessage:{requestResult.HttpStatusMessage}");
}

Also, you could combine your blob name with the MD5 code of your blob file before uploading to Azure Blob Storage.

As I known, there is no any configurations on Azure Portal or Storage Tools for you to achieve this purpose on server-side. You could try to post your feedback to Azure Storage Team.

Community
  • 1
  • 1
Bruce Chen
  • 17,123
  • 2
  • 14
  • 27
  • Please, see my clarification. – Mariusz888 Dec 15 '16 at 12:42
  • According to your scenario, I assumed that you should not expose the SAS token to your client app directly. For a workaround, you could expose a Web API to your client app for uploading the blob(file). Within your Web API back-end, you could check whether the file (uploaded from your client app) exists before uploading to your Azure Storage. – Bruce Chen Dec 15 '16 at 15:44
  • I have considered this scenario, but it has some downsides: I use the Azure mobile client library to do the rest of the work together with the authentication. Thus I need to implement a separated authentication or figure out how to upload the file within the mobile client API. I use the 'InvokeApiAsync' method for my other cases, but it seems a bit complicated to make it uploading files. – Mariusz888 Dec 15 '16 at 17:16