Microsoft Teams チャネル ボットと、ファイアウォールの背後にある Web アプリをセキュリティで保護するのに役立ちます

Azure App Service
Azure Web アプリケーション ファイアウォール

このシナリオ例は、Azure Private Link および Azure プライベート エンドポイントを使用して、Microsoft Teams チャネル ボットの Web アプリへの接続をセキュリティで保護するのに役立ちます。 同時に、Teams クライアントのチャネルで、Azure Firewall インスタンスを介して公開される IP を介してボットと通信できるようになります。

アーキテクチャ

Teams から Azure Firewall へのフローチャートを示す図。

このアーキテクチャの Visio ファイルをダウンロードします。

データフロー

  • Microsoft Azure Virtual Network では、Azure リソースとの間の通信が可能になります。 この例の仮想ネットワークでは、10.0.0.0/16 のアドレス空間を使用し、シナリオの必須コンポーネントで使用する 3 つのサブネットが含まれています。

    • "Azure Firewall サブネット" (10.0.1.0/26)。

    • "Microsoft Azure Virtual Network 統合サブネット" (10.0.2.0/24) は、ボットのプライベート エンドポイントからファイアウォールにトラフィックをルーティングするために使用されます。

    • "プライベート エンドポイント サブネット" (10.0.3.0/24) は、ファイアウォールからボットのプライベート エンドポイントにトラフィックをルーティングするために使用されます。

  • Azure Firewall によって、基になるボット サービスとの通信にクライアントが使用できる単一のパブリック IP アドレスが公開されます。 通常、ファイアウォールは独自の仮想ネットワークに配置されます。これは、ハブ アンド スポーク アーキテクチャの一般的なパターンですが、ここでの簡略化された例では、すべてのサービスとリソースを 1 つの VNet にデプロイします。 Azure Firewall のインスタンスは、独自のサブネットに配置されます。

  • ルーティング テーブル は、トラフィックが仮想ネットワーク内で受け取るルートを定義します。 これにより、ボットとの間を行き来するトラフィックがファイアウォールを通過することが保証されます。

    • アドレス プレフィックスが 0.0.0.0/0 の既定のルートは、Azure Firewall インスタンスがデプロイされているサブネットに、他のルートのアドレス プレフィックス内にはないトラフィックをルーティングするように Azure に指示します。 この例では、これが唯一のルートです。

    • "Virtual Network 統合サブネット" と "プライベート エンドポイント サブネット" がルーティング テーブルに関連付けられているので、それらを通過するトラフィックが、ファイアウォール経由でルーティングされることが保証されます。

  • Bot Service は、ボット App Service プランApp Serviceボット チャネル登録で構成されます。

    • この App Service には、ファイアウォールの IP アドレスをポイントする登録済みのカスタム ドメインが含まれています。 この方法では、App Service には、ファイアウォール経由でのみアクセスできます。
  • Azure Private Link は、Azure プライベート エンドポイント経由でのボット App Service への受信アクセスを提供します。

  • Virtual Network 統合では、App Service を仮想ネットワークに接続し、ボット App Service からの送信トラフィックが、ファイアウォールを通過することを保証します。

Components

代替

  • App Service Environment は、App Service アプリを高スケールで安全に実行するための完全に分離された専用環境を提供できます。 この例では、コスト削減のために App Service Environment を利用していませんが、サンプル アーキテクチャに変更を加えることでサポートできる可能性があります。

シナリオの詳細

ボットを使用すると、Teams ユーザーは、テキスト、対話型カード、タスク モジュールを使用して Web サービスと対話できます。 この Microsoft Bot Framework と Azure Bot Services を使用すると、これらのボットを作成および管理するための使いやすいツール セットが得られます。

ボットは、C#、JavaScript、Python などのさまざまな言語を使用して開発できます。 開発が完了したら、それらを Azure にデプロイできます。 ボットの重要なコンポーネントは、ユーザーが通信するコア ロジックとインターフェイスを含む Web アプリです。 ボットが動作するための主な要件の 1 つは、パブリックにアクセスできる HTTPS エンドポイントを公開する必要があるという点です。

通常 InfoSec ポリシーでは、Web アプリへのすべての受信トラフィックが、企業のファイアウォールを通過する必要があります。 つまり、ボットに送信されるトラフィックとボットからの応答はすべて、他の Web アプリと同様に、企業のファイアウォールを経由してルーティングされる必要があります。

考えられるユース ケース

組織は、モバイル ユーザーとデスクトップ ユーザーにボットを利用できます。 次に例をいくつか示します。

  • 単純なクエリ。 ボットは、完全一致をクエリまたは関連する一致のグループに配信して、あいまいさを回避するのに役立ちます。
  • マルチターンの対話。 次のステップを想定することで、ボットにより、ユーザーがタスク フローを実施しやすくなります。
  • ユーザーへの連絡。 ボットは、ドキュメントに何か変更が生じた場合や、作業項目が閉じられたときにメッセージを送信することがあります。

考慮事項

監視

このシナリオ例では監視は実装されていませんが、ボットの App Service で Azure Monitor サービスを使用し、その可用性とパフォーマンスを監視できます。

スケーラビリティ

このシナリオで使用されるボットは、Azure App Service でホストされます。 その結果、標準の App Service 自動スケーリング機能を使用して、ボットを実行しているインスタンスの数を自動的にスケーリングし、ボットが需要に対応できるようにすることができます。 自動スケーリングの詳細については、「自動スケーリングのベスト プラクティス」を参照してください。

スケーラビリティに関する他のトピックについては、Azure アーキテクチャ センターの「パフォーマンス効率のチェックリスト」を参照してください。

DevOps

継続的デプロイ パイプラインを使用して、Web アプリ、API アプリ、モバイル アプリを Azure App Service プランにデプロイするのが一般的な実践方法です。 セキュリティで保護されたボットの App Service はプライベート エンドポイントを使用して保護されます。外部でホストされるビルド エージェントには、更新プログラムをデプロイするために必要なアクセス権はありません。 この問題を回避するには、Azure パイプラインのセルフホステッド DevOps エージェントなどのソリューションを使用する必要がある場合があります。

セキュリティ

Azure DDoS Protection では、アプリケーションの設計に関するベスト プラクティスと組み合わせることにより、DDoS 攻撃からの保護を向上させるための強化された DDoS 軽減機能が提供されます。 すべての境界仮想ネットワークで Azure DDOS Protection を有効にする必要があります。

このシナリオのデプロイ

前提条件

既存の Azure アカウントが必要です。 Azure サブスクリプションをお持ちでない場合は、開始する前に 無料アカウント を作成してください。

