Slide 1

Slide 1 text

AWS のポリシー言語 Cedar を 活用した高速かつスケーラブルな 認可技術の探求 #phperkaigi チェシャ猫 (@y_taka_23) PHPerKaigi 2025 22nd Mar. 2025

Slide 2

Slide 2 text

バックエンド書いてる人?

Slide 3

Slide 3 text

セキュリティとか CCoE 系の人?

Slide 4

Slide 4 text

計算機科学の理論面が好きな人?

Slide 5

Slide 5 text

目次 ● ポリシー言語入門 ○ そもそもポリシー言語とはどのようなものか ● Cedar によるポリシー記述 ○ どのような機能があり、どのように使えるのか ● 理論面から見た Cedar ○ 安全性の保証にはどのような理論が利用されているか

Slide 6

Slide 6 text

Cedar: A New Language for Expressive, Fast, Safe, and Analyzable Authorization J. W. Cutler et al. (OOPSLA 2024) https://doi.org/10.1145/3649835

Slide 7

Slide 7 text

ポリシー言語入門 1. Hello, Policy Languages!

Slide 8

Slide 8 text

マイクロサービスに対する認可 ● アプリ開発チームの苦労 ○ 似たような判定を各チームが各言語で実装 ○ 実装は別なのに、概念として一貫していないと動かない ● セキュリティ / CCoE チームの苦労 ○ セキュリティ統制的に共通のガードレールを敷きたい ○ 実装は別なので、ルールに対する合致を監査できない

Slide 9

Slide 9 text

本日の主役「P ? P」

Slide 10

Slide 10 text

PDP と PEP ● Policy Decision Point (PDP) ○ ポリシー言語に基づきアクセス要求を評価 ○ 許可(Allow)または拒否(Deny)を判断 ● Policy Enforcement Point (PEP) ○ PDP に判断を仰いで実際のアクセス制御を行う ○ Web アプリでは API Gateway やバックエンド実装

Slide 11

Slide 11 text

ポリシー言語、見たことあるはず

Slide 12

Slide 12 text

AWS Identity and Access Management (IAM) https://aws.amazon.com/jp/iam

Slide 13

Slide 13 text

ポリシー言語としての IAM ● IAM も PDP の一種とみなせる ○ PEP は各種 AWS サービス、操作対象は AWS リソース ○ Principal / Action / Resource / Condition で指定 ● 複数チームがポリシーを定義しても最終結果は安全側 ○ Deny が一つでもあれば Allow より優先 ○ ポリシーの順番や重複で結果が変わらない

Slide 14

Slide 14 text

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ec2:TerminateInstances"], "Resource": ["*"], "Condition": { "IpAddress": { "aws:SourceIp": ["192.0.2.0/24"] } } } ] }

Slide 15

Slide 15 text

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["ec2:TerminateInstances"], "Resource": ["*"], "Condition": { "IpAddress": { "aws:SourceIp": ["192.0.2.0/24"] } } } ] } AWS 特化

Slide 16

Slide 16 text

これをアプリ内部の認可にも使いたい

Slide 17

Slide 17 text

Cedar Policy Language https://github.com/cedar-policy

Slide 18

Slide 18 text

Cedar が目指す立ち位置 ● 表現力が高い ○ RBAC と ABAC を組み合わせて設計できる ● パフォーマンスが高い ○ 高速で、ポリシー数に対して速度が劣化しづらい ● ポリシーの意味が理解しやすい ○ 人間にとってはもちろん、自動解析の基礎も整っている

Slide 19

Slide 19 text

Amazon Verified Permissions ● AWS マネージド版の Cedar エンジン ○ PDP は単一障害点なので管理したくない ○ PHP 含め各言語の SDK でアクセス可 ● Amazon Cognito とも連携可能 ○ 認証:Cognito User Pool ○ 認可:Verified Permissions https://aws.amazon.com/jp/verified-permissions/

Slide 20

Slide 20 text

