【レポート】Backend Engineer’s meetup ~マイクロサービスにおける認証認可基盤~
本記事は、2019年8月21日に行われたmerpay社の主催するイベント、「Backend Engineer’s meetup ~マイクロサービスにおける認証認可基盤~」の参加レポートです。
Backend Engineer’s meetup ~マイクロサービスにおける認証認可基盤~
レポート
セッションの概要
メルペイ社の認証基盤チームの担当している
- 外部向けに提供しているOIDCなどの認可の仕組み
- 内部のマイクロサービス間通信の認証の仕組み
のうち、後者についてのお話を聞いてきました。セッションのスライドはこちらで公開されています。
チームがやっていること
- 認証基盤チームではユーザーアカウント管理とかログインはやってない
- 従業員の管理とかはやってない
- セキュリティについてはセキュリティチームと相談しながらやっている
- それ以外の認証認可を認証基盤チームがやっている
現状のアーキテクチャ
AuthorityServiceというマイクロサービスが、
- 外部向けに提供しているOIDCなどの認可の仕組み
- 内部のマイクロサービス間通信の認証の仕組み
を提供している。
- メルカリAPIを利用するパターン
- マイクロサービスを利用するパターン
の2つのデータフローがあるが、AuthorityServiceが関連するのはマイクロサービスを利用するパターンのみ。
AuthorityServiceがやっていること
外部からのリクエスト検証
内部通信用トークンの生成
クライアントから受け取るトークンと内部通信用のトークンが別れていて、リクエストの検証後に内部通信用のトークンを生成している。
各マイクロサービスは、内部通信用のトークンの検証をしている。
- 1リクエストに対して、1つトークンが払い出される
- 各マイクロサービスが検証する内部トークンは同じもの
- JWT
- マイクロサービスはAuthorityServiceが提供する公開鍵で検証
- 鍵はマイクロサービス側でキャッシュしている
内部トークン用のSDK
Go言語のSDKのみ提供している。
内部スコープ
内部トークンが持つスコープで、マイクロサービス間のアクセス制御を行うための仕組み。
サードパーティからのリクエストに対してのみ、内部スコープを利用している。 外部スコープの値をそのまま内部スコープにセットしているが、それだけだとクライアントのユースケースの数だけマイクロサービスが内部スコープを管理しなくてはいけない。
外部クライアント用のスコープと、内部のスコープは本来1対1ではない。 外部スコープはユースケースベースで、内部スコープはリソースベースで持つべき。
ここを吸収するため、AuthorityServiceで外部スコープと内部スコープのマッピングテーブルを持っている。
例えば、決済処理を行うには「transaction」と「user」リソースに対する内部スコープが必要だが、クライアントからは「決済」が行いたいので「transaction」だけの指定で済むのが自然。
その他内部トークンのメリット
QA
セッションの最後にQAの時間がありました。
- 可用性に関するインフラの工夫とかある?
- 特別なことはしてない、しなくても良いくらい安定している
- 冗長化して分散、リトライ、タイムアウト、みたいなところをやる
- サービス間のアクセス制御はどうしてる?どのサービスがどのサービスにアクセスできるのか?をどう管理してる?
- マイクロサービス間の認証は現状してない
- やろうとはしている
- ただ、内部トークンで誰がどこにアクセスできるのか?は制御できる
- 内部トークンの不正利用について監視とかしてる?
- 現状してない
- 寿命が短いのでそこまでリスキーではないと考えている
- やったほうがいいのはそう
- スコープとかいれるとトークンでかくなると思う。復号とかでパフォーマンスの問題はおきない?
- 長い問題は考えてる
- JWTをやめたい
- バイナリにしたい(と勝手に思っている)
- CWT?
- バイナリにしたい(と勝手に思っている)
- AuthorityServiceについて、性能面で意識したこととかある?
- レイテンシーについて
- マイクロサービス化したときに、レイテンシーをあまり考えないようにした
- そこにフォーカスするならモノリスにすべき
- とはいえ必ず通るところが遅いと辛い
- ローカルメモリでデータをキャッシュしたりとかそういう工夫はある
- とはいえ必ず通るところが遅いと辛い
- そこにフォーカスするならモノリスにすべき
- マイクロサービス化したときに、レイテンシーをあまり考えないようにした
- レイテンシーについて
- SDKをサイドカープロキシにはしないのか?
- そうすることを考えている
- SDKをどう使うか、がService側の責務になっているし、Goだけなので多言語どうする?みたいな話がある
- そうすることを考えている
- 内部トークンの有効期限に対する検討軸は?
- クライアントがレスポンスをどれだけ待ってくれるか?で考えた
- 10分にしても、そんな待ってくれないよね、という考え方
- クライアントがレスポンスをどれだけ待ってくれるか?で考えた
- サービスからサービスにバッチ処理を依頼する場合とかある?
- 内部トークンで依頼する
- 各サービスが秘密鍵を持っていて、これで内部トークンを取得してバッチ処理を依頼
- 内部トークンで依頼する
- 一番システムが複雑化しそうなユースケースは?
- pub-Sub
- 内部トークンは有効期限が短い
- 途中で切れちゃう可能性があるので、それをどうするか?
- バッチでも使えてるのは?
- バッチを依頼するサービスが自分で内部トークンを生成してる(ゲートウェイから最初に受け取ったやつをそのままつかわない)
- pub-Sub
感想
外部クライアント用のスコープと、内部のスコープは1対1でマッチせず、前者はユースケースベース、後者はリソースベースという考え方は本当にその通りだなと思いました。
私からは以上です。