Commit d95e99f4 authored by Daniel Tian's avatar Daniel Tian Committed by Olena Horal-Koretska

Add scanner data to vulnerability pages

parent 4d0ca52e
...@@ -14,54 +14,81 @@ export default (el, dashboardType) => { ...@@ -14,54 +14,81 @@ export default (el, dashboardType) => {
return null; return null;
} }
if (el.dataset.isUnavailable) { const {
isUnavailable,
dashboardDocumentation,
emptyStateSvgPath,
noVulnerabilitiesSvgPath,
notEnabledScannersHelpPath,
noPipelineRunScannersHelpPath,
hasVulnerabilities,
scanners,
securityDashboardHelpPath,
projectAddEndpoint,
projectListEndpoint,
vulnerabilitiesExportEndpoint,
projectFullPath,
autoFixDocumentation,
autoFixMrsPath,
groupFullPath,
instanceDashboardSettingsPath,
pipelineCreatedAt,
pipelineId,
pipelinePath,
pipelineSecurityBuildsFailedCount,
pipelineSecurityBuildsFailedPath,
} = el.dataset;
if (isUnavailable) {
return new Vue({ return new Vue({
el, el,
render(createElement) { render(createElement) {
return createElement(UnavailableState, { return createElement(UnavailableState, {
props: { props: {
link: el.dataset.dashboardDocumentation, link: dashboardDocumentation,
svgPath: el.dataset.emptyStateSvgPath, svgPath: emptyStateSvgPath,
}, },
}); });
}, },
}); });
} }
const provide = {}; const provide = {
dashboardDocumentation,
noVulnerabilitiesSvgPath,
emptyStateSvgPath,
notEnabledScannersHelpPath,
noPipelineRunScannersHelpPath,
hasVulnerabilities: parseBoolean(hasVulnerabilities),
scanners: scanners ? JSON.parse(scanners) : [],
};
const props = { const props = {
securityDashboardHelpPath: el.dataset.securityDashboardHelpPath, securityDashboardHelpPath,
projectAddEndpoint: el.dataset.projectAddEndpoint, projectAddEndpoint,
projectListEndpoint: el.dataset.projectListEndpoint, projectListEndpoint,
vulnerabilitiesExportEndpoint: el.dataset.vulnerabilitiesExportEndpoint, vulnerabilitiesExportEndpoint,
}; };
let component; let component;
if (dashboardType === DASHBOARD_TYPES.PROJECT) { if (dashboardType === DASHBOARD_TYPES.PROJECT) {
component = FirstClassProjectSecurityDashboard; component = FirstClassProjectSecurityDashboard;
const {
pipelineCreatedAt: createdAt,
pipelineId: id,
pipelinePath: path,
pipelineSecurityBuildsFailedCount: securityBuildsFailedCount,
pipelineSecurityBuildsFailedPath: securityBuildsFailedPath,
} = el.dataset;
props.pipeline = { props.pipeline = {
createdAt, createdAt: pipelineCreatedAt,
id, id: pipelineId,
path, path: pipelinePath,
securityBuildsFailedCount: Number(securityBuildsFailedCount), securityBuildsFailedCount: Number(pipelineSecurityBuildsFailedCount),
securityBuildsFailedPath, securityBuildsFailedPath: pipelineSecurityBuildsFailedPath,
}; };
provide.projectFullPath = el.dataset.projectFullPath; provide.projectFullPath = projectFullPath;
provide.autoFixDocumentation = el.dataset.autoFixDocumentation; provide.autoFixDocumentation = autoFixDocumentation;
provide.autoFixMrsPath = el.dataset.autoFixMrsPath; provide.autoFixMrsPath = autoFixMrsPath;
} else if (dashboardType === DASHBOARD_TYPES.GROUP) { } else if (dashboardType === DASHBOARD_TYPES.GROUP) {
component = FirstClassGroupSecurityDashboard; component = FirstClassGroupSecurityDashboard;
props.groupFullPath = el.dataset.groupFullPath; props.groupFullPath = groupFullPath;
} else if (dashboardType === DASHBOARD_TYPES.INSTANCE) { } else if (dashboardType === DASHBOARD_TYPES.INSTANCE) {
provide.instanceDashboardSettingsPath = el.dataset.instanceDashboardSettingsPath; provide.instanceDashboardSettingsPath = instanceDashboardSettingsPath;
component = FirstClassInstanceSecurityDashboard; component = FirstClassInstanceSecurityDashboard;
} }
...@@ -73,15 +100,7 @@ export default (el, dashboardType) => { ...@@ -73,15 +100,7 @@ export default (el, dashboardType) => {
store, store,
router, router,
apolloProvider, apolloProvider,
provide: () => ({ provide,
dashboardDocumentation: el.dataset.dashboardDocumentation,
noVulnerabilitiesSvgPath: el.dataset.noVulnerabilitiesSvgPath,
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
notEnabledScannersHelpPath: el.dataset.notEnabledScannersHelpPath,
noPipelineRunScannersHelpPath: el.dataset.noPipelineRunScannersHelpPath,
hasVulnerabilities: parseBoolean(el.dataset.hasVulnerabilities),
...provide,
}),
render(createElement) { render(createElement) {
return createElement(component, { props }); return createElement(component, { props });
}, },
......
...@@ -253,7 +253,8 @@ module EE ...@@ -253,7 +253,8 @@ module EE
no_pipeline_run_scanners_help_path: new_project_pipeline_path(project), no_pipeline_run_scanners_help_path: new_project_pipeline_path(project),
security_dashboard_help_path: help_page_path('user/application_security/security_dashboard/index'), security_dashboard_help_path: help_page_path('user/application_security/security_dashboard/index'),
auto_fix_documentation: help_page_path('user/application_security/index', anchor: 'auto-fix-merge-requests'), auto_fix_documentation: help_page_path('user/application_security/index', anchor: 'auto-fix-merge-requests'),
auto_fix_mrs_path: project_merge_requests_path(@project, label_name: 'GitLab-auto-fix') auto_fix_mrs_path: project_merge_requests_path(@project, label_name: 'GitLab-auto-fix'),
scanners: VulnerabilityScanners::ListService.new(project).execute.to_json
}.merge!(security_dashboard_pipeline_data(project)) }.merge!(security_dashboard_pipeline_data(project))
end end
end end
......
...@@ -44,7 +44,8 @@ module Groups::SecurityFeaturesHelper ...@@ -44,7 +44,8 @@ module Groups::SecurityFeaturesHelper
no_vulnerabilities_svg_path: image_path('illustrations/issues.svg'), no_vulnerabilities_svg_path: image_path('illustrations/issues.svg'),
empty_state_svg_path: image_path('illustrations/security-dashboard-empty-state.svg'), empty_state_svg_path: image_path('illustrations/security-dashboard-empty-state.svg'),
dashboard_documentation: help_page_path('user/application_security/security_dashboard/index'), dashboard_documentation: help_page_path('user/application_security/security_dashboard/index'),
vulnerabilities_export_endpoint: expose_path(api_v4_security_groups_vulnerability_exports_path(id: group.id)) vulnerabilities_export_endpoint: expose_path(api_v4_security_groups_vulnerability_exports_path(id: group.id)),
scanners: VulnerabilityScanners::ListService.new(group).execute.to_json
} }
end end
end end
...@@ -10,7 +10,8 @@ module SecurityHelper ...@@ -10,7 +10,8 @@ module SecurityHelper
project_add_endpoint: security_projects_path, project_add_endpoint: security_projects_path,
project_list_endpoint: security_projects_path, project_list_endpoint: security_projects_path,
instance_dashboard_settings_path: settings_security_dashboard_path, instance_dashboard_settings_path: settings_security_dashboard_path,
vulnerabilities_export_endpoint: expose_path(api_v4_security_vulnerability_exports_path) vulnerabilities_export_endpoint: expose_path(api_v4_security_vulnerability_exports_path),
scanners: VulnerabilityScanners::ListService.new(InstanceSecurityDashboard.new(current_user)).execute.to_json
} }
end end
......
# frozen_string_literal: true
module VulnerabilityScanners
class ListService < BaseService
def initialize(vulnerable)
@vulnerable = vulnerable
end
def execute
@vulnerable
.vulnerability_scanners
.with_report_type
.map do |scanner|
{
external_id: scanner.external_id,
vendor: scanner.vendor,
report_type: ::Enums::Vulnerability.report_types.key(scanner.report_type).upcase
}
end
end
end
end
...@@ -161,7 +161,8 @@ RSpec.describe Groups::SecurityFeaturesHelper do ...@@ -161,7 +161,8 @@ RSpec.describe Groups::SecurityFeaturesHelper do
no_vulnerabilities_svg_path: '/images/illustrations/issues.svg', no_vulnerabilities_svg_path: '/images/illustrations/issues.svg',
empty_state_svg_path: '/images/illustrations/security-dashboard-empty-state.svg', empty_state_svg_path: '/images/illustrations/security-dashboard-empty-state.svg',
dashboard_documentation: '/help/user/application_security/security_dashboard/index', dashboard_documentation: '/help/user/application_security/security_dashboard/index',
vulnerabilities_export_endpoint: "/api/v4/security/groups/#{group.id}/vulnerability_exports" vulnerabilities_export_endpoint: "/api/v4/security/groups/#{group.id}/vulnerability_exports",
scanners: '[]'
} }
end end
......
...@@ -155,12 +155,15 @@ RSpec.describe ProjectsHelper do ...@@ -155,12 +155,15 @@ RSpec.describe ProjectsHelper do
not_enabled_scanners_help_path: help_page_path('user/application_security/index', anchor: 'quick-start'), not_enabled_scanners_help_path: help_page_path('user/application_security/index', anchor: 'quick-start'),
no_pipeline_run_scanners_help_path: "/#{project.full_path}/-/pipelines/new", no_pipeline_run_scanners_help_path: "/#{project.full_path}/-/pipelines/new",
auto_fix_documentation: help_page_path('user/application_security/index', anchor: 'auto-fix-merge-requests'), auto_fix_documentation: help_page_path('user/application_security/index', anchor: 'auto-fix-merge-requests'),
auto_fix_mrs_path: end_with('/merge_requests?label_name=GitLab-auto-fix') auto_fix_mrs_path: end_with('/merge_requests?label_name=GitLab-auto-fix'),
scanners: '[{"external_id":"security_vendor","vendor":"Security Vendor","report_type":"SAST"}]'
} }
end end
before do before do
create(:vulnerability, project: project) create(:vulnerability, project: project)
scanner = create(:vulnerabilities_scanner, project: project, external_id: 'security_vendor')
create(:vulnerabilities_finding, project: project, scanner: scanner)
end end
context 'without pipeline' do context 'without pipeline' do
......
...@@ -6,6 +6,8 @@ RSpec.describe SecurityHelper do ...@@ -6,6 +6,8 @@ RSpec.describe SecurityHelper do
describe '#instance_security_dashboard_data' do describe '#instance_security_dashboard_data' do
subject { instance_security_dashboard_data } subject { instance_security_dashboard_data }
let_it_be(:current_user) { create(:user) }
it 'returns vulnerability, project, feedback, asset, and docs paths for the instance security dashboard' do it 'returns vulnerability, project, feedback, asset, and docs paths for the instance security dashboard' do
is_expected.to eq({ is_expected.to eq({
dashboard_documentation: help_page_path('user/application_security/security_dashboard/index', anchor: 'instance-security-dashboard'), dashboard_documentation: help_page_path('user/application_security/security_dashboard/index', anchor: 'instance-security-dashboard'),
...@@ -15,7 +17,8 @@ RSpec.describe SecurityHelper do ...@@ -15,7 +17,8 @@ RSpec.describe SecurityHelper do
project_add_endpoint: security_projects_path, project_add_endpoint: security_projects_path,
project_list_endpoint: security_projects_path, project_list_endpoint: security_projects_path,
instance_dashboard_settings_path: settings_security_dashboard_path, instance_dashboard_settings_path: settings_security_dashboard_path,
vulnerabilities_export_endpoint: api_v4_security_vulnerability_exports_path vulnerabilities_export_endpoint: api_v4_security_vulnerability_exports_path,
scanners: '[]'
}) })
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe VulnerabilityScanners::ListService do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:vulnerability_scanner) { create(:vulnerabilities_scanner, project: project, external_id: 'external_vendor') }
let_it_be(:vulnerability_finding) { create(:vulnerabilities_finding, project: project, scanner: vulnerability_scanner) }
let(:service) { described_class.new(vulnerable) }
subject(:scanner_list) { service.execute }
context 'when looking for scanners for group' do
let(:vulnerable) { group }
it { is_expected.to eq([{ external_id: "external_vendor", vendor: "Security Vendor", report_type: "SAST" }]) }
end
context 'when looking for scanners for project' do
let(:vulnerable) { project }
it { is_expected.to eq([{ external_id: "external_vendor", vendor: "Security Vendor", report_type: "SAST" }]) }
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