How to download a file from Blob Storage using Azure API Management?


There are multiple ways to implement functionality to download a file with sensitive data from Azure Blob Storage through Azure API Management. All of them have pros & cons.

At first you should use private blob containers to store your files in a protected way. So you’ll have two options to retrieve a file: have access to storage account and key or have access to SAS and blob URI.

 

Option #1: API retrieves a file

You can set storage account name and key into configuration file of your backend API and implement functionality to download a file as part of it. The workflow is pretty simple:

  1. Customer sends request to API Management to download a specific file
  2. API Management sends request to backend API with file ID
  3. API retrieves a file from storage and responds back to API Management with a file content
  4. API Management responds back to customer with a file content

While this approach is very simple it has one drawback… Network traffic with file content will go through your backend and can affect scalability of your solution. Ofcourse it depends on file size, frequency of downloads, etc. If that’s the case for you then consider next options.

 

Option #2: Customer retrieves a file

Having storage account name and key your backend API can generate SAS for requested file and create a file URI with included SAS. Everyone who has access to created URI is able to download a file. So in that case the workflow is:

  1. Customer sends request to API Management to download a specific file
  2. API Management sends request to backend API with file ID
  3. API generates URI with SAS and returns it back to API Management
  4. API Management responds back to customer with created URI
  5. Customer downloads a file using URI

This approach solves drawback of previous option and also you can configure lifetime of SAS (e.g. access expiration after 15 minutes) to enhance security of access to the file. But still there is one drawback related to security. If someone outside of a company will get access to a file URI somehow then he’ll be able to download a file within short time window. That’s maybe a problem for files with financial data for instance. If that’s the problem for you then you should consider option below.

Option #3: API Management retrieves a file

 

So let’s recap briefly where we are. We’ve considered two approaches and both of them have two different drawbacks: network traffic with file content and security for file access. How to address them? Let’s retrieve file content using URI with SAS on API Management side! That’s not a problem with policy feature for Azure API Management. It’ll allow us to move network traffic outside of backend API as well as not share file URI to end customers. Let’s consider design below.

Design

api-management-download-a-file

The workflow is a bit complex comparing to previous options but still clear:

  1. Customer sends request to API Management to download a specific file
  2. API Management sends request to backend API with file ID
  3. API generates URI with SAS and returns it back to API Management
  4. API Management downloads a file using received URI and responds back to customer with a file content

Custom Policy

The key component in this design is custom policy which allows to download a file from Azure API Management using file URI created on backend API side. My implementation of custom policy is below. Feel free to use it and thanks for reading!

<policies>
   <inbound>
      <base />
   </inbound>
   <backend>
      <base />
   </backend>
   <outbound>
      <base />
      <set-variable name="fileSAS" value="@(context.Response.Body.As<string>())" />
      <send-request mode="new" response-variable-name="file" timeout="60" ignore-error="false">
         <set-url>@(((string)context.Variables["fileSAS"]))</set-url>
         <set-method>GET</set-method>
      </send-request>
      <set-body>@(((IResponse)context.Variables["file"]).Body.As<string>())</set-body>
      <set-header name="Content-Type" exists-action="override">
         <value>text/plain</value>
      </set-header>
   </outbound>
</policies>
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s