という悩みについて、記事でお答えしていきます。
この記事を読むことで、権限管理とはなにか、その際に押さえておくべきRBACとABACについて、また権限管理を設計するやり方の一例がわかるようになります。
私はエンジニアとして、主に立ち上げのフェーズで20以上のサービスを開発してきました。権限管理は、どのサービスにも必ず入ってくるプロセスでした。ここでの経験や、調べたことをもとにこの記事を書いています。
この記事でいう権限管理とは、ユーザー認証を行った相手に対して、『誰がどの機能に対してなにをしていいのか、あるいはしてはいけないのかを管理すること』をいいます。
たとえばTwitterにおける権限管理について考えてみると、次のようになります:
こういった、サービス内の行動に対する権限を設計するのが権限管理ですね。この権限管理について、この記事で書いていきます。
権限管理がなにかはわかったよ。じゃあ具体的にどう設計すればいいの?
Googleで『権限管理 設計』で検索してもらってもわかることですが、権限管理にはいろんなやり方があって、ベストプラクティスはないと思っています。この前提で、私はシートで管理するやり方をとっています。
たとえば次のような感じですね。これは架空のドキュメント共有サービスを例に作ってみています:
このシートには、次のようなことを書いていきます:
項目 | 内容 | 例 |
---|---|---|
機能 | どの機能に対する権限か | 投稿閲覧 |
役割 | どの役割に対する権限か | 一般ユーザー / 管理者 |
属性 | どんな属性をもったユーザーに対する権限か | 同じグループに属していること |
対象となるデータ | 処理するデータはどれか | グループのメンバーの投稿 |
処理の可否 | 処理をできるのかどうか | できる / できない |
説明 | その権限の概要 | 同じグループのユーザーの投稿を閲覧できる |
開発が進むにつれて、機能が追加・削除されて、権限もどんどん変わっていくことになります。その度に、このシートを更新していきます。
すべての権限管理が一枚のシートに集約されている状態がベストですね。
上の表で、権限管理には『役割』と『属性』があると書きました。これについて、権限管理を設計する上でRBACとABACという考え方が大切なので、それぞれについて書いていきます。
RBACは『ユーザーの役割によって権限のチェックを行う』やり方です。役割とは、たとえば一般ユーザーや管理者などがありますね。
権限を変更するだけで処理の可否を変更できるという利点がありますが、権限がふえると管理や実装が大変になってきます。
『管理者』のような役割以外にも、WritableやReadableのような複数のパーミッションを持たせるようなやり方もあります。
ABACは『ユーザーの属性によって権限のチェックを行う』やり方です。たとえばツイートの投稿者かどうか、あるいは同じグループに所属しているかどうか、ですね。
ABACは柔軟な権限管理ができる一方で実装が大変だったり、ものによってはデータベースへのアクセスがふえてパフォーマンスが悪くなったりします。
RBACとABAC、どっちのやり方がいいの?
RBACとABACは、システムの種類によって使い分けるとよいですね。ひとつのシステム内で両方を使うことももちろんあります。
権限管理の設計はシートでやるといい、と書きました。その手順としては、次の3つでやるとスムーズに設計できます。
まずシステムの機能を洗い出して、それぞれの機能に対する権限をシートにまとめていきます。このとき、重複した権限が出てきます。たとえば:
という二つの権限があったときに、『ブロックされている管理者』は投稿を閲覧できるのかどうかを考える必要が出てきます。
こういった重複について、ひとつひとつどうするかを決めていきます。
権限を設計するやり方はなんとなくわかった。あとは実装していくだけだね。
次はコード面での設計についてです。権限は、データベースなどのデータとのやりとりが発生するところでチェックするといいですね。
たとえばフロントエンドにJavaScriptを用いていて、データとのやりとりにAPIサーバーがある、という構成について考えてみます。
フロントエンド側で権限管理をする/しないについては選択の余地がありますが、API側での権限管理は必須ですね。なぜなら不正なリクエストなどで、意図しないやりとりが行われる可能性があるからです。
もちろんトークンの照合などでリクエスト自体の正当性は検証しつつも、API側で権限をチェックする必要があるといえます。
次は、チェックではなく権限自体をどこで実装するかについて考えてみます。
権限管理とは:
誰がどの機能に対してなにをしていいのか、あるいはしてはいけないのかを管理すること
であると書きました。つまり権限はビジネスロジックであるといえます。権限はそれ単体でひとつの責務をもつので、権限管理をする責務として切り出して実装していくとよさそうです。
権限管理を設計するときは、次の二つのことを実践していきます:
それぞれについて簡単に書きます。
権限管理の役割がふえると、その分だけ権限管理シートやソースコードが複雑になってしまいます。
ビジネスを表現するために必要であれば役割をふやすことも仕方がないですが、「とりあえず問題を解決するために役割をふやそう」という発想は避けるべきだといえますね。
前述のとおり、権限管理はビジネスロジックに属します。権限の実装にミスがあると、意図しないデータの流出などにつながるおそれがあります。
権限に対するユニットテストはもちろん、データとのやりとりが発生するコントローラ層へのユニットテスト、またE2Eテストなどを書くことで、信頼性の担保につながります。
この記事では権限管理を設計するときの考え方、やり方について書いてきました。
権限管理はシステムの種類によって変わってきます。この記事の内容を参考にしつつ、システムに適したやり方を見つけられればと思います。
共著で『現場で使えるRuby on Rails 5(マイナビ出版)』を書きました。
Amazonでみる
権限管理をすることになったけど、どうすればいいの? なにからはじめればいいのかわからない。