Skip to content

Conversation

@juanxiu
Copy link
Collaborator

@juanxiu juanxiu commented Dec 27, 2025

멀티테넌시 RBAC

관련 이슈

#176

핵심 설계 원칙

  1. 테넌트별 역할 할당: 사용자는 테넌트마다 다른 역할을 가짐
  2. 4차원 스코프: 권한 평가 시 항상 (user, tenant, role, resource) 스코프에서 판단
  3. 리소스 소유 테넌트: CloudResource는 반드시 tenant_id를 가져야 함
  4. 다중 테넌트 지원: 동일 Worker가 여러 테넌트에 속할 수 있고, 테넌트마다 역할 세트가 다를 수 있음
  5. 컨텍스트 선택: 동일 유저가 조직 Worker와 개인 Worker를 모두 가질 수 있으며, 요청 시 하나의 Worker만 선택하여 접근
  6. 일관된 권한 평가: 애플리케이션 코드에서 권한 체크를 호출할 때, 모든 권한 평가는 선택된 (tenantId, workerId) 기반으로 수행

주요 흐름

1. 로그인 흐름

1. 사용자가 로그인 요청 (username, password)
2. AuthenticationService.login() 실행
3. 사용자 인증 (비밀번호 확인)
4. 사용자의 모든 Worker 조회
5. Worker를 통해 접근 가능한 Tenant 목록 수집
6. JWT 토큰 생성 (accessToken, refreshToken)
7. TokenResponse 반환 (토큰 + availableTenants)

특징:

  • 로그인 시점에 사용자가 접근 가능한 모든 테넌트 목록을 반환
  • 클라이언트는 이 목록을 기반으로 테넌트 선택 UI 제공

2. 테넌트 컨텍스트 선택 흐름

1. 클라이언트가 API 요청 시 X-Tenant-Id 헤더 포함
2. TenantContextInterceptor가 요청 인터셉트
3. X-Tenant-Id 헤더에서 tenantId 추출
4. SecurityContext에서 현재 사용자 정보 조회
5. TenantContextService.validateTenantAccess() 호출
   - User의 Worker 중 해당 Tenant에 속한 Worker 존재 확인
   - Worker가 없으면 접근 거부
6. Worker 정보 조회
7. TenantContextHolder에 Tenant와 Worker 설정
8. 요청 계속 진행

특징:

  • 매 요청마다 테넌트 컨텍스트 검증
  • 검증 실패 시 즉시 403 Forbidden 반환
  • 검증 성공 시 ThreadLocal에 Context 저장

3. 권한 체크 흐름

1. 비즈니스 로직에서 PermissionService.can() 호출
2. 1단계: Tenant 격리 확인
   - 리소스의 tenantId와 현재 Context의 tenantId 비교
   - 불일치 시 즉시 DENY
3. 2단계: Worker의 Role 조회
   - WorkerRoleAssignment에서 현재 Worker의 Role 목록 조회
   - Role이 없으면 DENY
4. 3단계: Role의 Permission 확인
   - 각 Role에 연결된 Permission 목록 조회
5. 4단계: ResourceType과 Action 매칭
   - 리소스 타입과 액션이 일치하는 Permission 존재 확인
   - 일치하는 Permission이 있으면 ALLOW, 없으면 DENY

RBAC 관련 DB 스키마 설계

  1. 역할/권한 스키마: roles, permissions, role_permissions, worker_role_assignments

각 테이블의 역할:

  • roles: 역할 정의 (Kubernetes Role)
  • permissions: 권한 정의 (Kubernetes Role.rules)
  • role_permissions: Role에 Permission 할당 (Kubernetes Role 내부 rules 정의)
  • worker_role_assignments: Worker에 Role 할당 (Kubernetes RoleBinding)

Kubernetes RBAC 와 차이점:

  • Kubernetes: Role 정의 시 rules를 직접 포함
  • 우리 스키마: Role과 Permission을 분리하여 M:N 관계로 관리 (더 유연함)
  1. 리소스/워커 매핑 스키마: cloud_resources, cloud_resource_worker_map
Image

요구사항 정의

시나리오 개요

시나리오: User ↔ Worker (1:N), Worker → Tenant (N:1)

  • User ↔ Worker (1:N): 한 User는 여러 Worker를 가질 수 있음
  • Worker → Tenant (N:1): Worker는 하나의 Tenant에만 속함
  • User가 여러 Tenant에 속할 수 있음: 각 Tenant마다 Worker가 다름
  • 컨텍스트 선택 필요: User가 여러 Tenant 중 하나를 선택해야 함
  • Worker 결정: Tenant 선택 시 해당 Tenant의 Worker 자동 조회

핵심 원칙

  • User는 조직(테넌트)이 정해지면 Worker도 정해진다
  • Worker는 Tenant에 종속적 → Worker를 직접 선택할 필요 없음
  • Tenant 선택 → 해당 Tenant의 Worker 자동 결정

전제 조건

  • Tenant ↔ Organization (1:1): Tenant와 Organization은 1:1 관계

시퀀스 다이어그램

역할 및 권한 체크 시퀀스

Image

클라우드 리소스 접근 시퀀스

Image

권한 체크 흐름 요약

  1. Tenant 격리 확인: resource.tenantId == tenantId
  2. RBAC 권한 체크:
    • Worker의 Role 조회 (WorkerRoleAssignment)
    • Role의 Permission 확인 (RolePermission)
    • resourceTypeaction에 대한 권한 확인

권한 체크 함수: PermissionService.can(workerId, tenantId, action, resource)

레퍼런스

핵심 컴포넌트

1. TenantContextInterceptor

  • 역할: HTTP 요청 인터셉터
  • 기능:
    • X-Tenant-Id 헤더에서 테넌트 ID 추출
    • TenantContextService로 사용자의 테넌트 접근 권한 검증
    • 검증 성공 시 TenantContextHolder에 Context 설정

2. TenantContextService

  • 역할: 테넌트 접근 검증 및 Worker 조회
  • 주요 메서드:
    • validateTenantAccess(Long userId, Long tenantId): 접근 권한 검증
    • getAvailableTenantsForUser(Long userId): 사용자가 접근 가능한 모든 테넌트 조회

3. TenantContextHolder

  • 역할: ThreadLocal 기반 Context 관리
  • 저장 정보:
    • 현재 Tenant
    • 현재 Worker
  • 특징: 요청별로 독립적인 Context 유지

4. PermissionService

  • 역할: 권한 체크 로직 실행
  • 주요 메서드:
    • can(Long workerId, Long tenantId, String action, Object resource): 권한 체크

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants