Skip to content

Prototype allowing limited set of custom roles / duties

What

It might be possible to allow a limited set of abilities to be assigned to custom roles. We'd allow top level groups to specify a handful of custom roles each of which would have a name, and set of abilities it enables. These could then be assigned to users per group or project. Users would still have their normal guest/reporter/developer/master/owner access levels, and these new custom roles/duties would only add to those rather than overwriting them.

This issue is limited to a single prototype idea for exploring this and I've added some pseudocode below. I'm mostly interested in finding out how viable or crazy this approach is.

Who for

Large organizations that need restricted permissions for compliance and audit purposes. From https://gitlab.com/gitlab-org/gitlab-ce/issues/12736#note_60247043:

[Being] able to prove to auditors that we have things like separation of duties enforced in our workflow (think, things like "people who can deploy or manage repository creation/settings cannot be the same people as people who write the code").

Why

If this sounds viable it might be a path towards https://gitlab.com/gitlab-org/gitlab-ce/issues/12736, or help with issues like https://gitlab.com/gitlab-org/gitlab-ce/issues/43188 and https://gitlab.com/gitlab-org/gitlab-ee/issues/1896.

Why not

  • Adds complexity and isn't a well thought out solution
  • Only provides a limited number of custom roles
  • We have to cache CustomRoles * allowed_custom_abilities worth of conditions
  • In lots of places we use can?(user, :admin_project, project) instead of specific abilities, so lots of things won't work properly with this system.
  • From https://gitlab.com/gitlab-org/gitlab-ce/issues/12736#note_50662947: "However, the execution and implementation of custom roles is extremely hard to do well and to maintain to a reasonable degree. It adds significant complexity to the product, interface, user experience and code. In addition, it doesn't achieve in guarding users for bad decisions, gives a false sense of security and makes it much harder to introduce new features."

Pseudocode

ProjectPolicy:
  custom_duty_ids = (1..5)
  allowed_custom_abilities = %i(admin_issue push_code  ...  admin_project_member)
  
  custom_duty_ids.zip(abilities).each do |duty_id, ability|
    condition(:"duty_#{duty_id}_enables_#{ability}", scope: :subject) do
      duty = group.custom_duties.find_by(iid: duty_id)
      duty.enables?(ability)
    end

    condition(:"has_duty_#{duty_id}") do
      @subject.duty_assigned(user, duty_id)
    end

    rule { custom_duties & send(:"duty_#{duty_id}_enables_#{ability}") & send(:"has_duty_#{duty_id}") }.policy do
      enable ability
    end
  end
Edited by James Edwards-Jones