双向 TLS 身份验证

Dialogflow 针对网络钩子请求发起的网络流量通过公共网络发送。为了确保每个方向的流量都安全可靠又可信任,Dialogflow 还可视需要支持双向 TLS 身份验证 (mTLS)。使用 mTLS 时,客户端 (Dialogflow) 和服务器(您的网络钩子服务器)在 TLS 握手期间提供证书,互相证明身份。

请求 mTLS

如需请求 mTLS,请执行以下操作:

  1. 对您的 webhook HTTPS 服务器进行准备,以在 TLS 握手期间请求客户端证书。
  2. 网络钩子服务器应在收到客户端证书后对其进行验证。
  3. 为您的 webhook 服务器安装证书链,客户端和服务器共同信任该证书链。您应使用 Google Trust Services CA 1O1 (GTS CA 1O1)。 GTS CA 1O1 使用由 Google Trust Services 拥有和控制的 GlobalSign R2 root(GS Root R2)。 您可从以下网址下载:https://pki.goog/

Node.js 演示服务器

以下是一个 Node.js 演示服务器:

  1. 准备一个自签名证书和 pem 文件。
  2. 准备证书链文件:
    curl https://pki.goog/gsr2/GTS1O1.crt | openssl x509 -inform der >> ca-crt.pem
    curl https://pki.goog/gsr2/GSR2.crt | openssl x509 -inform der >> ca-crt.pem
        
  3. 将以下示例保存为 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);
    });
         
  4. 运行 server.js。
  5. 将 requestCert 设置为 true。
    curl https://127.0.0.1:4433 -k
        
  6. 发送客户端证书。SSL 握手成功完成。
    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
        

错误

如果客户端证书失败(例如没有客户端证书从客户端发出,或者客户端证书未正确签名),则 TLS 握手失败,会话终止。

常见的错误消息:

错误消息 说明
Failed to verify client's certificate: x509: certificate signed by unknown authority(未能验证客户端的证书:x509:证书由未知授权机构签署) Dialogflow 将其客户端证书发送到了外部网络钩子,但外部网络钩子无法对其进行验证。这可能是因为外部网络钩子未正确安装 CA 链。Dialogflow 的当前 CA 是 Google Trust Services CA 1O1。GTS CA 1O1 使用由 Google Trust Services 拥有和控制的 GlobalSign R2 root。