次の方法で共有


Azure Application Gateway で Web PubSub サービスを使用する

Azure Application Gateway は、アプリケーション レベルで機能する Web トラフィック ロード バランサーです。 これは、Web クライアントの単一窓口として使用でき、Web トラフィックを、特に URI パスなどの HTTP 属性に基づいてさまざまなバックエンドにルーティングするように構成できます。 Application Gateway には WebSocket のネイティブ サポートがあります。ユーザーは、WebSocket を有効にするために特別なものを構成する必要はありません。

このガイドでは、Azure Application Gateway を使用して Web PubSub リソースをセキュリティで保護する方法について説明します。 Application Gateway からのトラフィックのみを許可し、Web PubSub リソースへのパブリック トラフィックを無効にすることで、より高いレベルのセキュリティを実現します。

図に示すように、Web PubSub リソースのプライベート エンドポイントを設定する必要があります。 このプライベート エンドポイントは、Application Gateway と同じ仮想ネットワーク内に存在する必要があります。

Azure Application Gateway で Web PubSub を使用するアーキテクチャの概要を示す図。

このガイドでは、段階的なアプローチを採用します。 まず、Web PubSub リソースへのトラフィックが正常にプロキシされるように Application Gateway を構成します。 次に、Web PubSub のアクセス制御機能を適用して、Application Gateway からのトラフィックのみを許可します。

手順 1: Web PubSub リソースへのトラフィックをプロキシするように Application Gateway を構成する

手順 1 で達成しようとしている内容を図に示します。

「手順 1: Web PubSub リソースへのトラフィックをプロキシするように Application Gateway を構成する」のアーキテクチャの概要を示す図。

Azure Application Gateway インスタンスを作成する

Azure portal で Azure Application Gateway を検索し、手順に従ってリソースを作成します。 主な手順が図で強調表示されています。

Application Gateway リソースの作成方法 (基本) を示すスクリーンショット。

Azure リソースが安全に相互通信できるようにするために、仮想ネットワークが必要です。 Azure Application Gateway は専用のサブネットを必要とします。これを作成しました。 このガイドの手順 1 では、Azure Application Gateway リソースが、パブリック インターネット経由で Web PubSub リソースにトラフィックを転送します。 手順 2 では、Azure Application Gateway が仮想ネットワーク経由で安全に Web PubSub リソースにトラフィックを転送するように、Web PubSub リソースを格納する別のサブネットを作成します。

Azure Application Gateway を構成する

Azure Application Gateway の構成には、3 つのコンポーネントが必要です。

  • フロントエンド
  • バックエンド
  • ルーティング規則

フロントエンドは、Azure Application Gateway の IP アドレスです。 Web クライアントの単一窓口として Azure Application Gateway を使用するため、そのパブリック IP を作成する必要があります。

Application Gateway リソースの作成方法 (パブリック IP の作成) を示すスクリーンショット。

バックエンドは、Application Gateway リソースがトラフィックを送信できるリソースです。 ここでは、Web PubSub リソースという 1 つのターゲットがあります。 このガイドに従うために使用する既存の Web PubSub リソースのホスト名を Azure portal で見つけます。 xxxx.webpubsub.azure.com のような文字列です。

Application Gateway リソースの作成方法 (バックエンド プールの作成) を示すスクリーンショット。

フロントエンドとバックエンドの両方をセットアップしたら、フロントエンドとバックエンドを接続するルーティング規則を構成する必要があります。 ルーティング規則は、トラフィックのルーティング方法と場所を Application Gateway に指示します。

まず、リスナーをセットアップします。 この構成は、ポート 80 で HTTP トラフィックをリッスンするように Application Gateway に指示します。

Application Gateway リソースの作成方法 (ルーティング規則の作成、リスナー) を示すスクリーンショット。

次に、バックエンド ターゲットをセットアップします。 前に作成したバックエンド プール (Web PubSub リソース) に対するバックエンド ターゲットを構成します。 さらに、Application Gateway がトラフィックを転送する方法を指定する必要があります。 これは、[バックエンド設定] で行います。

Application Gateway リソースの作成方法 (ルーティング規則の作成、バックエンド ターゲット) を示すスクリーンショット。

