[Azure][ExpressRoute] Microsoft Peering の BGP コミュニティ値一覧を CSV に出力する

## この記事はなにか？

Azure ExpressRoute の話です。Microsoft Peering のルート フィルターで BGP コミュニティを許可すると、Azure 側から経路が広報されるのですが、その経路リストを CSV で取得する PowerShell スクリプトを紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127839/285800b4-3ad1-0277-7b10-ed0d38ece42d.png)

つまり `Get-AzBgpServiceCommunity` の結果をいい感じに整形する方法を紹介します。

## スクリプト

```powershell
$BgpServices = Get-AzBgpServiceCommunity | foreach {
    $Service = $_
    $Service.BgpCommunities.CommunityPrefixes | foreach {
        [PSCustomObject]@{
            Name = $Service.Name
            Id = $Service.Id
            Type = $Service.Type
            ServiceSupportedRegion = $Service.BgpCommunities.ServiceSupportedRegion
            CommunityName = $Service.BgpCommunities.CommunityName
            CommunityValue = $Service.BgpCommunities.CommunityValue
            CommunityPrefix = $_
            IsAuthorizedToUse = $Service.BgpCommunities.IsAuthorizedToUse
            ServiceGroup = $Service.BgpCommunities.ServiceGroup
        }
    }
}

function Write-PSObjectAsCSV($PSObject, $Path) {
    $Content = $PSObject | ConvertTo-CSV -NoTypeInformation
    $UTF8woBom = New-Object "System.Text.UTF8Encoding" -ArgumentList @($false)
    [System.IO.File]::WriteAllLines($Path, $Content, $UTF8woBom)
}

# カレント ディレクトリに CSV を出力
$Path = $(Join-Path $PWD "bgp-service-community.csv")
Write-PSObjectAsCSV $BgpServices $Path

# 既定のソフトウェアで CSV を開く
Start-Process $Path
```

## [応用] 特定の IP アドレスが含まれるサービスを調べる

CIDR で表された IPv4 ネットワーク アドレス範囲 (e.g. 10.0.0.0/24) に、特定の IP アドレスが含まれるかを調べるには python の `ipaddress` パッケージ等が使えます。
なので、次のような python スクリプトで、指定した IP アドレスが含まれる BGP サービスの行のみを抽出することが出来ます。

```python
#!/bin/env python3

import argparse
import pandas as pd
from ipaddress import IPv4Address, IPv4Network

parser = argparse.ArgumentParser()
parser.add_argument("csv_path", help="Path to the csv generated by Get-AzBgpServiceCommunity.")
parser.add_argument("address", help="IP address to check if there is an address prefix that contains this address.")
args = parser.parse_args()

data = pd.read_csv(args.csv_path)
indexes = [i for i, prefix in enumerate(data['CommunityPrefix'])
  if IPv4Address(args.address) in IPv4Network(prefix)
]

print(data.iloc[indexes, :].to_csv(index=False))
```

例えば、`40.78.243.192` が含まれるサービスを抽出するには、以下のコマンドを実行します。
ここで、`filter.py` は上の python スクリプトを、`bgp-service-community.csv` は PowerShell コマンドで取得した CSV を、それぞれ表しています。

```bash
$ python3 filter.py bgp-service-community.csv 40.78.243.192
Name,Id,Type,ServiceSupportedRegion,CommunityName,CommunityValue,CommunityPrefix,IsAuthorizedToUse,ServiceGroup
AzureWestUS2,/subscriptions//resourceGroups//providers/Microsoft.Network/bgpServiceCommunities/AzureWestUS2,Microsoft.Network/bgpServiceCommunities,Global,Azure West US 2,12076:51026,40.78.243.0/24,True,Azure
AzureCosmosDBWestUS2,/subscriptions//resourceGroups//providers/Microsoft.Network/bgpServiceCommunities/AzureCosmosDBWestUS2,Microsoft.Network/bgpServiceCommunities,Global,Azure Cosmos DB West US 2,12076:54026,40.78.243.192/26,True,AzureCosmosDB
```

結果を見てみると、AS 番号 51026 と 54026 で広報されているのがわかりますね。
2 つの BGP サービスが出力されるのは、AzureCosmosDBWestUS2 が AzureWestUS2 に包含されている (アドレス範囲的な意味で) ためです。