Skip to content
Snippets Groups Projects
Unverified Commit fb99e8c9 authored by Hinam Mehra's avatar Hinam Mehra Committed by GitLab
Browse files

Merge branch 'hmehra-add-job-token-permission-graphql' into 'master'

Add GraphQL endpoints to attach policies to ci allowlist

Closes gitlab-org/govern/authorization/team-tasks#69

See merge request https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167872



Merged-by: default avatarHinam Mehra <hmehra@gitlab.com>
Approved-by: default avatarmo khan <mo@mokhan.ca>
Approved-by: default avatarEugie Limpin <elimpin@gitlab.com>
Approved-by: default avatarGrzegorz Bizon <grzegorz@gitlab.com>
Reviewed-by: default avatarGrzegorz Bizon <grzegorz@gitlab.com>
Reviewed-by: default avatarHinam Mehra <hmehra@gitlab.com>
Reviewed-by: default avatarmo khan <mo@mokhan.ca>
parents b270a810 ccae814c
No related branches found
No related tags found
No related merge requests found
Showing
with 390 additions and 90 deletions
Loading
Loading
@@ -18,19 +18,28 @@ class AddGroupOrProject < BaseMutation
required: true,
description: 'Group or project to be added to the CI job token scope.'
 
argument :job_token_policies, [Types::Ci::JobTokenScope::PoliciesEnum],
required: false,
default_value: [],
alpha: { milestone: '17.5' },
description: 'List of policies added to the CI job token scope. Is ignored if ' \
'`add_policies_to_ci_job_token` feature flag is disabled.'
field :ci_job_token_scope,
Types::Ci::JobTokenScopeType,
null: true,
description: "CI job token's access scope."
 
def resolve(project_path:, target_path:)
project = authorized_find!(project_path)
def resolve(args)
project = authorized_find!(args[:project_path])
target = find_target_path(args[:target_path])
 
target = find_target_path(target_path)
args.delete(:job_token_policies) unless Feature.enabled?(:add_policies_to_ci_job_token, project)
 
result = ::Ci::JobTokenScope::AddGroupOrProjectService
.new(project, current_user)
.execute(target)
.execute(target, policies: args[:job_token_policies])
 
