このガイドでは、Debian 11(Bullseye)での TLS オフロードに Cloud HSM 鍵を使用するように NGINX を設定する手順について説明します。OS または Linux ディストリビューションで動作するように、これらのコマンドの変更が必要になる場合があります。
このチュートリアルの Terraform ベースのブループリント バージョンは、kms-solutions GitHub リポジトリで確認できます。
ユースケース
TLS オフロードに NGINX で Cloud HSM 鍵を使用すると、次のエンタープライズ セキュリティのニーズに対応できます。
- NGINX ウェブサーバーで TLS 暗号オペレーションを Cloud HSM にオフロードする。
- 証明書の秘密鍵を、ウェブ アプリケーションをホストしている Compute Engine インスタンスのローカル ファイル システムに保存することを回避する必要がある場合。
- 一般向けのアプリケーションが、FIPS 140-2 レベル 3 認定取得済みの HSM で証明書を保護するために、規制要件を満たす必要がある場合。
- ウェブ アプリケーションを保護するために、NGINX を使用して TLS 終端型のリバース プロキシを作成する場合。
始める前に
続行する前に、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に設定されていることを確認します。
ID にインスタンスに対する IAP で保護されたトンネル ユーザー(
roles/iap.tunnelResourceAccessor)のロールを付与します。- 詳細については、コンピューティングの IAP 構成をご覧ください。
Cloud HSM 署名鍵を作成して構成する
以降のセクションでは、Cloud HSM 署名鍵を作成して構成するために必要な手順について詳しく説明します。
Cloud HSM でホストされる署名鍵を作成する
OpenSSL 用に構成済みのキーリングで、Google Cloud プロジェクトの 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 を使用して VM に接続する
次のコマンドを使用して、SSH と IAP を使用して VM に接続します。
gcloud compute ssh INSTANCE \
--zone ZONE --tunnel-through-iap
問題が発生した場合は、--tunnel-through-iap フラグを使用したことを確認してください。また、gcloud CLI で認証された ID のインスタンスに対する IAP で保護されたトンネル ユーザー(roles/iap.tunnelResourceAccessor)のロールがあることを確認します。
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を使用します。特定の鍵バージョンを使用するには、鍵バージョンの完全なリソース ID とともにpkcs11: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
Cloud HSM を使用するように NGINX を構成する
いくつかの NGINX ファイルを編集して、TLS オフロードを許可します。まず、/etc/nginx/nginx.conf ファイルを 2 か所で編集し、NGINX が PKCS #11 を使用するように構成するためのディレクティブをいくつか追加します。
event ブロックの後、http ブロックの前に、次のディレクティブを追加します。
ssl_engine pkcs11;
env KMS_PKCS11_CONFIG=/etc/nginx/pkcs11-config.yaml;
同じ /etc/nginx/nginx.conf ファイルで、Cloud HSM の証明書とその秘密鍵を使用するように SSL ディレクティブを構成します。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;
#...
#...
}
TLS トラフィックをリッスンするように NGINX を構成する
TLS トラフィックをリッスンするように /etc/nginx/sites-enabled/default ファイルを編集します。
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 鍵に対するオペレーションが表示されます。
ログを表示するには、 Google Cloud コンソールで Cloud Logging に移動します。使用しているプロジェクトに次のフィルタを追加します。
resource.type="cloudkms_cryptokeyversion"
クエリを実行すると、NGINX_KEY 鍵に対する非対称鍵オペレーションが表示されます。
オプションの構成
NGINX サーバーを外部 IP で公開するには、外部パススルー ネットワーク ロードバランサの作成が必要になる場合があります。
負荷分散でリバース プロキシとして NGINX を使用する必要がある場合は、NGINX 構成ファイルの更新を検討してください。NGINX をリバース プロキシとして構成する方法については、 Google Cloudプラットフォームでの NGINX Plus のオールアクティブ HA をご覧ください。
次のステップ
これで、Cloud HSM への TLS オフロードを使用するように NGINX サーバーが構成されました。