Skip to content

Instantly share code, notes, and snippets.

@andreasbotsikas
Last active May 10, 2019 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andreasbotsikas/a4fdfaaa8d47284993e419b43d5431d4 to your computer and use it in GitHub Desktop.
Save andreasbotsikas/a4fdfaaa8d47284993e419b43d5431d4 to your computer and use it in GitHub Desktop.
Azure API Management backup automation
<#
.SYNOPSIS
This Azure Automation runbook automates Azure API Management backup to Blob storage and deletes old backups from blob storage.
.DESCRIPTION
You should use this Runbook if you want manage Azure API Management backups in Blob storage.
This is a PowerShell runbook, as opposed to a PowerShell Workflow runbook.
It requires AzureRM.ApiManagement module to be installed.
The script uses the AzureRunAsConnection connection to login and perform the backup.
.PARAMETER ApimResourceGroupName
Specifies the name of the resource group where the Azure Api Management instance is located.
.PARAMETER ApimInstanceName
Specifies the name of the Azure Api Management which script will backup.
.PARAMETER StorageAccountName
Specifies the name of the storage account where backup file will be uploaded.
.PARAMETER StorageAccountKey
Specifies the key of the storage account where backup file will be uploaded.
.PARAMETER BlobContainerName
Specifies the container name of the storage account where backup file will be uploaded. Container will be created
if it does not exist.
.PARAMETER BackupFilePrefix
Specifies the backup blob file prefix. The suffix will be automatically generated based on the date in the format
yyyyMMddHHmm followed by the .bak file extension. Default value apim_.
.PARAMETER RetentionDays
Specifies the number of days how long backups are kept in blob storage. The default value is 30 days as the backups
expire after that. Script will remove all older files from container, thus a dedicated container should be used
for this script.
.INPUTS
None.
.OUTPUTS
Human-readable informational and error messages produced during the job. Not intended to be consumed by another runbook.
#>
param(
[parameter(Mandatory=$true)]
[String] $ApimResourceGroupName,
[parameter(Mandatory=$true)]
[String] $ApimInstanceName,
[parameter(Mandatory=$true)]
[String]$StorageAccountName,
[parameter(Mandatory=$true)]
[String]$StorageAccountKey,
[parameter(Mandatory=$true)]
[string]$BlobContainerName,
[parameter(Mandatory=$false)]
[string]$BackupFilePrefix = "apim_",
[parameter(Mandatory=$false)]
[Int32]$RetentionDays = 30
)
$ErrorActionPreference = 'stop'
function Login() {
$connectionName = "AzureRunAsConnection"
try
{
Write-Verbose "Acquiring service principal for connection '$connectionName'" -Verbose
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
Write-Verbose "Logging in to Azure..." -Verbose
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint | Out-Null
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
}
function Create-Blob-Container([string]$blobContainerName, $storageContext) {
Write-Verbose "Checking if blob container '$blobContainerName' already exists" -Verbose
if (Get-AzureStorageContainer -ErrorAction "Stop" -Context $storageContext | Where-Object { $_.Name -eq $blobContainerName }) {
Write-Verbose "Container '$blobContainerName' already exists" -Verbose
} else {
New-AzureStorageContainer -ErrorAction "Stop" -Name $blobContainerName -Permission Off -Context $storageContext
Write-Verbose "Container '$blobContainerName' created" -Verbose
}
}
function Backup-To-Blob-Storage([string]$apimResourceGroupName, [string]$apimInstanceName, $storageContext, [string]$blobContainerName, [string]$backupPrefix) {
$backupBlobName = $backupPrefix + (Get-Date).ToString("yyyyMMddHHmm") + ".bak"
Write-Verbose "Starting APIM backup to blob '$blobContainerName/$backupBlobName'" -Verbose
Backup-AzureRmApiManagement -Name $apimInstanceName -ResourceGroupName $apimResourceGroupName -StorageContext $storageContext `
-TargetContainerName $blobContainerName `
-TargetBlobName $backupBlobName
}
function Delete-Old-Backups([int]$retentionDays, [string]$blobContainerName, $storageContext) {
Write-Output "Removing backups older than '$retentionDays' days from container: '$blobContainerName'"
$isOldDate = [DateTime]::UtcNow.AddDays(-$retentionDays)
$blobs = Get-AzureStorageBlob -Container $blobContainerName -Context $storageContext
foreach ($blob in ($blobs | Where-Object { $_.LastModified.UtcDateTime -lt $isOldDate -and $_.BlobType -eq "BlockBlob" })) {
Write-Verbose ("Removing blob: " + $blob.Name) -Verbose
Remove-AzureStorageBlob -Blob $blob.Name -Container $blobContainerName -Context $storageContext
}
}
Write-Verbose "Starting APIM backup" -Verbose
Write-Verbose "Establishing storage context" -Verbose
$StorageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $StorageAccountKey
Login
Create-Blob-Container `
-blobContainerName $blobContainerName `
-storageContext $storageContext
Backup-To-Blob-Storage `
-apimResourceGroupName $ApimResourceGroupName `
-apimInstanceName $ApimInstanceName `
-storageContext $StorageContext `
-blobContainerName $BlobContainerName `
-backupPrefix $BackupFilePrefix
Delete-Old-Backups `
-retentionDays $RetentionDays `
-storageContext $StorageContext `
-blobContainerName $BlobContainerName
Write-Verbose "APIM backup script finished" -Verbose
@mikedizzle
Copy link

I keep getting issues when the backup-azurermapimanagement cmdlet is run. I get the following error saying something about an invalid cast. I'm thinking it's when referencing the storagecontext variable in the cmdlet. Help?
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: System.Management.Automation.ParameterBindingException: Cannot bind parameter 'StorageContext'. Cannot convert the "Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" value of type "Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" to type "Microsoft.Azure.Commands.Common.Authentication.Abstractions.IStorageContext". ---> System.Management.Automation.PSInvalidCastException: Cannot convert the "Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" value of type "Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext" to type "Microsoft.Azure.Commands.Common.Authentication.Abstractions.IStorageContext". at System.Management.Automation.LanguagePrimitives.ThrowInvalidCastException(Object valueToConvert, Type resultType) at System.Management.Automation.LanguagePrimitives.ConvertNoConversion(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable) at System.Management.Automation.LanguagePrimitives.ConversionData`1.Invoke(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable) at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion, IFormatProvider forma

@mikedizzle
Copy link

I found that I needed to supply the subscription name in the Auth function. I have updated the script in my fork here: https://gist.github.com/mikedizzle/1d4f012857b654f301ab7f1047b56ea8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment