Commit d70caf96 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch 'graphql_for_pipeline_finding' into 'master'

Add false-positive for pipeline finding in GraphQL query

See merge request gitlab-org/gitlab!67188
parents c0ed68d1 5aec1a52
...@@ -11669,6 +11669,7 @@ Represents vulnerability finding of a security report on the pipeline. ...@@ -11669,6 +11669,7 @@ Represents vulnerability finding of a security report on the pipeline.
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="pipelinesecurityreportfindingconfidence"></a>`confidence` | [`String`](#string) | Type of the security report that found the vulnerability. | | <a id="pipelinesecurityreportfindingconfidence"></a>`confidence` | [`String`](#string) | Type of the security report that found the vulnerability. |
| <a id="pipelinesecurityreportfindingdescription"></a>`description` | [`String`](#string) | Description of the vulnerability finding. | | <a id="pipelinesecurityreportfindingdescription"></a>`description` | [`String`](#string) | Description of the vulnerability finding. |
| <a id="pipelinesecurityreportfindingfalsepositive"></a>`falsePositive` | [`Boolean`](#boolean) | Indicates whether the vulnerability is a false positive. Available only when feature flag `vulnerability_flags` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
| <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerabilit finding. | | <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerabilit finding. |
| <a id="pipelinesecurityreportfindinglocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. | | <a id="pipelinesecurityreportfindinglocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. |
| <a id="pipelinesecurityreportfindingname"></a>`name` | [`String`](#string) | Name of the vulnerability finding. | | <a id="pipelinesecurityreportfindingname"></a>`name` | [`String`](#string) | Name of the vulnerability finding. |
......
...@@ -27,6 +27,13 @@ module Types ...@@ -27,6 +27,13 @@ module Types
null: true, null: true,
description: 'Type of the security report that found the vulnerability.' description: 'Type of the security report that found the vulnerability.'
field :false_positive,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates whether the vulnerability is a false positive.',
resolver_method: :false_positive?,
feature_flag: :vulnerability_flags
field :scanner, field :scanner,
type: VulnerabilityScannerType, type: VulnerabilityScannerType,
null: true, null: true,
...@@ -78,6 +85,12 @@ module Types ...@@ -78,6 +85,12 @@ module Types
def location def location
object.location&.merge(report_type: object.report_type) object.location&.merge(report_type: object.report_type)
end end
def false_positive?
return unless object.project.licensed_feature_available?(:sast_fp_reduction)
object.vulnerability_flags.any?(&:false_positive?)
end
end end
# rubocop: enable Graphql/AuthorizeTypes # rubocop: enable Graphql/AuthorizeTypes
end end
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe GitlabSchema.types['PipelineSecurityReportFinding'] do RSpec.describe GitlabSchema.types['PipelineSecurityReportFinding'] do
let_it_be(:fields) do let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:pipeline) { create(:ci_pipeline, :with_sast_report, project: project) }
let(:fields) do
%i[report_type %i[report_type
name name
severity severity
...@@ -15,11 +19,84 @@ RSpec.describe GitlabSchema.types['PipelineSecurityReportFinding'] do ...@@ -15,11 +19,84 @@ RSpec.describe GitlabSchema.types['PipelineSecurityReportFinding'] do
project project
description description
location location
falsePositive
solution solution
state] state]
end end
before do
stub_licensed_features(sast: true, security_dashboard: true, sast_fp_reduction: true)
project.add_developer(user)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
specify { expect(described_class.graphql_name).to eq('PipelineSecurityReportFinding') } specify { expect(described_class.graphql_name).to eq('PipelineSecurityReportFinding') }
it { expect(described_class).to have_graphql_fields(fields) } it { expect(described_class).to have_graphql_fields(fields) }
describe 'false_positive' do
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
pipeline(iid: "#{pipeline.iid}") {
securityReportFindings {
nodes {
falsePositive
}
}
}
}
}
)
end
context 'when the vulnerability has a false-positive flag' do
before do
security_finding = pipeline.security_reports.reports['sast'].findings.first
vulnerability_finding = create(:vulnerabilities_finding, uuid: security_finding.uuid, pipelines: [pipeline], project: pipeline.project)
create(:vulnerabilities_flag, finding: vulnerability_finding)
end
it 'returns false-positive value' do
vulnerabilities = subject.dig('data', 'project', 'pipeline', 'securityReportFindings', 'nodes')
expect(vulnerabilities.first['falsePositive']).to be(true)
expect(vulnerabilities.last['falsePositive']).to be(false)
end
end
context 'when the vulnerability does not have any false-positive flag' do
it 'returns false for false-positive field' do
vulnerabilities = subject.dig('data', 'project', 'pipeline', 'securityReportFindings', 'nodes')
expect(vulnerabilities.first['falsePositive']).to be(false)
end
end
context 'when there exists no license' do
before do
stub_licensed_features(sast: true, security_dashboard: true, sast_fp_reduction: false)
end
it 'returns nil for false-positive field' do
vulnerabilities = subject.dig('data', 'project', 'pipeline', 'securityReportFindings', 'nodes')
expect(vulnerabilities.first['falsePositive']).to be_nil
end
end
context 'when vulnerability_flags FF has been disabled' do
before do
stub_feature_flags(vulnerability_flags: false)
end
it 'exposes an error message' do
error_msg = subject.dig('errors').first['message']
expect(error_msg).to eql("Field 'falsePositive' doesn't exist on type 'PipelineSecurityReportFinding'")
end
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment