Skip to content

security auth rbac

JJong-03 edited this page Jun 18, 2026 · 2 revisions

Dashboard 인증과 RBAC

Cognito는 사용자를 인증하고, RDS PostgreSQL의 앱 테이블은 역할과 접근 범위를 결정한다. Frontend 표시 정책과 Backend 강제 인가는 서로 다른 계층이다.

인증과 인가 경계

Cognito User Pool
  로그인, MFA/임시 비밀번호, Hosted UI, JWT 발급
          |
          v
Dashboard Web
  OIDC Authorization Code + PKCE, access token 전달
          |
          v
FastAPI Backend
  JWT 검증 -> Cognito sub 조회 -> RDS Principal 생성 -> endpoint 인가
          |
          v
RDS PostgreSQL
  app_user, factory, user_factory_access, audit_log

PostgreSQL 사람별 DB role을 만드는 구조가 아니다. Backend 서비스 계정만 DB에 접속하며, 애플리케이션 사용자의 권한은 앱 테이블에서 관리한다.

Cognito JWT 검증

Backend deps/auth.py는 다음을 검증한다.

  • Authorization: Bearer 존재
  • Cognito JWKS의 kid와 RS256 signature
  • User Pool issuer
  • access token의 client_id 또는 ID token의 aud
  • token_useaccess 또는 id
  • token 만료 등 JOSE 기본 검증

JWKS는 TTL cache와 lock을 사용한다. 갱신 실패 시 기존 cache가 있으면 사용하고, 검증 실패는 401WWW-Authenticate: Bearer로 반환한다.

WebSocket은 query의 JWT를 같은 방식으로 검증한다. 인증 실패는 close code 4001, 앱 사용자/공장 권한 실패는 4003이다.

RDS 권한 모델

테이블 역할
app_user Cognito sub, email, 표시 이름, global role, System 권한, 상태
factory 앱에서 관리하는 공장 목록
user_factory_access 사용자별 공장 grant와 legacy 공장 role
audit_log 사용자 생성/수정/삭제 actor와 target

JWT의 sub로 active app_user를 찾는다.

  • 사용자가 없으면 403 User is not provisioned
  • disabled면 403 User is disabled
  • 설정된 bootstrap sub는 RDS row 없이 임시 super_admin Principal로 허용

역할

역할 현재 의미
super_admin 모든 공장, 사용자 관리, System 접근
factory_admin user_factory_access에 배정된 공장만 접근
org_admin legacy global 관리자. 모든 공장, 사용자 관리, System 접근
viewer legacy 제한 사용자. 배정 공장과 별도 System flag 적용

사용자 생성/수정 API와 UI는 super_admin과 legacy org_admin만 허용한다. factory_admin, viewer는 생성·부여 가능한 사용자 역할이지만 사용자 관리 endpoint 접근 권한은 아니다.

공장 grant의 admin/viewer도 legacy 호환 값이다. 현재 factory_admin을 저장할 때 grant는 admin으로 정규화되며, 공장 조회 endpoint는 두 값을 기능별로 구분하지 않고 factory ID 포함 여부로 접근을 판단한다.

can_view_system

RDS에는 app_user.can_view_system이 저장된다. Principal의 실제 System 접근은:

can_access_system = can_manage_users OR can_view_system
can_manage_users  = global_role in {super_admin, org_admin}

따라서:

  • super_admin, legacy org_admin: 항상 System 접근
  • factory_admin: can_view_system=true일 때만 System 접근
  • legacy viewer: flag가 true이면 System 접근

GET /auth/mecan_view_system은 DB 원본 flag가 아니라 위의 최종 can_access_system 결과다. Frontend는 이 값을 Sidebar와 Reports selector에 사용한다.

Endpoint별 권한

