Commit 73bb0f7f authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Dmytro Zaporozhets (DZ)

Add methods to PolicyConfiguration to read active policies

This change adds new methods to read active policies and scan actions
that are applicable with provided branch.
parent 5cd7339e
......@@ -4,10 +4,45 @@ module Security
class OrchestrationPolicyConfiguration < ApplicationRecord
self.table_name = 'security_orchestration_policy_configurations'
POLICIES_BASE_PATH = '.gitlab/security-policies/'
ON_DEMAND_SCANS = %w[dast].freeze
belongs_to :project, inverse_of: :security_orchestration_policy_configuration
belongs_to :security_policy_management_project, class_name: 'Project', foreign_key: 'security_policy_management_project_id'
validates :project, presence: true, uniqueness: true
validates :security_policy_management_project, presence: true, uniqueness: true
def active_policies
security_policy_management_project
.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
def on_demand_scan_actions(branch)
active_policies
.select { |policy| applicable_for_branch?(policy, branch) }
.flat_map { |policy| policy[:actions] }
.select { |action| action[:scan].in?(ON_DEMAND_SCANS) }
end
private
def policy_at(path)
security_policy_management_project
.repository
.blob_data_at(security_policy_management_project.default_branch_or_master, path)
.then { |config| Gitlab::Config::Loader::Yaml.new(config).load! }
end
def applicable_for_branch?(policy, ref)
policy[:rules].any? do |rule|
rule[:type] == 'pipeline' && rule[:branches].any? { |branch| RefMatcher.new(branch).matches?(ref) }
end
end
end
end
......@@ -3,6 +3,12 @@
require 'spec_helper'
RSpec.describe Security::OrchestrationPolicyConfiguration do
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(:default_branch) { security_policy_management_project.default_branch_or_master }
let(:repository) { instance_double(Repository, root_ref: 'master') }
describe 'associations' do
it { is_expected.to belong_to(:project).inverse_of(:security_orchestration_policy_configuration) }
it { is_expected.to belong_to(:security_policy_management_project).class_name('Project') }
......@@ -17,4 +23,154 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
it { is_expected.to validate_uniqueness_of(:project) }
it { is_expected.to validate_uniqueness_of(:security_policy_management_project) }
end
describe '#active_policies' do
let(:enforce_dast_yaml) do
<<-EOS
type: 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
EOS
end
let(:disabled_policy_yaml) do
<<-EOS
type: scan_execution_policy
name: Disabled policy
description: This policy is disabled
enabled: false
rules: []
actions: []
EOS
end
let(:expected_active_policies) do
[
{
type: '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' }]
}
]
end
subject(:active_policies) { security_orchestration_policy_configuration.active_policies }
before do
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, '.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
it 'returns only enabled policies' do
expect(active_policies).to eq(expected_active_policies)
end
end
describe '#on_demand_scan_actions' do
let(:policy_1_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
type: scan_execution_policy
name: Run DAST in every pipeline
enabled: true
rules:
- type: pipeline
branches:
- "release/*"
actions:
- scan: dast
site_profile: Site Profile 2
scanner_profile: Scanner Profile 2
EOS
end
let(:policy_3_yaml) do
<<-EOS
type: scan_execution_policy
name: Run DAST in every pipeline
enabled: true
rules:
- type: pipeline
branches:
- "*"
actions:
- scan: dast
site_profile: Site Profile 3
scanner_profile: Scanner Profile 3
EOS
end
let(:policy_4_yaml) do
<<-EOS
type: scan_execution_policy
name: Run SAST in every pipeline
enabled: true
rules:
- type: pipeline
branches:
- "release/*"
actions:
- scan: sast
EOS
end
let(:expected_actions) do
[
{ scan: 'dast', scanner_profile: 'Scanner Profile 2', site_profile: 'Site Profile 2' },
{ scan: 'dast', scanner_profile: 'Scanner Profile 3', site_profile: 'Site Profile 3' }
]
end
subject(:on_demand_scan_actions) { security_orchestration_policy_configuration.on_demand_scan_actions('release/123') }
before do
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, '.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
it 'returns only actions for on-demand scans applicable for branch' do
expect(on_demand_scan_actions).to eq(expected_actions)
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