Web PubSub サービスは HTTPS トラフィックのみを受け入れます。 そのため、HTTPS を使用して Web PubSub と通信するように Application Gateway に指示します。 このガイドに集中するために、Application Gateway にホストを選択させます。 運用環境では、カスタム ドメインを設定することをお勧めします。

Application Gateway リソースの作成方法 (ルーティング規則の作成、バックエンド設定) を示すスクリーンショット。

3 つのコンポーネントが構成されると、次のスクリーンショットのような内容が表示されます。 Application Gateway を経由するトラフィックのフローを、次のように視覚化できます。

  1. Web クライアントが、Application Gateway リソースのパブリック IP に要求を送信します。
  2. Application Gateway が、ユーザーが構成したルーティング規則を参照してトラフィックをルーティングします。
  3. ルーティング規則が一致すると、トラフィックが指定されたバックエンド ターゲットに転送されます。

Application Gateway リソースの作成方法 (完了) を示すスクリーンショット。

強調に値することの 1 つは、WebSocket 以外の接続をまったく同じ方法で構成することです。 WebSocket 接続のプロキシに対する Application Gateway のネイティブ サポートの詳細を確認できます

最後に更新するのは、バックエンド正常性プローブです。 [設定] - >[正常性プローブ] を選択し、生成された正常性プローブの設定を選択し、パス/api/health に更新し、他の設定を変更しないようにします。

Application Gateway が正しく構成されたことをテストして確認する

Web PubSub リソースが正常であることを確認する

Web PubSub リソースの無効なエンドポイントに要求を送信し、Web PubSub からエラー メッセージが返されることを期待します。

curl https://<your-web-pubsub-resource-endpoint>/client

「"hub" の値が無効です」というエラー メッセージが表示されます。このエラーは、Web PubSub サービスが要求を正常に受信し、それに応じて応答したことを示しています。

Application Gateway が Web PubSub リソースへのトラフィックをプロキシすることを確認する

同様の手順を繰り返し、同じエラー メッセージが返されることを期待します。

curl http://<public-ip-of-your-application-gateway-resource>/client

「"hub" の値が無効です」という同じエラー メッセージが表示されます。このエラーは、Application Gateway リソースが、構成されたルーティング規則を使用してトラフィックを正常にルーティングしたことを示しています。

Application Gateway で WebSocket 接続をプロキシできることをテストして確認する

Web PubSub 経由でメッセージを発行する

Web PubSub 経由で定期的にメッセージを発行するサーバーをシミュレートする簡単なプログラムを作成します。 手順 1 でプログラムをローカルで実行してすべてが動作していることを確認し、手順 2 で同じアプリを Azure App Service にデプロイします。

フォルダー構造を準備する
mkdir server && cd server
touch package.json && touch publish.js
ソース コードをコピーする

作成した package.json ファイルにコードをコピーします。

{
  "scripts": {
    "start": "node ./publish.js"
  },
  "dependencies": {
    "@azure/web-pubsub": "^1.1.1",
    "express": "^4.19.2"
  }
}

作成した publish.js ファイルにコードをコピーします。

const express = require("express")
// Uses the service SDK, which makes it easy to consume the capabilities of the service
const { WebPubSubServiceClient } = require('@azure/web-pubsub');

const app = express()
const PORT = 3000

// Hardcodes the hub name 
const hub = "myHub1";

// Grabs the connection string stored as an environment variable
let webpubsub = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, hub);

// Serves the files found in the "public" directory  
app.use(express.static("public"))

