summaryrefslogtreecommitdiff
path: root/app/models/ci/job_token/scope.rb
blob: 1aa49b95201aa65b06762b07e18f266ad50ef7ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 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)
        # if the setting is disabled any project is considered to be in scope.
        return true unless source_project.ci_outbound_job_token_scope_enabled?

        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(target_projects, remove_duplicates: false)
      end

      private

      def target_project_ids
        Ci::JobToken::ProjectScopeLink.from_project(source_project).pluck(:target_project_id)
      end

      def target_projects
        [
          Project.id_in(source_project),
          Project.id_in(target_project_ids)
        ]
      end
    end
  end
end