Commit 8f13ed95 authored by Marcos Rocha's avatar Marcos Rocha Committed by Lin Jen-Shin

Update DAST On-demand scan template

The DAST On-demand scan template should be updated to use the API Security scanner

Changelog: changed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73564
EE: true
parent 4ee3f688
---
name: dast_api_scanner
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73564
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345837
milestone: '14.7'
type: development
group: group::dynamic analysis
default_enabled: false
...@@ -44,13 +44,25 @@ module AppSec ...@@ -44,13 +44,25 @@ module AppSec
def ci_configuration def ci_configuration
{ {
'stages' => [STAGE_NAME], 'stages' => [STAGE_NAME],
'include' => [{ 'template' => 'Security/DAST-On-Demand-Scan.gitlab-ci.yml' }], 'include' => [{ 'template' => dast_template }],
'dast' => { 'dast' => {
'dast_configuration' => { 'site_profile' => dast_site_profile.name, 'scanner_profile' => dast_scanner_profile&.name }.compact 'dast_configuration' => { 'site_profile' => dast_site_profile.name, 'scanner_profile' => dast_scanner_profile&.name }.compact
} }
}.to_yaml }.to_yaml
end end
def dast_template
if should_use_api_scan?
'Security/DAST-On-Demand-API-Scan.gitlab-ci.yml'
else
'Security/DAST-On-Demand-Scan.gitlab-ci.yml'
end
end
def should_use_api_scan?
Feature.enabled?(:dast_api_scanner, dast_site_profile.project, default_enabled: :yaml) && dast_site_profile.target_type == 'api'
end
def dast_profile def dast_profile
strong_memoize(:dast_profile) do strong_memoize(:dast_profile) do
params[:dast_profile] params[:dast_profile]
......
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_security_dast_on_demand_api_scan_monthly
name: "dast_on_demand_api_scan"
description: Count of pipelines using the latest DAST API template
product_section: sec
product_stage: secure
product_group: "group::dynamic analysis"
product_category: DAST
value_type: number
status: active
milestone: "14.7"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73564
time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- p_ci_templates_security_dast_on_demand_api_scan
performance_indicator_type: []
distribution:
- ee
tier:
#- premium
- ultimate
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_dast_on_demand_api_scan_monthly
name: "implicit_security_dast_on_demand_api_scan"
description: Count of pipelines with implicit runs using the latest DAST API template
product_section: sec
product_stage: secure
product_group: "group::dynamic analysis"
product_category: DAST
value_type: number
status: active
milestone: "14.7"
introduced_by_url:
time_frame: 28d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- p_ci_templates_implicit_security_dast_on_demand_api_scan
performance_indicator_type: []
distribution:
- ee
tier:
#- premium
- ultimate
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_security_dast_on_demand_api_scan_weekly
name: "dast_on_demand_api_scan"
description: Count of pipelines using the latest DAST API template
product_section: sec
product_stage: secure
product_group: "group::dynamic analysis"
product_category: DAST
value_type: number
status: active
milestone: "14.7"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73564
time_frame: 7d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- p_ci_templates_security_dast_on_demand_api_scan
performance_indicator_type: []
distribution:
- ee
tier:
#- premium
- ultimate
---
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_dast_on_demand_api_scan_weekly
name: "implicit_security_dast_on_demand_api_scan"
description: Count of pipelines with implicit runs using the latest DAST API template
product_section: sec
product_stage: secure
product_group: "group::dynamic analysis"
product_category: DAST
value_type: number
status: active
milestone: "14.7"
introduced_by_url:
time_frame: 7d
data_source: redis_hll
data_category: optional
instrumentation_class: RedisHLLMetric
options:
events:
- p_ci_templates_implicit_security_dast_on_demand_api_scan
performance_indicator_type: []
distribution:
- ee
tier:
#- premium
- ultimate
...@@ -4,7 +4,7 @@ require 'spec_helper' ...@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe AppSec::Dast::ScanConfigs::BuildService do RSpec.describe AppSec::Dast::ScanConfigs::BuildService do
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:dast_site_profile) { create(:dast_site_profile, project: project) } let_it_be_with_reload(:dast_site_profile) { create(:dast_site_profile, project: project, target_type: 'website') }
let_it_be(:dast_scanner_profile) { create(:dast_scanner_profile, project: project, spider_timeout: 5, target_timeout: 20) } let_it_be(:dast_scanner_profile) { create(:dast_scanner_profile, project: project, spider_timeout: 5, target_timeout: 20) }
let_it_be(:dast_profile) { create(:dast_profile, project: project, dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile, branch_name: 'master') } let_it_be(:dast_profile) { create(:dast_profile, project: project, dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile, branch_name: 'master') }
...@@ -19,45 +19,35 @@ RSpec.describe AppSec::Dast::ScanConfigs::BuildService do ...@@ -19,45 +19,35 @@ RSpec.describe AppSec::Dast::ScanConfigs::BuildService do
let(:dast_full_scan_enabled) { dast_scanner_profile.full_scan_enabled? } let(:dast_full_scan_enabled) { dast_scanner_profile.full_scan_enabled? }
let(:dast_use_ajax_spider) { dast_scanner_profile.use_ajax_spider? } let(:dast_use_ajax_spider) { dast_scanner_profile.use_ajax_spider? }
let(:dast_debug) { dast_scanner_profile.show_debug_messages? } let(:dast_debug) { dast_scanner_profile.show_debug_messages? }
let(:on_demand_scan_template) { 'Security/DAST-On-Demand-Scan.gitlab-ci.yml' }
let(:api_scan_template) { 'Security/DAST-On-Demand-API-Scan.gitlab-ci.yml' }
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile } } let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile } }
let(:expected_yaml_configuration) do let(:expected_yaml_configuration) do
<<~YAML <<~YAML
--- ---
stages: stages:
- dast - dast
include: include:
- template: Security/DAST-On-Demand-Scan.gitlab-ci.yml - template: #{template}
dast: dast:
dast_configuration: dast_configuration:
site_profile: #{dast_site_profile.name} site_profile: #{dast_site_profile.name}
scanner_profile: #{dast_scanner_profile.name} scanner_profile: #{dast_scanner_profile.name}
YAML YAML
end end
subject { described_class.new(container: project, params: params).execute } subject { described_class.new(container: project, params: params).execute }
describe 'execute' do describe 'execute' do
context 'when a dast_profile is provided' do shared_examples 'build service execute tests' do
let(:params) { { dast_profile: dast_profile } } context 'when a dast_profile is provided' do
let(:params) { { dast_profile: dast_profile } }
it 'returns a dast_profile, branch and YAML configuration' do it 'returns a dast_profile, branch and YAML configuration' do
expected_payload = {
dast_profile: dast_profile,
branch: dast_profile.branch_name,
ci_configuration: expected_yaml_configuration
}
expect(subject.payload).to eq(expected_payload)
end
end
context 'when a dast_site_profile is provided' do
shared_examples 'a payload without a dast_profile' do
it 'returns a branch and YAML configuration' do
expected_payload = { expected_payload = {
dast_profile: nil, dast_profile: dast_profile,
branch: dast_profile.branch_name, branch: dast_profile.branch_name,
ci_configuration: expected_yaml_configuration ci_configuration: expected_yaml_configuration
} }
...@@ -66,57 +56,99 @@ RSpec.describe AppSec::Dast::ScanConfigs::BuildService do ...@@ -66,57 +56,99 @@ RSpec.describe AppSec::Dast::ScanConfigs::BuildService do
end end
end end
context 'when a dast_scanner_profile is provided' do context 'when a dast_site_profile is provided' do
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile } } shared_examples 'a payload without a dast_profile' do
it 'returns a branch and YAML configuration' do
expected_payload = {
dast_profile: nil,
branch: dast_profile.branch_name,
ci_configuration: expected_yaml_configuration
}
it_behaves_like 'a payload without a dast_profile' expect(subject.payload).to eq(expected_payload)
end
end
context 'when the target is not validated and an active scan is requested' do context 'when a dast_scanner_profile is provided' do
let_it_be(:active_dast_scanner_profile) { create(:dast_scanner_profile, project: project, scan_type: 'active') } let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile } }
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: active_dast_scanner_profile } } it_behaves_like 'a payload without a dast_profile'
context 'when the target is not validated and an active scan is requested' do
let_it_be(:active_dast_scanner_profile) { create(:dast_scanner_profile, project: project, scan_type: 'active') }
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: active_dast_scanner_profile } }
it 'responds with an error message', :aggregate_failures do
expect(subject).not_to be_success
expect(subject.message).to eq('Cannot run active scan against unvalidated target')
end
end
end
it 'responds with an error message', :aggregate_failures do context 'when a dast_scanner_profile is not provided' do
expect(subject).not_to be_success let(:params) { { dast_site_profile: dast_site_profile } }
expect(subject.message).to eq('Cannot run active scan against unvalidated target')
let(:expected_yaml_configuration) do
<<~YAML
---
stages:
- dast
include:
- template: #{template}
dast:
dast_configuration:
site_profile: #{dast_site_profile.name}
YAML
end end
it_behaves_like 'a payload without a dast_profile'
end end
end end
context 'when a dast_scanner_profile is not provided' do context 'when a dast_site_profile is not provided' do
let(:params) { { dast_site_profile: dast_site_profile } } let(:params) { { dast_site_profile: nil, dast_scanner_profile: dast_scanner_profile } }
let(:expected_yaml_configuration) do it 'responds with an error message', :aggregate_failures do
<<~YAML expect(subject).not_to be_success
--- expect(subject.message).to eq('Dast site profile was not provided')
stages:
- dast
include:
- template: Security/DAST-On-Demand-Scan.gitlab-ci.yml
dast:
dast_configuration:
site_profile: #{dast_site_profile.name}
YAML
end end
end
it_behaves_like 'a payload without a dast_profile' context 'when a branch is provided' do
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile, branch: 'hello-world' } }
it 'returns the branch in the payload' do
expect(subject.payload[:branch]).to match('hello-world')
end
end end
end end
context 'when a dast_site_profile is not provided' do context 'when feature flag dast_api_scanner is disabled' do
let(:params) { { dast_site_profile: nil, dast_scanner_profile: dast_scanner_profile } } let(:template) { on_demand_scan_template }
it 'responds with an error message', :aggregate_failures do before do
expect(subject).not_to be_success stub_feature_flags(dast_api_scanner: false)
expect(subject.message).to eq('Dast site profile was not provided')
end end
it_behaves_like 'build service execute tests'
end end
context 'when a branch is provided' do context 'when feature flag dast_api_scanner is enabled' do
let(:params) { { dast_site_profile: dast_site_profile, dast_scanner_profile: dast_scanner_profile, branch: 'hello-world' } } context 'when the target_type is api' do
before do
dast_site_profile.target_type = 'api'
end
let(:template) { api_scan_template }
it_behaves_like 'build service execute tests'
end
context 'when the target_type is NOT api' do
let(:template) { on_demand_scan_template }
it 'returns the branch in the payload' do it_behaves_like 'build service execute tests'
expect(subject.payload[:branch]).to match('hello-world')
end end
end end
end end
......
stages:
- build
- test
- deploy
- dast
variables:
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
DAST_API_VERSION: "1"
DAST_API_IMAGE: $SECURE_ANALYZERS_PREFIX/api-fuzzing:$DAST_API_VERSION
dast:
stage: dast
image: $DAST_API_IMAGE
variables:
GIT_STRATEGY: none
allow_failure: true
script:
- /peach/analyzer-dast-api
artifacts:
when: always
paths:
- gl-assets
- gl-dast-api-report.json
- gl-*.log
reports:
dast: gl-dast-api-report.json
...@@ -103,6 +103,10 @@ ...@@ -103,6 +103,10 @@
category: ci_templates category: ci_templates
redis_slot: ci_templates redis_slot: ci_templates
aggregation: weekly aggregation: weekly
- name: p_ci_templates_security_dast_on_demand_api_scan
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_security_coverage_fuzzing - name: p_ci_templates_security_coverage_fuzzing
category: ci_templates category: ci_templates
redis_slot: ci_templates redis_slot: ci_templates
...@@ -539,6 +543,10 @@ ...@@ -539,6 +543,10 @@
category: ci_templates category: ci_templates
redis_slot: ci_templates redis_slot: ci_templates
aggregation: weekly aggregation: weekly
- name: p_ci_templates_implicit_security_dast_on_demand_api_scan
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
- name: p_ci_templates_implicit_security_coverage_fuzzing - name: p_ci_templates_implicit_security_coverage_fuzzing
category: ci_templates category: ci_templates
redis_slot: ci_templates redis_slot: ci_templates
......
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