API Gateway を PEP とするパターン DynamoDB Authorizer API Gateway Verified Permissions Cognito User Application Allow / Deny User Pool 連携

Slide 21

Slide 21 text

バックエンドを PEP とするパターン DynamoDB Authorizer API Gateway Verified Permissions Cognito User Application Allow / Deny User Pool 連携 Entity 情報

Slide 22

Slide 22 text

その他の OSS ポリシー言語 ● Open Policy Agent (OPA) ○ おそらく最も有名で広く使われている ○ Prolog ベースの Rego 言語による記述 ● OpenFGA ○ Google の認可基盤 Zanzibar がベース ○ エンティティ間のグラフ構造による記述 https://github.com/open-policy-agent https://github.com/openfga

Slide 23

Slide 23 text

Section 1 のまとめ ● PDP と PEP の分離 ○ 認可処理を直接アプリに密結合したくない ○ アプリとは分離して専用のポリシー言語で記述 ● OSS ポリシー言語 Cedar ○ マネージド版が Verified Permissions として利用可 ○ 表現力 / パフォーマンス / 解析可能性

Slide 24

Slide 24 text

Cedar によるポリシー記述 2. Defining Policies in Cedar

Slide 25

Slide 25 text

例:写真共有アプリの認可 ● ユーザの写真に対する操作を許可または禁止したい ○ ユーザが所属するグループに対して許可 ○ 写真が所属するアルバムに対して許可 ○ 写真の所有者はデフォルトで許可 ● ユーザは他のユーザに写真を共有できる ○ 共有された側は、その写真に限って閲覧許可

Slide 26

Slide 26 text

Any photo01.jpg photo02.jpg album01 team01 alice bob Request = ( alice, viewPhoto, photo01.jpg ) owner

Slide 27

Slide 27 text

Cedar によるポリシー記述 ● 効果は permit(許可)/ forbid(拒否) ○ 複数該当する場合は forbid が優先される ● エンティティの三つ組を基本としてルールを記述 ○ Principal:alice が(操作主体) ○ Action:写真を閲覧する(操作内容) ○ Resource:photo01.png を(操作対象)

Slide 28

Slide 28 text

permit ( principal == PhotoApp::User::"alice", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo01.jpg" ); forbid ( principal == PhotoApp::User::"bob", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo02.jpg" ); 基本となるポリシー

Slide 29

Slide 29 text

permit ( principal == PhotoApp::User::"alice", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo01.jpg" ); forbid ( principal == PhotoApp::User::"bob", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo02.jpg" ); 基本となるポリシー alice は photo01.jpg を閲覧できる

Slide 30

Slide 30 text