// Returns Web PubSub's access token
app.get("/negotiate", async (req, res) => {
  let token = await webpubsub.getClientAccessToken()
  let url = token.url
  res.json({
    url
  })
}
// Every 2 seconds, we ask Web PubSub service to send all connected clients the message "hello, world"
setInterval(() => {
  webpubsub.sendToAll("hello, world", { contentType: "text/plain" });
}, 2000);

// Starts the server
app.listen(process.env.PORT || PORT, () => console.log(`server running on ${PORT}`));
依存関係をインストールし、プログラムを実行する

Azure portal で、Web PubSub リソースの connection string を見つけます。 Web PubSub リソースの接続文字列の取得方法を示すスクリーンショット。

npm install

## Set environment variable
export WebPubSubConnectionString="<replace with the connection string of your Web PubSub resource>"

npm run start

コンソールに「server running on 3000 (3000 で実行されているサーバー)」と表示されます。 プログラムは 2 秒ごとに、接続されているすべての Web クライアントにメッセージをブロードキャストするように Web PubSub サービスに要求します。 現時点では Web PubSub リソースに接続されている Web クライアントはありませんが、重要なログをリアルタイムで監視するライブ トレース ツール機能を有効にすることで、このフローの動作を確認できます。

ブラウザーでメッセージを受信する

ブロードキャストされたメッセージを受け取らないと、点灯しません。 前に作成したサーバー フォルダー内に、クライアント コードを配置する単純な HTML ファイルを作成しましょう。 express アプリは、この静的ファイルに対して機能します。

mkdir public && cd public 
touch index.html
クライアント コードをコピーする

コードを index.html にコピーします

<!DOCTYPE html>

<body>
  <script type="module">
    const endpoint = "http://localhost:3000"

    // Gets an access token through which the client connects with your Web PubSub resource
    const webPubSubUrl = await getWebPubSubAccessToken(endpoint)

    // Opens a WebSocket connection with your Web PubSub resource using browser native WebSocket API 
    const socket = new WebSocket(webPubSubUrl)

    socket.addEventListener("open", () => {
      console.log("connection opened")
    })

    // Prints out the message when it arrives
    socket.addEventListener("message", (msg) => {
      console.log(msg)
    })

    async function getWebPubSubAccessToken(endpoint) {
      const response = await fetch(endpoint + "/negotiate")
      const { url } = await response.json()
      return url
    }
  </script>
</body>

</html>
クライアント プログラムを実行する

任意の Web ブラウザーを開き、サーバーがリッスンしている http://localhost:3000 にアクセスします。

Web PubSub リソースに直接接続するブラウザー クライアントと、ローカルで実行されているサーバー アプリを示すスクリーンショット。

まだ publish.js が実行されていることを確認します。 ページを調べて、[ネットワーク] パネルと [コンソール] パネルを開くと、クライアントが Web PubSub リソースに正常に接続され、ブロードキャストされたメッセージを取得していることがわかります。

Application Gateway 経由で WebSocket 接続をプロキシする

Application Gateway には WebSocket のネイティブ サポートがあるため、Application Gateway リソースの構成を変更する必要はありません。 必要なのは、クライアントが指すエンドポイントを変更することのみです。

publish.js ファイルを見つけて、2 つの変更を行います。

  • Application Gateway リソースのパブリック IP を保持する変数を宣言します。
  • 変数 url が初期化されている行 let url=token.url を変更します。
// ... code omitted from before
const appGatewayEndpoint = process.env.appGatewayEndpoint

app.get("/negotiate", async (req, res) => {
  const token = await webpubsub.getClientAccessToken()
  const url = "ws://" + appGatewayEndpoint + token.url.split(".com")[1]
  // ... code omitted from before
})
 
// ... code omitted from before

Application Gateway リソースのパブリック IP を見つけて、環境変数を設定します。

export appGatewayEndpoint="<replace with the public IP of your Application Gateway resource>"

3 つの注意点。

  • Application Gateway は http トラフィックのみをリッスンするように構成されているため、 wss:// の代わりに ws:// を使用します。
  • 運用環境では、Application Gateway リソースのカスタム ドメインを設定し、HTTPS のみを受け入れるようにそれを構成することをお勧めします。
  • アクセス トークンは、クライアントが Web PubSub リソースに接続するための資格情報をエンコードするため、そのまま保持する必要があります。

ブラウザーを開き、もう一度 http://localhost:3000 にアクセスすると、WebSocket が Application Gateway 経由で正常にプロキシされ、Application Gateway から約 2 秒ごとにメッセージを受信することを確認できます。

Web PubSub リソースに間接的に接続するブラウザー クライアントと、ローカルで実行されているサーバー アプリを示すスクリーンショット。

手順 1 のまとめ

手順 1 の最後に到達しました。 手順 1 に従ってきた場合は、Web PubSub リソースに Web クライアントで直接、および Application Gateway 経由で間接的にアクセスできることがわかります。 Application Gateway の WebSocket に対するネイティブ サポートが動作していることもわかります。 有効にするために、構成を変更する必要はありません。 必要なのは、Web クライアントが Application Gateway エンドポイントを指すようにすることだけです。 Web PubSub サービス SDK から生成された残りのアクセス URL は変更しないようにする必要があります。

手順 2 では、Web PubSub リソースへのパブリック アクセスを閉じて、セキュリティを強化します。

手順 2: Web PubSub リソースへのパブリック アクセスを無効にする

手順 1 の結果、パブリック インターネットと Application Gateway の両方を経由して Web PubSub リソースにアクセスできます。 Web PubSub リソースは同じ仮想ネットワーク内にないため、Application Gateway が Web PubSub リソースにトラフィックを転送すると、パブリック インターネット経由で Web PubSub のパブリック エンドポイントに到達します。 この状況は望ましくありません。

Web PubSub サービスは、アクセス制御の構成をサポートしています。 このような構成の 1 つは、パブリック インターネットからのアクセスを無効にすることです。 完了したら、必ず [保存] をクリックしてください。

Web PubSub のパブリック アクセスを無効にする方法を示すスクリーンショット。

同じコマンドを実行すると、前と同じ "無効なハブ名" が表示される代わりに、403 Forbidden が表示されます。

curl https://<your-web-pubsub-resource-endpoint>/client

これで、Web PubSub リソースでパブリック アクセスが無効になりました。 影響の 1 つは、手順 1 でセットアップされた Application Gateway にも到達できないことです。 Application Gateway エンドポイントに対して同じコマンドを実行すると、504 Gateway Time-out が表示されます。

curl http://<public-ip-of-your-application-gateway-resource>/client

Application Gateway と同じ仮想ネットワークに Web PubSub リソースを取り込む必要があります。 これは、プライベート エンドポイントを作成することで実現します。 プライベート エンドポイントの詳細については、こちらで確認できます。

プライベート エンドポイント用に別個のサブネットを作成する

手順 1 では、Application Gateway を格納するサブネットを作成しました。 Application Gateway は独自のサブネットを必要とするため、プライベート エンドポイント用に別のサブネットを作成する必要があります。

前に作成した仮想ネットワーク リソースを見つけて、新しいサブネットを作成します。

別のサブネットの作成方法を示すスクリーンショット。

Web PubSub リソースのプライベート エンドポイントを作成する

Azure portal で Web PubSub リソースを見つけて、[ネットワーク] ブレードに移動します。 別個のサブネットの作成方法を示すスクリーンショット。

Web PubSub リソースと同じリージョンに、プライベート エンドポイントを作成します。 Web PubSub リソースのプライベート エンドポイントの作成方法を示すスクリーンショット。

作成したばかりの別個のサブネットを選びます。 新しく作成されたサブネットに Web PubSub のプライベート エンドポイントを配置する方法を示すスクリーンショット。

プライベート DNS 統合を有効にします プライベート DNS 統合を有効にする方法を示すスクリーンショット。

Application Gateway リソースのバックエンド プールを更新する

Application Gateway リソースは、Web PubSub リソースのプライベート エンドポイントを作成したことを認識していません。 Application Gateway リソースを見つけて、バックエンド プールを更新します。 バックエンド プールの更新方法を示すスクリーンショット。

このコマンドを再度実行すると、"無効なハブ名" が再び表示されます。これは想定されています。 Application Gateway がパブリック インターネットではなく仮想ネットワーク経由でプロキシすることを示しています。

curl http://<public-ip-of-your-application-gateway-resource>/client

発行プログラムを App Service Web アプリとしてデプロイする

Web PubSub リソースへのパブリック アクセスが無効になっているため、ローカルの publish.js プログラムがリソースに到達できません。 Web PubSub リソースが配置されているのと同じ仮想ネットワークにプログラムを Web アプリとしてデプロイする必要があります。

Web アプリを ZIP ファイルとしてデプロイする

ソース コードを圧縮して Azure App Service にデプロイする前に、クライアント コードを少し変更する必要があります。 /negotiate エンドポイントは、localhost から提供されなくなります。

パブリック フォルダー内の index.html を見つけて、endpoint 変数が宣言されている行を変更します。 これを Web アプリのドメイン名に置き換える必要があります。

Web アプリ リソースのドメイン名を取得する場所を示すスクリーンショット。

  <script>
    // ...code omitted from before
   
   const endpoint = "<replace with your default domain name of your web app>"
    
    // ...code omitted from before
  </script>

Web アプリには、アプリを ZIP ファイルとしてデプロイするための便利なコマンドが用意されています。 az webapp up コマンドについて詳細を確認できます (コマンドが自動化するタスクを含む)。

手順 1 で作成したサーバー フォルダーを見つけます。

## Makes sure you are in the right working directory
cd server 

## Make sure you have Azure CLI installed and log into your Azure account.
az login 

## Creates a ZIP file with the content in the server folder and deploys it as a Web App
az webapp up \
--sku B1 \
--name <the-name-of-your-web-app> \
--location <the-same-location-as-your-Web-PubSub-resource>

Note

このガイドに従ってきた場合は、これまでに作成したリソースが含まれる Azure サブスクリプションに切り替えることが必要な場合があります。 サブスクリプションを切り替えるには、このドキュメントの記事で言及されているコマンドに従います。

環境変数を設定

publish.js プログラムが起動すると、App Service が環境変数をプログラムで使用できるようにします。

設定して publish.js が使用できるようにする必要がある環境変数は 2 つあります。

  • Azure portal で Web PubSub サービスへの接続文字列を見つけて、WebPubSubConnectionString 環境変数を設定します。
  • Application Gateway リソースのフロントエンド パブリック IP を見つけて、appGatewayEndpoint 環境変数を設定します。 Web アプリの 2 つの環境変数の設定のスクリーンショット。

Web アプリで仮想ネットワーク統合を有効にする

App Service は、仮想ネットワーク内に専用サブネットを必要とします。 仮想ネットワーク リソースにアクセスし、Web PubSub リソースに対して行ったように新しいサブネットを作成します。

新しいサブネットが作成されたら、Web アプリ リソースの [ネットワーク] ブレードに移動して、仮想ネットワーク統合を有効にします。

仮想ネットワーク統合を有効にする方法 (手順 1) を示すスクリーンショット。

Web PubSub リソースが配置されているのと同じ仮想ネットワークを選択するようにしてください。  仮想ネットワーク統合を有効にする方法 (手順 2) を示すスクリーンショット。

自動 HTTP リダイレクトをオフにする

既定では、Web アプリは HTTP トラフィックを HTTPS にリダイレクトします。 この既定の動作を無効にする必要があります。 これは運用環境のワークロードにはお勧めしません。 HTTPS への自動リダイレクトをオフにする方法を示すスクリーンショット。

すべてが機能することを確認する

ここまで、手順 2 で次の操作を行いました。

  1. Web PubSub リソースへのパブリック アクセスを無効にし、
  2. リソース用のプライベート エンドポイントを作成し、
  3. Web PubSub リソースに到達できるように、Application Gateway リソースのバックエンド プールを更新しました
  4. クライアントが Web PubSub リソースに接続するためのアクセス トークンを取得するエンドポイントを更新しました
  5. 同じ仮想ネットワークに Web アプリとして publish.js をデプロイし、
  6. Web アプリ リソースに 2 つの環境変数を設定し、
  7. HTTP トラフィックを HTTPS にリダイレクトする Web アプリの既定の動作を無効にしました。

ここで、Web ブラウザーを開き、Web アプリのドメイン名を入力します。 ページを調べて [ネットワーク] パネルを開くと、クライアントがアクセス トークンを求めて Web アプリに接続し、そのトークンを使用して Application Gateway との WebSocket 接続を確立することがわかります。

Web アプリからアクセス トークンを取得する方法を示すスクリーンショット。

Application Gateway 経由で WebSocket 接続が正常に確立されたことを示すスクリーンショット。

[コンソール] パネルを開いている場合、ブロードキャストされたメッセージも表示されます。 Web PubSub のトラフィックをプロキシする Application Gateway からのメッセージの取得を示すスクリーンショット。