Commit ce087b3b authored by Mehmet Emin INAC's avatar Mehmet Emin INAC Committed by GitLab Release Tools Bot

Authorize users to read security related pipeline fields

parent d2e8fb82
......@@ -2,13 +2,17 @@
module Resolvers
class SecurityReportSummaryResolver < BaseResolver
type Types::SecurityReportSummaryType, null: true
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::SecurityReportSummaryType, null: true
authorize :read_security_resource
extras [:lookahead]
alias_method :pipeline, :object
def resolve(lookahead:)
return unless authorized_resource?(pipeline.project)
Security::ReportSummaryService.new(
pipeline,
selection_information(lookahead)
......
# frozen_string_literal: true
module Types
# rubocop: disable Graphql/AuthorizeTypes
class PipelineSecurityReportFindingType < BaseObject
graphql_name 'PipelineSecurityReportFinding'
description 'Represents vulnerability finding of a security report on the pipeline.'
authorize :read_security_resource
field :report_type,
type: VulnerabilityReportTypeEnum,
null: true,
......@@ -97,5 +98,4 @@ module Types
object.project.licensed_feature_available?(:sast_fp_reduction)
end
end
# rubocop: enable Graphql/AuthorizeTypes
end
......@@ -106,6 +106,8 @@ module Vulnerabilities
.where("vulnerability_occurrences.location -> 'cluster_id' ?| array[:cluster_ids]", cluster_ids: cluster_ids)
end
alias_method :declarative_policy_subject, :project
def self.counted_by_severity
group(:severity).count.transform_keys do |severity|
severities[severity]
......
......@@ -5,9 +5,14 @@ require 'spec_helper'
RSpec.describe Resolvers::SecurityReportSummaryResolver do
include GraphqlHelpers
let_it_be(:pipeline) { 'pipeline' }
let_it_be(:pipeline) { create(:ci_pipeline) }
let_it_be(:user) { pipeline.project.owner }
describe '#resolve' do
before do
stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true, dast: true, security_dashboard: true)
end
context 'All fields are requested' do
let(:lookahead) do
build_mock_lookahead(expected_selection_info)
......@@ -32,7 +37,18 @@ RSpec.describe Resolvers::SecurityReportSummaryResolver do
) do |summary_service|
expect(summary_service).to receive(:execute).and_return({})
end
resolve(described_class, obj: pipeline, lookahead: lookahead)
resolve_security_report_summary
end
context 'when the user is not authorized' do
let_it_be(:user) { create(:user) }
it 'does not call Security::ReportSummaryService and returns nothing' do
stub_const('Security::ReportSummaryService', double)
expect(resolve_security_report_summary).to be_nil
end
end
end
......@@ -61,10 +77,15 @@ RSpec.describe Resolvers::SecurityReportSummaryResolver do
) do |summary_service|
expect(summary_service).to receive(:execute).and_return({})
end
resolve(described_class, obj: pipeline, lookahead: lookahead)
resolve_security_report_summary
end
end
end
def resolve_security_report_summary
resolve(described_class, obj: pipeline, lookahead: lookahead, ctx: { current_user: user })
end
end
def build_mock_lookahead(structure)
......
......@@ -33,6 +33,7 @@ RSpec.describe GitlabSchema.types['PipelineSecurityReportFinding'] do
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
specify { expect(described_class.graphql_name).to eq('PipelineSecurityReportFinding') }
specify { expect(described_class).to require_graphql_authorizations(:read_security_resource) }
it { expect(described_class).to have_graphql_fields(fields) }
......
......@@ -3,7 +3,9 @@
require 'spec_helper'
RSpec.describe 'Query.project(fullPath).pipeline(iid).securityReportFindings' do
let_it_be(:project) { create(:project, :repository) }
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project) }
let_it_be(:user) { create(:user) }
......@@ -49,13 +51,16 @@ RSpec.describe 'Query.project(fullPath).pipeline(iid).securityReportFindings' do
)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
let(:security_report_findings) { subject.dig('project', 'pipeline', 'securityReportFindings', 'nodes') }
let(:security_report_findings) { subject.dig('data', 'project', 'pipeline', 'securityReportFindings', 'nodes') }
subject do
post_graphql(query, current_user: user)
graphql_data
end
context 'when `sast` and `dast` features are enabled' do
context 'when the required features are enabled' do
before do
stub_licensed_features(sast: true, dast: true)
stub_licensed_features(sast: true, dast: true, security_dashboard: true)
end
context 'when user is member of the project' do
......@@ -86,18 +91,18 @@ RSpec.describe 'Query.project(fullPath).pipeline(iid).securityReportFindings' do
context 'when user is not a member of the project' do
it 'returns no vulnerability findings' do
expect(security_report_findings).to be_nil
expect(security_report_findings).to be_blank
end
end
end
context 'when `sast` and `dast` both features are disabled' do
context 'when the required features are disabled' do
before do
stub_licensed_features(sast: false, dast: false)
stub_licensed_features(sast: false, dast: false, security_dashboard: false)
end
it 'returns no vulnerability findings' do
expect(security_report_findings).to be_nil
expect(security_report_findings).to be_blank
end
end
end
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Query.project(fullPath).pipeline(iid).securityReportSummary' do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project) }
......@@ -66,28 +68,54 @@ RSpec.describe 'Query.project(fullPath).pipeline(iid).securityReportSummary' do
)
end
before do
stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true, dast: true)
project.add_developer(user)
let(:security_report_summary) { subject.dig('project', 'pipeline', 'securityReportSummary') }
subject do
post_graphql(query, current_user: user)
graphql_data
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
context 'when the required features are enabled' do
before do
stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true, dast: true, security_dashboard: true)
end
context 'when user is member of the project' do
before do
project.add_developer(user)
end
it 'shows the vulnerabilitiesCount and scannedResourcesCount' do
expect(security_report_summary.dig('dast', 'vulnerabilitiesCount')).to eq(20)
expect(security_report_summary.dig('dast', 'scannedResourcesCount')).to eq(26)
expect(security_report_summary.dig('sast', 'vulnerabilitiesCount')).to eq(5)
end
let(:security_report_summary) { subject.dig('data', 'project', 'pipeline', 'securityReportSummary') }
it 'shows the first 20 scanned resources' do
dast_scanned_resources = security_report_summary.dig('dast', 'scannedResources', 'nodes')
it 'shows the vulnerabilitiesCount and scannedResourcesCount' do
expect(security_report_summary.dig('dast', 'vulnerabilitiesCount')).to eq(20)
expect(security_report_summary.dig('dast', 'scannedResourcesCount')).to eq(26)
expect(security_report_summary.dig('sast', 'vulnerabilitiesCount')).to eq(5)
end
expect(dast_scanned_resources.length).to eq(20)
end
it 'shows the first 20 scanned resources' do
dast_scanned_resources = security_report_summary.dig('dast', 'scannedResources', 'nodes')
it 'returns nil for the scannedResourcesCsvPath' do
expect(security_report_summary.dig('dast', 'scannedResourcesCsvPath')).to be_nil
end
end
expect(dast_scanned_resources.length).to eq(20)
context 'when user is not a member of the project' do
it 'returns no scanned resources' do
expect(security_report_summary).to be_nil
end
end
end
it 'returns nil for the scannedResourcesCsvPath' do
expect(security_report_summary.dig('dast', 'scannedResourcesCsvPath')).to be_nil
context 'when the required features are disabled' do
before do
stub_licensed_features(sast: false, dependency_scanning: false, container_scanning: false, dast: false, security_dashboard: false)
end
it 'returns no scanned resources' do
expect(security_report_summary).to be_nil
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