# Create persistent Azure Automation Runbook variables using Azure Blob Storage

Because Azure Runbooks are invoked in temporary environments, you cannot save the Runbook results for later use in the local files. Which is one of the drawbacks compared to on-premises Schedules Tasks.

But what if you need some output persistence? For example, to take note of what users have already been notified about some issue, so you don't send them the same email next time, the Runbook runs.

For such cases, you have several options, based on the data you need to save.

* If you need to store some simple string or integer, built-in **Azure Automation Variable** is the way to go
    
* Built-in **Azure Automation Variable** can be used for saving some complex objects like array of hashtables etc too (check [How to save complex PowerShell variables as CliXML instead of Newtonsoft.Json.Linq.JProperty in the Azure Automation](https://doitpsway.com/how-to-save-complex-powershell-variables-as-clixml-instead-of-newtonsoftjsonlinqjproperty-in-the-azure-automation) post), but there are some limitations regarding the variable size. Therefore this can be used only for "small" objects a.k.a. it is not very reliable.
    
* But what if you need to store complex variables no matter what their size is? That's where **Azure Blob Storage** steps in 👍
    

# Comparison of saving variables to Azure Blob Storage

## Advantages

* Variables can be serialized using well-known **Export-CliXml** (a.k.a. saved as XML file) and then deserialized using **Import-CliXml** (a.k.a. converted back to the original object) PowerShell commands
    
* You can **saveany PowerShell complex object of any size** without worrying about hitting some internal Automation limits
    
* When importing the serialized variable back to the Runbook, you will get the same complex object **of the same type**, etc
    
* Can be used to **pass complex variables between different Runbooks**
    

## Disadvantages

* Azure Storage **isn't free** to use, but it will cost you like 0.1 $/month (depending on the exported file size and amount of data transfers)
    
* It's **not as simple** as using built-in Azure Automation Variable, because you need to create a Storage Account and set appropriate permissions
    
* Saving and reading data from the Storage Account makes your Runbook a little bit **slower**
    

---

# How to save the Runbook variable to Blob storage then?

## Create an Azure Storage Account

We don't need anything special for our case, so create a **Standard LRS Storage Account with Hot-tier storage** ([official documentation](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-create?tabs=azure-portal)).

You can name it like **persistentvariablesstore.**

Just make sure that `Default to Microsoft Entra authorization in the Azure portal` is set to `Disabled` in the Storage Account configuration pane!

## Create a Container to store your variables (XML files)

Create `Container` (it's like a folder). For example **variables**.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1709991704217/129fbcdc-b279-4521-8bcb-b06b197fa6f5.png align="center")

## Grant IAM role to the Automation Managed Identity

In the `Access Control (IAM)` section of the created container, grant a role `Storage Blob Data Contributor` role to your `Azure Automation Account Managed identity`. This allows the Runbook to modify data in this container.

## Import the AzureResourceStuff module to your Azure Automation

To be able to use my `Export-VariableToStorage`, `Import-VariableFromStorage` PowerShell functions that will help you to save/load variables from Azure storage, you need to add the [AzureResourceStuff](https://www.powershellgallery.com/packages/AzureResourceStuff) module to your Azure Automation

You can do this manually using `Add a module` button.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1709023386795/a1428327-a1ea-4f73-9c25-2e7f7fd71c55.png?auto=compress,format&format=webp align="left")

Or using my function `New-AzureAutomationModule` (part of my [**AzureResourceStuff**](https://www.powershellgallery.com/packages/AzureResourceStuff) module).

```powershell
New-AzureAutomationModule -moduleName AzureResourceStuff -resourceGroupName yourRESOURCEgroupNAME -automationAccountName yourAUTOMATIONaccountNAME
```

For more details check my post [**Import new (or update existing) PowerShell module (including its dependencies!) into Azure Automation Account using PowerShell**](https://doitpsway.com/import-new-or-update-existing-powershell-module-including-its-dependencies-into-azure-automation-account-using-powershell)

## Use my PowerShell functions inside your Runbook to export/import your variables

Now when the `AzureResourceStuff` module is added, you are ready to save variables from your Runbook to Azure storage and vice versa.

Just add a similar code to your Runbook 👇

```powershell
# functions Import-VariableFromStorage, Export-VariableToStorage are part of module AzureResourceStuff 

# authenticate, so you Runbook can work with the Storage
$null = Connect-AzAccount -Identity

# select variable name, this name will be used to store variable in the Storage (as '<name>.xml')
$persistentVariableName = "previouslyProcessedUsers"

# use parameter splatting to define common parameters
$varFncParams = @{
    fileName = $persistentVariableName
    resourceGroupName = "PersistentRunbookVariables"
    storageAccount = "persistentvariablesstore" # cASe SENSitive!
    containerName = "variables"
}

# set your variable
$previouslyProcessed = ...

# to export the variable to the Storage
Export-VariableToStorage -value $previouslyProcessed @varFncParams

# to import the variable back from the Storage
$previouslyProcessed = Import-VariableFromStorage @varFncParams
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💥</div>
<div data-node-type="callout-text">Don't forget to customize <code>resourceGroupName</code>, <code>storageAccount</code> and <code>containerName</code> keys in the <code>$varFncParams</code> hashtable to match your environment!</div>
</div>

To get more details about functions parameters etc, check their help.

Happy scripting 🙂
