Skip to content

Add application setting for limit of merge request approval policies

Martin Čavoj requested to merge mc/policy-limits-add-setting into master

What does this MR do and why?

This MR adds application setting for limit of merge request approval policies. The current limit is set to 5, so the application setting also defaults to 5. Additional context:

  • In Refine Policy Application Limits (&8084), we want to raise the limits and it will be easier to test when it's defined via ApplicationSetting compared to a const. In case of performance issues, it's also easy to reset back to 5.
  • Self-managed users may want to set a different value.

I think we should provide guardrails around this value and not allow it to be set unreasonably high, which could affect performance and user experience of related parts of GitLab (e.g. MR page load times due to many approval rules being loaded). For this reason, I set the maximum arbitrarily to 20 based on local testing in GDK.

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Limit hint MR approval rules
CleanShot_2024-02-05_at_19.03.09_2x CleanShot_2024-02-05_at_19.19.22_2x

How to set up and validate locally

  1. In rails console update the settings value to a value between 5 and 20
    Gitlab::CurrentSettings.update(security_approval_policies_limit: 10)
  2. Go to Secure -> Policies and create a new Merge request approval policy
  3. Configure with merge request & merge
  4. Go to the Security policy project which was created automatically
  5. Go to .gitlab/security-policies/policy.yml, edit the file and copy&paste the policy with a different name 10 times. Merge the changes.
  6. In the project for which the policies are enforced, update README, open MR and observe all 10 policies enforced.
  7. In the rails console, change the setting back to 5.
  8. Go back to the MR and observe that only first 5 policies are enforced (this is the current behavior)
Example `.gitlab/security-policies/policy.yml` file with 20 policies
---
approval_policy:
- name: Policy1
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy2
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy3
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy4
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy5
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy6
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy7
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy8
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy9
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy10
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy11
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy12
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy13
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy14
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy15
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy16
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy17
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy18
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy19
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false
- name: Policy20
  description: ''
  enabled: true
  rules:
  - type: scan_finding
    scanners: []
    vulnerabilities_allowed: 0
    severity_levels: []
    vulnerability_states: []
    branch_type: protected
  - type: license_finding
    match_on_inclusion: true
    license_types:
    - BSD 3-Clause "New" or "Revised" License
    - MIT License
    - GNU General Public License v3.0 only
    - GNU General Public License v3.0 or later
    license_states:
    - newly_detected
    branch_type: protected
  - type: any_merge_request
    branch_type: protected
    commits: unsigned
  actions:
  - type: require_approval
    approvals_required: 1
    role_approvers:
    - developer
  approval_settings:
    block_branch_modification: true
    prevent_pushing_and_force_pushing: true
    prevent_approval_by_author: true
    prevent_approval_by_commit_author: true
    remove_approvals_with_new_commit: true
    require_password_to_approve: false

Related to #436546 (closed)

Edited by Martin Čavoj

Merge request reports