logo
Published on

Azure Resource Managment using Azure Functions with Powershell

azure
Authors

This is a short guide on how you can manage Azure resources using Azure Functions with Powershell. You might use this approach to enable automated resource control in your Azure Subscription e.g. Turn off a service everyday at 00:00 and turn it back on at 08:00 Am the next morning

NB: Your Azure Function App needs to have the approapriate permissions to read or configure resources using Powershell. Follow this guide to learn more about managed identity for Azure functions.

Getting started

Step 1 - Create a function App

# Creates a function app that uses the Consumption plan instead of a dedicated app plan
yourResourceGroup=blog-rm-pwsh-rg
azureRegion=westeurope   # You may change this if you wish!
yourFunctionAppName=myblogrm-pwsh-$RANDOM
yourStorageAccount=mystorageaccount$RANDOM

# Create a resource group to manage all app resources collectively
az group create -n $yourResourceGroup -l $azureRegion

# Create a storage account used to store function log files, configuration etc.
az storage account create -n $yourStorageAccount -g $yourResourceGroup -l $azureRegion --sku Standard_LRS

# Finally create a powershell function app with a consumption plan
az functionapp create -g $yourResourceGroup --consumption-plan-location $azureRegion -n $yourFunctionAppName -s $yourStorageAccount --runtime powershell --functions-version 3

Step 2 - Role Assignment

  • Go to the identity section on the functionapp blade to enable managed identity

  • Click on role assignement and assign the required roles for the resources you want to manage


# E.g. Assign a managed identity to the app created in Step 1 and,
# Assign a contributor role to the managed identity within the entire resource group you want to manage
myOtherResourceGroup="/subscriptions/<your-subscription-id>/some-other-rg"

az functionapp identity assign -g $yourResourceGroup -n $yourFunctionAppName \
    --scope $myOtherResourceGroup \
    --role Contributor \
    --verbose

Step 3 - Create HTTP triggered Azure Function

We will make use of the built-in editor in Azure Portal to enable quick test runs of our powershell functions.

  • You are now ready to create a function within your function app. For this example, create a new function with an HTTP trigger

  • Edit, requirements.psd1 file in your app files so that it looks something like this

# This file enables modules to be automatically managed by the Functions service.
# See https://aka.ms/functionsmanageddependency for additional information.
#
@{ 
    'Az.Accounts'  = '2.*'
    'Az.Functions' = '2.*'
    'Az.Resources' = '5.*'
}

  • Make sure that this snippet is present in your profile.ps1 file
  • This snippet enables the function app to authenticate using the assigned managed identity
if ($env:MSI_SECRET) {
    Disable-AzContextAutosave -Scope Process | Out-Null
    Connect-AzAccount -Identity
}

Note: *When using the Consumption function App Plan, It is not recommended to install the entire Az module, as it might cause timeout issues!. Checkout the list of powershell modules your function app might need to use here.

Step 4 - Test

  • Navigate to the internal function code editor in Azure portal
  • Replace the contents of run.ps1 with the following code
using namespace System.Net
param($Request, $TriggerMetadata)


# Use Az module commands to manage your resources here
# Make sure you have assigned the required roles on the managed identity!!!
# For example: Read the metadata of a resource group within your subscription
$rg = (Get-AzResourceGroup -Name "your-own-rg").ResourceGroupName


$body = "Hello, $rg. This HTTP triggered function executed successfully."
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})
  • Use the Test/Run button within the Azure Portal editor to test your function
  • You should see a response similar to this:
Hello, your-own-rg. This HTTP triggered function executed successfully.

Remember to delete the resource you are not using to avoid unexpected charges!

# Remove all resource under the resource group we just created
az group delete -n $yourResourceGroup -y

Troubleshooting

  • "..SubscriptionId cannot be null"

    • Make your Azure Function App has the required roles to acces sthe resource you are trying to manage!
  • "..Az module installation failed"

    • If possible, avoid installing the entire Az module in your function App
    • Only use the submodules that your functions needs, e.g. 'Az.Resources' = '5.*'
  • "Unresolved Az cmd-let...."

    • Check that the managedDependency property is set in host.json
    //........
    
      "managedDependency": {
        "Enabled": true
    }
    
    //......
    
  • "Function timeout..."

    • If you are on the consumption plan, the app may need to re-download the dependenancies
    • In some cases, this may cause the function to run over the minimum timeout setting
    • You can change this deafult setting in host.json file
    // ....
     "functionTimeout": "00:10:00"  // Maximum  value on the consumption plan is 10 minutes
    // ...
    
    • Learn more about this setting, check out the docs

Closing remarks

This is a simple guide to get you started with Azure Resource Management using Azure Functions with Powershell. In my experience this is a rare yet useful pattern when you need to do something like turn off a VM or Container instance based on some event. However it is also important to note that some common use cases like turning on a VM at a specific time of the day can also be achieved using Azure Automation or Azure Dev-Test Labs. It is up to you to decide which approach works best for you.

Update 2023: Azure Container Instances might soon add support for auto-scaling using KEDA. Check out the Azure Updates page for more information on this feature.