none
Is it possible to use the Primary key in the storage REST API "PUT" calls?

    Question

  • From @jtcfeedbackapp via Twitter

    "@AzureSupport hi, can i use Storage REST API with my primary/ secondary account key to PUT a image on the storage?

     I am able to store the primary and secondary key securely. Please let me know if its possible to use the Primary key in the storage REST API "PUT" calls."

    Over DM

    Thanks,

    @AzureSupport

    Tuesday, May 17, 2016 1:06 AM

Answers

  • Hi Gary,

    You can build the logic in the API Management Gateway policies to build the Authorization header based on a storage key that you configure as a property there.

    Here is an example policy for a PUT blob operation:

    <policies>
    	<inbound>
    		<base />
    		<rewrite-uri template="{container}/{blob}" />
    		<set-variable name="date" value="@(string.Format("{0:r}", DateTime.UtcNow))" />
    		<set-variable name="key" value="{{StorageAccountKey}}" />
    		<set-variable name="account" value="{{StorageAccountName}}" />
    		<set-variable name="version" value="{{StorageAPIVersion}}" />
    		<set-header name="x-ms-date" exists-action="override">
    			<value>@((string)context.Variables["date"])</value>
    		</set-header>
    		<set-header name="x-ms-version" exists-action="override">
    			<value>{{StorageAPIVersion}}</value>
    		</set-header>
    		<set-header name="x-ms-blob-type" exists-action="skip">
    			<value>BlockBlob</value>
    		</set-header>
    		<set-header name="Authorization" exists-action="override">
    			<value>@{
    			var date = (string)context.Variables["date"];
    			var account = (string)context.Variables["account"];
    			var version = (string)context.Variables["version"];
    			var key = (string)context.Variables["key"];
    			var keyBytes = Convert.FromBase64String(key);
    			
    			var stringToSign = string.Format("{0}\n\n{1}\n\nx-ms-blob-type:{2}\nx-ms-date:{3}\nx-ms-version:{4}\n/{5}/{6}/{7}",context.Request.Method,context.Request.Headers.GetValueOrDefault("Content-Type", "application/octet-stream"),context.Request.Headers.GetValueOrDefault("x-ms-blob-type", "BlockBlob"),date,version,account,context.Request.MatchedParameters["container"], context.Request.MatchedParameters["blob"]);
    			
    			var hasher = new HMACSHA256(keyBytes);
    			
    			string signature = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    
    			string headerValue = string.Format("{0} {1}:{2}", "SharedKeyLite", account, signature);
    
    			return headerValue;
    			}</value>
    		</set-header>
    		<set-header name="Ocp-Apim-Subscription-Key" exists-action="delete">
    		</set-header>
    	</inbound>
    	<backend>
    		<base />
    	</backend>
    	<outbound>
    		<base />
    	</outbound>
    	<on-error>
    		<base />
    	</on-error>
    </policies>


    Friday, May 20, 2016 8:18 PM

