【Azure】AzurePowerShellを使用してApplication GatewayおよびWAFポリシー(カスタムルール：IP制限)の作成

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
インターネット経由からの通信について、指定したIPアドレスを制限したい。
上記要望が案件にて発生したため、Azureの「Application Gateway」および「Azure Web アプリケーション ファイアウォール (WAF) ポリシー」を用いて検証を実施。
構築はAzureCloudShellのPowerShellを利用します。

### 1-2 対象読者
- Azureに興味がある
- AzurePowerShellに興味がある
- 「Application Gateway」および「WAFポリシー」を触ったことある

### 1-3 成果物
成果物は以下になります。
- 「WAFポリシー」：今回は指定したIPアドレスを制限する設定を行うため必要となるサービス（他にも多数の機能あり）
- 「Application Gateway」：L7ロードバランサー。「WAFポリシー」をこのサービスに紐づける。
- 「Virtaul Machine」：検証用としてIISをインストールして利用する。
※その他、上記を構成するうえで必要なパブリックIPアドレス、仮想ネットワーク、NSG等も作成しています。

<img width="400" alt="成果物_20220701.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/f3787de7-c7a0-33c6-3f07-221f80c9c49b.png">

※事前にAzureアカウントは作成済みです。

### 1-4 検証内容
1. 成果物を作成後、クライアント端末のWEBブラウザに「Application Gateway」のパブリックIPアドレスを入力し、IISが表示されることを確認する。
1. 「WAFポリシー」のカスタムルールを作成する。内容としてはクライアント端末のIPアドレスをブロックする。
1. 再度、クライアント端末のWEBブラウザに「Application Gateway」のパブリックIPアドレスを入力し、IISが表示されないことを確認する。


# 2. 構築
それでは、PowerShellで作成します。仮想マシンを作成するまで記載します。
### 2-1 仮想マシンの作成およびIIS表示確認

```powershell:PowerShell
# 変数の設定 ====================================================================
$rgname = "waf-rg"                           # リソースグループ名
$location = "japaneast"                      # ロケーション
$appgwName = "waf-agw"                       # アプリケーションゲートウェイ名
$wafPolicy = 'waf-waf'                       # WAFポリシー名
$wafPolicyCustomRules = 'ToLimitIPAddress'   # WAFポリシーのカスタムルール名

$vnetName = 'waf-vnet'                       # 仮想ネットワーク名
$snetName1 = 'waf-snet-agw'                  # アプリケーションゲートウェイ用サブネット名
$snetName2 = 'waf-snet-backend'              # バックエンド用サブネット名
$VnetPrefixes = '10.0.0.0/16'                # VNetのIPアドレス プレフィックス
$SnetPrefixes1 = '10.0.0.0/24'               # アプリケーションゲートウェイ用サブネットのIPアドレス プレフィックス
$SnetPrefixes2 = '10.0.1.0/24'               # バックエンド用サブネットのIPアドレス プレフィックス

$vmName = 'waf-vm'                           # 仮想マシン名
$nsg = 'waf-nsg'                             # ネットワークセキュリティグループ名
$vmPip = 'waf-pip-vm'                        # 仮想マシン用パブリックIPアドレス名

$vmPip = 'waf-pip-vm'                        # 仮想マシン用パブリックIPアドレス名
$appgwPip = "waf-pip-agw"                    # アプリケーションゲートウェイ用パブリックIPアドレス名
# ==============================================================================

# 構築 =========================================================================
# リソースグループの作成
$resourceGroup = New-AzResourceGroup -Name $rgname -Location $location

# 仮想ネットワークの作成
$sub1 = New-AzVirtualNetworkSubnetConfig -Name $snetName1 -AddressPrefix $SnetPrefixes1
$sub2 = New-AzVirtualNetworkSubnetConfig -Name $snetName2 -AddressPrefix $SnetPrefixes2
$vnet = New-AzvirtualNetwork -Name $vnetName -ResourceGroupName $rgname -Location $location `
  -AddressPrefix $VnetPrefixes -Subnet @($sub1, $sub2)

# 仮想マシンの作成
New-AzVm `
    -ResourceGroupName $rgname `
    -Name $vmName `
    -Location $location `
    -VirtualNetworkName $vnetName `
    -SubnetName $snetName2 `
    -SecurityGroupName $nsg `
    -PublicIpAddressName $vmPip `
    -OpenPorts 80,3389 `
    -Image 'Win2019Datacenter' `
    -Size 'Standard_B2s'

