Commit a4379bae authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Dmytro Zaporozhets (DZ)

Add method to create issue in Jira from vulnerability finding

This change adds link to finding to create issue in Jira.
parent eb544aac
# frozen_string_literal: true # frozen_string_literal: true
module VulnerabilitiesHelper module VulnerabilitiesHelper
FINDING_FIELDS = %i[metadata identifiers name issue_feedback merge_request_feedback project project_fingerprint scanner].freeze
def vulnerability_details_json(vulnerability, pipeline) def vulnerability_details_json(vulnerability, pipeline)
vulnerability_details(vulnerability, pipeline).to_json vulnerability_details(vulnerability, pipeline).to_json
end end
...@@ -36,9 +38,10 @@ module VulnerabilitiesHelper ...@@ -36,9 +38,10 @@ module VulnerabilitiesHelper
def create_jira_issue_url_for(vulnerability) def create_jira_issue_url_for(vulnerability)
return unless vulnerability.project.jira_vulnerabilities_integration_enabled? return unless vulnerability.project.jira_vulnerabilities_integration_enabled?
summary = _('Investigate vulnerability: %{title}') % { title: vulnerability.title } decorated_vulnerability = vulnerability.present
summary = _('Investigate vulnerability: %{title}') % { title: decorated_vulnerability.title }
description = ApplicationController.render(template: 'vulnerabilities/jira_issue_description.md.erb', description = ApplicationController.render(template: 'vulnerabilities/jira_issue_description.md.erb',
locals: { vulnerability: vulnerability.present }) locals: { vulnerability: decorated_vulnerability })
vulnerability.project.jira_service.new_issue_url_with_predefined_fields(summary, description) vulnerability.project.jira_service.new_issue_url_with_predefined_fields(summary, description)
end end
...@@ -59,28 +62,7 @@ module VulnerabilitiesHelper ...@@ -59,28 +62,7 @@ module VulnerabilitiesHelper
end end
def vulnerability_finding_data(vulnerability) def vulnerability_finding_data(vulnerability)
finding = Vulnerabilities::FindingSerializer.new(current_user: current_user).represent(vulnerability.finding) data = Vulnerabilities::FindingSerializer.new(current_user: current_user).represent(vulnerability.finding, only: FINDING_FIELDS)
data = finding.slice(
:description,
:identifiers,
:links,
:location,
:name,
:issue_feedback,
:merge_request_feedback,
:project,
:project_fingerprint,
:remediations,
:evidence,
:scanner,
:solution,
:request,
:response,
:evidence_source,
:supporting_messages,
:assets
)
if data[:location]['file'] if data[:location]['file']
branch = vulnerability.finding.pipelines&.last&.sha || vulnerability.project.default_branch branch = vulnerability.finding.pipelines&.last&.sha || vulnerability.project.default_branch
......
...@@ -4,6 +4,10 @@ module Vulnerabilities ...@@ -4,6 +4,10 @@ module Vulnerabilities
class FindingPresenter < Gitlab::View::Presenter::Delegated class FindingPresenter < Gitlab::View::Presenter::Delegated
presents :finding presents :finding
def title
name
end
def blob_path def blob_path
return '' unless sha.present? return '' unless sha.present?
return '' unless location.present? && location['file'].present? return '' unless location.present? && location['file'].present?
......
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
class Vulnerabilities::FindingEntity < Grape::Entity class Vulnerabilities::FindingEntity < Grape::Entity
include RequestAwareEntity include RequestAwareEntity
include VulnerabilitiesHelper
expose :id, :report_type, :name, :severity, :confidence expose :id, :report_type, :name, :severity, :confidence
expose :scanner, using: Vulnerabilities::ScannerEntity expose :scanner, using: Vulnerabilities::ScannerEntity
expose :identifiers, using: Vulnerabilities::IdentifierEntity expose :identifiers, using: Vulnerabilities::IdentifierEntity
expose :project_fingerprint expose :project_fingerprint
expose :create_jira_issue_url do |occurrence|
create_jira_issue_url_for(occurrence)
end
expose :create_vulnerability_feedback_issue_path do |occurrence| expose :create_vulnerability_feedback_issue_path do |occurrence|
create_vulnerability_feedback_issue_path(occurrence.project) create_vulnerability_feedback_issue_path(occurrence.project)
end end
......
...@@ -12,11 +12,11 @@ h3. <%= _("Description") %>: ...@@ -12,11 +12,11 @@ h3. <%= _("Description") %>:
<% if vulnerability.confidence.present? %> <% if vulnerability.confidence.present? %>
* <%= _("Confidence") %>: <%= vulnerability.confidence %> * <%= _("Confidence") %>: <%= vulnerability.confidence %>
<% end %> <% end %>
<% if vulnerability.try(:file) %> <% if vulnerability.try(:location_text) && vulnerability.try(:location_link) %>
* <%= _("Location") %>: [<%= vulnerability.location_text %>|<%= vulnerability.location_link %>] * <%= _("Location") %>: [<%= vulnerability.try(:location_text) %>|<%= vulnerability.try(:location_link) %>]
<% end %> <% end %>
<% if vulnerability.solution.present? %> <% if vulnerability.solution.present? && vulnerability.is_a?(Vulnerability) %>
### <%= _("Solution") %>: ### <%= _("Solution") %>:
<%= _("See vulnerability %{vulnerability_link} for any Solution details.".html_safe) % { vulnerability_link: "[#{vulnerability.id}|#{vulnerability_url(vulnerability)}]" } %> <%= _("See vulnerability %{vulnerability_link} for any Solution details.".html_safe) % { vulnerability_link: "[#{vulnerability.id}|#{vulnerability_url(vulnerability)}]" } %>
...@@ -59,17 +59,17 @@ h3. <%= _("Scanner") %>: ...@@ -59,17 +59,17 @@ h3. <%= _("Scanner") %>:
* <%= _("Name") %>: <%= vulnerability.scanner[:name] %> * <%= _("Name") %>: <%= vulnerability.scanner[:name] %>
<% end %> <% end %>
<% if vulnerability.scan.present? %> <% if vulnerability.scan.present? %>
<% if vulnerability.scan[:type].present? %> <% if vulnerability.scan.type.present? %>
* <%= _("Type") %>: <%= vulnerability.scan[:type] %> * <%= _("Type") %>: <%= vulnerability.scan.type %>
<% end %> <% end %>
<% if vulnerability.scan[:status].present? %> <% if vulnerability.scan.status.present? %>
* <%= _("Status") %>: <%= vulnerability.scan[:status] %> * <%= _("Status") %>: <%= vulnerability.scan.status %>
<% end %> <% end %>
<% if vulnerability.scan[:start_time].present? %> <% if vulnerability.scan.start_time.present? %>
* <%= _("Start Time") %>: <%= vulnerability.scan[:start_time] %> * <%= _("Start Time") %>: <%= vulnerability.scan.start_time %>
<% end %> <% end %>
<% if vulnerability.scan[:end_time].present? %> <% if vulnerability.scan.end_time.present? %>
* <%= _("End Time") %>: <%= vulnerability.scan[:end_time] %> * <%= _("End Time") %>: <%= vulnerability.scan.end_time %>
<% end %> <% end %>
<% end %> <% end %>
<% end %> <% end %>
...@@ -41,6 +41,8 @@ RSpec.describe VulnerabilitiesHelper do ...@@ -41,6 +41,8 @@ RSpec.describe VulnerabilitiesHelper do
:solution) :solution)
end end
let(:desired_serializer_fields) { %i[metadata identifiers name issue_feedback merge_request_feedback project project_fingerprint scanner] }
before do before do
vulnerability_serializer_stub = instance_double("VulnerabilitySerializer") vulnerability_serializer_stub = instance_double("VulnerabilitySerializer")
expect(VulnerabilitySerializer).to receive(:new).and_return(vulnerability_serializer_stub) expect(VulnerabilitySerializer).to receive(:new).and_return(vulnerability_serializer_stub)
...@@ -48,7 +50,7 @@ RSpec.describe VulnerabilitiesHelper do ...@@ -48,7 +50,7 @@ RSpec.describe VulnerabilitiesHelper do
finding_serializer_stub = instance_double("Vulnerabilities::FindingSerializer") finding_serializer_stub = instance_double("Vulnerabilities::FindingSerializer")
expect(Vulnerabilities::FindingSerializer).to receive(:new).and_return(finding_serializer_stub) expect(Vulnerabilities::FindingSerializer).to receive(:new).and_return(finding_serializer_stub)
expect(finding_serializer_stub).to receive(:represent).with(finding).and_return(finding_serializer_hash) expect(finding_serializer_stub).to receive(:represent).with(finding, only: desired_serializer_fields).and_return(finding_serializer_hash)
end end
around do |example| around do |example|
...@@ -227,7 +229,7 @@ RSpec.describe VulnerabilitiesHelper do ...@@ -227,7 +229,7 @@ RSpec.describe VulnerabilitiesHelper do
subject { helper.vulnerability_finding_data(vulnerability) } subject { helper.vulnerability_finding_data(vulnerability) }
it 'returns finding information' do it 'returns finding information' do
expect(subject).to match( expect(subject.to_h).to match(
description: finding.description, description: finding.description,
identifiers: kind_of(Array), identifiers: kind_of(Array),
issue_feedback: anything, issue_feedback: anything,
......
...@@ -6,6 +6,12 @@ RSpec.describe Vulnerabilities::FindingPresenter do ...@@ -6,6 +6,12 @@ RSpec.describe Vulnerabilities::FindingPresenter do
let(:presenter) { described_class.new(occurrence) } let(:presenter) { described_class.new(occurrence) }
let(:occurrence) { build_stubbed(:vulnerabilities_finding) } let(:occurrence) { build_stubbed(:vulnerabilities_finding) }
describe '#title' do
subject { presenter.title }
it { is_expected.to eq occurrence.name }
end
describe '#blob_path' do describe '#blob_path' do
subject { presenter.blob_path } subject { presenter.blob_path }
......
...@@ -4,7 +4,7 @@ require 'spec_helper' ...@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Vulnerabilities::FindingEntity do RSpec.describe Vulnerabilities::FindingEntity do
let_it_be(:user) { build(:user) } let_it_be(:user) { build(:user) }
let_it_be(:project) { build(:project) } let_it_be_with_refind(:project) { create(:project) }
let(:scanner) { build(:vulnerabilities_scanner, project: project) } let(:scanner) { build(:vulnerabilities_scanner, project: project) }
...@@ -67,6 +67,7 @@ RSpec.describe Vulnerabilities::FindingEntity do ...@@ -67,6 +67,7 @@ RSpec.describe Vulnerabilities::FindingEntity do
end end
it 'does not contain vulnerability feedback paths' do it 'does not contain vulnerability feedback paths' do
expect(subject[:create_jira_issue_url]).to be_falsey
expect(subject[:create_vulnerability_feedback_issue_path]).to be_falsey expect(subject[:create_vulnerability_feedback_issue_path]).to be_falsey
expect(subject[:create_vulnerability_feedback_merge_request_path]).to be_falsey expect(subject[:create_vulnerability_feedback_merge_request_path]).to be_falsey
expect(subject[:create_vulnerability_feedback_dismissal_path]).to be_falsey expect(subject[:create_vulnerability_feedback_dismissal_path]).to be_falsey
...@@ -78,6 +79,10 @@ RSpec.describe Vulnerabilities::FindingEntity do ...@@ -78,6 +79,10 @@ RSpec.describe Vulnerabilities::FindingEntity do
project.add_developer(user) project.add_developer(user)
end end
it 'does not contain create jira issue path' do
expect(subject[:create_jira_issue_url]).to be_falsey
end
it 'contains vulnerability feedback dismissal path' do it 'contains vulnerability feedback dismissal path' do
expect(subject).to include(:create_vulnerability_feedback_dismissal_path) expect(subject).to include(:create_vulnerability_feedback_dismissal_path)
end end
...@@ -90,9 +95,28 @@ RSpec.describe Vulnerabilities::FindingEntity do ...@@ -90,9 +95,28 @@ RSpec.describe Vulnerabilities::FindingEntity do
expect(subject).to include(:create_vulnerability_feedback_merge_request_path) expect(subject).to include(:create_vulnerability_feedback_merge_request_path)
end end
context 'when jira service is configured' do
let_it_be(:jira_service) { create(:jira_service, project: project, issues_enabled: true, project_key: 'FE', vulnerabilities_enabled: true, vulnerabilities_issuetype: '10001') }
before do
stub_licensed_features(jira_vulnerabilities_integration: true)
allow_next_found_instance_of(JiraService) do |jira|
allow(jira).to receive(:jira_project_id).and_return('11223')
end
end
it 'does contains create jira issue path' do
expect(subject[:create_jira_issue_url]).to be_present
end
end
context 'when disallowed to create issue' do context 'when disallowed to create issue' do
let(:project) { create(:project, issues_access_level: ProjectFeature::DISABLED) } let(:project) { create(:project, issues_access_level: ProjectFeature::DISABLED) }
it 'does not contain create jira issue path' do
expect(subject[:create_jira_issue_url]).to be_falsey
end
it 'does not contain vulnerability feedback issue path' do it 'does not contain vulnerability feedback issue path' do
expect(subject[:create_vulnerability_feedback_issue_path]).to be_falsey expect(subject[:create_vulnerability_feedback_issue_path]).to be_falsey
end end
...@@ -109,6 +133,10 @@ RSpec.describe Vulnerabilities::FindingEntity do ...@@ -109,6 +133,10 @@ RSpec.describe Vulnerabilities::FindingEntity do
context 'when disallowed to create merge_request' do context 'when disallowed to create merge_request' do
let(:project) { create(:project, merge_requests_access_level: ProjectFeature::DISABLED) } let(:project) { create(:project, merge_requests_access_level: ProjectFeature::DISABLED) }
it 'does not contain create jira issue path' do
expect(subject[:create_jira_issue_url]).to be_falsey
end
it 'does not contain vulnerability feedback merge_request path' do it 'does not contain vulnerability feedback merge_request path' do
expect(subject[:create_vulnerability_feedback_merge_request_path]).to be_falsey expect(subject[:create_vulnerability_feedback_merge_request_path]).to be_falsey
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