認証認可とワンセットで語られることが多い印象だが、今回話すのは「認可(Authorization)」の話だ。「認証(Authentication)」の話は含まない。
(システムで言う)認可とは、大雑把に言うと「誰が」「何を」「どうすることが」「できる/できない」の要素に従って判定することだ。
どちらも略すと「Auth」になってしまってクラス名が衝突したりするので困ることがある。区別するために認証はAuthN、認可はAuthZと略されることがある。「WebAuthn」などは一例と言えるだろう。
弊社内ではまず話題になってこなかったため、実装の話が流れたとき、非エンジニアからは「認可?権限と何が違うの?おいしいの?」といった声が聞かれたり聞かれなかったりした。
認可制御の種類
認可制御にはいくつか種類があるので大雑把に紹介してみよう。
- ACL
- 単純な「誰が」「何に」「どの操作を」することを許可するかのリスト
- DAC
- よくあるOwner、Group、Everyoneに対してRead、Write、eXecuteを設定する形式
- 所有者が権限を決定する
- MAC
- DACの所有者ではなく管理者が権限を決定するバージョン
- RBAC
- 特定の「ロール(役割)」を想定したアクセス制御であり、アクセス権の束を「ロール」として設定し、そこにユーザーを割り当てる
- ABAC
- 属性ベースのアクセス制御。例えば「30代」「男性」「独身」などの属性でアクセス制御をする
- IBAC
- 認証後の認可はACL
その他、調べれば「XXAC」系の認可制御はたくさん出てくる。
MNTSQで採用した認可制御
ではMNTSQ(モンテスキュー)で採用した認可処理は何かというと、「RBAC」である。弊社のクライアントは主に大企業であり、基本的に部署や階級があるため、それに基づいたロールが設定する可能性が高かったことが選定理由となっている。おまけの話だが、SlackもRBACを参考に実装しているようだ。
ただ、RBACをベースにどのように実装するのか、そもそもRBACとは何であるか、どのような制御をするものかなどの資料が圧倒的に乏しいのが現状である。実際に書いてみて分かることだが、機密性の高い仕組みを公開することになってしまうので、公開されづらい傾向にあると思われる。
幸いなことに、RBACについてはANSIのPDFが公開されており、また日本語の論文も存在している。これらを読むことでRBACの仕様について理解を進めることが可能だ。
認可のrailsのgemの紹介
認可について、主に2つのgemが有名である。いずれも簡易なACLと言えそうだ。
pundit
モデル側から認可制御をする方式をとっているgemである。
対象のモデルがPostであればPostPolicyという名前のクラスを作成し、そこでどのような条件のユーザーにreadやwriteを許可するかを指定することが可能となっている。つまり、テーブルの数に比例して同名のPolicyクラスが増えていくことになる。
実装は以下のようにし、
class PostPolicy attr_reader :user, :post def initialize(user, post) @user = user @post = post end def update? user.admin? || !post.published? end end
実際の認可処理では以下のように「何を」「どうするか」を指定して実行する。
def publish @post = Post.find(params[:id]) authorize @post, :update? @post.publish! redirect_to @post end
cancancan
一見ふざけた名前だが、認可のgemとしては有名どころである。こちらは「誰が」側から認可を実装するかたちだ。
認可用のクラスを作成し、ユーザーをラップするかたちでインスタンタイズし、必要箇所で権限の有無の判定をすることができる。
実装は以下のようなかたちでクラスを実装し、
class Ability include CanCan::Ability def initialize(user) can :read, Post, public: true return unless user.present? # additional permissions for logged in users (they can read their own posts) can :read, Post, user: user return unless user.admin? # additional permissions for administrators can :read, Post end end
以下のようにController、Viewなど各所で認可処理をすることができる。punditと同じく「何を」「どうするか」を指定する。
<% if can? :read, @post %> <%= link_to "View", @post %> <% end %>
def show @post = Post.find(params[:id]) authorize! :read, @post end
MNTSQの認可制御の実装
MNTSQでは上記のgemでは複雑性を回避しづらいため、これらのgemは利用していない。自前で実装をすることとなった。実際のコードについては公開を控えさせていただくので、その点ご了承いただきたい。 MNTSQで認可処理を実装する際のポイント MNTSQの認可制御の複雑さは、1つの書類に対して契約データベース、契約管理、案件管理という3つの方向から認可制御をする必要があることだ。
衝突が発生した場合には、それぞれのORをとることで解決することとした。なぜなら、ある書類を案件管理から閲覧可能であれば、契約データベースからでも閲覧可能であって良いという整理が可能だったからだ。逆に、例えば契約管理で閲覧不可と設定されていた場合、契約データベース、契約管理、案件管理どの角度から閲覧しようとしても不可にするという制御とした。
また、関連するテーブルの数が30以上に上り、個別に管理するとメンテナンス性が損なわれるため、それらを中央集権的に管理する必要性に迫られていた。
これらについては、テーブル名と閲覧権限のペアを定義し、それをベースにフィルタリングする仕組みを導入した。
RBACは抽象的な仕様
RBACを実際に適用するに際して苦労した点としては、仕様としてはどのようなシステムにも適用可能なように抽象度が高く書かれているため、RBACを実際のシステムに適用するための間を自前で埋める必要があることだった。
それらをAWSなど他所のシステムの認可制御を参考にしながら、「MNTSQ用語」として落とし込んでいる。開発者や営業など非開発者の間での認識がずれにくいように、認可制御について記載したマークダウンを準備したり、認可の実装にあたって打ち合わせを何度か行い、認識合わせに注力した。ちなみに主に参考にしたのは、AWSのIAMの仕組みだ。
RBACをどのように実装したか
弊社ではgrapeというgemを利用してAPIを実装しているが、これにはRailsで言うApplicationController相当のroot.rbというファイルが存在しているので、そこでAPI全体に対する認可制御を包括的に行うことにした。
認可制御についてはフロントエンドでも「書類の削除ができない場合は削除ボタンを出さない」などの認可制御が必要なため、対象のリソースに対する認可情報を問い合わせるAPIを実装した。
検索にはElasticsearchを利用しており、ここの認可処理についてはRailsの効力が及んでいないため、自前の認可制御の仕組みのデータを作り、独自のプラグインを開発して認可を実装している。
構造上、速度に大きく影響する可能性が高かったため、キャッシュをする仕組みを導入することとした。キャッシュの設計をどうするかなどは当然RBACの仕様には書かれていないため、「誰」「何」「どのアクション」「ロール」のどのレベルでキャッシュを効かせるのが良いのかも悩みポイントとなった。ここはシステムによって最適なポイントが変わってくると推測されるが、MNTSQではユーザー側(「誰」)に寄ったキャッシュの持ち方をすることとした。
実装してみてどうだったか
弊社ではrspecでテストを書いているため、一定のバグを防ぐところには至っているが、いかんせん仕組みが複雑なため、カバーし切れていない部分の修正を続けているところだ。
また、システムに合わない部分について、ドラスティックに仕組みの変更を進めている途上である。
今後起こり得る事象
今後に起こり得る事象について、まだ運用が始まったばかりであり、残念ながら申し述べることができない段階にあるのだが、面白い資料をご紹介しよう。
この資料では企業において人事異動、組織改変、プロジェクト型や組織型など想定されるロールモデル、今後どのような問題が起こり得るか、そのために事前にどのようなことを決めておくべきかといったことが書かれた資料となっている。ぜひとも参考にしていただきたい。
参考文献一覧
- Access Control Acronyms: ACL, RBAC, ABAC, PBAC, RAdAC, and a Dash of CBAC - DZone Security
- Role Management at Slack
- American National Standard
- エンタープライズ ロール管理解説書 (第3版)
- アクセス制御の種類---DAC,MAC,RBAC | 日経クロステック(xTECH)
- アクセス制御 - Wikipedia
- What is Identity-Based IBAC Access Control? – Digital Masta
- Authorization in Rails controllers: Pundit versus CanCan
We are hiring!
上記の通り、MNTSQはまだまだ進化の途上である。複雑な課題にチャレンジしてみたい人も、そうでない人もぜひ右上の採用ページから応募してみて欲しい。