summaryrefslogtreecommitdiff
path: root/app/models/ci/job_token/scope.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/ci/job_token/scope.rb')
-rw-r--r--app/models/ci/job_token/scope.rb43
1 files changed, 43 insertions, 0 deletions
diff --git a/app/models/ci/job_token/scope.rb b/app/models/ci/job_token/scope.rb
new file mode 100644
index 00000000000..42cfdc21d66
--- /dev/null
+++ b/app/models/ci/job_token/scope.rb
@@ -0,0 +1,43 @@
+# 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_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([
+ 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