0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kong Gatewayとサービス間のmTLS通信を検証する

0
Posted at

Kong GatewayではmTLSで通信を行う際、以下のように行うことができる。

  • クライアントとKong GW間:mTLS Pluginで実施
  • Kong GWとサービス間:Serviceの機能で実施

これについては過去に@xibukaさんがKong Gateway入門 - mTLS対応で解説しているが、今回Kong GWとサービス間のmTLS通信についてもう少し踏み込んで検証してみる。

今回は以下の手順で検証を行う。

  1. 証明書の準備
  2. サービス側(Nginx)の設定
  3. Kong設定
  4. テスト

検証環境

今回はローカル環境(MacOS)にコンテナを使ってKong GatewayおよびmTLSを要求するサービス(Nginx)を用意する。
Kong Gatewayは3.10で検証した。
また利用する証明書は自己署名証明書を利用する。

1. 証明書の準備

まずサービス側、Kong側それぞれを認可するためのCA証明書を作成する。

mkdir certs
cd certs
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.crt -subj "/CN=My-Private-CA"

次にサービス側の証明書を作成し、CA証明書を使って署名する。

openssl genrsa -out service.key 2048
openssl req -new -key service.key -out service.csr -subj "/CN=backend-service"
openssl x509 -req -in service.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out service.crt -days 365 -sha256

同様にKong側の証明書を作成し、CA証明書を使って署名する。

openssl genrsa -out kong-client.key 2048
openssl req -new -key kong-client.key -out kong-client.csr -subj "/CN=kong-client"
openssl x509 -req -in kong-client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kong-client.crt -days 365 -sha256

2. サービス側の設定

次にNginxの設定を行う。以下でディレクトリを作成して設定ファイルを格納する。

cd -
mkdir nginx
cat << 'EOF' > nginx/default.conf
log_format mtls_debug '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      'client_cert_subject="$ssl_client_s_dn" ' 
                      'client_cert_verify="$ssl_client_verify"';

server {
    listen 443 ssl;
    server_name backend-service;

    ssl_certificate     /etc/nginx/certs/service.crt;
    ssl_certificate_key /etc/nginx/certs/service.key;
    ssl_verify_client on;
    ssl_client_certificate /etc/nginx/certs/ca.crt;

    access_log /var/log/nginx/access.log mtls_debug;

    location / {
        add_header Content-Type text/plain;
        return 200 "mTLS Connection Successful!\n";
    }
}
EOF

ポイントとしては、ssl_verify_client on;でクライアント証明書の検証を有効化し、ssl_client_certificateで信頼するCA証明書を指定している点である。
これによって、Kongからの接続時にクライアント証明書が提示され、その証明書が指定したCAで署名されているかが検証できる。
またログから証明書の検証の結果が分かるようにログフォーマットを変更している。

3. Kong設定

次にKong Gatewayの設定を行う。
今回はKong GatewayとNginxをdocker composeで立ち上げて、その後にdeckを使ってService/RouteとmTLS Pluginの設定を行う。
まずKong GatewayとNginxサービスを起動するためのdocker-compose.ymlを作成する。

cat << 'EOF' > docker-compose.yml
x-default: &default
  networks:
    - kong-net
  restart: on-failure
  platform: linux/arm64

x-kong-env: &kong-env
  KONG_DATABASE: postgres
  KONG_PG_HOST: kong-database
  KONG_PG_PASSWORD: kongpass
  KONG_PG_USER: kong

networks:
  kong-net:
    driver: bridge

services:
  kong-database:
    <<: *default
    image: postgres:16
    container_name: kong-database
    ports:
      - "5432:5432"
    restart: unless-stopped
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: kongpass
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "kong"]
      interval: 5s
      timeout: 5s
      retries: 5

  kong-bootstrap:
    <<: *default
    image: kong/kong-gateway:3.10
    container_name: kong-bootstrap
    depends_on:
      kong-database:
        condition: service_healthy
    environment:
      <<: *kong-env
    command: kong migrations bootstrap

  kong:
    <<: *default
    image: kong/kong-gateway:3.10
    container_name: kong-gateway
    user: "root"
    depends_on:
      kong-bootstrap:
        condition: service_completed_successfully
    environment:
      <<: *kong-env
      KONG_PROXY_LISTEN: 0.0.0.0:8000
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
      KONG_LICENSE_DATA: ${KONG_LICENSE_DATA}
      KONG_LOG_LEVEL: debug
    volumes:
      - ${PWD}/certs:/etc/kong/certs:ro
    ports:
      - "8000:8000"
      - "8001:8001"
      - "8002:8002"

  backend-service:
    <<: *default
    image: nginx:latest
    container_name: backend-service
    volumes:
      - ${PWD}/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ${PWD}/certs:/etc/nginx/certs:ro
    ports:
      - "8443:443"
