以前「Kong GatewayをProxy経由で利用する」というタイトルでForward Proxy Advanced Pluginを使っての接続方法を紹介した。
今回は逆方向でKongのコンポーネントを中に置き、外部のサービスに繋ぐようなケースを検証する。
社内Proxyが用意されていて、インターネットにアクセスする際にはそのProxy経由でないとアクセスできない会社は結構な数あると思う。
そういった会社の人がKong Gatewayを使う際に参考にしてもらえれば幸いである。
なお、今回はKonnectを使い、以下のような構成を検証する。
KonnectもKong Gatewayも基本的にはデプロイの仕方はそれほど変わらないので、Kong Gatewayで試す方はパラメータ設定部分などを上手く取り込んでもらえればと思う。
前提条件
以下の条件で検証する。
- ProxyはSquidを利用
- Data Plane、SquidはそれぞれAmazon Linux上に構築
- Data PlaneはDockerで構築
なお、以下は既に実施済みのものとする。
- EC2の払い出しやネットワーク設定
- KonnectのControl Plane作成
- EntraIDでのアプリケーション作成
構築・検証
以下の手順で構築・検証する。
- Proxyの構築
- Data Planeの構築
- 外部サービスとの接続
- OIDCとの連携確認
なお1の手順は前回記事のこちらと一緒なので割愛する。
Data Planeの構築
Dockerの有効化
Proxyのアドレスを環境変数に設定する。
export PROXY=http://172.31.66.0:3128
次に念の為Proxy経由で外部のサービスにアクセス出来ることを確認する。
$ curl -x http://172.31.66.0:3128 http://httpbin.org/user-agent
{
"user-agent": "curl/8.5.0"
}
問題なければ.bashrc
にProxyの環境変数を設定し、sourceコマンドで読み込む。
cat <<EOF >> ~/.bashrc
export HTTP_PROXY=$PROXY
export HTTPS_PROXY=$PROXY
export http_proxy=$PROXY
export https_proxy=$PROXY
export no_proxy="127.0.0.1,localhost"
export NO_PROXY="127.0.0.1,localhost"
EOF
. ~/.bashrc
これで先程のcurlなどの環境変数を参照するコマンドはProxyの指定なしで外部にアクセスできるようになる。
$ curl http://httpbin.org/user-agent
{
"user-agent": "curl/8.5.0"
}
次にDockerをインストールする。
今回はAmazon Linux 2023を使っているのでこちらの手順に従う。
sudo yum update -y
sudo yum install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
ログインしなおせばdocker ps
が正常に動作する。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
こちらの手順に従い、docker daemonがProxyを使えるようDocker側に設定を追加する。
sudo mkdir -p /etc/systemd/system/docker.service.d
cat <<EOF | sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=$HTTP_PROXY"
Environment="HTTPS_PROXY=$HTTPS_PROXY"
EOF
変更を反映しdaemonを再起動する。
sudo systemctl daemon-reload
sudo service docker restart
Kong Gatewayのイメージがpull出来ることを確認する。
docker pull kong/kong-gateway
Data Planeの構築
KonnectのWebUIにアクセスし、Gateway Manager
からControl Planeを選択後、Data Plane Nodes
->New Data Plane Node
からData Planeのデプロイ画面に遷移する。
PlatformでLinux (Docker)
を選択し、証明書を生成するとデプロイのためのdockerコマンドが表示されるのでこれをコピーする。
ここでProxyの設定を追加する。
ここでは以下のkong.confのパラメータを設定する。
-
proxy_server
:Proxyを利用する際のURLを指定 -
proxy_server_ssl_verify
:TLSの検証をするかどうか。ここではスキップするためoff
を指定。 -
cluster_use_proxy
:HybridモードでProxyを使う場合に指定。KonnectはHybridモード相当なのでon
を指定
Dockerでデプロイする場合、kong.confの設定はKONG_
を頭に付けて大文字にした環境変数を渡してあげることで設定できる。
そのため、以下のパラメータを追加してdocker runを実行すればよい
-e "KONG_PROXY_SERVER=$HTTPS_PROXY" \
-e "KONG_PROXY_SERVER_TLS_VERIFY=off" \
-e "KONG_CLUSTER_USE_PROXY=on" \
追加して起動すると無事にData Planeとして認識される。
外部サービスとの接続
Konnect上にService、Routeを作成し、Routeに対してForward Proxy Advanced Pluginを設定して外部サービスと通信できるか確認する。
ここではそれぞれのエンティティの作成はAPIを利用して行う。
API利用のため、最初にKonnectのトークン、ControlPlaneのID、KonnectのAPIエンドポイントをそれぞれ環境変数に設定する。
KONNECT_TOKEN=kpat_ER1WQxxxx
CP_ID=788397a0-b6f4-4dc8-a2f8-63cc6f0c62bb
KONNECT_API=https://us.api.konghq.com/v2
最初に外部サービスのhttpbin.orgと繋ぐためのエンティティServiceを作成する。
curl -s -X POST \
"${KONNECT_API}/control-planes/${CP_ID}/core-entities/services" \
-H "Authorization: Bearer $KONNECT_TOKEN" \
-d name=httpbin-service \
-d url=https://httpbin.org
作成時に表示されるServiceのIDを環境変数に設定する。
SERVICE_ID=75e92f55-5516-4173-8ad3-3491d6c51578
Proxy経由でService(httpbin.org)にアクセスするためのエンティティRouteを作成し、<ProxyのIP:Port>/httpbin
でアクセスできるよう設定する。
curl -s -X POST \
"${KONNECT_API}/control-planes/${CP_ID}/core-entities/routes" \
-H "Authorization: Bearer ${KONNECT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "httpbin-route",
"paths": ["/httpbin"],
"service": {
"id": "'"${SERVICE_ID}"'"
}
}'
作成したRouteのIDは後で使うので環境変数に設定しておく。
ROUTE_ID=0a8ca643-a2b2-4f1e-af17-fb39ce813b3c
Data Planeを構築したマシンからProxy経由で接続してみる。
$ curl -X GET -m 2 localhost:8000/httpbin
curl: (28) Operation timed out after 2002 milliseconds with 0 bytes received
今はForward Proxy Advanced Pluginの設定がないのでタイムアウトとなる。
Routeに対してForward Proxy Advanced Pluginを設定する。
curl -X POST \
"${KONNECT_API}/control-planes/${CP_ID}/core-entities/routes/${ROUTE_ID}/plugins" \
-H "Authorization: Bearer $KONNECT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "forward-proxy",
"config": {
"http_proxy_host": "172.31.66.0",
"http_proxy_port": 3128,
"https_proxy_host": "172.31.66.0",
"https_proxy_port": 3128,
"https_verify": false
}
}'
設定すると自動でプラグインが有効化されるので、再度curlを試してみる。
$ curl -X GET -m 2 localhost:8000/httpbin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>httpbin.org</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700"
rel="stylesheet">
:(省略)
無事通信出来た。
OIDCとの連携確認
最後におまけ的にOIDCとの連携も確認してみる。
OpenID Connect Pluginの設定にはProxyの設定があるので、これが使えるかの確認となる。
今回はEntraIDとの接続確認を行う。
EntraIDを使ったPlugin設定は過去に「APIの認証をEntra ID(旧Azure AD)で行う」で説明しているので今回は説明は大幅に省略して進める。
分からない部分は適宜そちらの記事を参照して欲しい。
Issuer、クライアントID、クライアントSecret、テナントIDを環境変数に設定する。
AZURE_ISSUER=https://login.microsoftonline.com/f177c1d6-50cf-49e0-818a-xxxxxx/v2.0
AZURE_CLIENT_ID=36cd0496-ab59-4ffd-8925-xxxxxx
AZURE_CLIENT_SECRET=U_u8Q~Jq3RRbYixxxxx
AZURE_TENANT_ID=$(sed "s@.*.com/\(.*\)/v2.0@\1@g" <<< "$AZURE_ISSUER")
次にリダイレクトURIを設定する。リダイレクト先は<ProxyのIP:Port>/<Routeのパス>
になる。
ENDPOINT=http://localhost:8000/httpbin
OIDC PluginをRouteに設定する。
curl -X POST \
"${KONNECT_API}/control-planes/${CP_ID}/core-entities/routes/${ROUTE_ID}/plugins" \
-H "Authorization: Bearer $KONNECT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "openid-connect",
"config": {
"issuer": "'"${AZURE_ISSUER}"'/.well-known/openid-configuration",
"issuers_allowed": [
"https://sts.windows.net/'"${AZURE_TENANT_ID}"'/",
"https://login.microsoftonline.com/'"${AZURE_TENANT_ID}"'/v2.0",
"https://login.windows.net/'"${AZURE_TENANT_ID}"'/v2.0"
],
"client_id": ["'"${AZURE_CLIENT_ID}"'"],
"client_secret": ["'"${AZURE_CLIENT_SECRET}"'"],
"redirect_uri": ["'"${ENDPOINT}"'"],
"display_errors": true,
"scopes": [
"openid",
"email",
"profile",
"'"${AZURE_CLIENT_ID}"'/.default"
],
"verify_parameters": false,
"http_proxy": "http://172.31.66.0:3128",
"https_proxy": "http://172.31.66.0:3128",
"authorization_endpoint": "https://login.microsoftonline.com/'"${AZURE_TENANT_ID}"'/oauth2/v2.0/authorize",
"token_endpoint": "https://login.microsoftonline.com/'"${AZURE_TENANT_ID}"'/oauth2/v2.0/token",
}
}'
前回記事と違う点として、http_proxy
とhttps_proxy
でProxyを指定しており、authorization_endpoint
とtoken_endpoint
でEntraIDの認可のエンドポイントとトークンのエンドポイントを指定している点である。
これ、試行方法によってエラーが出たり出なかったりして、必須なのかがよく分かっていないが、付けておけばとりあえず問題ないと思う。
なお、指定しなかった場合は以下のようなエラーが出る。
{"message":"An unexpected error occurred (authorization endpoint was not specified)"}
以上でOIDC認証をProxy経由で利用できる。
設定後、curlで動作確認する。
curlで確認する場合はトークンが必要なので以下で発行する。
BEARER_TOKEN=$(curl -X POST "https://login.microsoftonline.com/${AZURE_TENANT_ID}/oauth2/v2.0/token" \
--data scope="${AZURE_CLIENT_ID}/.default" \
--data grant_type="client_credentials" \
--data client_id="${AZURE_CLIENT_ID}" \
--data client_secret="${AZURE_CLIENT_SECRET}" \
| jq -r '.access_token')
発行したトークンを使ってアクセスする。
$ curl -s $ENDPOINT/user-agent -H "Authorization: Bearer $BEARER_TOKEN"
{
"user-agent": "curl/8.5.0"
}
問題なくアクセスできた。
またトークンがないとアクセスできないので、OIDC Plugin連携も適切に設定されていることが分かる。
おわりに
今回は閉鎖環境でData Planeを構築し、Forward Proxy Advanced PluginやOpenID Connect Pluginを使って外部のサービスにアクセスしてみた。
Proxyの設定箇所がコンポーネントごとに出てきて手間ではあるが、設定すればProxy経由でも問題なく動作することが確認できた。
自社のProxyのせいでなかなかKong Gatewayの検証が出来なかった人はこちらの記事を参考に試していただければ幸いである。