APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Azure Container AppsにWAFを組み合わせてみよう

はじめに

こんにちは、ACS事業部の吉川です。
コンテナ化されたアプリを簡単に扱うことができるAzure Container Appsですが、Web Application Firewall(WAF)と組み合わせるためにどのような構成を取ればよいかを検討をしてみました。

AzureのWAFサービス

以下のページで紹介されているように、AzureでもWAFサービスが提供されています。

azure.microsoft.com

このWAFは単体で提供されるものではなく、以下のサービスに含まれる1つの機能として提供されます。

  • Application Gateway
  • Azure Front Door

それぞれのサービスをAzure Container Appsと組み合わせる際に、どういった構成となるか検討してみましょう。

1. Application Gateway案

Application Gatewayとの組み合わせを考えると、以下のような構成となりました。

以下、ポイントを解説していきます。

Container Apps環境は内部向けとして作成する

ユーザーからのアクセス経路にWAFを設置したいので、WAFをバイパスしてアクセスされては困ってしまいます。
WAF機能を持つApplication GatewayはVNet内に配置されるリソースなので、Azure Container Appsも VNet内のみにサービス公開 されるようにしておきましょう。

# リソース名/リージョンの定義
RG_NAME=rg-sample
LOCATION=japaneast
VNET_NAME=vnet-sample
ACA_SUBNET_NAME=subnet-aca
AGW_SUBNET_NAME=subnet-agw
CAE_NAME=cae-sample
ACA_NAME=aca-sample

# VNet/サブネットの作成
az network vnet create -n $VNET_NAME -g $RG_NAME -l $LOCATION \
  --address-prefixes 192.168.0.0/16
az network vnet subnet create -n $ACA_SUBNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME \
  --address-prefixes 192.168.0.0/23
az network vnet subnet create -n $AGW_SUBNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME \
  --address-prefixes 192.168.2.0/24

# Container Apps環境を内部向けに作成
ACA_SUBNET_ID=$(az network vnet subnet show -n $ACA_SUBNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME --query id -o tsv)
az containerapp env create -n $CAE_NAME -g $RG_NAME -l $LOCATION \
  -s $ACA_SUBNET_ID --internal-only 

# Container Appsを作成
# ここではDocker Hubで公開されているNGINXのコンテナイメージを使用する
az containerapp create -n $ACA_NAME -g $RG_NAME \
  --image nginx:latest --environment $CAE_NAME \
  --ingress external --target-port 80 

Private DNS Zoneを作成する

下記のドキュメントにも記載があるように、内部向けにContainer Apps環境を作成した場合、Private DNS Zoneの作成が必要です。

learn.microsoft.com

ゾーン名は <ランダムに付与される識別子>.<リージョン名>.azurecontainerapps.io です。(カスタムドメインを使っていない場合)
Container AppsのURLの下図赤線部分のことですね。

以下のようにして作成します。

# ゾーン名の取得
ZONE_NAME=$(az containerapp env show -n $CAE_NAME -g $RG_NAME \
  --query properties.defaultDomain -o tsv)

# Private DNS Zoneの作成
az network private-dns zone create -n $ZONE_NAME -g $RG_NAME

# VNetにPrivate DNS Zoneをリンクする
az network private-dns link vnet create -n $VNET_NAME -g $RG_NAME \
  --registration-enabled false \
  --virtual-network $VNET_NAME --zone-name $ZONE_NAME

作成したDNS Zone内に以下のレコードを追加します。

名前 種類 IPアドレス
* A Container Apps環境の静的IPアドレス

Container Apps環境の静的IPアドレスは以下の箇所に表示されてるものです。

# 静的IPアドレスの取得
STATIC_IP=$(az containerapp env show -n $CAE_NAME -g $RG_NAME \
  --query properties.staticIp -o tsv)

# レコードの追加
az network private-dns record-set a add-record \
  --record-set-name '*' --ipv4-address $STATIC_IP \
  -g $RG_NAME --zone-name $ZONE_NAME

Application GatewayのバックエンドにFQDNでContainer Appsを登録する

Container Appsにアクセスする際は、必ずFQDNを使う必要があります。
今回のようにApplication Gatewayを前段に置く場合は以下のようなイメージです。

まずは以下のようにApplication Gatewayを作成します。

# リソース名の定義
PIP_NAME=pip-agw
WAF_POLICY_NAME=waf-sample
AGW_NAME=agw-sample

# Container AppsのFQDNを取得
APP_FQDN=$(az containerapp show -n $ACA_NAME -g $RG_NAME \
  --query properties.configuration.ingress.fqdn -o tsv)

