1
0
forked from baron/baron-sso
Files
baron-sso/docs/tenant-usergroup-policy.md
2026-02-20 08:35:52 +09:00

8.5 KiB

통합 테넌트 및 권한 아키텍처 정책 (Integrated Tenant & ReBAC Policy)

이 문서는 Baron SSO 시스템 내 B2C(개인)부터 B2B(단일기업), B2B2B(그룹사) 및 사내 조직도(UserGroup)에 이르는 모든 격리 공간과 권한 상속을 다루는 **다형성 테넌트(Polymorphic Tenant)**의 공식 정책을 정의합니다.

이 정책은 기존의 단순 TenantUserGroup 모델을 발전시켜, Ory Kratos(Identity), PostgreSQL(Business), Ory Keto(ReBAC) 3개의 분산 시스템 간 역할을 명확히 하고 데이터 정합성을 강제합니다.


1. 기본 원칙 (Core Axioms)

1.1 "모든 격리 공간은 테넌트이다" (Everything is a Tenant)

  • 개인 워크스페이스, 기업 고객, 지주사, 그리고 사내의 특정 팀이나 본부(UserGroup) 등 모든 종류의 격리 공간은 최상위 범용 단위인 Tenant로 취급됩니다.
  • 과거에 혼용되던 UserGroup 네임스페이스는 폐기되며, 격리 공간을 나타내는 Keto(ReBAC) 네임스페이스는 Tenant 하나로 단일화됩니다. 권한 상속 로직은 테넌트의 성격과 무관하게 동일하게 동작합니다.

1.2 "권한 주체와 자원의 분리" (Namespaces)

시스템의 완벽한 권한 통제를 위해, Keto에는 Tenant 외에도 다음과 같은 필수 네임스페이스가 존재합니다.

  • Tenant: 격리된 공간 (회사, 부서, 개인)
  • RelyingParty: 테넌트가 소유하는 자원/앱 (OIDC 클라이언트)
  • System: 테넌트에 종속되지 않는 전역 권한 (Super Admin 등)

1.3 소유(Ownership)와 가시성(Visibility)의 분리

  • 시스템의 모든 자원(예: RelyingParty, 앱)은 반드시 특정 Tenant가 소유(manage)합니다.
  • 그러나 자원의 소유권과 누가 접근할 수 있는가(가시성, access)는 별개입니다. 내부망용 앱(Private)과 대국민 서비스(Public)를 동일한 기업(Tenant)이 동시에 소유하고 제어할 수 있습니다.

1.4 단일 진실 공급원 분리 (Separation of SoT)

  • Kratos (Identity): "누구인가?" (인증, 이메일, 패스워드 등 순수 식별 정보). 테넌트, 직급 등 관계형 데이터는 절대 보관하지 않습니다.
  • PostgreSQL (Business): "어디에 속하며 조직 구조는 어떠한가?" (직급, 조직도, 테넌트 설정 등).
  • Keto (ReBAC): "무엇을 할 수 있는가?" (권한 및 상속).

2. 하이브리드(다형성) 테넌트 아키텍처

데이터베이스의 tenants 테이블은 가장 가벼운 신분증(Identity) 역할을 수행하며, 세부 비즈니스 설정은 타입별로 별도의 테이블에 1:1 조인(Join)하여 관리합니다.

2.1 테넌트 유형 (Tenant Types)

타입 (Enum) 설명 특징 및 1:1 조인 테이블
PERSONAL B2C 개인 워크스페이스 일반 사용자 가입 시 1:1로 생성. 조직도(UserGroup) 기능 비활성화.
COMPANY B2B 일반 기업/법인 독립된 비즈니스. 사내 조직도를 가짐. 무거운 설정은 company_settings에 저장.
COMPANY_GROUP B2B2B 지주사/그룹사 여러 COMPANY를 하위로 거느리며 최고 관리자 권한을 통합. company_settings 조인.
USER_GROUP 사내 조직 (본부/팀 등) COMPANY 내부에 속하는 조직. 사내 조직도 메타데이터는 user_groups 테이블에 저장.

3. ReBAC 권한 상속 및 관계 튜플 (Keto Tuples)

이전에는 UserGroup 네임스페이스가 존재했으나, 이제 모든 권한 검증은 오직 Tenant 네임스페이스 내에서 처리됩니다.

3.1 조직장(Leader)과 어드민(Admin) 상속

특정 부서(테넌트)의 그룹장(owners)으로 임명되면, 해당 부서 및 그 하위 부서의 최고 관리자(admins) 권한을 자동으로 상속받습니다.

  • 조직장 임명: Tenant:<조직ID>#owners@User:<유저ID>
  • 자동 상속 룰: Tenant:<조직ID>#admins@Tenant:<조직ID>#owners

3.2 계층 간 권한 상속 (Hierarchy)

지주사(COMPANY_GROUP) \rightarrow 법인(COMPANY) \rightarrow 사내조직(USER_GROUP) 간의 상속은 모두 parents 튜플을 사용합니다.

  • 계층 설정: Tenant:<하위ID>#parents@Tenant:<상위ID>
  • 자동 상속 룰: 상위 테넌트의 admins는 하위 테넌트의 manageview 권한을 모두 가집니다.

