Commit 3777d380 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'extract_scan_execution_policy_related_code' into 'master'

Extract scan execution policy related code

See merge request gitlab-org/gitlab!69017
parents 7444b2a2 3fcaabc3
# frozen_string_literal: true
module Security
module ScanExecutionPolicy
extend ActiveSupport::Concern
include ::Gitlab::Utils::StrongMemoize
POLICY_LIMIT = 5
RULE_TYPES = {
pipeline: 'pipeline',
schedule: 'schedule'
}.freeze
SCAN_TYPES = %w[dast secret_detection cluster_image_scanning container_scanning].freeze
ON_DEMAND_SCANS = %w[dast].freeze
included do
has_many :rule_schedules,
class_name: 'Security::OrchestrationPolicyRuleSchedule',
foreign_key: :security_orchestration_policy_configuration_id,
inverse_of: :security_orchestration_policy_configuration
end
def self.valid_scan_type?(scan_type)
SCAN_TYPES.include?(scan_type)
end
def active_scan_execution_policies
return [] unless enabled?
scan_execution_policy.select { |config| config[:enabled] }.first(POLICY_LIMIT)
end
def on_demand_scan_actions(ref)
active_policies_scan_actions(ref).select { |action| action[:scan].in?(ON_DEMAND_SCANS) }
end
def pipeline_scan_actions(ref)
active_policies_scan_actions(ref).reject { |action| action[:scan].in?(ON_DEMAND_SCANS) }
end
def active_policy_names_with_dast_site_profile(profile_name)
active_policy_names_with_dast_profiles.dig(:site_profiles, profile_name)
end
def active_policy_names_with_dast_scanner_profile(profile_name)
active_policy_names_with_dast_profiles.dig(:scanner_profiles, profile_name)
end
def delete_all_schedules
rule_schedules.delete_all(:delete_all)
end
def scan_execution_policy
policy_by_type(:scan_execution_policy)
end
private
def active_policy_names_with_dast_profiles
strong_memoize(:active_policy_names_with_dast_profiles) do
profiles = { site_profiles: Hash.new { Set.new }, scanner_profiles: Hash.new { Set.new } }
active_scan_execution_policies.each do |policy|
policy[:actions].each do |action|
next unless action[:scan].in?(ON_DEMAND_SCANS)
profiles[:site_profiles][action[:site_profile]] += [policy[:name]]
profiles[:scanner_profiles][action[:scanner_profile]] += [policy[:name]] if action[:scanner_profile].present?
end
end
profiles
end
end
def active_policies_scan_actions(ref)
active_scan_execution_policies
.select { |policy| applicable_for_ref?(policy, ref) }
.flat_map { |policy| policy[:actions] }
end
def applicable_for_ref?(policy, ref)
return false unless Gitlab::Git.branch_ref?(ref)
branch_name = Gitlab::Git.ref_name(ref)
policy[:rules].any? do |rule|
rule[:type] == RULE_TYPES[:pipeline] && rule[:branches].any? { |branch| RefMatcher.new(branch).matches?(branch_name) }
end
end
end
end
......@@ -2,6 +2,7 @@
module Security
class OrchestrationPolicyConfiguration < ApplicationRecord
include Security::ScanExecutionPolicy
include EachBatch
include Gitlab::Utils::StrongMemoize
......@@ -9,25 +10,11 @@ module Security
POLICY_PATH = '.gitlab/security-policies/policy.yml'
POLICY_SCHEMA_PATH = 'ee/app/validators/json_schemas/security_orchestration_policy.json'
POLICY_LIMIT = 5
RULE_TYPES = {
pipeline: 'pipeline',
schedule: 'schedule'
}.freeze
SCAN_TYPES = %w[dast secret_detection cluster_image_scanning container_scanning].freeze
ON_DEMAND_SCANS = %w[dast].freeze
AVAILABLE_POLICY_TYPES = %i{scan_execution_policy}.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'
has_many :rule_schedules,
class_name: 'Security::OrchestrationPolicyRuleSchedule',
foreign_key: :security_orchestration_policy_configuration_id,
inverse_of: :security_orchestration_policy_configuration
validates :project, presence: true, uniqueness: true
validates :security_policy_management_project, presence: true
......@@ -41,10 +28,6 @@ module Security
self.exists?(security_policy_management_project_id: project_id)
end
def self.valid_scan_type?(scan_type)
SCAN_TYPES.include?(scan_type)
end
def enabled?
::Feature.enabled?(:security_orchestration_policies_configuration, project, default_enabled: :yaml)
end
......@@ -67,28 +50,6 @@ module Security
.valid?(policy.to_h.deep_stringify_keys)
end
def active_policies
return [] unless enabled?
scan_execution_policy.select { |config| config[:enabled] }.first(POLICY_LIMIT)
end
def on_demand_scan_actions(ref)
active_policies_scan_actions(ref).select { |action| action[:scan].in?(ON_DEMAND_SCANS) }
end
def pipeline_scan_actions(ref)
active_policies_scan_actions(ref).reject { |action| action[:scan].in?(ON_DEMAND_SCANS) }
end
def active_policy_names_with_dast_site_profile(profile_name)
active_policy_names_with_dast_profiles.dig(:site_profiles, profile_name)
end
def active_policy_names_with_dast_scanner_profile(profile_name)
active_policy_names_with_dast_profiles.dig(:scanner_profiles, profile_name)
end
def policy_last_updated_by
strong_memoize(:policy_last_updated_by) do
policy_repo.last_commit_for_path(default_branch_or_main, POLICY_PATH)&.author
......@@ -101,20 +62,12 @@ module Security
end
end
def delete_all_schedules
rule_schedules.delete_all(:delete_all)
end
def policy_by_type(type)
return [] if policy_hash.blank?
policy_hash.fetch(type, [])
end
def scan_execution_policy
policy_by_type(:scan_execution_policy)
end
def default_branch_or_main
security_policy_management_project.default_branch_or_main
end
......@@ -125,43 +78,10 @@ module Security
security_policy_management_project.repository
end
def active_policy_names_with_dast_profiles
strong_memoize(:active_policy_names_with_dast_profiles) do
profiles = { site_profiles: Hash.new { Set.new }, scanner_profiles: Hash.new { Set.new } }
active_policies.each do |policy|
policy[:actions].each do |action|
next unless action[:scan].in?(ON_DEMAND_SCANS)
profiles[:site_profiles][action[:site_profile]] += [policy[:name]]
profiles[:scanner_profiles][action[:scanner_profile]] += [policy[:name]] if action[:scanner_profile].present?
end
end
profiles
end
end
def active_policies_scan_actions(ref)
active_policies
.select { |policy| applicable_for_ref?(policy, ref) }
.flat_map { |policy| policy[:actions] }
end
def policy_blob
strong_memoize(:policy_blob) do
policy_repo.blob_data_at(default_branch_or_main, POLICY_PATH)
end
end
def applicable_for_ref?(policy, ref)
return false unless Gitlab::Git.branch_ref?(ref)
branch_name = Gitlab::Git.ref_name(ref)
policy[:rules].any? do |rule|
rule[:type] == RULE_TYPES[:pipeline] && rule[:branches].any? { |branch| RefMatcher.new(branch).matches?(branch_name) }
end
end
end
end
......@@ -28,7 +28,7 @@ module Security
def policy
strong_memoize(:policy) do
security_orchestration_policy_configuration.active_policies.at(policy_index)
security_orchestration_policy_configuration.active_scan_execution_policies.at(policy_index)
end
end
......
......@@ -23,7 +23,7 @@ module Security
return unless policy_configuration.enabled?
policy[:rules].each_with_index do |rule, rule_index|
next if rule[:type] != Security::OrchestrationPolicyConfiguration::RULE_TYPES[:schedule]
next if rule[:type] != Security::ScanExecutionPolicy::RULE_TYPES[:schedule]
Security::OrchestrationPolicyRuleSchedule
.create!(
......
......@@ -22,7 +22,7 @@ module Security
private
def valid_scan_type?(scan_type)
::Security::OrchestrationPolicyConfiguration.valid_scan_type?(scan_type)
Security::ScanExecutionPolicy.valid_scan_type?(scan_type)
end
def prepare_policy_configuration(action, index)
......
......@@ -20,7 +20,7 @@ module Security
next
end
configuration.active_policies.each_with_index do |policy, policy_index|
configuration.active_scan_execution_policies.each_with_index do |policy, policy_index|
Security::SecurityOrchestrationPolicies::ProcessRuleService
.new(policy_configuration: configuration, policy_index: policy_index, policy: policy)
.execute
......
......@@ -73,11 +73,11 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
describe '.valid_scan_type?' do
it 'returns true when scan type is valid' do
expect(described_class.valid_scan_type?('secret_detection')).to be_truthy
expect(Security::ScanExecutionPolicy.valid_scan_type?('secret_detection')).to be_truthy
end
it 'returns false when scan type is invalid' do
expect(described_class.valid_scan_type?('invalid')).to be_falsey
expect(Security::ScanExecutionPolicy.valid_scan_type?('invalid')).to be_falsey
end
end
......@@ -206,7 +206,7 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
]
end
subject(:active_policies) { security_orchestration_policy_configuration.active_policies }
subject(:active_scan_execution_policies) { security_orchestration_policy_configuration.active_scan_execution_policies }
before do
allow(security_policy_management_project).to receive(:repository).and_return(repository)
......@@ -214,7 +214,7 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
end
it 'returns only enabled policies' do
expect(active_policies).to eq(expected_active_policies)
expect(active_scan_execution_policies).to eq(expected_active_policies)
end
context 'when feature is disabled' do
......@@ -223,7 +223,7 @@ RSpec.describe Security::OrchestrationPolicyConfiguration do
end
it 'returns empty array' do
expect(active_policies).to eq([])
expect(active_scan_execution_policies).to eq([])
end
end
end
......
......@@ -29,7 +29,7 @@ RSpec.describe Security::SecurityOrchestrationPolicies::RuleScheduleService do
project.repository.create_branch('production', project.default_branch)
allow_next_instance_of(Security::OrchestrationPolicyConfiguration) do |instance|
allow(instance).to receive(:active_policies).and_return([policy])
allow(instance).to receive(:active_scan_execution_policies).and_return([policy])
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