# ==============================================================================

```

上記で「Application Gateway」、「WAFポリシー」以外のAzureサービスの構築完了になります。仮想マシン作成の時に「ログインアカウント」、「パスワード」の作成が求められます。

下記はリモートデスクトップ経由で仮想マシンにログイン後、IISを仮想マシン上のPowerShellでインストールします。インストール後、クライアント端末のWEBブラウザで仮想マシンのパブリックIPアドレスを入力し既定のIIS Webサイトが表示されることを確認しましょう。

```powershell:PowerShell (Cloud)
# 仮想マシンのIPアドレス確認
Get-AzPublicIpAddress -ResourceGroupName $rgname | Select-Object -Property  'IpAddress'
```

```powershell:PowerShell (仮想マシン)
# 仮想マシン上のPowerShellでIISをインストール
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
```

### 2-2 「WAFポリシー」の作成
「WAFポリシー」を作成します。ポリシーモードは防止、状態は有効で作成します。

```powershell:PowerShell
# WAFポリシーのポリシーモードを'防止'、状態を'有効'で設定
$policySetting = New-AzApplicationGatewayFirewallPolicySetting -Mode Prevention -State Enabled

# WAFポリシーの作成
$wafPolicy = New-AzApplicationGatewayFirewallPolicy -Name $wafPolicy `
  -ResourceGroup $rgname -Location $location -PolicySetting $PolicySetting
```

### 2-3 「Application Gateway」の作成および「WAFポリシー」の紐づけ
「Application Gateway」を作成します。2-2で作成した「WAFポリシー」の紐づけも同時に実施します。

```powershell:PowerShell
# アプリケーションゲートウェイ用のパブリックIPアドレス作成 ==========================
$publicip = New-AzPublicIpAddress -ResourceGroupName $rgname -name $appgwPip `
  -location $location -AllocationMethod Static -Sku Standard
# ==============================================================================

# 「フロントエンドIP構成」、「フロントエンドポート」、「バックエンドプール」の作成 ====
# 「フロントエンドIP構成」
$gwSubnet = Get-AzVirtualNetworkSubnetConfig -Name $snetName1 -VirtualNetwork $vnet
$gipconfig = New-AzApplicationGatewayIPConfiguration -Name "AppGwIpConfig" -Subnet $gwSubnet
$fipconfig01 = New-AzApplicationGatewayFrontendIPConfig -Name "fipconfig" -PublicIPAddress $publicip

# 仮想マシンのプライベートアドレスを取得
$NICs = Get-AzNetworkInterface
$PrivateIpAddresses = $NICs | foreach { $_.IpConfigurations.PrivateIpAddress }

# 「バックエンドプール」の作成
$pool = New-AzApplicationGatewayBackendAddressPool -Name "pool1" `
  -BackendIPAddresses $PrivateIpAddresses

# 「フロントエンドポート」の作成
$fp01 = New-AzApplicationGatewayFrontendPort -Name "port1" -Port 80
# ==============================================================================

# 「リスナー」、「HTTP設定」、「ルール（規則）」、「自動スケーリング」の作成 =========
# 「リスナー」の作成
$listener01 = New-AzApplicationGatewayHttpListener -Name "listener1" -Protocol Http `
  -FrontendIPConfiguration $fipconfig01 -FrontendPort $fp01

# 「HTTP設定」の作成
$poolSetting01 = New-AzApplicationGatewayBackendHttpSettings -Name "setting1" -Port 80 `
  -Protocol Http -CookieBasedAffinity Disabled

# 「ルール」の作成
$rule01 = New-AzApplicationGatewayRequestRoutingRule -Name "rule1" -RuleType basic `
  -Priority 10 -BackendHttpSettings $poolSetting01 -HttpListener $listener01 -BackendAddressPool $pool

# 「自動スケーリング」の作成
$autoscaleConfig = New-AzApplicationGatewayAutoscaleConfiguration -MinCapacity 2

$sku = New-AzApplicationGatewaySku -Name WAF_v2 -Tier WAF_v2
# ==============================================================================

