Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」...
Search
andoshin11
September 07, 2024
Technology
0
280
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」Microservices認証認可基盤
Web Developer Conference 2024の登壇資料です
andoshin11
September 07, 2024
Tweet
Share
More Decks by andoshin11
See All by andoshin11
カーナベル株式会社2024年2月 エンジニアイベント資料
andoshin11
0
120
Private Cloudを支える最高のユーザーガイド運用技術
andoshin11
0
270
TS CompilerがVueを喋れても良いじゃないか
andoshin11
0
680
ain't giving up type-safe Express
andoshin11
2
400
Type Safe "Everything"
andoshin11
0
220
Hack your Nuxt router!
andoshin11
0
1.2k
GatewayパターンとSchema駆動開発
andoshin11
8
1.3k
Catch up Nuxt.js 2019.02
andoshin11
0
1.9k
The future of Nuxt.js with TypeScript
andoshin11
0
80
Other Decks in Technology
See All in Technology
Assisted reorganization of data structures
ennael
PRO
0
210
Efficient zero-copy networking using io_uring
ennael
PRO
0
270
HashHub会社案内「なぜ今、パブリックブロックチェーンに賭けるのか」
hashhub
3
75k
Causal Impactを用いたLINE Pay UIの効果検証とABテスト実施への貢献
lycorptech_jp
PRO
3
490
Report of JAWS PANKRATION 2024, a global online event using Amazon IVS
yoshimi0227
1
130
低コストで実現する社内文書RAG機能を搭載したAIチャットボット開発
takapy
3
570
Making Linux sucks less
ennael
PRO
0
490
エムスリーマネジメントチーム紹介資料 / Introduction of M3 Management Team
m3_engineering
0
250
エムスリー全チーム紹介資料 / Introduction of M3 All Teams
m3_engineering
1
210
【shownet.conf_】革新と伝統を融合したファシリティ
shownet
PRO
0
240
VS CodeでF1〜12キーつかってますか? / Do you use the F1-12 keys in VS Code?
74th
2
270
成果のためのコミュニケーション - 語彙を育てよう -/communication-for-good-outcome-developing-vocabulary
hassaku63
4
140
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3.4k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
Gamification - CAS2011
davidbonilla
80
5k
Adopting Sorbet at Scale
ufuk
73
8.9k
Optimising Largest Contentful Paint
csswizardry
31
2.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
The Cult of Friendly URLs
andyhume
76
6k
Build The Right Thing And Hit Your Dates
maggiecrowley
31
2.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
403
65k
Statistics for Hackers
jakevdp
796
220k
Unsuck your backbone
ammeep
667
57k
How to train your dragon (web standard)
notwaldorf
87
5.6k
Transcript
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」 Microservices認証認可基盤 Web Developer Conference 2024 @andoshin11
自己紹介 • 安藤真 (@andoshin11) • フリーランスエンジニア • お手伝いしてます👇 ◦ カーナベル
as a Platform Owner 2021年4月〜 ◦ Medixpost as a Lead Developer 2022年9月〜 • 好きな技術: ◦ TypeScript ◦ Terraform ◦ Cilium
カーナベル株式会社 • トレカ(遊戯王、デュエマ、ポケカ、MTG)の買 取 & 販売を行う日本最大級のトレカECサイト • 法人化: 2009年(創業は2003年ごろ) •
本社: 三重県四日市市 • スタッフ: 約100名 • 開発チーム: 10名
コンテキスト: サイトの老朽化 • 10年以上前に作ったPHPモノリスサーバー(Ethna)の耐用限界 • プロダクトの多機能化 & 多角化に対してコードの継ぎ足しでなんとかこれ まで粘ってきた
コンテキスト: サイトの老朽化 • 10年以上前に作ったPHPモノリスサーバー(Ethna)の耐用限界 • プロダクトの多機能化 & 多角化に対してコードの継ぎ足しでなんとかこれ まで粘ってきた •
マジで頑張ってる↓ ▪ 自動仕分けロボット用の画像認識AIを作ったり ▪ MirroringしたAuroraに対してLaravelのAPIサーバーを立てたり ▪ jQuery templateの中にWeb Components(Lit)を埋め込んだり
コンテキスト: サイトの老朽化 • 10年以上前に作ったPHPモノリスサーバー(Ethna)の耐用限界 • プロダクトの多機能化 & 多角化に対してコードの継ぎ足しでなんとかこれ まで粘ってきた •
マジで頑張ってる↓ ▪ 自動仕分けロボット用の画像認識AIを作ったり ▪ MirroringしたAuroraに対してLaravelのAPIサーバーを立てたり ▪ jQuery templateの中にWeb Components(Lit)を埋め込んだり そしてフルスクラッチリニューアルへ...
Architecture
お客様 ECサイト (Nuxt.js) Contour (Ingress controller) External AuthZ Server Argo
CD・ Workflows Cilium OTel Collector Microservice A Microservice B Microservice C スタッフ 管理画面 (Nuxt.js)
本日のテーマ
課題 1: 会員認証と社員認証をどう共存させるか
課題 1: 会員認証と社員認証をどう共存させるか 課題 2: Microservicesの認可をどうするか
課題 1: 会員認証と社員認証をどう共存させるか
お客様(Customer)と社員(Member)それぞれで要求される認証要件は異なる • メール所有権確認 • パスワードリセット • クレカ登録 • 不正ユーザー判定 •
etc… • 入退社管理 • 二段階認証強制 • パスワードローテーション • 細かな認可権限管理 • 情シス制御 • etc… お客様向けの要件 社員向けの要件
よくある解決方法: 同じシステム上でフラグ管理 Good: 一元管理・ロジックの使い回しが可能 Bad: 大量のif文・実装ミスによるアクセス範囲超過のリスク
弊社の場合
認証プロバイダー自体を分離 Firebase for Customers Google Workspace for Members • 利用実績あり
• スケーラビリティ • 利用料金の安さ • 対応認証手段の多さ • メール送信機能内包 • etc… • 全社のデフォルト認証手段 • 業務アプリでSSO利用中 • 入退社管理の容易さ • etc…
認証プロバイダー自体を分離 Firebase for Customers Google Workspace for Members • 利用実績あり
• スケーラビリティ • 利用料金の安さ • 対応認証手段の多さ • メール送信機能内包 • etc… • 全社のデフォルト認証手段 • 業務アプリでSSO利用中 • 入退社管理の容易さ • etc… 正確にはAmazon Cognitoを利用 ・ProviderとしてGoogle Workspaceを設定 ・社員にS3アクセスを許可するため
Multi Auth Providersならではの課題
認証プロバイダーごとにJWT Payloadが異なる iss, sub, iat, expなどは同様だが、メタフィールドに大きな違いがある
Point of failure・運用負担の増加 • 各Microservicesが賢くなりすぎると保守が大変 • bug修正・仕様修正のたびに全体再デプロイ。最悪の場合は都度サービスメンテ • 認証認可という根幹の部分の変更反映はなるべく数を減らしたい →
Microservicesを賢くさせたくない
Microservicesを賢くさせたくない
API GatewayとSTSで解決しよう!
API Gateway
中央集権的GWによる責務のオフロード • 外部認証プロバイダーとはAPI Gatewayでのみ通信 • MicroservicesからはFirebaseおよびCognitoの知識を完全に隠蔽 Microservice A Microservice B
Microservice C API Gateway 1. ユーザーアクセス 2. 署名検証 3. 検証済リクエスト
CONTOUR as API Gateway • オープンソースのKubernetes向けingress controller (CNCF Incubating Project)
• 実装はEnvoyのwrapper → External Authorizationが設定できる
What is ExtAuthZ ? • Envoyが提唱するEnvoy ↔ 外部認証サーバー間の通信プロトコル • Envoyを通過するリクエストに対する中間処理を切り出せる
External Authorization Serverで行える中間処理 ExtAuthZ Server側はexternal_auth.proto に則って実装することで下記の ような中間処理を行える(言語非依存) ◦ リクエストの認証チェック・エラーthrow ◦
Metadataの上書き ◦ リクエストヘッダーの上書き ◦ クエリパラメータの上書き ◦ 後続filterへのdynamic metadataの設定 ◦ etc…
External Authorization Serverで行える中間処理 ExtAuthZ Server側はexternal_auth.proto に則って実装することで下記の ような中間処理を行える(言語非依存) ◦ リクエストの認証チェック・エラーthrow ◦
Metadataの上書き ◦ リクエストヘッダーの上書き ◦ クエリパラメータの上書き ◦ 後続filterへのdynamic metadataの設定 ◦ etc… 弊社ではこの辺の機能を利用
Contour + ExtAuthZを活用したArchitecture • external_auth.protoを実装したAuthority Serviceを自前実装 • routing、流量調整、gRPC-Web変換等を行うContourと責務分離 Microservice A
Microservice B Microservice C 1. ユーザーリクエスト 3. 署名検証 5. 検証済みリクエスト Contour Authority Service 2. ExtAuthZ 4. Success
Contour + ExtAuthZを活用したArchitecture Microservice A Microservice B Microservice C 3.
署名検証 Contour Authority Service 2. ExtAuthZ 5. Denied 4. 認証エラー • エラーの場合はExtAuthZサーバー(Authority Service)からDenied Responseを返す • Microservicesにはリクエストは到達しない 6. 認証エラー 1. ユーザーリクエスト
STS(Security Token Service)
Authority Service as Security Token Service おさらい👇 • External Token(FirebaseとCognito)のJWT
Payloadは型が異なる • ExtAuthZサーバー(Authority Service)ではMetadataの上書きが可能
Authority ServiceをSTSとして活用しよう! (署名検証 & 署名発行)
Authority Service as Security Token Service • Authority ServiceでExternal Tokenを正規化して新たにInternal
Tokenを 署名発行する → Token Exchangeと呼ばれる手法
Authority Service as Security Token Service • Authority ServiceでExternal Tokenを正規化して新たにInternal
Tokenを 署名発行する → Token Exchangeと呼ばれる手法 • What is Internal Token? ◦ IssuerがAuthority ServiceのJWT ◦ 内部通信でのみ利用 ◦ 正規化済みのPayload ◦ 1リクエストごとに発行する ◦ External Tokenよりも寿命が短い(expが短命な)JWT = 60秒 ▪ → 万が一の漏出に対する耐性
Authroity ServiceでToken Exchange処理を行う Microservice A 1. Request (External Token) 3.
Validate (External Token) 5. Request (Internal Token) Contour Authority Service 2. ExtAuthZ (External Token) 4. Success (Internal Token) Step 2 & Step 4の処理が一般的に Token Exchangeと呼ばれる
Microservices側の実装
JSON Web Keysを活用したStandaloneな署名検証方式 Microservice A Request with Internal Token Contour
Authority Service Token Exchange AWS Secret Manager Key-pairを取得 (直近3世代) 定期的に新規の Key-pairを生成 • Authority ServiceからJWKsを取得し、 Internal Tokenを検証 • JWKはkid単位でcache → Authority Serviceのダウンに耐性アリ・通信量削減も • JWTの検証にはaws-jwt-verifyを利用 JWKsを取得(cached)
awslabs/aws-jwt-verify • OIDC-compatなJWTの検証に利用できるAWSチームのライブラリ • Zero dependencies ← メンテが楽!! • コードもシンプルで読みやすく、必要最低限な機能のみを提供
• カスタムJWKs fetcherを差し込める(デフォルトはHTTP fetcher) ◦ 弊社ではAuthority Serviceと通信するgRPC fetcherをinject • 地味にNode.js & Web Browser両方に対応 • 非常に高品質かつ爆速でJWT verifierを定義できるため長期betする 価値はありそう ← 激推しです
社内向けライブラリの提供 • Private PackageとしてNest.js向けのAuthGuardを提供 • 実態はInternal TokenのJWT verifier + 認可チェック機構(後述)
Nest.js向け共通ライブラリの社内提供
課題 1: 会員認証と社員認証をどう共存させるか
API GatewayとSTSを組み合わせることで複雑性 の隠蔽が可能になり、外部サービスの変更にも強 いアーキテクチャが実現できた
課題 2: Microservicesの認可をどうするか
セキュリティ・コンプライアンス観点における認可要求 カーナベルの部署構成(抜粋) • 開発課 • 経営企画 • カスタマーサポート • プライシング
• ロジスティクス(買取・封入) • 総務 • etc…
セキュリティ・コンプライアンス観点における認可要求 カーナベルの部署構成(抜粋) • 開発課 → 顧客情報アクセス禁止 • 経営企画 → 顧客情報アクセス禁止
• カスタマーサポート • プライシング → 顧客情報アクセス禁止 • ロジスティクス(買取・封入) • 総務 → 顧客情報アクセス禁止 • etc…
セキュリティ・コンプライアンス観点における認可要求 カーナベルの部署構成(抜粋) • 開発課 → 顧客情報アクセス禁止 • 経営企画 → 顧客情報アクセス禁止、在庫数変更禁止
• カスタマーサポート → 在庫数変更禁止 • プライシング → 顧客情報アクセス禁止、在庫数変更禁止 • ロジスティクス(買取・封入) • 総務 → 顧客情報アクセス禁止、在庫数変更禁止 • 情シス → 顧客情報アクセス禁止、在庫数変更禁止 • etc…
セキュリティ・コンプライアンス観点における認可要求 カーナベルの部署構成(抜粋) • 開発課 → 顧客情報アクセス禁止 • 経営企画 → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止
• カスタマーサポート → 在庫数変更禁止、価格変更禁止 • プライシング → 顧客情報アクセス禁止、在庫数変更禁止 • ロジスティクス(買取・封入) → 価格変更禁止 • 総務 → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止 • 情シス → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止 • etc…
セキュリティ・コンプライアンス観点における認可要求 カーナベルの部署構成(抜粋) • 開発課 → 顧客情報アクセス禁止 • 経営企画 → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止
• カスタマーサポート → 在庫数変更禁止、価格変更禁止 • プライシング → 顧客情報アクセス禁止、在庫数変更禁止 • ロジスティクス(買取・封入) → 価格変更禁止 • 総務 → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止 • 情シス → 顧客情報アクセス禁止、在庫数変更禁止、価格変更禁止 • etc… 部署ごとの細やかな権限管理が求められる
こんな認可処理はイヤだ 👉
• Controller method内にaccess scopeごとのif文を記述する方式 • 記述が冗長 & method単位でのテストが必須で保守性低 こんな認可処理はイヤだ
アプリケーションロジックに認可処理 をベタ書きしたくない
認可機構に求める要件 ① 可読性 ◦ API Methodsの仔細まで読まなくても認可スコープを瞬時に把握でき ること ② 記述性 ◦
言語非依存・FW非依存・ドメイン非依存であること = 個別のMicroservicesのドメイン知識が無くても容易に認可スコー プを記述できること ③ 変更容易性 ◦ 全てのMicroservices repositoriesに修正を加えなくても安全に Platform全体への認可スコープ追加/削除が行えること
Protobufに集約しよう!
Method Optionで認可スコープを定義する
Method Optionで認可スコープを定義する option blockにallowed_scopesを 記述していく optionのschemaはextensionで定義
Protobufに認可スコープを記載するメリット ① 可読性 ◦ Methodごとの認可スコープを一瞥できる ② 記述性 ◦ Protobuf syntaxさえ知っていれば誰でも記述できる
③ 変更容易性 ◦ Protobuf repository内をgrep/sedするだけで網羅的に認可スコープ の追加/削除を行える
How to define custom extensions?
google.protobuf.MethodOptionsをextendして定義する
google.protobuf.MethodOptionsをextendして定義する descriptor.protoをimport extend記法でfieldを追加
google.protobuf.MethodOptionsをextendして定義する AuthorizationRule型のauthorization fieldをcustom optionとして定義
google.protobuf.MethodOptionsをextendして定義する
google.protobuf.MethodOptionsをextendして定義する このfiled numはどこからでてきた?
google/protobuf/descriptor.proto
google/protobuf/descriptor.proto custom optionを定義する際は1000番以降 のfiled numを利用するよう指定がある
How to use custom extensions?
Method Optionの利用
Method Optionの利用 識別子の役割。 “authorization”というcustom extensionを利用すること明示
Method Optionの利用 option blockの中は AuthorizationRule型で記述
AuthGuard側の実装
None
リクエストを通過させるか どうかの判定を行う
Internal Tokenの署名検証 = 認証 対象Methodの認可チェック = 認可
subやscpは署名発行時 に自動で埋め込まれる
method pathはリクエストの ExecutionContextから特定できる
protobufjsでmethod optionをパースす る。@grpc/proto-loaderは未対応
scpとallowed_scopesを比較
課題 2: Microservicesの認可をどうするか
Protobufに認可スコープを記述することで可読性・ 記述性・変更容易性が担保された仕組みが実現
まとめ
色々話した(まだ話したりない)けど 実はそんなに難しいことはやってない
• 会員登録・ログイン機能 → FirebasesとCognito(Google Workspace)のSDKを利用 • JWTの検証 → 3rd-party libraryを利用
• API GatewayとToken Exchange → ContourのExternal Authorization機能を利用 • Protobufの拡張 → 標準のCustom Extensionを利用 • Nest.jsの認証Middleware → 標準のAuth Guardのを利用 • 自分たちで発明したものはほとんど無い
• 会員登録・ログイン機能 → FirebasesとCognito(Google Workspace)のSDKを利用 • JWTの検証 → 3rd-party libraryを利用
• API GatewayとToken Exchange → ContourのExternal Authorization機能を利用 • Protobufの拡張 → 標準のCustom Extensionを利用 • Nest.jsの認証Middleware → 標準のAuth Guardのを利用 • 自分たちで発明したものはほとんど無い 実際の開発工数は20人日程度
伝えたいこと
適切な技術選定と設計力があれば 小規模チームでも高品質な認証認可基盤を導入できる ※今回の基盤はセキュリティ会社の 脆弱性診断に合格済みの内容です
WE ARE HIRING!! • リモート勤務可能 • こんなことやってます ◦ OTel +
Grafanaでの監視基盤構築 ◦ Cloudflare Workersの実装 ◦ K6を利用した負荷試験 ◦ Web Vitalsの継続的計測と改善 ◦ 在庫回転率と需供分析でのDynamic Pricing ◦ Elasticsearchで検索基盤構築 ◦ Terraform Providerの開発 ◦ Custom Jest Environmentの整備 ◦ gRPC ServerのE2E coverage取得の仕組み作り ◦ Nuxt pluginの開発 ◦ etc… • 興味がある方は
[email protected]
又は自分まで
Thank you!