見出し画像

FastAPI でロールによるアクセス管理

みなさん、FastAPI使ってますか!? 僕は今年もこれで行く予定です!
さて、昨日(1/11)にPython 3.12 のサポートする 0.109.0がリリースされました。 3.9や3.10指定のライブラリが今現在も多いので僕はまだ使わないですが、選択肢が多いのはありがたいですね!

https://fastapi.tiangolo.com/release-notes/#01

本題ですが、昨年FastAPIで実装してきたプロジェクトのAPIを本番用にアップグレードする必要があり、FastAPIでロールアクセス制御はどう書くのがスマートなのか?ということで調べてみました。


結論1 

パーミッションを解決する専用のサービス(有料)があり、こちらを使うと専用のAdminツールから管理ができ、コードも以下のように簡単に実装できます。ほうほう、なるほど。。。

permit = Permit(
    pdp= os.getenv("permit_pdp_url"),
    token= os.getenv("permit_sdk_key")
)

async def authorize(request: Request, token: str = Depends(token_auth_scheme), body={}):
    resource_name = request.url.path.strip('/').split('/')[0]
    method = request.method.lower()
    resource = await request.json() if method in ["post", "put"] else body
    user = token.credentials

    allowed = await permit.check(user, method, {
        "type": resource_name,
        "attributes": resource
    })

    if not allowed:
        raise HTTPException(status_code=403, detail="Not authorized")

GUIのメニューで楽々管理できるということで素晴らしいサービスなのですが、Pro版は$125/月と2万円近くなります。無料プランもあって 1000MAU、20テナントまでは無料だそうです。制限来れる状態なら2万円払うのは全然問題ないケースがほとんどでしょう。

アクセス制御の設定はpermit.io で変更すれば、コードの変更なく動いてしまうわけなんです。テストとかも楽そうですね

curl -X PUT http://localhost:8000/tasks/4 \
    -d '{"title": "New Task", "checked": "false"}' \
    -H "Authorization: Bearer user@permit-todo.app" \
    -H 'accept: application/json' \
    -H 'Content-Type: application/json'

考慮すべきは以下になりそうです

  • 費用

  • 対応言語:Go, NodeJS, Python, Ruby, Java, DotNe)。 (日本で大人気なPHPや Erlang, Rust はBetaです)

  • permit.io のコンソールなどの使い方を覚えないといけない

結論2 (EasyAuthを使う)

EasyAuthはOSSのFastAPI Auth管理サービスのプロジェクトで、Azureのサービスとは別ものものです。

データベースの使用量をほとんど行わずに、ユーザー、グループ、ロール、または権限に基づいて FastAPI エンドポイントを簡単に保護します。
グループ・ロールという伝統的なアクセス制御なので導入しやすいですね。

素晴らしいなーと思ったのは以下のKey Features で、複数のサービスで共通で使える集中認証、Oauth連携、トークン時間切れの処理までケアされています。これ使えば優勝か!?

  • 集中認証 - ユーザーと権限を単一の場所でアプリ間で共有

  • きめ細かなエンドポイント セキュリティ - ユーザー ID を確認し、各ユーザーまたはユーザー グループが誰に、何にアクセスできるかを明示的に定義します。

  • 管理 GUI - ユーザー、権限、トークン、OAuth などを簡単に管理できます。

  • 高度な JWT - 無効化機能が組み込まれたトークンベースのクライアント認証

  • Google Oauth - Google ログインを簡単に設定できます

  • 統合されたログインと Cookie 管理 - ユーザーは認証および許可されるだけでなく、トークンの有効期限が切れると Cookie システム経由でログイン ページにリダイレクトされ、その後最後の場所に戻されます。


パーミッションと制御の要素は以下のようになっています。

Group

Role

Action

Tokens

実際にリポジトリのコードを見ると server,client がありちょっと混乱しますが、以下の動画を見るとなんとなく使い方がわかります。

Easyauth clientを学ぼう!

さて実行します、とエラーが…一瞬固まる様子がリアルで笑ってしまいました。


Easyauth server を学ぼう!


結論3

→2を利用して1のような雰囲気の実装にしてみる。

permit = Permit(
    pdp= os.getenv("permit_pdp_url"),
    token= os.getenv("permit_sdk_key")
)

このPermit に相当するクラスを2の仕組みを利用して書けば、表面的にはpermit.io の洗練された雰囲気になりそうです。

