Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/permissions/custom_roles.md')
-rw-r--r--doc/development/permissions/custom_roles.md166
1 files changed, 79 insertions, 87 deletions
diff --git a/doc/development/permissions/custom_roles.md b/doc/development/permissions/custom_roles.md
index 7a0d325d09a..457fe5a5d8b 100644
--- a/doc/development/permissions/custom_roles.md
+++ b/doc/development/permissions/custom_roles.md
@@ -168,74 +168,87 @@ For example, you see in `GroupPolicy` that there is an ability called
`read_project_security_dashboard`. You'd like to make both customizable. Rather
than adding a row to the `member_roles` table for each ability, consider
renaming them to `read_security_dashboard` and adding `read_security_dashboard`
-to the `member_roles` table. This is more expected because it means that
-enabling `read_security_dashboard` on the parent group will enable the custom role.
-For example, `GroupPolicy` has an ability called `read_group_security_dashboard` and `ProjectPolicy` has an ability
-called `read_project_security_dashboard`. If you would like to make both customizable, rather than adding a row to the
-`member_roles` table for each ability, consider renaming them to `read_security_dashboard` and adding
-`read_security_dashboard` to the `member_roles` table. This convention means that enabling `read_security_dashboard` on
+to the `member_roles` table. Enabling `read_security_dashboard` on
the parent group will allow the custom role to access the group security dashboard and the project security dashboard
for each project in that group. Enabling the same permission on a specific project will allow access to that projects'
security dashboard.
### Implement a new ability
-To add a new ability to a custom role:
+#### Step 1. Generate a configuration file
-- Generate YAML file by running `./ee/bin/custom-ability` generator
-- Add a new column to `member_roles` table, either manually or by running `custom_roles:code` generator, eg. by running `rails generate gitlab:custom_roles:code --ability new_ability_name`. The ability parameter is case sensitive and has to exactly match the permission name from the YAML file.
-- Add the ability to the respective Policy for example in [this change in merge request 114734](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114734/diffs#diff-content-edcbe28bdecbd848d4d9efdc5b5e9bddd2a7299e).
-- Update the specs. Don't forget to add a spec to `ee/spec/requests/custom_roles` - the spec template file was pre-generated if you used the code generator
-- Compile the documentation by running `bundle exec rake gitlab:custom_roles:compile_docs`
-- Update the GraphQL documentation by running `bundle exec rake gitlab:graphql:compile_docs`
-
-Examples of merge requests adding new abilities to custom roles:
+- Run `./ee/bin/custom-ability <ABILITY_NAME>` to generate a configuration file for the new ability.
+- This will generate a YAML file in `ee/config/custom_abilities` which follows the following schema:
-- [Read code](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106256)
-- [Read vulnerability](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114734)
-- [Admin vulnerability](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121534)
+| Field | Required | Description |
+| ----- | -------- |--------------|
+| `name` | yes | Unique, lowercase and underscored name describing the custom ability. Must match the filename. |
+| `description` | yes | Human-readable description of the custom ability. |
+| `feature_category` | yes | Name of the feature category. For example, `vulnerability_management`. |
+| `introduced_by_issue` | yes | Issue URL that proposed the addition of this custom ability. |
+| `introduced_by_mr` | yes | MR URL that added this custom ability. |
+| `milestone` | yes | Milestone in which this custom ability was added. |
+| `group_ability` | yes | Boolean value to indicate whether this ability is checked on group level. |
+| `project_ability` | yes | Boolean value to whether this ability is checked on project level. |
+| `requirements` | no | The list of custom permissions this ability is dependent on. For instance `admin_vulnerability` is dependent on `read_vulnerability`. If none, then enter `[]` |
-The above merge requests don't use YAML files and code generators. Some of the changes are not needed anymore. We will update the documentation once we have a permission implemented using the generators.
+#### Step 2: Create a migration file
-If you have any concerns, put the new ability behind a feature flag.
+- Run `bundle exec rails generate gitlab:custom_roles:code --ability <ABILITY_NAME>` which will generate a migration file to add the ability as a boolean column to the `member_roles` table.
-#### Documenting handling the feature flag
+#### Step 3: Update policies
-- When you introduce a new custom ability under a feature flag, add the `feature_flag` attribute to the appropriate ability YAML file.
-- When you enable the ability by default, add the `feature_flag_enabled_milestone` and `feature_flag_enabled_mr` attributes to the appropriate ability YAML file and regenerate the documentation.
-- You do not have to include these attributes in the YAML file if the feature flag is enabled by default in the same release as the ability is introduced.
+- If the ability is checked on a group level, add rule(s) to GroupPolicy to enable the ability.
+- For example: if the ability we would like to add is `read_dependency`, then an update to `ee/app/policies/ee/group_policy.rb` would look like as follows:
-#### Testing
+```ruby
+desc "Custom role on group that enables read dependency"
+condition(:role_enables_read_dependency) do
+ ::Auth::MemberRoleAbilityLoader.new(
+ user: @user,
+ resource: @subject,
+ ability: :read_dependency
+ ).has_ability?
+end
+
+rule { custom_roles_allowed & role_enables_read_dependency }.policy do
+ enable :read_dependency
+end
+```
-Unit tests are preferred to test out changes to any policies affected by the
-addition of new custom permissions. Custom Roles is an Ultimate tier feature so
-these tests can be found in the `ee/spec/policies` directory. The [spec file](https://gitlab.com/gitlab-org/gitlab/-/blob/13baa4e8c92a56260591a5bf0a58d3339890ee10/ee/spec/policies/project_policy_spec.rb#L2726-2740) for
-the `ProjectPolicy` contains shared examples that can be used to test out the
-following conditions:
+- Similarly, If the ability is checked on a project level, add rule(s) to ProjectPolicy to enable the ability.
+- For example: if the ability we would like to add is `read_dependency`, then an update to `ee/app/policies/ee/project_policy.rb` would look like as follows:
-- when the `custom_roles` licensed feature is not enabled
-- when the `custom_roles` licensed feature is enabled
- - when a user is a member of a custom role via an inherited group member
- - when a user is a member of a custom role via a direct group member
- - when a user is a member of a custom role via a direct project membership
+```ruby
+desc "Custom role on project that enables read dependency"
+condition(:role_enables_read_dependency) do
+ ::Auth::MemberRoleAbilityLoader.new(
+ user: @user,
+ resource: @subject,
+ ability: :read_dependency
+ ).has_ability?
+end
+
+rule { custom_roles_allowed & role_enables_read_dependency }.policy do
+ enable :read_dependency
+end
+```
-Below is an example for testing out `ProjectPolicy` related changes.
+- Not all abilities need to be enabled on both levels, for instance `admin_terraform_state` allows users to manage a project's terraform state. It only needs to be enabled on the project level and not the group level, and thus only needs to be configured in `ee/app/policies/ee/project_policy.rb`.
-```ruby
- context 'for a role with `custom_permission` enabled' do
- let(:member_role_abilities) { { custom_permission: true } }
- let(:allowed_abilities) { [:custom_permission] }
+#### Step 4: Verify
- it_behaves_like 'custom roles abilities'
- end
-```
+- Ensure SaaS mode is enabled with `GITLAB_SIMULATE_SAAS=1`.
+- Navigate to any Group that you are an owner of, then go to `Settings -> Roles and Permissions`.
+- Click on `Add new role` and create a custom role with the permission you have just created.
+- Navigate to the Group's `Manage -> Members` page and assign a member to this newly created custom role.
+- Next, log-in as that member and ensure that you are able to access the page that the custom ability is intended for.
-Request specs are preferred to test out any endpoint that allow access via a custom role permission.
-This includes controllers, REST API, and GraphQL. Examples of request specs can be found in `ee/spec/requests/custom_roles/`. In this directory you will find a sub-directory named after each permission that can be enabled via a custom role.
-The `custom_roles` licensed feature must be enabled to test this functionality.
+#### Step 5: Add specs
-Below is an example of the typical setup that is required to test out a
-Rails Controller endpoint.
+- Add the ability as a trait in the `MemberRoles` factory, `ee/spec/factories/member_roles.rb`.
+- Add tests to `ee/spec/requests/custom_roles/<ABILITY_NAME>/request_spec.rb` to ensure that once the user has been assigned the custom ability, they can successfully access the controllers, REST API endpoints and GraphQL API endpoints.
+- Below is an example of the typical setup that is required to test a Rails Controller endpoint.
```ruby
let_it_be(:user) { create(:user) }
@@ -245,6 +258,7 @@ Rails Controller endpoint.
before do
stub_licensed_features(custom_roles: true)
+
sign_in(user)
end
@@ -260,8 +274,7 @@ Rails Controller endpoint.
end
```
-Below is an example of the typical setup that is required to test out a GraphQL
-mutation.
+- Below is an example of the typical setup that is required to test a GraphQL mutation.
```ruby
let_it_be(:user) { create(:user) }
@@ -271,57 +284,36 @@ mutation.
before do
stub_licensed_features(custom_roles: true)
+
+ sign_in(user)
end
describe MyMutation do
include GraphqlHelpers
describe '#show' do
- it 'allows access' do
- post_graphql_mutation(graphql_mutation(:my_mutation, {
- example: "Example"
- }), current_user: user)
-
- expect(response).to have_gitlab_http_status(:success)
- mutation_response = graphql_mutation_response(:my_mutation)
- expect(mutation_response).to be_present
- expect(mutation_response["errors"]).to be_empty
- end
+ let(:mutation) { graphql_mutation(:my_mutation) }
+
+ it_behaves_like 'a working graphql query'
end
end
```
-[`GITLAB_DEBUG_POLICIES=true`](#finding-existing-abilities-checks) can be used
-to troubleshoot runtime policy decisions.
-
-## Custom abilities definition
-
-All new custom abilities must have a type definition stored in `ee/config/custom_abilities` that contains a single source of truth for every ability that is part of custom roles feature.
+- Add tests to `ProjectPolicy` and/or `GroupPolicy`. Below is an example for testing `ProjectPolicy` related changes.
-### Add a new custom ability definition
-
-To add a new custom ability:
+```ruby
+ context 'for a member role with read_dependency true' do
+ let(:member_role_abilities) { { read_dependency: true } }
+ let(:allowed_abilities) { [:read_dependency] }
-1. Create the YAML definition. You can either:
- - Use the `ee/bin/custom-ability` CLI to create the YAML definition automatically.
- - Perform manual steps to create a new file in `ee/config/custom_abilities/` with the filename matching the name of the ability name.
-1. Add contents to the file that conform to the [schema](#schema) defined in `ee/config/custom_abilities/types/type_schema.json`.
-1. Add [tests](#testing) for the new ability in `ee/spec/requests/custom_roles/` with a new directory named after the ability name.
+ it_behaves_like 'custom roles abilities'
+ end
+```
-### Schema
+#### Step 6: Update documentation
-| Field | Required | Description |
-| ----- | -------- |--------------|
-| `name` | yes | Unique, lowercase and underscored name describing the custom ability. Must match the filename. |
-| `description` | yes | Human-readable description of the custom ability. |
-| `feature_category` | yes | Name of the feature category. For example, `vulnerability_management`. |
-| `introduced_by_issue` | yes | Issue URL that proposed the addition of this custom ability. |
-| `introduced_by_mr` | no | MR URL that added this custom ability. |
-| `milestone` | yes | Milestone in which this custom ability was added. |
-| `group_ability` | yes | Indicate whether this ability is checked on group level. |
-| `project_ability` | yes | Indicate whether this ability is checked on project level. |
-| `requirements` | no | The custom abilities that need to be enabled for this ability. |
-| `skip_seat_consumption` | yes | Indicate wheter this ability should be skiped when counting licensed users. |
+- Update the list of custom abilities by running `bundle exec rake gitlab:custom_roles:compile_docs`
+- Update the GraphQL documentation by running `bundle exec rake gitlab:graphql:compile_docs`
### Privilege escalation consideration