プロダクト開発

システムの権限管理を設計するときの考え方

権限管理をすることになったけど、どうすればいいの? なにからはじめればいいのかわからない。

という悩みについて、記事でお答えしていきます。

この記事を読むことで、権限管理とはなにか、その際に押さえておくべきRBACとABACについて、また権限管理を設計するやり方の一例がわかるようになります。

私はエンジニアとして、主に立ち上げのフェーズで20以上のサービスを開発してきました。権限管理は、どのサービスにも必ず入ってくるプロセスでした。ここでの経験や、調べたことをもとにこの記事を書いています。

想定している読者の方

この記事が想定している読者の方としては、エンジニアとしてシステムを設計または実装する立場にある、実務経験が1〜3年目の方を想定して記事を書いています。

著者
ぜに/Hiroki Zenigami

Webエンジニア&プロダクトマネージャ←プログラミング教育で起業←東大院←熊本高専。 共著に「現場で使えるRuby on Rails 5」。

権限管理とは

この記事でいう権限管理とは、ユーザー認証を行った相手に対して、『誰がどの機能に対してなにをしていいのか、あるいはしてはいけないのかを管理すること』をいいます。

たとえばTwitterにおける権限管理について考えてみると、次のようになります:

  • すべてのユーザーは投稿できる
  • すべてのユーザーは自分の投稿を削除できる
  • ツイートはすべてのユーザーが閲覧できる
  • 非公開ツイートはフォロワーのみが閲覧できる
  • ブロックされたユーザーはツイートを閲覧できない

こういった、サービス内の行動に対する権限を設計するのが権限管理ですね。この権限管理について、この記事で書いていきます。

この記事の権限管理の前提

権限管理は、システムの種類によって大きく変わってきます。このため、この記事の内容はすべてのシステムに適用できるやり方というわけではありません。参考資料のひとつとしてお読みいただければと思っています。

loading...

どう権限管理を設計するか

Googleで『権限管理 設計』で検索してもらってもわかることですが、権限管理にはいろんなやり方があって、ベストプラクティスはないと思っています。この前提で、私はシートで管理するやり方をとっています。

たとえば次のような感じですね。これは架空のドキュメント共有サービスを例に作ってみています:

権限管理の例

権限管理のシートに書く内容

このシートには、次のようなことを書いていきます:

項目内容
機能どの機能に対する権限か投稿閲覧
役割どの役割に対する権限か一般ユーザー / 管理者
属性どんな属性をもったユーザーに対する権限か同じグループに属していること
対象となるデータ処理するデータはどれかグループのメンバーの投稿
処理の可否処理をできるのかどうかできる / できない
説明その権限の概要同じグループのユーザーの投稿を閲覧できる

開発が進むにつれて、機能が追加・削除されて、権限もどんどん変わっていくことになります。その度に、このシートを更新していきます。

すべての権限管理が一枚のシートに集約されている状態がベストですね。

権限管理におけるRBACとABACという考え方

上の表で、権限管理には『役割』と『属性』があると書きました。これについて、権限管理を設計する上でRBACABACという考え方が大切なので、それぞれについて書いていきます。

RBAC: Role-Based Access Control

RBACは『ユーザーの役割によって権限のチェックを行う』やり方です。役割とは、たとえば一般ユーザーや管理者などがありますね。

権限を変更するだけで処理の可否を変更できるという利点がありますが、権限がふえると管理や実装が大変になってきます。

『管理者』のような役割以外にも、WritableやReadableのような複数のパーミッションを持たせるようなやり方もあります。

ABAC: Attribute-Based Access Control

ABACは『ユーザーの属性によって権限のチェックを行う』やり方です。たとえばツイートの投稿者かどうか、あるいは同じグループに所属しているかどうか、ですね。

ABACは柔軟な権限管理ができる一方で実装が大変だったり、ものによってはデータベースへのアクセスがふえてパフォーマンスが悪くなったりします。

RBACとABACは、システムの種類によって使い分けるとよいですね。ひとつのシステム内で両方を使うことももちろんあります。

権限管理を設計するフロー

権限管理の設計はシートでやるといい、と書きました。その手順としては、次の3つでやるとスムーズに設計できます。

  1. 機能を洗い出す
  2. 機能に対する権限を洗い出す
  3. 重複した権限の優先度を考える

まずシステムの機能を洗い出して、それぞれの機能に対する権限をシートにまとめていきます。このとき、重複した権限が出てきます。たとえば:

  • 管理者はすべての投稿を表示できる
  • ブロックされたユーザーは、相手の投稿を表示できない

という二つの権限があったときに、『ブロックされている管理者』は投稿を閲覧できるのかどうかを考える必要が出てきます。

こういった重複について、ひとつひとつどうするかを決めていきます。

権限はどこでチェックするか

次はコード面での設計についてです。権限は、データベースなどのデータとのやりとりが発生するところでチェックするといいですね。

たとえばフロントエンドにJavaScriptを用いていて、データとのやりとりにAPIサーバーがある、という構成について考えてみます。

フロントエンド側で権限管理をする/しないについては選択の余地がありますが、API側での権限管理は必須ですね。なぜなら不正なリクエストなどで、意図しないやりとりが行われる可能性があるからです。

もちろんトークンの照合などでリクエスト自体の正当性は検証しつつも、API側で権限をチェックする必要があるといえます。

権限はどこで実装するか

次は、チェックではなく権限自体をどこで実装するかについて考えてみます。

権限管理とは:

誰がどの機能に対してなにをしていいのか、あるいはしてはいけないのかを管理すること

であると書きました。つまり権限はビジネスロジックであるといえます。権限はそれ単体でひとつの責務をもつので、権限管理をする責務として切り出して実装していくとよさそうです。

例:Rubyの場合

RubyにはPunditというGemがあります。これはモデル層に属する純粋なRubyオブジェクトで、リソースに対する権限を実装するときに有用なライブラリです。

権限管理を設計するときの指針

権限管理を設計するときは、次の二つのことを実践していきます:

  1. 役割をできるだけ減らす
  2. テストコードを書く

それぞれについて簡単に書きます。

役割をできるだけ減らす

権限管理の役割がふえると、その分だけ権限管理シートやソースコードが複雑になってしまいます。

ビジネスを表現するために必要であれば役割をふやすことも仕方がないですが、「とりあえず問題を解決するために役割をふやそう」という発想は避けるべきだといえますね。

テストコードを書く

前述のとおり、権限管理はビジネスロジックに属します。権限の実装にミスがあると、意図しないデータの流出などにつながるおそれがあります。

権限に対するユニットテストはもちろん、データとのやりとりが発生するコントローラ層へのユニットテスト、またE2Eテストなどを書くことで、信頼性の担保につながります。

loading...

まとめ

この記事では権限管理を設計するときの考え方、やり方について書いてきました。

権限管理はシステムの種類によって変わってきます。この記事の内容を参考にしつつ、システムに適したやり方を見つけられればと思います。

著者
ぜに/Hiroki Zenigami

Webエンジニア&プロダクトマネージャ←プログラミング教育で起業←東大院←熊本高専。 共著に「現場で使えるRuby on Rails 5」。

関連記事関連書籍人気記事
applis
エンジニアとしてのんびり暮らす
お問い合わせ
ご意見・ご質問やお仕事のご依頼などは下記よりお願いいたします
お問い合わせ
© applis