1
0
forked from baron/baron-sso
Files
baron-sso/docs/tenant-usergroup-policy.md

9.9 KiB

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

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

연구 결과에 기반하여, 단순한 B2C 수준을 넘어 복잡한 테넌트 생태계를 안정적이고 고성능으로 지원하기 위해 외부 DB 의무 채택, 트랜잭셔널 아웃박스 동기화, Keto 기반 인가 백본, 논리적 다중 테넌트 OIDC 관리라는 4대 핵심 아키텍처 원칙을 준수합니다.


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의 내부 트레이트(Traits)에 무분별하게 저장하는 것은 안티 패턴입니다. 이는 토큰 비대화와 쿼리 성능 저하를 초래합니다.

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

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. 중앙집중형 인가 백본 (Keto ReBAC Tuples)

복잡한 다단계 B2B2B 조직도 내에서의 상속 권한을 외부 RDBMS 논리만으로 실시간 검증하는 것은 과부하를 초래합니다. 따라서 조직도 변경 시 해당 데이터를 즉시 Keto의 관계 튜플로 변환하여 전송하고, 인가 검증(Check)은 초고속 병렬 처리가 가능한 Keto 엔진으로 오프로딩합니다.

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

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

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

3.2 계층 간 권한 상속 (Hierarchy)

지주사 \rightarrow 법인 \rightarrow 사내조직 간의 상속은 모두 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. 지능형 프록시를 통한 논리적 다중 테넌트 OIDC 관리

인프라 비용 팽창을 막기 위해 테넌트별로 Hydra(OAuth2/OIDC) 클러스터를 물리적으로 복제하는 것은 지양합니다.

5.1 Logical Pooling for OAuth2

  • 모든 테넌트(COMPANY, PERSONAL)는 소수의 공유된 Hydra 클러스터를 사용합니다.
  • Hydra 클러스터 앞단에 도메인 및 헤더를 재작성하는 지능형 프록시(API Gateway)를 배치하여, 테넌트별로 물리적으로 분리된 것과 같은 라우팅 효과를 제공합니다.

5.2 동적 클레임 주입 (Dynamic Claim Injection)

  • 로그인 및 동의(Consent) 흐름은 전적으로 외부 백엔드 데이터베이스(Business SoT)가 주도합니다.
  • 백엔드는 요청된 클라이언트(RP)의 테넌트 맥락(Context)을 파악하고, 유저가 속한 현재 조직 정보 및 권한(Role)을 Hydra에 전달하여 ID Token의 Custom Claim으로 동적 주입합니다.

6. 분산 시스템 동기화 무결성 확보 (Data Consistency)

Kratos 웹훅 통신 지연이나 이중 쓰기(Dual-Write) 오류로 인한 '고아 레코드(Ghost Identity)'를 원천 차단해야 합니다.

6.1 빠른 제어권 반환 및 비동기 처리 혼합 (Kratos \rightarrow DB)

  • 가입 웹훅(after_registration): Kratos에서 웹훅 요청이 오면, 백엔드는 국소 DB 트랜잭션을 열어 최소한의 필수 식별자 데이터만 users 테이블에 커밋하고 즉각적으로 200 OK를 응답하여 Kratos에 제어권을 반환합니다. (가입 중단 방지)
  • 웰컴 이메일 발송, 초기 조직도 프로비저닝 등 무거운 작업은 즉시 처리하지 않고 메시지 큐(Message Queue)나 비동기 워커로 넘겨 후속 처리합니다.

6.2 트랜잭셔널 아웃박스 패턴 (DB \rightarrow Keto)

  • 백엔드 로직에 의해 테넌트나 권한이 변경될 때, Keto API를 직접 호출하면 네트워크 오류 시 부분 실패(Partial Failure)가 발생할 수 있습니다.
  • 이를 방지하기 위해 DB 커밋 시 동일 트랜잭션 내에서 keto_outbox 테이블에 튜플 변경 이벤트를 기록합니다. 이후 CDC(Change Data Capture) 로직이나 릴레이 워커를 통해 비동기로 시스템 간 동기화를 진행하여 응답 속도와 정합성을 동시에 달성합니다.

6.3 삭제 정책 (Cascade) 및 정기 대사

  • 즉시 회수: 백엔드 DB에서 Soft Delete(deleted_at)가 발생하면, Outbox 워커는 지연 없이 즉각적으로 Keto의 튜플을 Hard Delete 합니다.
  • 정기 대사 (Reconciliation): Kratos(Identity), PostgreSQL(DB), Keto(ReBAC) 3자 간의 불일치(고아 튜플, 누락된 멤버십 등)를 매일 1회 이상 배치 크론 잡을 통해 능동적으로 색출하고 자동 복구/삭제합니다.