1
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?

APIの認証をEntra ID(旧Azure AD)で行う

Last updated at Posted at 2024-06-07

APIで認証を行う場合、アプリケーション側で作り込む方法もなくはないが、アプリケーション側で作り込むとAPIが乱立した際に個々に実装するのは手間でありメンテも大変なので、API Gateway側で認証を行うことが一般的である。
Kong GatewayをAPI Gatewayとして使った場合、OpenID Connectプラグイン(以下OIDCプラグイン)を使えば外部の認証サービスと連携して簡単にGateway側に認証の機能をもたせることが出来る。
今回はOIDCプラグインの設定方法や挙動の確認のために、素のnginxをEntra ID(旧Azure AD)の認証を使ってアクセスするようにしてみる。
なお、こちらのドキュメントを参考に検証した。

前提条件

以下があるものする。

  • Kong Gateway
  • サンプルアプリ&サービス
  • 上記のアプリ&サービスに対応するService・RouteをKong Gateway上で作成済み

今回サンプルアプリとサービスはKong Gatewayの通信の遅延箇所をJaegerで確認するの記事で使ったこちらのnginxを使用する。
なお、サービスはTLSで暗号化されている必要がある。
サンプルアプリのサービスについてブラウザでアクセスし証明書を確認すると、Let's Encryptを使った証明書で接続していることが確認できるのでこれで進める。
20240603101651.png

また、サンプルアプリのホスト名を後で使うため、ここで環境変数に設定しておく。

MYHOST=nginx.eks.hogehoge.com

※前の記事を読んでいないと分かりづらいが、このアドレスはProxyからアクセスするRoute設定であり、localhostに立てた場合はlocalhost:8000/<Routeのpath>部分になる。

事前準備

Entra IDの設定

OIDCプラグインを設定するにはEntra IDの以下の項目が必要となる。

  • Issuer
  • クライアントID(アプリケーションID)
  • クライアントSecret(シークレットIDに対応する値)

これらの値を取得するためにEntra 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

また、テナントIDが必要になるのでIssuerから引っこ抜く形で以下で設定しておく。

AZURE_TENANT_ID=$(sed "s@.*.com/\(.*\)/v2.0@\1@g" <<< "$AZURE_ISSUER")

OIDCプラグインの設定

Admin APIのエンドポイントを環境変数に設定する。

ADMIN_API=https://kong.hogehoge.com/api

サンプルアプリのServiceMYHOSTに対応するRouteのIDを取得する。

ROUTE_ID=$(curl -k -X GET ${ADMIN_API}/routes | jq -r --arg host "$MYHOST" '.data[] | select(.hosts != null) | select(.hosts[] == $host) | .id')

念の為値が入っているか確認する。

$ echo $ROUTE_ID
da7eea27-3de1-552b-8f18-xxxxx

公式の手順を参考にAdmin API経由でRouteに対してOIDCプラグインを有効化する。

curl -i -k -X POST ${ADMIN_API}/routes/${ROUTE_ID}/plugins \
  --data name="openid-connect" \
  --data config.issuer="${AZURE_ISSUER}/.well-known/openid-configuration" \
  --data config.issuers_allowed="https://sts.windows.net/${AZURE_TENANT_ID}/" \
  --data config.client_id="$AZURE_CLIENT_ID" \
  --data config.client_secret="$AZURE_CLIENT_SECRET" \
  --data config.redirect_uri="https://$MYHOST" \
  --data config.scopes="openid" \
  --data config.scopes="email" \
  --data config.scopes="profile" \
  --data config.scopes="${AZURE_CLIENT_ID}/.default" \
  --data config.verify_parameters="false"

なお、公式ドキュメントの手順だとconfig.issuers_allowedは含まれていないが、これを指定しないと以下のようなエラーが出る(log_leveldebugを指定しないと出力されないので注意)。

 invalid issuer (https://sts.windows.net/xxxxx/) was specified for access token, unknown error (not a table) was expected

これの回避策についてはこちらのナレッジに記載があり、これに従う形でパラメタconfig.issuers_allowedで追加している。

動作確認

ブラウザでの確認

ブラウザのキャッシュを削除し、先程と同じようにブラウザ経由でアクセスしてみる。

open https://$MYHOST

すると以下のようにMicrosoftの認証画面になる。
20240603114120.png

認証突破後、無事nginxの画面が見れればOK。
20240604150941.png

上記のようにただのnginxのアクセスに簡単にEntra IDの認証を設定することが出来た。

curlでの確認

APIの認証なのでcurlで出来ないとあまり意味がない。
ということでcurlでアクセスするためにIntra IDからアクセストークンを取得する。
グラントタイプをclient_credentialsでトークンを取得した。

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を実行する。最初はトークンなしで試してみる。

$ curl -i https://$MYHOST
HTTP/2 302
:(省略)

MSの認証サイトに飛ばされるので302が返る。
トークンをつけてみる。

$ curl -i https://$MYHOST -H "Authorization: Bearer $BEARER_TOKEN"
HTTP/2 200
:(省略)
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
:(省略)

無事アクセスできた。問題なさそうだ。

補足(追記)

この記事では手を抜いてconfig.issuers_allowedに1つのURLしか指定していないが、本来はKBにあるように3つ書いた方がいい。
この記事を書いてしばらく経った後に同じ手順で設定したところ、認証突破後に以下のエラーが表示されてUpstreamのサービスに接続できなかった。

{"message":"Unauthorized}

config.display_errors="true"を追加して再度プラグインを有効化してエラーを確認すると、以下のように表示されて記載漏れが確認できた。

{"message":"Unauthorized (required issuers were not found [ https://login.microsoftonline.com/f177c1d6-50cf-49e0-818a-xxxxxx/v2.0 ])"}

なので、issuers_allowedはちゃんと書こうというのと、config.display_errors="true"は開発環境とかであればとりあえず付けておくといいと思う。

1
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
1
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?