Commit 61ce6a77 authored by Kerri Miller's avatar Kerri Miller

Merge branch '299215-add-on-demand-pipeline-configuration-service' into 'master'

Add On Demand DAST Scan Pipeline Configuration Service

See merge request gitlab-org/gitlab!54418
parents 356428c1 9c8315e2
# frozen_string_literal: true
module Security
module SecurityOrchestrationPolicies
class OnDemandScanPipelineConfigurationService
include Gitlab::Utils::StrongMemoize
def initialize(project)
@project = project
end
def execute(actions)
actions
.map.with_index { |action, index| prepare_policy_configuration(action, index) }
.reduce({}, :merge)
end
private
DAST_ON_DEMAND_TEMPLATE_NAME = 'DAST-On-Demand-Scan'
attr_reader :project
def prepare_policy_configuration(action, index)
{
"dast-on-demand-#{index}" => prepare_on_demand_scan_configuration(action)
}.deep_symbolize_keys
end
def prepare_on_demand_scan_configuration(action)
result = prepare_on_demand_scan_params(action[:site_profile], action[:scanner_profile])
return error_script(result.message) unless result.success?
ci_configuration = YAML.safe_load(::Ci::DastScanCiConfigurationService.execute(result.payload))
dast_on_demand_template[:dast].deep_merge(
'variables' => dast_on_demand_template[:variables].deep_merge(ci_configuration['variables']),
'stage' => 'test'
)
end
def prepare_on_demand_scan_params(site_profile_name, scanner_profile_name)
site_profile = DastSiteProfilesFinder.new(project_id: project.id, name: site_profile_name).execute.first
scanner_profile = DastScannerProfilesFinder.new(project_ids: [project.id], name: scanner_profile_name).execute.first if scanner_profile_name.present?
DastOnDemandScans::ParamsCreateService
.new(container: project, params: { dast_site_profile: site_profile, dast_scanner_profile: scanner_profile })
.execute
end
def dast_on_demand_template
strong_memoize(:dast_on_demand_template) do
template = ::TemplateFinder.build(:gitlab_ci_ymls, nil, name: DAST_ON_DEMAND_TEMPLATE_NAME).execute
Gitlab::Config::Loader::Yaml.new(template.content).load!
end
end
def error_script(error_message)
{
'script' => "echo \"Error during On-Demand Scan execution: #{error_message}\" && false",
'allow_failure' => true
}
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Security::SecurityOrchestrationPolicies::OnDemandScanPipelineConfigurationService do
describe '#execute' do
let_it_be_with_reload(:project) { create(:project, :repository) }
let_it_be(:site_profile) { create(:dast_site_profile, project: project) }
let_it_be(:scanner_profile) { create(:dast_scanner_profile, project: project) }
let(:service) { described_class.new(project) }
let(:actions) do
[
{
scan: 'dast',
site_profile: site_profile.name,
scanner_profile: scanner_profile.name
},
{
scan: 'dast',
site_profile: 'Site Profile B'
}
]
end
subject(:pipeline_configuration) { service.execute(actions) }
before do
allow(DastSiteProfilesFinder).to receive(:new).and_return(double(execute: []))
allow(DastSiteProfilesFinder).to receive(:new).with(project_id: project.id, name: site_profile.name).and_return(double(execute: [site_profile]))
allow(DastScannerProfilesFinder).to receive(:new).and_return(double(execute: []))
allow(DastScannerProfilesFinder).to receive(:new).with(project_ids: [project.id], name: scanner_profile.name).and_return(double(execute: [scanner_profile]))
end
it 'uses DastSiteProfilesFinder and DastScannerProfilesFinder to find DAST profiles within the project' do
expect(DastSiteProfilesFinder).to receive(:new).with(project_id: project.id, name: site_profile.name)
expect(DastSiteProfilesFinder).to receive(:new).with(project_id: project.id, name: 'Site Profile B')
expect(DastScannerProfilesFinder).to receive(:new).with(project_ids: [project.id], name: scanner_profile.name)
pipeline_configuration
end
it 'delegates params creation to DastOnDemandScans::ParamsCreateService' do
expect(DastOnDemandScans::ParamsCreateService).to receive(:new).with(container: project, params: { dast_site_profile: site_profile, dast_scanner_profile: scanner_profile }).and_call_original
expect(DastOnDemandScans::ParamsCreateService).to receive(:new).with(container: project, params: { dast_site_profile: nil, dast_scanner_profile: nil }).and_call_original
pipeline_configuration
end
it 'delegates variables preparation to ::Ci::DastScanCiConfigurationService' do
expected_params = {
branch: project.default_branch_or_master,
full_scan_enabled: false,
show_debug_messages: false,
spider_timeout: nil,
target_timeout: nil,
target_url: site_profile.dast_site.url,
use_ajax_spider: false
}
expect(::Ci::DastScanCiConfigurationService).to receive(:execute).with(expected_params).and_call_original
pipeline_configuration
end
it 'fetches template content using ::TemplateFinder' do
expect(::TemplateFinder).to receive(:build).with(:gitlab_ci_ymls, nil, name: 'DAST-On-Demand-Scan').and_call_original
pipeline_configuration
end
it 'returns prepared CI configuration with DAST On-Demand scans defined' do
expected_configuration = {
'dast-on-demand-0': {
stage: 'test',
image: { name: '$SECURE_ANALYZERS_PREFIX/dast:$DAST_VERSION' },
variables: {
DAST_VERSION: 1,
SECURE_ANALYZERS_PREFIX: 'registry.gitlab.com/gitlab-org/security-products/analyzers',
DAST_WEBSITE: site_profile.dast_site.url,
DAST_FULL_SCAN_ENABLED: 'false',
DAST_USE_AJAX_SPIDER: 'false',
DAST_DEBUG: 'false'
},
allow_failure: true,
script: ['/analyze'],
artifacts: { reports: { dast: 'gl-dast-report.json' } }
},
'dast-on-demand-1': {
script: 'echo "Error during On-Demand Scan execution: Site Profile was not provided" && false',
allow_failure: true
}
}
expect(pipeline_configuration).to eq(expected_configuration)
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