如何使用Vault在APISIX中管理证书

Junduo Dong

Junduo Dong

June 9, 2023

Technology

APIゲートウェイは、APIライフサイクル管理における重要な基本コンポーネントです。すべてのトラフィックの入り口であり、下流のクライアントからのAPIリクエストを正しい上流サービスにルーティングして処理する役割を担っています。したがって、APIゲートウェイは、上流サービスと下流クライアント間のネットワーク通信を担当します。

新しいクラウドネイティブAPIゲートウェイであるApache APISIXは、下流クライアントとAPISIX間、およびAPISIXと上流サービス間のTLS/mTLS通信メカニズムを提供し、それらの間のネットワークセキュリティを確保します。APISIXはSSL証明書をSSL証明書オブジェクトとして保存し、TLSプロトコルをサポートする拡張SNI(Server Name Indication)を通じてSSL証明書の動的ロードを実現します。

APISIXにSSL証明書を安全に保存するために、APISIXはHashiCorp Vaultとの統合を実現し、Vaultの秘密情報セキュリティストレージを活用してSSL証明書の統一管理を実現します。この記事では、下流クライアントとAPISIX間のHTTPS通信を設定する例として、APISIXがVaultを統合してSSL証明書管理を実装する方法を紹介します。

APISIXとVaultの統合

SSL証明書とは

SSL/TLSは、通信する二者間で暗号化されたネットワーク接続を確立することで、ネットワーク通信のセキュリティを保護する暗号化プロトコルです。SSL/TLSプロトコルは、ユーザーとサーバーを認証することで、データが正しいクライアントとサーバーに送信されることを保証します。さらに、SSL/TLSプロトコルは通信データを暗号化し、データが送信中に盗まれたり、改ざんされたり、偽造されたりしないようにします。

SSL証明書は、ウェブサイトの身元を認証し、SSL/TLSプロトコルを使用して暗号化された接続を可能にするデジタル証明書です。SSL証明書は通常、信頼できるデジタル証明機関(CA)によって発行され、主に以下の情報を含みます:

  • ドメイン名
  • 証明機関
  • 証明機関によって署名されたデジタル署名
  • 関連するサブドメイン
  • 証明書の発行日
  • 証明書の有効期限
  • 公開鍵(秘密鍵は秘密鍵)

HashiCorp Vaultとは

HashiCorp Vault(以下、Vault)は、トークン、パスワード、証明書などの機密データを保存および管理するエンタープライズレベルのシークレット管理ツールです。Vaultは、ITシステム全体の技術と統合でき、IDベースのセキュリティ自動化と暗号化サービスを提供し、機密データとシステムへのアクセスを集中管理し、組織がデータ漏洩やデータ露出のリスクを軽減し、クラウドとアプリケーションのセキュリティを向上させるのに役立ちます。

HashiCorp Vault

APISIX SSL証明書をVaultに保存する方法

環境準備

Vaultサービスのデプロイと設定

このセクションでは、Dockerを使用してVaultコンテナサービスをデプロイします。環境に既にVaultサービスインスタンスが利用可能な場合は、このセクションをスキップできます。

DevモードでVaultコンテナを作成およびデプロイし、apisix-quickstart-vaultという名前を付けます。Vaultトークンをapisix-quickstart-vault-tokenとし、ポート8200をホストにマッピングします:

docker run -d --cap-add=IPC_LOCK \
  -e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' \
  -e 'VAULT_ADDR=http://0.0.0.0:8200' \
  -e 'VAULT_DEV_ROOT_TOKEN_ID=apisix-quickstart-vault-token' \
  -e 'VAULT_TOKEN=apisix-quickstart-vault-token' \
  --network=apisix-quickstart-net \
  --name apisix-quickstart-vault \
  -p 8200:8200 vault:1.13.0

APISIX SSL証明書の保存パスとしてkvを選択します:

docker exec apisix-quickstart-vault vault secrets enable -path=kv -version=1 kv

APISIXの設定

APISIXはVaultからSSL証明書を読み取る必要があるため、Vaultは指定されたパスに対するAPISIXの読み取り権限を付与する必要があります。

apisix-policy.hclという名前のVaultポリシーを作成し、APISIXにkv/apisix/パスへの読み取りアクセスを許可します:

docker exec apisix-quickstart-vault /bin/sh -c "echo '
path \"kv/apisix/*\" {
    capabilities = [\"read\"]
}
' > /etc/apisix-policy.hcl"

作成したポリシーファイルapisix-policy.hclをVaultに適用します:

docker exec apisix-quickstart-vault vault policy write apisix-policy /etc/apisix-policy.hcl

Vault接続情報と証明書保存パスを保存するために、quickstart-secret-idというIDのAPISIXシークレットオブジェクトを作成します:

