🛡️

Envoy入門(その3)Auth0 認証

2024/11/18に公開

はじめに

マイクロサービスやWeb API界隈では、サービス間のネットワークの制御をライブラリではなく、プロキシのコンテナをサイドカーとして使うのだとか。そのデファクトスタンダード的な立ち位置なのが Envoy さん。

(その1)(その2)は、Envoy のドキュメントが参照している Sandbox のコードを見ながら動かすというスタイルでしたが、今回は、より本番に近い設定を目指して、Auth0 と Envoy を組み合わせていきます。

やってみた

環境構築

Envoy

(その1)と(その2)は、Envoy さんのドキュメントの Sandbox のリポジトリを clone して、動かしながら、設定を読み解いてきましたが、Auth0 のものはありませんので、Sandbox さんの情報をコピーして、新たなリポジトリを作りました。(ま、パクリです)

https://github.com/take0a/envoy-samples

Auth0

Auth0 さんです。

https://auth0.com/jp

Sign up

Sign-up は、ここからやりました。今回は、上の GitHub に資材を残すので、Continue with GitHub しましたが、お好きな方法で良いと思います。このパターンだと Auth0 と GitHub の画面を往復して、プロファイルの画面へ遷移します。

Accout TypeOther。日本のサブドメインにしたかったので、I need advanced settings はチェックで Next して、Tenant Domaintake0a.jp.auth0.com にして Create Account しました。

Set up

Sign in して、ApplicationsAPIsCreate 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
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"}'
Response
{
  "access_token": "eyJ...Kw",
  "token_type": "Bearer"
}

あとは、見つけにくいところで、ApplicationsAPIs ではなくて、ApplicationsApplications から 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 の追加箇所

https://github.com/take0a/envoy-samples/blob/master/auth0/config/auth0/v3.yaml#L26-L45

そして、Auth0 行きの宛先となる clusters の追加箇所

https://github.com/take0a/envoy-samples/blob/master/auth0/config/auth0/v3.yaml#L65-L83

このようにすることで、Auth0 の JWT を利用した外部認証も可能です、当然ですが、take0a と書いてある箇所は、ご自分の Auth0 の設定に書き換えないと動きませんので、ご注意ください。

おわりに

なんか、すんなり、できたっぽく書きましたが、Auth0 の Sign-up でビビり、Envoy の設定では、Jwks remote fetch is failed に悩まされました。ビビったのはともかくとして、エラーについては、以下のページに助けてもらいました。

https://www.emmanuelgautier.com/blog/envoy-jwks-remote-fetch-failed

私の場合は、dns_lookup_family: V4_ONLY を設定していなかったことで、Envoy は、IPv6 を優先するそうなので、IPv6 が自由に使えない環境で実行される場合は、V4_ONLY を指定する必要があります。(うちの会社の場合は、自分がクラウド上の開発環境のネットワークに IPv6 を通してないからなんですが)

それでは、第4回があれば(笑)、第4回で。

GitHubで編集を提案
株式会社ROBONの技術ブログ

Discussion