チュートリアル

  1. 次の Azure CLI コマンドを Azure Cloud Shell またはお好みのデプロイ シェルで実行します。

    この一連のコマンドにより、このウォークスルーに必要なリソース グループ、仮想ネットワーク、サブネットが作成されます。 Teams で使用される IP 範囲は、52.112.0.0/14,52.122.0.0/15 です。

    # Declare variables (bash syntax)
    export PREFIX='SecureBot'
    export RG_NAME='rg-'${PREFIX}
    export VNET_NAME='vnet-'${PREFIX}
    export SUBNET_INT_NAME='VnetIntegrationSubnet'
    export SUBNET_PVT_NAME='PrivateEndpointSubnet'
    export LOCATION='eastus'
    export TEAMS_IP_RANGE='52.112.0.0/14 52.122.0.0/15'
    export FIREWALL_NAME='afw-'${LOCATION}'-'${PREFIX}
    
    # Create a resource group
    az group create --name ${RG_NAME} --location ${LOCATION}
    
    # Create a virtual network with a subnet for the firewall
    az network vnet create \
    --name ${VNET_NAME} \
    --resource-group ${RG_NAME} \
    --location ${LOCATION} \
    --address-prefix 10.0.0.0/16 \
    --subnet-name AzureFirewallSubnet \
    --subnet-prefix 10.0.1.0/26
    
    # Add a subnet for the Virtual network integration
    az network vnet subnet create \
    --name ${SUBNET_INT_NAME} \
    --resource-group ${RG_NAME} \
    --vnet-name ${VNET_NAME} \
    --address-prefix 10.0.2.0/24
    
    # Add a subnet where the private endpoint will be deployed for the app service
    az network vnet subnet create \
    --name ${SUBNET_PVT_NAME} \
    --resource-group ${RG_NAME} \
    --vnet-name ${VNET_NAME} \
    --address-prefix 10.0.3.0/24
    

    プライベート エンドポイント サブネットを作成すると、プライベート エンドポイント ポリシーは既定で無効になります。

    デプロイが完了すると、仮想ネットワーク内に次のサブネットが表示されます。

    vnet-SecureBot [サブネット] ウィンドウのスクリーンショット。

  2. 次の CLI コマンドを実行して、手順 1 で作成したファイアウォール サブネットに Azure Firewall インスタンスをデプロイします。

    # Create a firewall
    az network firewall create \
        --name ${FIREWALL_NAME} \
        --resource-group ${RG_NAME} \
        --location ${LOCATION}
    
    # Create a public IP for the firewall
    az network public-ip create \
        --name ${FIREWALL_NAME}-pip \
        --resource-group ${RG_NAME} \
        --location ${LOCATION} \
        --allocation-method static \
        --sku standard
    
    # Associate the IP with the firewall
    az network firewall ip-config create \
        --firewall-name ${FIREWALL_NAME} \
        --name ${FIREWALL_NAME}-Config \
        --public-ip-address ${FIREWALL_NAME}-pip \
        --resource-group ${RG_NAME} \
        --vnet-name ${VNET_NAME}
    
    # Update the firewall
    az network firewall update \
        --name ${FIREWALL_NAME} \
        --resource-group ${RG_NAME}
    
    # Get the public IP address for the firewall and take note of it for later use
    az network public-ip show \
        --name ${FIREWALL_NAME}-pip \
        --resource-group ${RG_NAME}
    

    ファイアウォールの構成は、次のようになります。

    fw-SecureBot ファイアウォール構成のスクリーンショット。

  3. 基本的なボットを作成します。

  4. 基本的なボットを、手順 1 で作成したリソース グループにデプロイします。

    このプロセスの一環として、アプリの登録を作成します。これは、チャネルを介してボットと対話する必要があります。 このプロセスでは、必要な App Service プラン、App Service、および Web アプリ ボットもデプロイします。

    注意

    Azure Private Link をサポートする App Service プランを選択します。

  5. カスタム ドメインを、手順 3 でリソース グループにデプロイされた App Service にマップします。

    この手順ではドメイン レジストラーにアクセスする必要があります。また、手順 2 で作成したファイアウォールのパブリック IP を指す A レコードをカスタム ドメインに追加する必要があります。

  6. マップされたカスタム ドメインをセキュリティで保護するには、ドメインの既存の証明書をアップロードするか、Azure で App Service 証明書を購入してインポートします。 これを行うには、「Azure App Service で TLS/SSL バインドを使用してカスタム DNS 名をセキュリティで保護する」にある手順に従います。

    これで、完全に機能するボットが作成され、Teams のチャネルに追加し、「Bot Framework SDK のドキュメント」に記載された指示を使用して Web チャットを介してテストできるようになりました。

    注意

    この時点で、ボットの App Service には、azurewebsites.net URL と構成したカスタム URL の両方を介してまだパブリック アクセスが可能です。 次の手順では、プライベート エンドポイントを使用してパブリック アクセスを無効にします。 また、ボット サービスに Teams クライアントとの通信のみを許可するように、ファイアウォールを構成します。

  7. 次の Azure CLI スクリプトを実行し、プライベート エンドポイントをデプロイして構成します。 この手順では、ボットの App Service の VNet 統合も実装し、仮想ネットワークの統合サブネットに接続します。

    # Disable private endpoint network policies (this step is not required if you're using the Azure portal)
    az network vnet subnet update \
      --name ${SUBNET_PVT_NAME} \
      --resource-group ${RG_NAME} \
      --vnet-name ${VNET_NAME} \
      --disable-private-endpoint-network-policies true
    
    # Create the private endpoint, being sure to copy the correct resource ID from your deployment of the bot app service
    # The ID can be viewed by using the following CLI command:
    # az resource show --name wapp-securebot --resource-group rg-securebot --resource-type Microsoft.web/sites --query "id" 
    az network private-endpoint create \
      --name pvt-${PREFIX}Endpoint \
      --resource-group ${RG_NAME} \
      --location ${LOCATION} \
      --vnet-name ${VNET_NAME} \
      --subnet ${SUBNET_PVT_NAME} \
      --connection-name conn-${PREFIX} \
      --private-connection-resource-id /subscriptions/cad87d9e-c941-4519-a638-c9804a0577b9/resourceGroups/rg-securebot/providers/Microsoft.Web/sites/wapp-securebot \
      --group-id sites
    
    # Create a private DNS zone to resolve the name of the app service
    az network private-dns zone create \
      --name ${PREFIX}privatelink.azurewebsites.net \
      --resource-group ${RG_NAME}
    
    az network private-dns link vnet create \
      --name ${PREFIX}-DNSLink \
      --resource-group ${RG_NAME} \
      --registration-enabled false \
      --virtual-network ${VNET_NAME} \
      --zone-name ${PREFIX}privatelink.azurewebsites.net
    
    az network private-endpoint dns-zone-group create \
      --name chatBotZoneGroup \
      --resource-group ${RG_NAME} \
      --endpoint-name pvt-${PREFIX}Endpoint \
      --private-dns-zone ${PREFIX}privatelink.azurewebsites.net \
      --zone-name ${PREFIX}privatelink.azurewebsites.net
    
    # Establish virtual network integration for outbound traffic
    az webapp vnet-integration add \
      -g ${RG_NAME} \
      -n wapp-${PREFIX} \
      --vnet ${VNET_NAME} \
      --subnet ${SUBNET_INT_NAME}
    

    これらのコマンドを実行すると、リソース グループに次のリソースが表示されます。

    リソース グループ内のリソースの一覧を示すスクリーンショット。

    App Service の [ネットワーク] セクションの [VNet 統合] オプションは、次のように表示されるはずです。

    wapp-securebot の [ネットワーク] オプションのスクリーンショット。

    [VNet 統合] オプションのスクリーンショット。

    [プライベート エンドポイント接続] ウィンドウのスクリーンショット。

  8. 次に、各サブネットとの間のトラフィックがファイアウォールを通過するルーティング テーブルを作成します。 前の手順で作成したファイアウォールのプライベート IP アドレスが必要です。

    # Create a route table
    az network route-table create \
      -g ${RG_NAME} \
      -n rt-${PREFIX}RouteTable
    
    # Create a default route with 0.0.0.0/0 prefix and the next hop as the Azure firewall virtual appliance to inspect all traffic. Make sure you use your firewall's internal IP address instead of 10.0.1.4
    az network route-table route create -g ${RG_NAME} \
      --route-table-name rt-${PREFIX}RouteTable -n default \
      --next-hop-type VirtualAppliance \
      --address-prefix 0.0.0.0/0 \
      --next-hop-ip-address 10.0.1.4
    
    # Associate the two subnets with the route table
    az network vnet subnet update -g ${RG_NAME} \
      -n ${SUBNET_INT_NAME} --vnet-name ${VNET_NAME} \
      --route-table rt-${PREFIX}RouteTable
    
    az network vnet subnet update -g ${RG_NAME} \
      -n ${SUBNET_PVT_NAME} \
      --vnet-name ${VNET_NAME} \
      --route-table rt-${PREFIX}RouteTable
    

    コマンドを実行すると、ルーティング テーブル リソースは次のようになります。

    rt-SecureBotRouteTable ウィンドウのスクリーンショット。

    ルーティング テーブルを作成した後、パブリック IP からボット App Service にトラフィックを配信し、Microsoft Teams 以外のすべてのエンドポイントからのトラフィックを制限する規則をファイアウォールに追加します。 さらに、仮想ネットワークと Azure Bot Service または Microsoft Entra ID と間のトラフィックをサービス タグを使って許可します。

  9. 次のコマンドを実行します。

    # Create a NAT rule collection and a single rule. The source address is the public IP range of Microsoft Teams
    # Destination address is that of the firewall. 
    # The translated address is that of the app service's private link.
    az network firewall nat-rule create \
      --resource-group ${RG_NAME} \
      --collection-name coll-${PREFIX}-nat-rules \
      --priority 200 \
      --action DNAT \
      --source-addresses ${TEAMS_IP_RANGE} \
      --dest-addr 23.100.26.84 \
      --destination-ports 443 \
      --firewall-name ${FIREWALL_NAME} \
      --name rl-ip2appservice \
      --protocols TCP \
      --translated-address 10.0.3.4 \
      --translated-port 443
    
    # Create a network rule collection and add three rules to it. 
    # The first one is an outbound network rule to only allow traffic to the Teams IP range.
    # The source address is that of the virtual network address space, destination is the Teams IP range.
    az network firewall network-rule create \
      --resource-group ${RG_NAME} \
      --collection-name coll-${PREFIX}-network-rules \
      --priority 200 \
      --action Allow \
      --source-addresses 10.0.0.0/16 \
      --dest-addr ${TEAMS_IP_RANGE} \
      --destination-ports 443 \
      --firewall-name ${FIREWALL_NAME} \
      --name rl-OutboundTeamsTraffic \
      --protocols TCP
    
    # This rule will enable traffic to all IP addresses associated with Azure AD service tag
    az network firewall network-rule create \
      --resource-group ${RG_NAME} \
      --collection-name coll-${PREFIX}-network-rules \
      --source-addresses 10.0.0.0/16 \
      --dest-addr AzureActiveDirectory \
      --destination-ports '*' \
      --firewall-name ${FIREWALL_NAME} \
      --name rl-AzureAD \
      --protocols TCP
    
    # This rule will enable traffic to all IP addresses associated with Azure Bot Services service tag
    az network firewall network-rule create \
      --resource-group ${RG_NAME} \
      --collection-name coll-${PREFIX}-network-rules \
      --source-addresses 10.0.0.0/16 \
      --dest-addr AzureBotService \
      --destination-ports '*' \
      --firewall-name ${FIREWALL_NAME} \
      --name rl-AzureBotService \
      --protocols TCP
    

    コマンドを実行すると、ファイアウォール規則は次のようになります。

    [NAT 規則コレクションの編集] ウィンドウのスクリーンショット。

    [ネットワーク規則コレクションの編集] ウィンドウのスクリーンショット。

  10. ボットは Teams のチャネルからのみアクセス可能であり、ボット App Service との間のすべてのトラフィックがファイアウォールを通過することを確認できます。

共同作成者

この記事は、Microsoft によって保守されています。 当初の寄稿者は以下のとおりです。

プリンシパル作成者:

  • Ali Jafry | クラウド ソリューション アーキテクト

次のステップ