# アプリケーションゲートウェイの作成 ==============================================
$appgw = New-AzApplicationGateway -Name $appgwName -ResourceGroupName $rgname `
  -Location $location -BackendAddressPools $pool `
  -BackendHttpSettingsCollection  $poolSetting01 `
  -GatewayIpConfigurations $gipconfig -FrontendIpConfigurations $fipconfig01 `
  -FrontendPorts $fp01 -HttpListeners $listener01 `
  -RequestRoutingRules $rule01 -Sku $sku -AutoscaleConfiguration $autoscaleConfig `
  -FirewallPolicy $wafPolicy
# ==============================================================================
```
上記で「Application Gateway」の作成および「WAFポリシー」の紐づけが完成です。
備忘録として今回「Application Gateway」のSKUを「WAF_v2」で作成しています。「WAF_v2」、「Standard_v2」で作成する場合は「ルール」作成時の「-Priority」が必須になります。
以下コマンドで「Application Gateway」のパブリックIPアドレスを取得し、クライアント端末のWEBブラウザにアプリケーションゲートウェイのIPアドレスを入力します。
IISが表示されることを確認しましょう。

```powershell:PowerShell 
# アプリケーションゲートウェイのIPアドレス確認
Get-AzPublicIpAddress -ResourceGroupName $rgname -Name $appgwPip | Select-Object -Property  'IpAddress'
```

![WS000021.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/a96dc2ed-5019-bf8e-58c3-98a8270237ac.jpeg)

以下に「Application Gateway」と「WAFポリシー」のスクショを載せます。枚数が多いので小さく載せます。
お手数をおかけしますが、確認したい場合は画像のクリックを適宜お願いいたします。

1.「Application Gateway」の概要
<img width="300" alt="1_概要.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7a4e88e5-ebf7-eb3c-1f79-dcdc2e546e3d.png">

2.「Application Gateway」の構成
<img width="300" alt="2_構成.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7a56802f-0749-74fd-04a1-a9cba93aa78c.png">

3.「Application Gateway」のWeb アプリケーション ファイアウォール
<img width="300" alt="3_Webアプリケーションファイアウォール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/260b2bec-460b-7ec0-26ea-f563b8524957.png">

4.「Application Gateway」のバックエンドプール
<img width="300" alt="4_バックエンドプール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/6848e046-b2ea-6413-ee7d-1dadcecfc0ae.png">

5.「Application Gateway」のバックエンドプールの編集
<img width="300" alt="5_バックエンドプールの編集.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/a076986d-08a9-cfa2-468b-d73df0ebcebc.png">

6.「Application Gateway」のバックエンド設定
<img width="300" alt="6_バックエンド設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/9adf6c9f-fea3-375b-fb93-0ba74ea99f27.png">

7.「Application Gateway」のフロントエンドIP構成
<img width="300" alt="フロントエンドIP構成.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/027c207a-5b41-9cbb-5ae0-2f9deab1f682.png">

8.「Application Gateway」のフロントエンドIP構成_詳細
<img width="300" alt="8_fipconfig.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/650bd4b4-f82e-0d6d-5a14-b4e30f57ff55.png">

9.「Application Gateway」のリスナー
<img width="300" alt="9_リスナー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/b6b41f21-010e-c9bb-ed6f-5720214f993e.png">

10.「Application Gateway」のリスナー_詳細
<img width="300" alt="10_listener1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/be86bc6f-0013-c646-e53a-d798e5dd72f9.png">

11.「Application Gateway」のルール
<img width="300" alt="11_ルール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/1479990c-b352-38b6-7f56-39b3cf0c4428.png">

12.「Application Gateway」のルール_バックエンドプール
<img width="300" alt="12_ルール_backend.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/99c1d1ae-cc17-4c34-fe4f-8bd081de3553.png">

13.「Application Gateway」のルール_リスナー
<img width="300" alt="12_ルール_listener.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/c5dcd047-af4f-f218-8189-23e89be890f5.png">

14.「WAFポリシー」の概要
<img width="300" alt="13_WAF_概要.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7eb91dc8-925e-b8b5-6379-d74eaabc458d.png">

15.「WAFポリシー」のポリシー設定
<img width="300" alt="14_WAF_ポリシー設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/11be5321-b88c-255b-aaf6-2d8c7ea49737.png">

16.「WAFポリシー」の管理されているルール
<img width="300" alt="15_WAF_管理されているルール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/2d9bff7c-a347-c4c0-4d3c-199c158b4f29.png">

17.「WAFポリシー」のカスタムルール
<img width="300" alt="16_WAF_カスタムルール.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/dfa45323-acda-2f1c-c656-59a4f93b0157.png">

17.「WAFポリシー」の関連付けられたアプリケーションゲートウェイ
<img width="300" alt="17_WAF_関連付けられたアプリケーションゲートウェイ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/d895bbb9-8559-6a10-ab1a-f015c04609b1.png">

### 2-4 「WAFポリシー」のカスタムルール更新
最後に「WAFポリシー」のカスタムルールにてIPアドレスの制限を実施します。

```powershell:PowerShell
# 一致変数を'RemoteAddr'に設定
$variable = New-AzApplicationGatewayFirewallMatchVariable -VariableName RemoteAddr

