Connecting Microsoft Forms, Microsoft Flow and Azure Runbooks together to deploy Azure ARM Templates

My college courses did not revolve around learning programming languages. I studied routing, switching and infrastructure. It has been awhile since my college days and we must adapt. With the introduction of Infrastructure as Code, I have evolved and enjoy the process of build, test, repeat and eventually release. However, not all share my enthusiasm with deciphering lines of code. As such, we can make their lives a little easier by creating front ends to our Infrastructure as Code deployments. Let’s begin...

Getting Started

There is an assumption here that you have created and deployed ARM templates from PowerShell using a template and passing in a parameters file.

Before we get to the Form and Flow, we need to know what parameters are needed within our template. For the case of simplicity, we will deploy a new Storage Account to an Azure Subsciption. Our ARM template looks like this. Note the three required parameters include “Deployment***” in the name. We will touch on that later. Save this file as TemplateTest.Json.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "DeploymentStorageAccountType": {
            "type": "string",
            "defaultValue": "Standard_LRS",
            "allowedValues": [ "Standard_LRS",
            "Standard_GRS",
            "Standard_ZRS",
            "Premium_LRS"],
            "metadata": {
                "description": "Storage Account type"
            }
        }
        ,
        "DeploymentLocation": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "Location for all resources."
            }
        }
        ,
        "DeploymentStorageAccountName": {
            "type": "string"
        }
    }
    ,
    "variables": {}
    ,
    "resources": [ {
        "type": "Microsoft.Storage/storageAccounts",
        "name": "[parameters('DeploymentStorageAccountName')]",
        "apiVersion": "2018-02-01",
        "location": "[parameters('DeploymentLocation')]",
        "sku": {
            "name": "[parameters('DeploymentStorageAccountType')]"
        }
        ,
        "kind": "Storage",
        "properties": {}
    }
    ],
    "outputs": {}
}

For this example, we will store our template in a Storage Account in Azure. Use the following code to upload the contents and create a share:

# Login to Azure
Connect-AzAccount
Select-AzSubscription -Subscription ""

# Get the access key for your storage account
$key = Get-AzStorageAccountKey -ResourceGroupName '’ -Name
''

# Create an Azure Storage context using the first access key
$context = New-AzStorageContext -StorageAccountName '' -StorageAccountKey $key[0].value

# Create a file share named 'resource-templates' in your Azure Storage account
$fileShare = New-AzStorageShare -Name 'resource-templates' -Context $context

# Add the TemplateTest.json file to the new file share
# "TemplatePath" is the path where you saved the TemplateTest.json file
$templateFile = ‘\TemplateTest.json'
Set-AzStorageFileContent -ShareName $fileShare.Name -Context $context -Source $templateFile

Azure Information

Now that we have a template to use stored in a place that an Automation Account can access, it is time to create a Runbook that calls the template. We can create the PowerShell script locally and upload it with code.

Save the following code as a .ps1 file. Note the additional parameters that start with “Template***”. We do this because we need to differentiate the template file information from the deployment information. For instance, our template may reside in a different Resource Group than where we are deploying our new Storage account.

The next step is to create and publish a runbook with the PowerShell script we’ve just completed (via code of course):

 

param (

[Parameter(Mandatory=$true)]
[string]
$TemplateStorageAccountName,
[Parameter(Mandatory=$true)]
[string]
$TemplateName,
[Parameter(Mandatory=$true)]
[string]
$TemplateStorageResourceGroupName,
[Parameter(Mandatory=$true)]
[string]
$TemplateStorageAccountShareName,
[Parameter(Mandatory=$true)]
[string]
$TemplateStorageAccountKey,
[Parameter(Mandatory=$true)]
[string]
$DeploymentResourceGroupName,
[Parameter(Mandatory=$true)]
[string]
$DeploymentLocation,
[Parameter(Mandatory=$true)]
[string]
$DeploymentStorageAccountName,
[Parameter(Mandatory=$true)]
[string]
$DeploymentStorageAccountType
)

# Authenticate to Azure if running from Azure Automation
$ServicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
Login-AzureRmAccount `

-ServicePrincipal `
-TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId `
-CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint | Write-Verbose

#Set the parameter values for the Resource Manager template

$Parameters = @{

"DeploymentStorageAccountType"= $DeploymentStorageAccountType
"DeploymentLocation" = $DeploymentLocation
"DeploymentStorageAccountName" = $DeploymentStorageAccountName
}

# Create a new context
$Context = New-AzureStorageContext -StorageAccountName $TemplateStorageAccountName -StorageAccountKey $TemplateStorageAccountKey

The next step is to create and publish a runbook with the PowerShell script we’ve just completed (via code of course):

$importParams = @{
    Path                 = '\DeployTemplate.ps1'
    ResourceGroupName     = ''
    AutomationAccountName = ‘
    Type                  = 'PowerShell'
}
Import-AzAutomationRunbook @importParams

# Publish the runbook
$publishParams = @{
    ResourceGroupName     = 'AutomationAccountResourceGroupName>'
    AutomationAccountName = ‘
    Name                  = 'DeployTemplate'
}
Publish-AzAutomationRunbook @publishParams

We can now test our runbook using PowerShell passing in the parameters

# Get the access key for your storage account
$key = Get-AzStorageAccountKey -ResourceGroupName '< TemplateStorageResourceGroupName >' -Name 'StorageAccountName'

# Set up the parameters for the runbook
$runbookParams = @{
    TemplateStorageAccountName       = ‘< TemplateStorageAccountName>’
    TemplateName                     = 'TemplateTest.json'
    TemplateStorageResourceGroupName = ‘
    TemplateStorageAccountShareName  = '
    TemplateStorageAccountKey        =  $key[0].value
    DeploymentResourceGroupName      = '
    DeploymentLocation               = 'EastUS2'
    DeploymentStorageAccountName     = ''
    DeploymentStorageAccountType     = 'Standard_LRS'
}

# Set up parameters for the Start-AzureRmAutomationRunbook cmdlet
$startParams = @{
    ResourceGroupName     = ''
    AutomationAccountName = ‘
    Name                  = 'DeployTemplate'
    Parameters            = $runbookParams
}

# Start the runbook
$job = Start-AzAutomationRunbook @startParams

 

Microsoft Forms

We are now going to create a form for our staff to fill out that will provide the parameters we need for deployment.

Login to Microsoft Forms at https://forms.office.com/

The example below provides a direct mapping to the parameters we need. However, we can change these to be more user friendly.

Screenshot of the Cloud Foundation Framework (CFF) Forms Demo

I also recommend setting a restriction to the Form via the settings:

Settings panel in Microsoft Forms showing that only people in the organization can respond, and that it will record the names

Microsoft Flow

Let’s bring it all together with Microsoft Flow. Flow will monitor the form submissions and kickoff the Azure runbook job for us. Ensure the second task to get response details is included. It will provide the list of items to choose as parameters.

Microsoft Flow screenshot

Closing

I hope you enjoyed this quick overview of deploying ARM templates using input from forms. As I continue to learn Microsoft Flow, I will be adding in an approval process step to ensure deployments are structured. If you have any questions, feel free to reach out.

 

 




Our Values Are Found in Everything we do
AIR:


Attitude

We are professionals; we are accountable and never say, "It's not my job."

Integrity

We are upfront on what we say we will do, and then we do it.

Relationships

We build strong relationships with clients, partners, community, and most importantly, with each other.
Want to enable your future workforce?

We're here to help.

Get Started today!
Loading...