本指南介绍了如何设置 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.signerVerifier
roles/cloudkms.viewer
- 分配以下角色:
请按如下方式配置组织政策,以限制外部 IP 和服务账号密钥的创建。
constraints/compute.vmExternalIpAccess
constraints/iam.disableServiceAccountKeyCreation
创建启用了专用 Google 访问通道的自定义子网。
配置防火墙规则。
- 仅为 SSH 创建 IAP 防火墙规则。
创建一个 Linux 虚拟机,并按如下方式进行配置:
- 选择您之前创建的正确服务账号。
- 选择您之前创建的网络。
- 为所有防火墙规则添加适当的标签。
- 确保子网的“外部 IP”字段设置为
none
。
向您的身份授予实例上的 IAP-Secured Tunnel User (
roles/iap.tunnelResourceAccessor
) 角色。- 如需了解详情,请参阅计算设备的 IAP 配置。
创建和配置 Cloud KMS 托管的签名密钥
下一部分将详细介绍创建和配置 Cloud KMS 托管的签名密钥所需的步骤。
创建 Cloud KMS 托管的签名密钥
在您的Google Cloud 项目内,在您之前为 OpenSSL 配置的密钥环中创建 Cloud KMS 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"
使用 IAP 通过 SSH 连接到虚拟机
使用以下命令通过 IAP 通过 SSH 连接到您的虚拟机:
gcloud compute ssh INSTANCE \
--zone ZONE --tunnel-through-iap
如果您遇到问题,请确认您是否使用了 --tunnel-through-iap
标志。此外,请确认您已为使用 gcloud CLI 进行身份验证的实例分配了 IAP-Secured Tunnel User (roles/iap.tunnelResourceAccessor
) 角色。
使用 OpenSSL 创建证书
对于生产环境,请创建证书签名请求 (CSR)。如需了解详情,请参阅生成 CSR 的示例。将 CSR 提供给证书授权机构 (CA),以便他们为您创建证书。在后续部分中,使用 CA 提供的证书。
例如,您可以使用 Cloud KMS 托管的签名密钥生成自签名证书。为此,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
重启启用了 TLS 分流的 NGINX
运行以下命令,以便 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
密钥的操作。如需查看日志,请在 Cloud 控制台中前往 Cloud Logging。在您一直在使用的项目中,添加以下过滤条件:
resource.type="cloudkms_cryptokeyversion"
运行查询后,您应该会看到对 NGINX_KEY
密钥的非对称密钥操作。
可选配置
您可能需要创建外部直通式网络负载平衡器,以便使用外部 IP 公开 NGINX 服务器。
如果您需要将 NGINX 用作具有负载均衡功能的反向代理,请考虑更新 NGINX 配置文件。如需详细了解如何将 NGINX 配置为反向代理,请参阅 Google Cloud 平台上 NGINX Plus 的所有活动高可用性。
后续步骤
现在,您已将 NGINX 服务器配置为将 TLS 分流到 Cloud HSM。