Dialogflow が Webhook リクエストに対して開始するネットワーク トラフィックは、パブリック ネットワークで送信されます。両方向のトラフィックの安全性と信頼性を確保するため、Dialogflow は相互 TLS 認証(mTLS)をオプションでサポートします。mTLS では、クライアント(Dialogflow)とサーバー(Webhook サーバー)の両方が TLS handshake の間に証明書を提示し、相互に ID を証明します。
mTLS のリクエスト
mTLS をリクエストするには:
- Webhook HTTPS サーバーが TLS handshake 中にクライアント証明書をリクエストするように、準備をします。
- Webhook サーバーは、クライアント証明書の受信時に、この証明書を検証する必要があります。
クライアントとサーバーの両方で相互に信頼できる Webhook サーバーの証明書チェーンをインストールします。Google サービスに接続するアプリケーションは、Google Trust Services によってリストされているすべての認証局を信頼する必要があります。ルート証明書は https://pki.goog/ からダウンロードできます。
デモ用 Node.js サーバー
Node.js デモサーバーの例を示します。
- 自己署名証明書と pem ファイルを準備します。
- 証明書チェーン ファイルを準備します。
curl https://pki.goog/roots.pem >> ca-crt.pem
-
次のサンプルを
server.js
として保存します。var https = require('https'); const express = require('express') var fs = require('fs'); var options = { // Specify the key file for the server key: fs.readFileSync('./server-key.pem'), // Specify the certificate file cert: fs.readFileSync('./server-crt.pem'), // Specify the Certificate Authority certificate ca: fs.readFileSync('./ca-crt.pem'), // Requesting the client to provide a certificate, to authenticate the user. requestCert: true, // As specified as "true", so no unauthenticated traffic // will make it to the specified route specified rejectUnauthorized: false }; var app = express(); app.use(function (req, res, next) { if (!req.client.authorized) { //return res.status(401).send('Client cert failed. User is not authorized\n'); } // Examine the cert itself, and even validate based on that! var cert = req.socket.getPeerCertificate(); if (cert.subject) { console.log('Client Certificate: ',cert); console.log('Client Certificate Common Name: '+cert.subject.CN); console.log('Client Certificate Location: '+cert.subject.L); console.log('Client Certificate Organization Name: '+cert.subject.O); console.log('Client Certificate Email Address: '+cert.subject.emailAddress); } res.writeHead(200, {'Content-Type': 'text/plain'}); res.end("hello world from client cert\n"); next(); }); var listener = https.createServer(options, app).listen(4433, function () { console.log('Express HTTPS server listening on port ' + listener.address().port); });
- server.js を実行します。
-
requestCert を true に設定します。
curl https://127.0.0.1:4433 -k
-
クライアント証明書を送信します。SSL handshake が完了しました。
curl -v -s -k --key client-key.pem --cert client-crt.pem https://localhost:4433 openssl s_client -key client-key.pem -cert client-crt.pem -connect localhost:4433 -CAfile ca-crt.pem
ベスト プラクティス
独自の Dialogflow エージェントから確実に Webhook リクエストが行われるようにするには、Webhook サーバーの Webhook リクエストのリソース名(例: session
)でプロジェクト ID を確認する必要があります。
エラー
クライアント証明書が失敗した場合(たとえば、クライアント証明書がクライアントから送信されなかった場合や、クライアント証明書が正しく署名されていない場合など)、TLS handshake は失敗し、セッションは終了します。
一般的なエラー メッセージ:
エラー メッセージ | 説明 |
---|---|
Failed to verify client's certificate: x509: certificate signed by unknown authority(クライアントの証明書を検証できませんでした: x509: 不明な権限で署名された証明書) | Dialogflow はクライアント証明書を外部 Webhook に送信しましたが、外部 Webhook で検証できませんでした。外部 Webhook で CA チェーンが正しくインストールされなかったことが原因として考えられます。Google のすべてのルート CA は信頼される必要があります。 |