Azure Functions is a serverless compute service that allows you to run code on demand without the need to explicitly deploy or manage infrastructure. In this article, we will explore how to use PowerShell, a popular and powerful scripting language, in an Azure Function.
A typical Azure Functions project with PowerShell has a folder structure as follows:
Each function must be in a folder of the same name, which will contain two files: function.json and run.ps1.
The function.json file contains what is needed to trigger the function execution (HTTP trigger, timer trigger, etc.), while run.ps1 contains the function’s body, the code that will be executed.
PowerShell in Azure Functions supports the installation of modules from the PowerShell Gallery repository. To do this, you need to include a `requirements.psd1` file at the root of your project.
To work with Azure Functions locally, you will need the following tools:
Here is an example of a function that extends KeyVault secrets expiring within less than a month by one year. This function will run once per day thanks to the `TimerTrigger` defined in the `function.json` file of our function. It is important to note that the expiration of a secret in KeyVault is not a “true” expiration date, but more of a reminder. In fact, if the secret itself does not have an expiration date, it will still be usable. However, if you have stored, for example, an OAuth token containing an expiration date, it’s likely that the date indicated on the KeyVault secret corresponds to the expiration date of the token, so the token should be renewed before its expiration.
run.ps1 file:
# Define a parameter named $Timer, typically used for a timer-based trigger in PowerShell automation param($Timer) # Output the current date and time to the console, indicating when the script is run Write-Output "PowerShell Timer trigger function executed at: $(Get-Date)" # Define a function named Renew-ExpiringSecrets to renew secrets that are about to expire in Azure Key Vault function Renew-ExpiringSecrets { param ( # Define a mandatory parameter $KeyVaultName, which is the name of the Azure Key Vault [Parameter(Mandatory=$true)] [string]$KeyVaultName, # Define an optional parameter $DaysBeforeExpiry with a default value of 30, which specifies how many days before expiry the secret should be renewed [Parameter(Mandatory=$false)] [int]$DaysBeforeExpiry = 30 ) # Authenticate to Azure using Managed Identity Connect-AzAccount -Identity -AccountId managedIdentityToken # Get the current date and time $currentDate = Get-Date # Calculate the threshold date by adding the specified number of days to the current date $expiryThresholdDate = $currentDate.AddDays($DaysBeforeExpiry) # Retrieve all secrets from the specified Azure Key Vault $secrets = Get-AzKeyVaultSecret -VaultName $KeyVaultName # Loop through each secret in the Key Vault foreach ($secret in $secrets) { # Check if the secret has an expiration date if ($secret.Expires) { # Check if the secret's expiration date is on or before the threshold date (in our case, less than 30 days) if ($secret.Expires -le $expiryThresholdDate) { # Renew the secret (this example simply updates the expiry date) $newExpiryDate = $secret.Expires.AddYears(1) # Get the value of the secret and convert it to a secure string format $secretValue = ConvertTo-SecureString (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name $secret.Name -AsPlainText) -AsPlainText -Force # Update the secret in Azure Key Vault with the new expiry date Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $secret.Name -SecretValue $secretValue -Expires $newExpiryDate # Output a message indicating that the secret has been renewed and its new expiry date Write-Output "Secret '$($secret.Name)' has been renewed and will now expire on $($newExpiryDate)" } } } } # Set the name of the Azure Key Vault to be used in the function $KeyVaultName = "mw-kv-poc" # Call the function to renew any expiring secrets in the specified Azure Key Vault Renew-ExpiringSecrets -KeyVaultName $KeyVaultName
And in the function.json file:
{ "bindings": [ { "name": "Timer", "type": "timerTrigger", "direction": "in", "schedule": "0 0 0 * * *" } ] }
Here, the function will be automatically triggered by a timerTrigger every day at midnight. For more information on CRON syntax, visit: https://man7.org/linux/man-pages/man5/crontab.5.html.
Dependency management can be specified in the profile.ps1 file, which will be loaded at each cold start. Here’s its content for our example:
profile.ps1
# Check if the environment variable MSI_SECRET is present # MSI_SECRET is typically set by Azure when using Managed Service Identity (MSI) for authentication if ($env:MSI_SECRET) { # Disable the automatic saving of Azure context (credentials and other session info) to prevent storing this information on disk Disable-AzContextAutosave -Scope Process | Out-Null # Authenticate to Azure using Managed Identity Connect-AzAccount -Identity } # Import the Az.Keyvault module, which contains cmdlets to manage Azure Key Vaults and their contents Import-Module Az.Keyvault
Pour gérer les versions des modules à utiliser, c’est dans requirements.ps1 que ça se passe !
@{ 'Az.Keyvault' = '3.*' }
Azure Functions offers a powerful platform for serverless development, and with PowerShell, you can leverage your existing scripting skills to build robust solutions.