Compare results from all pipelines related to change when evaluating Scan Result Policies
Why are we doing this work
It might be possible that the pipeline for target branch sha
or source branch sha
contains detached pipelines that do not include security jobs. Because of this we might incorrectly require approvals while they are not needed or not require approvals while they needed. With this change we want to change this behavior to get reports from all pipelines related to given source/target commit.
Release post
Scan result policies are a type of security policy that allows you to evaluate and block merge requests if particular rules are violated. Approvers may review and approve the change, or work with their development teams to address any issues (such as addressing critical security vulnerabilities).
To determine if there's a violation, we previously compared latest source and target branches to compare vulnerabilities and detect any new violations of policy rules. But, this may not capture vulnerabilities detected from scans running as a result of various pipeline sources. To increase accuracy, we will be comparing all of the latest completed pipelines of each pipeline source (with the exception of parent/child pipelines). This will ensure a more comprehensive evaluation and reduce the cases where approvals are required when it may be unexpected.
Use Cases to consider
- Project is using merge request pipelines and the results in these findings are not considered in the evaluation.
- A scheduled pipeline is being run overnight as it takes to long to run on every MR and slows developers down. The scheduled pipeline may include security scanners and may discover new findings that should be raised on existing MRs.
- A new CVE is posted related to a dependency (unrelated to the MR) that is already in the default branch. This results in a "new vulnerability" for that finding.
- A parent-child pipeline is used to separate scanners into an external/detached pipeline. (Out of scope for this issue, but we'll explore in future iteration. I think we can learn more about how prevalent this pattern is used with security scan jobs)
Relevant links
Non-functional requirements
-
Documentation: -
Feature flag: Add feature flag to be able to enable/disable this behavior (default: false
) -
Performance: -
Testing:
Implementation plan
-
backend Update Ci::Pipeline
model to get latest pipelines for a given sha grouped by source
def self.latest_pipelines_per_source(sha)
select('DISTINCT ON (source) *').where(sha: sha).order(:source, id: :desc)
end
-
backend Update Security::Finding
model to get findings for given pipeline ids:
def for_pipelines(pipeline_ids)
where(scan_id: Security::Scan.where(pipeline_id: pipeline_ids))
end
-
backend Update Security::ScanResultPolicies::SyncFindingsToApprovalRulesService
to check if all latest pipelines for the latest pipeline sha are complete -
backend Update Security::ScanResultPolicies::UpdateApprovalsService
to consider the latest pipelines for target pipeline of MR and get the security findings -
backend feature flag keep changes behind feature flag,
Verification steps
-
Create new project -
Add .gitlab-ci.yml
file that includes detached pipeline:container_scanning: image: "busybox:latest" stage: test allow_failure: true artifacts: reports: container_scanning: gl-container-scanning-report.json paths: [gl-container-scanning-report.json] dependencies: [] script: - wget -O gl-container-scanning-report.json https://gitlab.com/-/snippets/2438327/raw/main/gl-container-scanning-report-empty.json?inline=false rules: - if: $CONTAINER_SCANNING_DISABLED when: never - if: $CI_COMMIT_BRANCH other_job: image: busybox:latest stage: test script: - echo "This is other branch" detachedjob: rules: - when: always script: - echo "Hello from detached job"
-
Add Scan Result Policy (go to Security & Compliance -> Policies
), clickNew Policy
, selectScan Result Policies
and add new policy and merge created MR:name: Enforce check when there is at least 1 critical description: '' enabled: true actions: - type: require_approval approvals_required: 1 group_approvers_ids: - # add your group ID rules: - type: scan_finding branches: [] scanners: [] vulnerabilities_allowed: 0 severity_levels: - critical vulnerability_states: - newly_detected
-
Add new MR with change to .gitlab-ci.yml
:diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0cf690cc8622c2262dd1ea492e4019e40dc078d0..46167e7f57632551d085397fe6994a596d4c1ae3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,7 +31,7 @@ container_scanning: paths: [gl-container-scanning-report.json] dependencies: [] script: - - wget -O gl-container-scanning-report.json http://gdk.test:3000/-/snippets/22/raw/main/gl-container-scanning-report-empty.json?inline=false + - wget -O gl-container-scanning-report.json http://gdk.test:3000/-/snippets/22/raw/main/gl-container-scanning-report-1-critical.json?inline=false rules: - if: $CONTAINER_SCANNING_DISABLED when: never
-
Verify if approvals in the MR are required