permit ( principal == PhotoApp::User::"alice", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo01.jpg" ); forbid ( principal == PhotoApp::User::"bob", action == PhotoApp::Action::"viewPhoto", resource == PhotoApp::Photo::"photo02.jpg" ); 基本となるポリシー bob は photo02.jpg を閲覧できない

Slide 31

Slide 31 text

Cedar による RBAC ● Role-Based Access Control (RBAC) ○ Principal の所属関係に依存した判定 ● Cedar では Principal に加え Resource もグループ化できる ○ Principal:グループ team01 のメンバが ○ Action:写真を閲覧する ○ Resource:アルバム album01 内の写真を

Slide 32

Slide 32 text

permit ( principal in PhotoApp::UserGroup::"team01", action == PhotoApp::Action::"viewPhoto", resource in PhotoApp::Album::"album01" ); RBAC によるポリシー

Slide 33

Slide 33 text

permit ( principal in PhotoApp::UserGroup::"team01", action == PhotoApp::Action::"viewPhoto", resource in PhotoApp::Album::"album01" ); RBAC によるポリシー team01 に含まれる任意の principal album01 に含まれる任意の resource

Slide 34

Slide 34 text

Cedar による ABAC ● Attribute-Based Access Control (ABAC) ○ エンティティの持つ属性に依存した判定 ● Cedar では自由に属性が定義できる ○ Principal:誰でも ○ Action:写真を閲覧する ○ Resource:自分が所有する(owner)写真を

Slide 35

Slide 35 text

permit ( principal, action == PhotoApp::Action::"viewPhoto", resource ) when { resource has owner && resource.owner == principal }; ABAC によるポリシー

Slide 36

Slide 36 text

permit ( principal, action == PhotoApp::Action::"viewPhoto", resource ) when { resource has owner && resource.owner == principal }; ABAC によるポリシー 指定がない = ワイルドカード

Slide 37

Slide 37 text

permit ( principal, action == PhotoApp::Action::"viewPhoto", resource ) when { resource has owner && resource.owner == principal }; ABAC によるポリシー 属性 owner による指定

Slide 38

Slide 38 text

動的なポリシー生成 ● アプリの機能として動的にポリシーを生成したい ○ 例:写真をシェアした相手に閲覧権限を付与 ● テンプレートからの生成が可能、変更時も追従してくれる ○ Principal:ユーザ〇〇が ○ Action:写真を閲覧する ○ Resource:写真〇〇を

Slide 39

Slide 39 text

permit ( principal == ?principal, action == PhotoApp::Action::"viewPhoto", resource == ?resource ); ポリシーテンプレート

Slide 40

Slide 40 text

permit ( principal == ?principal, action == PhotoApp::Action::"viewPhoto", resource == ?resource ); ポリシーテンプレート API を叩いて動的に ポリシーをインスタンス化

Slide 41

Slide 41 text

セキュリティ系は記述ミスが怖い

Slide 42

Slide 42 text

Schema によるバリデーション ● 記述言語としての汎用性はエラーの温床 ○ エンティティ名も属性名もユーザ定義 ○ Undefined 属性を参照すると意図しない結果を招く ● Cedar は組み込みのバリデーション機能をサポート ○ ポリシー自体とは別に Schema を定義できる ○ 違反したポリシーは登録時に弾かれる

Slide 43

Slide 43 text

"Photo": { "shape": { "type": "Record", "attributes": { "owner": { "type": "Entity", "name": "User", "required": true } } }, "memberOfTypes": ["Album"] }

Slide 44

Slide 44 text

内部の動作はどうなっているのか?

Slide 45

Slide 45 text

ポリシー判定の流れ 1. リクエストとエンティティを受け取る 2. ポリシー全体の内、そのリクエストとエンティティに対し 該当するものを全てリストアップする 3. リストアップされたものを permit と forbid に分ける 4. permit 組が空集合でなく、forbid 組が空集合なら Allow 5. それ以外なら Deny

Slide 46

Slide 46 text

全部のポリシーを判定していると遅い

Slide 47

Slide 47 text

Slice 処理の流れ 1. 予め Principal + Resource をキーとしてポリシーを保持 2. リクエストが来たら、その Principal と Resource から 遡れる祖先要素をそれぞれ求める 3. Principle と Resource たちの全ての組合せを求める 4. ポリシーの中で最終結果に影響するのは、 ここで求めた組合せをキーとするポリシーのみ

Slide 48

Slide 48 text

Any photo01.jpg photo02.jpg album01 team01 alice bob Request = ( alice, viewPhoto, photo01.jpg ) owner

Slide 49

Slide 49 text

Any photo01.jpg photo02.jpg album01 team01 alice bob Request = ( alice, viewPhoto, photo01.jpg ) owner alice の祖先 photo01.png の祖先

Slide 50

Slide 50 text

Principal Resource Any Any Any album01 Any photo01.jpg team01 Any team01 album01 team01 photo01.jpg alice Any alice album01 alice photo01.jpg Slice の絞り込み Key Principal Resource Effect Any photo02.png permit team01 album01 permit alice album01 permit bob album01 permit alice photo02.jpg permit bob photo02.jpg permit alice photo02.jpg forbid team01 photo01.jpg forbid bob photo01.png forbid 定義されている全 Policy

Slide 51

Slide 51 text

Principal Resource Any Any Any album01 Any photo01.jpg team01 Any team01 album01 team01 photo01.jpg alice Any alice album01 alice photo01.jpg Slice の絞り込み Key Principal Resource Effect Any photo02.png permit team01 album01 permit alice album01 permit bob album01 permit alice photo02.jpg permit bob photo02.jpg permit alice photo02.jpg forbid team01 photo01.jpg forbid bob photo01.png forbid Slice で絞り込まれた Policy

Slide 52

Slide 52 text

Principal Resource Any Any Any album01 Any photo01.jpg team01 Any team01 album01 team01 photo01.jpg alice Any alice album01 alice photo01.jpg Slice の絞り込み Key Principal Resource Effect Any photo02.png permit team01 album01 permit alice album01 permit bob album01 permit alice photo02.jpg permit bob photo02.jpg permit alice photo02.jpg forbid team01 photo01.jpg forbid bob photo01.png forbid forbid に該当するので結果は拒否

Slide 53

Slide 53 text

パフォーマンスの比較 ● Cedar > OpenFAG >> Rego ● 特に Rego に比べ、Cedar はエンティティ数で速度劣化しない https://doi.org/10.1145/3649835

Slide 54

Slide 54 text

Slice による最適化 ● テンプレートからのポリシー生成を行う場合に強い ○ 生成で増えた分のポリシーは Slice で効果的に振り落とせる https://doi.org/10.1145/3649835

Slide 55

Slide 55 text

Section 2 のまとめ ● Cedar によるポリシー記述 ○ Principal / Action / Resource で条件を指定 ○ RBAC / ABAC / 動的なポリシー生成 ● パフォーマンス上の特性 ○ OpenFGA や Rego より高速でスケールに強い ○ テンプレートポリシーに対して Slice が有効

Slide 56

Slide 56 text

理論から見た Cedar 3. Theoretical Aspects of Cedar

Slide 57

Slide 57 text

言語仕様と信頼性 ● 自然言語で書かれた仕様書による定義 ○ C++ / Java / PHP など大多数の言語が採用 ○ 曖昧性や矛盾の発見は人間の観察力頼み ● 形式的意味論による定義 ○ 言語の動作について厳密な数学的ルールを提供 ○ アルゴリズムにより自動化された確実な検査が可能

Slide 58

Slide 58 text

Cedar の形式的意味論 ● ポリシーの評価規則 ○ Alloy / Deny を判定する上で、対象のリクエストが ポリシーの条件に合致するかどうかを定義 ● ポリシーの型付け規則(今日は省略) ○ Schema によるバリデーションの実体は型検査 ○ capability と呼ばれる付帯条件付きの型付けを定義

Slide 59

Slide 59 text

どんな風に「意味」を記述するのか?

Slide 60

Slide 60 text

https://doi.org/10.1145/3649835

Slide 61

Slide 61 text

なるほどわからん

Slide 62

Slide 62 text

【書き換え規則】 エンティティが μ、リクエストが σ であるとき 式 e を式 e’ に書き換えてよい

Slide 63

Slide 63 text

e = resource in PhotoApp::Album::"album01" σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] μ = [ PhotoApp::Photo::"photo01.jpg" => [ owner => PhotoApp::User::"alice", predecessors => { PhotoApp::Album::"album01" } ] ]

