カスタムロール
Ultimateのお客様は、カスタムロールを作成し、特定の能力を割り当ててロールを定義することができます。
たとえば、ユーザーは、read code
およびadmin merge requests
の能力を持ち、admin issues
のような能力を持たない「エンジニア」ロールを作成できます。
この文脈では、「権限」と「能力」という用語はしばしば同じ意味で使われます。
- 「能力」はユーザーができるアクションです。これらはDeclarative Policyの能力にマッピングされ、
ee/app/policies/*
のPolicyクラスに存在します。 - “権限 “は、ユーザー向けのドキュメントで能力を参照する方法です。権限に関する文書は手動で生成されるため、文書に記載されている権限と Policy クラスに定義されている能力は必ずしも 1 対 1 で対応付けられるわけではありません。
カスタム・ロールと静的ロール
GitLab 15.9以前では、GitLabには権限システムとして静的ロールしかありませんでした。このシステムでは、特定の能力に静的に割り当てられるいくつかの定義済みのロールがあります。これらの静的ロールは顧客がカスタマイズすることはできません。
カスタムロールでは、どの能力を特定のユーザーグループに割り当てるかを顧客が決めることができます。例えば
- 静的ロールシステムでは、脆弱性の読み取りは開発者ロールに制限されています。
- カスタムロールシステムでは、顧客はこの能力を、任意の静的ロールに基づく新しいカスタムロールに割り当てることができます。
静的ロールのように、カスタムロールはグループ階層内で継承されます。ユーザーがグループのカスタム・ロールを持つ場合、そのユーザーはグループ内のプロジェクトやサブグループのカスタム・ロールも持つことになります。
技術的な概要
- 個々のカスタムロールは
member_roles
テーブル (MemberRole
モデル) に格納されます。 -
member_roles
レコードは、namespace_id
外部キーを介してトップレベルのグループ(サブグループではない)に関連付けられます。 - グループまたはプロジェクトメンバーシップ(
members
レコード)は、member_role_id
外部キーを介してカスタムロールに関連付けられます。 - グループまたはプロジェクト・メンバーシップは、グループまたはプロジェクトのルートレベル・グループに定義されているカスタム・ロールに関連付けることができます。
-
member_roles
テーブルには、内部権限とbase_access_level
値が含まれます。 -
base_access_level
は有効なアクセス・レベルでなければなりません。はbase_access_level
カスタム・ロールに含まれる能力を決定base_access_level
します。例えば、10
のbase_access_level
場合base_access_level
、カスタム・ロールには静的なゲスト・ロールが受け取る権限に加え、read_code
のような属性をtrueに設定することでmember_roles
のレコードが有効にする追加権限が含まれます。 - カスタムロールは
base_access_level
の追加能力を有効にすることはできますが、権限を無効にすることはできません。結果として、カスタム・ロールは「追加のみ」です。この選択の根拠はこのコメントにあります。 - 今のところ、カスタムロールの能力はプロジェクトレベルでのみサポートされています。カスタムグループ能力のサポートを追加するイシューがあります。
カスタム・ロールの新しい能力を実装する方法
通常、新しい能力のために2-3個のマージリクエストを作成する必要があります。大まかなガイダンスは以下のとおりです:
- カスタムロールに能力を追加したい機能を選んでください。
- 機能のリファクタリングとアビリティの統合 (機能の複雑さに応じて1-2回のマージリクエスト)
- 新しい能力の実装 (1 マージリクエスト)
能力のリファクタリング
既存の能力チェックの検索
一つのエンドポイントやウェブリクエストに対して、複数の場所でアビリティがチェックされることがよくあります。そのため、特定のエンドポイントに対して実行される作成者チェックのリストを見つけるのは難しいかもしれません。
これを支援するために、内部でGITLAB_DEBUG_POLICIES=true
を設定することができます。
これは、あなたが実行するどの仕様のリクエストでどの能力がチェックされたかという情報を出力します。出力には、作成者チェックが行われたコード行も含まれます。呼び出し元の情報は、メタプログラミングが使用されている場合に特に役に立ちます。
使用例:
# example spec run
GITLAB_DEBUG_POLICIES=true bundle exec rspec spec/controllers/groups_controller_spec.rb:162
# permissions debug output when spec is run; if multiple policy checks are run they will all be in the debug output.
POLICY CHECK DEBUG -> policy: GlobalPolicy, ability: create_group, called_from: ["/gitlab/app/controllers/application_controller.rb:245:in `can?'", "/gitlab/app/controllers/groups_controller.rb:255:in `authorize_create_group!'"]
リファクタリング中の作成者チェックについて詳しく知りたい場合は、この設定を使用します。デフォルトブランチの仕様では、この設定を有効にしておくべきではありません。
個々の能力に関するロジックの理解
ある能力への参照は、DeclarativePolicy
クラス内に何度も出現し、他の能力を参照する条件やルールに依存する場合があります。そのため、どの条件が特定の能力に適用されるかを正確に知ることは困難な場合があります。
DeclarativePolicy
は、各ポリシークラスに対して、ability_map
を提供し、能力のすべてのルールを配列に取り込みます。
使用例:
> GroupPolicy.ability_map.map.select { |k,v| k == :read_group_member }
=> {:read_group_member=>[[:enable, #<Rule can?(:read_group)>], [:prevent, #<Rule ~can_read_group_member>]]}
> GroupPolicy.ability_map.map.select { |k,v| k == :read_group }
=> {:read_group=>
[[:enable, #<Rule public_group>],
[:enable, #<Rule logged_in_viewable>],
[:enable, #<Rule guest>],
[:enable, #<Rule admin>],
[:enable, #<Rule has_projects>],
[:enable, #<Rule read_package_registry_deploy_token>],
[:enable, #<Rule write_package_registry_deploy_token>],
[:prevent, #<Rule all?(~public_group, ~admin, user_banned_from_group)>],
[:enable, #<Rule auditor>],
[:prevent, #<Rule needs_new_sso_session>],
[:prevent, #<Rule all?(ip_enforcement_prevents_access, ~owner, ~auditor)>]]}
DeclarativePolicy
にもdebug
メソッドがあり、特定のオブジェクトとアクターのロジック ツリーを理解するために使用できます。出力は、ability_map
からのルールのリストと似ています。しかし、DeclarativePolicy
は、prevent
アビリティの後にルールの評価を停止するので、すべての条件が呼び出されない可能性があります。
使用例:
policy = GroupPolicy.new(User.last, Group.last)
policy.debug(:read_group)
- [0] enable when public_group ((@custom_guest_user1 : Group/139))
- [0] enable when logged_in_viewable ((@custom_guest_user1 : Group/139))
- [0] enable when admin ((@custom_guest_user1 : Group/139))
- [0] enable when auditor ((@custom_guest_user1 : Group/139))
- [14] prevent when all?(~public_group, ~admin, user_banned_from_group) ((@custom_guest_user1 : Group/139))
- [14] prevent when needs_new_sso_session ((@custom_guest_user1 : Group/139))
- [16] enable when guest ((@custom_guest_user1 : Group/139))
- [16] enable when has_projects ((@custom_guest_user1 : Group/139))
- [16] enable when read_package_registry_deploy_token ((@custom_guest_user1 : Group/139))
- [16] enable when write_package_registry_deploy_token ((@custom_guest_user1 : Group/139))
[21] prevent when all?(ip_enforcement_prevents_access, ~owner, ~auditor) ((@custom_guest_user1 : Group/139))
=> #<DeclarativePolicy::Runner::State:0x000000015c665050
@called_conditions=
#<Set: {
"/dp/condition/GroupPolicy/public_group/Group:139",
"/dp/condition/GroupPolicy/logged_in_viewable/User:83,Group:139",
"/dp/condition/BasePolicy/admin/User:83",
"/dp/condition/BasePolicy/auditor/User:83",
"/dp/condition/GroupPolicy/user_banned_from_group/User:83,Group:139",
"/dp/condition/GroupPolicy/needs_new_sso_session/User:83,Group:139",
"/dp/condition/GroupPolicy/guest/User:83,Group:139",
"/dp/condition/GroupPolicy/has_projects/User:83,Group:139",
"/dp/condition/GroupPolicy/read_package_registry_deploy_token/User:83,Group:139",
"/dp/condition/GroupPolicy/write_package_registry_deploy_token/User:83,Group:139"}>,
@enabled=false,
@prevented=true>
アビリティの統合
カスタムロールに追加されるすべての機能は最小限の能力を持つべきです。ほとんどの機能については、read_*
とadmin_*
があれば十分です。すべてを統合すべきです:
-
read_*
。例えば、リストや詳細の表示。 -
admin_*
にあるオブジェクトの更新。例えば、オブジェクトの更新、担当者の追加、オブジェクトのクローズなど。通常、admin_
を有効にするロールは、read_
の能力も有効にしなければなりません。これはMemberRole
モデルのALL_CUSTOMIZABLE_PERMISSIONS
ハッシュのrequirement
オプションで定義されています。
追加の能力を必要とする機能があるかもしれませんが、それらを最小限にするようにしてください。いつでもAuthentication and Authorizationグループのメンバーに意見や助けを求めることができます。
また、ここから作業を始めるべきです。作業する機能のすべての能力を取り出し、それらの能力をread_
、admin_
、または必要であれば追加能力に統合してください。
GroupPolicy
およびProjectPolicy
クラスの多くの能力には、多くの冗長なポリシーがあります。これらのポリシークラスを統合するためのエピックがあります。これらのクラスで同じような権限に遭遇した場合、同じ名前を持つようにリファクタリングすることを検討してください。
たとえば、GroupPolicy
にはread_group_security_dashboard
という権限があり、ProjectPolicy
にはread_project_security_dashboard
という権限があります。両方ともカスタマイズ可能にしたいでしょう。member_roles
それぞれの能力についてテーブルに member_roles
行を追加するよりも、member_roles
名前を変更してテーブルにread_security_dashboard
追加 read_security_dashboard
することを検討して member_roles
ください。これは、親グループでread_security_dashboard
を有効にすると、カスタムが有効になることを意味するので、より期待されます。例えば、GroupPolicy
にはread_group_security_dashboard
という能力があり、ProjectPolicy
にはread_project_security_dashboard
という能力があります。両方をカスタマイズ可能にしたい場合、member_roles
各能力の member_roles
行をmember_roles
テーブルに追加するのではなく、それらの名前を member_roles
変更してテーブルにmember_roles
read_security_dashboard
追加 read_security_dashboard
member_roles
することをmember_roles
検討して member_roles
ください。この規約は、親グループでread_security_dashboard
を有効にすると、カスタムロールがそのグループ内の各プロジェクトのグループセキュリティダッシュボードとプロジェクトセキュリティダッシュボードにアクセスできるようになることを意味します。特定のプロジェクトで同じ権限を有効にすると、そのプロジェクトのセキュリティダッシュボードにアクセスできるようになります。
新しい機能の実装
カスタム・ロールに新しい能力を追加します:
- 例えば、マージリクエスト114734のこの変更では、
member_roles
テーブルに新しい列を追加します。 -
MemberRole
モデルにALL_CUSTOMIZABLE_PERMISSIONS
ハッシュALL_CUSTOMIZABLE_PERMISSIONS
機能を追加しました(ALL_CUSTOMIZABLE_PERMISSIONS
マージリクエスト 121534ALL_CUSTOMIZABLE_PERMISSIONS
の変更例)。ALL_CUSTOMIZABLE_PERMISSIONS
ハッシュには以下のキーがALL_CUSTOMIZABLE_PERMISSIONS
あります:-
description
- 能力の説明。 -
minimal_level
- ユーザーが能力に割り当てられるために必要な最小レベル。 -
requirement
- ハッシュで定義された能力に必要な能力。要件がfalse
である場合、その能力はtrue
できません。
-
- 例えば、マージリクエスト114734のこの変更では、それぞれのポリシーに能力を追加します。
- 仕様を更新しました。
カスタムロールに新しい能力を追加するマージリクエストの例:
- コードを読む
- 脆弱性を読む
-
管理者の脆弱性- これは新しいカスタムロール機能を実装した最新のMRです。以前のMRからのいくつかの変更はもう必要ありません(例えば、プリローダー・クエリの変更や
User
モデルへのメソッドの追加)。
新しいカスタムロール機能が機能フラグの下にあることを確認する必要があります。
シートの消費
ロールGuest
を持つ新規ユーザーが、CUSTOMIZABLE_PERMISSIONS_EXEMPT_FROM_CONSUMING_SEAT
配列にない能力を有効にすることを含むメンバーロールに追加された場合、シートが消費されます。単純に、”昇格 “した能力を持つゲスト・ユーザーに対して、アルティメット・カスタマーに課金していることを確認したいだけです。これは、SaaSの課金対象ユーザー(ネームスペース・サブスクリプションにカウントされる課金対象ユーザー)にのみ適用されます。このトピックの詳細については、このイシューを参照してください。