From ab190bf6faedfff4ef0845394f1af5b0e7180b2c Mon Sep 17 00:00:00 2001 From: devmrko Date: Thu, 25 Jun 2026 21:43:09 +0900 Subject: [PATCH] test #459: document edge scenarios and invalid token smoke --- .../README.md | 75 +++++++++++++++++++ docs/testing/459-permission-edge-scenarios.md | 56 ++++++++++++++ scripts/vpd-ords-regression-test.sh | 31 ++++++++ 3 files changed, 162 insertions(+) create mode 100644 docs/design/459-permission-edge-test-scenarios/README.md create mode 100644 docs/testing/459-permission-edge-scenarios.md diff --git a/docs/design/459-permission-edge-test-scenarios/README.md b/docs/design/459-permission-edge-test-scenarios/README.md new file mode 100644 index 0000000..7963eeb --- /dev/null +++ b/docs/design/459-permission-edge-test-scenarios/README.md @@ -0,0 +1,75 @@ +# 설계서: 권한 조합/경계값/오류 메시지 시나리오 확장 (#459) + +> **상태**: Approved +> **작성**: [AI] Architect · **최종수정**: 2026-06-25 +> **추적성** — Redmine: #459 · 관련 ADR: 없음 +> · 구현 파일: `docs/testing/459-permission-edge-scenarios.md`, `scripts/vpd-ords-regression-test.sh` · 테스트: `./run.sh backoffice-vpd-ords-test`, `mvn test` + +## 1. 목적 (Why) + +정상 권한 매트릭스뿐 아니라 잘못된 token, 권한 조합, 컬럼/값 누락, ORDS path 불일치 같은 운영 중 자주 발생할 경계 시나리오를 테스트 항목으로 고정한다. + +## 2. 범위 (Scope) + +- **포함**: 수동/E2E 테스트 체크리스트 문서, invalid bearer token 자동 smoke, 기대 오류 관점 정리. +- **제외**: Playwright 브라우저 자동화, 모든 UI 입력 케이스 자동화. + +## 3. 인수조건 (Acceptance Criteria) + +- [ ] 권한 조합/경계값/오류 메시지 체크리스트가 문서화된다. +- [ ] 자동 ORDS smoke에 invalid token 실패 검증이 포함된다. +- [ ] 실패 시 request/response evidence 경로가 출력된다. +- [ ] `mvn test`가 통과한다. + +## 4. 컨텍스트 & 제약 + +- ORDS 정상 매트릭스는 #458 스크립트를 재사용한다. +- UI 입력 검증은 #457에서 일부 보강됐고, 여기서는 테스트 관점에서 확인 항목을 정리한다. + +## 5. 아키텍처 개요 + +``` +docs/testing/459-permission-edge-scenarios.md + -> 수동/운영 테스트 체크리스트 + +scripts/vpd-ords-regression-test.sh + -> 정상 HR/SELF/ALL 검증 + -> invalid token smoke 검증 +``` + +## 6. 데이터 모델 + +- invalid token: DB에 등록하지 않은 UUID token. +- 기대 결과: HTTP 200이 아니어야 하며, 성공 rows로 해석되면 실패. + +## 7. 함수 명세 (Function Specs) + +| 함수 | 책임(1줄) | 시그니처(잠정) | 입력 | 출력 | 에러/실패 | 복잡? | +|------|-----------|----------------|------|------|-----------|-------| +| `call_and_assert_rejected` | 잘못된 token이 성공 조회로 처리되지 않는지 검증 | bash function | label, token | PASS/FAIL | HTTP 200이면 실패 | 단순 | + +## 8. 흐름 / 알고리즘 + +1. 정상 매트릭스 HR/SELF/ALL을 검증한다. +2. 등록되지 않은 token으로 같은 ORDS endpoint를 호출한다. +3. HTTP 200이면 실패, 아니면 거부 smoke PASS로 처리한다. +4. request/response evidence를 남긴다. + +## 9. 엣지케이스 & 에러 처리 + +- invalid token이 ORDS 403을 반환하는지 확인한다. +- ORDS 404/500도 성공 조회가 아니므로 이 smoke에서는 거부로 본다. 상세 오류 분류는 백오피스 probe classifier에서 검증한다. + +## 10. 테스트 계획 + +- `SQLCL_BIN=/tmp/sqlcl/sqlcl/bin/sql SQLCL_JAVA_HOME=... ./run.sh backoffice-vpd-ords-test` +- `mvn test` + +## 11. 리스크 & 대안 검토 + +- 선택: invalid token smoke를 기존 회귀 스크립트에 포함한다. 테스트 실행 시간이 거의 늘지 않고 보안 기본 동작을 고정할 수 있다. +- 대안: 별도 스크립트. 중복 token/ORDS 설정 로직이 생긴다. + +## 12. 미해결 질문 (Open Questions) + +- 브라우저 기반 권한 등록/삭제 자동화는 별도 E2E 도입 시 다룬다. diff --git a/docs/testing/459-permission-edge-scenarios.md b/docs/testing/459-permission-edge-scenarios.md new file mode 100644 index 0000000..4928b22 --- /dev/null +++ b/docs/testing/459-permission-edge-scenarios.md @@ -0,0 +1,56 @@ +# 권한 조합/경계값/오류 메시지 테스트 체크리스트 (#459) + +## 목적 + +VPD/ORDS 권한 백오피스에서 권한 저장, token 검증, ORDS 호출 실패가 운영자가 이해 가능한 결과로 드러나는지 확인한다. + +## 자동 Smoke + +| ID | 시나리오 | 실행 | 기대 결과 | +|----|----------|------|-----------| +| A-01 | HR token 문서 조회 | `./run.sh backoffice-vpd-ords-test` | 3행, `DOC_ID=[1,2,6]`, `CONTENTS` 없음 | +| A-02 | SELF token 문서 조회 | `./run.sh backoffice-vpd-ords-test` | 1행, `DOC_ID=[3]`, `CONTENTS` 없음 | +| A-03 | ALL token 문서 조회 | `./run.sh backoffice-vpd-ords-test` | 6행, `DOC_ID=[1,2,3,4,5,6]`, `CONTENTS` 있음 | +| A-04 | 미등록 bearer token 조회 | `./run.sh backoffice-vpd-ords-test` | HTTP 200 성공 rows로 처리되지 않음 | + +## 권한 저장 경계값 + +| ID | 입력 | 기대 결과 | +|----|------|-----------| +| P-01 | `ALL` 단독 | 저장 성공 | +| P-02 | `ALL` + 다른 rule | 저장 거부, `ALL 규칙은 다른 규칙과 함께 저장할 수 없습니다.` | +| P-03 | `MY_DEPT`, 컬럼 비움 | 저장 성공, VPD 기본 컬럼 `DEPT_CODE` 사용 | +| P-04 | `SELF`, 컬럼 비움 | 저장 성공, VPD 기본 컬럼 `OWNER_EMP_NO` 사용 | +| P-05 | `DEPT`, 값 비움 | 저장 거부, 값 필요 메시지 | +| P-06 | `EMP_NO`, 값 비움 | 저장 거부, 값 필요 메시지 | +| P-07 | `=`, 컬럼 비움 | 저장 거부, 컬럼 필요 메시지 | +| P-08 | `!=`, 값 비움 | 저장 거부, 값 필요 메시지 | +| P-09 | 보호 객체에 없는 컬럼 | 저장 거부 또는 DB VPD 함수에서 fail-closed | + +## 권한 조합 + +| ID | 조합 | 기대 결과 | +|----|------|-----------| +| C-01 | 동일 사용자에게 HR role + SELF role | 두 rule이 OR 조건으로 합쳐진 결과 | +| C-02 | 동일 사용자에게 ALL role 포함 | 전체 행 조회 | +| C-03 | 권한 삭제 후 해당 객체 권한 0개 | 보호 객체 드롭다운에서 protected 표시 제거 | +| C-04 | 민감 컬럼 예외 없음 | 민감 컬럼 NULL/미노출 | +| C-05 | 민감 컬럼 예외 있음 | 허용 role에서만 민감 컬럼 노출 | + +## ORDS/환경 오류 + +| ID | 상황 | 기대 메시지 방향 | +|----|------|------------------| +| O-01 | ORDS base URL 미설정 | `ORDS_NOT_CONFIGURED`, 설정 조치 안내 | +| O-02 | ORDS path 불일치 | `ORDS_PATH_NOT_FOUND`, schema/module/template 확인 안내 | +| O-03 | ORDS handler PL/SQL 오류 | `ORDS_USER_DEFINED_RESOURCE_ERROR`, response body 표시 | +| O-04 | DB 연결 실패 | DB URL/사용자/비밀번호/ADB wallet 확인 안내 | +| O-05 | token 만료/폐기 | 권한 결과가 아니라 token 거부로 표시 | + +## 수동 확인 절차 + +1. `권한` 탭에서 `MY_DEPT`, `SELF`, `DEPT`, `EMP_NO`, `=`, `!=`를 각각 저장해 본다. +2. 저장 후 권한 목록의 `적용 필터`가 실제 rule 의미와 일치하는지 확인한다. +3. `ORDS 검증` 탭에서 HR/SELF/ALL token으로 결과를 비교한다. +4. 잘못된 ORDS path를 임시로 넣어 request/response header/body가 표시되는지 확인한다. +5. 권한 삭제 후 보호 객체 표시가 갱신되는지 확인한다. diff --git a/scripts/vpd-ords-regression-test.sh b/scripts/vpd-ords-regression-test.sh index f7d8b78..e54b875 100644 --- a/scripts/vpd-ords-regression-test.sh +++ b/scripts/vpd-ords-regression-test.sh @@ -137,6 +137,36 @@ print(f"[PASS] {label}: rows={len(rows)} ids={ids} rows_with_contents={contents_ PY } +call_and_assert_rejected() { + local label="$1" token="$2" + local response_file="$WORK_DIR/${label}.response.json" + local request_file="$WORK_DIR/${label}.request.txt" + local url="${ORDS_BASE%/}/${ORDS_PATH}?limit=50" + + { + printf "POST %s\n" "$url" + printf "Authorization: Bearer ****%s\n" "${token: -6}" + printf "Content-Type: application/json\n" + printf "{}\n" + } >"$request_file" + + local status + status="$(curl -sS -o "$response_file" -w "%{http_code}" \ + -X POST "$url" \ + -H "Authorization: Bearer $token" \ + -H "Content-Type: application/json" \ + -d "{}")" + + if [[ "$status" == "200" ]]; then + echo "[FAIL] $label: invalid token returned HTTP 200" + echo " request=$request_file" + echo " response=$response_file" + exit 1 + fi + + echo "[PASS] $label: rejected with HTTP $status" +} + echo "[INFO] SQLcl: $SQLCL_BIN" echo "[INFO] ORDS: ${ORDS_BASE%/}/${ORDS_PATH}" echo "[INFO] Evidence: $WORK_DIR" @@ -145,5 +175,6 @@ insert_tokens call_and_assert "HR" "$TOKEN_HR" "3" "1,2,6" "0" call_and_assert "SELF" "$TOKEN_SELF" "1" "3" "0" call_and_assert "ALL" "$TOKEN_ALL" "6" "1,2,3,4,5,6" "6" +call_and_assert_rejected "INVALID_TOKEN" "codex_invalid_$(uuidgen)" echo "[PASS] VPD/Redaction ORDS regression passed"