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
310
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
84
Other Decks in Technology
See All in Technology
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
2
1.7k
開発生産性を上げながらビジネスも30倍成長させてきたチームの姿
kamina_zzz
2
1.7k
誰も全体を知らない ~ ロールの垣根を超えて引き上げる開発生産性 / Boosting Development Productivity Across Roles
kakehashi
1
230
OCI 運用監視サービス 概要
oracle4engineer
PRO
0
4.8k
CysharpのOSS群から見るModern C#の現在地
neuecc
2
3.3k
Taming you application's environments
salaboy
0
190
AIチャットボット開発への生成AI活用
ryomrt
0
170
アジャイルでの品質の進化 Agile in Motion vol.1/20241118 Hiroyuki Sato
shift_evolve
0
140
20241120_JAWS_東京_ランチタイムLT#17_AWS認定全冠の先へ
tsumita
2
270
Lexical Analysis
shigashiyama
1
150
IBC 2024 動画技術関連レポート / IBC 2024 Report
cyberagentdevelopers
PRO
0
110
Featured
See All Featured
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
Imperfection Machines: The Place of Print at Facebook
scottboms
265
13k
Rails Girls Zürich Keynote
gr2m
94
13k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
890
Measuring & Analyzing Core Web Vitals
bluesmoon
4
120
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
8.2k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
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!