Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/policies/project_policy_spec.rb')
-rw-r--r--spec/policies/project_policy_spec.rb375
1 files changed, 250 insertions, 125 deletions
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 3de006d8c9b..fda889ff422 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -214,6 +214,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it 'allows modify pipelines' do
expect_allowed(:create_pipeline)
expect_allowed(:update_pipeline)
+ expect_allowed(:cancel_pipeline)
expect_allowed(:create_pipeline_schedule)
end
end
@@ -224,6 +225,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it 'disallows to modify pipelines' do
expect_disallowed(:create_pipeline)
expect_disallowed(:update_pipeline)
+ expect_disallowed(:cancel_pipeline)
expect_disallowed(:destroy_pipeline)
expect_disallowed(:create_pipeline_schedule)
end
@@ -285,7 +287,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it 'disallows all permissions except pipeline when the feature is disabled' do
builds_permissions = [
- :create_build, :read_build, :update_build, :admin_build, :destroy_build,
+ :create_build, :read_build, :update_build, :cancel_build, :admin_build, :destroy_build,
:create_pipeline_schedule, :read_pipeline_schedule_variables, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
:create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
:create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
@@ -304,7 +306,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it 'disallows pipeline and commit_status permissions' do
builds_permissions = [
- :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
+ :create_pipeline, :update_pipeline, :cancel_pipeline, :admin_pipeline, :destroy_pipeline,
:create_commit_status, :update_commit_status, :admin_commit_status, :destroy_commit_status
]
@@ -316,8 +318,8 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
context 'repository feature' do
let(:repository_permissions) do
[
- :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline,
- :create_build, :read_build, :update_build, :admin_build, :destroy_build,
+ :create_pipeline, :update_pipeline, :cancel_pipeline, :admin_pipeline, :destroy_pipeline,
+ :create_build, :read_build, :cancel_build, :update_build, :admin_build, :destroy_build,
:create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
:create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
:create_cluster, :read_cluster, :update_cluster, :admin_cluster,
@@ -389,7 +391,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
let(:maintainer_abilities) do
- %w(create_build create_pipeline)
+ %w[create_build create_pipeline]
end
it 'does not allow pushing code' do
@@ -411,7 +413,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'importing members from another project' do
- %w(maintainer owner).each do |role|
+ %w[maintainer owner].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -419,7 +421,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest reporter developer anonymous).each do |role|
+ %w[guest reporter developer anonymous].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -441,7 +443,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'importing work items' do
- %w(reporter developer maintainer owner).each do |role|
+ %w[reporter developer maintainer owner].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -449,7 +451,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest anonymous).each do |role|
+ %w[guest anonymous].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -471,7 +473,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'reading usage quotas' do
- %w(maintainer owner).each do |role|
+ %w[maintainer owner].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -479,7 +481,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest reporter developer anonymous).each do |role|
+ %w[guest reporter developer anonymous].each do |role|
context "with #{role}" do
let(:current_user) { send(role) }
@@ -690,7 +692,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it { is_expected.to be_disallowed(:fork_project) }
end
- %w(reporter developer maintainer).each do |role|
+ %w[reporter developer maintainer].each do |role|
context role do
let(:current_user) { send(role) }
@@ -789,7 +791,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest reporter developer maintainer owner).each do |role|
+ %w[guest reporter developer maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -817,7 +819,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest reporter developer maintainer owner).each do |role|
+ %w[guest reporter developer maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1437,7 +1439,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'security configuration feature' do
- %w(guest reporter).each do |role|
+ %w[guest reporter].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1447,7 +1449,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(developer maintainer owner).each do |role|
+ %w[developer maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1459,7 +1461,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'infrastructure google cloud feature' do
- %w(guest reporter developer).each do |role|
+ %w[guest reporter developer].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1469,7 +1471,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(maintainer owner).each do |role|
+ %w[maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1481,7 +1483,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'infrastructure aws feature' do
- %w(guest reporter developer).each do |role|
+ %w[guest reporter developer].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1491,7 +1493,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(maintainer owner).each do |role|
+ %w[maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -1972,7 +1974,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
context 'project member' do
let(:project) { private_project }
- %w(guest reporter developer maintainer).each do |role|
+ %w[guest reporter developer maintainer].each do |role|
context role do
let(:current_user) { send(role) }
@@ -2001,7 +2003,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'project member' do
- %w(guest reporter developer maintainer).each do |role|
+ %w[guest reporter developer maintainer].each do |role|
context role do
before do
project.add_member(current_user, role.to_sym)
@@ -2035,7 +2037,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'project member' do
- %w(guest reporter developer maintainer).each do |role|
+ %w[guest reporter developer maintainer].each do |role|
context role do
before do
project.add_member(current_user, role.to_sym)
@@ -2065,7 +2067,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
let(:current_user) { create(:user) }
context 'project member' do
- %w(guest reporter developer maintainer).each do |role|
+ %w[guest reporter developer maintainer].each do |role|
context role do
before do
project.add_member(current_user, role.to_sym)
@@ -2393,44 +2395,48 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
developer_permissions + [:create_cluster, :read_cluster, :update_cluster, :admin_cluster, :admin_terraform_state, :admin_project_google_cloud]
end
- where(:project_visibility, :access_level, :role, :allowed) do
- :public | ProjectFeature::ENABLED | :maintainer | true
- :public | ProjectFeature::ENABLED | :developer | true
- :public | ProjectFeature::ENABLED | :guest | true
- :public | ProjectFeature::ENABLED | :anonymous | true
- :public | ProjectFeature::PRIVATE | :maintainer | true
- :public | ProjectFeature::PRIVATE | :developer | true
- :public | ProjectFeature::PRIVATE | :guest | true
- :public | ProjectFeature::PRIVATE | :anonymous | false
- :public | ProjectFeature::DISABLED | :maintainer | false
- :public | ProjectFeature::DISABLED | :developer | false
- :public | ProjectFeature::DISABLED | :guest | false
- :public | ProjectFeature::DISABLED | :anonymous | false
- :internal | ProjectFeature::ENABLED | :maintainer | true
- :internal | ProjectFeature::ENABLED | :developer | true
- :internal | ProjectFeature::ENABLED | :guest | true
- :internal | ProjectFeature::ENABLED | :anonymous | false
- :internal | ProjectFeature::PRIVATE | :maintainer | true
- :internal | ProjectFeature::PRIVATE | :developer | true
- :internal | ProjectFeature::PRIVATE | :guest | true
- :internal | ProjectFeature::PRIVATE | :anonymous | false
- :internal | ProjectFeature::DISABLED | :maintainer | false
- :internal | ProjectFeature::DISABLED | :developer | false
- :internal | ProjectFeature::DISABLED | :guest | false
- :internal | ProjectFeature::DISABLED | :anonymous | false
- :private | ProjectFeature::ENABLED | :maintainer | true
- :private | ProjectFeature::ENABLED | :developer | true
- :private | ProjectFeature::ENABLED | :guest | true
- :private | ProjectFeature::ENABLED | :anonymous | false
- :private | ProjectFeature::PRIVATE | :maintainer | true
- :private | ProjectFeature::PRIVATE | :developer | true
- :private | ProjectFeature::PRIVATE | :guest | true
- :private | ProjectFeature::PRIVATE | :anonymous | false
- :private | ProjectFeature::DISABLED | :maintainer | false
- :private | ProjectFeature::DISABLED | :developer | false
- :private | ProjectFeature::DISABLED | :guest | false
- :private | ProjectFeature::DISABLED | :anonymous | false
- end
+ shared_context 'with permission matrix' do
+ where(:project_visibility, :access_level, :role, :allowed) do
+ :public | ProjectFeature::ENABLED | :maintainer | true
+ :public | ProjectFeature::ENABLED | :developer | true
+ :public | ProjectFeature::ENABLED | :guest | true
+ :public | ProjectFeature::ENABLED | :anonymous | true
+ :public | ProjectFeature::PRIVATE | :maintainer | true
+ :public | ProjectFeature::PRIVATE | :developer | true
+ :public | ProjectFeature::PRIVATE | :guest | true
+ :public | ProjectFeature::PRIVATE | :anonymous | false
+ :public | ProjectFeature::DISABLED | :maintainer | false
+ :public | ProjectFeature::DISABLED | :developer | false
+ :public | ProjectFeature::DISABLED | :guest | false
+ :public | ProjectFeature::DISABLED | :anonymous | false
+ :internal | ProjectFeature::ENABLED | :maintainer | true
+ :internal | ProjectFeature::ENABLED | :developer | true
+ :internal | ProjectFeature::ENABLED | :guest | true
+ :internal | ProjectFeature::ENABLED | :anonymous | false
+ :internal | ProjectFeature::PRIVATE | :maintainer | true
+ :internal | ProjectFeature::PRIVATE | :developer | true
+ :internal | ProjectFeature::PRIVATE | :guest | true
+ :internal | ProjectFeature::PRIVATE | :anonymous | false
+ :internal | ProjectFeature::DISABLED | :maintainer | false
+ :internal | ProjectFeature::DISABLED | :developer | false
+ :internal | ProjectFeature::DISABLED | :guest | false
+ :internal | ProjectFeature::DISABLED | :anonymous | false
+ :private | ProjectFeature::ENABLED | :maintainer | true
+ :private | ProjectFeature::ENABLED | :developer | true
+ :private | ProjectFeature::ENABLED | :guest | true
+ :private | ProjectFeature::ENABLED | :anonymous | false
+ :private | ProjectFeature::PRIVATE | :maintainer | true
+ :private | ProjectFeature::PRIVATE | :developer | true
+ :private | ProjectFeature::PRIVATE | :guest | true
+ :private | ProjectFeature::PRIVATE | :anonymous | false
+ :private | ProjectFeature::DISABLED | :maintainer | false
+ :private | ProjectFeature::DISABLED | :developer | false
+ :private | ProjectFeature::DISABLED | :guest | false
+ :private | ProjectFeature::DISABLED | :anonymous | false
+ end
+ end
+
+ include_context 'with permission matrix'
with_them do
let(:current_user) { user_subject(role) }
@@ -2448,6 +2454,8 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
context 'when terraform state management is disabled' do
+ include_context 'with permission matrix'
+
before do
stub_config(terraform_state: { enabled: false })
end
@@ -2562,73 +2570,154 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
describe 'when user is authenticated via CI_JOB_TOKEN', :request_store do
using RSpec::Parameterized::TableSyntax
- where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
- :private | :reporter | false | :same | true | true
- :private | :reporter | false | :same | false | true
- :private | :reporter | false | :different | true | false
- :private | :reporter | false | :different | false | true
- :private | :guest | false | :same | true | true
- :private | :guest | false | :same | false | true
- :private | :guest | false | :different | true | false
- :private | :guest | false | :different | false | true
-
- :internal | :reporter | false | :same | true | true
- :internal | :reporter | true | :same | true | true
- :internal | :reporter | false | :same | false | true
- :internal | :reporter | false | :different | true | true
- :internal | :reporter | true | :different | true | false
- :internal | :reporter | false | :different | false | true
- :internal | :guest | false | :same | true | true
- :internal | :guest | true | :same | true | true
- :internal | :guest | false | :same | false | true
- :internal | :guest | false | :different | true | true
- :internal | :guest | true | :different | true | false
- :internal | :guest | false | :different | false | true
-
- :public | :reporter | false | :same | true | true
- :public | :reporter | false | :same | false | true
- :public | :reporter | false | :different | true | true
- :public | :reporter | false | :different | false | true
- :public | :guest | false | :same | true | true
- :public | :guest | false | :same | false | true
- :public | :guest | false | :different | true | true
- :public | :guest | false | :different | false | true
- end
+ RSpec.shared_examples 'CI_JOB_TOKEN enforces the expected permissions' do
+ with_them do
+ let(:current_user) { public_send(user_role) }
+ let(:project) { public_send("#{project_visibility}_project") }
+ let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
- with_them do
- let(:current_user) { public_send(user_role) }
- let(:project) { public_send("#{project_visibility}_project") }
- let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
+ let(:scope_project) do
+ if scope_project_type == :same
+ project
+ else
+ create(:project, :private)
+ end
+ end
- let(:scope_project) do
- if scope_project_type == :same
- project
- else
- create(:project, :private)
+ before do
+ current_user.set_ci_job_token_scope!(job)
+ current_user.external = external_user
+ project.update!(
+ ci_outbound_job_token_scope_enabled: token_scope_enabled,
+ ci_inbound_job_token_scope_enabled: token_scope_enabled
+ )
+ scope_project.update!(
+ ci_outbound_job_token_scope_enabled: token_scope_enabled,
+ ci_inbound_job_token_scope_enabled: token_scope_enabled
+ )
+ end
+
+ it "enforces the expected permissions" do
+ if result
+ is_expected.to be_allowed("#{user_role}_access".to_sym)
+ else
+ is_expected.to be_disallowed("#{user_role}_access".to_sym)
+ end
end
end
+ end
- before do
- current_user.set_ci_job_token_scope!(job)
- current_user.external = external_user
- project.update!(
- ci_outbound_job_token_scope_enabled: token_scope_enabled,
- ci_inbound_job_token_scope_enabled: token_scope_enabled
- )
- scope_project.update!(
- ci_outbound_job_token_scope_enabled: token_scope_enabled,
- ci_inbound_job_token_scope_enabled: token_scope_enabled
- )
- end
-
- it "enforces the expected permissions" do
- if result
- is_expected.to be_allowed("#{user_role}_access".to_sym)
- else
- is_expected.to be_disallowed("#{user_role}_access".to_sym)
+ # Remove project_visibility on FF restrict_ci_job_token_for_public_and_internal_projects cleanup
+ where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
+ :public | :reporter | false | :same | true | true
+ :public | :reporter | true | :same | true | true
+ :public | :reporter | false | :same | false | true
+ :public | :reporter | false | :different | true | false
+ :public | :reporter | true | :different | true | false
+ :public | :reporter | false | :different | false | true
+ :public | :guest | false | :same | true | true
+ :public | :guest | true | :same | true | true
+ :public | :guest | false | :same | false | true
+ :public | :guest | false | :different | true | false
+ :public | :guest | true | :different | true | false
+ :public | :guest | false | :different | false | true
+ end
+
+ include_examples "CI_JOB_TOKEN enforces the expected permissions"
+
+ context "when the project is public or internal and not on the allowlist" do
+ where(:feature, :permissions) do
+ :container_registry | [:build_read_container_image, :read_container_image]
+ :package_registry | [:read_package, :read_project]
+ :builds | [:read_commit_status]
+ :releases | [:read_release]
+ :environments | [:read_environment]
+ end
+
+ with_them do
+ let(:current_user) { developer }
+ let(:project) { public_project }
+ let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
+ let_it_be(:scope_project) { create(:project, :private) }
+
+ before do
+ current_user.set_ci_job_token_scope!(job)
+
+ scope_project.update!(ci_inbound_job_token_scope_enabled: true)
+ end
+
+ it 'allows the permissions based on the feature access level' do
+ project.project_feature.update!("#{feature}_access_level": ProjectFeature::ENABLED)
+
+ permissions.each { |p| expect_allowed(p) }
+ end
+
+ it 'disallows the permissions if feature access level is restricted' do
+ project.project_feature.update!("#{feature}_access_level": ProjectFeature::PRIVATE)
+
+ permissions.each { |p| expect_disallowed(p) }
+ end
+
+ it 'disallows the permissions if feature access level is disabled' do
+ project.project_feature.update!("#{feature}_access_level": ProjectFeature::DISABLED)
+
+ permissions.each { |p| expect_disallowed(p) }
+ end
+
+ context "with restrict_ci_job_token_for_public_and_internal_projects disabled" do
+ before do
+ stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false)
+ end
+
+ it 'allows all permissions for private' do
+ project.project_feature.update!("#{feature}_access_level": ProjectFeature::PRIVATE)
+
+ permissions.each { |p| expect_allowed(p) }
+ end
end
end
end
+
+ context "with FF restrict_ci_job_token_for_public_and_internal_projects disabled" do
+ before do
+ stub_feature_flags(restrict_ci_job_token_for_public_and_internal_projects: false)
+ end
+
+ where(:project_visibility, :user_role, :external_user, :scope_project_type, :token_scope_enabled, :result) do
+ :private | :reporter | false | :same | true | true
+ :private | :reporter | false | :same | false | true
+ :private | :reporter | false | :different | true | false
+ :private | :reporter | false | :different | false | true
+ :private | :guest | false | :same | true | true
+ :private | :guest | false | :same | false | true
+ :private | :guest | false | :different | true | false
+ :private | :guest | false | :different | false | true
+
+ :internal | :reporter | false | :same | true | true
+ :internal | :reporter | true | :same | true | true
+ :internal | :reporter | false | :same | false | true
+ :internal | :reporter | false | :different | true | true
+ :internal | :reporter | true | :different | true | false
+ :internal | :reporter | false | :different | false | true
+ :internal | :guest | false | :same | true | true
+ :internal | :guest | true | :same | true | true
+ :internal | :guest | false | :same | false | true
+ :internal | :guest | false | :different | true | true
+ :internal | :guest | true | :different | true | false
+ :internal | :guest | false | :different | false | true
+
+ :public | :reporter | false | :same | true | true
+ :public | :reporter | false | :same | false | true
+ :public | :reporter | false | :different | true | true
+ :public | :reporter | false | :different | false | true
+ :public | :guest | false | :same | true | true
+ :public | :guest | false | :same | false | true
+ :public | :guest | false | :different | true | true
+ :public | :guest | false | :different | false | true
+ end
+
+ include_examples "CI_JOB_TOKEN enforces the expected permissions"
+ end
end
describe 'container_image policies' do
@@ -2825,7 +2914,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(guest reporter developer).each do |role|
+ %w[guest reporter developer].each do |role|
context role do
let(:current_user) { send(role) }
@@ -2833,7 +2922,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
- %w(maintainer owner).each do |role|
+ %w[maintainer owner].each do |role|
context role do
let(:current_user) { send(role) }
@@ -3212,9 +3301,23 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
describe 'add_catalog_resource' do
- let(:current_user) { owner }
+ using RSpec::Parameterized::TableSyntax
- specify { is_expected.to be_disallowed(:read_namespace_catalog) }
+ let(:current_user) { public_send(role) }
+
+ where(:role, :allowed) do
+ :owner | true
+ :maintainer | false
+ :developer | false
+ :reporter | false
+ :guest | false
+ end
+
+ with_them do
+ it do
+ expect(subject.can?(:add_catalog_resource)).to be(allowed)
+ end
+ end
end
describe 'read_model_registry' do
@@ -3237,6 +3340,28 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
end
+ describe 'write_model_registry' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:ff_model_registry_enabled, :current_user, :allowed) do
+ true | ref(:reporter) | true
+ true | ref(:guest) | false
+ false | ref(:owner) | false
+ end
+ with_them do
+ before do
+ stub_feature_flags(model_registry: false)
+ stub_feature_flags(model_registry: project) if ff_model_registry_enabled
+ end
+
+ if params[:allowed]
+ it { expect_allowed(:write_model_registry) }
+ else
+ it { expect_disallowed(:write_model_registry) }
+ end
+ end
+ end
+
describe ':read_model_experiments' do
using RSpec::Parameterized::TableSyntax