[Build 2019] Azure Functions 2.xのPowerShellでAzure Firewallを自動停止・起動させる

今回はMicrosoft Build 2019でアナウンスのあった「Azure Functions 2.x PowerShell」を利用し、
Azure Firewallの自動停止・起動を試してみる。FunctionsにこだわらずともAzure Automationなどを使えば仮想マシンの停止・起動といった自動化は可能だが、Runbookを作ったりとなにかと手間で、仕組みに慣れてないと敷居が高い。

それよりもLinux OSのCronでBashスクリプトを定期実行させるように、作ったPowerShellスクリプトサクッと定期実行させる環境が欲しいところだ。

ちなみに、以前にもFnctionsでPowerShellがプレビュー版としてサポートされたことがあったようだが、いつの間にか利用できなくなり今回の復活に至った経緯があるそうだ。

ゴール

Azureテスト環境上のAzure Firewallを特定の時間に自動的に停止・再開させる関数を作成する。

セットアップ

Azure Portalに慣れていればAzure Functionx 2.xのセットアップは簡単だ。

  1. Functions Appワークスペースの作成

ここではPowerShellを使いたいため、OSとして「Windows」を選ぶ。
ランタイムスタックで「PowerShell」が選べるようになっているはずだ。

Function Appの新規作成

  1. Function Appができあがったら、停止スクリプトを実行する新しい関数を作成する。特定の時間にFunctionを呼び出すので、「Time Trigger」を選択する。

関数の作成

  1. ここでは、火曜日-土曜日の夜中の2時に実行されるようスケジュールを設定した。

Time Trigger

  1. 同様に、開始スクリプトを構成する新しい関数を作成すると、
    Function Appは以下のような構成となる。

Function Appの状態

依存関係の解決

PowerShellでAzureコマンドを実行するには、Azモジュール(*1)が必要だが、
Azure Functions 2.xにおいてはユーザーによるAzモジュールの導入作業は不要だ。

Azure Functionの関数における「Get-Module -ListAvailable」コマンド実行
結果は以下の通りであり、デフォルトでAzモジュールが利用可能な状態であることがわかる。
ModuleType Version Name PSEdition ExportedCommands
2019-05-14T00:24:55.518 [Information] OUTPUT: ---------- ------- ---- --------- ----------------
2019-05-14T00:24:55.518 [Information] OUTPUT: Script 1.8.0 Az Core,Desk
2019-05-14T00:24:55.518 [Information] OUTPUT: Script 1.5.2 Az.Accounts Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosav…
2019-05-14T00:24:55.519 [Information] OUTPUT: Script 1.0.1 Az.Aks Core,Desk {Get-AzAks, New-AzAks, Remove-AzAks, Import-AzAksCr…
2019-05-14T00:24:55.519 [Information] OUTPUT: Script 1.1.0 Az.AnalysisServices Core,Desk {Resume-AzAnalysisServicesServer, Suspend-AzAnalysi…
~以下省略

(*)AzureRMモジュールの後継となるモジュール

スクリプトの作成

Azureの認証

PowerShellから自分のAzureアカウントでログインを試みたところエラーとなってしまった。
多要素認証が必要なアカウントはAzure Functionx 2.xでは利用できないようだ。
代わりに以下コマンドでServicePrincipalをAzure AD上に新規作成し利用することにした。
Import-Module Az.Resources
$credentials = New-Object Microsoft.Azure.Commands.ActiveDirectory.PSADPasswordCredential -Property @{ StartDate=Get-Date; EndDate=Get-Date -Year 2024; Password="SecurePasswordHere" }
$sp = New-AzAdServicePrincipal -DisplayName "ServicePrincipalDisplayName" -PasswordCredential $credentials

Azure Firewallの起動・停止

ここに実現したい処理をPowerShellで書けばよい。
ここでは、Azure Firewallを停止・起動するスクリプトを作成する。

Firewall起動ブロック

function startazfw($azfwName,$azfwRGName,$vnetName, $vnetRGName, $pipName, $pipRGName){
Write-Host "Starting Azure Firewall $azfwName."
$azfwName
$azfw = Get-AzureRmFirewall -Name $azfwName -ResourceGroupName $azfwRGName
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $azfwRGName -Name $vnetName

$publicip = Get-AzureRmPublicIpAddress -Name $pipName -ResourceGroupName $pipRGName
$azfw.Allocate($vnet,$publicip)
Set-AzureRmFirewall -AzureFirewall $azfw
}

Firewall停止ブロック

function stopazfw($azfwRGName,$azfwName){
Write-Host "Deallocating Azure Firewall $azfwName."
$azfw = Get-AzureRmFirewall -Name $azfwRGName -ResourceGroupName $azfwName
$azfw.Deallocate()
Set-AzureRmFirewall -AzureFirewall $azfw
}

変数宣言

$azfwName="myazurefw"
$azfwRGName="*****-*******"
$vnetRGName="*****-******* "
$vnetName="*************-vnet01"
$pipRGName="*****-*******"
$pipName="azureFirewalls-ip"

ブロック実行

起動

# 起動
startazfw $azfwName $azfwRGName $vnetName $vnetRGName $pipName $pipRGName

停止

# 停止
stopazfw $azfwName $azfwRGName

テスト

実行ボタンを押すとFunctions内でスクリプトが実行されコンソールにログが表示される。
また、各関数の監視メニューからも実行結果を確認可能だ。自動実行の結果を確認する場合は後者を確認することになるだろう。

Functionsの監視

Azure Firewall停止関数をテスト実行しAzure Firewallの状態を確認すると、プライベートIPやパブリックIPがリリースされ、Azure Firewallが停止状態となったことを確認できた。
サンプル
AzureFWの状態

今後はTime Triggerで設定したスケジュールに従い、サーバーレスでこの処理が繰り返し自動実行されることになる。

まとめ

Azure Functions2.xでPowerShellを利用する場合のポイントは以下の通り。

  • Azコマンドを標準で利用できる(モジュールの導入作業不要)
  • 多用素認証が必要なAzureアカウントは利用できないので、サービスプリンシパルを用意する
  • Time Triggerにより仮想マシンなしでスクリプトを定期実行可能
  • PowerShellのため、プログラムに精通するアプリケーション開発者でなくても利用しやすい

Azure Firewallに限らずPowerShellのAzモジュールで操作可能なAzureのリソースであればAzure Functionsで自動実行させることができる。もちろん、Azure以外のPowerShellコマンドも実行可能だ。スクリプトの内容はアイディア次第。読者の皆さんもぜひAzure Functions 2.xを活用してみてはいかがだろうか。