# 一致の種類をIPアドレスに指定。IPアドレスにクライアントIPアドレスを指定。
$condition = New-AzApplicationGatewayFirewallCondition -MatchVariable $variable `
  -Operator IPMatch -MatchValue 'XXX.XXX.XXX.XXX' # ここに制限するIPアドレスを記載する。

# カスタムルールの作成。優先度を10、トラフィックを拒否するに指定。
$rule = New-AzApplicationGatewayFirewallCustomRule -Name $wafPolicyCustomRules `
  -Priority 10 -RuleType MatchRule -MatchCondition $condition -Action Block

# WAFポリシーの更新
Set-AzApplicationGatewayFirewallPolicy  -Name $wafPolicy -ResourceGroup $rgname -CustomRule $rule
```
クライアント端末のWEBブラウザにアプリケーションゲートウェイのIPアドレスを入力します。
IISが表示されないことを確認しましょう。

![WS000023.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/663cb0e6-5689-f703-e8bd-0bcd9a55b51e.jpeg)

以下が「WAFポリシー」のカスタムルール更新後の画像になります。
※赤枠は拒否するIPアドレスになります。

![18_カスタムルール更新.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/2f0444a6-9f1f-a989-1a42-444b8d04c6b1.png)

# 3. おわりに
本記事を最後まで読んで頂きましてありがとうございます。
普段はAzureCLIで記載することが多いのですが、今回はPowerShellで構築してみました。
GUI、CUI、IaC等いろんな構築方法がありますが、縛らずに楽しめたらと思います。

# 4. 参考記事
-  [Azure PowerShell を使用してカスタム ルールによって Application Gateway 上に Web アプリケーション ファイアウォール v2 を構成する](https://docs.microsoft.com/ja-jp/azure/web-application-firewall/ag/configure-waf-custom-rules)

-  [クイック スタート:PowerShell を使用して Azure に Windows 仮想マシンを作成する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/quick-create-powershell)

-  [WAF ポリシーを既存の Application Gateway に関連付ける](https://docs.microsoft.com/ja-jp/azure/web-application-firewall/ag/associate-waf-policy-existing-gateway)

-  [Azure PowerShell を使用して Web アプリケーション ファイアウォール (WAF) のカスタム規則を作成する](https://docs.microsoft.com/ja-jp/azure/application-gateway/scripts/waf-custom-rules-powershell)

-  [New-AzVM](https://docs.microsoft.com/en-us/powershell/module/az.compute/new-azvm?view=azps-8.0.0)

-  [New-AzApplicationGateway](https://docs.microsoft.com/en-us/powershell/module/az.network/new-azapplicationgateway?view=azps-8.0.0)

-  [New-AzApplicationGatewayRequestRoutingRule](https://docs.microsoft.com/en-us/powershell/module/az.network/new-azapplicationgatewayrequestroutingrule?view=azps-8.0.0)

-  [New- AzApplicationGatewayファイアウォールの一致変数](https://docs.microsoft.com/ja-JP/powershell/module/az.network/New-AzApplicationGatewayFirewallMatchVariable?view=azps-8.0.0)

-  [New- AzApplicationGatewayファイアウォールの状態](https://docs.microsoft.com/en-us/powershell/module/az.network/new-azapplicationgatewayfirewallcondition?view=azps-8.0.0)