if result.success?
{
Loading
Loading
# frozen_string_literal: true
module Types
module Ci
module JobTokenScope
class PoliciesEnum < BaseEnum
graphql_name 'CiJobTokenScopePolicies'
description 'CI_JOB_TOKEN policy'
::Ci::JobToken::Policies.all_values.each do |policy|
value policy.upcase, value: policy, description: policy.titleize
end
end
end
end
end
Loading
Loading
@@ -30,25 +30,35 @@ def groups
::Group.id_in(group_links.pluck(:target_group_id))
end
 
def add!(target_project, user:)
def add!(target_project, user:, policies: [])
job_token_policies = add_policies_to_ci_job_token_enabled ? policies : []
Ci::JobToken::ProjectScopeLink.create!(
source_project: @source_project,
direction: @direction,
target_project: target_project,
added_by: user
added_by: user,
job_token_policies: job_token_policies
)
end
 
def add_group!(target_group, user:)
def add_group!(target_group, user:, policies: [])
job_token_policies = add_policies_to_ci_job_token_enabled ? policies : []
Ci::JobToken::GroupScopeLink.create!(
source_project: @source_project,
target_group: target_group,
added_by: user
added_by: user,
job_token_policies: job_token_policies
)
end
 
private
 
def add_policies_to_ci_job_token_enabled
Feature.enabled?(:add_policies_to_ci_job_token, @source_project)
end
def source_links
Ci::JobToken::ProjectScopeLink
.with_source(@source_project)
Loading
Loading
Loading
Loading
@@ -5,13 +5,13 @@ module JobTokenScope
class AddGroupOrProjectService < ::BaseService
include EditScopeValidations
 
def execute(target)
def execute(target, policies: [])
validate_target_exists!(target)
 
if target.is_a?(::Group)
::Ci::JobTokenScope::AddGroupService.new(project, current_user).execute(target)
::Ci::JobTokenScope::AddGroupService.new(project, current_user).execute(target, policies: policies)
else
::Ci::JobTokenScope::AddProjectService.new(project, current_user).execute(target)
::Ci::JobTokenScope::AddProjectService.new(project, current_user).execute(target, policies: policies)
end
 
rescue EditScopeValidations::NotFoundError => e
Loading
Loading
Loading
Loading
@@ -5,11 +5,11 @@ module JobTokenScope
class AddGroupService < ::BaseService
include EditScopeValidations
 
def execute(target_group)
def execute(target_group, policies: [])
validate_group_add!(project, target_group, current_user)
 
link = allowlist
.add_group!(target_group, user: current_user)
.add_group!(target_group, policies: policies, user: current_user)
 
ServiceResponse.success(payload: { group_link: link })
 
Loading
Loading
Loading
Loading
@@ -5,11 +5,11 @@ module JobTokenScope
class AddProjectService < ::BaseService
include EditScopeValidations
 
def execute(target_project, direction: :inbound)
def execute(target_project, policies: [], direction: :inbound)
validate_edit!(project, target_project, current_user)
 
link = allowlist(direction)
.add!(target_project, user: current_user)
.add!(target_project, policies: policies, user: current_user)
 
ServiceResponse.success(payload: { project_link: link })
 
Loading
Loading
Loading
Loading
@@ -29,6 +29,7 @@
"read_environment",
"read_group",
"read_job_artifacts",
"read_package",
"read_pipeline",
"read_project",
"read_release",
Loading
Loading
---
name: add_policies_to_ci_job_token
feature_issue_url: https://gitlab.com/gitlab-org/govern/authorization/team-tasks/-/issues/69
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167872
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/497754
milestone: '17.5'
group: group::authorization
type: wip
default_enabled: false
Loading
Loading
@@ -2997,6 +2997,7 @@ Input type: `CiJobTokenScopeAddGroupOrProjectInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcijobtokenscopeaddgrouporprojectclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcijobtokenscopeaddgrouporprojectjobtokenpolicies"></a>`jobTokenPolicies` **{warning-solid}** | [`[CiJobTokenScopePolicies!]`](#cijobtokenscopepolicies) | **Deprecated:** **Status**: Experiment. Introduced in GitLab 17.5. |
| <a id="mutationcijobtokenscopeaddgrouporprojectprojectpath"></a>`projectPath` | [`ID!`](#id) | Project that the CI job token scope belongs to. |
| <a id="mutationcijobtokenscopeaddgrouporprojecttargetpath"></a>`targetPath` | [`ID!`](#id) | Group or project to be added to the CI job token scope. |
 
Loading
Loading
@@ -36906,6 +36907,48 @@ Direction of access.
| <a id="cijobtokenscopedirectioninbound"></a>`INBOUND` | Target projects in the inbound allowlist can access the scope project through their job tokens. |
| <a id="cijobtokenscopedirectionoutbound"></a>`OUTBOUND` | Job token scope project can access target project in the outbound allowlist. |
 
### `CiJobTokenScopePolicies`
CI_JOB_TOKEN policy.
| Value | Description |
| ----- | ----------- |
| <a id="cijobtokenscopepoliciesadmin_container_image"></a>`ADMIN_CONTAINER_IMAGE` | Admin Container Image. |
| <a id="cijobtokenscopepoliciesadmin_secure_files"></a>`ADMIN_SECURE_FILES` | Admin Secure Files. |
| <a id="cijobtokenscopepoliciesadmin_terraform_state"></a>`ADMIN_TERRAFORM_STATE` | Admin Terraform State. |
| <a id="cijobtokenscopepoliciesbuild_create_container_image"></a>`BUILD_CREATE_CONTAINER_IMAGE` | Build Create Container Image. |
| <a id="cijobtokenscopepoliciesbuild_destroy_container_image"></a>`BUILD_DESTROY_CONTAINER_IMAGE` | Build Destroy Container Image. |
| <a id="cijobtokenscopepoliciesbuild_download_code"></a>`BUILD_DOWNLOAD_CODE` | Build Download Code. |
| <a id="cijobtokenscopepoliciesbuild_push_code"></a>`BUILD_PUSH_CODE` | Build Push Code. |
| <a id="cijobtokenscopepoliciesbuild_read_container_image"></a>`BUILD_READ_CONTAINER_IMAGE` | Build Read Container Image. |
| <a id="cijobtokenscopepoliciescreate_deployment"></a>`CREATE_DEPLOYMENT` | Create Deployment. |
| <a id="cijobtokenscopepoliciescreate_environment"></a>`CREATE_ENVIRONMENT` | Create Environment. |
| <a id="cijobtokenscopepoliciescreate_on_demand_dast_scan"></a>`CREATE_ON_DEMAND_DAST_SCAN` | Create On Demand Dast Scan. |
| <a id="cijobtokenscopepoliciescreate_package"></a>`CREATE_PACKAGE` | Create Package. |
| <a id="cijobtokenscopepoliciescreate_release"></a>`CREATE_RELEASE` | Create Release. |
| <a id="cijobtokenscopepoliciesdestroy_container_image"></a>`DESTROY_CONTAINER_IMAGE` | Destroy Container Image. |
| <a id="cijobtokenscopepoliciesdestroy_deployment"></a>`DESTROY_DEPLOYMENT` | Destroy Deployment. |
| <a id="cijobtokenscopepoliciesdestroy_environment"></a>`DESTROY_ENVIRONMENT` | Destroy Environment. |
| <a id="cijobtokenscopepoliciesdestroy_package"></a>`DESTROY_PACKAGE` | Destroy Package. |
| <a id="cijobtokenscopepoliciesdestroy_release"></a>`DESTROY_RELEASE` | Destroy Release. |
| <a id="cijobtokenscopepoliciesread_build"></a>`READ_BUILD` | Read Build. |
| <a id="cijobtokenscopepoliciesread_container_image"></a>`READ_CONTAINER_IMAGE` | Read Container Image. |
| <a id="cijobtokenscopepoliciesread_deployment"></a>`READ_DEPLOYMENT` | Read Deployment. |
| <a id="cijobtokenscopepoliciesread_environment"></a>`READ_ENVIRONMENT` | Read Environment. |
| <a id="cijobtokenscopepoliciesread_group"></a>`READ_GROUP` | Read Group. |
| <a id="cijobtokenscopepoliciesread_job_artifacts"></a>`READ_JOB_ARTIFACTS` | Read Job Artifacts. |
| <a id="cijobtokenscopepoliciesread_package"></a>`READ_PACKAGE` | Read Package. |
| <a id="cijobtokenscopepoliciesread_pipeline"></a>`READ_PIPELINE` | Read Pipeline. |
| <a id="cijobtokenscopepoliciesread_project"></a>`READ_PROJECT` | Read Project. |
| <a id="cijobtokenscopepoliciesread_release"></a>`READ_RELEASE` | Read Release. |
| <a id="cijobtokenscopepoliciesread_secure_files"></a>`READ_SECURE_FILES` | Read Secure Files. |
| <a id="cijobtokenscopepoliciesread_terraform_state"></a>`READ_TERRAFORM_STATE` | Read Terraform State. |
| <a id="cijobtokenscopepoliciesstop_environment"></a>`STOP_ENVIRONMENT` | Stop Environment. |
| <a id="cijobtokenscopepoliciesupdate_deployment"></a>`UPDATE_DEPLOYMENT` | Update Deployment. |
| <a id="cijobtokenscopepoliciesupdate_environment"></a>`UPDATE_ENVIRONMENT` | Update Environment. |
| <a id="cijobtokenscopepoliciesupdate_pipeline"></a>`UPDATE_PIPELINE` | Update Pipeline. |
| <a id="cijobtokenscopepoliciesupdate_release"></a>`UPDATE_RELEASE` | Update Release. |
### `CiPipelineCreationStatus`
 
| Value | Description |
Loading
Loading
@@ -7,7 +7,7 @@ module AddGroupService
extend ::Gitlab::Utils::Override
 
override :execute
def execute(target_group)
def execute(target_group, policies: [])
super.tap do |response|
audit(project, target_group, current_user) if response.success?
end
Loading
Loading
Loading
Loading
@@ -7,7 +7,7 @@ module AddProjectService
extend ::Gitlab::Utils::Override
 
override :execute
def execute(target_project, direction: :inbound)
def execute(target_project, policies: [], direction: :inbound)
super.tap do |response|
audit(project, target_project, current_user) if direction == :inbound && response.success?
end
Loading
Loading
Loading
Loading
@@ -6,44 +6,48 @@
include GraphqlHelpers
 
describe '#resolve' do
let(:project) do
create(:project, ci_outbound_job_token_scope_enabled: true)
end
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true) }
let_it_be(:project_path) { project.full_path }
 
let(:target_group) { create(:group) }
let_it_be(:target_group) { create(:group) }
let_it_be(:target_group_path) { target_group.full_path }
 
let(:target_group_path) { target_group.full_path }
let(:project_path) { project.full_path }
let(:input) do
{
project_path: project.full_path,
target_path: target_group_path
}
end
let_it_be(:target_project) { create(:project) }
let_it_be(:target_project_path) { target_project.full_path }
 
let(:current_user) { create(:user) }
let_it_be(:policies) { %w[read_project read_package] }
let_it_be(:current_user) { create(:user) }
 
let(:expected_audit_context) do
{
name: event_name,
author: current_user,
scope: project,
target: target_group,
target: target,
message: expected_audit_message
}
end
 
let(:call_add_group) do
ctx = { current_user: current_user }
mutation = graphql_mutation(described_class, input)
GitlabSchema.execute(mutation.query, context: ctx, variables: mutation.variables).to_h
let(:mutation_args) do
{
project_path: project.full_path,
target_path: target.full_path,
job_token_policies: policies,
direction: :inbound
}
end
let(:mutation) do
described_class.new(object: nil, context: query_context, field: nil)
end
 
context 'when adding group validate it triggers audits' do
before do
project.add_maintainer(current_user)
target_group.add_guest(current_user)
end
subject(:resolver) do
mutation.resolve(**mutation_args)
end
context 'when user adds target group to the job token scope' do
let(:target) { target_group }
 
let(:expected_audit_message) do
"Group #{target_group_path} was added to list of allowed groups for #{project_path}"
Loading
Loading
@@ -51,28 +55,52 @@
 
let(:event_name) { 'secure_ci_job_token_group_added' }
 
context 'when user adds target group to the job token scope' do
it 'logs an audit event' do
expect(::Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(expected_audit_context))
call_add_group
end
before_all do
project.add_maintainer(current_user)
target_group.add_guest(current_user)
end
 
context 'and service returns an error' do
it 'does not log an audit event' do
expect_next_instance_of(::Ci::JobTokenScope::AddGroupService) do |service|
expect(service)
.to receive(:validate_group_add!)
.with(project, target_group, current_user)
.and_raise(ActiveRecord::RecordNotUnique)
end
it 'logs an audit event' do
expect(::Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(expected_audit_context))
 
expect(::Gitlab::Audit::Auditor).not_to receive(:audit)
resolver
end
 
call_add_group
context 'when service returns an error' do
it 'does not log an audit event' do
expect_next_instance_of(::Ci::JobTokenScope::AddGroupService) do |service|
expect(service)
.to receive(:validate_group_add!)
.with(project, target_group, current_user)
.and_raise(ActiveRecord::RecordNotUnique)
end
expect(::Gitlab::Audit::Auditor).not_to receive(:audit)
resolver
end
end
end
context 'when user adds target project to the inbound job token scope' do
let(:target) { target_project }
let(:expected_audit_message) do
"Project #{target_project_path} was added to inbound list of allowed projects for #{project_path}"
end
let(:event_name) { 'secure_ci_job_token_project_added' }
before_all do
project.add_maintainer(current_user)
target_project.add_guest(current_user)
end
it 'logs an audit event' do
expect(::Gitlab::Audit::Auditor).to receive(:audit).with(hash_including(expected_audit_context))
resolver
end
end
end
end
Loading
Loading
@@ -45,6 +45,12 @@ module Policies
:update_pipeline,
:update_release
].freeze
class << self
def all_values
(FIXED + ALLOWED).map(&:to_s)
end
end
end
end
end
Loading
Loading
@@ -34,9 +34,13 @@
 
context 'when we add a project' do
let_it_be(:target_project) { create(:project) }
let_it_be(:target_project_path) { target_project.full_path }
 
let(:target_project_path) { target_project.full_path }
let(:mutation_args) { { project_path: project.full_path, target_path: target_project_path } }
let(:policies) { %w[read_project read_package] }
let(:mutation_args) do
{ project_path: project.full_path, target_path: target_project_path, job_token_policies: policies }
end
 
it_behaves_like 'when user is not logged in'
 
Loading
Loading
@@ -52,9 +56,24 @@
end
 
it 'adds target project to the inbound job token scope by default' do
expect do
expect(resolver).to include(ci_job_token_scope: be_present, errors: be_empty)
end.to change { Ci::JobToken::ProjectScopeLink.count }.by(1)
expect { resolver }.to change { Ci::JobToken::ProjectScopeLink.count }.by(1)
expect(resolver).to include(ci_job_token_scope: be_present, errors: be_empty)
project_link = Ci::JobToken::ProjectScopeLink.last
expect(project_link.source_project).to eq(project)
expect(project_link.target_project).to eq(target_project)
expect(project_link.added_by).to eq(current_user)
expect(project_link.job_token_policies).to eq(policies)
end
context 'when the policies provided are invalid' do
let(:policies) { %w[read_issue read_project] }
it 'returns an error message' do
expect(resolver.fetch(:errors))
.to include('Validation failed: Job token policies must be a valid json schema')
end
end
end
 
Loading
Loading
@@ -75,9 +94,13 @@
 
context 'when we add a group' do
let_it_be(:target_group) { create(:group, :private) }
let_it_be(:target_group_path) { target_group.full_path }
 
let(:target_group_path) { target_group.full_path }
let(:mutation_args) { { project_path: project.full_path, target_path: target_group_path } }
let(:policies) { %w[read_project read_package] }
let(:mutation_args) do
{ project_path: project.full_path, target_path: target_group_path, job_token_policies: policies }
end
 
it_behaves_like 'when user is not logged in'
 
Loading
Loading
@@ -93,9 +116,26 @@
end
 
it 'adds target group to the job token scope' do
expect do
expect(resolver).to include(ci_job_token_scope: be_present, errors: be_empty)
end.to change { Ci::JobToken::GroupScopeLink.count }.by(1)
expect { resolver }.to change { Ci::JobToken::GroupScopeLink.count }.by(1)
expect(resolver).to include(ci_job_token_scope: be_present, errors: be_empty)
group_link = Ci::JobToken::GroupScopeLink.last
expect(group_link.source_project).to eq(project)
expect(group_link.target_group).to eq(target_group)
expect(group_link.added_by).to eq(current_user)
expect(group_link.job_token_policies).to eq(policies)
end
context 'when the policies provided are invalid' do
let(:policies) { %w[read_issue read_project] }
it 'returns an error message' do
response = resolver
expect(response.fetch(:errors))
.to include('Validation failed: Job token policies must be a valid json schema')
end
end
end
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['CiJobTokenScopePolicies'], feature_category: :secrets_management do
it 'exposes all policies' do
expect(described_class.values.keys).to contain_exactly(*%w[
ADMIN_CONTAINER_IMAGE
ADMIN_SECURE_FILES
ADMIN_TERRAFORM_STATE
BUILD_CREATE_CONTAINER_IMAGE
BUILD_DESTROY_CONTAINER_IMAGE
BUILD_DOWNLOAD_CODE
BUILD_PUSH_CODE
BUILD_READ_CONTAINER_IMAGE
CREATE_DEPLOYMENT
CREATE_ENVIRONMENT
CREATE_ON_DEMAND_DAST_SCAN
CREATE_PACKAGE
CREATE_RELEASE
DESTROY_CONTAINER_IMAGE
DESTROY_DEPLOYMENT
DESTROY_ENVIRONMENT
DESTROY_PACKAGE
DESTROY_RELEASE
READ_BUILD
READ_CONTAINER_IMAGE
READ_DEPLOYMENT
READ_ENVIRONMENT
READ_GROUP
READ_JOB_ARTIFACTS
READ_PACKAGE
READ_PIPELINE
READ_PROJECT
READ_RELEASE
READ_SECURE_FILES
READ_TERRAFORM_STATE
STOP_ENVIRONMENT
UPDATE_DEPLOYMENT
UPDATE_ENVIRONMENT
UPDATE_PIPELINE
UPDATE_RELEASE
])
end
end
Loading
Loading
@@ -67,20 +67,38 @@
describe 'add!' do
let_it_be(:added_project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:policies) { %w[read_package read_project] }
 
subject { allowlist.add!(added_project, user: user) }
subject(:add_project) { allowlist.add!(added_project, policies: policies, user: user) }
 
[:inbound, :outbound].each do |d|
context "with #{d}" do
let(:direction) { d }
 
it 'adds the project' do
subject
it 'adds the project scope link' do
project_link = add_project
 
expect(allowlist.projects).to contain_exactly(source_project, added_project)
expect(subject.added_by_id).to eq(user.id)
expect(subject.source_project_id).to eq(source_project.id)
expect(subject.target_project_id).to eq(added_project.id)
expect(project_link.added_by_id).to eq(user.id)
expect(project_link.source_project_id).to eq(source_project.id)
expect(project_link.target_project_id).to eq(added_project.id)
expect(project_link.job_token_policies).to eq(policies)
end
context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do
before do
stub_feature_flags(add_policies_to_ci_job_token: false)
end
it 'adds the project scope link but with empty job token policies' do
project_link = add_project
expect(allowlist.projects).to contain_exactly(source_project, added_project)
expect(project_link.added_by_id).to eq(user.id)
expect(project_link.source_project_id).to eq(source_project.id)
expect(project_link.target_project_id).to eq(added_project.id)
expect(project_link.job_token_policies).to eq([])
end
end
end
end
Loading
Loading
@@ -89,16 +107,34 @@
describe 'add_group!' do
let_it_be(:added_group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be(:policies) { %w[read_package read_project] }
 
subject { allowlist.add_group!(added_group, user: user) }
subject(:add_group) { allowlist.add_group!(added_group, policies: policies, user: user) }
 
it 'adds the group' do
subject
it 'adds the group scope link' do
group_link = add_group
 
expect(allowlist.groups).to contain_exactly(added_group)
expect(subject.added_by_id).to eq(user.id)
expect(subject.source_project_id).to eq(source_project.id)
expect(subject.target_group_id).to eq(added_group.id)
expect(group_link.added_by_id).to eq(user.id)
expect(group_link.source_project_id).to eq(source_project.id)
expect(group_link.target_group_id).to eq(added_group.id)
expect(group_link.job_token_policies).to eq(policies)
end
context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do
before do
stub_feature_flags(add_policies_to_ci_job_token: false)
end
it 'adds the group scope link but with empty job token policies' do
group_link = add_group
expect(allowlist.groups).to contain_exactly(added_group)
expect(group_link.added_by_id).to eq(user.id)
expect(group_link.source_project_id).to eq(source_project.id)
expect(group_link.target_group_id).to eq(added_group.id)
expect(group_link.job_token_policies).to eq([])
end
end
end
 
Loading
Loading
Loading
Loading
@@ -3,14 +3,16 @@
require 'spec_helper'
 
RSpec.describe Ci::JobTokenScope::AddGroupOrProjectService, feature_category: :continuous_integration do
subject(:service_execute) { described_class.new(source_project, current_user).execute(target) }
let_it_be(:source_project) { create(:project) }
let_it_be(:target_project) { create(:project) }
let_it_be(:target_group) { create(:group) }
let_it_be(:current_user) { create(:user) }
let_it_be(:policies) { %w[read_project read_package] }
let(:response_success) { ServiceResponse.success }
 
subject(:service_execute) { described_class.new(source_project, current_user).execute(target, policies: policies) }
describe '#execute' do
context 'when group is a target to add' do
let(:target) { target_group }
Loading
Loading
@@ -24,7 +26,7 @@
 
it 'calls AddGroupService to add a target' do
expect(add_group_service_double)
.to receive(:execute).with(target)
.to receive(:execute).with(target, policies: policies)
.and_return(response_success)
 
expect(service_execute).to eq(response_success)
Loading
Loading
@@ -34,6 +36,7 @@
context 'when project is a target to add' do
let(:target) { target_project }
let(:add_project_service_double) { instance_double(::Ci::JobTokenScope::AddProjectService) }
let(:policies) { %w[read_project] }
 
before do
allow(::Ci::JobTokenScope::AddProjectService).to receive(:new)
Loading
Loading
@@ -43,7 +46,7 @@
 
it 'calls AddProjectService to add a target' do
expect(add_project_service_double)
.to receive(:execute).with(target)
.to receive(:execute).with(target, policies: policies)
.and_return(response_success)
 
expect(service_execute).to eq(response_success)
Loading
Loading
Loading
Loading
@@ -8,17 +8,44 @@
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_group) { create(:group, :private) }
let_it_be(:current_user) { create(:user) }
let_it_be(:policies) { %w[read_project read_package] }
 
shared_examples 'adds group' do |_context|
it 'adds the group to the scope' do
expect do
it 'adds the group to the scope', :aggregate_failures do
expect { result }.to change { Ci::JobToken::GroupScopeLink.count }.by(1)
expect(result).to be_success
group_link = result.payload[:group_link]
expect(group_link.source_project).to eq(project)
expect(group_link.target_group).to eq(target_group)
expect(group_link.added_by).to eq(current_user)
expect(group_link.job_token_policies).to eq(policies)
end
context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do
before do
stub_feature_flags(add_policies_to_ci_job_token: false)
end
it 'adds the group to the scope without the policies', :aggregate_failures do
expect { result }.to change { Ci::JobToken::GroupScopeLink.count }.by(1)
expect(result).to be_success
end.to change { Ci::JobToken::GroupScopeLink.count }.by(1)
group_link = result.payload[:group_link]
expect(group_link.source_project).to eq(project)
expect(group_link.target_group).to eq(target_group)
expect(group_link.added_by).to eq(current_user)
expect(group_link.job_token_policies).to eq([])
end
end
end
 
describe '#execute' do
subject(:result) { service.execute(target_group) }
subject(:result) { service.execute(target_group, policies: policies) }
 
it_behaves_like 'editable group job token scope' do
context 'when user has permissions on source and target groups' do
Loading
Loading
Loading
Loading
@@ -7,17 +7,44 @@
let_it_be(:project) { create(:project, ci_outbound_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:target_project) { create(:project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:policies) { %w[read_project read_package] }
 
shared_examples 'adds project' do |context|
it 'adds the project to the scope' do
expect do
it 'adds the project to the scope', :aggregate_failures do
expect { result }.to change { Ci::JobToken::ProjectScopeLink.count }.by(1)
expect(result).to be_success
project_link = result.payload[:project_link]
expect(project_link.source_project).to eq(project)
expect(project_link.target_project).to eq(target_project)
expect(project_link.added_by).to eq(current_user)
expect(project_link.job_token_policies).to eq(policies)
end
context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do
before do
stub_feature_flags(add_policies_to_ci_job_token: false)
end
it 'adds the project to the scope but without the policies', :aggregate_failures do
expect { result }.to change { Ci::JobToken::ProjectScopeLink.count }.by(1)
expect(result).to be_success
end.to change { Ci::JobToken::ProjectScopeLink.count }.by(1)
project_link = result.payload[:project_link]
expect(project_link.source_project).to eq(project)
expect(project_link.target_project).to eq(target_project)
expect(project_link.added_by).to eq(current_user)
expect(project_link.job_token_policies).to eq([])
end
end
end
 
describe '#execute' do
subject(:result) { service.execute(target_project) }
subject(:result) { service.execute(target_project, policies: policies) }
 
it_behaves_like 'editable job token scope' do
context 'when user has permissions on source and target projects' do
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment