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のAdmin APIをKong Gateway自身で保護する

Last updated at Posted at 2025-01-22

Kong GatewayのAdmin APIはKong GatewayをAPIで操作することが出来る強力な機能であるが、強力が故に保護したいと考えることもあると思う。
前段にWAF/LBを置いて保護することも出来るが、設定次第ではKong Gateway自身でAdmin APIを保護することも出来る。
ここではそのやり方を紹介する。

仕組み

まず基礎知識としてKong Gatewayで提供されるProxy機能とAdmin API機能は同一のバイナリで提供され、待受ポートによって役割を変えている。
20250122095845.png

また、Admin APIはどのIPで待ち受けるかはkong.confのadmin_listenで指定する。

これを組み合わせると以下のような感じでProxy経由の通信のみ受け付け、その他の呼び出しは受け付けないようにすることが出来る。
20250122100533.png

更にはProxy経由なので、PluginなどのKong Gatewayの機能も付与することが出来る。
これによってAdmin APIに認証を追加したり、レート制限を掛けたり、様々な設定を追加することが可能となる。

検証

ここではdockerを使って起動し、動作確認してみる。
以下の手順でKong Gatewayを立ち上げる。

  1. DockerのNetworkを作成
  2. Postgresの起動
  3. DBの初期化
  4. Admin APIのためのService/Route設定をDBに書き込み
  5. Kong Gatewayを起動

Kong Gatewayの起動前にService/Route設定をDBに書き込んでいるのは、起動したタイミングで既にAdmin API用のServiceとRouteがないとAPIを叩こうにも叩きようがなくなるためである。

PostgresとKong Gatewayが接続できるようNetworkを作成する。

docker network create kong-net

Postgresを起動する。

docker run -d --name kong-database \
  --network=kong-net \
  -p 5432:5432 \
  -e "POSTGRES_USER=kong" \
  -e "POSTGRES_DB=kong" \
  -e "POSTGRES_PASSWORD=kongpass" \
  postgres:16

利用するKongのバージョンを環境変数に設定後、DBを初期化する。

VERSION=3.9.0.0
docker run --rm --network=kong-net \
 -e "KONG_DATABASE=postgres" \
 -e "KONG_PG_HOST=kong-database" \
 -e "KONG_PG_PASSWORD=kongpass" \
kong/kong-gateway:$VERSION kong migrations bootstrap

次にAdmin APIのService/Routeを定義する。
DB lessモードで起動する時に使うフォーマットで定義ファイルを作成する。

cat <<EOF > ./admin-api.yaml
_format_version: "3.0"
_transform: true

services:
- name: admin-api-service
  url: http://localhost:8001
  routes:
  - name: admin-api-route
    paths:
    - /admin-api
EOF

ここでは以下の仕様とした。

  • Service:
    • ホスト:http://localhost:8001
  • Routes:
    • パス:/admin-api

これにより、Proxyの/admin-apiにアクセスするとAdmin APIが利用できるようになる。
作成したYAMLを使ってDBに設定を反映する。
これにはkong config db_importコマンドを使う。

docker run --rm --network=kong-net \
 -v ./admin-api.yaml:/tmp/admin-api.yaml \
 -e "KONG_DATABASE=postgres" \
 -e "KONG_PG_HOST=kong-database" \
 -e "KONG_PG_PASSWORD=kongpass" \
 kong/kong-gateway:$VERSION kong config db_import /tmp/admin-api.yaml

なお、KongのService/Route設定を読ますのにdeclarative_configが使えそうと思ってしまうが、これはdatabase=offを指定した時のみ動作し、今回はDBありで検証しているため利用できない。

設定を反映したらKong Gatewayを起動する。

docker run -d --name kong-gateway \
 --network=kong-net \
 -e "KONG_DATABASE=postgres" \
 -e "KONG_PG_HOST=kong-database" \
 -e "KONG_PG_USER=kong" \
 -e "KONG_PG_PASSWORD=kongpass" \
 -e "KONG_ADMIN_LISTEN=localhost:8001" \
 -p 8000:8000 \
 -p 8001:8001 \
 kong/kong-gateway:$VERSION

KONG_ADMIN_LISTEN=localhost:8001を指定し、Admin APIのアクセス元を同一コンテナ内からのアクセスに限定している。
なお、ポート8001はProxy経由で使うので公開する必要はないが、外部からアクセスできないことを検証するために空けている。
以上で起動手順は終了となる。

確認

dockerの仕組みの話なので説明は割愛するが、dockerでポートをマッピングしてlocalhostにアクセスした時、ネットワークをブリッジしてアクセスするためコンテナ側から見るとlocalhostにはならない。
そのためlocalhost:8001にアクセスしてもadmin_listenで指定したアドレスと一致せずAdmin APIにはアクセスできない。

$ curl localhost:8001
curl: (52) Empty reply from server

Proxy経由でアクセスしてみる。

$ curl localhost:8000/admin-api
{"plugins":{"enabled_in_cluster":[],"available_on_server":{"redirect":true,"standard-webhooks":true,"ai-response-transformer":true,"ai-request-transformer":true,"ai-prompt-guard":true,
:(省略)

Proxy経由でのみアクセスできた。
追加で、Admin APIにレート制限を掛けてみる。

ADMIN_API=http://localhost:8000/admin-api
curl -X POST $ADMIN_API/services/admin-api-service/plugins \
    --data "name=rate-limiting" \
    --data "config.minute=3"

config.minute=3を指定し、1分間のアクセスの上限を3回まで
この状態でAdmin APIにcurlで5回連続でアクセスし、-wオプションを使ってステータスコードだけ表示する。

for((i=0;i<5;i++)); do curl -o /dev/null -s -w "%{http_code}\n" localhost:8000/admin-api; done

結果は以下となった。

200
200
200
429
429

4回目以降は429となってアクセスが禁止され、Admin APIにレート制限によって保護されたことが確認できた。

以上よりAdmin APIをKong Gatewayを使って保護できることが確認できた。

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?