All replies

  • Hi,

    any hint for this? thanks!


    -G

    Tuesday, May 17, 2016 4:10 AM
  • Hi,

    Thank you for posting here,

    You can use either of storage account keys to storage REST API "PUT" calls.

    Regards,

    Vikranth S.

    Please remember to click "Mark as Answer" on the post that helps you, this can be beneficial to other community members reading the thread. And Vote as Helpful.

     

    Tuesday, May 17, 2016 10:03 AM
    Moderator
  • Hi Vikranth S.,

    I couldn't find any documentation on how to use that. Can you point me to that?

    What would the authorisation header be?

    Thanks!


    -G

    Tuesday, May 17, 2016 2:15 PM
  • Hello,

    For more information, to put blob refer below link:

    https://msdn.microsoft.com/en-us/library/dd179451.aspx

    Regards,

    Vikranth S.

    Please remember to click "Mark as Answer" on the post that helps you, this can be beneficial to other community members reading the thread. And Vote as Helpful.

    Tuesday, May 17, 2016 2:38 PM
    Moderator
  • Hi,

    I have already gone through that document. In the document there is no mentioning of how i can use the Storage API primary key to submit the PUT request?

    So, my question really is, how can i use the STORAGE API Primary key to submit the PUT request??

    e.g. The below is a sample request from the document using SHARED KEY not Primary Key

    <code>

    Request Syntax: PUT https://myaccount.blob.core.windows.net/mycontainer/mypageblob HTTP/1.1 Request Headers: x-ms-version: 2015-02-21 x-ms-date: <date> Content-Type: text/plain; charset=UTF-8 x-ms-blob-type: PageBlob x-ms-blob-content-length: 1024 x-ms-blob-sequence-number: 0 Authorization: SharedKey Origin: http://contoso.com Vary: Origin myaccount:YhuFJjN4fAR8/AmBrqBz7MG2uFinQ4rkh4dscbj598g= Content-Length: 0

    </code>


    -G

    Tuesday, May 17, 2016 2:51 PM
  • Hi..

    i think you are not getting me.

    1) I am using Azure Blob Storage REST API not the API management REST API that you point to me.

    2)  i need to use the Azure BLOB STORAGE REST API directly by directly using its Primary Key, 

    NOT shared key, NOT shared accesss signature and NOT programmatically create tokens.

    3) What you have advised so far is service call using SHARED key, not the primary key.

    Can you advise if i'm missing anything from you?


    -G

    Tuesday, May 17, 2016 4:21 PM
  • In order to call Put Blob (or any REST API call that does not support anonymous access), you must use one of two types of authentication:

    1 - Shared Key authentication, described here: https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx

    2 - A shared access signature granting write access to that blob resource. See here: https://msdn.microsoft.com/en-us/library/azure/ee395415.aspx

    Every call to Put Blob must be authenticated using one of these two approaches.

    Shared Key authentication uses your storage account key to authenticate the request. Your key is used to construct the authorization header. This could be your primary storage account key, or your secondary account key. Either one will work.

    That is the only "primary" key that relates to Blob storage.

    Thursday, May 19, 2016 12:31 AM
  • Hi Tamra Myer,

    As i am using Azure API management to do the web service call to Put Blob, i can't programmatically construct the authorisation header. Any idea how i can go around this?

    Thanks.


    -G

    Thursday, May 19, 2016 2:38 AM
  • I'm not sure what you mean by "using Azure API Management to do the web service call to Put Blob".

    Can you tell us more about what you are trying to accomplish? What does your application do, what language are you using, and what APIs are you calling? Are you constructing your own REST calls?

    All of our client libraries (for .NET, Java, etc.) handle request authentication for you under the covers.

    Thursday, May 19, 2016 4:06 AM
  • Hi Tamra Myers,

    I am building a mobile app that will call REST web services curated on Azure API management. My intention is to use Azure API management as a 'gateway' to the backend services.

    One of the app feature is to be able to upload images to Azure Storage and because my app doesn't have any user registration features, i can't actually construct the authorisation header directly in the app. 

    Therefore, i hope to use Azure API Management(As a proxy) to access Azure Blob Storage REST API in order to upload my images from the mobile app.

    I would not be able to construct the required Authorisation Header for Blob Storage in Azure API Management correct? What other methods are there?

    Thanks in advance.

     


    -G

    Thursday, May 19, 2016 6:43 PM
  • Hi Gary,

    You can build the logic in the API Management Gateway policies to build the Authorization header based on a storage key that you configure as a property there.

    Here is an example policy for a PUT blob operation:

    <policies>
    	<inbound>
    		<base />
    		<rewrite-uri template="{container}/{blob}" />
    		<set-variable name="date" value="@(string.Format("{0:r}", DateTime.UtcNow))" />
    		<set-variable name="key" value="{{StorageAccountKey}}" />
    		<set-variable name="account" value="{{StorageAccountName}}" />
    		<set-variable name="version" value="{{StorageAPIVersion}}" />
    		<set-header name="x-ms-date" exists-action="override">
    			<value>@((string)context.Variables["date"])</value>
    		</set-header>
    		<set-header name="x-ms-version" exists-action="override">
    			<value>{{StorageAPIVersion}}</value>
    		</set-header>
    		<set-header name="x-ms-blob-type" exists-action="skip">
    			<value>BlockBlob</value>
    		</set-header>
    		<set-header name="Authorization" exists-action="override">
    			<value>@{
    			var date = (string)context.Variables["date"];
    			var account = (string)context.Variables["account"];
    			var version = (string)context.Variables["version"];
    			var key = (string)context.Variables["key"];
    			var keyBytes = Convert.FromBase64String(key);
    			
    			var stringToSign = string.Format("{0}\n\n{1}\n\nx-ms-blob-type:{2}\nx-ms-date:{3}\nx-ms-version:{4}\n/{5}/{6}/{7}",context.Request.Method,context.Request.Headers.GetValueOrDefault("Content-Type", "application/octet-stream"),context.Request.Headers.GetValueOrDefault("x-ms-blob-type", "BlockBlob"),date,version,account,context.Request.MatchedParameters["container"], context.Request.MatchedParameters["blob"]);
    			
    			var hasher = new HMACSHA256(keyBytes);
    			
    			string signature = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
    
    			string headerValue = string.Format("{0} {1}:{2}", "SharedKeyLite", account, signature);
    
    			return headerValue;
    			}</value>
    		</set-header>
    		<set-header name="Ocp-Apim-Subscription-Key" exists-action="delete">
    		</set-header>
    	</inbound>
    	<backend>
    		<base />
    	</backend>
    	<outbound>
    		<base />
    	</outbound>
    	<on-error>
    		<base />
    	</on-error>
    </policies>


    Friday, May 20, 2016 8:18 PM
  • Hi Chris Brooks,

    Thanks, it works! Learnt a new thing in Azure APIM from you!


    -G

    Sunday, May 22, 2016 5:26 PM