Endpoint Backend 정책
GET /healthz 공개
GET /auth/me 유효 JWT + active/provisioned 앱 사용자
GET /factories 허용 공장만 필터링
GET /factories/{id} 권한 없는 공장은 403
GET /factories/{id}/history 권한 없는 공장은 403
WS /ws/factories/{id} 구독 전 공장 권한 검사, 실패 시 4003
GET /reports 공장 보고서는 허용 공장만, Cloud Infra는 System 권한 사용자만
GET /reports/{date}/{id} 공장은 공장 권한, cloud-infra는 System 권한, 실패 시 403
GET /cloud-infra System 권한, 없으면 403
GET /cloud-infra/history System 권한, 없으면 403
GET/POST /admin/users super_admin 또는 legacy org_admin, 없으면 403
PATCH/DELETE /admin/users/{id} super_admin 또는 legacy org_admin, 없으면 403

404는 권한 거부의 대체가 아니다. 공장/보고서 권한은 먼저 403으로 거부하고, 권한이 있는 대상의 실제 데이터가 없을 때 404를 반환한다.

Frontend 표시와 Backend 강제의 차이

기능 Frontend 표시 정책 Backend 강제 정책
공장 목록 /factories 응답만 표시 서버가 허용 공장만 필터링
공장 상세 Sidebar에 허용 공장만 표시 직접 URL/API도 공장 권한 검사
Cloud Infra can_view_system일 때 메뉴 표시 두 endpoint 모두 System 권한 검사
Cloud Infra 보고서 can_view_system일 때 selector 표시 보고서 조회 시 System 권한 검사
사용자 관리 can_manage_users일 때 메뉴 표시 모든 admin endpoint에서 관리자 검사
SPA route 로그인 여부만 검사 데이터 요청마다 Principal과 권한 검사

메뉴 숨김은 보안 통제가 아니다. 사용자가 숨겨진 route를 직접 입력하거나 REST를 직접 호출해도 Backend가 동일한 권한을 강제해야 한다.

사용자 생성, 수정, 삭제

생성

  1. 관리자 권한 검사
  2. 역할과 공장 ID 검증
  3. Cognito 사용자 생성
  4. RDS app_user와 공장 grant 생성
  5. audit log 기록

중복 active email은 409, 알 수 없는 공장은 400, Cognito 작업 실패는 502다. 과거 disabled row가 남아 있으면 stale Cognito/RDS 정보를 정리한 뒤 재생성한다.

수정

  • email은 UI에서 변경하지 않는다.
  • global 관리자는 개별 공장 grant를 가질 수 없다.
  • factory_admin grant role은 admin으로 정규화한다.
  • super_admin의 System 권한은 항상 true다.
  • 변경 후 audit log를 기록한다.

삭제

Cognito 사용자를 먼저 삭제하고 RDS grant/user를 삭제한다. Cognito 삭제가 실패하면 RDS만 먼저 지우지 않고 502를 반환한다. 성공한 작업은 audit log에 기록한다.

Cognito와 RDS 일관성

인증 성공과 앱 인가 성공은 별개다.

  • Cognito에만 존재: 로그인은 가능하지만 Backend에서 미등록 사용자 403
  • RDS에만 존재: Cognito 로그인이 불가능하므로 앱 접근 불가
  • Cognito sub 불일치: RDS 사용자를 찾지 못해 403
  • RDS disabled: Cognito token이 유효해도 403
  • 생성/삭제 Cognito Admin API 실패: Backend가 502를 반환하고 성공으로 확정하지 않음

운영 시 사용자 lifecycle은 /admin/users API를 통해 수행해 두 저장소를 함께 변경해야 한다. Cognito console 또는 RDS를 한쪽만 수동 변경하면 위 불일치가 발생할 수 있다.

관련 문서

Aegis-Pi Wiki

· 대표 문서 목록은 홈의 문서 탐색 표 참조

시작하기

요구사항

핵심 개념

아키텍처

컴포넌트 (Edge → Cloud → Dashboard)

Dashboard & 운영

시나리오 · 사례 · 참조

Clone this wiki locally