OIDC連携を設定したALBの背後で動かすWebアプリをローカルPC上で開発するためにOAuth2 Proxyで環境構築してみた
CX事業本部@大阪の岩田です。ALBの認証機能はアプリケーションを簡単にOIDC準拠のIdPと連携できる非常に便利な機能です。
単に認証機能を付与できるだけでなく、ALBはバックエンドのターゲットに
- x-amzn-oidc-accesstoken
- x-amzn-oidc-identity
- x-amzn-oidc-data
といったカスタムヘッダでIdPから取得した諸々の情報を送信するため、バックエンドのアプリケーションはこれらのヘッダを参照して様々な処理を実装することができます。ここで課題になるのが、ローカル環境でのアプリケーションの開発です。本番環境と同等の条件でテストをするためには、アプリケーションに上記のカスタムヘッダを渡してやる必要があります。ローカル環境での開発時にALBの代替えとして利用できるツールが無いか探していたところ、社内でOAuth2 Proxyというツールを紹介してもらいました。今回はこのOAuth2 Proxyについて簡単に紹介させて頂きます。
OAuth2 Proxyとは
OAuth2 ProxyはGoogle、GitHub、FaceBookといった外部のIdPと連携して認証機能を提供するGo言語製のリバースプロキシです。GitHubのリポジトリはこちらです。
https://github.com/oauth2-proxy/oauth2-proxy/
元々はhttps://github.com/bitly/oauth2_proxyで開発されていたものを2018/11/27にフォークし、以後も継続的に開発されています
※現在こちらのリポジトリはアーカイブ済みです
現在の最新バージョンは7.1.3で、以下のIdPがサポートされています
- Google(デフォルト)
- Azure
- GitHub
- Keycloak
- GitLab
- Microsoft Azure AD
- OpenID Connect
- login.gov
- Nextcloud
- DigitalOcean
- Bitbucket
- Gitea
現時点ではα版という位置づけではありますが、アップストリームにリクエストをプロキシする際にリクエストヘッダー/レスポンスヘッダーを加工する機能も持っているため、ローカル環境でALBの代替えとして利用できそうな雰囲気を感じます。
https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/alpha-config
OAuth2 Proxyを使ってローカル開発環境を構築してみる
ここからは実際にOAuth2 Proxyを使ってローカルの開発環境を構築していきます。
今回は
- ローカルマシンの80ポートでOAuth2 Proxyを稼働させる
- OAuth2 Proxyは公開されているDockerイメージを利用する
- アップストリームとして設定するWebアプリはローカルマシンの8080ポートで稼働させる
- OAuth2 ProxyはGoogleとの連携を設定し、Google認証済みの場合だけアップストリームにプロキシする
- OAuth2 ProxyからアップストリームのWebアプリにプロキシする際に
X-AMZN-OIDC*
系のリクエストヘッダを追加で付与する
という環境を作ります
Googleの認証情報を準備
まずは以下のURLからGoogleの認証情報を作成します。
https://console.cloud.google.com/apis/credentials
「認証情報」から「認証情報を作成」をクリックし、「OAuthクライアントID」を選択します
続いて以下のように入力します
- 「アプリケーションの種類」に「ウェブアプリケーション」を
- 「名前」は適当にわかりやすいように名前を設定
- 「承認済みのリダイレクトURI」は
http://127.0.0.1/oauth2/callback
を- ※今回OAuth2 Proxyをローカルマシンの80ポートで起動するため
作成できたらクライアントIDとクライアントシークレットが発行されるため、これらの情報を控えて下さい。後ほどOAuth2 Proxyの設定に利用します。
OAuth2 Proxyの設定ファイルを準備
Googleの認証情報が準備できたので、今度はローカル環境でOAuth2 Proxyを起動する準備をしていきます。前述の通り今回はDockerを使って環境を構築していきます。
OAuth2のリポジトリで公開されているサンプルの設定を加工しつつ設定を作っていきます。
https://github.com/oauth2-proxy/oauth2-proxy/tree/master/contrib/local-environment
まずはdocker-compose.yaml
です
version: '3.0' services: oauth2-proxy: command: --config /oauth2-proxy.cfg --alpha-config /oauth2-proxy-alpha-config.yaml volumes: - "./oauth2-proxy-alpha-config.cfg:/oauth2-proxy.cfg" - "./oauth2-proxy-alpha-config.yaml:/oauth2-proxy-alpha-config.yaml" image: quay.io/oauth2-proxy/oauth2-proxy:v7.1.3-arm64 ports: - "80:80"
image
にはquay.io/oauth2-proxy/oauth2-proxy:v7.1.3-arm64
を指定しています。前述の通りアップストリームにリクエストを転送する際にリクエストヘッダを加工する機能は現在α版という位置付けで、設定の書き方も現在進行系でどんどん変わっています。今回紹介する設定はバージョン7.1.3でしか動作しない可能性が高いので、イメージのタグでv7.1.3までしっかり指定しましょう。
volumes
ではoauth2-proxy-alpha-config.cfg
とoauth2-proxy-alpha-config.yaml
という2つの設定ファイルを指定し、コンテナ内にマウントします。commnad
に指定した--command
と--alpha-config
でこれらの設定ファイルが読み込まれます。
続いて設定ファイルoauth2-proxy-alpha-config.cfg
です。こちらはtoml形式です
email_domains="<適当なドメイン もしくは*>" cookie_secret="<適当なシークレット>" redirect_url="http://127.0.0.1/oauth2/callback"
設定内容は以下の通りです
email_domains
- ここで指定したドメインに一致するメールアドレスのみOAuth2 Proxyの認証を通過できます。例えば、
email_domains
にexample.com
が指定されていた場合、hoge@gmail.com
というメールアドレスはGoogle認証済みでもOAuth2 Proxy側で403エラーが返却されます
- ここで指定したドメインに一致するメールアドレスのみOAuth2 Proxyの認証を通過できます。例えば、
cookie_secret
- Cookieの暗号化/復号に利用する鍵です以下のようなコマンドで作成しましょう
python -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(16)).decode())'
- https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#generating-a-cookie-secret
redirect_url
- IdPの認証後にリダイレクトさせるURLです。OAuth2 Proxyのデフォルト設定だと
/oauth2/callback
といるURLが利用されます。今回はローカルPCの80ポート上でOAuth2 Proxyを起動するのでhttp://127.0.0.1/oauth2/callback
を設定します。
- IdPの認証後にリダイレクトさせるURLです。OAuth2 Proxyのデフォルト設定だと
続いて設定ファイルoauth2-proxy-alpha-config.yaml
です。こちらはYAML形式になります
injectRequestHeaders: - name: x-amzn-oidc-identity values: - claim: user - name: x-amzn-oidc-data values: - claim: id_token - name: x-amzn-oidc-accesstoken values: - claim: access_token providers: - approvalPrompt: force clientID: <Google側で発行したクライアントID> clientSecret: <Google側で発行したクライアントシークレット> id: google oidcConfig: emailClaim: email groupsClaim: groups insecureSkipNonce: true userIDClaim: email provider: google server: BindAddress: :80 SecureBindAddress: "" TLS: null upstreams: - flushInterval: 1s id: / passHostHeader: true path: / proxyWebSockets: true uri: http://host.docker.internal:8080/
設定箇所のいくつかを抜粋して紹介します
injectRequestHeaders
ここで追加するリクエストヘッダが設定可能です。ALB環境をシミュレーションするためにX-AMZN-OIDC*
系のヘッダを定義しています。
- x-amzn-oidc-identity
- ALBがUserInfoエンドポイントから取得した
sub
を設定するヘッダです。OAuth2 Proxyでの設定はsub
ではなくuser
を指定します。
- ALBがUserInfoエンドポイントから取得した
- x-amzn-oidc-data
- ALBがJWT形式でユーザークレームを設定するヘッダです。JWT形式ですが、IDトークンではありません
- 現状OAuth2 Proxyでの設定ではALBと同様のクレームを設定できないので、IDトークンを設定することで代替えとしています。ALB環境と完全に同等にはなりませんが、これである程度互換性を担保できます。
- x-amzn-oidc-accesstoken
- ALBがトークンエンドポイントから取得したアクセストークンを設定するヘッダです。OAuth2 Proxyでも
access_token
を指定することで、リクエストヘッダに追加可能です。
- ALBがトークンエンドポイントから取得したアクセストークンを設定するヘッダです。OAuth2 Proxyでも
OAuth2 Proxyが管理するセッション情報からどういった値が設定できるか(claim:xxxxのxxxx部分)の詳細はパっと見る限りドキュメントに記述されていなさそうだったので、ソースコードを確認しながら設定してみました。恐らくこの当たりを見れば詳細が分かりそうです。
providers
ここにはIdPとの連携に関わる項目を設定します。clientID
とclientSecret
にそれぞれGoogle側で発行したクライアントID、クライアントシークレットを設定します
upstreams
uri
にはアップストリームのURIを指定します。今回はOAuth2 Proxyをコンテナとして起動して、ローカルPCの8080ポート上で動作するアプリケーションにプロキシする構成なので、host.docker.internal
の8080ポートを指定しています。
ローカル環境でOAuth2 Proxyを起動してみる
準備ができたので、実際にOAuth2 Proxyのコンテナを起動して動作確認してみます。
docker-compose -f docker-compose-alpha-config.yaml up
まずはトップページにアクセス
「Sign in with Google」と表示され、Google認証で保護されていることが分かります。
「Sign in with Google」をクリックしてGoogleにログインします
ログイン完了すると、数回のリダイレクトを経たのちにアップストリームから返却されたコンテンツが表示されます。
今回アップストリームのアプリケーションとしてPHPでprint_r($_SERVER)
するだけの簡単ものを利用しています。画面にHTTP_X_AMZN_OIDC*
のヘッダが表示されており、ALBと同等の環境がシミュレーションできていることが分かります。
まとめ
OAuth2 Proxyを利用してOIDC連携を設定したALBの環境をシミュレーションしてみました。リクエストヘッダのx-amzn-oidc-dataに関してはALBがユーザークレームを設定しているところをIDトークンで代替しているため完全な再現とは言えませんが、ローカル環境でアプリケーションを開発する上では支障の無いレベルでシミュレーション出来ているのではないでしょうか?
OIDC連携を設定したALBの背後で動かすWebアプリをどうやってローカルPC上で開発しよう?とお悩みの方は一度OAuth2 Proxyの利用をご検討下さい。