Slide 64

Slide 64 text

e = resource in PhotoApp::Album::"album01" σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] μ = [ PhotoApp::Photo::"photo01.jpg" => [ owner => PhotoApp::User::"alice", predecessors => { PhotoApp::Album::"album01" } ] ] 祖先要素を保持

Slide 65

Slide 65 text

e = resource in PhotoApp::Album::"album01" σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] μ = [ PhotoApp::Photo::"photo01.jpg" => [ owner => PhotoApp::User::"alice", predecessors => { PhotoApp::Album::"album01" } ] ] 書き換えたい式

Slide 66

Slide 66 text

σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] x = principal / action / resource に対して リクエストの x が v であるとき、 目的の式内の x を v で書き換えてよい e'= PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01" e = resource in PhotoApp::Album::"album01"

Slide 67

Slide 67 text

σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] x = principal / action / resource に対して リクエストの x が v であるとき、 目的の式内の x を v で書き換えてよい e'= PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01" e = resource in PhotoApp::Album::"album01" 前提条件

Slide 68

Slide 68 text

σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] x = principal / action / resource に対して リクエストの x が v であるとき、 目的の式内の x を v で書き換えてよい e'= PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01" e = resource in PhotoApp::Album::"album01" 可能な書き換え

Slide 69

