本指南介绍了如何设置 NGINX 以在 Debian 11 (Bullseye) 上使用 Cloud HSM 密钥进行 TLS 分流。您可能需要修改这些命令,才能使其适用于您的操作系统或 Linux 发行版。
您可以在 kms-solutions GitHub 代码库中找到本教程的基于 Terraform 的蓝图版本。
使用场景
将 Cloud HSM 密钥与 NGINX 结合使用以进行 TLS 分流有助于满足以下企业安全需求:
- 您希望 NGINX Web 服务器将 TLS 加密操作分流到 Cloud HSM。
- 您不希望将证书的私钥存储在托管 Web 应用的 Compute Engine 实例的本地文件系统上。
- 您需要满足监管要求,其中面向公众的应用需要使用通过 FIPS 140-2 3 级认证的 HSM 来保护其证书。
- 您希望使用 NGINX 创建一个具有 TLS 终止的反向代理来保护您的 Web 应用。
准备工作
在继续之前,请完成将 Cloud HSM 密钥与 OpenSSL 结合使用中的步骤。
OpenSSL 设置完成后,请确保安装了最新版本的 nginx:
sudo apt-get update
sudo apt-get install libengine-pkcs11-openssl opensc nginx
安全配置建议
根据以下建议保护托管 NGINX 的实例:
按照为实例创建和启用服务账号中的说明托管 NGINX。
- 分配以下角色:
roles/cloudkms.signerVerifierroles/cloudkms.viewer
- 分配以下角色:
按如下方式配置组织政策,以限制外部 IP 和服务账号密钥的创建。
constraints/compute.vmExternalIpAccessconstraints/iam.disableServiceAccountKeyCreation
创建启用专用 Google 访问通道的自定义子网。
配置防火墙规则。
- 仅为 SSH 创建 IAP 防火墙规则。
创建 Linux 虚拟机,并按如下方式进行配置:
- 选择您之前创建的正确服务账号。
- 选择您之前创建的网络。
- 为所有防火墙规则添加适当的标签。
- 确保子网的“外部 IP”字段设置为
none。
向您的身份授予实例的 IAP-Secured Tunnel User (
roles/iap.tunnelResourceAccessor) 角色。- 如需了解详情,请参阅针对 Compute 的 IAP 配置。
创建并配置 Cloud HSM 签名密钥
以下部分详细介绍了创建和配置 Cloud HSM 签名密钥所需的步骤。
创建 Cloud HSM 托管的签名密钥
在您的Google Cloud 项目内,在您之前为 OpenSSL 配置的密钥环中创建 Cloud HSM EC-P256-SHA256 签名密钥:
gcloud kms keys create NGINX_KEY \
--keyring "KEY_RING" --project "PROJECT_ID" \
--location "LOCATION" --purpose "asymmetric-signing" \
--default-algorithm "ec-sign-p256-sha256" --protection-level "hsm"
使用 SSH 和 IAP 连接到虚拟机
使用 SSH 和 IAP 通过以下命令连接到虚拟机:
gcloud compute ssh INSTANCE \
--zone ZONE --tunnel-through-iap
如果您遇到问题,请确认您使用了 --tunnel-through-iap 标志。
此外,还要确认您在实例上拥有 IAP-Secured Tunnel User (roles/iap.tunnelResourceAccessor) 角色,以便使用 gcloud CLI 进行身份验证。
使用 OpenSSL 创建证书
对于生产环境,请创建证书签名请求 (CSR)。如需了解详情,请参阅生成 CSR 的示例。向证书授权机构 (CA) 提供 CSR,以便他们为您创建证书。在后续部分中使用您的 CA 提供的证书。
为便于说明,您可以使用 Cloud HSM 签名密钥生成自签名证书。为此,OpenSSL 允许您使用 PKCS #11 URI(而非常规路径),通过其标签标识密钥(对于 Cloud KMS 密钥,标签是 CryptoKey 名称)。
openssl req -new -x509 -days 3650 -subj '/CN=CERTIFICATE_NAME/' \
DIGEST_FLAG -engine pkcs11 -keyform engine \
-key PKCS_KEY_TYPE=KEY_IDENTIFIER > CA_CERT
替换以下内容:
CERTIFICATE_NAME:证书的名称。DIGEST_FLAG:非对称签名密钥使用的摘要算法。根据密钥使用-sha256、-sha384或-sha512。PKCS_KEY_TYPE:用于标识密钥的标识符类型。 如需使用最新的密钥版本,请使用pkcs11:object并提供密钥的名称。如需使用特定密钥版本,请将pkcs11:id与密钥版本的完整资源 ID 搭配使用。KEY_IDENTIFIER:密钥的标识符。如果您使用的是pkcs11:object,请使用密钥的名称,例如NGINX_KEY。 如果您使用的是pkcs11:id,请使用密钥或密钥版本的完整资源 ID,例如projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/NGINX_KEY/cryptoKeyVersions/KEY_VERSION。CA_CERT:您要保存证书文件的路径。
如果该命令失败,则 PKCS11_MODULE_PATH 可能设置不正确,或者您可能没有使用 Cloud KMS 签名密钥的正确权限。
您现在应该有一个如下所示的证书:
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
为 NGINX 安装证书
运行以下命令,创建一个用于放置公共证书的位置:
sudo mkdir /etc/ssl/nginx
sudo mv CA_CERT /etc/ssl/nginx
配置环境以使用 PKCS #11 库
接下来的部分将详细介绍准备和测试环境所需的步骤。
为 NGINX 准备库配置
允许 NGINX 使用以下命令通过库记录其 PKCS #11 引擎操作:
sudo mkdir /var/log/kmsp11
sudo chown www-data /var/log/kmsp11
创建一个空的库配置文件,并为 NGINX 设置适当的权限。
sudo touch /etc/nginx/pkcs11-config.yaml
sudo chmod 744 /etc/nginx/pkcs11-config.yaml
修改空白配置文件,并添加所需的配置,如以下代码段所示:
# cat /etc/nginx/pkcs11-config.yaml
---
tokens:
- key_ring: "projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING"
log_directory: "/var/log/kmsp11"
测试 OpenSSL 配置
运行以下命令:
openssl engine -tt -c -v pkcs11
您将看到如下所示的输出:
(pkcs11) pkcs11 engine
[RSA, rsaEncryption, id-ecPublicKey]
[ available ]
SO_PATH, MODULE_PATH, PIN, VERBOSE, QUIET, INIT_ARGS, FORCE_LOGIN
配置 NGINX 以使用 Cloud HSM
通过修改几个 NGINX 文件来允许 TLS 分流。首先,修改 /etc/nginx/nginx.conf 文件中的两个位置,添加一些指令来配置 NGINX 以使用 PKCS #11。
在 event 代码块之后、http 代码块之前,添加以下指令:
ssl_engine pkcs11;
env KMS_PKCS11_CONFIG=/etc/nginx/pkcs11-config.yaml;
在同一 /etc/nginx/nginx.conf 文件中,配置 SSL 指令以使用 Cloud HSM 中的证书及其私钥。在 http 代码块中添加以下属性:
ssl_certificate "/etc/ssl/nginx/CA_CERT";
ssl_certificate_key "engine:pkcs11:PKCS_KEY_TYPE=KEY_IDENTIFIER";
ssl_protocols TLSv1.2 TLSv1.3; # Consider changing the default to only TLS1.2 or newer
# Consider defining the `ssl_ciphers` to use ciphers approved by your security teams and handle
# appropriate client compatibility requirements.
您的 /etc/nginx/nginx.conf 文件应如下所示:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
ssl_engine pkcs11;
env KMS_PKCS11_CONFIG=/etc/nginx/pkcs11-config.yaml;
http {
#...
#...
# SSL configuration
ssl_certificate "/etc/ssl/nginx/CA_CERT";
ssl_certificate_key "engine:pkcs11:pkcs11:object=NGINX_KEY";
ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
# ssl_ciphers YOUR_CIPHERS
ssl_prefer_server_ciphers on;
#...
#...
}
配置 NGINX 以监听 TLS 流量
修改 /etc/nginx/sites-enabled/default 文件以监听 TLS 流量。对 server 块中的 SSL 配置取消注释。
最终的更改应如下例所示:
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# ...
# ...
}
向 NGINX 服务提供环境变量
运行以下命令:
sudo systemctl edit nginx.service
在生成的编辑器中,添加以下行,并将 LIBPATH 替换为您安装 libkmsp11.so 的位置的值:
[Service]
Environment="GRPC_ENABLE_FORK_SUPPORT=1"
Environment="KMS_PKCS11_CONFIG=/etc/nginx/pkcs11-config.yaml"
Environment="PKCS11_MODULE_PATH=LIBPATH/libkmsp11-1.0-linux-amd64/libkmsp11.so"
配置这些值后,您需要运行以下命令才能使这些值生效:
sudo systemctl daemon-reload
重启 NGINX(启用 TLS 分流)
运行以下命令,以便 NGINX 重新启动并使用更新后的配置:
sudo systemctl start nginx
测试 NGINX 使用 TLS 分流到 Cloud HSM
使用 openssl s_client 运行以下命令,测试与 NGINX 服务器的连接:
openssl s_client -connect localhost:443
客户端完成 SSL 握手并等待您的输入:
# completes SSL handshake
# ...
# ...
# ...
Verify return code: 18 (self signed certificate)
# ...
Max Early Data: 0
---
read R BLOCK
# When the client pauses, it's waiting for instructions.
# Have the client get the index.html file in the root path (`/`), by typing the following:
GET /
# Press enter.
# You should now see the default NGINX index.html file.
您的审核日志现在应显示对 NGINX_KEY 密钥的操作。
如需查看日志,请在 Google Cloud 控制台中前往 Cloud Logging。
在您一直使用的项目中,添加以下过滤条件:
resource.type="cloudkms_cryptokeyversion"
运行查询后,您应该会看到对 NGINX_KEY 密钥的非对称密钥操作。
可选配置
您可能需要创建外部直通式网络负载平衡器,以使用外部 IP 公开 NGINX 服务器。
如果您需要将 NGINX 用作具有负载均衡功能的反向代理,请考虑更新 NGINX 配置文件。如需详细了解如何将 NGINX 配置为反向代理,请参阅 Google Cloud平台上的 NGINX Plus 全主动 HA。
后续步骤
您现在已将 NGINX 服务器配置为使用 TLS 分流到 Cloud HSM。