WebApp on Linux から Azure Database for MySQL(PostgreSQL) へのIP制限を許可する方法

## 概要
Azure SQL Database では「Azure サービスへのアクセスを許可」でファイヤーウォールを許可することができますが、現時点の Azure Database for MySQL にはありません。
Webサービスを PaaS で完結させるためには WebApp on Linux と組み合わせて使いたいところです。

ここでは WebApp on Linux からのアクセスを許可する方法について書きます。

## 方法
### お手軽編
WebApp の「プロパティ」で確認できる「送信 IP アドレス」を MySQL(PostgreSQL) の「接続のセキュリティ」「ファイヤーウォール規則」に登録します。

### 本気編
以下の PowerShell スクリプトを AzureAutomation あたりで定期実行します。
パラメータは環境に合うように変更してください。

```ps1
$connectionName = "AzureRunAsConnection"
try
{
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         

    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
}
catch {
    if (!$servicePrincipalConnection)
    {
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

# パラメータ設定
$resource_group_name = "{RESOURCE_GROUP_NAME}"
$webapp_name = "{WEBAPP_NAME}"
$mysqlName = "{MYSQL_NAME}"
$location = "{MYSQL_LOCATION}"

$serverfarm = Get-AzureRmResource -ResourceType "Microsoft.Web/serverfarms/sites" -Name $webapp_name -ApiVersion 2016-03-01 -ResourceGroupName $resource_group_name
$outboundIpAddresses = [String] $serverfarm.Properties.outboundIpAddresses
$outboundIpAddresses = $outboundIpAddresses.Trim()
$ips = $outboundIpAddresses.Split(",")

$rules = Get-AzureRmResource -ResourceType "Microsoft.DBforMySQL/servers/firewallRules" -Name $mysqlName -ApiVersion 2017-04-30-preview -ResourceGroupName $resource_group_name
$new_rules = @()
$added_rules = @()
foreach($rule in $rules) {
    if (!([String] $rule.Name).Contains('WebApp')) {
        $new_rules += $rule
    }
}
$changed = $False
for ($i = 0; $i -lt $ips.Count; $i++) {
    $exists = $False
    $new_ip = [String] $ips[$i]
    $new_ip = $new_ip.Trim()
    $rule_name = ([String]::Format("WebApp{0}", $i))
    foreach($rule in $rules) {
        if ($rule.Name -eq $rule_name -and
            $rule.Properties.startIpAddress -eq $new_ip -and
            $rule.Properties.endIpAddress -eq $new_ip) {
            $exists = $True
            break
        }
    }
    if ($exists) {
        $new_rules += $rule
    } else {
        $changed = $True
        $added_rules += @{
            Name = $rule_name
            Properties = @{
                startIpAddress = $new_ip
                endIpAddress = $new_ip
            }
        }
    }
}
if ($changed) {
    Write-Host "changed"
    foreach($rule in $new_rules) {
        Write-Host $rule.Name $rule.Properties.startIpAddress
    }
    $new_rules | Set-AzureRmResource -ApiVersion 2017-04-30-preview -Force
    foreach($rule in $added_rules) {
        Write-Host "added" $rule.Name $rule.Properties.startIpAddress
        New-AzureRmResource -ApiVersion 2017-04-30-preview -ResourceGroupName $resource_group_name -Location $location -ResourceType "Microsoft.DBforMySQL/servers/firewallRules" -ResourceName ($mysqlName + "/" + $rule.Name) -Properties $rule.Properties -Force
    }
}
```

## 解説
[WebApp ではアウトバウンド IP アドレスが固定されています](https://blogs.msdn.microsoft.com/jpcie/?p=325)が、Linux 版もおそらく同じで、「プロパティ」から確認できる IP アドレスを登録しておけばほぼ問題ないでしょう。
しかし大きなメンテナンスによって変わることがあるようなので、それに耐えられるようにしておきたいところです。
上記の PowerShell をなんらかの方法で定期実行すればよいでしょう。