为使用 ESPv2 的 Cloud Endpoints 启用 SSL

本页面介绍在使用 Google Kubernetes Engine、Kubernetes 或 Compute Engine 部署 Extensible Service Proxy V2 (ESPv2) 时,如何启用安全套接字层 (SSL) 端口。对于某些用例,您可能需要为已部署的 Endpoints 服务启用 SSL 端口。

开始之前,请确保您已阅读所选服务类型和环境对应的教程,并且了解如何在不使用 SSL 的情况下部署 ESPv2。

配置 SSL 密钥和证书

要配置 SSL 端口以处理 HTTPS 请求,请按以下步骤操作:

  1. 检查并确保您的 SSL 密钥文件名为 server.key 并且证书文件名为 server.crt。要进行测试,您可以通过以下命令使用 OpenSSL 生成自签名 server.keyserver.crt

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout ./server.key -out ./server.crt
  2. 在服务器证书中同时指定 CNsubjectAltName。这些特性的值应与客户端用于调用您服务的 DNS 或 IP 匹配;否则,SSL 握手将失败。

在 Kubernetes 上为 ESPv2 启用 SSL

要在 Kubernetes 上为 ESPv2 启用 SSL 端口,请执行以下操作:

  1. 使用您的 SSL 密钥和证书创建 Kubernetes Secret:

    kubectl create secret generic esp-ssl \
      --from-file=./server.crt --from-file=./server.key
  2. 修改 Kubernetes 配置文件(例如 echo-ssl.yaml),如以下代码段所示:

    template:
      metadata:
        labels:
          app: esp-echo
      spec:
        volumes:
        - name: esp-ssl
          secret:
            secretName: esp-ssl
        containers:
        - name: esp
          image: gcr.io/endpoints-release/endpoints-runtime:2
          args: [
            "--listener_port", "9000",
            "--backend", "127.0.0.1:8081",
            "--service", "SERVICE_NAME",
            "--rollout_strategy", "managed",
            "--ssl_server_cert_path", "/etc/esp/ssl",
          ]
          ports:
            - containerPort: 9000
          volumeMounts:
          - mountPath: /etc/esp/ssl
            name: esp-ssl
            readOnly: true
        - name: echo
          image: gcr.io/endpoints-release/echo:latest
          ports:
            - containerPort: 8081

    注意:配置示例显示的是需要修改的行。要将文件部署到 Cloud Endpoints,需要完整的配置文件。

  3. 按照 Kubernetes 卷页面中的说明,将您创建的 Kubernetes Secret 作为卷进行装载。

  4. 按照指定 ESPv2 的启动选项中的说明启动 ESPv2,但请务必添加启动标志 --ssl_server_cert_path 以指定装载证书文件的路径。

  5. 运行 kubectl,使用更新后的 Kubernetes 配置文件来启动服务。

    kubectl apply -f echo-ssl.yaml

  6. 使用以下 OpenSSL 命令为客户端生成根证书:

       openssl x509 -in ./server.crt -out ./client.pem -outform PEM
     

    如果客户端使用 curl,则可以在 --caroot 标志中使用 client.pem 文件。对于 gRPC,client.pem 用作 gRPC 通道的 SSL 凭据的根证书文件。

更新 SSL 证书

定期更新 SSL 证书非常重要。要更新 SSL 证书,您必须执行以下步骤:

  • 创建新证书,如上文步骤 1 所述。
  • 将新证书装载到 Kubernetes Secret,如上文步骤 3 所述。
  • 更新 ESPv2 Kubernetes Deployment,如上文步骤 5 所述。
  • 重新生成客户端根证书文件(如上面的第 6 步所述)。

在 Compute Engine 上为 ESPv2 启用 SSL

要在 Compute Engine 上启用 SSL,请先将 server.keyserver.crt 文件复制到 Compute Engine 实例的 /etc/nginx/ssl 文件夹,具体步骤如下:

  1. 运行以下命令,并将 INSTANCE_NAME 替换为您的 Compute Engine 实例的名称:

    gcloud compute scp server.* INSTANCE-NAME
    
  2. 使用 ssh 连接到实例。

    gcloud compute ssh INSTANCE-NAME
    
  3. 在实例虚拟机框中,使用以下命令在文件中创建目录和副本:

      sudo mkdir -p /etc/esp/ssl
      sudo cp server.* /etc/esp/ssl/
    
  4. 要使用 Docker 进行部署,请按照与您的服务类型对应的说明操作。运行 ESPv2 Docker 容器时,请使用以下命令:

    sudo docker run --name=esp \
     --detach \
     --publish=443:9000 \
     --net=esp_net \
     --volume=/etc/esp/ssl:/etc/esp/ssl \
      gcr.io/endpoints-release/endpoints-runtime:2 \
     --service=SERVICE_NAME \
     --rollout_strategy=managed \
     --backend=echo:8080 \
     --ssl_server_cert_path=/etc/esp/ssl \
     --listener_port=9000

    与非 SSL docker run 命令相比,该命令的 SSL 版本会创建不同的配置。例如,该 SSL 命令会:

    • 使用 --volume 将包含密钥文件和 CRT 文件的文件夹装载到容器。
    • 使用 --ssl_server_cert_path=/etc/esp/ssl 指示 ESPv2 在 /etc/esp/ssl 文件夹中查找服务器证书文件 server.keyserver.crt
    • 更改端口映射标志 --publish。HTTPS 端口 443 的传入请求会映射到 ESPv2 端口 9000。

更新 SSL 证书

定期更新 SSL 证书非常重要。要更新 SSL 证书,您必须执行以下步骤:

  • 创建新证书并将其复制到虚拟机实例中,如上文步骤 1 所述。
  • 将新证书复制到 /etc/esp/ssl 目录中,如上文步骤 3 所述。
  • 使用 sudo docker run 命令停止然后重启 ESPv2 容器,具体请参见上文第 4 步。

测试 SSL 端口

要简化 SSL 端口的测试,请设置以下环境变量:

  1. IP_ADDRESS 设置为采用新 SSL 证书的 Compute Engine 实例的 IP 地址。

  2. ENDPOINTS_KEY 设置为有效的 API 密钥

SSL 端口启用后,您可以使用 HTTPS 向 Extensible Service Proxy 发送请求。如果您的证书是自签名证书,请在 curl 中使用 -k 启用不安全选项:

curl -k -d '{"message":"hello world"}' -H "content-type:application/json" \
https://IP_ADDRESS:443/echo?key=ENDPOINTS_KEY

或者,生成 pem 格式的证书,并使用 --cacert 选项在 curl 中使用自签名证书,如下所示:

  openssl x509 -in server.crt -out client.pem -outform PEM
  curl --cacert "./client.pem" -d '{"message":"hello world"}' -H "content-type:application/json" \
  https://IP_ADDRESS:443/echo?key=ENDPOINTS_KEY