Commit de4ac85b authored by David Kim's avatar David Kim

Merge branch 'sk/335661-create-security-policy-project' into 'master'

Add support for security policy project for Projects::CreateService

See merge request gitlab-org/gitlab!66448
parents 0db9ffcb 75e3e09a
...@@ -101,6 +101,8 @@ module Projects ...@@ -101,6 +101,8 @@ module Projects
@project.track_project_repository @project.track_project_repository
@project.create_project_setting unless @project.project_setting @project.create_project_setting unless @project.project_setting
yield if block_given?
event_service.create_project(@project, current_user) event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create) system_hook_service.execute_hooks_for(@project, :create)
......
...@@ -5,6 +5,15 @@ module EE ...@@ -5,6 +5,15 @@ module EE
module CreateService module CreateService
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
attr_reader :security_policy_target_project_id
override :initialize
def initialize(user, params)
super
@security_policy_target_project_id = @params.delete(:security_policy_target_project_id)
end
override :execute override :execute
def execute def execute
limit = params.delete(:repository_size_limit) limit = params.delete(:repository_size_limit)
...@@ -45,11 +54,25 @@ module EE ...@@ -45,11 +54,25 @@ module EE
override :after_create_actions override :after_create_actions
def after_create_actions def after_create_actions
super super do
create_security_policy_configuration if security_policy_target_project?
end
create_predefined_push_rule create_predefined_push_rule
end end
def security_policy_target_project?
security_policy_target_project_id && ::Feature.enabled?(:security_orchestration_policies_configuration, project)
end
def create_security_policy_configuration
if (security_policy_target_project = ::Project.find(security_policy_target_project_id))
::Security::Orchestration::AssignService
.new(security_policy_target_project, current_user, policy_project_id: project.id)
.execute
end
end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def create_predefined_push_rule def create_predefined_push_rule
return unless project.feature_available?(:push_rules) return unless project.feature_available?(:push_rules)
......
...@@ -10,11 +10,6 @@ module Security ...@@ -10,11 +10,6 @@ module Security
return error(policy_project.errors.full_messages.join(',')) unless policy_project.saved? return error(policy_project.errors.full_messages.join(',')) unless policy_project.saved?
project.create_security_orchestration_policy_configuration! do |p|
p.security_policy_management_project_id = policy_project.id
end
create_or_update_protected_branch(policy_project)
members = add_members(policy_project) members = add_members(policy_project)
errors = members.flat_map { |member| member.errors.full_messages } errors = members.flat_map { |member| member.errors.full_messages }
...@@ -25,26 +20,6 @@ module Security ...@@ -25,26 +20,6 @@ module Security
private private
def create_or_update_protected_branch(policy_project)
protected_branch = policy_project.protected_branches.find_by_name(policy_project.default_branch_or_main)
params = {
name: policy_project.default_branch_or_main,
push_access_levels_attributes: [{ access_level: Gitlab::Access::NO_ACCESS }],
merge_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }]
}
if protected_branch.present?
ProtectedBranches::UpdateService
.new(policy_project, current_user, params)
.execute(protected_branch)
return
end
ProtectedBranches::CreateService
.new(policy_project, current_user, params)
.execute(skip_authorization: true)
end
def add_members(policy_project) def add_members(policy_project)
members_to_add = project.team.maintainers - policy_project.team.members members_to_add = project.team.maintainers - policy_project.team.members
policy_project.add_users(members_to_add, :developer) policy_project.add_users(members_to_add, :developer)
...@@ -53,6 +28,7 @@ module Security ...@@ -53,6 +28,7 @@ module Security
def create_project_params def create_project_params
{ {
visibility_level: project.visibility_level, visibility_level: project.visibility_level,
security_policy_target_project_id: project.id,
name: "#{project.name} - Security policy project", name: "#{project.name} - Security policy project",
description: "This project is automatically generated to manage security policies for the project.", description: "This project is automatically generated to manage security policies for the project.",
namespace_id: project.namespace.id, namespace_id: project.namespace.id,
......
...@@ -357,6 +357,37 @@ RSpec.describe Projects::CreateService, '#execute' do ...@@ -357,6 +357,37 @@ RSpec.describe Projects::CreateService, '#execute' do
end end
end end
context 'security policy configuration' do
let_it_be(:security_policy_target_project) { create(:project) }
before do
opts[:security_policy_target_project_id] = security_policy_target_project.id
stub_licensed_features(security_orchestration_policies: feature_enabled)
stub_feature_flags(security_orchestration_policies_configuration: feature_enabled)
end
context 'when feature flag is enabled' do
let_it_be(:feature_enabled) { true }
it 'creates security policy configuration for the project' do
expect(::Security::Orchestration::AssignService).to receive_message_chain(:new, :execute)
create_project(user, opts)
end
end
context 'when feature flag is disabled' do
let_it_be(:feature_enabled) { false }
it 'does not create security policy configuration' do
expect(::Security::Orchestration::AssignService).not_to receive(:new)
create_project(user, opts)
end
end
end
def create_project(user, opts) def create_project(user, opts)
described_class.new(user, opts).execute described_class.new(user, opts).execute
end end
......
...@@ -20,58 +20,13 @@ RSpec.describe Security::SecurityOrchestrationPolicies::ProjectCreateService do ...@@ -20,58 +20,13 @@ RSpec.describe Security::SecurityOrchestrationPolicies::ProjectCreateService do
response = service.execute response = service.execute
policy_project = response[:policy_project] policy_project = response[:policy_project]
expect(project.security_orchestration_policy_configuration.security_policy_management_project).to eq(policy_project) expect(project.reload.security_orchestration_policy_configuration.security_policy_management_project).to eq(policy_project)
expect(policy_project.namespace).to eq(project.namespace) expect(policy_project.namespace).to eq(project.namespace)
expect(policy_project.protected_branches.map(&:name)).to contain_exactly(project.default_branch_or_main)
expect(policy_project.protected_branches.first.merge_access_levels.map(&:access_level)).to eq([Gitlab::Access::MAINTAINER])
expect(policy_project.protected_branches.first.push_access_levels.map(&:access_level)).to eq([Gitlab::Access::NO_ACCESS])
expect(policy_project.team.developers).to contain_exactly(maintainer) expect(policy_project.team.developers).to contain_exactly(maintainer)
expect(policy_project.container_registry_access_level).to eq(ProjectFeature::DISABLED) expect(policy_project.container_registry_access_level).to eq(ProjectFeature::DISABLED)
end end
end end
context 'when protected branch already exists' do
let_it_be(:project) { create(:project) }
let_it_be(:current_user) { project.owner }
let_it_be(:maintainer) { create(:user) }
before do
project.add_maintainer(maintainer)
allow_next_instance_of(Project) do |instance|
allow(instance).to receive_message_chain(:protected_branches, :find_by_name).and_return([ProtectedBranch.new])
end
protected_branch_service = instance_spy(ProtectedBranches::UpdateService)
allow(ProtectedBranches::UpdateService).to receive(:new).and_return(protected_branch_service)
end
it 'updates protected branch' do
service.execute
expect(ProtectedBranches::UpdateService).to have_received(:new)
end
end
context 'when protected branch does not exist' do
let_it_be(:project) { create(:project) }
let_it_be(:current_user) { project.owner }
let_it_be(:maintainer) { create(:user) }
before do
project.add_maintainer(maintainer)
protected_branch_service = instance_spy(ProtectedBranches::CreateService)
allow(ProtectedBranches::CreateService).to receive(:new).and_return(protected_branch_service)
end
it 'creates protected branch' do
service.execute
expect(ProtectedBranches::CreateService).to have_received(:new)
end
end
context 'when adding users to security policy project fails' do context 'when adding users to security policy project fails' do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:current_user) { project.owner } let_it_be(:current_user) { project.owner }
......
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