本指南說明如何設定 NGINX,在 Debian 11 (Bullseye) 上使用 Cloud HSM 金鑰進行 TLS 卸載。您可能需要修改這些指令,才能在 OS 或 Linux 發行版本中運作。
您可以在 kms-solutions GitHub 存放區中,找到以 Terraform 為基礎的本教學課程藍圖版本。
用途
使用 Cloud HSM 金鑰搭配 NGINX 進行 TLS 卸載,有助於滿足下列企業安全需求:
- 您希望 NGINX 網路伺服器將 TLS 加密編譯作業卸載至 Cloud HSM。
- 您不希望將憑證的私密金鑰儲存在託管網路應用程式的 Compute Engine 執行個體本機檔案系統中。
- 您需要符合法規要求,因為公開應用程式的憑證必須受到通過 FIPS 140-2 第 3 級認證的 HSM 保護。
- 您想使用 NGINX 建立具有 TLS 終止功能的反向 Proxy,保護網頁應用程式。
事前準備
繼續操作前,請先完成「使用 OpenSSL 搭配 Cloud HSM 金鑰」中的步驟。
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 VM,並按照以下步驟進行設定:
- 選取您先前建立的正確服務帳戶。
- 選取您先前建立的網路。
- 為所有防火牆規則新增適當的標籤。
- 確認子網路的「外部 IP」欄位設為
none。
在執行個體上,授予身分「受 IAP 保護的通道使用者」角色 (
roles/iap.tunnelResourceAccessor)。- 詳情請參閱「Compute 的 IAP 設定」。
建立及設定 Cloud HSM 簽署金鑰
接下來的章節會詳細說明建立及設定 Cloud HSM 簽署金鑰的必要步驟。
建立 Cloud HSM 代管的簽署金鑰
在專案中,於先前為 OpenSSL 設定的金鑰環中,建立 Cloud HSM EC-P256-SHA256 簽署金鑰:Google Cloud
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 連線至 VM
使用下列指令,透過 SSH 和 IAP 連線至 VM:
gcloud compute ssh INSTANCE \
--zone ZONE --tunnel-through-iap
如果遇到問題,請確認您是否使用了 --tunnel-through-iap 標記。
此外,請確認您在執行個體上擁有「受 IAP 保護的通道使用者」(roles/iap.tunnelResourceAccessor) 角色,可供透過 gcloud CLI 驗證的身分使用。
使用 OpenSSL 建立憑證
如果是實際工作環境,請建立憑證簽署要求 (CSR)。請參閱範例,進一步瞭解如何產生 CSR。將 CSR 提供給憑證授權單位 (CA),讓他們為您建立憑證。在後續章節中,請使用 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:用於識別金鑰的 ID 類型。 如要使用最新金鑰版本,請搭配金鑰名稱使用pkcs11:object。如要使用特定金鑰版本,請搭配金鑰版本的完整資源 ID 使用pkcs11:id。KEY_IDENTIFIER:金鑰的 ID。如果您使用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 做為反向 Proxy 使用,並進行負載平衡,請考慮更新 NGINX 設定檔。如要進一步瞭解如何將 NGINX 設定為反向 Proxy,請參閱平台上的「All-Active HA for NGINX Plus」 Google Cloud。
後續步驟
您已將 NGINX 伺服器設為使用 TLS 卸載功能,將流量導向 Cloud HSM。