🚪
API Gateway KongのOSS版管理画面(Kong Manager)をSSL化+Basic認証で外部からアクセス
TL;DR
- Kong外のnginxでSSL化+Basic認証
- Kong側も同一ホスト名でSSL化しておく
- Kong外nginx→Kong Managerへはホスト名でフォワーディング
背景
- Kongを外部からGUIで操作したい
- Kong Managerへは認証をかけたい
- オンプレでBasic以外のwebサイト認証の仕組みを独自に構築するのはハードルが高い
- ホスト環境を汚さないために全部Dockerで完結させたい
完成形イメージ
事前準備:Basic認証用.htpasswd作成
コマンド履歴にパスワードは残したくないので、環境変数にパスワードを指定しコンテナに渡して.httpasswdファイル作成
.passenv
HTPASSWD=Basic認証のパスワード
source ./.passenv && \
docker run \
--rm -it httpd:2.4.57-bookworm \
htpasswd -nb Basic認証のログインユーザー名 $HTPASSWD >> ./.htpasswd
./.htpasswd
Basic認証のパスワード:エンコード済パスワード
docker-compose用のKong・nginx共通.env作成
以下のような.envファイルを作成しておく。
.env
POSTGERS_DB=データベース名
POSTGERS_USER=データベースのログインユーザー名
POSTGERS_PASSWORD=データベースのログインパスワード
DB_DIR=データベースのデータ保存先ディレクトリ
CERTS_DIR=サーバー証明書のあるディレクトリ
KONG_HOST=外部公開用ホスト名
API_SSL_PORT=SSL接続API用ポート
ADMIN_SSL_PORT=管理機能SSL通信用ポート
ADMIN_GUI_SSL_PORT_INTERNAL=管理画面SSL通信用のコンテナ内部ポート
ADMIN_GUI_SSL_PORT_EXPOSE=管理画面SSL通信用の外部nginx向けホスト側ポート
NGINX_CONF_TMPL_PATH=Kong向け外部nginxの設定ファイルテンプレートのパス
HTPASSWD_PATH=.htpasswdファイルのパス
NGINX_INTERNAL_ADMIN_GUI_PORT=Kong向け外部nginxの、管理画面SSL通信用の内部ポート番号
サーバー証明書ディレクトリに 公開鍵:fullchain.pem、秘密鍵:privkey.pemを配置しておく。
また、外部からのアクセスの場合ADMIN_SSL_PORTで指定したポートの通信も一旦外に出るようなので、ポートを公開しておく必要がある。
Basic認証を有効にするnginx設定テンプレート作成
kong.conf.template
server {
listen ${NGINX_INTERNAL_KONG_GUI_PORT} ssl;
server_name ${KONG_HOST};
ssl_certificate /certs/fullchain.pem;
ssl_certificate_key /certs/privkey.pem;
location / {
auth_basic "Login required";
auth_basic_user_file /auth/.htpasswd;
set $redirect_to https://172.17.0.1:${KONG_GUI_PORT_EXPOSE};
set $internal_host $server_name:${KONG_GUI_PORT_INTERNAL};
add_header Reqested-Host $remote_addr;
proxy_redirect off;
proxy_pass $redirect_to;
proxy_set_header Host $internal_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $internal_host;
proxy_set_header X-Forwarded-Server $internal_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
Kong+nginx起動
docker-compose.yml
version: '3'
services:
kong-migrations:
image: kong:3.4.0-ubuntu
command: kong migrations bootstrap
environment:
KONG_DATABASE: postgres
KONG_PG_DATABASE: ${POSTGERS_DB}
KONG_PG_HOST: db
KONG_PG_USER: ${POSTGERS_USER}
KONG_PG_PASSWORD: ${POSTGERS_PASSWORD}
depends_on:
- db
deploy:
restart_policy:
condition: on-failure
kong:
image: kong:3.4.0-ubuntu
restart: always
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: db
KONG_PG_USER: ${POSTGERS_USER}
KONG_PG_PASSWORD: ${POSTGERS_PASSWORD}
KONG_REAL_IP_HEADER: X-Forwarded-For
KONG_PROXY_LISTEN: 0.0.0.0:${API_SSL_PORT} ssl
KONG_SSL_CERT: /certs/fullchain.pem
KONG_SSL_CERT_KEY: /certs/privkey.pem
KONG_ADMIN_LISTEN: 0.0.0.0:${ADMIN_SSL_PORT} ssl
KONG_ADMIN_SSL_CERT: /certs/fullchain.pem
KONG_ADMIN_SSL_CERT_KEY: /certs/privkey.pem
KONG_ADMIN_GUI_LISTEN: 0.0.0.0:${ADMIN_GUI_SSL_PORT_INTERNAL} ssl
KONG_ADMIN_GUI_URL: https://${KONG_HOST}:${ADMIN_GUI_SSL_PORT_INTERNAL}
KONG_ADMIN_GUI_PATH: /
KONG_ADMIN_GUI_SSL_CERT: /certs/fullchain.pem
KONG_ADMIN_GUI_SSL_CERT_KEY: /certs/privkey.pem
extra_hosts:
- "${KONG_HOST}:172.17.0.1"
ports:
- ${API_SSL_PORT}:${API_SSL_PORT}
- ${ADMIN_SSL_PORT}:${ADMIN_SSL_PORT}
- ${ADMIN_GUI_SSL_PORT_EXPOSE}:${ADMIN_GUI_SSL_PORT_INTERNAL}
volumes:
- ${CERTS_DIR}:/certs
depends_on:
- db
links:
- db
db:
image: postgres:12.16-bookworm
restart: always
environment:
POSTGRES_DB: ${POSTGERS_DB}
POSTGRES_USER: ${POSTGERS_USER}
POSTGRES_PASSWORD: ${POSTGERS_PASSWORD}
volumes:
- ${DB_DIR}:/var/lib/postgresql/data
nginx:
image: nginx:1.25.2-alpine3.18-slim
restart: always
command: /bin/sh -c "envsubst \
'$$KONG_HOST $$KONG_GUI_PORT_INTERNAL $$KONG_GUI_PORT_EXPOSE \
$$NGINX_INTERNAL_KONG_GUI_PORT\
' < /templates/kong.conf.template > /etc/nginx/conf.d/kong.conf; nginx -g 'daemon off;'"
environment:
KONG_HOST: ${KONG_HOST}
KONG_GUI_PORT_INTERNAL: ${ADMIN_GUI_SSL_PORT_INTERNAL}
KONG_GUI_PORT_EXPOSE: ${ADMIN_GUI_SSL_PORT_EXPOSE}
NGINX_INTERNAL_KONG_GUI_PORT: ${NGINX_INTERNAL_ADMIN_GUI_PORT}
ports:
- ${ADMIN_GUI_SSL_PORT_INTERNAL}:${NGINX_INTERNAL_ADMIN_GUI_PORT}
volumes:
- ${NGINX_CONF_TMPL_PATH}:/templates/kong.conf.template
- ${CERTS_DIR}:/certs
- ${HTPASSWD_PATH}:/auth/.htpasswd
depends_on:
- kong
command
docker compose up -d
Kong Manager(OSS版)にアクセス
データベースのマイグレーションが完了後、https://KONG_HOSTのホスト名:ADMIN_GUI_SSL_PORT_INTERNALのポート番号
にアクセスする。
※同一LAN内からアクセスする場合は以下参照。
ログインが求められる。
作成した.htpasswdのアカウントでログインすればKong Managerにアクセスできる。
Enterprise版とはデザインが異なる模様。
管理機能の通信がうまくできていないと「Gateway Services could not be retrieved
Data cannot be displayed due to an error.」といったエラーが出る。
この場合、エラー分類の詳細までは出してくれないので原因は地道に手当たり次第で調査していくしかない。
例えばポート番号やホスト名、証明書、名前解決などが正しく設定されているかを確認する。
なお、管理画面と管理機能で別ホスト名+別ホスト名用証明書を用いた場合でも上記エラーが出るので、おそらく外部公開と内部処理でホスト名は統一しなければならない模様。詳細不明。
参考
- Docker版Kong
Discussion