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_abilitiesworth 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