Skip to content

Instantly share code, notes, and snippets.

@springcomp
Last active January 24, 2023 08:25
Show Gist options
  • Save springcomp/8a4cf991533b73a203091eca5922451a to your computer and use it in GitHub Desktop.
Save springcomp/8a4cf991533b73a203091eca5922451a to your computer and use it in GitHub Desktop.
Azure API Management `foreach-` PowerShell scripts

Those scripts allow to perform an operation (a script block) to every item in Azure API Management. Supported scripts are:

  • foreach-api.ps1
  • foreach-api-operation.ps1
  • foreach-product.ps1

Those scripts call the following more general - albeit slightly more complex - script:

  • foreach-apim-object.ps1

Using any script block, you can perform any operation on, say, all apis or all products. For instance, to display all apis, type the following command:

PS> . ./foreach-api.ps1 { echo $_ }

Using the provided with-policy.ps1 sample file below, you can find all apis, or products that have a policy containing a given syntax, for instance.

PS> . ./foreach-product.ps1 (. ./with-policy.ps1)
[CmdletBinding()]
param(
[string]$subscriptionId = "39754fe4-dc3a-4f2d-a68a-d2234bb78bb6",
[string]$resourceGroupName = "rg-apim-int",
[string]$serviceName = "apim-lplcloud-int",
[Parameter(Position = 0)]
[PSObject]$scriptBlock = [scriptBlock] { echo $_ },
[Parameter(Position = 1)]
[string]$api = ""
)
BEGIN {
$apiVersion = "2021-01-01-preview"
$baseAddress = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$serviceName"
Function From-Json {
param([string[]] $lines)
ConvertFrom-JSON -InputObject ([string]::Join("`r`n", $lines))
}
Function Serialize-Command {
param([scriptblock]$Scriptblock)
$rxp = '\$using:(?<var>\w+)'
$ssb = $Scriptblock.ToString()
$cb = {
$v = (Get-Variable -Name $args[0].Groups['var'] -ValueOnly)
$ser = [System.Management.Automation.PSSerializer]::Serialize($v)
"`$([System.Management.Automation.PSSerializer]::Deserialize('{0}'))" -f $ser
}
$sb = [RegEx]::Replace($ssb, $rxp, $cb, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
$Serialized = [System.Management.Automation.PSSerializer]::Serialize($sb)
[System.Text.Encoding]::UTF8.GetBytes($Serialized)
}
Function Make-ScriptBlock {
param([scriptBlock]$innerScriptBlock)
$text = @"
`$apiName = [IO.Path]::GetFilename(`$_)
. "$PSScriptRoot/foreach-api-operation.ps1" ``
-SubscriptionId $subscriptionId ``
-ResourceGroupName $resourceGroupName ``
-ServiceName $serviceName ``
-ScriptBlock `$using:innerScriptBlock ``
-Api `$apiName
"@
Serialize-Command ([ScriptBlock]::Create($text))
}
}
PROCESS {
if (-not $api) {
[byte[]] $onEachApi = Make-ScriptBlock -InnerScriptBlock $scriptBlock
. "$($PSScriptRoot)/foreach-api.ps1" `
-SubscriptionId $subscriptionId `
-ResourceGroupName $resourceGroupName `
-ServiceName $serviceName `
-ScriptBlock $onEachApi
} else {
. "$($PSScriptRoot)/foreach-apim-object.ps1" `
-SubscriptionId $subscriptionId `
-ResourceGroupName $resourceGroupName `
-ServiceName $serviceName `
-Fragment "apis/$($api)/operations" `
-ScriptBlock $scriptBlock
}
}
[CmdletBinding()]
param(
[string]$subscriptionId = "39754fe4-dc3a-4f2d-a68a-d2234bb78bb6",
[string]$resourceGroupName = "rg-apim-int",
[string]$serviceName = "apim-lplcloud-int",
[Parameter(Position = 0)]
[PSObject]$scriptBlock = [scriptBlock]{ echo $_ }
)
. "$($PSScriptRoot)/foreach-apim-object.ps1" `
-SubscriptionId $subscriptionId `
-ResourceGroupName $resourceGroupName `
-ServiceName $serviceName `
-Fragment "apis" `
-ScriptBlock $scriptBlock
[CmdletBinding()]
param(
[string]$subscriptionId = "39754fe4-dc3a-4f2d-a68a-d2234bb78bb6",
[string]$resourceGroupName = "rg-apim-int",
[string]$serviceName = "apim-lplcloud-int",
[Parameter(Mandatory = $true, Position = 0)]
[string]$fragment,
[Parameter(Position = 1)]
[PSObject]$scriptBlock = [scriptBlock] { Write-Host $_ }
)
BEGIN {
$apiVersion = "2021-01-01-preview"
$baseAddress = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$serviceName"
Function From-Json {
param([string[]] $lines)
ConvertFrom-JSON -InputObject ([string]::Join("`r`n", $lines))
}
Function Deserialize-Command {
param([PSObject] $command)
switch ($command.GetType().FullName) {
"System.String" {
if ($command.StartsWith("<Objs")) {
$sb = [System.Management.Automation.PSSerializer]::Deserialize($command)
[ScriptBlock]::Create($sb).GetNewClosure()
} else {
[ScriptBlock]::Create($command)
}
}
"System.Byte[]" { Deserialize-Command ([System.Text.Encoding]::UTF8.GetString($command)) }
"System.Management.Automation.ScriptBlock" { [scriptBlock] $command }
}
}
[scriptBlock] $script = Deserialize-Command $scriptBlock
}
PROCESS {
$address = "$($baseAddress)/$($fragment)?api-version=$($apiVersion)"
$nextLink = $null
do {
## https://github.com/Azure/azure-cli/blob/dev/doc/quoting-issues-with-powershell.md
## when iterating over multiple pages, nextLink will have a &%24skip= (&$skip=)
## this is incorrectly interpreted by PowerShell and cannot be easily escaped away
## so we disable parsing using the --% switch
$command = "az --% rest --method GET --uri $address --query {nextLink:nextLink,value:value[].id}" "
$records = iex $command
$json = From-Json $records
$nextLink = $json.nextLink
$address = $nextLink
$json.value |% $script
Write-Host $nextLink -ForegroundColor Cyan
} until (-not $nextLink)
}
[CmdletBinding()]
param(
[string]$subscriptionId = "39754fe4-dc3a-4f2d-a68a-d2234bb78bb6",
[string]$resourceGroupName = "rg-apim-int",
[string]$serviceName = "apim-lplcloud-int",
[Parameter(Position = 0)]
[PSObject]$scriptBlock = { echo $_ }
)
. "$($PSScriptRoot)/foreach-apim-object.ps1" `
-SubscriptionId $subscriptionId `
-ResourceGroupName $resourceGroupName `
-ServiceName $serviceName `
-Fragment "products" `
-ScriptBlock $scriptBlock
[scriptblock] {
$item = $_
Write-Host "Retrieving policies for  $item"
$policy = az rest --method GET --uri "$($item)/policies?api-version=2021-01-01-preview" --query "value[].properties.value" --output tsv
if ($policy) {
$xml = [string]::Join("`r`n", $policy)
$contains = $xml.Contains("-logger")
if ($contains) { Write-Host $item }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment