REST API 구현 가이드
GitLab v19.5요약
침해된 개인 액세스 토큰(PAT)의 보안 영향을 줄이기 위해, 세분화된 PAT 또는 세밀한 PAT는 특정 조직 경계(그룹, 프로젝트, 사용자 또는 인스턴스 수준)로 제한된 세밀한 권한을 가진 토큰을 사용자가 생성할 수 있게 합니다.
침해된 개인 액세스 토큰(PAT)의 보안 영향을 줄이기 위해, 세분화된 PAT 또는 세밀한 PAT는 특정 조직 경계(그룹, 프로젝트, 사용자 또는 인스턴스 수준)로 제한된 세밀한 권한을 가진 토큰을 사용자가 생성할 수 있게 합니다. 이를 통해 사용자는 토큰에 필요한 권한만 부여하여 최소 권한 원칙을 따를 수 있습니다.
세분화된 PAT는 경계와 특정 리소스 권한으로 구성된 세분화된 범위를 통해 세밀한 액세스 제어를 제공합니다. 세분화된 PAT로 API 요청을 인증할 때 GitLab은 토큰의 권한에 지정된 경계 수준에서 요청된 리소스에 대한 액세스가 포함되는지 검증합니다.
이 문서는 REST API 엔드포인트를 세분화된 PAT 인가에 맞게 준수시키려는 커뮤니티 기여자와 GitLab 개발자를 대상으로 작성되었습니다.
단계별 구현 가이드#
이 가이드는 REST API 엔드포인트에 세분화된 PAT 인가를 추가하는 과정을 안내합니다. 시작하기 전에 문서 전반에서 사용되는 용어를 이해하기 위해 권한 명명 규칙 문서를 확인합니다.
이 단계는 REST API 엔드포인트만 다룹니다. GraphQL 쿼리 및 뮤테이션에 대한 지원 추가는 GraphQL 구현 가이드를 참고합니다.
워크플로 개요#
구현은 다음 흐름을 따릅니다:
- 1-2단계: 계획 - 엔드포인트 식별 및 권한 설계
- 3단계: 원시 권한 생성(YAML 파일)
- 4단계: 원시 권한을 할당 가능한 권한으로 묶기(YAML 파일)
- 5단계: 엔드포인트에 인가 데코레이터 추가(Ruby 코드)
- 6단계: 인가 테스트 작성(Ruby 스펙)
- 7단계: 로컬 테스트(수동 검증)
- 8단계: 문서 검증 및 재생성(Rake 태스크)
각 단계에서 생성되는 파일#
각 단계에서 생성하는 파일을 보여주는 빠른 참조:
| 단계 | 파일 유형 | 위치 | 수량 | 예시 |
|---|---|---|---|---|
| 2 | 계획 문서 | (메모) | - | 권한 이름 식별 |
| 3 | 원시 권한 YAML | config/authz/permissions/<resource>/<action>.yml |
권한당 1개 | config/authz/permissions/job/read.yml |
| 3 | 원시 권한 리소스 메타데이터 | config/authz/permissions/<resource>/.metadata.yml |
리소스당 1개 | config/authz/permissions/job/.metadata.yml |
| 4 | 할당 가능한 권한 YAML | config/authz/permission_groups/assignable_permissions/<category>/<resource>/<action>.yml |
그룹당 1개 | config/authz/permission_groups/assignable_permissions/ci_cd/job/run.yml |
| 4(선택) | 범주 메타데이터 | config/authz/permission_groups/assignable_permissions/<category>/.metadata.yml |
범주당 0 또는 1개 | config/authz/permission_groups/assignable_permissions/ci_cd/.metadata.yml |
| 4 | 리소스 메타데이터 | config/authz/permission_groups/assignable_permissions/<category>/<resource>/.metadata.yml |
리소스당 1개 | config/authz/permission_groups/assignable_permissions/ci_cd/job/.metadata.yml |
| 5 | Grape 데코레이터 | lib/api/<resource>.rb 수정 |
엔드포인트당 1개 | route_setting :authorization 추가 |
| 6 | RSpec 테스트 | spec/requests/api/<resource>_spec.rb 수정 |
엔드포인트당 1개 | it_behaves_like 'authorizing...' 추가 |
| 8 | 생성된 참조 문서 | doc/auth/tokens/fine_grained_access_tokens_rest.md |
1 | bundle exec rake gitlab:permissions:routes:compile_docs로 재생성 |
1단계: 리소스의 REST API 엔드포인트 식별#
목표: 작업 중인 리소스의 모든 REST API 엔드포인트를 찾습니다.
-
lib/api/<resource_name>.rb에서 해당 리소스의 API 파일을 찾습니다.예시: jobs 리소스의 경우
lib/api/ci/jobs.rb를 엽니다팁:
- 일부 리소스는 여러 API 파일에 엔드포인트가 분산되어 있을 수 있습니다(예: 중첩된 리소스)
- 중첩된 엔드포인트를 정의하는
resources :resource_name do블록이 있는지 확인합니다 - 라우터를 살펴보고 해당 리소스의 엔드포인트 전체 범위를 파악합니다
-
파일에서 모든 HTTP 메서드/라우트 쌍을 식별합니다. HTTP 동사와 함께 각 엔드포인트를 문서화합니다:
get ':id/jobs' get ':id/jobs/:job_id' post ':id/jobs/:job_id/cancel' post ':id/jobs/:job_id/retry' delete ':id/jobs/:job_id/artifacts' -
이미 인가 데코레이터(
route_setting :authorization)가 있는 엔드포인트가 있는지 확인합니다. 다음 작업이 필요합니다:- 데코레이터가 없는 엔드포인트에 데코레이터 추가
- 불완전하거나 잘못된 권한을 가진 엔드포인트의 데코레이터 업데이트
이러한 엔드포인트는 다음 단계에서 생성할 원시 권한의 기준이 됩니다. 각 고유한 작업(HTTP 동사 + 라우트)에는 일반적으로 자체 권한이 필요합니다.
2단계: 필요한 권한 결정#
목표: GitLab 명명 규칙에 따라 세분화된 권한을 정의합니다.
명명 규칙은 규칙 문서의 권한 명명을 참고합니다.
엔드포인트의 리소스 이름 결정#
세분화된 PAT 인가를 구현할 때 권한 이름은 라우트 구조가 아니라 엔드포인트가 수정하거나 반환하는 대상을 기준으로 지정합니다.
예시:
- 엔드포인트
DELETE /projects/:id/jobs/:job_id/artifacts→artifacts를 수정 → 권한 이름은delete_job_artifact - 엔드포인트
GET /projects/:id/issues→issues를 반환 → 권한 이름은read_issue - 엔드포인트
POST /projects/:id/jobs/:job_id/cancel→job상태를 수정 → 권한 이름은cancel_job
일반적인 패턴#
- 목록 및 표시 작업: 두 작업에 단일
read_resource권한을 사용합니다GET /projects/:id/jobs→read_jobGET /projects/:id/jobs/:job_id→read_job
- 중첩된 리소스: 권한 이름에 상위 리소스를 포함합니다
POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables→create_pipeline_schedule_variable
- 특수 작업: 고유한 작업에는 별도의 권한을 생성합니다
- 취소, 재시도, 다운로드, 트리거 등은 각각 자체 권한을 가집니다
- 속성 업데이트: 모든 속성을 포괄하는 단일 업데이트 권한을 사용합니다
update_issue는 제목, 설명, 담당자 업데이트 등을 모두 포괄합니다update_issue_description,update_issue_title은 생성하지 않습니다
3단계: 권한 정의 파일 생성#
목표: 각 권한의 YAML 정의 파일이 아직 없으면 생성합니다.
bin/permission 명령으로 원시 권한 YAML 파일을 생성하려면 권한 정의 파일 섹션의 지침을 따릅니다.
4단계: 할당 가능한 권한 생성 또는 업데이트#
목표: 더 단순한 사용자 경험을 위해 원시 권한을 할당 가능한 권한으로 묶습니다.
타당한 경우라면 새 할당 가능한 권한을 생성하기보다 기존 할당 가능한 권한에 원시 권한을 추가하는 방식을 우선합니다. 할당 가능한 권한은 사용자에게 노출됩니다. 새로 추가된 항목은 각각 토큰 생성 UI에 표시되고, 그 이름은 해당 항목을 선택한 모든 토큰에 대해 데이터베이스에 저장됩니다. 나중에 할당 가능한 권한을 제거하거나 이름을 변경하면 호환성이 깨지는 변경이지만, 기존 할당 가능한 권한 안의 원시 권한은 자유롭게 이름을 변경하거나 이동할 수 있습니다. 해당 리소스의 기존 할당 가능한 권한과 별도로 사용자가 부여할 수 있어야 하는 기능을 원시 권한이 나타내는 경우에만 새 할당 가능한 권한을 생성합니다. 각 변경 유형의 영향은 할당 가능한 권한 유지 관리를 참고합니다.
할당 가능한 권한 YAML 파일을 생성하거나 업데이트하려면 할당 가능한 권한 문서의 지침을 따릅니다.
5단계: API 엔드포인트에 인가 데코레이터 추가#
각 엔드포인트에서 라우트 정의 바로 앞에 route_setting :authorization 데코레이터를 추가합니다:
route_setting :authorization, permissions: :read_job, boundary_type: :project
get ':id/jobs' do
# endpoint implementation
end
데코레이터 옵션#
| 옵션 | 설명 |
|---|---|
permissions |
이 엔드포인트에 필요한 권한(심볼 또는 심볼 배열) |
boundary_type |
단일 경계 엔드포인트의 경계 유형: :project, :group, :user 또는 :instance |
boundary_param |
선택 사항. 경계 식별자를 담은 요청 매개변수. 프로젝트의 경우 :project_id와 폴백 :id, 그룹의 경우 :group_id와 폴백 :id가 기본값입니다 |
boundaries |
여러 경계를 지원하는 엔드포인트에서 boundary_type 대신 사용합니다(아래 참조) |
boundary |
표준 매개변수 조회로 경계를 결정할 수 없는 엔드포인트에서 boundary_type 대신 사용합니다. 경계 객체를 반환하는 호출 가능한 객체(proc, lambda 또는 method)입니다 |
skip_granular_token_authorization |
선택 사항. 세분화된 PAT가 특정 권한 없이도 엔드포인트에 액세스할 수 있는 이유를 나타내는 심볼입니다(예: :public_endpoint)(아래 참조) |
todo |
선택 사항. 세분화된 토큰 인가에 대한 결정을 유보하는 비어 있지 않은 문자열(이슈 링크 또는 간단한 사유)입니다. 이 값이 있는 동안 세분화된 PAT는 엔드포인트 액세스가 거부됩니다(아래 참조) |
assignable_when |
선택 사항. 엔드포인트가 현재 사용자에게 적용하는 조건의 배열입니다. 예를 들어 authenticated_as_admin! 뒤에 있는 엔드포인트에는 [:admin]을 사용합니다. 엔드포인트가 선언한 모든 경계 유형에 적용됩니다. 검증 태스크는 엔드포인트 태그와 할당 가능한 권한의 assignable_when 조건이 서로 일치하도록 요구합니다(아래 참조) |
사용자 지정 boundary_param 예시:
route_setting :authorization, permissions: :read_job, boundary_type: :project, boundary_param: :project_id
get 'jobs' do
# endpoint uses params[:project_id] instead of params[:id]
end
boundary를 사용하는 예시:
def registry
::VirtualRegistries::Packages::Maven::Registry.find(params[:id])
end
route_setting :authorization, permissions: :download_maven_package_file, boundary: -> { registry.group }, boundary_type: :group
get '/api/v4/virtual_registries/packages/maven/:id/*path' do
# Boundary cannot be determined through `params`. Instead, it is determined
# from an object (registry) fetched using an ID from the endpoint's
# parameters.
end
엔드포인트당 여러 경계#
일부 엔드포인트는 여러 경계 유형을 지원해야 할 수 있습니다. 예를 들어 가져오기 엔드포인트는 그룹 네임스페이스로 가져올 때는 그룹 수준에서, 개인 네임스페이스로 가져올 때는 사용자 수준에서 동작할 수 있습니다. 이러한 경우에는 boundary_type이나 boundary 대신 boundaries 옵션을 사용합니다:
route_setting :authorization, permissions: :create_bitbucket_import,
boundaries: [{ boundary_type: :group, boundary_param: :target_namespace }, { boundary_type: :user }]
post 'import/bitbucket' do
# endpoint implementation
end
여러 경계를 정의한 경우:
- 배열의 각 경계에는
boundary_type키가 필요하며, 경계 식별자를 담은 요청 매개변수를 지정하는boundary_param키는 선택적으로 지정합니다 - 요청 매개변수에서 확인할 수 있는 모든 경계가 고려됩니다(
user및instance경계는 항상 확인됩니다) - 확인된 경계는 우선순위 순서(
project>group>user>instance)로 평가되며, 토큰의 범위가 그중 하나에서 필요한 모든 권한을 부여하면 액세스가 허용됩니다
세분화된 토큰 인가 건너뛰기#
일부 엔드포인트는 인증이 필요하지 않아 공개적으로 액세스할 수 있거나, 토큰 인증을 구현하지 않습니다. 이러한 엔드포인트에서는 토큰 인증을 건너뛰므로 세분화된 권한을 정의하는 것이 의미가 없습니다. 다만 모든 엔드포인트의 적용 범위 추적을 유지하기 위해, 건너뛰는 이유를 나타내는 심볼과 함께 skip_granular_token_authorization 옵션을 사용합니다:
route_setting :authorization, skip_granular_token_authorization: :public_endpoint
get 'public-endpoint' do
# endpoint implementation
end
이유는 lib/tasks/gitlab/permissions/routes/skip_reasons.rb에 정의된 키 중 하나여야 합니다. 검증 Rake 태스크는 알 수 없는 이유를 거부합니다. 엔드포인트에 맞는 기존 이유가 없으면 사람이 읽을 수 있는 레이블과 함께 새 키를 해당 파일에 추가합니다.
skip_granular_token_authorization 사용 시점:
- 디스커버리 또는 메타데이터 엔드포인트를 포함해 인증이 필요하지 않은 공개 엔드포인트(
:public_endpoint) - 개인 액세스 토큰이 아닌 다른 수단으로 인증하는 엔드포인트(예:
:runner_token_auth,:job_token_auth,:geo_jwt_auth) - 인증이 선택 사항이며 인증 여부와 무관하게 응답이 동일한 엔드포인트
이 데코레이터를 추가하면 권한이 필요하지 않은 엔드포인트까지 포함해 모든 엔드포인트가 인가 시스템의 적용 범위에 명시적으로 포함됩니다.
세분화된 토큰 인가 유보#
엔드포인트를 추가했지만 세분화된 토큰 인가를 어떻게 처리할지 아직 결정하지 않았다면 todo를 사용합니다. 권한 확인 없이 세분화된 PAT를 통과시키는 skip_granular_token_authorization과 달리, todo는 엔드포인트를 검증 태스크의 적용 범위에 유지하면서 세분화된 PAT를 거부합니다. 레거시 개인 액세스 토큰은 영향을 받지 않습니다.
route_setting :authorization, todo: 'https://gitlab.com/gitlab-org/gitlab/-/issues/123456'
post 'assignments' do
# endpoint implementation
end
값은 이슈 링크나 간단한 사유처럼 비어 있지 않은 문자열이어야 합니다. 값이 비어 있으면 인가가 누락된 것으로 간주되어 검증 태스크가 실패합니다.
인가 서비스가 확인할 권한을 찾지 못하므로, 해당 엔드포인트를 호출하는 세분화된 PAT는 403 Forbidden 응답을 받습니다. 엔드포인트의 동작 방식을 결정한 뒤에는 todo를 permissions와 boundary_type(또는 skip_granular_token_authorization)으로 교체합니다.
조건부로 사용 가능한 엔드포인트 태깅#
엔드포인트가 멤버십을 넘어서는 액세스 제한을 두는 경우, 예를 들어
authenticated_as_admin!을 사용하는 경우에는 그 제한이 권한 도구에 드러나도록
assignable_when으로 태깅합니다:
route_setting :authorization, permissions: :read_audit_event, boundary_type: :instance, assignable_when: [:admin]
get 'audit_events' do
# endpoint requires authenticated_as_admin!
end
이 태그는 제한을 설명할 뿐 제한을 적용하지는 않습니다. 엔드포인트는 요청 시점에 확인을 직접 수행해야 합니다.
검증 태스크는 이러한 태그를 할당 가능한 권한 YAML 파일에 선언된 조건과 대조합니다. 자세한 내용은 조건부로 할당 가능한 권한을 참고합니다. GraphQL 유형과 뮤테이션에 태그를 지정하는 방법은 조건부로 사용 가능한 유형 및 뮤테이션 태깅을 참고합니다.
공개적으로 표시되는 리소스에 대한 액세스 허용#
config/authz/roles/public_anonymous.yml에 나열된 권한은 대상 프로젝트 또는 그룹이 공개적으로 표시되고 관련 기능이 활성화된 경우, 일치하는 범위가 없는 세밀한 PAT에도 부여됩니다. 이는 동일한 리소스에 대해 익명 호출자가 갖는 액세스를 그대로 반영합니다. Authz::BoundaryPolicy는 기반이 되는 프로젝트 또는 그룹에서 Users::Anonymous에게 동일한 권한이 허용될 때마다 경계에서 해당 권한을 부여합니다.
권한을 이 동작에 옵트인하려면 config/authz/roles/public_anonymous.yml에서 해당 경계(project: 또는 group:) 아래에 추가합니다:
project:
permissions: []
raw_permissions:
- read_release
group:
permissions: []
raw_permissions:
- read_subgroup
옵트인 시점:
- 해당 권한이 공개 프로젝트 또는 그룹에서 익명 호출자에게 이미 표시되는 데이터에 대한 읽기 전용 액세스를 나타내는 경우입니다.
- 해당 권한이
ProjectFeature(예:repository,issues)로 제어되어, 기능을 비활성화하면 여전히 액세스가 차단되는 경우입니다.
이 우회는 :project 및 :group 경계에만 적용됩니다. :user 및 :instance 경계는 public_anonymous.yml을 참조하지 않습니다.
중요 사항:
- 여러 엔드포인트가 동일한 권한을 사용하더라도 모든 엔드포인트에 데코레이터를 개별적으로 추가합니다
- 데코레이터는 HTTP 메서드 정의(
get,post,put,delete) 바로 앞에 위치합니다 - YAML 파일에 정의한 정확한 권한 이름(심볼)을 사용합니다
- 단일 경계 엔드포인트에는
boundary_type또는boundary를 사용합니다. 다중 경계 엔드포인트에는boundaries배열을 사용합니다 skip_granular_token_authorization은 인증을 거치지 않거나 개인 액세스 토큰이 아닌 다른 수단으로 인증하는 엔드포인트에만 사용합니다. PAT 인증을 허용하는 엔드포인트에서 권한 확인을 우회하는 데에는 절대 사용하지 않습니다
6단계: 인가 테스트 추가#
목표: 세분화된 PAT 권한이 엔드포인트에서 올바르게 적용되는지 확인합니다.
테스트 파일은 보통 spec/requests/api/<resource>_spec.rb에 있습니다. 해당 위치에 없으면 관련 스펙 파일을 좀 더 찾아봐야 할 수 있습니다.
이 테스트가 하는 일: 이 테스트는 다음을 확인합니다:
- 레거시(비세분화) 개인 액세스 토큰이 엔드포인트에 대한 액세스를 계속 부여하는지
- 경계의 최상위 그룹이 세밀한 토큰을 강제하는 경우 레거시 토큰의 액세스가 거부되는지
- 세분화된 PAT에서 필요한 권한을 부여받은 사용자의 액세스가 허용되는지
- 필요한 권한이 없는 사용자의 액세스가 403 Forbidden 응답과 적절한 오류 메시지(
insufficient_granular_scope)로 거부되는지 - 인가 시스템이 엔드포인트의 권한 요구 사항에 대해 세분화된 범위를 올바르게 평가하는지
- 기능 플래그
granular_personal_access_tokens가 올바르게 적용되는지(비활성화된 경우 액세스 거부) - 공개 리소스의
:project및:group경계에서 공개 리소스 우회가 비멤버 요청을 그대로 반영하는지, 즉 범위가 없는 세분화된 PAT가 레거시 비멤버 토큰이 액세스할 수 있는 GET 엔드포인트에 한해 정확히 같은 조건으로 액세스를 허용하고(public_anonymous.yml에서 누락된 권한을 잡아냅니다), GET이 아닌 엔드포인트를 통해서는 절대 액세스를 허용하지 않는지
각 엔드포인트에 공유 예시 추가#
각 엔드포인트에 'authorizing granular token permissions' 공유 예시를 추가합니다. 이는 인가 동작을 검증하는 재사용 가능한 테스트 헬퍼입니다:
it_behaves_like 'authorizing granular token permissions', :<permission_name> do
let(:boundary_object) { <boundary_object> }
let(:user) { <user> }
let(:request) do
<http_method> api("<endpoint_path>", personal_access_token: pat), params: <params_if_needed>
end
end
공유 예시는 권한 이름 뒤에 다음 키워드 인수를 받습니다. 이들은 let 정의가 아니라
it_behaves_like에 전달하는 키워드 인수입니다(do 앞에 위치합니다):
expected_success_status:성공 응답이:success가 아닌 경우에 사용합니다. 일반적인 값은:created,:accepted,:no_content,:redirect(다운로드 또는 파일 엔드포인트)입니다.legacy_token_scopes:엔드포인트가 기본값%w[api]이외의 레거시 토큰 범위를 요구하는 경우에 사용합니다.
it_behaves_like 'authorizing granular token permissions', :create_release, expected_success_status: :created do
"액세스 부여" 어설션은 실제 성공 응답을 기대하므로, 유효한 params를 제공하고 요청 경로가
참조하는 리소스가 모두 존재하도록 합니다. 이미 해당 엔드포인트를 테스트하는 describe 블록의
let 정의와 설정을 재사용하고, 공유 예시를 그 블록 안에 배치합니다.
경계 객체 매핑#
boundary_object는 boundary_type과 일치해야 합니다:
| 경계 유형 | 경계 객체 |
|---|---|
:project |
project |
:group |
group |
:user |
:user |
:instance |
:instance |
중요: 경계 객체가 :project 또는 :group인 경우, 인가가 부여되려면 user가 해당 네임스페이스(프로젝트 또는 그룹)에 대한 액세스 권한이 있어야 합니다. 레거시 토큰 컨텍스트가 해당 사용자에 대해 관리자 모드 토큰을 생성하므로, :user 및 :instance 경계에서도 항상 user를 정의합니다.
7단계: 수동 검증#
목표: 머지 리퀘스트를 생성하기 전에 로컬 환경에서 구현을 수동으로 테스트해 권한이 예상대로 동작하는지 확인합니다.
전체 테스트 스위트를 실행하기 전에 Rails 콘솔에서 엔드포인트와 권한을 테스트하려면 이 방법을 사용합니다.
설정:
Rails 콘솔에서 사용자의 세분화된 PAT를 생성하고, 그 토큰으로 엔드포인트를 테스트할 URL을 복사합니다:
# Enable feature flag
Feature.enable(:granular_personal_access_tokens)
user = User.human.first
# Create granular token
token = PersonalAccessTokens::CreateService.new(
current_user: user,
target_user: user,
organization_id: user.organization_id,
params: { expires_at: 1.month.from_now, scopes: ['granular'], granular: true, name: 'gPAT' }
).execute[:personal_access_token]
# Get the appropriate boundary object (project, group, :user, or :instance)
project = user.projects.first
boundary = Authz::Boundary.for(project)
# Create a scope with the assignable permission being tested (replace :read_job with yours).
# Scopes store assignable permission names, which expand to raw permissions at request time.
scope = Authz::GranularScope.new(namespace: boundary.namespace, access: boundary.access, permissions: [:read_job])
# Add the scope to the token
Authz::GranularScopeService.new(token).add_granular_scopes(scope)
# Copy the API endpoint URL with the token (replace with your endpoint)
IO.popen('pbcopy', 'w') { |f| f.puts "curl \"http://#{Gitlab.host_with_port}/api/v4/projects/#{project.id}/jobs\" --request GET --header \"PRIVATE-TOKEN: #{token.token}\"" }
- 다른 터미널에 URL을 붙여 넣습니다. 성공해야 합니다.
8단계: 문서 검증 및 재생성#
목표: 모든 권한 정의, 데코레이터, 테스트가 일관되는지 확인하고 생성된 참조 문서를 업데이트합니다.
-
세밀한 토큰 참조 문서를 재생성합니다:
bundle exec rake gitlab:permissions:routes:compile_docs이 명령은
doc/auth/tokens/fine_grained_access_tokens_rest.md를 업데이트합니다. 이 파일은 직접 편집하지 않습니다. -
권한 검증을 실행합니다:
bundle exec rake gitlab:permissions:validate이 태스크는 Lefthook pre-push 후크로도 실행됩니다. 여러 확인 항목 중에서 다음과 같은 경우에 실패합니다:
- 엔드포인트에
route_setting :authorization데코레이터가 없고 건너뛰기 이유도 없는 경우. - 데코레이터의 권한에 원시 권한 정의 파일이 없는 경우.
- 데코레이터의 권한이 어떤 할당 가능한 권한에도 속하지 않는 경우.
- 데코레이터의 경계 유형이 할당 가능한 권한의
boundaries와 일치하지 않는 경우. - 건너뛰기 이유가
lib/tasks/gitlab/permissions/routes/skip_reasons.rb에 정의되지 않은 경우. assignable_when조건이 해당 권한을 사용하는 코드의 태그와 일치하지 않는 경우.- 생성된 참조 문서가 최신이 아닌 경우.
- 엔드포인트에