Commit bfb73335 authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Gabriel Mazetto

Add new fields for creating issues from vulnerabilities in Jira

This change adds new fields vulnerabilities_enabled and
vulnerabilities_issuetype to JiraTrackerData to allow user to configure
Jira for vulnerabilities.
parent 241ab0c9
...@@ -13,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -13,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController
before_action :redirect_deprecated_prometheus_service, only: [:update] before_action :redirect_deprecated_prometheus_service, only: [:update]
before_action only: :edit do before_action only: :edit do
push_frontend_feature_flag(:jira_issues_integration, @project, type: :licensed, default_enabled: true) push_frontend_feature_flag(:jira_issues_integration, @project, type: :licensed, default_enabled: true)
push_frontend_feature_flag(:jira_vulnerabilities_integration, @project, type: :licensed, default_enabled: true)
push_frontend_feature_flag(:jira_for_vulnerabilities, @project, type: :development, default_enabled: false)
end end
respond_to :html respond_to :html
......
...@@ -30,7 +30,7 @@ class JiraService < IssueTrackerService ...@@ -30,7 +30,7 @@ class JiraService < IssueTrackerService
# TODO: we can probably just delegate as part of # TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab/issues/29404 # https://gitlab.com/gitlab-org/gitlab/issues/29404
data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled, :vulnerabilities_enabled, :vulnerabilities_issuetype
before_update :reset_password before_update :reset_password
after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type? after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
......
---
name: jira_for_vulnerabilities
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46982
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276893
type: development
group: group::threat insights
default_enabled: false
# frozen_string_literal: true
class AddVulnerabilitiesEnabledAndIssuetypeToJiraTrackerData < ActiveRecord::Migration[6.0]
DOWNTIME = false
# rubocop:disable Migration/AddLimitToTextColumns
# limit is added in 20201105143312_add_text_limit_to_jira_tracker_data_issuetype.rb
def change
add_column :jira_tracker_data, :vulnerabilities_issuetype, :text
add_column :jira_tracker_data, :vulnerabilities_enabled, :boolean, default: false, null: false
end
# rubocop:enable Migration/AddLimitToTextColumns
end
# frozen_string_literal: true
class AddTextLimitToJiraTrackerDataIssuetype < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_text_limit :jira_tracker_data, :vulnerabilities_issuetype, 255
end
def down
remove_text_limit :jira_tracker_data, :vulnerabilities_issuetype
end
end
b614435cdb654ebbd11bcc5ac0ed69352219e51b368d8f10c0b2998c5258caf9
\ No newline at end of file
decdc314dbcf6b8ac2ce140f81f9d342efca0d98bbeff10c7a041568a67b63f3
\ No newline at end of file
...@@ -13172,6 +13172,9 @@ CREATE TABLE jira_tracker_data ( ...@@ -13172,6 +13172,9 @@ CREATE TABLE jira_tracker_data (
project_key text, project_key text,
issues_enabled boolean DEFAULT false NOT NULL, issues_enabled boolean DEFAULT false NOT NULL,
deployment_type smallint DEFAULT 0 NOT NULL, deployment_type smallint DEFAULT 0 NOT NULL,
vulnerabilities_issuetype text,
vulnerabilities_enabled boolean DEFAULT false NOT NULL,
CONSTRAINT check_0bf84b76e9 CHECK ((char_length(vulnerabilities_issuetype) <= 255)),
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255)) CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
); );
......
...@@ -13,7 +13,9 @@ module EE ...@@ -13,7 +13,9 @@ module EE
:opsgenie_mvc_enabled, :opsgenie_mvc_enabled,
:opsgenie_mvc_target_url, :opsgenie_mvc_target_url,
:repository_url, :repository_url,
:static_context :static_context,
:vulnerabilities_enabled,
:vulnerabilities_issuetype
].freeze ].freeze
override :allowed_service_params override :allowed_service_params
......
...@@ -16,8 +16,11 @@ module EE ...@@ -16,8 +16,11 @@ module EE
if integration.is_a?(JiraService) if integration.is_a?(JiraService)
form_data.merge!( form_data.merge!(
show_jira_issues_integration: @project&.feature_available?(:jira_issues_integration).to_s, show_jira_issues_integration: @project&.feature_available?(:jira_issues_integration).to_s,
show_jira_vulnerabilities_integration: @project&.jira_vulnerabilities_integration_available?.to_s,
enable_jira_issues: integration.issues_enabled.to_s, enable_jira_issues: integration.issues_enabled.to_s,
enable_jira_vulnerabilities: integration.jira_vulnerabilities_integration_enabled?.to_s,
project_key: integration.project_key, project_key: integration.project_key,
vulnerabilities_issuetype: integration.vulnerabilities_issuetype,
gitlab_issues_enabled: @project&.issues_enabled?.to_s, gitlab_issues_enabled: @project&.issues_enabled?.to_s,
upgrade_plan_path: @project && ::Gitlab::CurrentSettings.should_check_namespace_plan? ? upgrade_plan_path(@project.group) : nil, upgrade_plan_path: @project && ::Gitlab::CurrentSettings.should_check_namespace_plan? ? upgrade_plan_path(@project.group) : nil,
edit_project_path: @project ? edit_project_path(@project, anchor: 'js-shared-permissions') : nil edit_project_path: @project ? edit_project_path(@project, anchor: 'js-shared-permissions') : nil
......
...@@ -189,6 +189,7 @@ module EE ...@@ -189,6 +189,7 @@ module EE
delegate :merge_trains_enabled?, to: :ci_cd_settings delegate :merge_trains_enabled?, to: :ci_cd_settings
delegate :auto_rollback_enabled, :auto_rollback_enabled=, :auto_rollback_enabled?, to: :ci_cd_settings delegate :auto_rollback_enabled, :auto_rollback_enabled=, :auto_rollback_enabled?, to: :ci_cd_settings
delegate :closest_gitlab_subscription, to: :namespace delegate :closest_gitlab_subscription, to: :namespace
delegate :jira_vulnerabilities_integration_enabled?, to: :jira_service, allow_nil: true
delegate :requirements_access_level, to: :project_feature, allow_nil: true delegate :requirements_access_level, to: :project_feature, allow_nil: true
...@@ -349,6 +350,10 @@ module EE ...@@ -349,6 +350,10 @@ module EE
feature_available?(:jira_issues_integration) feature_available?(:jira_issues_integration)
end end
def jira_vulnerabilities_integration_available?
::Feature.enabled?(:jira_for_vulnerabilities, self, default_enabled: false) && feature_available?(:jira_vulnerabilities_integration)
end
def multiple_approval_rules_available? def multiple_approval_rules_available?
feature_available?(:multiple_approval_rules) feature_available?(:multiple_approval_rules)
end end
......
...@@ -95,6 +95,7 @@ class License < ApplicationRecord ...@@ -95,6 +95,7 @@ class License < ApplicationRecord
ide_schema_config ide_schema_config
issues_analytics issues_analytics
jira_issues_integration jira_issues_integration
jira_vulnerabilities_integration
ldap_group_sync_filter ldap_group_sync_filter
merge_pipelines merge_pipelines
merge_request_performance_metrics merge_request_performance_metrics
......
...@@ -5,7 +5,16 @@ module EE ...@@ -5,7 +5,16 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
prepended do prepended do
validates :project_key, presence: true, if: :issues_enabled validates :project_key, presence: true, if: :project_key_required?
validates :vulnerabilities_issuetype, presence: true, if: :vulnerabilities_enabled
end
def jira_vulnerabilities_integration_enabled?
project.jira_vulnerabilities_integration_available? && vulnerabilities_enabled
end
def project_key_required?
issues_enabled || vulnerabilities_enabled
end end
def issue_types def issue_types
......
---
title: Add new fields for creating issues from vulnerabilities in Jira
merge_request: 46982
author:
type: added
...@@ -13,7 +13,7 @@ RSpec.describe EE::ServicesHelper do ...@@ -13,7 +13,7 @@ RSpec.describe EE::ServicesHelper do
end end
end end
let_it_be(:project) { create(:project) } let_it_be_with_refind(:project) { create(:project) }
subject { controller_class.new } subject { controller_class.new }
...@@ -28,26 +28,55 @@ RSpec.describe EE::ServicesHelper do ...@@ -28,26 +28,55 @@ RSpec.describe EE::ServicesHelper do
let(:integration) { build(:slack_service) } let(:integration) { build(:slack_service) }
it 'does not include Jira specific fields' do it 'does not include Jira specific fields' do
is_expected.not_to include(:show_jira_issues_integration, :enable_jira_issues, :project_key, :gitlab_issues_enabled, :edit_project_path) is_expected.not_to include(:show_jira_issues_integration, :show_jira_vulnerabilities_integration, :enable_jira_issues, :project_key, :gitlab_issues_enabled, :edit_project_path)
end end
end end
context 'Jira service' do context 'Jira service' do
let(:integration) { create(:jira_service, project: project, issues_enabled: true, project_key: 'FE') } let_it_be_with_refind(:integration) { create(:jira_service, project: project, issues_enabled: true, project_key: 'FE', vulnerabilities_enabled: true, vulnerabilities_issuetype: '10001') }
context 'when there is no license for jira_vulnerabilities_integration' do
before do
stub_feature_flags(jira_for_vulnerabilities: true)
end
it 'includes Jira specific fields' do it 'includes Jira specific fields' do
stub_licensed_features(jira_issues_integration: true) is_expected.to include(show_jira_vulnerabilities_integration: 'false')
end
end
context 'when flag is disabled for jira_for_vulnerabilities' do
before do
stub_licensed_features(jira_issues_integration: true, jira_vulnerabilities_integration: true)
stub_feature_flags(jira_for_vulnerabilities: false)
end
it 'includes Jira specific fields' do
is_expected.to include(show_jira_vulnerabilities_integration: 'false')
end
end
context 'when all flags are enabled' do
before do
stub_licensed_features(jira_issues_integration: true, jira_vulnerabilities_integration: true)
stub_feature_flags(jira_for_vulnerabilities: true)
end
it 'includes Jira specific fields' do
is_expected.to include( is_expected.to include(
show_jira_issues_integration: 'true', show_jira_issues_integration: 'true',
show_jira_vulnerabilities_integration: 'true',
enable_jira_issues: 'true', enable_jira_issues: 'true',
enable_jira_vulnerabilities: 'true',
project_key: 'FE', project_key: 'FE',
vulnerabilities_issuetype: '10001',
gitlab_issues_enabled: 'true', gitlab_issues_enabled: 'true',
edit_project_path: edit_project_path(project, anchor: 'js-shared-permissions') edit_project_path: edit_project_path(project, anchor: 'js-shared-permissions')
) )
end end
end end
end end
end
describe '#add_to_slack_link' do describe '#add_to_slack_link' do
it 'encodes a masked CSRF token' do it 'encodes a masked CSRF token' do
......
...@@ -12,6 +12,68 @@ RSpec.describe JiraService do ...@@ -12,6 +12,68 @@ RSpec.describe JiraService do
expect(jira_service).to be_invalid expect(jira_service).to be_invalid
end end
it 'validates presence of project_key if vulnerabilities_enabled' do
jira_service.project_key = ''
jira_service.vulnerabilities_enabled = true
expect(jira_service).to be_invalid
end
it 'validates presence of vulnerabilities_issuetype if vulnerabilities_enabled' do
jira_service.vulnerabilities_issuetype = ''
jira_service.vulnerabilities_enabled = true
expect(jira_service).to be_invalid
end
end
describe 'jira_vulnerabilities_integration_enabled?' do
subject(:jira_vulnerabilities_integration_enabled) { jira_service.jira_vulnerabilities_integration_enabled? }
context 'when jira integration is not available for the project' do
before do
allow(jira_service.project).to receive(:jira_vulnerabilities_integration_available?).and_return(false)
end
context 'when vulnerabilities_enabled is set to false' do
before do
allow(jira_service).to receive(:vulnerabilities_enabled).and_return(false)
end
it { is_expected.to eq(false) }
end
context 'when vulnerabilities_enabled is set to true' do
before do
allow(jira_service).to receive(:vulnerabilities_enabled).and_return(true)
end
it { is_expected.to eq(false) }
end
end
context 'when jira integration is available for the project' do
before do
allow(jira_service.project).to receive(:jira_vulnerabilities_integration_available?).and_return(true)
end
context 'when vulnerabilities_enabled is set to false' do
before do
allow(jira_service).to receive(:vulnerabilities_enabled).and_return(false)
end
it { is_expected.to eq(false) }
end
context 'when vulnerabilities_enabled is set to true' do
before do
allow(jira_service).to receive(:vulnerabilities_enabled).and_return(true)
end
it { is_expected.to eq(true) }
end
end
end end
describe '#issue_types' do describe '#issue_types' do
......
...@@ -83,6 +83,8 @@ FactoryBot.define do ...@@ -83,6 +83,8 @@ FactoryBot.define do
jira_issue_transition_id { '56-1' } jira_issue_transition_id { '56-1' }
issues_enabled { false } issues_enabled { false }
project_key { nil } project_key { nil }
vulnerabilities_enabled { false }
vulnerabilities_issuetype { nil }
end end
before(:create) do |service, evaluator| before(:create) do |service, evaluator|
...@@ -90,7 +92,8 @@ FactoryBot.define do ...@@ -90,7 +92,8 @@ FactoryBot.define do
create(:jira_tracker_data, service: service, create(:jira_tracker_data, service: service,
url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id, url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id,
username: evaluator.username, password: evaluator.password, issues_enabled: evaluator.issues_enabled, username: evaluator.username, password: evaluator.password, issues_enabled: evaluator.issues_enabled,
project_key: evaluator.project_key project_key: evaluator.project_key, vulnerabilities_enabled: evaluator.vulnerabilities_enabled,
vulnerabilities_issuetype: evaluator.vulnerabilities_issuetype
) )
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