diff --git a/app/graphql/types/ci/job_token_scope/allowlist_entry_type.rb b/app/graphql/types/ci/job_token_scope/allowlist_entry_type.rb index 77e795f5c7435a1d7536073fb6a687aaaac303da..3e976ef69193516c301a11f90ac8b5e8b1131f7d 100644 --- a/app/graphql/types/ci/job_token_scope/allowlist_entry_type.rb +++ b/app/graphql/types/ci/job_token_scope/allowlist_entry_type.rb @@ -66,7 +66,7 @@ def direction def job_token_policies return unless Feature.enabled?(:add_policies_to_ci_job_token, object.source_project) - object.job_token_policies + object.job_token_policies&.map(&:to_sym) end end # rubocop: enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/ci/job_token_scope/job_token_policy_category_type.rb b/app/graphql/types/ci/job_token_scope/job_token_policy_category_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..31a013f8888d341b0f402438adbd98c7fb6ee71e --- /dev/null +++ b/app/graphql/types/ci/job_token_scope/job_token_policy_category_type.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Types + module Ci + module JobTokenScope + # rubocop: disable Graphql/AuthorizeTypes -- this is static data + class JobTokenPolicyCategoryType < BaseObject + graphql_name 'JobTokenPolicyCategory' + description 'Job token policy category type' + + field :description, GraphQL::Types::String, description: 'Description of the category.' + field :policies, [Types::Ci::JobTokenScope::JobTokenPolicyType], description: 'Policies of the category.' + field :text, GraphQL::Types::String, description: 'Display text of the category.' + field :value, Types::Ci::JobTokenScope::PolicyCategoriesEnum, description: 'Value of the category.' + end + # rubocop: enable Graphql/AuthorizeTypes + end + end +end diff --git a/app/graphql/types/ci/job_token_scope/job_token_policy_type.rb b/app/graphql/types/ci/job_token_scope/job_token_policy_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..b31255550ff4a6dc6f8cfa9a6113441a7d9f8907 --- /dev/null +++ b/app/graphql/types/ci/job_token_scope/job_token_policy_type.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Types + module Ci + module JobTokenScope + # rubocop: disable Graphql/AuthorizeTypes -- this is static data + class JobTokenPolicyType < BaseObject + graphql_name 'JobTokenPolicy' + description 'Job token policy' + + field :description, GraphQL::Types::String, description: 'Description of the job token policy.' + field :text, GraphQL::Types::String, description: 'Display text of the job token policy.' + field :type, Types::Ci::JobTokenScope::PolicyTypesEnum, description: 'Job token policy type.' + field :value, Types::Ci::JobTokenScope::PoliciesEnum, description: 'Value of the job token policy.' + end + # rubocop: enable Graphql/AuthorizeTypes + end + end +end diff --git a/app/graphql/types/ci/job_token_scope/policies_enum.rb b/app/graphql/types/ci/job_token_scope/policies_enum.rb index 88ed8612f54d4f9b9ce4f44e3477b2fe9e202a94..be4abc61d5a71f103ef85199752a733be1717881 100644 --- a/app/graphql/types/ci/job_token_scope/policies_enum.rb +++ b/app/graphql/types/ci/job_token_scope/policies_enum.rb @@ -7,8 +7,8 @@ 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 + ::Ci::JobToken::Policies.all_policies.each do |policy| + value policy[:value].to_s.upcase, value: policy[:value], description: policy[:description] end end end diff --git a/app/graphql/types/ci/job_token_scope/policy_categories_enum.rb b/app/graphql/types/ci/job_token_scope/policy_categories_enum.rb new file mode 100644 index 0000000000000000000000000000000000000000..39683b3d6ca0ce4c4788281841fd7967650609c6 --- /dev/null +++ b/app/graphql/types/ci/job_token_scope/policy_categories_enum.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Types + module Ci + module JobTokenScope + class PolicyCategoriesEnum < BaseEnum + graphql_name 'CiJobTokenScopePolicyCategoriesTypes' + description 'CI_JOB_TOKEN policy category type' + + ::Ci::JobToken::Policies::POLICIES_BY_CATEGORY.each do |category| + value category[:value].to_s.upcase, value: category[:value], description: category[:description] + end + end + end + end +end diff --git a/app/graphql/types/ci/job_token_scope/policy_types_enum.rb b/app/graphql/types/ci/job_token_scope/policy_types_enum.rb new file mode 100644 index 0000000000000000000000000000000000000000..420dfb46d71bc16fc0d4f43cc919a18761a64b99 --- /dev/null +++ b/app/graphql/types/ci/job_token_scope/policy_types_enum.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Types + module Ci + module JobTokenScope + class PolicyTypesEnum < BaseEnum + graphql_name 'CiJobTokenScopePolicyTypes' + description 'CI_JOB_TOKEN policy type' + + value 'READ', value: :read, description: 'Read-only access to the resource.' + value 'ADMIN', value: :admin, description: 'Admin access to the resource.' + end + end + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 781da8778513efc5d12242cae6b912285bfd6a07..e7637e2c7e8ab333185ef048f7d34e82eb55dded 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -245,6 +245,10 @@ class QueryType < ::Types::BaseObject description: 'Check if a feature flag is enabled', resolver: Resolvers::FeatureFlagResolver + field :job_token_policies_by_category, [::Types::Ci::JobTokenScope::JobTokenPolicyCategoryType], + description: 'List of job token policies for use with fine-grained permissions on CI/CD job allowlist.', + experiment: { milestone: '17.7' } + def design_management DesignManagementObject.new(nil) end @@ -298,6 +302,10 @@ def ci_pipeline_stage(id:) stage end + + def job_token_policies_by_category + ::Ci::JobToken::Policies::POLICIES_BY_CATEGORY + end end end diff --git a/app/validators/json_schemas/ci_job_token_policies.json b/app/validators/json_schemas/ci_job_token_policies.json index 3da0d8b309ac559544ce110e2371567564195a94..b5d2d37aa267c63b1e0a3314952b892e5ae42dc1 100644 --- a/app/validators/json_schemas/ci_job_token_policies.json +++ b/app/validators/json_schemas/ci_job_token_policies.json @@ -5,41 +5,22 @@ "items": { "type": "string", "enum": [ - "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_containers", + "admin_containers", + "read_deployments", + "admin_deployments", + "read_environments", + "admin_environments", + "read_jobs", + "admin_jobs", + "read_packages", + "admin_packages", + "read_releases", + "admin_releases", "read_secure_files", + "admin_secure_files", "read_terraform_state", - "stop_environment", - "update_deployment", - "update_environment", - "update_pipeline", - "update_release" + "admin_terraform_state" ] }, "uniqueItems": true, diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 004652f747cafad47858cbd3e8a4489041b7f75c..d39c335c6984814aa2845d829b39460a7f29f451 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -725,6 +725,16 @@ Returns [`Iteration`](#iteration). | ---- | ---- | ----------- | | `id` | [`IterationID!`](#iterationid) | Find an iteration by its ID. | +### `Query.jobTokenPoliciesByCategory` + +List of job token policies for use with fine-grained permissions on CI/CD job allowlist. + +DETAILS: +**Introduced** in GitLab 17.7. +**Status**: Experiment. + +Returns [`[JobTokenPolicyCategory!]`](#jobtokenpolicycategory). + ### `Query.jobs` All jobs on this GitLab instance. Returns an empty result for users without administrator access. @@ -26798,6 +26808,32 @@ Represents the Geo replication and verification state of a job_artifact. | `readJobArtifacts` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_job_artifacts` on this resource. | | `updateBuild` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_build` on this resource. | +### `JobTokenPolicy` + +Job token policy. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `description` | [`String`](#string) | Description of the job token policy. | +| `text` | [`String`](#string) | Display text of the job token policy. | +| `type` | [`CiJobTokenScopePolicyTypes`](#cijobtokenscopepolicytypes) | Job token policy type. | +| `value` | [`CiJobTokenScopePolicies`](#cijobtokenscopepolicies) | Value of the job token policy. | + +### `JobTokenPolicyCategory` + +Job token policy category type. + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `description` | [`String`](#string) | Description of the category. | +| `policies` | [`[JobTokenPolicy!]`](#jobtokenpolicy) | Policies of the category. | +| `text` | [`String`](#string) | Display text of the category. | +| `value` | [`CiJobTokenScopePolicyCategoriesTypes`](#cijobtokenscopepolicycategoriestypes) | Value of the category. | + ### `Kas` #### Fields @@ -37879,41 +37915,46 @@ CI_JOB_TOKEN policy. | Value | Description | | ----- | ----------- | -| `ADMIN_CONTAINER_IMAGE` | Admin Container Image. | -| `ADMIN_SECURE_FILES` | Admin Secure Files. | -| `ADMIN_TERRAFORM_STATE` | Admin Terraform State. | -| `BUILD_CREATE_CONTAINER_IMAGE` | Build Create Container Image. | -| `BUILD_DESTROY_CONTAINER_IMAGE` | Build Destroy Container Image. | -| `BUILD_DOWNLOAD_CODE` | Build Download Code. | -| `BUILD_PUSH_CODE` | Build Push Code. | -| `BUILD_READ_CONTAINER_IMAGE` | Build Read Container Image. | -| `CREATE_DEPLOYMENT` | Create Deployment. | -| `CREATE_ENVIRONMENT` | Create Environment. | -| `CREATE_ON_DEMAND_DAST_SCAN` | Create On Demand Dast Scan. | -| `CREATE_PACKAGE` | Create Package. | -| `CREATE_RELEASE` | Create Release. | -| `DESTROY_CONTAINER_IMAGE` | Destroy Container Image. | -| `DESTROY_DEPLOYMENT` | Destroy Deployment. | -| `DESTROY_ENVIRONMENT` | Destroy Environment. | -| `DESTROY_PACKAGE` | Destroy Package. | -| `DESTROY_RELEASE` | Destroy Release. | -| `READ_BUILD` | Read Build. | -| `READ_CONTAINER_IMAGE` | Read Container Image. | -| `READ_DEPLOYMENT` | Read Deployment. | -| `READ_ENVIRONMENT` | Read Environment. | -| `READ_GROUP` | Read Group. | -| `READ_JOB_ARTIFACTS` | Read Job Artifacts. | -| `READ_PACKAGE` | Read Package. | -| `READ_PIPELINE` | Read Pipeline. | -| `READ_PROJECT` | Read Project. | -| `READ_RELEASE` | Read Release. | -| `READ_SECURE_FILES` | Read Secure Files. | -| `READ_TERRAFORM_STATE` | Read Terraform State. | -| `STOP_ENVIRONMENT` | Stop Environment. | -| `UPDATE_DEPLOYMENT` | Update Deployment. | -| `UPDATE_ENVIRONMENT` | Update Environment. | -| `UPDATE_PIPELINE` | Update Pipeline. | -| `UPDATE_RELEASE` | Update Release. | +| `ADMIN_CONTAINERS` | Admin container images in a project. | +| `ADMIN_DEPLOYMENTS` | Admin deployments in a project. | +| `ADMIN_ENVIRONMENTS` | Admin + Stop environments in a project. | +| `ADMIN_JOBS` | Read job metadata, upload artifacts and update the pipeline status. | +| `ADMIN_PACKAGES` | Admin packages. | +| `ADMIN_RELEASES` | Admin releases in a project. | +| `ADMIN_SECURE_FILES` | Admin secure files in a project. | +| `ADMIN_TERRAFORM_STATE` | Admin terraform state files/versions. | +| `READ_CONTAINERS` | Read container images in a project. | +| `READ_DEPLOYMENTS` | Read deployments in a project. | +| `READ_ENVIRONMENTS` | Read environments in a project. | +| `READ_JOBS` | Read job metadata and artifacts. | +| `READ_PACKAGES` | Read packages. | +| `READ_RELEASES` | Read releases in a project. | +| `READ_SECURE_FILES` | Read secure files in a project. | +| `READ_TERRAFORM_STATE` | Read terraform state files/version. | + +### `CiJobTokenScopePolicyCategoriesTypes` + +CI_JOB_TOKEN policy category type. + +| Value | Description | +| ----- | ----------- | +| `CONTAINERS` | Containers category. | +| `DEPLOYMENTS` | Deployments category. | +| `ENVIRONMENTS` | Environments category. | +| `JOBS` | Jobs category. | +| `PACKAGES` | Packages category. | +| `RELEASES` | Releases category. | +| `SECURE_FILES` | Secure files category. | +| `TERRAFORM_STATE` | Terraform state category. | + +### `CiJobTokenScopePolicyTypes` + +CI_JOB_TOKEN policy type. + +| Value | Description | +| ----- | ----------- | +| `ADMIN` | Admin access to the resource. | +| `READ` | Read-only access to the resource. | ### `CiRunnerAccessLevel` diff --git a/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_group_or_project_spec.rb b/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_group_or_project_spec.rb index 13a9bbc8ee03c9b6c8fdda7c2288a241ac20d777..92b086f568d6f712e080de95ec8f5ba7218909ba 100644 --- a/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_group_or_project_spec.rb +++ b/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_group_or_project_spec.rb @@ -15,7 +15,7 @@ let_it_be(:target_project) { create(:project) } let_it_be(:target_project_path) { target_project.full_path } - let_it_be(:policies) { %w[read_project read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } let_it_be(:current_user) { create(:user) } @@ -51,7 +51,7 @@ let(:expected_audit_message) do "Group #{target_group_path} was added to list of allowed groups for #{project_path}, " \ - "with job token permissions: read_project, read_package" + "with job token permissions: read_containers, read_packages" end let(:event_name) { 'secure_ci_job_token_group_added' } @@ -104,7 +104,7 @@ let(:expected_audit_message) do "Project #{target_project_path} was added to inbound list of allowed projects for #{project_path}, " \ - "with job token permissions: read_project, read_package" + "with job token permissions: read_containers, read_packages" end let(:event_name) { 'secure_ci_job_token_project_added' } diff --git a/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_project_spec.rb b/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_project_spec.rb index fef9eaa927fadaff58f1fe0d69b86195ecbb7743..7f7286d9857d2981b20910005247a8806bb7496d 100644 --- a/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_project_spec.rb +++ b/ee/spec/graphql/ee/mutations/ci/job_token_scope/add_project_spec.rb @@ -16,7 +16,7 @@ let_it_be(:target_project) { create(:project) } let_it_be(:target_project_path) { target_project.full_path } - let_it_be(:policies) { %w[read_project read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } let_it_be(:current_user) { create(:user, maintainer_of: project, guest_of: target_project) } diff --git a/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_group_spec.rb b/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_group_spec.rb index 90bfa41476c378b699ad70baff66671416507e69..57ecd73105c225118701ba4ac512bfa569da8ba1 100644 --- a/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_group_spec.rb +++ b/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_group_spec.rb @@ -16,7 +16,7 @@ create(:ci_job_token_group_scope_link, source_project: project, target_group: target_group, - job_token_policies: %w[read_group read_project] + job_token_policies: %w[read_containers read_packages] ) end @@ -51,7 +51,7 @@ context 'when user removes target group to the job token scope' do let(:expected_audit_message) do "Group #{target_group_path} was removed from list of allowed groups for #{project_path}, " \ - "with job token permissions: read_group, read_project" + "with job token permissions: read_containers, read_packages" end let(:event_name) { 'secure_ci_job_token_group_removed' } diff --git a/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_project_spec.rb b/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_project_spec.rb index c1ba6da18bbfaca935a656e1ed74691f752a9045..20db1a312ed9a2fd5cab123a02f507a1cea653e0 100644 --- a/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_project_spec.rb +++ b/ee/spec/graphql/ee/mutations/ci/job_token_scope/remove_project_spec.rb @@ -17,7 +17,7 @@ direction: :inbound, source_project: project, target_project: target_project, - job_token_policies: %w[read_project read_package] + job_token_policies: %w[read_containers read_packages] ) end @@ -59,7 +59,7 @@ let(:expected_audit_message) do "Project #{target_project_path} was removed from inbound list of allowed projects for #{project_path}, " \ - "with job token permissions: read_project, read_package" + "with job token permissions: read_containers, read_packages" end let(:event_name) { 'secure_ci_job_token_project_removed' } diff --git a/ee/spec/services/ee/ci/job_token_scope/add_group_service_spec.rb b/ee/spec/services/ee/ci/job_token_scope/add_group_service_spec.rb index 337c6bc0e2e3372e6d97c3bf5721ddd23d26026c..be3884a5a6fe3155962a4e0765a3baf5abe6a60b 100644 --- a/ee/spec/services/ee/ci/job_token_scope/add_group_service_spec.rb +++ b/ee/spec/services/ee/ci/job_token_scope/add_group_service_spec.rb @@ -8,14 +8,14 @@ let_it_be(:current_user) { create(:user, maintainer_of: project, developer_of: target_group) } - let_it_be(:policies) { %w[read_group read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } subject(:service_result) { described_class.new(project, current_user).execute(target_group, policies: policies) } describe '#execute' do let(:expected_audit_message) do "Group #{target_group.full_path} was added to list of allowed groups for #{project.full_path}, " \ - "with job token permissions: read_group, read_package" + "with job token permissions: read_containers, read_packages" end let(:audit_event) do diff --git a/ee/spec/services/ee/ci/job_token_scope/add_project_service_spec.rb b/ee/spec/services/ee/ci/job_token_scope/add_project_service_spec.rb index de65f035a1b857c5c6704976317bcb744eefbbae..ce33ee00f39f703afa53890742b7aa0b669d46af 100644 --- a/ee/spec/services/ee/ci/job_token_scope/add_project_service_spec.rb +++ b/ee/spec/services/ee/ci/job_token_scope/add_project_service_spec.rb @@ -8,7 +8,7 @@ let_it_be(:current_user) { create(:user, maintainer_of: project, developer_of: target_project) } - let_it_be(:policies) { %w[read_project read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } let_it_be(:direction) { :inbound } @@ -20,7 +20,7 @@ context 'when the direction is inbound' do let(:expected_audit_message) do "Project #{target_project.full_path} was added to inbound list of allowed projects for #{project.full_path}, " \ - "with job token permissions: read_project, read_package" + "with job token permissions: read_containers, read_packages" end let(:audit_event) do diff --git a/ee/spec/services/ee/ci/job_token_scope/remove_group_service_spec.rb b/ee/spec/services/ee/ci/job_token_scope/remove_group_service_spec.rb index 33a17cb77810ed50e9a5cf2e189baa30e5d83fe6..dbe43c999f5f0e329688402078e49330a826aa7e 100644 --- a/ee/spec/services/ee/ci/job_token_scope/remove_group_service_spec.rb +++ b/ee/spec/services/ee/ci/job_token_scope/remove_group_service_spec.rb @@ -8,7 +8,7 @@ let_it_be(:current_user) { create(:user, maintainer_of: project, developer_of: target_group) } - let_it_be(:policies) { %w[read_group read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } let_it_be(:group_link) do create(:ci_job_token_group_scope_link, @@ -23,7 +23,7 @@ describe '#execute' do let(:expected_audit_message) do "Group #{target_group.full_path} was removed from list of allowed groups for #{project.full_path}, " \ - "with job token permissions: read_group, read_package" + "with job token permissions: read_containers, read_packages" end let(:audit_event) do diff --git a/ee/spec/services/ee/ci/job_token_scope/remove_project_service_spec.rb b/ee/spec/services/ee/ci/job_token_scope/remove_project_service_spec.rb index 6328aee54c0e737899d37ec26994d3263d906575..5cd8f249d62d068835866b817c07c86d2cea73b9 100644 --- a/ee/spec/services/ee/ci/job_token_scope/remove_project_service_spec.rb +++ b/ee/spec/services/ee/ci/job_token_scope/remove_project_service_spec.rb @@ -8,7 +8,7 @@ let_it_be(:current_user) { create(:user, maintainer_of: project, developer_of: target_project) } - let_it_be(:policies) { %w[read_project read_package] } + let_it_be(:policies) { %w[read_containers read_packages] } let_it_be(:direction) { :inbound } @@ -29,7 +29,7 @@ let(:expected_audit_message) do "Project #{target_project.full_path} was removed from inbound list of allowed projects " \ - "for #{project.full_path}, with job token permissions: read_project, read_package" + "for #{project.full_path}, with job token permissions: read_containers, read_packages" end let(:audit_event) do diff --git a/ee/spec/services/ee/ci/job_token_scope/update_policies_service_spec.rb b/ee/spec/services/ee/ci/job_token_scope/update_policies_service_spec.rb index 9319968e10b317f3fc63f3468480d6e0713f607e..ba07f2b18c85e7113ace76ef33a7c46d3b1d18ba 100644 --- a/ee/spec/services/ee/ci/job_token_scope/update_policies_service_spec.rb +++ b/ee/spec/services/ee/ci/job_token_scope/update_policies_service_spec.rb @@ -8,7 +8,7 @@ let_it_be(:current_user) { create(:user, maintainer_of: project, developer_of: target_project) } - let(:policies) { %w[read_project read_container_image] } + let(:policies) { %w[read_containers read_packages] } subject(:service_result) do described_class.new(project, current_user).execute(target_project, policies) @@ -20,7 +20,7 @@ create(:ci_job_token_project_scope_link, source_project: project, target_project: target_project, - job_token_policies: %w[read_project read_package], + job_token_policies: %w[read_containers read_packages], direction: :inbound ) end @@ -31,7 +31,7 @@ author: current_user, scope: project, target: target_project, - message: 'CI job token policies updated to: read_project, read_container_image' + message: 'CI job token policies updated to: read_containers, read_packages' } end diff --git a/lib/ci/job_token/policies.rb b/lib/ci/job_token/policies.rb index b48926cd7555dbd770c6d1c33707e8ec1621faa9..c746e20fdd304cba5782df61bf93ebefcdaed52b 100644 --- a/lib/ci/job_token/policies.rb +++ b/lib/ci/job_token/policies.rb @@ -3,52 +3,124 @@ module Ci module JobToken module Policies - # policies that every CI job token needs - FIXED = [ - :build_create_container_image, - :build_destroy_container_image, - :build_download_code, - :build_push_code, - :build_read_container_image, - :read_project - ].freeze - - # policies that can be assigned to a CI job token - ALLOWED = [ - :admin_container_image, - :admin_secure_files, - :admin_terraform_state, - :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_release, - :read_secure_files, - :read_terraform_state, - :stop_environment, - :update_deployment, - :update_environment, - :update_pipeline, - :update_release + POLICIES_BY_CATEGORY = [ + { + value: :containers, + text: 'Containers', + description: 'Containers category', + policies: [ + { + value: :read_containers, + type: :read, + text: 'Read', + description: 'Read container images in a project' + }, + { + value: :admin_containers, + type: :admin, + text: 'Read and write', + description: 'Admin container images in a project' + } + ] + }, + { + value: :deployments, + text: 'Deployments', + description: 'Deployments category', + policies: [ + { value: :read_deployments, type: :read, text: 'Read', description: 'Read deployments in a project' }, + { + value: :admin_deployments, + type: :admin, + text: 'Read and write', + description: 'Admin deployments in a project' + } + ] + }, + { + value: :environments, + text: 'Environments', + description: 'Environments category', + policies: [ + { value: :read_environments, type: :read, text: 'Read', description: 'Read environments in a project' }, + { + value: :admin_environments, + type: :admin, + text: 'Read and write', + description: 'Admin + Stop environments in a project' + } + ] + }, + { + value: :jobs, + text: 'Jobs', + description: 'Jobs category', + policies: [ + { value: :read_jobs, type: :read, text: 'Read', description: 'Read job metadata and artifacts' }, + { + value: :admin_jobs, + type: :admin, + text: 'Read and write', + description: 'Read job metadata, upload artifacts and update the pipeline status' + } + ] + }, + { + value: :packages, + text: 'Packages', + description: 'Packages category', + policies: [ + { value: :read_packages, type: :read, text: 'Read', description: 'Read packages' }, + { value: :admin_packages, type: :admin, text: 'Read and write', description: 'Admin packages' } + ] + }, + { + value: :releases, + text: 'Releases', + description: 'Releases category', + policies: [ + { value: :read_releases, type: :read, text: 'Read', description: 'Read releases in a project' }, + { value: :admin_releases, type: :admin, text: 'Read and write', description: 'Admin releases in a project' } + ] + }, + { + value: :secure_files, + text: 'Secure files', + description: 'Secure files category', + policies: [ + { value: :read_secure_files, type: :read, text: 'Read', description: 'Read secure files in a project' }, + { + value: :admin_secure_files, + type: :admin, + text: 'Read and write', + description: 'Admin secure files in a project' + } + ] + }, + { + value: :terraform_state, + text: 'Terraform state', + description: 'Terraform state category', + policies: [ + { + value: :read_terraform_state, + type: :read, + text: 'Read', + description: 'Read terraform state files/version' + }, + { + value: :admin_terraform_state, + type: :admin, + text: 'Read and write', + description: 'Admin terraform state files/versions' + } + ] + } ].freeze class << self - def all_values - (FIXED + ALLOWED).map(&:to_s) + def all_policies + POLICIES_BY_CATEGORY.flat_map { |category| category[:policies] } end end end diff --git a/spec/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb b/spec/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb index fa2a14f300871fe03665c67fc1519717a1e0607c..86385bfcd0c0be48bfedfd9a3b810a5b67815ae0 100644 --- a/spec/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb +++ b/spec/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb @@ -36,7 +36,7 @@ let_it_be(:target_project) { create(:project) } let_it_be(:target_project_path) { target_project.full_path } - let(:policies) { %w[read_project read_package] } + let(:policies) { %w[read_containers read_packages] } let(:mutation_args) do { project_path: project.full_path, target_path: target_project_path, job_token_policies: policies } @@ -96,7 +96,7 @@ let_it_be(:target_group) { create(:group, :private) } let_it_be(:target_group_path) { target_group.full_path } - let(:policies) { %w[read_project read_package] } + let(:policies) { %w[read_containers read_packages] } let(:mutation_args) do { project_path: project.full_path, target_path: target_group_path, job_token_policies: policies } diff --git a/spec/graphql/types/ci/job_token_scope/job_token_policy_category_type_spec.rb b/spec/graphql/types/ci/job_token_scope/job_token_policy_category_type_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..80be69d715bbe0f3a3aaf0e1513e8ff708b074c4 --- /dev/null +++ b/spec/graphql/types/ci/job_token_scope/job_token_policy_category_type_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Types::Ci::JobTokenScope::JobTokenPolicyCategoryType, feature_category: :secrets_management do + specify { expect(described_class.graphql_name).to eq('JobTokenPolicyCategory') } + specify { expect(described_class).to have_graphql_fields(%i[text value description policies]) } +end diff --git a/spec/graphql/types/ci/job_token_scope/job_token_policy_type_spec.rb b/spec/graphql/types/ci/job_token_scope/job_token_policy_type_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..717ea0753b22f401b07d82d5ef34896742db2973 --- /dev/null +++ b/spec/graphql/types/ci/job_token_scope/job_token_policy_type_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Types::Ci::JobTokenScope::JobTokenPolicyType, feature_category: :secrets_management do + specify { expect(described_class.graphql_name).to eq('JobTokenPolicy') } + specify { expect(described_class).to have_graphql_fields(%i[text value type description]) } +end diff --git a/spec/graphql/types/ci/job_token_scope/policies_enum_spec.rb b/spec/graphql/types/ci/job_token_scope/policies_enum_spec.rb index 17e56e7f5d243b48c63da97eb16c61085fb015ab..1dd215a18074feb175fdd2464faf4f715127a7c6 100644 --- a/spec/graphql/types/ci/job_token_scope/policies_enum_spec.rb +++ b/spec/graphql/types/ci/job_token_scope/policies_enum_spec.rb @@ -2,44 +2,25 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['CiJobTokenScopePolicies'], feature_category: :secrets_management do +RSpec.describe ::Types::Ci::JobTokenScope::PoliciesEnum, 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 + expect(described_class.values.keys).to match_array(%w[ + READ_CONTAINERS + ADMIN_CONTAINERS + READ_DEPLOYMENTS + ADMIN_DEPLOYMENTS + READ_ENVIRONMENTS + ADMIN_ENVIRONMENTS + READ_JOBS + ADMIN_JOBS + READ_PACKAGES + ADMIN_PACKAGES + READ_RELEASES + ADMIN_RELEASES READ_SECURE_FILES + ADMIN_SECURE_FILES READ_TERRAFORM_STATE - STOP_ENVIRONMENT - UPDATE_DEPLOYMENT - UPDATE_ENVIRONMENT - UPDATE_PIPELINE - UPDATE_RELEASE + ADMIN_TERRAFORM_STATE ]) end end diff --git a/spec/graphql/types/ci/job_token_scope/policy_categories_enum_spec.rb b/spec/graphql/types/ci/job_token_scope/policy_categories_enum_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4166254311168e1626d72149729e538223ad1b27 --- /dev/null +++ b/spec/graphql/types/ci/job_token_scope/policy_categories_enum_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Types::Ci::JobTokenScope::PolicyCategoriesEnum, feature_category: :secrets_management do + it 'exposes all categories' do + expect(described_class.values.keys).to match_array(%w[ + CONTAINERS + DEPLOYMENTS + ENVIRONMENTS + JOBS + PACKAGES + RELEASES + SECURE_FILES + TERRAFORM_STATE + ]) + end +end diff --git a/spec/graphql/types/ci/job_token_scope/policy_types_enum_spec.rb b/spec/graphql/types/ci/job_token_scope/policy_types_enum_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..171d7ddac6efb1cdf66b3f8aad01b2034ed78801 --- /dev/null +++ b/spec/graphql/types/ci/job_token_scope/policy_types_enum_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Types::Ci::JobTokenScope::PolicyTypesEnum, feature_category: :secrets_management do + it 'the correct enum members' do + expect(described_class.values).to match( + 'READ' => have_attributes(value: :read, description: 'Read-only access to the resource.'), + 'ADMIN' => have_attributes(value: :admin, description: 'Admin access to the resource.') + ) + end +end diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index 74e9522c16c7cd6cb7a717da85656480fdfc6ea8..3d4ea44fa3d039cacd42effc25336475d142ea81 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -177,4 +177,48 @@ is_expected.to have_graphql_resolver(Resolvers::FeatureFlagResolver) end end + + describe 'jobTokenPoliciesByCategory field' do + subject { described_class.fields['jobTokenPoliciesByCategory'] } + + it 'returns job token policies', :aggregate_failures do + is_expected.to have_graphql_type(::Types::Ci::JobTokenScope::JobTokenPolicyCategoryType) + + query = <<~GRAPHQL + query { + jobTokenPoliciesByCategory { + text + value + description + policies { + text + value + description + type + } + } + } + GRAPHQL + + expected_result = ::Ci::JobToken::Policies::POLICIES_BY_CATEGORY.map do |category| + { + 'text' => category[:text], + 'value' => category[:value].upcase, + 'description' => category[:description], + 'policies' => category[:policies].map do |policy| + { + 'text' => policy[:text], + 'value' => policy[:value].upcase, + 'description' => policy[:description], + 'type' => policy[:type].upcase + } + end + } + end + + result = GitlabSchema.execute(query).as_json.dig('data', 'jobTokenPoliciesByCategory') + + expect(result).to eq(expected_result.as_json) + end + end end diff --git a/spec/models/ci/job_token/allowlist_spec.rb b/spec/models/ci/job_token/allowlist_spec.rb index babefc7c96eea13cc00f31a41a2b3e68f34f6979..dfab57ff80620c924d3e9edde37ebd5e02bdd86c 100644 --- a/spec/models/ci/job_token/allowlist_spec.rb +++ b/spec/models/ci/job_token/allowlist_spec.rb @@ -67,7 +67,7 @@ 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] } + let_it_be(:policies) { %w[read_containers read_packages] } subject(:add_project) { allowlist.add!(added_project, policies: policies, user: user) } @@ -107,7 +107,7 @@ 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] } + let_it_be(:policies) { %w[read_containers read_packages] } subject(:add_group) { allowlist.add_group!(added_group, policies: policies, user: user) } diff --git a/spec/models/ci/job_token/group_scope_link_spec.rb b/spec/models/ci/job_token/group_scope_link_spec.rb index c087e636921764450027c78cfffad37a719cad36..1e5770fb9c56f7a78d5ea377f3238b40b8880a52 100644 --- a/spec/models/ci/job_token/group_scope_link_spec.rb +++ b/spec/models/ci/job_token/group_scope_link_spec.rb @@ -74,12 +74,12 @@ using RSpec::Parameterized::TableSyntax where(:value, :valid) do - nil | true - [] | true - %w[read_build] | true - %w[read_build read_project] | true - %w[read_issue] | false - { project: %w[read_build] } | false + nil | true + [] | true + %w[read_containers] | true + %w[read_containers read_packages] | true + %w[read_issue] | false + { project: %w[read_build] } | false end with_them do diff --git a/spec/models/ci/job_token/project_scope_link_spec.rb b/spec/models/ci/job_token/project_scope_link_spec.rb index 87b77761ef2d2f63622b68db53c514073ce9c67b..155da77a32c9e70f5d6445c2da3184e58b96e8fc 100644 --- a/spec/models/ci/job_token/project_scope_link_spec.rb +++ b/spec/models/ci/job_token/project_scope_link_spec.rb @@ -78,12 +78,12 @@ using RSpec::Parameterized::TableSyntax where(:value, :valid) do - nil | true - [] | true - %w[read_build] | true - %w[read_build read_project] | true - %w[read_issue] | false - { project: %w[read_build] } | false + nil | true + [] | true + %w[read_containers] | true + %w[read_containers read_packages] | true + %w[read_issue] | false + { project: %w[read_build] } | false end with_them do diff --git a/spec/requests/api/graphql/ci/job_token_scope/allowlist_query_spec.rb b/spec/requests/api/graphql/ci/job_token_scope/allowlist_query_spec.rb index d4c314d85594fb86fbec7b70b246162dcdbaeb06..3778d47c06ac2fe91d7b667c9cf9f8c30d52e8b4 100644 --- a/spec/requests/api/graphql/ci/job_token_scope/allowlist_query_spec.rb +++ b/spec/requests/api/graphql/ci/job_token_scope/allowlist_query_spec.rb @@ -70,7 +70,7 @@ { 'addedBy' => { 'username' => current_user.username }, 'direction' => 'inbound', - 'jobTokenPolicies' => ['READ_GROUP'], + 'jobTokenPolicies' => ['READ_CONTAINERS'], 'sourceProject' => { 'fullPath' => project.full_path }, 'target' => { 'fullPath' => target_group_1.full_path } } @@ -85,14 +85,14 @@ { 'addedBy' => { 'username' => current_user.username }, 'direction' => 'outbound', - 'jobTokenPolicies' => ['READ_PROJECT'], + 'jobTokenPolicies' => ['READ_CONTAINERS'], 'sourceProject' => { 'fullPath' => project.full_path }, 'target' => { 'fullPath' => target_project_2.full_path } }, { 'addedBy' => { 'username' => current_user.username }, 'direction' => 'inbound', - 'jobTokenPolicies' => ['READ_PROJECT'], + 'jobTokenPolicies' => ['READ_CONTAINERS'], 'sourceProject' => { 'fullPath' => project.full_path }, 'target' => { 'fullPath' => target_project_1.full_path } } @@ -138,7 +138,7 @@ :ci_job_token_project_scope_link, source_project: project, target_project: target_project_1, - job_token_policies: %w[read_project], + job_token_policies: %w[read_containers], added_by: current_user, direction: :inbound ) @@ -147,7 +147,7 @@ :ci_job_token_project_scope_link, source_project: project, target_project: target_project_2, - job_token_policies: %w[read_project], + job_token_policies: %w[read_containers], added_by: current_user, direction: :outbound ) @@ -157,7 +157,7 @@ source_project: project, target_group: target_group_1, added_by: current_user, - job_token_policies: %w[read_group] + job_token_policies: %w[read_containers] ) end diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb index 0a10852c9fc90b104f6c71250ff6447bf13de53f..cbf9f4a18835289b12552d17181f2ee7aa234bc2 100644 --- a/spec/requests/api/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/add_group_or_project_spec.rb @@ -7,7 +7,7 @@ let_it_be(:project) { create(:project, ci_inbound_job_token_scope_enabled: true) } - let(:policies) { %w[READ_PROJECT] } + let(:policies) { %w[READ_CONTAINERS] } let(:mutation_response) { graphql_mutation_response(:ci_job_token_scope_add_group_or_project) } diff --git a/spec/requests/api/graphql/mutations/ci/job_token_scope/update_job_token_policies_spec.rb b/spec/requests/api/graphql/mutations/ci/job_token_scope/update_job_token_policies_spec.rb index 10ef438148b07fd6e184b57a2fa1a1b804379ec4..acecd77b2443db464435a418bff5f205658a211b 100644 --- a/spec/requests/api/graphql/mutations/ci/job_token_scope/update_job_token_policies_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/job_token_scope/update_job_token_policies_spec.rb @@ -45,7 +45,7 @@ let_it_be(:target_project) { create(:project, :private) } let_it_be(:target_path) { target_project.full_path } - let(:policies) { %w[READ_PROJECT READ_PACKAGE] } + let(:policies) { %w[READ_CONTAINERS READ_PACKAGES] } context 'when user does not have permissions to admin project' do let_it_be(:current_user) { create(:user, guest_of: target_project) } @@ -74,7 +74,7 @@ :ci_job_token_project_scope_link, source_project: project, target_project: target_project, - job_token_policies: %w[read_project], + job_token_policies: %w[read_containers], direction: :inbound ) end @@ -123,7 +123,7 @@ let_it_be(:target_group) { create(:group, :private) } let_it_be(:target_path) { target_group.full_path } - let(:policies) { %w[READ_GROUP READ_PACKAGE] } + let(:policies) { %w[READ_CONTAINERS READ_PACKAGES] } context 'when user does not have permissions to admin project' do let_it_be(:current_user) { create(:user, guest_of: target_group) } @@ -152,7 +152,7 @@ :ci_job_token_group_scope_link, source_project: project, target_group: target_group, - job_token_policies: %w[read_group] + job_token_policies: %w[read_containers] ) end diff --git a/spec/services/ci/job_token_scope/add_group_or_project_service_spec.rb b/spec/services/ci/job_token_scope/add_group_or_project_service_spec.rb index 3d8d7f68e6221c5ab4b40dfd0b3fa5e6738c44e4..8fbc181dfee6922aa9828e048792b8cf1c554baf 100644 --- a/spec/services/ci/job_token_scope/add_group_or_project_service_spec.rb +++ b/spec/services/ci/job_token_scope/add_group_or_project_service_spec.rb @@ -7,7 +7,7 @@ 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_it_be(:policies) { %w[read_containers read_packages] } let(:response_success) { ServiceResponse.success } @@ -36,7 +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] } + let(:policies) { %w[read_containers] } before do allow(::Ci::JobTokenScope::AddProjectService).to receive(:new) diff --git a/spec/services/ci/job_token_scope/add_group_service_spec.rb b/spec/services/ci/job_token_scope/add_group_service_spec.rb index 8556dbc2d94d0bc5b1f51b95134bde5ce8f0523c..b6e087a25d23c40f8f46d4d9211ef05ac78c649c 100644 --- a/spec/services/ci/job_token_scope/add_group_service_spec.rb +++ b/spec/services/ci/job_token_scope/add_group_service_spec.rb @@ -6,7 +6,7 @@ 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] } + let_it_be(:policies) { %w[read_containers read_packages] } let(:service) { described_class.new(project, current_user) } diff --git a/spec/services/ci/job_token_scope/add_project_service_spec.rb b/spec/services/ci/job_token_scope/add_project_service_spec.rb index d61518d91c6551b5757fe89941ec48a31025ac90..55815e2852a829b968d5b40234f479a51cb11b41 100644 --- a/spec/services/ci/job_token_scope/add_project_service_spec.rb +++ b/spec/services/ci/job_token_scope/add_project_service_spec.rb @@ -7,7 +7,7 @@ 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] } + let_it_be(:policies) { %w[read_containers read_packages] } shared_examples 'adds project' do |context| it 'adds the project to the scope', :aggregate_failures do diff --git a/spec/services/ci/job_token_scope/update_policies_service_spec.rb b/spec/services/ci/job_token_scope/update_policies_service_spec.rb index fed5d5e4c79b37ba4fd263d97833525f1883a9d6..cbcbba5f1e004f3f34a7319cca50ad3c05f23802 100644 --- a/spec/services/ci/job_token_scope/update_policies_service_spec.rb +++ b/spec/services/ci/job_token_scope/update_policies_service_spec.rb @@ -78,12 +78,12 @@ :ci_job_token_project_scope_link, source_project: project, target_project: target_project, - job_token_policies: %w[read_project], + job_token_policies: %w[read_containers], direction: :inbound ) end - let(:policies) { %w[read_project read_package] } + let(:policies) { %w[read_containers read_packages] } it_behaves_like 'when user is not logged in' @@ -106,7 +106,7 @@ expect(project_link.source_project).to eq(project) expect(project_link.target_project).to eq(target_project) - expect(project_link.job_token_policies).to eq(%w[read_project read_package]) + expect(project_link.job_token_policies).to eq(%w[read_containers read_packages]) end context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do @@ -117,7 +117,7 @@ it 'does not update the policies' do project_link = Ci::JobToken::ProjectScopeLink.last - expect(project_link.job_token_policies).to eq(%w[read_project]) + expect(project_link.job_token_policies).to eq(%w[read_containers]) end end end @@ -132,11 +132,11 @@ :ci_job_token_group_scope_link, source_project: project, target_group: target_group, - job_token_policies: %w[read_group] + job_token_policies: %w[read_containers] ) end - let(:policies) { %w[read_group read_package] } + let(:policies) { %w[read_containers read_packages] } it_behaves_like 'when user is not logged in' @@ -159,7 +159,7 @@ expect(group_link.source_project).to eq(project) expect(group_link.target_group).to eq(target_group) - expect(group_link.job_token_policies).to eq(%w[read_group read_package]) + expect(group_link.job_token_policies).to eq(%w[read_containers read_packages]) end context 'when feature-flag `add_policies_to_ci_job_token` is disabled' do @@ -170,7 +170,7 @@ it 'does not update the policies' do group_link = Ci::JobToken::GroupScopeLink.last - expect(group_link.job_token_policies).to eq(%w[read_group]) + expect(group_link.job_token_policies).to eq(%w[read_containers]) end end end diff --git a/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb b/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb index 8585ddd7f8cd13d842e8469fb481c351298f6baf..997988e3636dee49c4fa6e66abecd1941b99f4b4 100644 --- a/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb +++ b/spec/support/shared_contexts/graphql/types/query_type_shared_context.rb @@ -51,7 +51,8 @@ :audit_event_definitions, :abuse_report, :abuse_report_labels, - :feature_flag_enabled + :feature_flag_enabled, + :job_token_policies_by_category ] end end