커스텀 역할
Ultimate 고객은 커스텀 역할을 생성하고 특정 능력을 할당하여 해당 역할을 정의할 수 있습니다.
예를 들어, 사용자는 코드 읽기
및 병합 요청 관리
능력이 있는 “엔지니어” 역할을 만들 수 있지만, 이슈 관리
와 같은 능력은 제외할 수 있습니다.
이 문맥에서 “permission”과 “ability”라는 용어는 종종 서로 바꿔 사용됩니다.
-
“Ability”는 사용자가 할 수 있는 작업입니다. 이는 선언적 정책 능력과 매핑되며
ee/app/policies/*
의 정책 클래스에 있습니다. -
“Permission”은 사용자가 마주하는 문서에서 능력을 언급하는 방법입니다 사용자 권한 문서. 권한 문서의 문서화는 수동으로 생성되므로 문서에 나열된 권한과 정책 클래스에서 정의된 능력 사이에 반드시 1:1 매핑이 이루어지는 것은 아닙니다.
커스텀 역할과 기본 역할
GitLab 15.9 이전에는 GitLab에 기본 역할만 있는 권한 시스템이 있었고, 이 시스템에서는 특정 능력에 정적으로 할당된 몇 가지 미리 정의된 역할만 있었습니다. 이러한 기본 역할은 고객이 사용자 지정할 수 없습니다.
커스텀 역할을 통해 고객은 특정 사용자 그룹에 할당할 능력을 결정할 수 있습니다. 예를 들어:
-
기본 역할 시스템에서는 취약점을 읽는 것이 개발자 역할로 제한됩니다.
-
커스텀 역할 시스템에서는 고객이 이러한 능력을 기본 역할을 기반으로 하는 새로운 커스텀 역할에 할당할 수 있습니다.
기본 역할과 마찬가지로 커스텀 역할은 그룹 계층 구조 내에서 상속됩니다. 사용자가 그룹에 커스텀 역할을 가지고 있는 경우, 해당 사용자는 그룹 내의 모든 프로젝트 또는 하위 그룹에 대해서도 커스텀 역할을 가지게 됩니다.
기술 개요
-
개별 커스텀 역할은
member_roles
테이블(MemberRole
모델)에 저장됩니다. -
member_roles
레코드는namespace_id
외래 키를 통해 최상위 그룹(하위 그룹 아님)과 연결됩니다. -
그룹 또는 프로젝트 멤버십(
members
레코드)은member_role_id
외래 키를 통해 커스텀 역할과 연결됩니다. -
그룹 또는 프로젝트 멤버십은 그룹 또는 프로젝트의 루트 레벨 그룹에 정의된 모든 커스텀 역할과 연결될 수 있습니다.
-
member_roles
테이블에는 개별 권한과base_access_level
값이 포함됩니다. -
base_access_level
은 유효한 접근 수준이어야 합니다.base_access_level
은 커스텀 역할에 포함된 능력을 결정합니다. 예를 들어,base_access_level
이10
인 경우, 커스텀 역할은 기본 게스트 역할이 받을 모든 능력과member_roles
레코드에서 속성을 true로 설정하여 활성화된 추가 능력을 포함합니다. -
커스텀 역할은
base_access_level
에 대해 추가 능력을 활성화할 수 있지만 권한을 비활성화할 수는 없습니다. 결과적으로 커스텀 역할은 “추가적만 가능”합니다. 이러한 선택의 이유는 이 댓글에 있습니다. -
커스텀 역할 능력은 프로젝트 레벨과 그룹 레벨에서 지원됩니다.
능력 재구성
기존 능력 체크 찾기
능력은 종종 단일 엔드포인트 또는 웹 요청에 대해 여러 위치에서 체크됩니다. 따라서 주어진 엔드포인트에 대해 실행되는 권한 확인 목록을 찾는 것이 어려울 수 있습니다.
이와 관련하여, GITLAB_DEBUG_POLICIES=true
를 로컬에 설정할 수 있습니다.
이 설정은 실행하는 모든 사양에서의 요청에서 어떤 능력이 체크되는지를 출력합니다. 출력에는 권한 확인이 이루어진 코드의 줄 번호도 포함됩니다. 호출자 정보는 메타프로그래밍이 사용된 경우 특히 유용하며, 이러한 경우는 능력 이름 문자열을 기준으로 grep을 통해 찾기 어렵습니다.
예를 들어:
# 예제 사양 실행
GITLAB_DEBUG_POLICIES=true bundle exec rspec spec/controllers/groups_controller_spec.rb:162
# 사양이 실행될 때의 권한 디버그 출력; 여러 정책 체크가 실행되면 디버그 출력에 모두 포함됩니다.
POLICY CHECK DEBUG -> policy: GlobalPolicy, ability: create_group, called_from: ["/gitlab/app/controllers/application_controller.rb:245:in `can?'", "/gitlab/app/controllers/groups_controller.rb:255:in `authorize_create_group!'"]
이 설정을 사용하여 재구성을 수행하는 동안 권한 체크에 대해 더 많이 알아보세요.
기본 브랜치의 어떤 사양에서도 이 설정을 활성화된 상태로 유지하서는 안 됩니다.
개별 능력에 대한 이해
DeclarativePolicy
클래스에서는 능력에 대한 참조가 여러 차례 나타날 수 있으며, 이는 다른 능력을 참조하는 조건과 규칙에 의존합니다. 그 결과로 특정 능력에 적용되는 조건을 정확히 아는 것은 어려울 수 있습니다.
DeclarativePolicy
는 각 정책 클래스에 대해 ability_map
를 제공하여, 능력에 대한 모든 규칙을 배열로 가져옵니다.
예를 들어:
> GroupPolicy.ability_map.map.select { |k,v| k == :read_group_member }
=> {:read_group_member=>[[:enable, #<Rule can?(:read_group)>], [:prevent, #<Rule ~can_read_group_member>]]}
> GroupPolicy.ability_map.map.select { |k,v| k == :read_group }
=> {:read_group=>
[[:enable, #<Rule public_group>],
[:enable, #<Rule logged_in_viewable>],
[:enable, #<Rule guest>],
[:enable, #<Rule admin>],
[:enable, #<Rule has_projects>],
[:enable, #<Rule read_package_registry_deploy_token>],
[:enable, #<Rule write_package_registry_deploy_token>],
[:prevent, #<Rule all?(~public_group, ~admin, user_banned_from_group)>],
[:enable, #<Rule auditor>],
[:prevent, #<Rule needs_new_sso_session>],
[:prevent, #<Rule all?(ip_enforcement_prevents_access, ~owner, ~auditor)>]]}
DeclarativePolicy
는 또한 특정 객체와 행위자에 대한 논리 트리를 이해하는 데 사용할 수 있는 debug
방법을 제공합니다. 출력은 ability_map
의 규칙 목록과 유사합니다. 그러나 DeclarativePolicy
는 능력을 prevent
한 후에는 규칙 평가를 중지하므로, 모든 조건이 호출되지 않을 수 있습니다.
예시:
policy = GroupPolicy.new(User.last, Group.last)
policy.debug(:read_group)
- [0] enable when public_group ((@custom_guest_user1 : Group/139))
- [0] enable when logged_in_viewable ((@custom_guest_user1 : Group/139))
- [0] enable when admin ((@custom_guest_user1 : Group/139))
- [0] enable when auditor ((@custom_guest_user1 : Group/139))
- [14] prevent when all?(~public_group, ~admin, user_banned_from_group) ((@custom_guest_user1 : Group/139))
- [14] prevent when needs_new_sso_session ((@custom_guest_user1 : Group/139))
- [16] enable when guest ((@custom_guest_user1 : Group/139))
- [16] enable when has_projects ((@custom_guest_user1 : Group/139))
- [16] enable when read_package_registry_deploy_token ((@custom_guest_user1 : Group/139))
- [16] enable when write_package_registry_deploy_token ((@custom_guest_user1 : Group/139))
[21] prevent when all?(ip_enforcement_prevents_access, ~owner, ~auditor) ((@custom_guest_user1 : Group/139))
=> #<DeclarativePolicy::Runner::State:0x000000015c665050
@called_conditions=
#<Set: {
"/dp/condition/GroupPolicy/public_group/Group:139",
"/dp/condition/GroupPolicy/logged_in_viewable/User:83,Group:139",
"/dp/condition/BasePolicy/admin/User:83",
"/dp/condition/BasePolicy/auditor/User:83",
"/dp/condition/GroupPolicy/user_banned_from_group/User:83,Group:139",
"/dp/condition/GroupPolicy/needs_new_sso_session/User:83,Group:139",
"/dp/condition/GroupPolicy/guest/User:83,Group:139",
"/dp/condition/GroupPolicy/has_projects/User:83,Group:139",
"/dp/condition/GroupPolicy/read_package_registry_deploy_token/User:83,Group:139",
"/dp/condition/GroupPolicy/write_package_registry_deploy_token/User:83,Group:139"}>,
@enabled=false,
@prevented=true>
기능 통합
사용자 지정 역할에 추가된 모든 기능은 최소한의 능력을 가져야 합니다. 대부분의 기능에서는 read_*
와 admin_*
만 있으면 충분합니다. 모두 통합해야 합니다:
-
read_*
에 관련된 보기 능력. 예를 들어, 목록이나 세부정보 보기. -
admin_*
에 객체 업데이트. 예를 들어, 객체 업데이트, 담당자 추가 또는 해당 객체 닫기. 일반적으로admin_
를 활성화하는 역할은read_
능력도 활성화되어 있어야 합니다. 이는MemberRole
모델의ALL_CUSTOMIZABLE_PERMISSIONS
해시에서requirement
옵션에 정의되어 있습니다.
추가적인 능력이 필요한 기능이 있을 수 있지만, 이를 최소화하려고 노력하십시오. 인증 및 권한 부서의 구성원에게 의견이나 도움을 요청할 수 있습니다.
이곳이 당신의 작업이 시작되어야 하는 곳이기도 합니다. 당신이 작업하는 기능의 모든 능력을 가져와서, 필요하다면 이를 read_
, admin_
또는 추가 능력으로 통합하십시오.
GroupPolicy
및 ProjectPolicy
클래스의 많은 능력에 중복된 정책이 많이 있습니다. 이 정책 클래스를 통합하기 위한 epic이 있습니다.
이러한 클래스에서 유사한 권한을 발견하면, 동일한 이름을 사용하도록 리팩토링하는 것을 고려하십시오.
예를 들어, GroupPolicy
에서 read_group_security_dashboard
라는 능력이 있고, ProjectPolicy
에는 read_project_security_dashboard
라는 능력이 있습니다. 두 가지 모두 사용자 정의 가능하게 만들고 싶습니다. 각 능력에 대해 member_roles
테이블에 행을 추가하는 것 대신, 이들을 read_security_dashboard
로 이름을 바꾸고 member_roles
테이블에 read_security_dashboard
를 추가하는 것을 고려하십시오. 상위 그룹에서 read_security_dashboard
를 활성화하면 사용자 지정 역할이 해당 그룹의 보안 대시보드와 해당 그룹의 각 프로젝트에 대한 보안 대시보드에 접근할 수 있습니다. 특정 프로젝트에서 동일한 권한을 활성화하면 해당 프로젝트의 보안 대시보드에 접근할 수 있습니다.
사용자 지정 역할에 대한 능력을 추가하는 방법
기존 능력을 추가할 경우, 아래 작업을 완료하기 전에 리팩토링 및 기능을 위한 능력 통합을 고려하십시오.
단계 1. 구성 파일 생성
-
./ee/bin/custom-ability <ABILITY_NAME>
를 실행하여 새 능력에 대한 구성 파일을 생성합니다. - 이 명령은 다음 스키마를 따르는
ee/config/custom_abilities
에 YAML 파일을 생성합니다:
필드 | 필수 | 설명 |
---|---|---|
name |
예 | 사용자 정의 능력을 설명하는 고유하고, 소문자이며, 밑줄이 있는 이름. 파일 이름과 일치해야 합니다. |
title |
예 | 사용자 정의 능력의 사람이 읽을 수 있는 제목. |
description |
예 | 사용자 정의 능력의 사람이 읽을 수 있는 설명. |
feature_category |
예 | 기능 카테고리의 이름. 예: vulnerability_management . |
introduced_by_issue |
예 | 이 사용자 정의 능력의 추가를 제안하는 이슈 URL. |
introduced_by_mr |
예 | 이 사용자 정의 능력을 추가한 MR URL. |
milestone |
예 | 이 사용자 정의 능력이 추가된 마일스톤. |
group_ability |
예 | 이 능력이 그룹 수준에서 체크되는지 여부를 나타내는 불리언 값. |
project_ability |
예 | 이 능력이 프로젝트 수준에서 체크되는지 여부를 나타내는 불리언 값. |
requirements |
아니요 | 이 능력이 의존하는 사용자 정의 권한 목록. 예: admin_vulnerability 는 read_vulnerability 에 의존합니다. 없으면 [] 를 입력하십시오. |
available_from_access_level |
아니요 | 이 능력이 사용 가능한 사전 정의된 역할의 접근 수준. 이 섹션은 개별 능력의 논리 이해에 대한 도움을 참조하십시오. 이는 정보 제공을 위한 것이며 사용자 지정 역할의 작동에 영향을 미치지 않습니다. |
2단계: 스펙 파일 생성 및 검증 스키마 업데이트
-
bundle exec rails generate gitlab:custom_roles:code --ability <ABILITY_NAME>
를 실행하면 권한 검증 스키마 파일이 업데이트되고 빈 스펙 파일이 생성됩니다.
3단계: 정책 업데이트
- 능력이 그룹 수준에서 체크되면 GroupPolicy에 규칙을 추가하여 능성을 활성화합니다.
- 예를 들어 추가하고자 하는 능력이
read_dependency
인 경우,ee/app/policies/ee/group_policy.rb
의 업데이트는 다음과 같이 보일 것입니다:
rule { custom_role_enables_read_dependency }.enable(:read_dependency)
- 유사하게, 능력이 프로젝트 수준에서 체크되면 ProjectPolicy에 규칙을 추가하여 능성을 활성화합니다.
- 예를 들어 추가하고자 하는 능력이
read_dependency
인 경우,ee/app/policies/ee/project_policy.rb
의 업데이트는 다음과 같이 보일 것입니다:
rule { custom_role_enables_read_dependency }.enable(:read_dependency)
- 모든 능성이 두 수준 모두에서 활성화될 필요는 없습니다. 예를 들어
admin_terraform_state
는 사용자가 프로젝트의 terraform 상태를 관리할 수 있도록 합니다. 이는 프로젝트 수준에서만 활성화하면 충분하며 그룹 수준에서는 필요하지 않으므로ee/app/policies/ee/project_policy.rb
에만 구성하면 됩니다.
4단계: 검증
- SaaS 모드가
GITLAB_SIMULATE_SAAS=1
로 활성화되어 있는지 확인합니다. - 귀하가 소유한 그룹으로 이동한 다음
설정 -> 역할 및 권한
으로 이동합니다. -
새 역할
을 선택하고 방금 생성한 권한을 가진 사용자 정의 역할을 생성합니다. - 그룹의
관리 -> 구성원
페이지로 이동하여 이 새로 생성된 사용자 정의 역할에 구성원을 할당합니다. - 다음으로, 그 구성원으로 로그인하여 해당 사용자 정의 능성이 의도한 페이지에 접근할 수 있는지 확인합니다.
5단계: 스펙 추가
-
ee/spec/factories/member_roles.rb
의MemberRoles
팩토리에 능성을 특성으로 추가합니다. - 사용자가 사용자 정의 능성이 할당된 후 컨트롤러, REST API 엔드포인트 및 GraphQL API 엔드포인트에 성공적으로 접근할 수 있도록
ee/spec/requests/custom_roles/<ABILITY_NAME>/request_spec.rb
에 테스트를 추가합니다. - 다음은 Rails Controller 엔드포인트를 테스트하는 데 필요한 일반적인 설정의 예입니다.
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :in_group) }
let_it_be(:role) { create(:member_role, :guest, namespace: project.group, custom_permission: true) }
let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) }
before do
stub_licensed_features(custom_roles: true)
sign_in(user)
end
describe MyController do
describe '#show' do
it 'allows access' do
get my_controller_path(project)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template(:show)
end
end
end
- GraphQL 뮤테이션을 테스트하는 데 필요한 일반적인 설정의 예입니다.
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :in_group) }
let_it_be(:role) { create(:member_role, :guest, namespace: project.group, custom_permission: true) }
let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) }
before do
stub_licensed_features(custom_roles: true)
sign_in(user)
end
describe MyMutation do
include GraphqlHelpers
describe '#show' do
let(:mutation) { graphql_mutation(:my_mutation) }
it_behaves_like 'a working graphql query'
end
end
-
ProjectPolicy
및/또는GroupPolicy
에 테스트를 추가합니다. 다음은ProjectPolicy
관련 변경 사항을 테스트하기 위한 예입니다.
context '읽기 종속성이 true인 구성원 역할의 경우' do
let(:member_role_abilities) { { read_dependency: true } }
let(:allowed_abilities) { [:read_dependency] }
it_behaves_like 'custom roles abilities'
end
6단계: 문서 업데이트
GitLab 문서에 기여하기 페이지를 따라 문서에 다음과 같은 변경 사항을 추가하세요:
-
bundle exec rake gitlab:custom_roles:compile_docs
명령어를 실행하여 사용자 정의 역할 목록을 업데이트합니다. -
bundle exec rake gitlab:graphql:compile_docs
명령어를 실행하여 GraphQL 문서를 업데이트합니다.
권한 상승 고려사항
기본 역할(base role)은 일반적으로 해당 아티팩트와 상호작용할 때 기본 역할에 해당하는 아티팩트의 생성 또는 관리 권한을 허용합니다. 예를 들어, Developer
가 프로젝트에 대한 액세스 토큰을 생성할 때, 이 토큰은 해당 자격 증명에 Developer
접근 권한이 인코딩된 채로 생성됩니다. 새로운 사용자 정의 권한이 생성됨에 따라 GitLab 아티팩트와 상호작용할 때 권한 상승의 위험이 있을 수 있으므로 적절한 보호 장치나 기본 역할 확인을 추가해야 합니다.
이용 중인 좌석
역할 Guest
를 가진 새로운 사용자가 CUSTOMIZABLE_PERMISSIONS_EXEMPT_FROM_CONSUMING_SEAT
배열에 없는 권한을 활성화하는 구성원 역할에 추가되는 경우, 좌석이 소비됩니다. 우리는 단순히 “권한 상승”이 있는 게스트 사용자에 대해 Ultimate 고객에게 요금을 부과하고자 합니다. 이는 SaaS에서 청구 가능한 사용자(네임스페이스 구독에 포함되는 청구 가능한 사용자)에게만 해당됩니다. 이 주제에 대한 자세한 내용은 이슈에서 확인할 수 있습니다.
모듈 정책
GitLab 모듈식 모놀리식 디자인 문서를 지원하기 위해 Authorization 그룹은 Create:IDE 그룹와 협력하고 있습니다. POC가 구현되면, 결과는 논의될 것이며, Authorization 그룹은 앞으로의 정책의 모듈 설계에 대해 결정할 것입니다.