Slide 69 text

σ = [ principal => PhotoApp::User::"alice", action => PhotoApp::Action::"viewPhoto", resource => PhotoApp::Photo::"photo01.jpg" ] x = principal / action / resource に対して リクエストの x が v であるとき、 目的の式内の x を v で書き換えてよい e'= PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01" e = resource in PhotoApp::Album::"album01" x v

Slide 70

Slide 70 text

μ = [ PhotoApp::Photo::"photo01.jpg" => [ owner => PhotoApp::User::"alice", predecessors => { PhotoApp::Album::"album01" } ] ] エンティティ E1::s1 の先祖に E2::s2 が含まれるとき、 in 式は true に書き換えてよい e'= true e = PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01"

Slide 71

Slide 71 text

μ = [ PhotoApp::Photo::"photo01.jpg" => [ owner => PhotoApp::User::"alice", predecessors => { PhotoApp::Album::"album01" } ] ] エンティティ E1::s1 の先祖に E2::s2 が含まれるとき、 in 式は true に書き換えてよい e'= true e = PhotoApp::Photo::"photo01.jpg" in PhotoApp::Album::"album01" h1 E1::s1 E2::s2

Slide 72

Slide 72 text

人間、どこかで間違える

Slide 73

Slide 73 text

Lean Theorem Prover https://github.com/leanprover

Slide 74

Slide 74 text

Lean による意味論の検証 ● 定理証明支援系と呼ばれるツールの一種 ○ いわば「証明付きの関数型言語」 ● 型に乗せられる情報量が非常に多い ○ 数学的な命題を型で表現し、コンパイル時にチェック ○ 命題 P の証明を受け取って、別の命題 Q の証明を返す といった「関数」が定義できる

Slide 75

Slide 75 text

例:forbid がひとつでもあれば拒否 theorem forbid_trumps_permit (request : Request) (entities : Entities) (policies : Policies) : (∃ (policy : Policy), policy ∈ policies ∧ policy.effect = .forbid ∧ satisfied policy request entities ) → (isAuthorized request entities policies).decision = .deny

Slide 76

Slide 76 text

証明されている Cedar の性質 ● forbid が一つでもあれば他に permit があっても拒否 ● 許可されるのは permit が一つでもある場合のみ ● ポリシーの重複や順序は結果に影響しない ● Slice によるポリシーの絞り込みは結果に影響しない ● バリデーションを通ったポリシーは評価時にエラーが起きない

Slide 77

Slide 77 text

Section 3 のまとめ ● 言語の意味論は厳密に定義できる ○ 各規則は式の書き換えルールを与えている ● 論文中では Cedar の意味論が与えられている ○ ポリシーの評価 / 型付けによるバリデーション ● Cedar の意味論は Lean を用いて検証されている ○ コンパイルが通っていれば証明として正しい

Slide 78

Slide 78 text

まとめ 4. Today’s Recap

Slide 79

Slide 79 text

本日のまとめ ● マイクロサービスでのポリシー言語の役割 ○ 認可(PDP)をアプリ(PEP)から分離 ● Cedar / Amazon Verified Permissions の機能 ○ RBAC / ABAC / テンプレート / バリデーション ● 安全性が理論的に保証されている ○ 形式的意味論 / 定理証明支援系 Lean による証明

Slide 80

Slide 80 text

Implement Your Policies! Presented by チェシャ猫(@y_taka_23)