3つあるって結論出てないじゃん!ってなりそうですが技術って数学とちがって答え1つじゃないので一応。。。(言い訳

なぜ君は書かないのだ

これらの処理は場当たり的に書く分にはなんら難しいことはありませんが、なぜ様々なサービスやモジュールが世の中にあるか、それはもちろんアプリの首根っこと言って良い重要部分だからですね。
そして、関わる開発者すべてに関係するのでできれば自前で書かず広く使われる方法のほうが学習コストが小さく、もちろんバグのリスクも小さいので毎回書くのは避けたいところです。

ですが、意外と仕様書が整ってないことが多いのです。こっちは逆に毎回毎回、面倒でも書かないといけません。
初期の頃にあったものがメンテされない、というのが一番多いケースかと思いますが問題が起きてからは相談をするにもコードを見るしかなくなってしまいます。
ロール権限処理を書く前・変更前に、関連仕様をきちんと整備したいものです。

付録:アクセス制御のいろいろトレンド

結論が出るまでに調べたことも付録として書いておこうと思います。
ロールベースのアクセス制御でOKかと思っていた原始人だったのですが、調べたら時代はABACとかハイブリッドとかになっているようです。確かに細かいことに対応できないですもんね。

現代ではアクセスコントロールは RBAC, ABAC, ReBAC、PBAC など、多様化するネットワークサービスに合わせていくつかの考え方、実装があります。

以下はトレンドになっているアクセス制御の考え方の比較です

ABAC  vs RBAC

RBAC は、権限が設定された事前定義されたロールに重点を置いているのに対し、ABAC は、より動的な意思決定のために複数属性のフレームワークを導入しています。

Roles & Permissions Matrix。これだけじゃ足りない場合はどうすれば良いのですか

RBAC では、「マネージャー」の役割が部門内で広範なアクセス権を持つ場合があります。
ABAC はプロジェクトの割り当てや場所などの追加属性を考慮することでこれを改善し、よりカスタマイズされたアクセスを提供できます。

ABAC vs ReBAC

ReBAC は、エンティティ間の関係を考慮することで、アクセス制御に別の次元を追加します。たとえば、ソーシャル ネットワーキング プラットフォームでは、アクセス制御はユーザー関係 (友人やフォロワーなど) の性質に依存する場合があります。ABAC は複数の属性の評価に多用途ですが、本質的にはこれらの関係ダイナミクスを考慮しません。

ABAC vs PBAC

ABAC は、アクセス決定に幅広い属性を活用することに重点を置いた、PBAC の特殊な形式とみなされます。PBAC はより広範なポリシーベースの制御を包含しますが、ABAC はきめ細かい属性中心のアプローチで差別化されています。

PBACは、ABACモデルをベースに、ユーザー認証以外のアクセスの許容範囲を表現できるようにしたもので、アクセス制御の定義、適応、自動化の幅を広げます。

RBACとは?

Role-based access control (RBAC) 

ロールベースのアクセス制御 (RBAC) は、 事前定義されたロールに基づいてアクセス制御を決定するために使用される認可モデルです。権限はロール (「管理者」や「ユーザー」など) に割り当てられ、ロールは管理者によってユーザーに割り当てられます。この構造により、誰が何にアクセスできるかを簡単に理解でき、アクセス制御の基本形となっています。

PBACのパーミッションは個別に設定されているため、ビジネスや規制上のニーズに応じて、コントロールを正確かつ直感的に、段階的に変更することが可能であり、時間をかけてメンテナンスを行う必要がないため、「最小特権」アーキテクチャの可能性を最大限に引き出すことができる。

RBAC を使用すると、権限のないユーザーがリソースにアクセスすることがより困難になるため、セキュリティが向上し、個々のユーザーごとに手動でアクセス権を割り当てる必要性が減り、効率が向上します。(以下、例)

  • 管理 者はブログ 投稿を作成、 編集、 削除、 表示できます 。

  • ライター はブログ 投稿を作成、 編集、 表示できます

  • 編集 者はブログ 投稿を編集および 表示できます

ABACとは?

Attribute-Based Access Control (ABAC) の頭文字をとったもので、日本語にすると属性ベースのアクセス制御 です。

精密ななアプリケーションのセキュリティとアクセス制御のために、ロールよりも属性を使用する高度な認可モデルの考え方で、ABAC は、ロールではなく属性 (または特性) に適用される条件に基づいてアクセスを決定するため、きめ細かい複雑なアクセス制御ルールを定義できます。

4つの属性

ABAC モデルがアクセス ポリシーを作成するために利用する属性には 4 つのタイプがあります。ABAC ポリシーでは、コンテキストとポリシー要件に応じて、これらの 1 つまたはすべてを一緒に使用できます。

  1. サブジェクト属性: これらには、役割、部門、セキュリティ クリアランスなどのユーザー関連の特性が含まれます。これらは、ABAC フレームワーク内でユーザー ID のバックボーンを形成し、アクセスの決定をガイドする詳細なプロファイルを提供します。

  2. リソース属性: これらは、アクセスされるアセットまたはオブジェクト (ファイル、アプリケーション、API) に関連します。ファイル タイプ、機密レベル、所有権などの属性は、アクセス制御方程式におけるリソースの性質を定義する際に重要です。

  3. アクション属性: これらは、リソースとのユーザーの対話の性質を定義します。
    アクションは通常、実行されるアクションのタイプ (読み取り、書き込み、編集、削除など) を記述し、「頻度」 (アクションの実行回数の制限など) などのアクション属性と組み合わせることができます。

  4. 環境属性: これらは、時間、場所、使用されたデバイスなど、アクセス要求のより広範なコンテキストをキャプチャします。このディメンションにより、ABAC に動的な側面が追加され、ポリシーがコンテキストの変化に適応できるようになります。

ABAC の利点

  1. 粒度: ABAC は、意思決定時に幅広い要素を考慮することで、精度の高い政策立案を可能にします。この粒度は、基本的な役割ベースの制御をはるかに超えて拡張され、特定のコンテキスト駆動型のアクセス決定が可能になります。

  2. 柔軟性: ABAC のポリシーは、組織のニーズの変化に合わせて動的に調整できます。各国のさまざまなデータ保護法に基づいてアクセス権を調整する必要がある多国籍企業を考えてみましょう。ABAC ポリシーは、アクセス制御システムを完全に見直すことなく、これらの法的変更に準拠するように迅速に適応できます。

  3. スケーラビリティ: ABAC は、増加するユーザーとリソースの量を効率的に管理します。たとえば、急速に成長しているテクノロジー企業では、新しい従業員が入社し、新しいプロジェクトが開始されると、ABAC はポリシーを定期的に再構成することなく、これらの変化に合わせてシームレスに拡張できます。

  4. 強化されたセキュリティとコンプライアンス: ABAC の詳細なアクセス制御により、セキュリティが大幅に向上します。金融機関では、ABAC を使用すると、ユーザーの役割、場所、取引コンテキストの組み合わせに基づいて機密の財務記録へのアクセスを制限できるため、データ侵害のリスクが軽減され、金融規制へのコンプライアンスが確保されます。

  5. 管理オーバーヘッドの削減: ABAC は、属性に基づいてアクセス決定を自動化することで、手動介入を最小限に抑えます。たとえば、大学の設定では、学生の在籍状況、コース登録、学業上の役割に基づいて学業記録へのアクセスを自動的に調整できるため、IT スタッフの管理負担が軽減されます。

これらの利点はそれぞれ、アクセス制御に対する ABAC の微妙なアプローチが実際にさまざまな分野にどのように適用できるかを示しており、複雑なセキュリティの課題に対処する際のその多用途性と有効性を示しています。

ABACの課題

属性ベースのアクセス制御 (ABAC) を採用すると多くの利点が得られますが、次のような課題を認識することが重要です。

  • 複雑な実装: ABAC を確立するには、ユーザーとリソース全体にわたる広範な属性セットを定義する必要があります。この複雑さは、運用およびセキュリティのダイナミクスについての深い理解を必要とするため、技術リソースが限られている小規模な組織にとっては特に困難になる可能性があります。この複雑さは、ポリシーやコードの分離などのベスト プラクティスを使用することで軽減できます。

  • 複雑なポリシー管理: ABAC では、コンテキスト固有の詳細なポリシーの作成が必要になりますが、そのポリシーは数が多く複雑になる場合があります。この複雑さにより、組織のニーズの変化に応じてポリシーの関連性と有効性を維持するには、細心の注意を払った管理が必要になります。これらのポリシーは、ポリシー管理ソリューションを作成または導入することで管理できます。

  • パフォーマンスのオーバーヘッド: ABAC の詳細な属性評価プロセスは、システムのパフォーマンスに影響を与える可能性があります。迅速なアクセスの決定が必要なシナリオや大規模な展開では、複数の属性や複雑なポリシーの処理によるリソース集中により、遅延の問題が発生する可能性があります。

  • ポリシーの競合のリスク: ABAC ポリシーの粒度の細かい性質を考慮すると、特に多数の属性や条件が関係する場合、ルールの競合が発生する可能性があります。これらの競合を解決するには、アクセス制御の決定における一貫性と明確さを維持するための慎重なポリシー設計と定期的なレビューが必要です。

  • データ同期: アプリケーションは多くの場合、意思決定プロセスを支援するためにデータ ソース (内部または外部) に依存します (支払いステータス (Stripe に含まれ管理される情報) に基づいてアクセスを制限することを考えてください)。関連するすべての属性データを意思決定時点に取り込むことは、かなりの課題となる可能性があります (ただし、OPAL などのツールを使用すると、それを軽減できます)。

付録2:ロールベースの表、その起源?

ロールベースの表はマイクロソフトが2012年ごろ?出版した要件定義の本「Visual Models for Software Requirements」で広く知られるところになったと思います。 有料のSaaSサービスなどでも価格のページでこれの簡単バージョンを目にしますが、開発をしていると驚くほど(炎上案件で)これがありません、日本の企業。

おそらく専門知識がない人が年功序列などで管理職・マネージャー・リーダーになれることが原因だろうと推測しています。

有名な表

この本は高いですが図が多く、当たり前なことが書いてあって元はすぐに取れる名著かと思います。英語の勉強にも良いです!


⇩のを書いて気がついたら1年。 時間が経つのがあっという間で焦ります。(汗


EasyAuth の Google oauth ログイン と併用の記事


サポートありがとうございます😊 ベトナムにお越しの際はお声がけくださいね🌻