3.3 리소스 제어 및 RP Admin (Relying Party)

RP(앱)는 별도의 가상 테넌트를 만들지 않고 자원(Object) 자체의 다중 상속을 통해 권한을 제어합니다.

  • 앱 관리 (Manage):
    • RelyingParty:<앱ID>#parents@Tenant:<소유테넌트ID> (앱 소유권 지정. 해당 테넌트의 최고 관리자가 앱을 관리할 수 있음)
    • RelyingParty:<앱ID>#admins@User:<유저ID> (특정 유저를 RP Admin으로 직접 지정)
  • Private 앱 접근 (Access): RelyingParty:<앱ID>#access@Tenant:<소유테넌트ID>#members (소유한 회사의 멤버만 접근)
  • Public 앱 접근 (Access): RelyingParty:<앱ID>#access@System:authenticated_users#members (전역 인증 유저 누구나 접근)

4. 권한 흐름도 (Mermaid)

graph TD
    %% Types
    subgraph COMPANY_GROUP [지주사 테넌트]
        CG[Tenant: 한맥 그룹]
    end

    subgraph COMPANY [법인 테넌트]
        C1[Tenant: 한맥 IT]
    end

    subgraph USER_GROUP [사내조직 테넌트]
        UG1[Tenant: 개발본부]
        UG2[Tenant: 클라우드팀]
    end

    subgraph USERS [사용자]
        CEO[User: 그룹 최고경영자]
        DEV_L[User: 팀장]
        DEV[User: 팀원]
        RP_ADM[User: RP 전담 관리자]
    end

    subgraph RESOURCES [자원]
        RP1[RelyingParty: 사내 인트라넷]
    end

    %% Hierarchy Tuples
    C1 -- "parents" --> CG
    UG1 -- "parents" --> C1
    UG2 -- "parents" --> UG1
    RP1 -- "parents" --> C1

    %% Memberships
    CEO -- "owners" --> CG
    DEV_L -- "owners" --> UG2
    DEV -- "members" --> UG2
    
    %% RP Admin
    RP_ADM -- "admins" --> RP1

    %% Effective Admin Control (Inherited)
    CEO -. "Inherits Admin Control" .-> C1
    CEO -. "Inherits Admin Control" .-> UG1
    CEO -. "Inherits Admin Control" .-> UG2
    CEO -. "Inherits Manage" .-> RP1
    DEV_L -. "Inherits Admin Control" .-> UG2

    %% Styles
    style CG fill:#dfd,stroke:#333
    style C1 fill:#dfd,stroke:#333
    style UG1 fill:#f9f,stroke:#333
    style UG2 fill:#f9f,stroke:#333
    style CEO fill:#ff9,stroke:#333
    style DEV_L fill:#ff9,stroke:#333
    style RP_ADM fill:#ff9,stroke:#333
    style RP1 fill:#bbf,stroke:#333

5. 분산 시스템 정합성 강제 정책 (Data Consistency Check)

인증(Kratos), 비즈니스 로직(PG), 권한(Keto)이 어긋나지 않도록 다음의 안전 장치를 반드시 구현해야 합니다.

5.1 트랜잭셔널 아웃박스 패턴 (Transactional Outbox)

  • 목적: 백엔드 DB에는 저장되었으나, 일시적인 네트워크 장애로 인해 Keto(ReBAC)에 권한이 저장되지 않는 '부분 실패(Partial Failure)' 방지.
  • 방식: DB에 새로운 테넌트(UserGroup 등) 생성 시, 동일 DB 트랜잭션 내에서 keto_outbox 테이블에 튜플 이벤트를 함께 저장합니다. 이후 Background Worker가 이를 안전하게 Keto로 동기화(재시도 보장)합니다.

5.2 삭제 정책 연동 (Delete Cascade)

  • 보안 원칙 (즉시 회수): 백엔드에서 테넌트나 유저를 Soft Delete(deleted_at) 처리하는 즉시, Outbox를 통해 Keto의 관련된 모든 튜플을 Hard Delete하여 권한을 즉각적으로 회수합니다.
  • Kratos 계정 삭제: 사용자가 계정을 영구 탈퇴할 경우, Kratos에서 데이터가 지워지기 직전에 백엔드로 Webhook을 전송하여 Keto 권한 및 로컬 users 테이블의 프로필 데이터를 먼저 비우도록 연동합니다.

5.3 Kratos-Backend 실시간 동기화 (Webhooks)

  • Kratos에서의 회원 가입(after_registration) 및 정보 변경(after_settings) 발생 시, 즉시 Webhook을 발생시켜 Backend의 users 테이블(프로필 로컬 캐시)을 Upsert 합니다.

5.4 정기 대사 스크립트 (Reconciliation Cron Job)

  • 매일 1회 이상 배치 작업을 돌려 분산 시스템 간 엣지 케이스 오류를 복구합니다.
  • 검증 항목:
    1. Keto에 남아있는 고아 튜플(Orphaned Tuples) 검출 및 자동 삭제.
    2. DB의 user_groups 멤버십에는 존재하나 Keto 튜플에서 누락된 권한 색출 및 복원.
    3. Kratos와 Backend 간 유저 ID 매핑 상태 일치 여부 스캔.