Use bot users to trigger scan execution policies pipelines
<!---
Please read this!
Before opening a new issue, make sure to search for keywords in the issues
filtered by the "regression" or "type::bug" label:
- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=regression
- https://gitlab.com/gitlab-org/gitlab/issues?label_name%5B%5D=type::bug
and verify the issue you're about to submit isn't a duplicate.
--->
# Summary
Scan execution policies can trigger pipelines on projects. As the user triggering the pipeline, we use the last user that modified the security policy project. This user might not have the permission to start a pipeline on the linked project, though.
This issue is the result of a spike issue: https://gitlab.com/gitlab-org/gitlab/-/issues/384322
Related feature flag: https://gitlab.com/gitlab-org/gitlab/-/issues/409459+
# Release post
Security bot users will be created to support in managing background tasks to enforce security policies for all newly created or updated security policy project links. This will ease the process for security and compliance team members to configure and enforce policies, specifically removing the need for security policy project maintainers to also maintain `Developer` access in development projects. Security policy bot users will also make it much clearer for users within an enforced project when pipelines are executed on behalf of a security policy, as this bot user will be the pipeline author.
When a security policy project is linked to a group or subgroup, a security policy bot will be created in each project in the group or subgroup. When a link is made to a single project, a security bot user will be created for the single project. Any groups, subgroups, or projects that already have a link to a security policy project will be unaffected, but users may re-establish any existing links to take advantage of this feature.
# Steps to reproduce
1. [Set up runners](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/howto/runner.md#simple-configuration).
1. Create a project with a working `.gitlab-ci.yml` file as the development project.
1. Create another project as the security policies project.
1. If you are logged in as `root` pick a different user and add it as owner to both projects
1. [Impersonate](https://docs.gitlab.com/ee/user/admin_area/#user-impersonation) the other user
1. On the development project go to **Security and Compliance > Policies**.
1. Select **Edit policy project**.
1. Select your security policies project.
1. Select **Save**.
1. Select **New Policy**.
1. Select **Scan execution policy**
1. Choose a **Name**.
1. As **Conditions** Select **IF** **Schedule** actions for the **branch** `main` **daily** at **00:00**.
1. As **Actions** choose **SAST**.
1. Select **Configure with a Merge Request**.
1. Merge the new MR
1. To avoid waiting for the next day until the execution runs
1. Open a rails console
2. Reset the timers by `Security::OrchestrationPolicyRuleSchedule.update_all(next_run_at: Time.now - 1.day)`
3. Run the schedule worker `Security::OrchestrationPolicyRuleScheduleWorker.new.perform`
1. A new pipeline should be started on the development project and the triggerer should be the user that created the scan execution policy.
1. Stop the user impersonation.
1. Change the user access for the development prject to **Guest**
1. Run the steps to execute the schedule worker again
1. There should not be a new pipeline in the development project because the user doesn't have access anymore.
# Previous attempt to fix this
We tried to fix this with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/103544. This would create a bot user to trigger pipelines and bypass the permission check if the user is of type `security_policy_bot `. But it got [reverted](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105557) because it caused [issues in accessing registry](https://gitlab.com/gitlab-org/gitlab/-/issues/384174).
# Implementation plan
We can fix this issue by creating a bot user on each project or group that is linked to a security policy project. Those users would have the necessary permissions to run pipelines and access registry. For this we can add a checkbox to the link security policy form. If checked, this will create and use the bot user, otherwise fall back to use the schedule owner as the triggerer of the pipeline:
## Iterations
### 1. Create and use bot users
1. Create a feature flag `scan_execution_bot_users`
1. Add a new column `bot_user_id` to the `security_orchestration_policy_configurations` table.
1. If the FF is enabled, create a new user with type `security_policy_bot` for the project or group. The bot user ID can be stored in `security_orchestration_policy_configurations.bot_user_id`. This has to be a find_or_create action in case a bot already exists. We might be able to re-use parts of [`app/services/resource_access_tokens/create_service.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/0c2b051db337e9fe037073fd84243f126622cc4b/app/services/resource_access_tokens/create_service.rb) for this.
1. Modify [`Security::Orchestration::UnassignService`](https://gitlab.com/gitlab-org/gitlab/-/blob/0c2b051db337e9fe037073fd84243f126622cc4b/ee/app/services/security/orchestration/unassign_service.rb) to delete the bot user and clear `security_orchestration_policy_configurations.bot_user_id`.
1. Modify the schedule workers ([`ee/app/workers/security/orchestration_policy_rule_schedule_namespace_worker.rb:25-27`](https://gitlab.com/gitlab-org/gitlab/-/blob/c5946f3f3c6a1f86e4c8f194ee24fb291b175a49/ee/app/workers/security/orchestration_policy_rule_schedule_namespace_worker.rb#L25-27) and [`ee/app/workers/security/orchestration_policy_rule_schedule_worker.rb:18`](https://gitlab.com/gitlab-org/gitlab/-/blob/c5946f3f3c6a1f86e4c8f194ee24fb291b175a49/ee/app/workers/security/orchestration_policy_rule_schedule_worker.rb#L18)) to use instead of `schedule.owner`:
```
if Feature.enabled(`scan_execution_bot_users`)
schedule.security_orchestration_policy_configuration.bot_user || schedule.owner
end
```
### 2. Make bot users optional
1. Modify the [`Security::Orchestration::AssignService`](https://gitlab.com/gitlab-org/gitlab/-/blob/b8782f71c59f73c1b5c2e9c3ea4e848a73d9b168/ee/app/services/security/orchestration/assign_service.rb#L30) to take a boolean argument `create_project_bot`
1. Modify the [`SecurityPolicyProjectAssign` GraphQL mutation](https://gitlab.com/gitlab-org/gitlab/-/blob/0c2b051db337e9fe037073fd84243f126622cc4b/ee/app/graphql/mutations/security_policy/assign_security_policy_project.rb) to take the `create_project_bot` argument and forward it to [`Security::Orchestration::AssignService`](https://gitlab.com/gitlab-org/gitlab/-/blob/b8782f71c59f73c1b5c2e9c3ea4e848a73d9b168/ee/app/services/security/orchestration/assign_service.rb#L30)
### 3. Frontend
1. Add a checkbox to the **Select security project** form so users can choose to create a bot.  if the FF is enabled.
### 4. Feature flag rollout
Come up with a strategy to enable the feature flag and measure success.
## Alternative solution
If the opt-in solution, with checkbox turns out to be too confusing, we can create a backfill migration to create bot users for existing projects.
### Implementation plan
1. Create a backfill migration that adds bot users to projects and groups for all records in `security_orchestration_policy_configurations` where `bot_user_id IS NULL`.
1. Remove the create bot checkbox.
<!-- triage-serverless v3 PLEASE DO NOT REMOVE THIS SECTION -->
*This page may contain information related to upcoming products, features and functionality.
It is important to note that the information presented is for informational purposes only, so please do not rely on the information for purchasing or planning purposes.
Just like with all projects, the items mentioned on the page are subject to change or delay, and the development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.*
<!-- triage-serverless v3 PLEASE DO NOT REMOVE THIS SECTION -->
epic