Envoy入門(その3)Auth0 認証
はじめに
マイクロサービスやWeb API界隈では、サービス間のネットワークの制御をライブラリではなく、プロキシのコンテナをサイドカーとして使うのだとか。そのデファクトスタンダード的な立ち位置なのが Envoy さん。
(その1)と(その2)は、Envoy のドキュメントが参照している Sandbox のコードを見ながら動かすというスタイルでしたが、今回は、より本番に近い設定を目指して、Auth0 と Envoy を組み合わせていきます。
やってみた
環境構築
Envoy
(その1)と(その2)は、Envoy さんのドキュメントの Sandbox のリポジトリを clone して、動かしながら、設定を読み解いてきましたが、Auth0 のものはありませんので、Sandbox さんの情報をコピーして、新たなリポジトリを作りました。(ま、パクリです)
Auth0
Auth0 さんです。
Sign up
Sign-up は、ここからやりました。今回は、上の GitHub に資材を残すので、Continue with GitHub
しましたが、お好きな方法で良いと思います。このパターンだと Auth0 と GitHub の画面を往復して、プロファイルの画面へ遷移します。
Accout Type
は Other
。日本のサブドメインにしたかったので、I need advanced settings
はチェックで Next
して、Tenant Domain
を take0a.jp.auth0.com
にして Create Account
しました。
Set up
Sign in して、Applications
の APIs
で Create API
します。
項目 | 値 |
---|---|
Name | Auth0 API for Envoy Blog |
Identifier | https://zenn.dev/take0a |
JSON Web Token (JWT) Profile | Auth0 |
JSON Web Token (JWT) Signing Algorithm | RS256 |
Create
すると、API の画面に遷移するので、Test
タブへ行った CURL
で必要な情報は、だいたい揃います。(... で省略してあります。自分のでやりましょう)
curl --request POST \
--url https://take0a.jp.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"KEt...Ny","client_secret":"FFl...j_","audience":"https://zenn.dev/take0a","grant_type":"client_credentials"}'
{
"access_token": "eyJ...Kw",
"token_type": "Bearer"
}
あとは、見つけにくいところで、Applications
の APIs
ではなくて、Applications
の Applications
から Settings
タブの一番下の方に Advanced Settings
というアコーディオンで隠したセクションがあるので、そこの Endpoints
タブへ行くと、あとで使う JSON Web Key Set
の URL を確認することができます。
take0a/envoy-samples/auth0
(その2)の復讐
環境構築のところで紹介したリポジトリを持ってくると、(その2)の外部認証がない状態で実行できます。
$ docker-compose pull
Pulling upstream-service ... done
Pulling front-envoy ... done
$ docker-compose up --build -d
Creating network "auth0_default" with the default driver
Creating auth0_upstream-service_1 ... done
Creating auth0_front-envoy_1 ... done
$ docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------------------------------------
auth0_front-envoy_1 /docker-entrypoint.sh /bin ... Up 10000/tcp, 0.0.0.0:8000->8000/tcp,:::8000->8000/tcp
auth0_upstream-service_1 python3 /code/service.py Up (healthy)
$ curl -v localhost:8000/service
* Trying [::1]:8000...
* Connected to localhost (::1) port 8000
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.3.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain; charset=utf-8
< content-length: 29
< date: Mon, 04 Nov 2024 04:39:45 GMT
< server: envoy
< x-envoy-upstream-service-time: 0
<
* Connection #0 to host localhost left intact
Hello None from behind Envoy!
ここまでの説明は、(その2)まででしていますので、まだの方は、(その2)でご確認ください。
Auth0 認証
(その2)と同じように、front-envoy
の Yaml ファイルを切り替えて(出力を省略しながら)実行します。
$ docker-compose down
$ FRONT_ENVOY_YAML=config/auth0/v3.yaml docker-compose up --build -d
$ docker-compose ps
先ほどと同様に呼び出しますが、JWT が無いため、401 エラーになるパターン
$ curl -v localhost:8000/service
* Trying [::1]:8000...
* Connected to localhost (::1) port 8000
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.3.0
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< www-authenticate: Bearer realm="http://localhost:8000/service"
< content-length: 14
< content-type: text/plain
< date: Mon, 04 Nov 2024 04:58:41 GMT
< server: envoy
<
* Connection #0 to host localhost left intact
Jwt is missing
上で見た Auth0 の Test タブの Response の access_token
を渡したパターン
$ curl -v localhost:8000/service --header 'authorization: Bearer eyJ...Ig'
* Trying [::1]:8000...
* Connected to localhost (::1) port 8000
> GET /service HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.3.0
> Accept: */*
> authorization: Bearer eyJ...Ig
>
< HTTP/1.1 200 OK
< content-type: text/plain; charset=utf-8
< content-length: 29
< date: Mon, 04 Nov 2024 05:00:58 GMT
< server: envoy
< x-envoy-upstream-service-time: 0
<
* Connection #0 to host localhost left intact
Hello None from behind Envoy!
という感じに、Auth0 から得た JWT を Auth0 に検証してもらう設定です。まずは、http_filters
の追加箇所
そして、Auth0 行きの宛先となる clusters
の追加箇所
このようにすることで、Auth0 の JWT を利用した外部認証も可能です、当然ですが、take0a
と書いてある箇所は、ご自分の Auth0 の設定に書き換えないと動きませんので、ご注意ください。
おわりに
なんか、すんなり、できたっぽく書きましたが、Auth0 の Sign-up でビビり、Envoy の設定では、Jwks remote fetch is failed
に悩まされました。ビビったのはともかくとして、エラーについては、以下のページに助けてもらいました。
私の場合は、dns_lookup_family: V4_ONLY
を設定していなかったことで、Envoy は、IPv6 を優先するそうなので、IPv6 が自由に使えない環境で実行される場合は、V4_ONLY
を指定する必要があります。(うちの会社の場合は、自分がクラウド上の開発環境のネットワークに IPv6 を通してないからなんですが)
それでは、第4回があれば(笑)、第4回で。
Discussion