diff --git a/ee/app/services/issues/build_from_vulnerability_service.rb b/ee/app/services/issues/build_from_vulnerability_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..042214af184985fe868cd8ba02d7df73af2727ba --- /dev/null +++ b/ee/app/services/issues/build_from_vulnerability_service.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Issues + class BuildFromVulnerabilityService < Issues::BuildService + def execute + vulnerability = params[:vulnerability] + + params.merge!( + title: _("Investigate vulnerability: %{title}") % { title: vulnerability.title }, + description: render_description(vulnerability), + confidential: true + ) + + super + end + + private + + def render_description(vulnerability) + ApplicationController.render( + template: 'vulnerabilities/issue_description.md.erb', + locals: { vulnerability: vulnerability.present } + ) + end + end +end diff --git a/ee/app/views/vulnerabilities/issue_description.md.erb b/ee/app/views/vulnerabilities/issue_description.md.erb index 1c23adffa3fc6146207e84ba15cc7f48016e94c5..df6bf36bfb8c1b4f269584a1101e68c1c30c7597 100644 --- a/ee/app/views/vulnerabilities/issue_description.md.erb +++ b/ee/app/views/vulnerabilities/issue_description.md.erb @@ -15,14 +15,14 @@ <% if vulnerability.try(:file) %> * <%= _("Location") %>: [<%= vulnerability.location_text %>](<%= vulnerability.location_link %>) <% end %> - <% if vulnerability.solution.present? %> + ### <%= _("Solution") %>: <%= vulnerability.solution %> <% end %> - <% if vulnerability.identifiers.present? %> + ### <%= _("Identifiers") %>: <% vulnerability.identifiers.each do |identifier| %> @@ -33,8 +33,8 @@ <% end %> <% end %> <% end %> - <% if vulnerability.links.present? %> + ### <%= _("Links") %>: <% vulnerability.links.each do |link| %> @@ -45,8 +45,8 @@ <% end %> <% end %> <% end %> - <% if vulnerability.remediations.present? && vulnerability.remediations.any? %> + ### <%= _("Remediations") %>: <% vulnerability.remediations.each do |remediation| %> @@ -60,8 +60,8 @@ </details> <% end %> <% end %> - <% if vulnerability.scanner.present? || vulnerability.scan.present? %> + ### <%= _("Scanner") %>: <% if vulnerability.scanner.present? %> diff --git a/ee/spec/services/ee/issues/build_from_vulnerability_service_spec.rb b/ee/spec/services/ee/issues/build_from_vulnerability_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..5e825619235f8fca47310ba35586e19302999b32 --- /dev/null +++ b/ee/spec/services/ee/issues/build_from_vulnerability_service_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Issues::BuildFromVulnerabilityService do + describe '#execute' do + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :public, :repository, namespace: group) } + let_it_be(:user) { create(:user) } + + before_all do + group.add_developer(user) + end + + before do + stub_licensed_features(security_dashboard: true) + end + + it 'builds the issue with the given params' do + vulnerability = create(:vulnerability, :with_finding, project: project) + service = described_class.new(project, user, vulnerability: vulnerability) + + issue = service.execute + + expect(issue).not_to be_persisted + expect(issue).to have_attributes( + project: project, + author: user, + title: "Investigate vulnerability: #{vulnerability.title}", + description: + <<~DESC + Issue created from vulnerability <a href="http://localhost/#{group.name}/#{project.name}/-/security/vulnerabilities/#{vulnerability.id}">#{vulnerability.id}</a> + + ### Description: + + Description of #{vulnerability.title} + + * Severity: #{vulnerability.severity} + * Confidence: #{vulnerability.confidence} + * Location: [maven/src/main/java/com/gitlab/security_products/tests/App.java:29](http://localhost/#{project.full_path}/-/blob/master/maven/src/main/java/com/gitlab/security_products/tests/App.java#L29) + + ### Solution: + + #{vulnerability.solution} + + ### Identifiers: + + * [CVE-2018-1234](http://cve.mitre.org/cgi-bin/cvename.cgi?name=2018-1234) + + ### Links: + + * [Cipher does not check for integrity first?](https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first) + + ### Scanner: + + * Name: Find Security Bugs + DESC + ) + end + + context 'when a vulnerability has remediations' do + it 'displays Remediations section with attached diff' do + vulnerability = create(:vulnerability, :with_remediation, project: project) + service = described_class.new(project, user, vulnerability: vulnerability) + + issue = service.execute + + expect(issue.description).to match(/Remediations/) + expect(issue.description).to match(/This is a diff/) + end + end + end +end diff --git a/ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb b/ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb index a8df9f261a3906d40570787a0df86ffe569ecaef..3f368a10ba02167a1d3eaff77a521aeb5cbec7f8 100644 --- a/ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb +++ b/ee/spec/services/ee/issues/create_from_vulnerability_data_service_spec.rb @@ -118,7 +118,6 @@ * [Awesome-security blog post](https;//example.com/blog-post) * https://example.com/another-link - ### Scanner: * Name: Gemnasium @@ -164,9 +163,6 @@ Please do something! - - - ### Scanner: * Name: Gemnasium diff --git a/ee/spec/services/ee/issues/create_from_vulnerability_service_spec.rb b/ee/spec/services/ee/issues/create_from_vulnerability_service_spec.rb index 36c0c04432d886bac53f958ca467960015e5d443..64f655197cfcbf90f9aafe081dae3fdc7aec69de 100644 --- a/ee/spec/services/ee/issues/create_from_vulnerability_service_spec.rb +++ b/ee/spec/services/ee/issues/create_from_vulnerability_service_spec.rb @@ -119,7 +119,6 @@ * [Cipher does not check for integrity first?](https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first) - ### Scanner: * Name: Find Security Bugs