# Application GatewayのパブリックIPを作成
az network public-ip create \
  -n $PIP_NAME -g $RG_NAME \
  --allocation-method Static \
  --sku Standard

# WAFポリシーの作成
az network application-gateway waf-policy create \
  -n $WAF_POLICY_NAME -g $RG_NAME

# Application Gatewayの作成
# バックエンドにContainer AppsのFQDNを指定する
az network application-gateway create \
  -n $AGW_NAME -g $RG_NAME \
  --location $LOCATION \
  --sku WAF_v2 \
  --waf-policy $WAF_POLICY_NAME \
  --public-ip-address $PIP_NAME \
  --vnet-name $VNET_NAME \
  --subnet $AGW_SUBNET_NAME \
  --servers $APP_FQDN \
  --priority 100

できあがったApplication Gatewayのバックエンド設定を以下のように変更します。

  • バックエンド プロトコル: HTTPS
  • 既知の CA 証明書を使用する: はい
  • 新しいホスト名でオーバーライドする: はい
  • ホスト名をオーバーライドする: バックエンド ターゲットからホスト名を選択する

上記の設定を保存しApplication GatewayのIPアドレスにアクセスすると、Container Appsで起動したNGINXにアクセスできます。

2. Front Door案

つづいてFront Doorを利用する案です。

Container AppsとFront Doorの組み合わせについては先日Tech Communityブログにて紹介されており、こちらの内容をベースにしています。

techcommunity.microsoft.com

以下、ポイントを解説していきます。

Container Apps環境を既存のVNet内に作成した場合、「MC_~」で始まる名前のリソースグループが同時に作成され、Container Appsが利用するロードバランサーやNSGが配置されます。AKSユーザーには馴染みある構成ですね。

Front Doorからの接続を受け付けるためにPrivate Link Serviceを作成します。
まずはPrivate Endpoint用のサブネットを作成しましょう。

# リソース名の定義
PE_SUBNET_NAME=subnet-pe

# サブネットの作成
az network vnet subnet create -n $PE_SUBNET_NAME \
  --vnet-name $VNET_NAME -g $RG_NAME \
  --address-prefixes 192.168.3.0/28

サブネットができたらPrivate Link Serviceを作成します。
Private Link Service作成時の送信設定で、ロードバランサーの項目に「MC_~」リソースグループ内の kubernetes-internal を指定します。
また、ソースNATサブネットには先に作成したPrivate Endpoint用サブネットを指定します。

ここで作成したPrivate Link Serviceを、Front Doorの配信元として設定していきます。

Front Door作成時に以下の項目を設定します。配信元にPrivate Link Serviceを指定する場合、Premiumレベルが必須となるので注意が必要です。

  • レベル: Premium
  • 配信元の種類: カスタム
  • 配信元のホスト名: Container AppsのFQDN
  • プライベートリンクサービス: 有効にする
  • プライベートリンクを選択する: 前項で作成したPrivate Link Serviceを選択

ポータルの画面だと以下のようになります。
要求メッセージ欄は好きな文字列を入れればよいです。ここでは frontdoor としました。

Private Endpointの承認を忘れずに

Front Doorを作成した直後の状態では、Private Endpointが保留中のステータスとなっており通信が確立されていません。忘れずに承認をしましょう。
Private Link Serviceの設定から承認できます。

説明欄にはFront Door作成時に指定した要求メッセージが表示されます。複数のPrivate Endpoint接続を作成する場合は区別の付く文字列にするとよいでしょう。

正常性プローブの設定をHTTPSに変更

Container AppsのIngressはデフォルト設定ではHTTPSのみに対応しています。
Front Doorのヘルスチェック設定で、HTTPSを参照するように変更しておきましょう。

設定完了後Front Doorのエンドポイントにアクセスすると、Container Apps上のNGINXにアクセスできます。

おわりに

Azure Container AppsでWAFを使いたい場合どうすればよいか、構成を検討してみました。
WAFも含めてAzureで環境を統一させようとすると上記2案のどちらかになると思います。
どちらの案を取るにしても、ヘルスチェックプローブが定期的に発信されるため、Container Appsのゼロスケールができないことには注意が必要ですね。

私達ACS事業部はAzure・ACAなどのクラウドネイティブ技術を活用した内製化のご支援をしております。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!

www.ap-com.co.jp

本記事の投稿者: 吉川 俊甫
AKS/ACAをメインにインフラ系のご支援を担当しています。 Shunsuke Yoshikawa - Credly