포스트

[이제와서 시작하는 Metabase 마스터하기 #10] 권한과 보안 - Collections와 그룹 관리

[이제와서 시작하는 Metabase 마스터하기 #10] 권한과 보안 - Collections와 그룹 관리

학습 목표

이 포스트를 마치면 다음을 할 수 있습니다:

  • 조직의 권한 구조 설계
  • Groups와 Collections로 접근 제어
  • Data permissions로 데이터베이스 수준 보안
  • Row-level security로 세밀한 접근 제어
  • SQL permissions로 쿼리 제한
  • 감사 로그로 사용 추적

권한 시스템 개요

3계층 권한 모델

graph TD
    A[Metabase Permissions] --> B[User Management]
    A --> C[Data Permissions]
    A --> D[Collection Permissions]

    B --> B1[Users & Groups]
    C --> C1[Database Access]
    C --> C2[Table Access]
    D --> D1[Questions & Dashboards]

    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#e8f5e9
    style D fill:#fce4ec

1. User Management (사용자 관리)

  • 사용자 계정 생성/삭제
  • 그룹 할당
  • 관리자 권한

2. Data Permissions (데이터 권한)

  • 어떤 데이터베이스에 접근 가능한가?
  • 어떤 테이블을 볼 수 있는가?
  • Native query 작성 가능한가?

3. Collection Permissions (컬렉션 권한)

  • 어떤 Questions/Dashboards를 볼 수 있는가?
  • 편집 가능한가?
  • 새로 만들 수 있는가?

Users & Groups

사용자 생성

1
2
3
4
5
6
7
8
Admin > People > Add someone

Email: john@company.com
First name: John
Last name: Doe
Groups:
  - All Users (자동)
  - Sales (수동 선택)

Groups (그룹)

기본 그룹:

1
2
3
4
5
6
7
8
1. Administrators
   - 모든 권한
   - 설정 변경 가능
   - 사용자 관리

2. All Users
   - 모든 사용자 자동 포함
   - 기본 권한 설정

사용자 정의 그룹 예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
조직 구조 기반:
  - Sales Team
  - Marketing Team
  - Engineering Team
  - Finance Team
  - Executives

역할 기반:
  - Analysts
  - Managers
  - Viewers
  - Data Scientists

프로젝트 기반:
  - Project Alpha
  - Product Launch Team
  - Customer Success

그룹 생성 및 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Admin > People > Groups > Create a group

Name: Sales Team
Description: 영업팀 멤버 - 매출 및 고객 데이터 접근

Members:
  - jane@company.com (Sales Manager)
  - john@company.com (Sales Rep)
  - sarah@company.com (Sales Rep)

Data permissions:
  ✅ Sample Database > Orders (Full access)
  ✅ Sample Database > Customers (Full access)
  ❌ Sample Database > Internal (No access)

Collection permissions:
  ✅ Sales Analytics (Edit)
  👁️ Executive Dashboard (View only)
  ❌ Finance Reports (No access)

Data Permissions

권한 레벨

graph LR
    A[No access] --> B[Limited access]
    B --> C[Unrestricted access]

    A --> A1[테이블 안 보임]
    B --> B1[GUI만 사용]
    B --> B2[승인된 쿼리만]
    C --> C1[GUI + SQL]
    C --> C2[모든 쿼리]

1. No access (접근 불가)

1
데이터베이스/테이블이 존재하지 않는 것처럼 보임

2. Limited access (제한된 접근)

1
2
3
- GUI Query Builder만 사용 가능
- Native SQL 불가
- 또는 승인된 Models/Questions만 사용

3. Unrestricted access (무제한 접근)

1
2
3
- GUI + Native SQL 모두 사용
- 모든 테이블 접근
- 임의의 쿼리 실행

데이터베이스 수준 권한

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Admin > Permissions > Databases

Database: Sample Database

Group permissions:
┌─────────────────┬──────────────────────┐
│ Group           │ Access Level         │
├─────────────────┼──────────────────────┤
│ Administrators  │ Unrestricted         │
│ All Users       │ No access            │
│ Sales Team      │ Limited (GUI only)   │
│ Analysts        │ Unrestricted         │
│ Executives      │ Limited (GUI only)   │
└─────────────────┴──────────────────────┘

테이블 수준 권한

1
2
3
4
5
6
7
8
9
10
11
12
Admin > Permissions > Databases > Sample Database

Sales Team permissions:
┌───────────────┬──────────────────────┐
│ Table         │ Access Level         │
├───────────────┼──────────────────────┤
│ Orders        │ Unrestricted         │
│ Customers     │ Unrestricted         │
│ Products      │ Sandboxed (특정 행만)│
│ Employees     │ No access            │
│ Financial     │ No access            │
└───────────────┴──────────────────────┘

SQL Permissions

Native Query 권한:

1
2
3
4
5
6
7
8
9
10
11
12
Group: Junior Analysts

SQL permissions:
  ○ No native query access
  ● Can write native queries
    ☑ Must be approved before running
    ☑ Query results reviewed

Use case:
  - 학습 중인 분석가
  - 쿼리 리뷰 후 실행
  - 데이터 보안 유지

Collection Permissions

Collection 구조 설계

Best Practice 폴더 구조:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Our analytics/
├── Executive/
│   ├── Company Overview (View: Executives, Edit: Admin)
│   └── Board Reports (View: Board, Edit: CFO)
├── Sales/
│   ├── Daily Metrics (View: Sales, Edit: Sales Analysts)
│   ├── Customer Analysis (View: Sales + Marketing)
│   └── Forecasting (View: Sales Managers, Edit: FP&A)
├── Marketing/
│   ├── Campaign Performance (View: Marketing, Edit: Marketing Analysts)
│   ├── Attribution (View: Marketing + Sales)
│   └── Ad Hoc Analysis (Edit: Marketing Team)
├── Product/
│   ├── Usage Metrics (View: Product + Eng)
│   ├── Feature Performance (Edit: Product Analysts)
│   └── A/B Tests (Edit: Data Science)
├── Finance/
│   ├── Revenue Reports (View: Finance + Exec)
│   ├── Cost Analysis (View: Finance only)
│   └── Internal (View: CFO only)
└── Shared/
    ├── Company KPIs (View: All Users)
    └── Data Dictionary (View: All Users)

Collection 권한 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Collection: Sales Analytics

Permissions:
┌─────────────────┬──────────────────────┐
│ Group           │ Access Level         │
├─────────────────┼──────────────────────┤
│ Administrators  │ Curate (최고 권한)    │
│ Sales Managers  │ Curate               │
│ Sales Team      │ Edit                 │
│ Marketing       │ View                 │
│ All Users       │ No access            │
└─────────────────┴──────────────────────┘

Access levels:
  - Curate: 보기 + 편집 + 권한 관리
  - Edit: 보기 + 편집
  - View: 보기만
  - No access: 접근 불가

Row-Level Security (행 수준 보안)

📝 용어 변경: v0.56부터 “데이터 샌드박싱(Data Sandboxing)”이 공식적으로 “행 수준 보안(Row-level Security)”으로 명칭이 변경되었습니다. 기능은 동일하며, 열 수준 권한(Column-level Permissions)과 함께 더 세밀한 보안 제어가 가능합니다.

개념

특정 사용자/그룹이 테이블의 일부 행만 볼 수 있도록 제한

1
2
3
4
5
6
7
8
-- 일반 쿼리
SELECT * FROM orders
-- 모든 주문 표시

-- Row-level security 적용 후
SELECT * FROM orders
WHERE sales_rep_id = 
-- 해당 영업 담당자의 주문만 표시

열 수준 권한 (Column-level Permissions) - v0.56+

특정 컬럼 숨기기:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Admin > Permissions > Databases > Sample Database

Table: Customers
Group: Sales Reps

Column permissions:
  ✅ id (view)
  ✅ name (view)
  ✅ email (view)
  ❌ credit_card (hidden)
  ❌ ssn (hidden)
  ✅ total_spent (view)

Result:
  Sales Reps는 민감한 컬럼(신용카드, SSN)을 볼 수 없음

Sandboxing 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
Admin > Permissions > Databases > Sample Database

Table: Orders
Group: Sales Reps

Sandboxed access:
  ☑ Enable row-level permissions

Attribute to filter on: sales_rep_id
User attribute to use: user_id

Result:
  Sales Rep #123은 sales_rep_id = 123인 주문만 볼 수 있음

User Attributes (사용자 속성)

속성 정의:

1
2
3
4
5
6
7
Admin > People > john@company.com > Edit

User attributes:
  - user_id: 123
  - region: West
  - department: Sales
  - level: Manager

Sandboxing 예제:

예제 1: 지역별 접근

1
2
3
4
5
6
7
8
9
10
11
Table: Customers
Group: Regional Managers

Sandbox:
  Filter: state IN ()

User: Jane (Regional Manager - West)
  user_regions: ['CA', 'OR', 'WA', 'NV']

Result:
  Jane은 서부 지역 고객만 볼 수 있음

예제 2: 계층 기반 접근

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Table: Orders
Group: Managers

Sandbox:
  Filter:
    CASE
      WHEN  = 'Executive' THEN TRUE
      WHEN  = 'Manager' THEN department = 
      ELSE sales_rep_id = 
    END

Result:
  - Executive: 모든 주문
  - Manager: 자신의 부서 주문
  - Rep: 자신의 주문만

예제 3: 시간 기반 접근

1
2
3
4
5
6
7
8
9
10
11
Table: Financial_Reports
Group: Auditors

Sandbox:
  Filter: report_date >= DATE_SUB(CURRENT_DATE, INTERVAL  DAY)

User: External Auditor
  retention_days: 90

Result:
  최근 90일 리포트만 접근 가능

Advanced Sandboxing

다중 조건:

1
2
3
4
5
6
7
8
9
10
11
12
Table: Orders
Group: Sales Analysts

Sandbox filters (AND 조건):
  1. region = 
  2. created_at >= '2024-01-01'
  3. status IN ('completed', 'shipped')

Result:
  - 자신의 지역만
  - 2024년 이후만
  - 완료/배송 상태만

동적 테이블:

1
2
3
4
5
6
-- User attribute: accessible_customers (쉼표 구분 ID 목록)
-- "101,102,103"

SELECT *
FROM orders
WHERE customer_id IN ()

권한 설계 패턴

패턴 1: Role-Based (역할 기반)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Groups:
  - Admin
  - Analyst
  - Manager
  - Viewer

Permissions:
  Admin:
    Data: All databases (Unrestricted)
    Collections: All (Curate)

  Analyst:
    Data: Production DB (Unrestricted)
    Collections: Analytics (Edit), Others (View)

  Manager:
    Data: Production DB (Limited - GUI only)
    Collections: Department (Edit), Company (View)

  Viewer:
    Data: Production DB (No access)
    Collections: Dashboards only (View)

패턴 2: Department-Based (부서 기반)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Groups by Department:
  - Sales
  - Marketing
  - Finance
  - Engineering
  - HR

Permissions:
  Sales:
    Data: Orders, Customers (Unrestricted)
    Collections: Sales folder (Edit)
    Sandboxing: own territory

  Finance:
    Data: Financial tables (Unrestricted)
    Collections: Finance folder (Curate)
    Sandboxing: none (full access)

  Marketing:
    Data: Campaigns, Analytics (Limited)
    Collections: Marketing folder (Edit)
    Sandboxing: own campaigns

패턴 3: Project-Based (프로젝트 기반)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Groups by Project:
  - Project Alpha Team
  - Product Launch Team
  - Customer Success Initiative

Permissions:
  Project Alpha:
    Data: Alpha DB (Unrestricted)
    Collections: Project Alpha folder (Curate)
    Duration: 2025-01-01 to 2025-06-30 (임시)

  Product Launch:
    Data: Products, Orders (Limited)
    Collections: Launch Metrics (Edit)
    Collaboration: with Marketing, Sales

패턴 4: Hybrid (혼합)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Groups:
  - By Role: Admin, Analyst, Viewer
  - By Department: Sales, Marketing, Finance
  - By Project: Special initiatives

User: Jane
  Groups:
    - Analyst (role)
    - Marketing (department)
    - Project Alpha (project)

  Effective permissions:
    - Analyst 권한 (기본)
    - Marketing 데이터 추가 접근
    - Project Alpha 컬렉션 추가 접근

  계산: 모든 그룹 권한의 합집합 (가장 높은 권한 적용)

보안 Best Practices

1. 최소 권한 원칙

1
2
3
4
5
6
7
8
9
10
기본: No access
필요시: 점진적으로 권한 부여

❌ 나쁜 예:
  신규 사용자에게 "All Users = Unrestricted" 부여

✅ 좋은 예:
  1. 신규 사용자는 View only
  2. 필요성 검증 후 Edit 권한
  3. 비즈니스 케이스 있으면 Curate

2. 정기 권한 감사

1
2
3
4
5
6
7
8
9
10
11
12
13
14
월간:
  - 비활성 사용자 확인
  - 불필요한 권한 제거
  - 새 팀원 온보딩

분기별:
  - 그룹 구조 리뷰
  - 데이터 접근 패턴 분석
  - 권한 매트릭스 업데이트

연간:
  - 전체 권한 재설계 검토
  - 비즈니스 변화 반영
  - 보안 정책 업데이트

3. 민감 데이터 보호

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
High sensitivity (높은 민감도):
  - PII (개인식별정보)
  - 금융 데이터
  - 비밀 프로젝트

Protection:
  1. 별도 데이터베이스 분리
  2. 최소한의 그룹만 접근
  3. No SQL access (GUI only)
  4. Row-level security 적용
  5. 감사 로그 모니터링

Example:
  Table: customer_financial
  Access: Finance team only
  Sandboxing: 특정 고객만 (customer_id IN (...))
  SQL: No (GUI only)
  Logging: All queries logged

4. 외부 사용자 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
External Users (고객, 파트너, 컨설턴트):

Restrictions:
  - 전용 그룹 생성 (External)
  - 제한된 컬렉션 접근
  - Public Links 대신 계정 제공 (추적 가능)
  - Expiration date 설정
  - 데이터 export 제한

Example:
  Group: External Consultants
  Data: Custom database view (민감 정보 제거)
  Collections: Project X (View only)
  Duration: 2025-01-01 to 2025-03-31
  No download: CSV export disabled

5. 관리자 계정 보호

1
2
3
4
5
6
7
Admin account best practices:
  - 2FA (Two-factor authentication) 활성화
  - 강력한 비밀번호
  - 정기적 비밀번호 변경
  - 일반 작업은 일반 계정 사용
  - 관리 작업만 Admin 계정 사용
  - 모든 관리 작업 로깅

감사 및 모니터링

Audit Log

활성화:

1
2
3
4
5
6
7
8
9
Admin > Settings > General > Enable audit logging

Logged events:
  - User login/logout
  - Question/Dashboard created/edited/deleted
  - Database connections added/modified
  - Permissions changed
  - Data exports
  - Failed login attempts

로그 확인:

1
2
3
4
5
6
7
8
9
10
11
Admin > Troubleshooting > Logs > Audit

Filter:
  User: john@company.com
  Action: query
  Date range: Last 7 days

Result:
  - 2025-03-20 10:30: Created question "Sales by Region"
  - 2025-03-20 11:15: Exported data (1,234 rows)
  - 2025-03-20 14:00: Modified dashboard "Executive Summary"

사용 분석

활용도 모니터링:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 사용자별 활동 (예: PostgreSQL 기반)
SELECT
  user_id,
  COUNT(*) as query_count,
  COUNT(DISTINCT DATE(created_at)) as active_days
FROM query_execution_log
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
ORDER BY query_count DESC

-- 미사용 컨텐츠
SELECT
  q.id,
  q.name,
  q.created_at,
  COUNT(qe.id) as executions
FROM questions q
LEFT JOIN query_executions qe
  ON q.id = qe.question_id
  AND qe.created_at >= CURRENT_DATE - INTERVAL '90 days'
GROUP BY q.id, q.name, q.created_at
HAVING COUNT(qe.id) = 0
ORDER BY q.created_at DESC

보안 알림

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Alert 설정:

1. 비정상적 데이터 export:
   IF user.export_rows > 10000
   THEN notify security_team

2. 권한 변경:
   IF permission_changed
   THEN notify admin + log

3. 실패한 로그인:
   IF failed_logins > 5 IN 10 minutes
   THEN lock account + notify

4. 민감 데이터 접근:
   IF table = 'financial'
   THEN log + notify (real-time)

실전 연습 문제

연습 1: 기본 권한 설정 (초급)

과제: 3개 부서의 권한 구조 설정

부서:

  • Sales: Orders, Customers 접근
  • Marketing: Campaigns, Analytics 접근
  • Finance: 모든 데이터 접근
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Groups 생성:
  1. Sales Team
  2. Marketing Team
  3. Finance Team

Data Permissions:

Sales Team:
  Database: Production
    Orders: Unrestricted
    Customers: Unrestricted
    Products: Limited (GUI only)
    Campaigns: No access
    Financial: No access

Marketing Team:
  Database: Production
    Campaigns: Unrestricted
    Analytics: Unrestricted
    Customers: Limited (GUI only)
    Orders: Limited (GUI only)
    Financial: No access

Finance Team:
  Database: Production
    All tables: Unrestricted
    Native SQL: Allowed

Collection Permissions:

Sales Team:
  - Sales Analytics: Edit
  - Company Dashboards: View
  - Others: No access

Marketing Team:
  - Marketing Reports: Edit
  - Company Dashboards: View
  - Sales Analytics: View (협업)
  - Others: No access

Finance Team:
  - Finance Reports: Curate
  - All other collections: View

연습 2: Row-Level Security (중급)

과제: 영업 담당자별 데이터 분리

요구사항:

  • 각 영업 담당자는 자신의 고객만 볼 수 있음
  • 매니저는 팀 전체 볼 수 있음
  • VP는 모든 데이터 볼 수 있음
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
User Attributes 설정:

User: john@company.com (Sales Rep)
  - user_id: 123
  - role: rep
  - team_id: 5

User: jane@company.com (Sales Manager)
  - user_id: 456
  - role: manager
  - team_id: 5

User: mike@company.com (VP Sales)
  - user_id: 789
  - role: vp

Groups:
  - Sales Reps
  - Sales Managers
  - Sales Leadership

Sandboxing:

Table: Customers
Group: Sales Reps
Filter:
  sales_rep_id = 

Table: Customers
Group: Sales Managers
Filter:
  sales_rep_id IN (
    SELECT id FROM sales_reps
    WHERE team_id = 
  )

Table: Customers
Group: Sales Leadership
Filter: (none - 모든 데이터)

Table: Orders
(동일한 로직 적용)

Result:
  - John (Rep): 자신의 고객 123번만
  - Jane (Manager): 팀 5의 모든 담당자 고객
  - Mike (VP): 모든 고객

연습 3: 복합 보안 시나리오 (고급)

과제: 외부 컨설턴트 접근 관리

요구사항:

  • 특정 프로젝트 데이터만 접근
  • 3개월 제한
  • 민감 정보 제외
  • 모든 활동 로깅
해답 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
1. 전용 Database View 생성:

CREATE VIEW consultant_view AS
SELECT
  o.id,
  o.created_at,
  o.total,
  -- PII 제외
  CONCAT('Customer ', o.customer_id) as customer_ref,
  -- 주소 제외
  c.state as customer_state,
  -- 이메일/전화 제외
  p.category as product_category
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN products p ON o.product_id = p.id
WHERE o.project = 'Project Alpha'
  AND o.created_at >= '2025-01-01';

2. Group 생성:

Name: External Consultants - Project Alpha
Description: 임시 접근 (2025-01-01 ~ 2025-03-31)

Members:
  - consultant@external.com

3. Data Permissions:

Database: Analytics
  consultant_view: Limited (GUI only)
  All other tables: No access

Native SQL: No

4. Collection Permissions:

Project Alpha Reports: View only
All others: No access

5. Additional Restrictions:

Settings > External Consultants group:
  - Disable data exports
  - Disable dashboard subscriptions
  - Link sharing: No

6. Monitoring:

Audit log filter:
  Group: External Consultants
  Alert on:
    - Any export attempt
    - Access outside working hours
    - More than 100 queries/day

Weekly report to:
  - Project owner
  - Security team

7. Expiration:

Calendar reminder: 2025-03-31
  - Disable accounts
  - Revoke all access
  - Export activity log
  - Archive project data

다음 단계

권한과 보안을 마스터했습니다. 다음 포스트에서는:

  • 임베딩과 공유: Public dashboards, iFrames
  • 외부 통합: 웹사이트에 대시보드 삽입
  • 화이트라벨링: 브랜딩 커스터마이징

요약

권한 체크리스트

사용자 관리:

  • 조직 구조 기반 그룹 생성
  • 역할 정의 및 문서화
  • 신규 사용자 온보딩 프로세스
  • 퇴사자 접근 제거 프로세스

데이터 권한:

  • 데이터베이스별 접근 정책
  • 테이블별 세밀한 권한
  • Row-level security 검토
  • SQL 권한 제한

컬렉션 권한:

  • 논리적 폴더 구조
  • 부서별 컬렉션 분리
  • 공유 리소스 식별
  • 편집 권한 최소화

보안:

  • 최소 권한 원칙 적용
  • 정기 감사 스케줄
  • 민감 데이터 보호
  • 감사 로그 모니터링

다음 포스트에서는 Metabase를 외부에 공유하고 임베딩하는 방법을 배웁니다!

📚 시리즈 전체 목차

🚀 기초편 (1-5화)

  1. Metabase 소개와 핵심 개념
  2. 설치와 초기 설정
  3. 샘플 데이터 둘러보기
  4. 첫 차트 만들기 - 실습 완전정복
  5. 대시보드 만들기 - 한 화면에 모으기

💪 활용편 (6-10화)

  1. 필터와 파라미터
  2. SQL 네이티브 쿼리
  3. 데이터 모델링
  4. 자동화와 알림
  5. [권한과 보안] (현재 글)

🎯 고급편 (11-16화)

  1. 임베딩과 공유
  2. 성능 최적화
  3. 멀티 데이터소스
  4. 커스터마이징
  5. 운영과 모니터링
  6. 실전 프로젝트
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.