AzFnUtil.psm1
<#
# Module that includes utility functions that make use of # # AzureRM and relevant SDKs in order to # # help with azure functions management. #> <# .DESCRIPTION Used for validating whether an azure web app is a function. .PARAMETER appSvc The web app used to perform the relevant checks by. #> Function Test-AzFn { param( [Parameter(Mandatory=$true,Position=0)] [PSCustomObject]$appSvc ) return $appSvc.kind -ilike "*function*"; } <# .DESCRIPTION Used to check the running status of a specific azure function from an azure web app list. .PARAMETER fnName The azure function name to check. .PARAMETER webapp The list of azure functions app services to perform the necessary checks based on the function name. #> Function Test-FnStopped { param( [Parameter(Mandatory=$true,Position=0)] [string]$fnName, [Parameter(Mandatory=$true,Position=1)] [PSCustomObject[]]$webapp ) $reswebApp = $webApp | ?{Test-AzFn -appSvc $_} return ($reswebapp | ?{$_.Name -eq $fnName}).state -eq "Stopped"; } <# .SYNOPSIS Retrieve a nested listing of all azure function apps and relevant functions -with details- .DESCRIPTION Get all azure function apps from list of web apps and all inner function data that are a part of a function project. This includes basic top level information and the extended functions data of the web application such as: invokable url, inner function name, language. #> Function Get-AzureFn { if(((Get-Module -ListAvailable Azure) -ne $null) -and ($env:PSModulePath -ilike "*\Microsoft SDKs\Azure\*")) { Write-Host "Azure SDK detected OK.." -ForegroundColor Cyan -BackgroundColor DarkBlue $is32bit = (Test-Path "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell"); $is64bit = (Test-Path "$env:ProgramFiles\Microsoft SDKs\Azure\PowerShell"); $sdkval =""; if ($is32bit) { $sdkval = "32-bit"; } if ($is64bit) { $sdkval ="64-bit"; } Write-Host "Running script with $($sdkval) SDK.." -ForegroundColor Cyan -BackgroundColor DarkBlue } Try { if (((Get-Module AzureRM.Profile) -eq $null) -or ((Get-Module AzureRM.Websites) -eq $null)) { Write-Warning "`r`nSetting Azure SDK Modules.."; Import-Module AzureRM.Profile,AzureRM.Websites -ErrorVariable "testmodule" -Force } } Catch { Write-Error "Cannot import modules properly, error $testmodule - Please make sure that the Azure SDK is installed properly."; return; } if ((Get-AzureRmContext -OutVariable 'azureRmCtx') -eq $null) { Login-AzureRmAccount; return Write-Host "`r`n -- Login complete, re-run script. -- `r`n" -ErrorAction Stop; } $rgfnInfo = (Get-AzureRmResource | ?{$_.Kind -eq "web"}); if ($rgfnInfo -eq $null) { Trap [System.Exception] { return Write-Host "Could not retrieve azure resources, exiting.." -BackgroundColor Red -ForegroundColor DarkGray -ErrorAction Stop; } } $rgData = @{"rgName"=($rgfnInfo | Select -First 1 -ExpandProperty ResourceGroupName); "Plan"=$(($rgfnInfo | Select -First 1 -ExpandProperty Location)+"Plan") }; Try { $appsvc = Get-AzureRmAppServicePlan -ResourceGroupName $rgData['rgName'] -Name $rgData['Plan'] $webAppsvcs = Get-AzureRmWebApp -AppServicePlan $appsvc $subscr = (Get-AzureSubscription).SubscriptionId # Azure profile modules v5.* $rmProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile; $rmClient = [Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient]::new($rmProfile); $bearerAccess = $rmClient.AcquireAccessToken($azureRmCtx.Tenant.TenantId); $fnlisting = Invoke-WebRequest -Method Get -Uri "https://management.azure.com/subscriptions/$subscr/resourceGroups/$($rgData['rgName'])/providers/Microsoft.Web/sites/?api-version=2016-08-01" -UseDefaultCredentials -UseBasicParsing -Headers @{Authorization=("Bearer {0}" -f $bearerAccess.AccessToken)} $fns = ($fnlisting.Content | ConvertFrom-Json).Value.properties; $stoppedfns = $fns | %{ Test-FnStopped -fnName $_.name -webapp $_ } -ErrorAction SilentlyContinue $fnOutput = @(); $stoppedfns | %{ $fnObjOut = New-Object -TypeName PSCustomObject; $fnObjOut | Add-Member -MemberType NoteProperty -Name "Name" -Value $_.Name $fnObjOut | Add-Member -MemberType NoteProperty -Name "State" -Value $_.State; $fnObjOut | Add-Member -MemberType NoteProperty -Name "Enabled" -Value $_.Enabled; $fnObjOut | Add-Member -MemberType NoteProperty -Name "HttpsOnly" -Value $_.HttpsOnly; $fnObjOut | Add-Member -MemberType NoteProperty -Name "HostName" -Value $_.DefaultHostName; $fnObjOut | Add-Member -MemberType NoteProperty -Name "FunctionsDetail" -Value ""; $fnOutput += $fnObjOut; } $datafnOut = @(); $stoppedfns | %{ $data = Invoke-WebRequest -Method Get -Uri "https://management.azure.com/subscriptions/$subscr/resourceGroups/$($rgData['rgName'])/providers/Microsoft.Web/sites/$($_.name)/functions?api-version=2016-08-01" -UseDefaultCredentials -UseBasicParsing -Headers @{Authorization=("Bearer {0}" -f $bearerAccess.AccessToken)}; $datafnOut+=($data.Content | ConvertFrom-Json).value.properties; } [PSCustomObject[]]$fnInfo=@(); $r=0; $datafnOut | %{ $fnInfo += @{"name"=$_.name;"href"=$_.href;"invoke_url"=$_.invoke_url;"language"=$_.language;"isDisabled"=$_.isDisabled}; $fnOutput[$r].FunctionsDetail = $fnInfo; $r++; } } Catch { Logout-AzureRmAccount; Clear-AzureRmContext -Force; Clear-AzureRmDefault -Force; return Write-Error "Exception Occured - $_" -ErrorAction Stop; } # Terminate azure session and cmdlet process. Logout-AzureRmAccount; Clear-AzureRmContext -Force; Clear-AzureRmDefault -Force; return ($fnOutput | Format-Table) } <# .DESCRIPTION Calling an azure function directly from its url and perform error checks. An alternative response can be set via a blob container if there is an error on the function. .PARAMETER InvokeUrlPath The function's endpoint url used to make the http call and error checks. #> Function Invoke-AzureFunctionEndPoint { param( [Parameter(Mandatory=$true,Position=0)] [string]$InvokeUrlPath ) Try { $urlpath = "$InvokeUrlPath" -replace "\?","" -replace "<","" -replace ">","" -replace "@","" -replace "%", "" -replace "\\", "" -replace "&","" -replace "\*", "" -replace "-","" -replace "|","" -replace "`r`n","" -replace "\^","" -replace "\(", "" -replace "\)","" -replace ":{","" -replace ":\'","" -replace "\'}","" -replace ":\[","" -replace "\[\{","" -replace "\}\]" -replace "}","" -replace "\]","" -replace "\'",""; $response = Invoke-RestMethod -Uri $urlpath -ErrorVariable '$error' -UseDefaultCredentials -UseBasicParsing -ErrorAction SilentlyContinue } Catch { Write-Host "Call to azure function failed, getting default response.." | Out-Null; $error | Out-File ".\error-azurefn.log" $altern = ((Invoke-WebRequest -Uri "https://xxxxxx.blob.core.windows.net/xxxxxx/data.json").Content | ConvertFrom-Json); return $altern; # Catch exception, retrieve alternative response from an azure blob container } return ($response.httpResponse | ConvertFrom-Json); } |