Commit 83912362 authored by Peter Leitzen's avatar Peter Leitzen

Merge branch 'rf-update-sast-mutation' into 'master'

Update in preparation of supporting analyzers

See merge request gitlab-org/gitlab!42173
parents ccfc0e69 36e637fc
...@@ -27,8 +27,7 @@ module Mutations ...@@ -27,8 +27,7 @@ module Mutations
def resolve(project_path:, configuration:) def resolve(project_path:, configuration:)
project = authorized_find!(full_path: project_path) project = authorized_find!(full_path: project_path)
sast_create_service_params = format_for_service(configuration) result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, configuration).execute
result = ::Security::CiConfiguration::SastCreateService.new(project, current_user, sast_create_service_params).execute
prepare_response(result) prepare_response(result)
end end
...@@ -38,15 +37,6 @@ module Mutations ...@@ -38,15 +37,6 @@ module Mutations
resolve_project(full_path: full_path) resolve_project(full_path: full_path)
end end
# Temporary formatting necessary for supporting REST API
# Will be removed during the implementation of
# https://gitlab.com/gitlab-org/gitlab/-/issues/246737
def format_for_service(configuration)
global_values = configuration["global"]&.collect {|k| [k["field"], k["value"]]}.to_h
pipeline_values = configuration["pipeline"]&.collect {|k| [k["field"], k["value"]]}.to_h
global_values.merge!(pipeline_values)
end
def prepare_response(result) def prepare_response(result)
{ {
status: result[:status], status: result[:status],
......
...@@ -25,7 +25,7 @@ module Security ...@@ -25,7 +25,7 @@ module Security
private private
def attributes def attributes
actions = Security::CiConfiguration::SastBuildActions.new(@project.auto_devops_enabled?, @params, existing_gitlab_ci_content, default_sast_values).generate actions = Security::CiConfiguration::SastBuildActions.new(@project.auto_devops_enabled?, @params, existing_gitlab_ci_content).generate
@project.repository.add_branch(@current_user, @branch_name, @project.default_branch) @project.repository.add_branch(@current_user, @branch_name, @project.default_branch)
message = _('Set .gitlab-ci.yml to enable or configure SAST') message = _('Set .gitlab-ci.yml to enable or configure SAST')
...@@ -43,14 +43,6 @@ module Security ...@@ -43,14 +43,6 @@ module Security
YAML.safe_load(gitlab_ci_yml) if gitlab_ci_yml YAML.safe_load(gitlab_ci_yml) if gitlab_ci_yml
end end
def default_sast_values
result = Security::CiConfiguration::SastParserService.new(@project)
global_defaults = result.configuration["global"].collect { |k| [k["field"], k["default_value"]] }.to_h
pipeline_defaults = result.configuration["pipeline"].collect { |k| [k["field"], k["default_value"]] }.to_h
global_defaults.merge!(pipeline_defaults)
end
def successful_change_path def successful_change_path
description = _('Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings.') description = _('Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings.')
merge_request_params = { source_branch: @branch_name, description: description } merge_request_params = { source_branch: @branch_name, description: description }
......
---
title: Update in preparation of supporting analyzers
merge_request: 42173
author:
type: changed
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
module Security module Security
module CiConfiguration module CiConfiguration
class SastBuildActions class SastBuildActions
def initialize(auto_devops_enabled, params, existing_gitlab_ci_content, default_sast_values) def initialize(auto_devops_enabled, params, existing_gitlab_ci_content)
@auto_devops_enabled = auto_devops_enabled @auto_devops_enabled = auto_devops_enabled
@params = params @variables = variables(params)
@existing_gitlab_ci_content = existing_gitlab_ci_content || {} @existing_gitlab_ci_content = existing_gitlab_ci_content || {}
@default_sast_values = default_sast_values @default_sast_values = default_sast_values(params)
end end
def generate def generate
...@@ -20,6 +20,25 @@ module Security ...@@ -20,6 +20,25 @@ module Security
private private
def variables(params)
# This early return is necessary for supporting REST API.
# Will be removed during the implementation of
# https://gitlab.com/gitlab-org/gitlab/-/issues/246737
return params unless params['global'].present?
collect_values(params, 'value')
end
def default_sast_values(params)
collect_values(params, 'defaultValue')
end
def collect_values(config, key)
global_variables = config['global']&.collect {|k| [k['field'], k[key]]}.to_h
pipeline_variables = config['pipeline']&.collect {|k| [k['field'], k[key]]}.to_h
global_variables.merge!(pipeline_variables)
end
def update_existing_content! def update_existing_content!
@existing_gitlab_ci_content['stages'] = set_stages @existing_gitlab_ci_content['stages'] = set_stages
@existing_gitlab_ci_content['variables'] = set_variables(global_variables, @existing_gitlab_ci_content) @existing_gitlab_ci_content['variables'] = set_variables(global_variables, @existing_gitlab_ci_content)
...@@ -49,15 +68,15 @@ module Security ...@@ -49,15 +68,15 @@ module Security
end end
def sast_stage def sast_stage
@params['stage'].presence ? @params['stage'] : 'test' @variables['stage'].presence ? @variables['stage'] : 'test'
end end
def set_variables(variables, hash_to_update = {}) def set_variables(variables, hash_to_update = {})
hash_to_update['variables'] ||= {} hash_to_update['variables'] ||= {}
variables.each do |key| variables.each do |key|
if @params[key].present? && @params[key].to_s != @default_sast_values[key].to_s if @variables[key].present? && @variables[key].to_s != @default_sast_values[key].to_s
hash_to_update['variables'][key] = @params[key] hash_to_update['variables'][key] = @variables[key]
else else
hash_to_update['variables'].delete(key) hash_to_update['variables'].delete(key)
end end
......
...@@ -4,18 +4,31 @@ require 'fast_spec_helper' ...@@ -4,18 +4,31 @@ require 'fast_spec_helper'
RSpec.describe Security::CiConfiguration::SastBuildActions do RSpec.describe Security::CiConfiguration::SastBuildActions do
let(:default_sast_values) do let(:default_sast_values) do
{ "SECURE_ANALYZERS_PREFIX" => "registry.gitlab.com/gitlab-org/security-products/analyzers", { 'global' =>
"SAST_EXCLUDED_PATHS" => "spec, test, tests, tmp", "SAST_ANALYZER_IMAGE_TAG" => "2", [
"stage" => "test", { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'registry.gitlab.com/gitlab-org/security-products/analyzers' }
"SEARCH_MAX_DEPTH" => "4" } ],
'pipeline' =>
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'test' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 4 },
{ 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec, test, tests, tmp' }
] }
end end
let(:params) do let(:params) do
{ 'stage' => 'security', { 'global' =>
'SEARCH_MAX_DEPTH' => 1, [
'SECURE_ANALYZERS_PREFIX' => 'new_registry', { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'new_registry' }
'SAST_ANALYZER_IMAGE_TAG' => 2, ],
'SAST_EXCLUDED_PATHS' => 'spec,docs' } 'pipeline' =>
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'security' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 1 },
{ 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
] }
end end
context 'with existing .gitlab-ci.yml' do context 'with existing .gitlab-ci.yml' do
...@@ -25,7 +38,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -25,7 +38,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'template includes are array' do context 'template includes are array' do
let(:gitlab_ci_content) { existing_gitlab_ci_and_template_array_without_sast } let(:gitlab_ci_content) { existing_gitlab_ci_and_template_array_without_sast }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -36,7 +49,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -36,7 +49,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'template include is not an array' do context 'template include is not an array' do
let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_without_sast } let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_without_sast }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -48,7 +61,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -48,7 +61,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'sast template include is not an array' do context 'sast template include is not an array' do
let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage } let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -60,7 +73,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -60,7 +73,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
let(:params) { default_sast_values } let(:params) { default_sast_values }
let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage } let(:gitlab_ci_content) { existing_gitlab_ci_and_single_template_with_sast_and_default_stage }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set) expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set)
...@@ -69,15 +82,22 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -69,15 +82,22 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'with update stage and SEARCH_MAX_DEPTH and set SECURE_ANALYZERS_PREFIX to default' do context 'with update stage and SEARCH_MAX_DEPTH and set SECURE_ANALYZERS_PREFIX to default' do
let(:params) do let(:params) do
{ 'stage' => 'brand_new_stage', { 'global' =>
'SEARCH_MAX_DEPTH' => 5, [
'SECURE_ANALYZERS_PREFIX' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', { 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => 'registry.gitlab.com/gitlab-org/security-products/analyzers' }
'SAST_EXCLUDED_PATHS' => 'spec,docs' } ],
'pipeline' =>
[
{ 'field' => 'stage', 'defaultValue' => 'test', 'value' => 'brand_new_stage' },
{ 'field' => 'SEARCH_MAX_DEPTH', 'defaultValue' => 4, 'value' => 5 },
{ 'field' => 'SAST_ANALYZER_IMAGE_TAG', 'defaultValue' => 2, 'value' => 2 },
{ 'field' => 'SAST_EXCLUDED_PATHS', 'defaultValue' => 'spec, test, tests, tmp', 'value' => 'spec,docs' }
] }
end end
let(:gitlab_ci_content) { existing_gitlab_ci } let(:gitlab_ci_content) { existing_gitlab_ci }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -88,7 +108,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -88,7 +108,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'with no existing variables' do context 'with no existing variables' do
let(:gitlab_ci_content) { existing_gitlab_ci_with_no_variables } let(:gitlab_ci_content) { existing_gitlab_ci_with_no_variables }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -99,7 +119,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -99,7 +119,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'with no existing sast config' do context 'with no existing sast config' do
let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_section } let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_section }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -110,7 +130,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -110,7 +130,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'with no existing sast variables' do context 'with no existing sast variables' do
let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_variables } let(:gitlab_ci_content) { existing_gitlab_ci_with_no_sast_variables }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:action]).to eq('update') expect(result.first[:action]).to eq('update')
...@@ -173,9 +193,14 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -173,9 +193,14 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
let(:auto_devops_enabled) { false } let(:auto_devops_enabled) { false }
context 'with one empty parameter' do context 'with one empty parameter' do
let(:params) { { 'SECURE_ANALYZERS_PREFIX' => '' } } let(:params) do
{ 'global' =>
[
{ 'field' => 'SECURE_ANALYZERS_PREFIX', 'defaultValue' => 'registry.gitlab.com/gitlab-org/security-products/analyzers', 'value' => '' }
] }
end
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set) expect(result.first[:content]).to eq(sast_yaml_with_no_variables_set)
...@@ -183,7 +208,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -183,7 +208,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
end end
context 'with all parameters' do context 'with all parameters' do
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
it 'generates the correct YML' do it 'generates the correct YML' do
expect(result.first[:content]).to eq(sast_yaml_all_params) expect(result.first[:content]).to eq(sast_yaml_all_params)
...@@ -194,7 +219,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do ...@@ -194,7 +219,7 @@ RSpec.describe Security::CiConfiguration::SastBuildActions do
context 'with autodevops enabled' do context 'with autodevops enabled' do
let(:auto_devops_enabled) { true } let(:auto_devops_enabled) { true }
subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content, default_sast_values).generate } subject(:result) { described_class.new(auto_devops_enabled, params, gitlab_ci_content).generate }
before do before do
allow_any_instance_of(described_class).to receive(:auto_devops_stages).and_return(fast_auto_devops_stages) allow_any_instance_of(described_class).to receive(:auto_devops_stages).and_return(fast_auto_devops_stages)
......
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