Commit fd1af13b authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Robert Speicher

Add support for SAST in security policies

parent 0255ba46
......@@ -13602,7 +13602,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectscanexecutionpoliciesactionscantypes"></a>`actionScanTypes` | [`[SecurityReportTypeEnum!]`](#securityreporttypeenum) | Filters policies by the action scan type. Only these scan types are supported: `dast`, `secret_detection`, `cluster_image_scanning`, `container_scanning`. |
| <a id="projectscanexecutionpoliciesactionscantypes"></a>`actionScanTypes` | [`[SecurityReportTypeEnum!]`](#securityreporttypeenum) | Filters policies by the action scan type. Only these scan types are supported: `dast`, `secret_detection`, `cluster_image_scanning`, `container_scanning`, `sast`. |
##### `Project.sentryDetailedError`
......@@ -307,7 +307,7 @@ rule in the defined policy are met.
| Field | Type | Possible values | Description |
|-------|------|-----------------|-------------|
| `scan` | `string` | `dast`, `secret_detection` | The action's type. |
| `scan` | `string` | `dast`, `secret_detection`, `sast` | The action's type. |
| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/index.md#site-profile). | The DAST site profile to execute the DAST scan. This field should only be set if `scan` type is `dast`. |
| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/index.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. This field should only be set if `scan` type is `dast`.|
......@@ -330,6 +330,7 @@ Note the following:
- A container scanning and cluster image scanning scans configured for the `pipeline` rule type will ignore the cluster defined in the `clusters` object.
They will use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type.
Cluster with name provided in `clusters` object must be created and configured for the project. To be able to successfully perform the `container_scanning`/`cluster_image_scanning` scans for the cluster you must follow instructions for the [Cluster Image Scanning feature](../cluster_image_scanning/index.md#prerequisites).
- The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/parent_child_pipelines.md).
### Example security policies project
......
......@@ -11,7 +11,7 @@ module Security
schedule: 'schedule'
}.freeze
SCAN_TYPES = %w[dast secret_detection cluster_image_scanning container_scanning].freeze
SCAN_TYPES = %w[dast secret_detection cluster_image_scanning container_scanning sast].freeze
ON_DEMAND_SCANS = %w[dast].freeze
included do
......
......@@ -6,7 +6,8 @@ module Security
SCAN_TEMPLATES = {
'secret_detection' => 'Jobs/Secret-Detection',
'cluster_image_scanning' => 'Security/Cluster-Image-Scanning',
'container_scanning' => 'Security/Container-Scanning'
'container_scanning' => 'Security/Container-Scanning',
'sast' => 'Security/SAST'
}.freeze
def execute(action, ci_variables)
......@@ -15,6 +16,8 @@ module Security
secret_detection_configuration(ci_variables)
when 'container_scanning', 'cluster_image_scanning'
scan_configuration(action[:scan], ci_variables)
when 'sast'
child_pipeline_configuration(action[:scan])
else
error_script('Invalid Scan type')
end
......@@ -44,6 +47,17 @@ module Security
.except(:rules)
end
def child_pipeline_configuration(template)
{
inherit: {
variables: false
},
trigger: {
include: [{ template: "#{SCAN_TEMPLATES[template.to_s]}.gitlab-ci.yml" }]
}
}
end
def error_script(error_message)
{
'script' => "echo \"Error during Scan execution: #{error_message}\" && false",
......
......@@ -25,6 +25,7 @@ module Security
when 'container_scanning' then schedule_container_scanning_scan(action, schedule, branches)
when 'cluster_image_scanning' then schedule_cluster_image_scanning_scan(action, schedule)
when 'dast' then schedule_dast_on_demand_scan(action, branches)
when 'sast' then schedule_scan(action, branches)
end
end
......
......@@ -119,7 +119,8 @@
"dast",
"secret_detection",
"container_scanning",
"cluster_image_scanning"
"cluster_image_scanning",
"sast"
],
"type": "string"
},
......@@ -184,6 +185,18 @@
"then": {
"maxProperties": 1
}
},
{
"if": {
"properties": {
"scan": {
"const": "sast"
}
}
},
"then": {
"maxProperties": 1
}
}
],
"additionalProperties": false
......
......@@ -112,6 +112,20 @@ RSpec.describe Security::SecurityOrchestrationPolicies::CiConfigurationService d
expect(subject.deep_symbolize_keys).to eq(expected_configuration)
end
end
context 'when scan type is sast' do
let_it_be(:action) { { scan: 'sast' } }
let_it_be(:ci_variables) { {} }
it 'returns prepared CI configuration for SAST' do
expected_configuration = {
inherit: { variables: false },
trigger: { include: [{ template: 'Security/SAST.gitlab-ci.yml' }] }
}
expect(subject.deep_symbolize_keys).to eq(expected_configuration)
end
end
end
context 'when action is invalid' do
......
......@@ -125,6 +125,16 @@ RSpec.describe Security::SecurityOrchestrationPolicies::CreatePipelineService do
expect(build.name).to eq('container_scanning')
end
end
context 'for sast scan' do
let(:action) { { scan: 'sast' } }
it 'sets the build name to sast' do
build = pipeline.bridges.first
expect(build.name).to eq('sast')
end
end
end
end
end
......
......@@ -124,6 +124,32 @@ RSpec.describe Security::SecurityOrchestrationPolicies::RuleScheduleService do
end
end
context 'when scan type is sast' do
before do
policy[:actions] = [{ scan: 'sast' }]
end
it 'invokes Security::SecurityOrchestrationPolicies::CreatePipelineService for both branches' do
expect(::Security::SecurityOrchestrationPolicies::CreatePipelineService).to(
receive(:new)
.with(project: project, current_user: current_user, params: { action: policy[:actions].first, branch: 'master' })
.and_call_original)
expect(::Security::SecurityOrchestrationPolicies::CreatePipelineService).to(
receive(:new)
.with(project: project, current_user: current_user, params: { action: policy[:actions].first, branch: 'production' })
.and_call_original)
service.execute(schedule)
end
it 'invokes Security::SecurityOrchestrationPolicies::CreatePipelineService' do
expect(::Security::SecurityOrchestrationPolicies::CreatePipelineService).to receive(:new).twice.and_call_original
service.execute(schedule)
end
end
context 'when policy actions exists and there are multiple matching branches' do
it 'creates multiple scan pipelines and updates next_run_at' do
expect { service.execute(schedule) }.to change(Ci::Pipeline, :count).by(2)
......
......@@ -38,11 +38,12 @@ RSpec.describe Security::SecurityOrchestrationPolicies::ScanPipelineService do
{ scan: 'secret_detection' },
{ scan: 'dast', scanner_profile: 'Scanner Profile', site_profile: 'Site Profile' },
{ scan: 'cluster_image_scanning' },
{ scan: 'container_scanning' }
{ scan: 'container_scanning' },
{ scan: 'sast' }
]
end
it_behaves_like 'creates scan jobs', 4, [:'secret-detection-0', :'dast-1', :'cluster-image-scanning-2', :'container-scanning-3']
it_behaves_like 'creates scan jobs', 5, [:'secret-detection-0', :'dast-1', :'cluster-image-scanning-2', :'container-scanning-3', :'sast-4']
end
context 'when there are valid and invalid actions' do
......
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