はじめに
AzureでNetwork Security Group(NSG)を作成したものの疎通確認を1個1個実施していくと膨大な時間と手間が掛かってしまいます。
なんとか一括で出来ないものかと悩んでいたところ、
Network WatcherのIPフローの確認
でNSGのチェックが出来るということを思い出しました。
そしてポータルにあるのであればAzure PowerShellで実行出来るだろう。と思い、調べてスクリプト作ってみました。
疎通確認用インプットデータ準備
編集が簡単に出来るようにインプットデータはエクセルを選択。
エクセルに必要なデータを入力出来る表を作成。
パラメータファイル
読込むエクセルのシート名や列などをパラメータ化し、jsonに記述するようにしました。
その他にサブスクリプションID等も一緒にパラメータ化。
シートは複数選択出来るようにしています。
{
"Excel": {
"InitialDirectory": "C:\\",
"Sheet": [
{
"Name": "Main",
"Column": {
"VMName": 2,
"ResourceGroup": 3,
"Direction": 4,
"Protocol": 5,
"LocalPort": 6,
"RemoteIPAddress": 7,
"RemotePort": 8,
"Max": 8
},
"Row": {
"Start": 4
}
}
]
},
"Azure": {
"SubscriptionID": "",
"NetworkWatcher": {
"ResourceGroup": "NetworkWatcherRG",
"Name": "NetworkWatcher_japaneast"
}
},
"Output": {
"Directory": "C:\\out"
}
}
スクリプトの作成
PowerShell 7で作成しました。
エクセルを1行ずつ読み込んでIPフローの確認
を実行します。
VMが停止していると実行できないため、停止している場合はスキップするようにしています。
他にはブランクの項目がある場合もスキップします。
foreach ($eachRow in $($Row.Start)..($MaxRow)) {
# ブランク項目存在チェック
$blankCol = $ExcelRange[$eachRow, $Column.VMName]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.ResourceGroup]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.Direction]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.Protocol]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.LocalPort]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.RemoteIPAddress]
$blankCol = $blankCol -and $ExcelRange[$eachRow, $Column.RemotePort]
if (!$blankCol) {
$Log.Warn("空白の項目が存在するため、次の行にスキップします。")
continue
}
# VM情報の取得
if ($VirtualMachine.Name -ne $ExcelRange[$eachRow, $Column.VMName]) {
$VirtualMachine = $null
$VirtualMachine = Get-AzVM -ResourceGroupName $ExcelRange[$eachRow, $Column.ResourceGroup] -Name $ExcelRange[$eachRow, $Column.VMName]
if (!$VirtualMachine) {
$Log.warn("仮想マシン「$($ExcelRange[$eachRow, $Column.VMName])」の取得に失敗しました。")
$resultCheck = $returnCode.Error
continue
}
# VMステータス取得
$VMStatus = ($VirtualMachine | Get-AzVM -Status).Statuses | where { $_.Code -match "PowerState" }
}
if ($VMStatus.Code -ne "PowerState/running") {
$Log.Warn("仮想マシン「$($ExcelRange[$eachRow, $Column.VMName])」を起動してください。現在のステータスは「$($VMStatus.Code)」です。")
$resultCheck = $returnCode.Error
continue
}
# プライベートIPアドレス(NIC)情報の取得
$NetworkInterface = $null
$NetworkInterface = Get-AzNetworkInterface -ResourceGroupName $VirtualMachine.ResourceGroupName | where { $_.VirtualMachine.Id -eq $VirtualMachine.Id }
$LocalIP = $NetworkInterface.IpConfigurations.PrivateIpAddress
$Log.info("測定内容: 仮想マシン:$($VirtualMachine.Name) 方向:$($ExcelRange[$eachRow, $Column.Direction]) プロトコル:$($ExcelRange[$eachRow, $Column.Protocol]) ローカルIP:${LocalIP} ローカルポート:$($ExcelRange[$eachRow, $Column.LocalPort]) リモートIP:$($ExcelRange[$eachRow, $Column.RemoteIPAddress]) リモートポート:$($ExcelRange[$eachRow, $Column.RemotePort])")
# ローカルIPとリモートIPの同一チェック
if ($LocalIP -eq $ExcelRange[$eachRow, $Column.RemoteIPAddress]) {
$Log.Warn("リモートIPがローカルIPと同一のため、次の行にスキップします。")
$resultCheck = $returnCode.Error
continue
}
# IPFlow実行
$resultNWIPFlow = $null
$resultNWIPFlow = Test-AzNetworkWatcherIPFlow -NetworkWatcher $NetworkWatcher -TargetVirtualMachineId $VirtualMachine.Id -Direction $ExcelRange[$eachRow, $Column.Direction] -Protocol $ExcelRange[$eachRow, $Column.Protocol] -LocalIPAddress $LocalIP -RemoteIPAddress $ExcelRange[$eachRow, $Column.RemoteIPAddress] -LocalPort $ExcelRange[$eachRow, $Column.LocalPort] -RemotePort $ExcelRange[$eachRow, $Column.RemotePort]
if (!$resultNWIPFlow) {
$Log.Error("NSGチェック処理に失敗しました。")
$resultCheck = $returnCode.Error
continue
}
$Log.Info("結果: アクセス:$($resultNWIPFlow.Access) ルール:$($resultNWIPFlow.RuleName)")
$OutputNSGCheck += "$($resultNWIPFlow.Access),$($resultNWIPFlow.RuleName),$($VirtualMachine.Name),$($ExcelRange[$eachRow, $Column.Direction]),$($ExcelRange[$eachRow, $Column.Protocol]),$($LocalIP),$($ExcelRange[$eachRow, $Column.LocalPort]),$($ExcelRange[$eachRow, $Column.RemoteIPAddress]),$($ExcelRange[$eachRow, $Column.RemotePort])"
}
スクリプトの実行
スクリプト実行前にAzureにPowerShellでログインします。
Login-AzAccount
ログイン後、スクリプトを実行します。
.\AzureNSGCheck.ps1 -ConfigFileName NSGCheckConfig.json
読込むエクセルファイルを選択するダイアログが表示されますのでファイルを選択します。
処理が実行され、結果がcsvファイルで出力されます。
内容は許可/拒否、対応したセキュリティルール名と実行した情報です。
Access,Rule,VMName,Direction,Protocol,LocalIP,LocalPort,RemoteIP,RemotePort
Allow,defaultSecurityRules/AllowVnetInBound,sample-vm,Inbound,TCP,10.0.0.4,3389,10.0.1.4,3389
Deny,defaultSecurityRules/DenyAllInBound,sample-vm,Inbound,TCP,10.0.0.4,3389,10.10.0.5,3389
Allow,defaultSecurityRules/AllowVnetInBound,sample-vm,Inbound,TCP,10.0.0.4,22,10.0.1.4,22
Deny,defaultSecurityRules/DenyAllOutBound,sample-vm,Outbound,TCP,10.0.0.4,443,0.0.0.0,443
おわりに
これでAzureポータルからポチポチ実行しなくても良くなりました。
ただ、あくまでNSGのチェックになるのでスクリプトの実行結果がOKでもOS上で疎通確認すると結果が異なることがあります。
OS上のfirewall等で引っかかったり。
その辺りは不便ですが、NSG自体の設定に不備がないかの確認が出来るだけでも良しとします。
今回作成したスクリプトはGitHubに公開しています。(こちら)