feat(database): PostgreSQL RLS 접근 거부 관측과 제한 역할 E2E 검증 - #99
Merged
Conversation
- SQLSTATE 42501을 cause 및 next-exception 체인에서 안전하게 분류한다. - 접근 거부를 내부 500 응답, route-pattern 로그와 단일 metric으로 관측한다. - 일반 낙관적 락은 기존 CONCURRENT_MODIFICATION 계약을 유지한다.
제한 시간 advisory lock으로 공유 PostgreSQL 보안 테스트를 직렬화한다. 테이블별 RLS와 FORCE 초기 상태를 저장해 정확히 복원하고, setup/cleanup 실패 시에도 역할과 연결 정리를 끝까지 수행하며 오류를 보존한다.
제한된 PostgreSQL 역할로 Worker 저장소의 조회·생성·수정·삭제 실패 폐쇄 동작을 검증한다. 역할과 Spring 애플리케이션 수명주기, Worker 데이터와 스냅샷을 두 fixture로 분리하고 기존 RLS 잠금·상태 복원 및 안전한 정리 순서를 유지한다.
임시 제한 runtime role과 명시적 최소 GRANT로 Spring 애플리케이션을 기동해 Login, Refresh Token, Worker Link 및 Worker API의 tenant 격리를 검증한다. 테스트 전용 unbound INSERT로 SQLSTATE 42501의 안전한 HTTP 응답·로그·metric 계약을 확인하고, fixture ID 충돌 방지와 RLS 상태 복원 및 역할 정리 순서를 보장한다.
CI·로컬 임시 제한 역할과 staging runtime 역할의 책임을 구분하고, SQLSTATE 42501 관측과 silent filtering의 차이를 정리한다. HTTP E2E, advisory lock, RLS 상태 복원, production DELETE 비범위와 staging 후속 검증 조건을 rollout 가이드에 기록한다.
Outbox 통합 테스트에 고정 UTC Clock을 주입해 최초 발행과 즉시 claim의 시간 비교를 결정적으로 만든다. lease 만료 시각도 애플리케이션 Clock 기준으로 설정해 H2 DB 시계와의 경계 차이로 발생하는 간헐 실패를 방지한다.
Contributor
|
ㅎㅇ |
공유 PostgreSQL 테스트가 Flyway migration 전에 advisory lock을 획득하도록 수명주기 순서를 통일한다. HTTP 및 RLS isolation fixture가 직접 변경하는 task와 user_account 테이블의 RLS 상태를 정확히 저장·복원하고, 제한 runtime role에 task 권한이 없음을 검증한다.
Contributor
|
확인했습니다! 참고로 코드 문제는 아니지만, 열린 PR인 #100·#102도 PostgreSqlRlsIsolationTest.java를 수정하고 있어서 나중에 병합하는 PR에서 충돌 정리는 필요합니다. |
# Conflicts: # src/test/java/com/fowoco/server/common/security/PostgreSqlRlsIsolationTest.java
hywznn
approved these changes
Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
관련 Issue
이번 PR은 운영·staging runtime role 발급이나 RLS 활성화 migration까지 포함하지 않습니다.
해당 작업은 #9와 staging 검증에서 이어서 진행합니다.
무엇을 바꾸나요?
42501을 cause chain과SQLException#getNextException()chain에서 분류합니다.route pattern 기반 구조화 로그와 저카디널리티 metric으로 관측합니다.
ObjectOptimisticLockingFailureException은 기존CONCURRENT_MODIFICATION계약을 유지합니다.주요 보안 계약
42501만DATABASE_ACCESS_DENIED관측 대상으로 분류합니다.USING에 따른 SELECT empty 및 UPDATE·DELETE 0건은 silent filtering으로 취급하며42501로 오분류하지 않습니다.NOSUPERUSER,NOBYPASSRLS,NOINHERIT이고 table owner나 migration role member가 아닙니다.어떻게 검증했나요?
아래 테스트는 사용자가 로컬에서 직접 실행해 통과를 확인했습니다.
AuthSecurityIntegrationTest.replayingAUsedRefreshTokenRevokesTheWholeFamily()가 간헐 실패했으나, 같은 코드로 이어진 전체 실행 2회는 통과했습니다.API·DB·운영 영향
후속 작업