見出し画像

API Management を安全にバックアップする

はじめに

API Management は、REST API やコマンドによってストレージ アカウントにバックアップすることができます。
ただし、ストレージ アカウントのファイアウォール機能を有効にした状態で、API Management のバックアップを取得には一工夫が必要になります。
この記事では、実際に試しながら、どうすれば API Management を安全にバックアップできるかを紹介します。

使用するツール類

  • Azure ポータル

  • Azure Cloud Shell

検証

API Management 、ストレージ アカウントの準備

検証のため、API Management とストレージ アカウントを、東日本リージョンに作成しました。

  • API Management

API Management > 概要
API Management > 概要
  • ストレージ アカウント

ストレージ アカウント (jpe) > 概要
ストレージ アカウント (jpe) > 概要

ストレージ アカウントに、API Management のバックアップ先となるコンテナーを作成します。

  • ストレージ アカウント > コンテナー

ストレージ アカウント (jpe) > コンテナー
ストレージ アカウント (jpe) > コンテナー

ストレージ アカウントの「ネットワーク」は、まずは「許可するアクセス元 : すべてのネットワーク」にしておきます。

  • ストレージ アカウント > ネットワーク

ストレージ アカウント (jpe) > ネットワーク (すべてのネットワーク)
ストレージ アカウント (jpe) > ネットワーク (すべてのネットワーク)

検証で使用するので、ストレージ アカウントの診断ログも設定しておきます。

  • ストレージ アカウント > 診断設定 (クラシック)

ストレージ アカウント (jpe) > 診断設定 (クラシック)
ストレージ アカウント (jpe) > 診断設定 (クラシック)

API Management のバックアップ (1)
(ストレージ アカウントのファイウォール:なし)

まずは、「ストレージ アカウントのファイウォール:なし」の状態で、API Management のバックアップを実行してみます。
下記のコマンドを Azure Cloud Shell で実行し、バックアップします。

$rgpName = "tst-mm-rgp"
$saName = "tstmmapimbackupjpe"
$apimName = "tst-mm-apim"
$containerName = "apim-backup"
$blobName = "backup-01.zip"

$saKey = (Get-AzStorageAccountKey -ResourceGroupName "${rgpName}" -StorageAccountName "${saName}")[0].Value
$saCtx = New-AzStorageContext -StorageAccountName "${saName}" -StorageAccountKey "${saKey}"
Backup-AzApiManagement -ResourceGroupName "${rgpName}" -Name "${apimName}" -StorageContext $saCtx -TargetContainerName "${containerName}" -TargetBlobName "${blobName}"

しばらくすると、バックアップ ファイルが格納されます。

バックアップ (1 回目) の実行結果
バックアップ (1 回目) の実行結果

問題なくバックアップできているので、コマンドに間違いはなさそうです。

API Management のバックアップ (2)
(ストレージ アカウントのファイウォール:あり)

次は、「ストレージ アカウントのファイウォール:あり」の状態で、API Management のバックアップを実行してみます。
ストレージ アカウントの「ネットワーク」で「許可するアクセス元 : 選択されたネットワーク」にします。
これだけだと、どこからもアクセスできません。
API Management からは (バックアップ ファイルを作成するため) アクセスできるようにする必要があります。
そこで、ファイアウォールに API Management のパブリック IP アドレスを設定します。

ストレージ アカウント (jpe) > ネットワーク (選択されたネットワーク)
ストレージ アカウント (jpe) > ネットワーク (選択されたネットワーク)

設定内容を保存して、(適用されるまで少し時間がかかるので) 5 分くらい待ってから、API Management のバックアップを実行してみます。

$rgpName = "tst-mm-rgp"
$saName = "tstmmapimbackupjpe"
$apimName = "tst-mm-apim"
$containerName = "apim-backup"
$blobName = "backup-02.zip"

$saKey = (Get-AzStorageAccountKey -ResourceGroupName "${rgpName}" -StorageAccountName "${saName}")[0].Value
$saCtx = New-AzStorageContext -StorageAccountName "${saName}" -StorageAccountKey "${saKey}"
Backup-AzApiManagement -ResourceGroupName "${rgpName}" -Name "${apimName}" -StorageContext $saCtx -TargetContainerName "${containerName}" -TargetBlobName "${blobName}"

Backup-AzApiManagement: Operation returned an invalid status code 'BadRequest'

バックアップ ファイル名を変更しただけですが、エラーが発生し、バックアップに失敗しました。
成功したバックアップと失敗したバックアップで異なる点は、ストレージ アカウントのファイアウォールのみです。

何がダメだったのか、ストレージ アカウントの診断ログを確認してみます。
ストレージ アカウントの診断ログ (クラシック) は、 $log というコンテナーに出力されます。
(診断ログを取得するため、「ストレージ アカウントのファイウォール:なし」に戻しています。)

ストレージ アカウント (jpe) > 診断ログ
ストレージ アカウント (jpe) > 診断ログ

成功したバックアップ、失敗したバックアップの両方について、診断ログを確認してみます。

【成功したバックアップ (先頭 1 行のみ)】
2.0;2022-01-15T09:10:53.4067789Z;CreateContainer;ContainerAlreadyExists;409;5;4;authenticated;tstmmapimbackupjpe;tstmmapimbackupjpe;blob;"https://tstmmapimbackupjpe.blob.core.windows.net/apim-backup?restype=container";"/tstmmapimbackupjpe/apim-backup";b01873a3-301e-0062-7aef-09d41b000000;0;10.0.0.14:54341;2018-03-28;446;0;182;230;0;;;;;;"Azure-Storage/9.3.2 (.NET CLR 4.0.30319.42000; Win32NT 6.2.9200.0)";;"b7363edc-423f-4c0b-b810-3b28801228c6";;;;;;;;

【失敗したバックアップ】
2.0;2022-01-15T09:32:56.5967955Z;CreateContainer;IpAuthorizationError;403;1;1;authenticated;tstmmapimbackupjpe;tstmmapimbackupjpe;blob;"https://tstmmapimbackupjpe.blob.core.windows.net/apim-backup?restype=container";"/";47ef1086-201e-00a5-60f2-094046000000;0;10.0.0.12:53732;2018-03-28;426;0;130;246;0;;;;;;"Azure-Storage/9.3.2 (.NET CLR 4.0.30319.42000; Win32NT 6.2.9200.0)";;"54164299-3523-4b40-bc3b-6a1579d957f7";;;;;;;;

ストレージ アカウントの診断ログのフォーマットは、下記ページに記載があります。

Backup-AzApiManagement コマンドは、まずコンテナーを作成する処理が実行されるようです。
成功したバックアップの <request-status> は ContainerAlreadyExists となっています。(あらかじめコンテナーを作成していたため)。
それに対して、失敗したバックアップの <request-status> は IpAuthorizationError となっています。
これは、ストレージ アカウントのファイアウォールによってアクセス拒否されたと推測できます。

しかし、API Management のパブリック IP アドレスを設定したはずです。
そこで、失敗したバックアップの診断ログの <requester-ip-address> を確認します。
そうすると、 10.0.0.12 という IP アドレスにが記録されています。
これは、API Management のパブリック IP ではありません。

公式情報が見つけられませんでしたが、あるリソースから同一リージョンのストレージ アカウントにアクセスするとき、Azure 内部で使用されているプライベート IP アドレスでアクセスするような挙動になるようです。

ストレージ アカウントのファイアウォールには、パブリック IP アドレスしか登録できないため、このままでは API Management からのアクセスのみ許可するといったことができません…

API Management のバックアップ (3)
(西日本リージョン、ストレージ アカウントのファイウォール:あり)

上述のとおり、同一リージョンのストレージ アカウントのファイアウォールは使用できません。
この問題は、異なるリージョンにストレージ アカウントを作成すれば、解決できます。 ただし、ここでも注意しなければいけない点があるので、実際に試してみます。

まずは、API Management とは異なるリージョン (西日本リージョン) に、ストレージ アカウントを作成します。

ストレージ アカウント (jpw) &gt; 概要
ストレージ アカウント (jpw) > 概要

西日本リージョンに作成したストレージ アカウントの「ネットワーク」も「許可するアクセス元 : 選択されたネットワーク」にします。
ファイアウォールにパブリック IP アドレスを登録しますが、ここで登録するのは API Management のパブリック IP アドレスではありません。
52.140.238.179 という IP アドレスを登録します。

ストレージ アカウント (jpw) &gt; ネットワーク (選択されたネットワーク)
ストレージ アカウント (jpw) > ネットワーク (選択されたネットワーク)

この 52.140.238.179 という IP アドレスの正体は、”Azure API Management のコントロール プレーン IP アドレス” です。

API Management が異なるリージョンにアクセスするとき、API Management に割り当てられているパブリック IP アドレスではなく、 "コントロール プレーンの IP アドレスからのアクセス" となります。
コントロール プレーンはリージョンごとに存在し、東日本リージョンの場合は上述の 52.140.238.179 となります。

設定が終わったので、西日本リージョンのストレージ アカウントを指定して、バックアップを実行します。

$rgpName = "tst-mm-rgp"
$saName = "tstmmapimbackupjpw"
$apimName = "tst-mm-apim"
$containerName = "apim-backup"
$blobName = "backup-03.zip"

$saKey = (Get-AzStorageAccountKey -ResourceGroupName "${rgpName}" -StorageAccountName "${saName}")[0].Value
$saCtx = New-AzStorageContext -StorageAccountName "${saName}" -StorageAccountKey "${saKey}"
Backup-AzApiManagement -ResourceGroupName "${rgpName}" -Name "${apimName}" -StorageContext $saCtx -TargetContainerName "${containerName}" -TargetBlobName "${blobName}"

しばらくすると、バックアップ ファイルが格納されます。

バックアップ (3 回目) の実行結果
バックアップ (3 回目) の実行結果

これで、東日本リージョンの API Management からのみアクセスできる状態でのバックアップ取得を実現することができました。
元々は (ネットワーク経路としては) どこからでもアクセス可能な状態だったので、かなり安全になったと思います。
とはいえ、東日本リージョンの API Management という条件さえ満たせばアクセスできてしまうので、さらに安全性を高めるなら、バックアップ取得時のみコントロール プレーンの IP アドレスをファイアウォールに登録し、バックアップが完了したらファイアウォールから IP アドレスを削除するなどの対応が必要です。

まとめ

  • API Management から同一リージョンのストレージ アカウント対しては、プライベート IP アドレスでアクセスされる。

  • API Management から異なるリージョンのストレージ アカウントに対しては、コントロール プレーンの IP アドレスからアクセスされる。

おわりに

ストレージ アカウントにアクセスするときの IP アドレスについて、特に PaaS からのアクセスの場合はわかりにくいと思います。
この記事の内容は、意外な結果 (?) だったのではないでしょうか。
IP アドレスによるアクセス制御を行うときは、公式ドキュメントを確認したり、実際に試すなどして、アクセス元の IP アドレスをしっかり確認しましょう。

この記事が気に入ったらサポートをしてみませんか?