API通信におけるセキュリティは、システムの信頼性を保つ上で非常に重要です。本記事では、Kong API Gatewayを使用して、mTLS(Mutual TLS、相互TLS)を設定する方法を詳しく解説します。特に、「Client -> Kong」と「Kong -> Upstream API」の2つの通信パスでのmTLSの設定方法について取り上げます。

mTLSの基礎知識

mTLSとは、TLS(Transport Layer Security)を拡張したプロトコルで、通信の両側(クライアントとサーバー)が互いに証明書を使って認証を行います。通常のTLSはサーバー側の認証だけを行いますが、mTLSでは以下のようなプロセスが追加されます:

  1. サーバー認証:クライアントは、サーバーが信頼できる証明書を持っていることを確認します。
  2. クライアント認証:サーバーは、クライアントが信頼できる証明書を持っていることを確認します。

image.png

この双方向の認証により、より安全な通信が実現します。

Kong API Gatewayで実現するmTLS通信

Kong API Gatewayを使えば、以下の2つの通信経路でmTLSを簡単に実現できます:

  • クライアント → Kong API Gateway
  • Kong API Gateway → Upstream API

image.png

Client->KongのmTLS設定

クライアントからKong API Gatewayへの通信にmTLSを実装するには、Kongの「mTLS Plugin」を使用します。以下は手順の概要です。

  1. 管理者がクライアント認証用のCA証明書をKongに設定
  2. クライアントはリクエスト時に自分の証明書をKongに提示
  3. Kongがクライアント証明書を検証し、安全な通信を許可

CA証明書を登録

Clientの証明書を検証するためのCA証明書をvalutに登録

1
2
3
4
5
6
7
8
9
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プラグインを有効化します。ここではグローバル範囲に指定しています。

1
2
3
4
5
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フラグを追加する必要があります。

1
curl https://<PROXY_URL>:8443/mtls --key client.key --cert client.crt -k
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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": "[email protected]",
        "X-Consumer-Id": "35cfdf1b-11ef-4582-b80f-a0cfb1d67b07",
        "X-Consumer-Username": "[email protected]",
        "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 証明書も一緒に送ります。

1
2
3
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を導入してみてください。