API通信におけるセキュリティは、システムの信頼性を保つ上で非常に重要です。本記事では、Kong API Gatewayを使用して、mTLS(Mutual TLS、相互TLS)を設定する方法を詳しく解説します。特に、「Client -> Kong」と「Kong -> Upstream API」の2つの通信パスでのmTLSの設定方法について取り上げます。
mTLSの基礎知識
mTLSとは、TLS(Transport Layer Security)を拡張したプロトコルで、通信の両側(クライアントとサーバー)が互いに証明書を使って認証を行います。通常のTLSはサーバー側の認証だけを行いますが、mTLSでは以下のようなプロセスが追加されます:
- サーバー認証:クライアントは、サーバーが信頼できる証明書を持っていることを確認します。
- クライアント認証:サーバーは、クライアントが信頼できる証明書を持っていることを確認します。
この双方向の認証により、より安全な通信が実現します。
Kong API Gatewayで実現するmTLS通信
Kong API Gatewayを使えば、以下の2つの通信経路でmTLSを簡単に実現できます:
- クライアント → Kong API Gateway
- Kong API Gateway → Upstream API
Client->KongのmTLS設定
クライアントからKong API Gatewayへの通信にmTLSを実装するには、Kongの「mTLS Plugin」を使用します。以下は手順の概要です。
- 管理者がクライアント認証用のCA証明書をKongに設定
- クライアントはリクエスト時に自分の証明書をKongに提示
- Kongがクライアント証明書を検証し、安全な通信を許可
CA証明書を登録
Clientの証明書を検証するためのCA証明書をvalutに登録
curl http://localhost:8001/ca_certificates -F cert=@ca.crt
{
"cert": "<PEM_CERT>",
"id": "c383d81a-bffc-4e2a-b0d3-ac56b441a07b",
"cert_digest": "3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c",
"tags": null,
"created_at": 1607347576
}
mTLSプラグインを有効化
先ほど作ったca_certificateを利用して、mTLSプラグインを有効化します。ここではグローバル範囲に指定しています。
curl --request POST \
--url http://localhost:8001/plugins \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data name=mtls-auth \
--data config.ca_certificates=c383d81a-bffc-4e2a-b0d3-ac56b441a07b
このタイミングで、clientの証明書なしでアクセスすると、HTTP/1.1 401 Unauthorized
のエラーが返ってくるはず。
client証明書ありでのアクセス
mTLSは相互TLS認証を意味するため、アクセスする際にはHTTPS
プロトコルを使用する必要があります。もしKong側のTLS証明書が自己署名証明書である場合、証明書の検証をスキップするために-k
フラグを追加する必要があります。
curl https://<PROXY_URL>:8443/mtls --key client.key --cert client.crt -k
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 752
Content-Type: application/json
Date: Fri, 20 Dec 2024 15:14:38 GMT
Server: gunicorn/19.9.0
Via: 1.1 kong/3.9.0.0-enterprise-edition
X-Kong-Proxy-Latency: 9
X-Kong-Request-Id: ada6f204577fe50a144706292a01f421
X-Kong-Upstream-Latency: 8
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Host": "httpbin.backends:8080",
"Kong-Request-Id": "e8560956-1bdf-491b-aa05-f962db06adcd",
"User-Agent": "HTTPie/3.2.4",
"X-Consumer-Custom-Id": "demo@apim.eu",
"X-Consumer-Id": "35cfdf1b-11ef-4582-b80f-a0cfb1d67b07",
"X-Consumer-Username": "demo@apim.eu",
"X-Forwarded-Host": "localhost",
"X-Forwarded-Path": "/mtls-auth",
"X-Forwarded-Prefix": "/mtls-auth",
"X-Kong-Request-Id": "ada6f204577fe50a144706292a01f421"
},
"json": null,
"method": "GET",
"origin": "192.168.65.1",
"url": "https://localhost/anything"
}
Kong->upstream APIのmTLS設定
Kong側がAPIにアクセスする際、Upstream API側がclientの証明書を求めています。そのため、Kong側でクライアントとしての証明書を登録する必要があります。登録の手法が二つありまして、Kong全体での登録と、Service単位の登録
Kong全体での登録
設定ファイルに、以下の三つのパラメータを追加します。KongがAPIにリクエストを送るときにclient 証明書も一緒に送ります。
client_ssl = on
client_ssl_cert = /etc/secrets/my-kong-certificate/kong.crt
client_ssl_cert_key = /etc/secrets/my-kong-certificate/kong.key
Service単位での登録
Serviceを作る際に、client_certificate
でclient 証明書を追加することができます。
優先順位として、Service単位>Kong全体になるため、両方設定した場合は、 Service単位の方が使われます。
まとめ
mTLSを適切に設定することで、API通信のセキュリティを大幅に向上させることができます。本記事では、「Client -> Kong」と「Kong -> Upstream API」の2つの通信経路における設定方法を紹介しました。
安全なAPI通信を実現するために、以下のポイントを押さえてください:
- クライアント認証用のCA証明書を適切に管理する
- KongとUpstream APIの間でクライアント証明書を正しく設定する
- Kong全体の設定とサービス単位の設定を用途に応じて使い分ける
図を参考にしながら、ぜひ自分の環境にmTLSを導入してみてください。