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
290
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
690
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
使えそうで使われないCloudHSM
maikamibayashi
0
170
新卒1年目が向き合う生成AI事業の開発を加速させる技術選定 / ai-web-launcher
cyberagentdevelopers
PRO
7
1.5k
「 SharePoint 難しい」ってよく聞くけど、そんなに言うなら8歳の息子に試してもらった
taichinakamura
1
620
グローバル展開を見据えたサービスにおける機械翻訳プラクティス / dp-ai-translating
cyberagentdevelopers
PRO
1
150
新卒1年目が挑む!生成AI × マルチエージェントで実現する次世代オンボーディング / operation-ai-onboarding
cyberagentdevelopers
PRO
1
160
プロダクト成長に対応するプラットフォーム戦略:Authleteによる共通認証基盤の移行事例 / Building an authentication platform using Authlete and AWS
kakehashi
1
150
【若手エンジニア応援LT会】AWS Security Hubの活用に苦労した話
kazushi_ohata
0
170
Automated Promptingを目指すその前に / Before we can aim for Automated Prompting
rkaga
0
110
【若手エンジニア応援LT会】AWSで繋がり、共に成長! ~コミュニティ活動と新人教育への挑戦~
kazushi_ohata
0
180
WINTICKETアプリで実現した高可用性と高速リリースを支えるエコシステム / winticket-eco-system
cyberagentdevelopers
PRO
1
190
ガバメントクラウド単独利用方式におけるIaC活用
techniczna
3
270
Amazon FSx for NetApp ONTAPを利用するにあたっての要件整理と設計のポイント
non97
1
160
Featured
See All Featured
Fontdeck: Realign not Redesign
paulrobertlloyd
81
5.2k
Gamification - CAS2011
davidbonilla
80
5k
Being A Developer After 40
akosma
86
590k
Designing on Purpose - Digital PM Summit 2013
jponch
115
6.9k
For a Future-Friendly Web
brad_frost
175
9.4k
The Power of CSS Pseudo Elements
geoffreycrofte
72
5.3k
Building Your Own Lightsaber
phodgson
102
6k
Thoughts on Productivity
jonyablonski
67
4.3k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
290
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
167
49k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
37
1.8k
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!