[レポート]ポリシーを使用してAmazon Verified Permissionsでアクセス許可を管理する #SEC335 #reinvent

2023.01.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、臼田です。

みなさん、re:Invent楽しんでますか?(挨拶

今回は下記セッションのレポートです。

[NEW LAUNCH!] Using policies to manage permissions with Amazon Verified Permissions

Permissions in your application can be based on several factors, including principal’s roles and attributes, resource data, and other contextual information such as method of authentication. By using policy-based permissions, you can decouple authorization logic from your applications, gain better visibility and auditability into access rules, and manage permissions at scale. Join us in this session to learn how policy-based permissions can be applied to your applications using Amazon Verified Permissions, and discover how this fits into the end-to-end journey of application authentication, authorization, and fine-grained access control.

[NEW LAUNCH!] ポリシーを使用して Amazon Verified Permissions でアクセス許可を管理する

アプリケーションのアクセス許可は、プリンシパルの役割と属性、リソース データ、および認証方法などのその他のコンテキスト情報など、いくつかの要因に基づく場合があります。 ポリシーベースのアクセス許可を使用することで、承認ロジックをアプリケーションから切り離し、アクセス ルールの可視性と監査能力を向上させ、大規模なアクセス許可を管理できます。 このセッションに参加して、Amazon Verified Permissions を使用してポリシーベースのアクセス許可をアプリケーションに適用する方法を学び、これがアプリケーションの認証、承認、きめ細かいアクセス制御のエンドツーエンドの旅にどのように適合するかを発見してください。

Emina Torlak, Sr Principal Applied Scientist, Amazon Julian Lovelock, Product Manager - Technical, Amazon Mahmoud Matouk, Principal Solutions Architect, AWS

動画

レポート

このセッションでは今回プレビューとしてリリースしたAmazon Verified Permissionsを使って、アプリケーション内のアクセス許可を管理する方法を説明する。

まずなぜAmazon Verified Permissionsを作ったかの全体像をジュリアン氏が説明し、実際の使い方とアプリケーションのデモをマフムード氏が話し、最後にこの許可システムのポリシー言語であるCedarについてエミナ氏が説明する。

まず、Amazon Verified Permissionsの作られた背景にある課題の話からです。

つまりPermissions(権限)の問題です。あるいはもっと広く、アプリケーション開発者がどのようにアプリケーションでのアクセス許可を管理するかということです。

構築しようとするアプリケーションが何であれ、権限管理は必要です。

例えば銀行のアプリケーションでは、どのユーザー・アカウントでどのような取引が許可されているかを判断する必要がある。

写真共有アプリケーションなら、誰に写真を共有するか、誰が写真にコメントして誰がアルバムを作成できるかを考える必要がある。

人事管理アプリケーションなら、誰が従業員レコードにアクセスできて誰が給与を確認することができるのか。

つまり構築するアプリケーションでは、どのようにアクセス許可を管理するのか、そして実際にユーザーのアクションを承認するのか考える必要がある。アプリケーション内の各ユーザーが何を行うことが許可されているかを説明するためにパーミッションを広く定義できる。

そしてそのアクセス許可をポリシーとして表現できる。簡単に言うとポリシーには2種類あり、ユーザーに対する許可とユーザーに対する禁止です。

また、一般的には2つの認可モデルがある。多くの階層型組織で機能するRBAC(Role-Based Access Control)はユーザーがグループなどの階層に分割され、グループ単位でロールを割り当て、ロールでアクションが決まる。

RBACの欠点は細かいアクセス許可をしたい場合には多数のロールが必要になること。

もう1つのモデルは属性ベースのアクセス制御であるABAC(Attribute-Based Access Control)で、これはコンシューマー向けのアプリケーションでは非常にうまく機能する。保持しているリソースの属性やIDに対して許可を追加していく。

ABACの欠点は非常に不透明になる可能性があること。ルールの分析が難しくその場しのぎの設定になっていることもある。

そのためPermissionsをコードで定義して論理的な評価ができるようにする必要がある。このセッションでは様々なアプリケーションの例を出していく。

まずは金融系の例から。あるユーザーが支払先を追加するためのアクセスとそのアクションを定義します。アプリケーションコードにロジックを組み込んでいるケースが良く見られます。下記のコードではこの特定のトランザクションを保護するための複雑なロジックが組み込まれています。

If employee.dept = 'finance'
and account.type = 'payable'
employee is in 'AP Team'
and payee.location equall "US" or "CA"
then ALLOW else DENY

これはコードの一部となるため問題があります。このアプリケーションで何が、誰が何を行うことが許可されているかを理解するためにアプリケーションコードを効果的に読み取ることができなければならない。そしてこのルールを変更するときにコードも変更する必要がある。組織の変更や新しいレギュレーションも出てくるかもしれない。そして監査が難しい。

以上でモジュラー型のPermissionsシステムに持たせたい特性のいくつかを理解していくことができる。

これらのポリシーはシンプルで読みやすく、RBACとABACをサポートし、監査しやすい必要がある。

非機能要件としては、ゼロトラストポリシー戦略のために非常に低いレイテンシーが必要になる。すべてのアクセスでPermissionsを確認しなければならないから。そして高可用性であり、アプリケーション開発者が簡単に組み込める必要がある。

これを実現するためにたとえば自分たちで権限管理システムを構築することを考えてみる。しかしこれは難しい。なぜか?

時間はかかるし、様々なポリシーに対応しようとするとすぐに複雑になるし、正確に矛盾なく動作するポリシーは設計が難しく自動推論を使いたくなるし(これは後ほどエミナ氏が説明する)、50個のロールで動作するように構築したとしても5万個のロールまでスケールすることは難しいし、多くの場合ガバナンスは後回しになり組み込まれない。

というわけでAmazon Verified Permissionsを紹介する。基本的にAmazon Verified Permissionsが行うのは、ポリシーとして表現されたPermissionsを保持し、アプリケーションがPermissionsを管理し、ポリシーを評価することでユーザーを認可する手段を提供する。

まず大きなレベルでユースケースをいくつか説明する。

金融サービスのアプリケーションを想定する。アプリケーションでポリシーを作成して維持するか、ユーザーはどうやってアクセス許可を生成するか。承認プロセスは?監査は?

アプリケーション開発者を想定して見ていきます。金融サービスアプリケーションを開発しています。

すべてのユーザーに適用するポリシーを考える。アカウント所有者がアカウントにアクセスできるだけでなく、アカウント所有者が不在でも別のユーザーに権限を委任できる、とする。これはアプリケーションの拡張と考えられ、アプリケーションと一緒にデプロイされる。

この画面のポリシーは細かく見えないかもしれないが、ポリシーの中身の詳細は後ほど説明するのでここでは触れない。

まずポリシーとしてRBACでベースラインのアクセス許可を与え、さらにABACでも許可を与えるようにしていくことができる。

もう少し具体的に、ここではCFOであるエンドユーザーのJaneという人物を想定する。彼女は有給休暇を取得するため、不在の間にアカウントの管理を委任したい。これはアプリケーション内でJaneが操作すると、ポリシーが生成されるということ。今回はJeffという人物に#533...というIDのアカウントを委任する。

その後、Jeffがアプリケーションにログオンして支払先の登録を行おうとすると、アプリケーションはAmazon Verified Permissionsに「Jeffが支払先の登録を#533...のアカウントに対して行おうとしているがどうか?」と訪ね、Amazon Verified Permissionsが「allow」をレスポンスします。そしてこれはミリ秒単位で処理されます。

そして監査人はこれらの操作をビューで確認したい。Amazon Verified Permissionsの分析ツールと通常のCloudTrailの監査ログでこれが実現できる。

ここでマフムード氏に交代する。

実際にAmazon Verified Permissionsを構築し、アプリケーションに組み込む方法を説明する。

まずAWSマネジメントコンソールからAmazon Verified Permissionsにアクセスし、ポリシーストアを作成する。ポリシーストアは1つのコンテナであり、違う要件のアプリケーションがあれば別のポリシーストアを作成することができる。

ポリシーストアはデフォルトで空であり、最初にポリシーを記述していく。具体的なポリシーの書き方はまた後で。ここでは簡単にprincipal, action, resourceを定義し、リソースの所有者はそのリソースにアクセスできるという単純なポリシーが書かれている。そして複数のポリシーを作成して認可モデルを作っていく。

ポリシーの作成はマネジメントコンソールでもできるしAPIを経由してCLIなどで行うこともできる。写真の共有や別の従業員への委任など、動的なポリシーを追加していくことが可能。

ポリシーストアにポリシーを追加したら、実際のこのポリシーを検証できる。コンソールに組み込みのツールで実施でき、検証やトラブルシュートに役立つ。

最初のリクエスト部分は、実際にアプリケーションコードからクエリするデータと同じもの。定義したprincipal, action, resourceが何かを指定する。必要に応じて自由フォーマットのリクエストコンテキストを追加できる。コンテキストはランタイムの情報、IPアドレス、時間などポリシーに関連するすべてのものを指定する。そして対象のエンティティ間の関連性を伝えるデータセットをJSON形式で追加する。

そしてシミュレーターが許可か拒否、あるいはエラーの内容などをレスポンスする。この内容に応じてポリシーやデータセットを調整できる。

これを実際のアプリケーションに適用してみます。今回は動物病院のポータルをシミュレートするサンプルアプリケーションを用意しました。動物病院にこの写真に映る犬のOnyxを連れていきます。彼は食べてはいけないものを食べてしまったため、動物病院に連れて行く必要があります。

どのようなシナリオでしょうか?

  • Dave氏はOnyxのオーナーで動物病院につれていきます
  • Dave氏は動物病院のオフィス管理者であるSally氏に連絡し予約を取ります
  • Sally氏はOnyxの主治医であるDr. Janeに予約を割り当てます
  • Dr. JaneはOnyxの主治医のため、Onyxの過去の履歴と以前の訪問記録にアクセスできる
  • Dr. JaneはOnyxにレントゲンが必要だと判断し、レントゲンの専門医であるDr. AdamをDave氏に紹介します
  • Dr. AdamはDave氏とOnyxの情報にアクセスできるようになります

このシナリオがサンプルアプリケーション上で動作します。ポリシーの評価や変更を見ていきます。

まずは単純に、クライアントのデータを表示し、予約をスケジュールします。このシステムには様々なペルソナがあり、すべてのペルソナに様々な権限があります。

まずDave氏がログインします。

彼は患者(クライアント)であり自身の記録を見ることができます。

自分のプロフィールは見ることができますが、

予約を取ることはできません。

そして専門医に紹介(referral)することもできません。この操作はオフィス管理者を経由する必要があるからです。

3つのアクションを確認しました。情報の確認、予約のスケジューリング、患者を紹介する。1つだけ許可され、2つは拒否されていました。

続いてSally氏のアクセスです。

彼女はオフィス管理者であり、このクリニックのすべての患者を閲覧でき、

これらの患者のプロフィールを確認することを許可され、

予約もできますが、紹介はできません。

Dave氏を実際に予約できました。

これをどのようにポリシーにするか説明します。

最初のルールはすべてを拒否したいということです。このクリニックポータルが複数のクリニックで使用されていることを想定し、別クリニック間のアクセスを禁止するように記述します(principal.clinicIDresource.clinicIDが一致しない場合forbidする)。これは、これが決して起こらないという安全なチェックである。

2つ目のルールは患者が自分の情報を表示できるようにします。これはClientタイプのprincipalが、principalresourceが一致する場合に、GETのactionを実行できます。この記述方法は色々あり、後ほど最適化します。

続いてオフィス管理者のポリシーです。クライアントレコードを表示し、予約を実行できます。これは単純なロールベースのアクセスです。

主治医はRBACとABACを組み合わせています。このポリシーは主治医というRoleに対して適用され、prinsipalと患者(resource)の間で属性が一致するABACの条件が存在しています。

こういったポリシーをどんどん追加していきます。

次のユースケースを見ていきましょう。どのようにアプリケーションが許可を追加するかです。この例ではDr. JaneがOnyxを専門医に紹介します。

まず専門医であるDr. Adamとしてログインします。

現時点ではDr. AdamはDaveとは関係がないため、患者の情報を表示できません。

もちろん予約を取ったり、

紹介したりもできません。

Dr. JaneでログインしDave氏(及びOnyx)をDr. Adamに紹介します。この紹介状の期限を3ヶ月とし、レントゲンの取得を依頼します。これにより動的なポリシーがポリシーストアに作成されます。

そのため、再度Dr. AdamでログインするとDave氏とOnyxに関する記録を参照できるようになりました。

この裏側では何が起きたのでしょうか?アプリケーションが動的ポリシーを追加しています。

まず専門医に適用される全体的なポリシーをロールベースに記述し、条件としてprincipalAdamresourceDave、タイムスタンプのコンテキストを追加しました。

ではアプリケーションのアーキテクチャはどうなっているでしょうか?ここまで6つのポリシーを追加しましたがどのように評価されますか?

この図では左側にアプリケーションがあり右側にバックエンドAPIがあります。間にAPI Gatewayがあります。今回はIDプロバイダーとしてAmazon Cognitoが上に書かれています。今回利用しているユーザーのログイン制御と資格情報のための属性などを管理します。

そして図の下にはAmazon Verified Permissionsがあり認可のエンジンとして動作しています。

フローはまずAmazon Cognitoでサインインするところから。オプションでフェデレーションできます。パブリッククライアントはパスワードで、従業員は企業のIdPでサインインさせるというのはよくあるシナリオです。

サインイン後、Cognitoはアプリケーションにトークンを発行します(図左下)。これらのトークンは署名され改ざんが防止され、一般的な所属するグループや、アプリケーション固有の保険の有無など追加の属性情報などを取得できます。

フロントアプリケーションからAPI Gatewayへのアクセスは認可のためこのトークンをAuthorizationヘッダーに入れて渡し、API GatewayはLambdaオーソライザーを使用して評価します。Lambdaオーソライザーはトークンを検証し、クエリをフォーマットし、Amazon Verified Permissionsへクエリし、許可または拒否をAPI Gatewayに返します。

許可された場合バックエンドを呼び出し、拒否ならクライアントにエラーを返します。

もちろんこれは1つの例で、API Gatewayの代わりにAppSyncを利用するなどもできます。

ここでLambdaオーソライザーが行っていることが重要なため、詳細を見ていきます。必要な確認はこのprinsipalはこのactionをこのresourceに対してこのcontextで実行できるかです。これを元にコードを起こします。4つのステップです。

まずAuthorizationヘッダからトークンを取得しそれを検証します。

続いてAmazon Verified Permissionsに対するクエリを作成していきます。ポリシーストアのIDを指定し、トークンからprincipalを取得し、APIからアクションを取得し、アクセス先のパスからリソースを取得し、現在時刻を取得し、データセットを作成します。

クエリを作成したら実際にクエリします。Amazon Verified Permissionsは他のサービス同様APIで呼び出せます。そして最後にその結果を判断してレスポンスします。

これがアプリケーションのコードです。アクションが沢山あろうがユーザーの種類が沢山あろうが、コードは変わりません。そしてAmazon Verified Permissionsというマネージドサービスにオフロードできるため運用負荷は非常に少ないです。

続いてエミナ氏に交代し、ポリシー言語であるCedarの詳細説明です。ここでは設計と開発について深く掘り下げ、ポリシー言語であるCedarがユニークである理由について説明します。

Cedarは認可のために新しく設計されたドメイン固有言語であり、3つのバッテリーを持っています。人間工学に基づいた構文とセマンティクスがあり、高速で安全な実行時間があり、強力な静的分析ツールがあります。認可は非常に重要であり、Cedarは高水準の保証を備えています。自動推論や差分ランダムテストなどの手法を使用しています。

詳細に入る前に、Cedarのような言語を構築する難しさを説明します。これには3つの課題があり、本当に必要なことを定義できる表現力、パフォーマンスとレイテンシー、本当に適切に動作できるかです。例えばリストを作ってループしたらいつまでも終わらないかもしれないし、高速化するためにC言語を採用すれば安全性が損なわれるかもしれないし、殆どの場合に適切に動作しても一部で問題が起きるかもしれない。

Cedarを構築する前に、既存のものを利用できるか確認していった。これらは大きく2つに分類できた。1つは非常に表現力豊かな言語とエンジンがあった。でも表現力が豊かだとパフォーマンスを発揮できず分析もできなかった。もう1つは高速な言語のクラス。高性能で分析は簡単だが、表現力が足りずRBACしかできないし分析もできない。

この分野に必要だったのはCedarのように表現力、パフォーマンス、分析能力という競合する懸念事項のバランスを取る言語だった。

ではCedarを見ていく。まずは言語の設計から。写真共有クラウドのユースケースで考えてみる。

このユーザーであるjaneは自分の写真をクラウドにアップロードし、タグ付けをし、アルバムを作成したい。そしてjaneは別のユーザーやユーザーグループに写真を共有したい。例えばjaneはartアルバムを作成し、これへのアクセスを友人に許可します。この写真はnatureタグが設定されていて、2MB以下です。

それでは金融アプリ・写真共有アプリ・動物病院アプリのように異なるものでも同じように表現できる言語には何が必要でしょうか?まず独自のデータ型を指定できること。必要なタイプ・階層・属性は自分で追加します。そして属性は様々な場所で作られ開発者が直接コントロールできないこともあるため、JSONをサポートする必要があります。そしてシンプルに読み書きできなければいけません。設定と監査のためにも。

この要件は2つのブロックで満たすことができ、ベースとしてのRBACと追加のABACで構成できます。

ここではRBACを緑色で示しています。これがポリシーのスコープでheadになります。in演算子と等式制約==のみ使用します。

更に制限したい場合にABACを記述します。Cedarは任意のブール式でこれを書いていきます。ループはなく副作用はありません。

ここで1つ疑問が出てきます。すべてABACで記述しないのはなぜでしょう?

一番の理由は可読性です。構造化された物を見ればひと目で何が起きているかわかります。そして、これは評価の効率が上がります。Cedarはslicingという特性を活用してポリシーストア全体に対してインデックスを作成し、迅速に評価します。

続いてどのようにこのエンジンを構成するか。

Cedarは3つの入力が必要です。リクエスト、エンティティデータ、ポリシー。そしてこれらをAuthorizerモジュールに渡します。Authorizerはevaluatorを使って1つのポリシーに対してtrue, false, errorのいずれかを返します。そして複数のポリシーの結果を統合しallowかdenyを判断します。

どのように速度を確保するか、そのためにCedarはRustで実装されています。RustはCのような低レベル言語のパフォーマンスとメモリ特性を備えた高レベル言語です。参考までに数百のポリシーと数千のエンティティを含む一般的な認可の検証は1ms以内に処理されます。

しかし正しさを得ることはプログラミング言語だけでは実現できません。リファレンスエンジンを別で作り、差分ランダムテストを実施します。これはDafnyで実装されています。Dafnyはビルドされたエンド層改善プログラムと検証ツールを備えた、別言語に変換できるプログラミング言語で、数学的証明が可能になる。この安全機能がセキュリティを確保する。

そしてこれはポリシー作成者のために提供される静的分析ツールにつながる。

静的分析ツールはすべての可能な入力に対する普遍的な回答を迅速にできる。

例を見ていく。このツールを利用して同等性分析を行う。これにより安全なリファクタリングが可能。

ここでは写真共有のユースケースでポリシーを追加している(左側)。ポリシーを深く読み込むことはここでは期待していない。ポリシーをどんどん追加していくと、可読性が悪くなるためリファクタリングしたくなる。というわけでそれを書いてみた(右側)。これを書いたときは、多分正しいだろうと考える。

では実際はどうだろうか?分析を行うと、膨大な入力をシミュレートしてこれが一致するかを確かめる。

ここでの結果はNoだ。新しいポリシーでは一部が許可されなくなった。その結果のデータセットが表示される。

この内容を元に修正する。修正方法は色々な書き方がある。今回はリソースを知っているときと知らないときで分けて記述した。

同等性分析はあくまでCedarで実現できる1つの例に過ぎない。分析の種類を思いついたらぜひ教えてほしい。

Amazon Verified Permissionsは現在プレビューで、ここから申し込むことができる。ぜひ利用してフィードバックしてほしい。

感想

これまでAWS上で構築したアプリケーションの認可(AuthZ)は自分たちで頑張る必要がありましたが、Amazon Verified Permissionsによってこの労力がオフロードできそうな期待感が非常に高まりました。

特にCedarというすでに考え抜かれた安全な設計と、実際に運用で活用できる分析ツールを兼ね備えた言語という巨人の肩に乗れるのであればメリットは大きいでしょう。

気になる方はぜひプレビューに申込みましょう!そしてフィードバックするのです!