Deploy Storage Account And Output Connection String With SAS Token Using ARM Template

During our development life with Azure, we found ourselves in a situation where we need to deploy the storage account using ARM templates and output Connection strings. In most of the cases, we should generate SAS tokens for connection strings, in order to provide limited access to the storage account.

I found myself in a situation where I needed to deploy the Azure Storage Account with a blob container and generate a connection string with SAS token and update one of the web app's settings with that generated connection string.
For this purpose, I used linked ARM template and created a storage account and blob container. Then, I generated the connection string with the SAS token and the output from that template so that the master template can use this value.
 

Table of content

  • Craft ARM Template
  • Output connection string with SAS token
  • Output connection string with account key
  • Deploy Template

Craft ARM template

 
We need to craft the ARM template as below for our requirement. 
  1. {  
  2.     "$schema""http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",  
  3.     "contentVersion""1.0.0.0",  
  4.     "variables": {  
  5.         "storageAccountApiVersion""2018-07-01",  
  6.         "storageAccountNameTidy""[toLower(trim(parameters('storageAccountName')))]",   
  7.         "blobEndPoint":"[concat('https://',variables('storageAccountNameTidy'),'.blob.core.windows.net/')]"  
  8.     },  
  9.     "parameters": {  
  10.         "location": {  
  11.             "type""string",  
  12.             "defaultValue""southeastasia"  
  13.         },  
  14.         "storageAccountName": {  
  15.             "type""string",  
  16.             "defaultValue""awesomestorage"  
  17.         },  
  18.         "accountType": {  
  19.             "type""string",  
  20.             "defaultValue""Standard_LRS"  
  21.         },  
  22.         "accessTier": {  
  23.             "type""string",  
  24.             "defaultValue""Hot"  
  25.         },  
  26.         "supportsHttpsTrafficOnly": {  
  27.             "type""bool",  
  28.             "defaultValue"true  
  29.         },  
  30.         "sasTokenExpiry": {  
  31.             "type""string",  
  32.             "defaultValue":  "2020-12-31T23:59:00Z"  
  33.         },  
  34.         "containerName": {  
  35.             "type""string",  
  36.             "defaultValue""test"  
  37.         },  
  38.         "accountSasProperties": {  
  39.             "type""object",  
  40.             "defaultValue": {  
  41.                 "signedServices""b",  
  42.                 "signedPermission""rl",  
  43.                 "signedResourceTypes""sco",  
  44.                 "keyToSign""key2",  
  45.                 "signedExpiry""[parameters('sasTokenExpiry')]"  
  46.             }  
  47.         }  
  48.     },  
  49.     "resources": [  
  50.         {  
  51.             "name""[parameters('storageAccountName')]",  
  52.             "type""Microsoft.Storage/storageAccounts",  
  53.             "apiVersion""[variables('storageAccountApiVersion')]",  
  54.             "location""[parameters('location')]",  
  55.             "properties": {  
  56.                 "accessTier""[parameters('accessTier')]",  
  57.                 "supportsHttpsTrafficOnly""[parameters('supportsHttpsTrafficOnly')]"  
  58.             },  
  59.             "dependsOn": [],  
  60.             "sku": {  
  61.                 "name""[parameters('accountType')]"  
  62.             },  
  63.             "kind""BlobStorage",  
  64.             "resources": [  
  65.                 {  
  66.                     "name""[concat('default/', parameters('containerName'))]",  
  67.                     "type""blobServices/containers",  
  68.                     "apiVersion""[variables('storageAccountApiVersion')]",  
  69.                     "dependsOn": [  
  70.                         "[parameters('storageAccountName')]"  
  71.                     ]  
  72.                 }  
  73.             ]  
  74.         }  
  75.     ],  
  76.     "outputs": {  
  77.         "storageAccountConnectionString": {  
  78.             "type""string",  
  79.             "value""[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountNameTidy'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountNameTidy')), variables('storageAccountApiVersion')).keys[0].value)]"  
  80.         },  
  81.         "storageAccountConnectionStringWithSAS": {  
  82.             "type""string",  
  83.             "value""[concat('BlobEndpoint=',variables('blobEndPoint'),';SharedAccessSignature=', listAccountSas(variables('storageAccountNameTidy'), variables('storageAccountApiVersion'), parameters('accountSasProperties')).accountSasToken)]"  
  84.         }  
  85.     }  
  86. }  

Generate connection string with sas token

 
As per the above full ARM Template, we can see the connection string is generated with full access and another is generated with SAS token.
 
In order to generate a connection string with SAS token, I have used the listAccountSas ARM function.
 
Find more details about this function here.
  1. "storageAccountConnectionStringWithSAS": { "type""string""value""[concat('BlobEndpoint=',variables('blobEndPoint'),';SharedAccessSignature=', listAccountSas(variables('storageAccountNameTidy'), variables('storageAccountApiVersion'), parameters('accountSasProperties')).accountSasToken)]" }
We need to pass three parameters for this function.
  • resourceIdenifier
    The name of the storage account within the specified resource group.
  • apiVersion
    The API version to use for this operation.
  • requestParameters
    We need to pass parameters as specified here.
  1. "accountSasProperties": { "type""object""defaultValue": { "signedServices""b""signedPermission""rl""signedResourceTypes""sco""keyToSign""key2""signedExpiry""[parameters('sasTokenExpiry')]" } }  
We can find more details about parameters specified herein above Microsoft documentation.
 

Generate connection string with storage account key

 
We can generate connection string which has full access to storage account with the storage account access keys.
 
We can use listKeys ARM function for this. You can find more details about this function here. We need to pass two parameters for this function.
  • Storage account resource id
  • API version
This function gives you all keys in the storage account and we can select one key to create connection string as below.
  1. listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountNameTidy')), variables('storageAccountApiVersion')).keys[0].value  

Deploy ARM template

 
We can use the following PowerShell script to deploy ARM template.
 
Note
Fill out the required parameters. (denotes in the capital). For this deployment, we use Azure Service principle.
 
Please take a look at this post on my blog to read more on how to create an Azure service principle. 
  1. $password = "SECRET"  
  2. $clientId = "CLIENTID"  
  3. $securePassword = ConvertTo-SecureString $password -AsPlainText -Force  
  4. $credentials = New-Object System.Management.Automation.PSCredential ($clientId, $securePassword)  
  5. Login-AzureRmAccount -ServicePrincipal -TenantId "TENANTID" -SubscriptionId "SUBSCRIPTIONID" -Credential $credentials   
  6.   
  7.   
  8. $templateFilePath = "ARM TEMPLATE PATH"  
  9.   
  10. $resourceGroupName = "RESOURCEGROUPNAME"  
  11. $resourceGroupLocation = "LOCATION"  
  12. $deploymentName = "DEPLOYMENTNAME"  
  13.  
  14. #Create or check for existing resource group  
  15. $resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue  
  16. if(!$resourceGroup)  
  17. {  
  18.     Write-Host "Resource group '$resourceGroupName' does not exist. To create a new resource group, please enter a location.";  
  19.     if(!$resourceGroupLocation) {  
  20.         $resourceGroupLocation = Read-Host "resourceGroupLocation";  
  21.     }  
  22.     Write-Host "Creating resource group '$resourceGroupName' in location '$resourceGroupLocation'";  
  23.     New-AzureRmResourceGroup -Name $resourceGroupName -Location $resourceGroupLocation  
  24. }  
  25. else{  
  26.     Write-Host "Using existing resource group '$resourceGroupName'";  
  27. }  
  28.  
  29.  
  30. # Start the deployment  
  31. Write-Host "Starting deployment...";  
  32. New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFilePath;  
We can see the following output once deployment is successful.
 
So this is how we deploy storage account and generate connection strings.
 

Summary

 
In most of the cases when we do Azure resource deployment using ARM template, we found our self in a situation where we need to create a storage account and generate connection strings. So in this post, we explained how we can get this requirement done. Hope This would be helpful.