curl -i "http://127.0.0.1:9180/apisix/admin/secrets/vault/quickstart-secret-id" -X PUT -d '
{
    "uri": "http://apisix-quickstart-vault:8200",
    "prefix": "kv/apisix",
    "token" : "apisix-quickstart-vault-token"
}'

SSL証明書をVaultに保存

自己署名CA証明書ca.crtとキーca.keyを作成します:

openssl genrsa -out ca.key 2048 && \
  openssl req -new -sha256 -key ca.key -out ca.csr -subj "/CN=ROOTCA" && \
  openssl x509 -req -days 36500 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.crt

CAによって発行されたSSL証明書server.crtとキーserver.keyを作成し、その共通名(CN)はtest.comです:

openssl genrsa -out server.key 2048 && \
  openssl req -new -sha256 -key server.key -out server.csr -subj "/CN=test.com" && \
  openssl x509 -req -days 36500 -sha256 -extensions v3_req \
  -CA ca.crt -CAkey ca.key -CAserial ca.srl -CAcreateserial \
  -in server.csr -out server.crt

発行されたSSL証明書とキーをVaultコンテナにコピーします:

docker cp server.key apisix-quickstart-vault:/root/
docker cp server.crt apisix-quickstart-vault:/root/

vault kv putコマンドを使用して、SSL証明書とキーをシークレットとして保存し、キーはssl、保存パスはkv/apisixです:

docker exec apisix-quickstart-vault vault kv put kv/apisix/ssl test.com.crt=@/root/server.crt test.com.key=@/root/server.key

上記のコマンドにより、Vaultにsslという名前のシークレットを保存しました。これには2つのキーと値のペアが含まれています:証明書と秘密鍵。

Vaultに保存されたAPISIX SSL証明書の使用方法

APISIXは、下流クライアントとAPISIX間、およびAPISIXと上流サービス間のTLS/mTLSネットワーク暗号化をサポートしており、Vaultに保存されたSSL証明書を使用できます。クライアントとAPISIX間のHTTPS通信を設定する例として、APISIXでVaultに保存されたSSL証明書を使用する方法をデモンストレーションします。

クライアントとAPISIX間のHTTPS通信を設定

SSL証明書を保持するSSL証明書オブジェクトを作成します:

curl -i "http://127.0.0.1:9180/apisix/admin/ssls" -X PUT -d '
{
  "id": "quickstart-tls-client-ssl",
  "sni": "test.com",
  "cert": "$secret://vault/quickstart-secret-id/ssl/test.com.crt",
  "key": "$secret://vault/quickstart-secret-id/ssl/test.com.key"
}'

このオブジェクトのsnitest.comで、証明書の発行時のCNと一致します。certkeyは発行された証明書と秘密鍵に対応し、確立されたシークレットリソースロケーターを通じてVaultから自動的に取得されます。リソースロケーターのルールは以下の通りです:

$secret://$manager/$id/$secret_name/$key
  • manager: キー管理サービスVault
  • id: APISIXシークレットリソースID
  • secret_name: Vault内のシークレット名
  • key: secret_nameという名前のシークレット内のキーと値のペアのキー

クライアントとAPISIX間のHTTPS通信を検証

/ipに送信されたすべてのリクエストを上流のhttpbin.orgに転送するルートを作成します:

curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT -d '
{
  "id": "quickstart-client-ip",
  "uri": "/ip",
  "upstream": {
    "nodes": {
      "httpbin.org:80":1
    },
    "type": "roundrobin"
  }
}'

cURLを使用してhttps://test.com:9443/ipにリクエストを送信します。test.com127.0.0.1に解決されます:

curl -ikv --resolve "test.com:9443:127.0.0.1" "https://test.com:9443/ip"

設定が成功した場合、cURLによって返されるクライアントとAPISIX間のTLSハンドシェイクプロセスは以下の結果と同じになります:

* Added test.com:9443:127.0.0.1 to DNS cache
* Hostname test.com was found in DNS cache
*   Trying 127.0.0.1:9443...
* Connected to test.com (127.0.0.1) port 9443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=test.com
*  start date: Apr 21 07:47:54 2023 GMT
*  expire date: Mar 28 07:47:54 2123 GMT
*  issuer: CN=ROOTCA
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x556274d632e0)
> GET /ip HTTP/2
> Host: test.com:9443
> user-agent: curl/7.74.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
HTTP/2 200
...

まとめ

APISIXがVaultを統合してSSL証明書管理を実装する方法を紹介し、下流クライアントとAPISIX間のHTTPS通信を例として設定と統合の手順を詳細に説明しました。

APISIXにおけるSSL証明書の関連概念と使用シナリオについては、以下の記事を参照してください:

Tags: