Commit 8165db74 authored by Markus Koller's avatar Markus Koller

Merge branch 'limit-policy-to-file' into 'master'

Limit security policy to a file

See merge request gitlab-org/gitlab!57736
parents a1519664 b7e3049d
...@@ -6,7 +6,8 @@ module Security ...@@ -6,7 +6,8 @@ module Security
self.table_name = 'security_orchestration_policy_configurations' self.table_name = 'security_orchestration_policy_configurations'
POLICIES_BASE_PATH = '.gitlab/security-policies/' POLICY_PATH = '.gitlab/security-policies/policy.yml'
POLICY_LIMIT = 5
ON_DEMAND_SCANS = %w[dast].freeze ON_DEMAND_SCANS = %w[dast].freeze
...@@ -23,12 +24,7 @@ module Security ...@@ -23,12 +24,7 @@ module Security
def active_policies def active_policies
return [] unless enabled? return [] unless enabled?
security_policy_management_project scan_execution_policy_at(POLICY_PATH).select { |config| config[:enabled] }.first(POLICY_LIMIT)
.repository
.ls_files(security_policy_management_project.default_branch_or_master)
.grep(/\A#{Regexp.escape(POLICIES_BASE_PATH)}.+\.(yml|yaml)\z/)
.map { |path| policy_at(path) }
.select { |config| config[:enabled] }
end end
def on_demand_scan_actions(branch) def on_demand_scan_actions(branch)
...@@ -48,6 +44,14 @@ module Security ...@@ -48,6 +44,14 @@ module Security
private private
def policy_repo
security_policy_management_project.repository
end
def default_branch_or_master
security_policy_management_project.default_branch_or_master
end
def active_policy_names_with_dast_profiles def active_policy_names_with_dast_profiles
strong_memoize(:active_policy_names_with_dast_profiles) do strong_memoize(:active_policy_names_with_dast_profiles) do
profiles = { site_profiles: Hash.new { Set.new }, scanner_profiles: Hash.new { Set.new } } profiles = { site_profiles: Hash.new { Set.new }, scanner_profiles: Hash.new { Set.new } }
...@@ -65,11 +69,9 @@ module Security ...@@ -65,11 +69,9 @@ module Security
end end
end end
def policy_at(path) def scan_execution_policy_at(path)
security_policy_management_project policy_repo.blob_data_at(default_branch_or_master, path)
.repository .then { |config| Gitlab::Config::Loader::Yaml.new(config).load!.fetch(:scan_execution_policy, []) }
.blob_data_at(security_policy_management_project.default_branch_or_master, path)
.then { |config| Gitlab::Config::Loader::Yaml.new(config).load! }
end end
def applicable_for_branch?(policy, ref) def applicable_for_branch?(policy, ref)
......
scan_execution_policy:
- name: Run DAST in every pipeline
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "production"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
- name: Run DAST in every pipeline_v1
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "master"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
- name: Disabled policy
description: This policy is disabled
enabled: false
rules: []
actions: []
- name: Disabled policy_v2
description: This policy is disabled v2
enabled: false
rules: []
actions: []
- name: Run DAST in every pipeline_v3
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "master"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
- name: Run DAST in every pipeline_v4
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "master"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
- name: Run DAST in every pipeline_v5
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "master"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
- name: Run DAST in every pipeline_v6
description: This policy enforces to run DAST for every pipeline within the project
enabled: true
rules:
- type: pipeline
branches:
- "master"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
\ No newline at end of file
...@@ -4,7 +4,9 @@ require 'spec_helper' ...@@ -4,7 +4,9 @@ require 'spec_helper'
RSpec.describe Security::OrchestrationPolicyConfiguration do RSpec.describe Security::OrchestrationPolicyConfiguration do
let_it_be(:security_policy_management_project) { create(:project, :repository) } let_it_be(:security_policy_management_project) { create(:project, :repository) }
let_it_be(:security_orchestration_policy_configuration) { create(:security_orchestration_policy_configuration, security_policy_management_project: security_policy_management_project) } let_it_be(:security_orchestration_policy_configuration) do
create( :security_orchestration_policy_configuration, security_policy_management_project: security_policy_management_project)
end
let(:default_branch) { security_policy_management_project.default_branch_or_master } let(:default_branch) { security_policy_management_project.default_branch_or_master }
let(:repository) { instance_double(Repository, root_ref: 'master') } let(:repository) { instance_double(Repository, root_ref: 'master') }
...@@ -57,26 +59,54 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do ...@@ -57,26 +59,54 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
EOS EOS
end end
let(:disabled_policy_yaml) do let(:policy_yaml) { fixture_file('security_orchestration.yml', dir: 'ee') }
<<-EOS
type: scan_execution_policy
name: Disabled policy
description: This policy is disabled
enabled: false
rules: []
actions: []
EOS
end
let(:expected_active_policies) do let(:expected_active_policies) do
[ [
{ {
type: 'scan_execution_policy',
name: 'Run DAST in every pipeline', name: 'Run DAST in every pipeline',
description: 'This policy enforces to run DAST for every pipeline within the project', description: 'This policy enforces to run DAST for every pipeline within the project',
enabled: true, enabled: true,
rules: [{ type: 'pipeline', branches: ['production'] }], rules: [{ type: 'pipeline', branches: %w[production] }],
actions: [{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }] actions: [
{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }
]
},
{
name: 'Run DAST in every pipeline_v1',
description: 'This policy enforces to run DAST for every pipeline within the project',
enabled: true,
rules: [{ type: 'pipeline', branches: %w[master] }],
actions: [
{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }
]
},
{
name: 'Run DAST in every pipeline_v3',
description: 'This policy enforces to run DAST for every pipeline within the project',
enabled: true,
rules: [{ type: 'pipeline', branches: %w[master] }],
actions: [
{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }
]
},
{
name: 'Run DAST in every pipeline_v4',
description: 'This policy enforces to run DAST for every pipeline within the project',
enabled: true,
rules: [{ type: 'pipeline', branches: %w[master] }],
actions: [
{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }
]
},
{
name: 'Run DAST in every pipeline_v5',
description: 'This policy enforces to run DAST for every pipeline within the project',
enabled: true,
rules: [{ type: 'pipeline', branches: %w[master] }],
actions: [
{ scan: 'dast', site_profile: 'Site Profile', scanner_profile: 'Scanner Profile' }
]
} }
] ]
end end
...@@ -85,17 +115,7 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do ...@@ -85,17 +115,7 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
before do before do
allow(security_policy_management_project).to receive(:repository).and_return(repository) allow(security_policy_management_project).to receive(:repository).and_return(repository)
allow(repository).to receive(:ls_files).and_return(['README.md', '.gitlab/security-policies/enforce-dast.yml', '.gitlab/security-policies/disabled-policy.yml', '.gitlab-ci.yml']) allow(repository).to receive(:blob_data_at).with( default_branch, Security::OrchestrationPolicyConfiguration::POLICY_PATH).and_return(policy_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/enforce-dast.yml').and_return(enforce_dast_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/disabled-policy.yml').and_return(disabled_policy_yaml)
end
it 'reads yml file from repository' do
expect(repository).to receive(:ls_files).with(default_branch)
expect(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/enforce-dast.yml')
expect(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/disabled-policy.yml')
active_policies
end end
it 'returns only enabled policies' do it 'returns only enabled policies' do
...@@ -114,65 +134,47 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do ...@@ -114,65 +134,47 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
end end
describe '#on_demand_scan_actions' do describe '#on_demand_scan_actions' do
let(:policy_1_yaml) do let(:policy_yaml) do
<<-EOS
type: scan_execution_policy
name: Run DAST in every pipeline
enabled: true
rules:
- type: pipeline
branches:
- "production"
actions:
- scan: dast
site_profile: Site Profile
scanner_profile: Scanner Profile
EOS
end
let(:policy_2_yaml) do
<<-EOS <<-EOS
type: scan_execution_policy scan_execution_policy:
name: Run DAST in every pipeline - name: Run DAST in every pipeline
enabled: true enabled: true
rules: rules:
- type: pipeline - type: pipeline
branches: branches:
- "release/*" - "production"
actions: actions:
- scan: dast - scan: dast
site_profile: Site Profile 2 site_profile: Site Profile
scanner_profile: Scanner Profile 2 scanner_profile: Scanner Profile
EOS - name: Run DAST in every pipeline
end enabled: true
rules:
let(:policy_3_yaml) do - type: pipeline
<<-EOS branches:
type: scan_execution_policy - "release/*"
name: Run DAST in every pipeline actions:
enabled: true - scan: dast
rules: site_profile: Site Profile 2
- type: pipeline scanner_profile: Scanner Profile 2
branches: - name: Run DAST in every pipeline
- "*" enabled: true
actions: rules:
- scan: dast - type: pipeline
site_profile: Site Profile 3 branches:
scanner_profile: Scanner Profile 3 - "*"
EOS actions:
end - scan: dast
site_profile: Site Profile 3
let(:policy_4_yaml) do scanner_profile: Scanner Profile 3
<<-EOS - name: Run SAST in every pipeline
type: scan_execution_policy enabled: true
name: Run SAST in every pipeline rules:
enabled: true - type: pipeline
rules: branches:
- type: pipeline - "release/*"
branches: actions:
- "release/*" - scan: sast
actions:
- scan: sast
EOS EOS
end end
...@@ -183,15 +185,13 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do ...@@ -183,15 +185,13 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
] ]
end end
subject(:on_demand_scan_actions) { security_orchestration_policy_configuration.on_demand_scan_actions('release/123') } subject(:on_demand_scan_actions) do
security_orchestration_policy_configuration.on_demand_scan_actions('release/123')
end
before do before do
allow(security_policy_management_project).to receive(:repository).and_return(repository) allow(security_policy_management_project).to receive(:repository).and_return(repository)
allow(repository).to receive(:ls_files).and_return(['.gitlab/security-policies/policy-1.yml', '.gitlab/security-policies/policy-2.yml', '.gitlab/security-policies/policy-3.yml', '.gitlab/security-policies/policy-4.yml']) allow(repository).to receive(:blob_data_at).with(default_branch, Security::OrchestrationPolicyConfiguration::POLICY_PATH).and_return(policy_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/policy-1.yml').and_return(policy_1_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/policy-2.yml').and_return(policy_2_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/policy-3.yml').and_return(policy_3_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/policy-4.yml').and_return(policy_4_yaml)
end end
it 'returns only actions for on-demand scans applicable for branch' do it 'returns only actions for on-demand scans applicable for branch' do
...@@ -200,62 +200,61 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do ...@@ -200,62 +200,61 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
end end
describe '#active_policy_names_with_dast_site_profile' do describe '#active_policy_names_with_dast_site_profile' do
let(:enforce_dast_yaml) do let(:policy_yaml) do
<<-EOS <<-EOS
type: scan_execution_policy scan_execution_policy:
name: Run DAST in every pipeline - name: Run DAST in every pipeline
description: This policy enforces to run DAST for every pipeline within the project description: This policy enforces to run DAST for every pipeline within the project
enabled: true enabled: true
rules: rules:
- type: pipeline - type: pipeline
branches: branches:
- "production" - "production"
actions: actions:
- scan: dast - scan: dast
site_profile: Site Profile site_profile: Site Profile
scanner_profile: Scanner Profile scanner_profile: Scanner Profile
- scan: dast - scan: dast
site_profile: Site Profile site_profile: Site Profile
scanner_profile: Scanner Profile 2 scanner_profile: Scanner Profile 2
EOS EOS
end end
before do before do
allow(security_policy_management_project).to receive(:repository).and_return(repository) allow(security_policy_management_project).to receive(:repository).and_return(repository)
allow(repository).to receive(:ls_files).and_return(['.gitlab/security-policies/enforce-dast.yml']) allow(repository).to receive(:blob_data_at).with(default_branch, Security::OrchestrationPolicyConfiguration::POLICY_PATH).and_return(policy_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/enforce-dast.yml').and_return(enforce_dast_yaml)
end end
it 'returns list of policy names where site profile is referenced' do it 'returns list of policy names where site profile is referenced' do
expect(security_orchestration_policy_configuration.active_policy_names_with_dast_site_profile('Site Profile')).to contain_exactly('Run DAST in every pipeline') expect( security_orchestration_policy_configuration.active_policy_names_with_dast_site_profile('Site Profile')).to contain_exactly('Run DAST in every pipeline')
end end
end end
describe '#active_policy_names_with_dast_scanner_profile' do describe '#active_policy_names_with_dast_scanner_profile' do
let(:enforce_dast_yaml) do let(:enforce_dast_yaml) do
<<-EOS <<-EOS
type: scan_execution_policy scan_execution_policy:
name: Run DAST in every pipeline type: scan_execution_policy
description: This policy enforces to run DAST for every pipeline within the project - name: Run DAST in every pipeline
enabled: true description: This policy enforces to run DAST for every pipeline within the project
rules: enabled: true
- type: pipeline rules:
branches: - type: pipeline
- "production" branches:
actions: - "production"
- scan: dast actions:
site_profile: Site Profile - scan: dast
scanner_profile: Scanner Profile site_profile: Site Profile
- scan: dast scanner_profile: Scanner Profile
site_profile: Site Profile 2 - scan: dast
scanner_profile: Scanner Profile site_profile: Site Profile 2
scanner_profile: Scanner Profile
EOS EOS
end end
before do before do
allow(security_policy_management_project).to receive(:repository).and_return(repository) allow(security_policy_management_project).to receive(:repository).and_return(repository)
allow(repository).to receive(:ls_files).and_return(['.gitlab/security-policies/enforce-dast.yml']) allow(repository).to receive(:blob_data_at).with(default_branch, Security::OrchestrationPolicyConfiguration::POLICY_PATH).and_return(enforce_dast_yaml)
allow(repository).to receive(:blob_data_at).with(default_branch, '.gitlab/security-policies/enforce-dast.yml').and_return(enforce_dast_yaml)
end end
it 'returns list of policy names where site profile is referenced' do it 'returns list of policy names where site profile is referenced' 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