Commit 92a89f89 authored by Fabio Pitino's avatar Fabio Pitino Committed by Grzegorz Bizon

Scope JobToken to authorized projects [RUN ALL RSPEC] [RUN AS-IF-FOSS]

parent 85e509c2
......@@ -15,6 +15,10 @@ module Ci
next unless job
validate_job!(job)
if job.user && Feature.enabled?(:ci_scoped_job_token, job.project, default_enabled: :yaml)
job.user.set_ci_job_token_scope!(job)
end
end
end
......
# frozen_string_literal: true
# The connection between a source project (which defines the job token scope)
# and a target project which is the one allowed to be accessed by the job token.
module Ci
module JobToken
class ProjectScopeLink < ApplicationRecord
self.table_name = 'ci_job_token_project_scope_links'
belongs_to :source_project, class_name: 'Project'
belongs_to :target_project, class_name: 'Project'
belongs_to :added_by, class_name: 'User'
scope :from_project, ->(project) { where(source_project: project) }
scope :to_project, ->(project) { where(target_project: project) }
validates :source_project, presence: true
validates :target_project, presence: true
validate :not_self_referential_link
private
def not_self_referential_link
return unless source_project && target_project
if source_project == target_project
self.errors.add(:target_project, _("can't be the same as the source project"))
end
end
end
end
end
# frozen_string_literal: true
# This model represents the surface where a CI_JOB_TOKEN can be used.
# A Scope is initialized with the project that the job token belongs to,
# and indicates what are all the other projects that the token could access.
#
# By default a job token can only access its own project, which is the same
# project that defines the scope.
# By adding ScopeLinks to the scope we can allow other projects to be accessed
# by the job token. This works as an allowlist of projects for a job token.
#
# If a project is not included in the scope we should not allow the job user
# to access it since operations using CI_JOB_TOKEN should be considered untrusted.
module Ci
module JobToken
class Scope
attr_reader :source_project
def initialize(project)
@source_project = project
end
def includes?(target_project)
target_project.id == source_project.id ||
Ci::JobToken::ProjectScopeLink.from_project(source_project).to_project(target_project).exists?
end
def all_projects
Project.from_union([
Project.id_in(source_project),
Project.where_exists(
Ci::JobToken::ProjectScopeLink
.from_project(source_project)
.where('projects.id = ci_job_token_project_scope_links.target_project_id'))
], remove_duplicates: false)
end
end
end
end
......@@ -1923,6 +1923,20 @@ class User < ApplicationRecord
confirmed? && !blocked? && !ghost?
end
# This attribute hosts a Ci::JobToken::Scope object which is set when
# the user is authenticated successfully via CI_JOB_TOKEN.
def ci_job_token_scope
Gitlab::SafeRequestStore[ci_job_token_scope_cache_key]
end
def set_ci_job_token_scope!(job)
Gitlab::SafeRequestStore[ci_job_token_scope_cache_key] = Ci::JobToken::Scope.new(job.project)
end
def from_ci_job_token?
ci_job_token_scope.present?
end
protected
# override, from Devise::Validatable
......@@ -2086,6 +2100,10 @@ class User < ApplicationRecord
def update_highest_role_attribute
id
end
def ci_job_token_scope_cache_key
"users:#{id}:ci:job_token_scope"
end
end
User.prepend_mod_with('User')
......@@ -84,6 +84,10 @@ module PolicyActor
def password_expired?
false
end
def from_ci_job_token?
false
end
end
PolicyActor.prepend_mod_with('PolicyActor')
......@@ -75,6 +75,11 @@ class ProjectPolicy < BasePolicy
user.is_a?(DeployToken) && user.has_access_to?(project) && user.write_package_registry
end
desc "If user is authenticated via CI job token then the target project should be in scope"
condition(:project_allowed_for_job_token) do
!@user&.from_ci_job_token? || @user.ci_job_token_scope.includes?(project)
end
with_scope :subject
condition(:forking_allowed) do
@subject.feature_available?(:forking, @user)
......@@ -508,6 +513,8 @@ class ProjectPolicy < BasePolicy
enable :read_project_for_iids
end
rule { ~project_allowed_for_job_token }.prevent_all
rule { can?(:public_access) }.policy do
enable :read_package
enable :read_project
......
---
name: ci_scoped_job_token
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62733
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332272
milestone: '14.0'
type: development
group: group::pipeline execution
default_enabled: false
# frozen_string_literal: true
class CreateCiJobTokenProjectScopeLinks < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
def up
with_lock_retries do
create_table :ci_job_token_project_scope_links, if_not_exists: true do |t|
t.belongs_to :source_project, index: false, null: false, foreign_key: { to_table: :projects, on_delete: :cascade }
t.belongs_to :target_project, null: false, foreign_key: { to_table: :projects, on_delete: :cascade }
t.belongs_to :added_by, foreign_key: { to_table: :users, on_delete: :nullify }
t.datetime_with_timezone :created_at, null: false
t.index [:source_project_id, :target_project_id], unique: true, name: 'i_ci_job_token_project_scope_links_on_source_and_target_project'
end
end
end
def down
with_lock_retries do
drop_table :ci_job_token_project_scope_links, if_exists: true
end
end
end
8c0661a42edbdb79be283df0e88879707ef34ba3fe21b6756b21cd99ea9f05de
\ No newline at end of file
......@@ -10777,6 +10777,23 @@ CREATE SEQUENCE ci_job_artifacts_id_seq
ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY ci_job_artifacts.id;
CREATE TABLE ci_job_token_project_scope_links (
id bigint NOT NULL,
source_project_id bigint NOT NULL,
target_project_id bigint NOT NULL,
added_by_id bigint,
created_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE ci_job_token_project_scope_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE ci_job_token_project_scope_links_id_seq OWNED BY ci_job_token_project_scope_links.id;
CREATE TABLE ci_job_variables (
id bigint NOT NULL,
key character varying NOT NULL,
......@@ -19699,6 +19716,8 @@ ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_i
ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass);
ALTER TABLE ONLY ci_job_token_project_scope_links ALTER COLUMN id SET DEFAULT nextval('ci_job_token_project_scope_links_id_seq'::regclass);
ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_variables_id_seq'::regclass);
ALTER TABLE ONLY ci_minutes_additional_packs ALTER COLUMN id SET DEFAULT nextval('ci_minutes_additional_packs_id_seq'::regclass);
......@@ -20881,6 +20900,9 @@ ALTER TABLE ONLY ci_instance_variables
ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_job_token_project_scope_links
ADD CONSTRAINT ci_job_token_project_scope_links_pkey PRIMARY KEY (id);
ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT ci_job_variables_pkey PRIMARY KEY (id);
......@@ -22335,6 +22357,8 @@ CREATE INDEX finding_evidences_on_vulnerability_occurrence_id ON vulnerability_f
CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
CREATE UNIQUE INDEX i_ci_job_token_project_scope_links_on_source_and_target_project ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id);
CREATE INDEX idx_analytics_devops_adoption_segments_on_namespace_id ON analytics_devops_adoption_segments USING btree (namespace_id);
CREATE INDEX idx_audit_events_part_on_entity_id_desc_author_id_created_at ON ONLY audit_events USING btree (entity_id, entity_type, id DESC, author_id, created_at);
......@@ -22815,6 +22839,10 @@ CREATE INDEX index_ci_job_artifacts_on_project_id ON ci_job_artifacts USING btre
CREATE INDEX index_ci_job_artifacts_on_project_id_for_security_reports ON ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8]));
CREATE INDEX index_ci_job_token_project_scope_links_on_added_by_id ON ci_job_token_project_scope_links USING btree (added_by_id);
CREATE INDEX index_ci_job_token_project_scope_links_on_target_project_id ON ci_job_token_project_scope_links USING btree (target_project_id);
CREATE INDEX index_ci_job_variables_on_job_id ON ci_job_variables USING btree (job_id);
CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables USING btree (key, job_id);
......@@ -26493,6 +26521,9 @@ ALTER TABLE ONLY metrics_dashboard_annotations
ALTER TABLE ONLY wiki_page_slugs
ADD CONSTRAINT fk_rails_358b46be14 FOREIGN KEY (wiki_page_meta_id) REFERENCES wiki_page_meta(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_job_token_project_scope_links
ADD CONSTRAINT fk_rails_35f7f506ce FOREIGN KEY (added_by_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY board_labels
ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
......@@ -26628,6 +26659,9 @@ ALTER TABLE ONLY upcoming_reconciliations
ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_job_token_project_scope_links
ADD CONSTRAINT fk_rails_4b2ee3290b FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
......@@ -26844,6 +26878,9 @@ ALTER TABLE ONLY vulnerability_finding_evidence_headers
ALTER TABLE ONLY geo_hashed_storage_migrated_events
ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_job_token_project_scope_links
ADD CONSTRAINT fk_rails_6904b38465 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY plan_limits
ADD CONSTRAINT fk_rails_69f8b6184f FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE CASCADE;
......@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe API::Internal::AppSec::Dast::SiteValidations do
include AfterNextHelpers
let_it_be(:project) { create(:project) }
let_it_be(:developer) { create(:user, developer_projects: [project]) }
let_it_be(:site_validation) { create(:dast_site_validation, dast_site_token: create(:dast_site_token, project: project)) }
......@@ -66,11 +68,23 @@ RSpec.describe API::Internal::AppSec::Dast::SiteValidations do
context 'when site validation and job are associated with different projects' do
let_it_be(:job) { create(:ci_build, :running, user: developer) }
it 'returns 400 and a contextual error message', :aggregate_failures do
it 'returns 403', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to eq('message' => '400 Bad request - Project mismatch')
expect(response).to have_gitlab_http_status(:forbidden)
end
context 'when the job project belongs to the same job token scope' do
before do
allow_next(Ci::JobToken::Scope).to receive(:includes?).with(project).and_return(true)
end
it 'returns 400 and a contextual error message', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response).to eq('message' => '400 Bad request - Project mismatch')
end
end
end
......
......@@ -3,18 +3,25 @@
require 'spec_helper'
RSpec.describe API::Triggers do
include AfterNextHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :auto_devops, creator: user) }
let_it_be(:other_project) { create(:project) }
describe 'POST /projects/:project_id/trigger/pipeline' do
context 'when triggering a pipeline from a job token' do
let(:other_job) { create(:ci_build, :running, user: other_user) }
let(:other_job) { create(:ci_build, :running, user: other_user, project: other_project) }
let(:params) { { ref: 'refs/heads/other-branch' } }
subject do
post api("/projects/#{project.id}/ref/master/trigger/pipeline?token=#{other_job.token}"), params: params
end
before do
allow_next(Ci::JobToken::Scope).to receive(:includes?).with(project).and_return(true)
end
context 'without user' do
let(:other_user) { nil }
......@@ -70,6 +77,21 @@ RSpec.describe API::Triggers do
)
end
context 'when project is not in the job token scope' do
before do
allow_next(Ci::JobToken::Scope)
.to receive(:includes?)
.with(project)
.and_return(false)
end
it 'forbids to create a pipeline' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when build is complete' do
before do
other_job.success
......
......@@ -38009,6 +38009,9 @@ msgstr ""
msgid "can't be enabled because signed commits are required for this project"
msgstr ""
msgid "can't be the same as the source project"
msgstr ""
msgid "can't include: %{invalid_storages}"
msgstr ""
......
# frozen_string_literal: true
FactoryBot.define do
factory :ci_job_token_project_scope_link, class: 'Ci::JobToken::ProjectScopeLink' do
association :source_project, factory: :project
association :target_project, factory: :project
association :added_by, factory: :user
end
end
......@@ -66,6 +66,7 @@ RSpec.describe 'factories' do
# associations must be unique and cannot be reused, or the factory default
# is being mutated.
skip_factory_defaults = %i[
ci_job_token_project_scope_link
evidence
exported_protected_branch
fork_network_member
......
......@@ -2,7 +2,8 @@
require 'spec_helper'
RSpec.describe Ci::AuthJobFinder do
let_it_be(:job, reload: true) { create(:ci_build, status: :running) }
let_it_be(:user, reload: true) { create(:user) }
let_it_be(:job, reload: true) { create(:ci_build, status: :running, user: user) }
let(:token) { job.token }
......@@ -55,10 +56,31 @@ RSpec.describe Ci::AuthJobFinder do
describe '#execute' do
subject(:execute) { finder.execute }
before do
job.success!
context 'when job is not running' do
before do
job.success!
end
it { is_expected.to be_nil }
end
it { is_expected.to be_nil }
context 'when job is running', :request_store do
it 'sets ci_job_token_scope on the job user', :aggregate_failures do
expect(subject).to eq(job)
expect(subject.user).to be_from_ci_job_token
expect(subject.user.ci_job_token_scope.source_project).to eq(job.project)
end
context 'when feature flag ci_scoped_job_token is disabled' do
before do
stub_feature_flags(ci_scoped_job_token: false)
end
it 'does not set ci_job_token_scope on the job user' do
expect(subject).to eq(job)
expect(subject.user).not_to be_from_ci_job_token
end
end
end
end
end
......@@ -50,7 +50,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
shared_examples 'find user from job token' do |without_job_token_allowed|
context 'when route is allowed to be authenticated' do
context 'when route is allowed to be authenticated', :request_store do
let(:route_authentication_setting) { { job_token_allowed: true } }
context 'for an invalid token' do
......@@ -68,6 +68,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
it 'return user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
expect(subject).to be_from_ci_job_token
expect(subject.ci_job_token_scope.source_project).to eq(job.project)
end
end
......@@ -81,7 +83,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
end
context 'when route is not allowed to be authenticated' do
context 'when route is not allowed to be authenticated', :request_store do
let(:route_authentication_setting) { { job_token_allowed: false } }
context 'with a running job' do
......@@ -96,6 +98,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
it 'returns the user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
expect(subject).to be_from_ci_job_token
expect(subject.ci_job_token_scope.source_project).to eq(job.project)
end
else
it 'returns nil' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::JobToken::ProjectScopeLink do
it { is_expected.to belong_to(:source_project) }
it { is_expected.to belong_to(:target_project) }
it { is_expected.to belong_to(:added_by) }
let_it_be(:project) { create(:project) }
describe 'unique index' do
let!(:link) { create(:ci_job_token_project_scope_link) }
it 'raises an error' do
expect do
create(:ci_job_token_project_scope_link,
source_project: link.source_project,
target_project: link.target_project)
end.to raise_error(ActiveRecord::RecordNotUnique)
end
end
describe 'validations' do
it 'must have a source project', :aggregate_failures do
link = build(:ci_job_token_project_scope_link, source_project: nil)
expect(link).not_to be_valid
expect(link.errors[:source_project]).to contain_exactly("can't be blank")
end
it 'must have a target project', :aggregate_failures do
link = build(:ci_job_token_project_scope_link, target_project: nil)
expect(link).not_to be_valid
expect(link.errors[:target_project]).to contain_exactly("can't be blank")
end
it 'must have a target project different than source project', :aggregate_failures do
link = build(:ci_job_token_project_scope_link, target_project: project, source_project: project)
expect(link).not_to be_valid
expect(link.errors[:target_project]).to contain_exactly("can't be the same as the source project")
end
end
describe '.from_project' do
subject { described_class.from_project(project) }
let!(:source_link) { create(:ci_job_token_project_scope_link, source_project: project) }
let!(:target_link) { create(:ci_job_token_project_scope_link, target_project: project) }
it 'returns only the links having the given source project' do
expect(subject).to contain_exactly(source_link)
end
end
describe '.to_project' do
subject { described_class.to_project(project) }
let!(:source_link) { create(:ci_job_token_project_scope_link, source_project: project) }
let!(:target_link) { create(:ci_job_token_project_scope_link, target_project: project) }
it 'returns only the links having the given target project' do
expect(subject).to contain_exactly(target_link)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::JobToken::Scope do
let_it_be(:project) { create(:project) }
let(:scope) { described_class.new(project) }
describe '#all_projects' do
subject(:all_projects) { scope.all_projects }
context 'when no projects are added to the scope' do
it 'returns the project defining the scope' do
expect(all_projects).to contain_exactly(project)
end
end
context 'when other projects are added to the scope' do
let_it_be(:scoped_project) { create(:project) }
let_it_be(:unscoped_project) { create(:project) }
let!(:link_in_scope) { create(:ci_job_token_project_scope_link, source_project: project, target_project: scoped_project) }
let!(:link_out_of_scope) { create(:ci_job_token_project_scope_link, target_project: unscoped_project) }
it 'returns all projects that can be accessed from a given scope' do
expect(subject).to contain_exactly(project, scoped_project)
end
end
end
describe 'includes?' do
subject { scope.includes?(target_project) }
context 'when param is the project defining the scope' do
let(:target_project) { project }
it { is_expected.to be_truthy }
end
context 'when param is a project in scope' do
let(:target_link) { create(:ci_job_token_project_scope_link, source_project: project) }
let(:target_project) { target_link.target_project }
it { is_expected.to be_truthy }
end
context 'when param is a project in another scope' do
let(:scope_link) { create(:ci_job_token_project_scope_link) }
let(:target_project) { scope_link.target_project }
it { is_expected.to be_falsey }
end
end
end
......@@ -1385,4 +1385,53 @@ RSpec.describe ProjectPolicy do
end
end
end
describe 'when user is authenticated via CI_JOB_TOKEN', :request_store do
let(:current_user) { developer }
let(:job) { build_stubbed(:ci_build, project: scope_project, user: current_user) }
before do
current_user.set_ci_job_token_scope!(job)
end
context 'when accessing a private project' do
let(:project) { private_project }
context 'when the job token comes from the same project' do
let(:scope_project) { project }
it { is_expected.to be_allowed(:developer_access) }
end
context 'when the job token comes from another project' do
let(:scope_project) { create(:project, :private) }
before do
scope_project.add_developer(current_user)
end
it { is_expected.to be_disallowed(:guest_access) }
end
end
context 'when accessing a public project' do
let(:project) { public_project }
context 'when the job token comes from the same project' do
let(:scope_project) { project }
it { is_expected.to be_allowed(:developer_access) }
end
context 'when the job token comes from another project' do
let(:scope_project) { create(:project, :private) }
before do
scope_project.add_developer(current_user)
end
it { is_expected.to be_disallowed(:public_access) }
end
end
end
end
......@@ -18,7 +18,7 @@ RSpec.describe API::GenericPackages do
let_it_be(:project_deploy_token_wo) { create(:project_deploy_token, deploy_token: deploy_token_wo, project: project) }
let(:user) { personal_access_token.user }
let(:ci_build) { create(:ci_build, :running, user: user) }
let(:ci_build) { create(:ci_build, :running, user: user, project: project) }
def auth_header
return {} if user_role == :anonymous
......
......@@ -11,7 +11,7 @@ RSpec.describe API::GoProxy do
let_it_be(:base) { "#{Settings.build_gitlab_go_url}/#{project.full_path}" }
let_it_be(:oauth) { create :oauth_access_token, scopes: 'api', resource_owner: user }
let_it_be(:job) { create :ci_build, user: user, status: :running }
let_it_be(:job) { create :ci_build, user: user, status: :running, project: project }
let_it_be(:pa_token) { create :personal_access_token, user: user }
let_it_be(:modules) do
......
......@@ -15,7 +15,7 @@ RSpec.describe API::MavenPackages do
let_it_be(:package_file) { package.package_files.with_file_name_like('%.xml').first }
let_it_be(:jar_file) { package.package_files.with_file_name_like('%.jar').first }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true, write_package_registry: true) }
......
......@@ -78,7 +78,7 @@ RSpec.describe API::NpmProjectPackages do
context 'with a job token for a different user' do
let_it_be(:other_user) { create(:user) }
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user) }
let_it_be_with_reload(:other_job) { create(:ci_build, :running, user: other_user, project: project) }
let(:headers) { build_token_auth_header(other_job.token) }
......
......@@ -192,7 +192,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'job token for package uploads', authorize_endpoint: true do
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
end
it_behaves_like 'rejects nuget access with unknown target id'
......@@ -260,7 +260,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'deploy token for package uploads'
it_behaves_like 'job token for package uploads' do
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
end
it_behaves_like 'rejects nuget access with unknown target id'
......
......@@ -13,7 +13,7 @@ RSpec.describe API::PypiPackages do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
let(:headers) { {} }
context 'simple API endpoint' do
......
......@@ -775,7 +775,7 @@ RSpec.describe API::Releases do
end
context 'when using JOB-TOKEN auth' do
let(:job) { create(:ci_build, user: maintainer) }
let(:job) { create(:ci_build, user: maintainer, project: project) }
let(:params) do
{
name: 'Another release',
......
......@@ -10,7 +10,7 @@ RSpec.describe API::RubygemPackages do
let_it_be_with_reload(:project) { create(:project) }
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
let_it_be(:headers) { {} }
......
......@@ -12,7 +12,7 @@ RSpec.describe API::Terraform::Modules::V1::Packages do
let_it_be(:package) { create(:terraform_module_package, project: project) }
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
......
......@@ -883,10 +883,10 @@ RSpec.describe 'Git HTTP requests' do
context 'when admin mode is enabled', :enable_admin_mode do
it_behaves_like 'can download code only'
it 'downloads from other project get status 403' do
it 'downloads from other project get status 404' do
clone_get "#{other_project.full_path}.git", user: 'gitlab-ci-token', password: build.token
expect(response).to have_gitlab_http_status(:forbidden)
expect(response).to have_gitlab_http_status(:not_found)
end
end
......
......@@ -569,7 +569,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
# I'm not sure what this tests that is different from the previous test
it_behaves_like 'LFS http 403 response'
it_behaves_like 'LFS http 404 response'
end
end
......@@ -1043,7 +1043,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
# I'm not sure what this tests that is different from the previous test
it_behaves_like 'LFS http 403 response'
it_behaves_like 'LFS http 404 response'
end
end
......
......@@ -8,11 +8,11 @@ RSpec.shared_context 'conan api setup' do
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:user) { personal_access_token.user }
let_it_be(:base_secret) { SecureRandom.base64(64) }
let_it_be(:job) { create(:ci_build, :running, user: user) }
let_it_be(:job_token) { job.token }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let(:project) { package.project }
let(:job) { create(:ci_build, :running, user: user, project: project) }
let(:job_token) { job.token }
let(:auth_token) { personal_access_token.token }
let(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
......
......@@ -11,7 +11,7 @@ RSpec.shared_context 'npm api setup' do
let_it_be(:package, reload: true) { create(:npm_package, project: project, name: "@#{group.path}/scoped_package") }
let_it_be(:token) { create(:oauth_access_token, scopes: 'api', resource_owner: user) }
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running) }
let_it_be(:job, reload: true) { create(:ci_build, user: user, status: :running, project: project) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
......
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