EOF

ここでは先程作った証明書と設定ファイルをNginxコンテナにマウントして読み込ませている。
platform: linux/arm64の部分はMac以外の人は要変更となる。
ライセンスファイルの内容をKONG_LICENSE_DATAに設定して起動する。

export KONG_LICENSE_DATA=$(cat ~/license.json) 
docker-compose up -d

起動後、以下のようにlocalhost:8000にアクセスしてKong Gatewayが起動していることを確認する。

$ curl localhost:8000/httpbin
{
  "message":"no Route matched with those values",
  "request_id":"d0c541735f24db1e62b83a339281d203"
}

次にService/Routeを作成する。
deckのYAMLを格納するディレクトリを作成する。

mkdir kong

次に証明書の内容を環境変数に設定する。これは後ほどdeckのYAMLに埋め込む際に利用する。

CA_CERT=$(cat certs/ca.crt | sed '      s/^/      /')
KONG_CERT=$(cat certs/kong-client.crt | sed '      s/^/      /')
KONG_KEY=$(cat certs/kong-client.key | sed '      s/^/      /')

同様に証明書のUUIDも設定する。通常はGW側に採番してもらうが、事前に設定しておくことでServiceに紐付けやすくなる。

MY_CA_ID="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
MY_CERT_ID="11111111-2222-3333-4444-555555555555"

証明書をKong Gatewayに登録するためのYAMLを作成する。

cat << EOF > kong/mtls-cert.yaml
_format_version: "3.0"

# 1. 信頼するCAの登録(KongがNginxを検証する場合に使用)
ca_certificates:
  - id: $MY_CA_ID
    cert: |
$CA_CERT

# 2. Kong自身の証明書の登録(mTLSでNginxに提示する用)
certificates:
  - id: $MY_CERT_ID
    cert: |
$KONG_CERT
    key: |
$KONG_KEY
EOF

次にService/Routeも作成する。
Serviceでは先程定義した証明書の各IDを指定してmTLS通信を行うように設定する。

cat << EOF > kong/mtls-service.yaml
_format_version: "3.0"
services:
  - name: mtls-service
    url: https://backend-service:443
    # 提示する証明書のIDを指定
    client_certificate: $MY_CERT_ID
    # 必要に応じて、Kong側でもバックエンドを検証する場合
    ca_certificates:
      - $MY_CA_ID
    tls_verify: true
    routes:
      - name: mtls-route
        paths:
          - /test
EOF

設定を適用する。

deck gateway apply kong/

4. テスト

まず、Nginxに直接アクセスしてmTLSが有効になっていることを確認する。

curl -k https://localhost:8443/

証明書を渡していないのでエラーとなる。

<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.29.0</center>
</body>
</html>

Nginxのログも以下のように証明書に関連する部分がNONEとなっている。

172.18.0.1 - - [26/Jan/2026:05:47:34 +0000] "GET / HTTP/1.1" 400 237 client_cert_subject="-" client_cert_verify="NONE"

証明書を渡してアクセスしてみる。

curl -k --cert certs/kong-client.crt --key certs/kong-client.key https://localhost:8443/

結果は以下のようになった。

mTLS Connection Successful!

ログ出力は以下のようになった。

172.18.0.1 - - [26/Jan/2026:05:49:00 +0000] "GET / HTTP/1.1" 200 28 client_cert_subject="CN=kong-client" client_cert_verify="SUCCESS"

次にKong Gatewayからアクセスしてみる。

curl http://localhost:8000/test

証明書は指定しなかったが、以下のように成功した。

mTLS Connection Successful!

これはKong GatewayがNginxに対してmTLS通信を行い、正常に接続できたことを示している。
Nginxのログも以下のように証明書が正しく検証されzていることが分かる。

172.18.0.4 - - [26/Jan/2026:05:49:30 +0000] "GET / HTTP/1.1" 200 28 client_cert_subject="CN=kong-client" client_cert_verify="SUCCESS"

以上より、サービス側からも証明書の検証が正常に行われていることが確認できた。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?