ops #460: add SQLcl environment check runbook

This commit is contained in:
devmrko
2026-06-25 21:45:41 +09:00
parent ab190bf6fa
commit 1869fe46a6
4 changed files with 251 additions and 1 deletions

View File

@@ -0,0 +1,82 @@
# 설계서: SQLcl 기반 배포/롤백 런북 및 환경 점검 명령 정리 (#460)
> **상태**: Approved
> **작성**: [AI] Architect · **최종수정**: 2026-06-25
> **추적성** — Redmine: #460 · 관련 ADR: 없음
> · 구현 파일: `scripts/check-sqlcl-backoffice-env.sh`, `docs/runbooks/460-sqlcl-vpd-deploy-runbook.md`, `run.sh` · 테스트: `./run.sh backoffice-env-check`
## 1. 목적 (Why)
운영자가 신규 DB/ORDS 환경에서 SQLcl, JDK, ADB 접속, ORDS endpoint를 적용 전에 점검하고 VPD filter 배포/검증/롤백 순서를 확인할 수 있게 한다.
## 2. 범위 (Scope)
- **포함**: SQLcl/JDK/DB/ORDS 환경 점검 스크립트, 배포/검증/롤백 런북, `run.sh backoffice-env-check` 명령.
- **제외**: SQLcl 설치 자동화, JDK 설치 자동화, ORDS metadata 자동 생성.
## 3. 인수조건 (Acceptance Criteria)
- [ ] SQLcl 실행 파일과 버전을 확인한다.
- [ ] Java 버전을 확인한다.
- [ ] DB 접속 사용자와 `CB_AGENT_DOC_VPD_FILTER` 상태를 확인한다.
- [ ] ORDS base URL과 documents endpoint의 HTTP 상태를 확인한다.
- [ ] 운영자가 실행할 배포/검증/롤백 순서가 문서화된다.
## 4. 컨텍스트 & 제약
- `.env`는 민감 정보를 포함하므로 점검 출력에 password/token을 출력하지 않는다.
- SQLcl 경로는 `SQLCL_BIN` 우선, 없으면 PATH의 `sql`을 사용한다.
- JDK는 `SQLCL_JAVA_HOME`이 있으면 `JAVA_HOME`으로 사용한다.
## 5. 아키텍처 개요
```
run.sh backoffice-env-check
-> scripts/check-sqlcl-backoffice-env.sh
-> SQLcl version
-> Java version
-> SELECT USER, function status
-> curl ORDS endpoint
```
## 6. 데이터 모델
- 입력 환경변수: `SQLCL_BIN`, `SQLCL_JAVA_HOME`, `BACKOFFICE_DB_USERNAME`, `BACKOFFICE_DB_PASSWORD`, `ADB_TNS`, `BACKOFFICE_ORDS_BASE_URL`.
- 출력: PASS/FAIL 로그, 민감값 마스킹.
## 7. 함수 명세 (Function Specs)
| 함수 | 책임(1줄) | 시그니처(잠정) | 입력 | 출력 | 에러/실패 | 복잡? |
|------|-----------|----------------|------|------|-----------|-------|
| `resolve_sqlcl` | SQLcl 실행 파일 찾기 | bash function | env/path | path | 없으면 exit 1 | 단순 |
| `check_db` | DB 접속과 function 상태 확인 | bash function | SQLcl connection | PASS/FAIL | SQLcl exit code | 단순 |
| `check_ords` | ORDS endpoint HTTP 상태 확인 | bash function | base url/path | PASS/WARN | curl status | 단순 |
## 8. 흐름 / 알고리즘
1. `.env`를 로드한다.
2. SQLcl 경로와 Java 버전을 출력한다.
3. DB 접속 필수값 존재 여부를 확인한다.
4. SQLcl로 현재 사용자와 VPD function 상태를 조회한다.
5. ORDS endpoint에 GET을 보내 상태 코드를 확인한다.
6. 다음 실행 명령을 안내한다.
## 9. 엣지케이스 & 에러 처리
- SQLcl 없음: `SQLCL_BIN=/path/to/sql` 안내.
- DB 접속 실패: DB 설정 확인 메시지.
- ORDS 404: base URL/path 확인 경고.
- ORDS 401/403: endpoint는 살아 있으나 인증 필요 상태로 안내.
## 10. 테스트 계획
- `SQLCL_BIN=/tmp/sqlcl/sqlcl/bin/sql SQLCL_JAVA_HOME=... ./run.sh backoffice-env-check`
## 11. 리스크 & 대안 검토
- 선택: bash 점검 스크립트. 운영자가 Java/Maven 없이도 SQLcl/curl만으로 확인 가능하다.
- 대안: Spring Boot health endpoint. 앱이 뜨기 전 문제를 잡기 어렵다.
## 12. 미해결 질문 (Open Questions)
- SQLcl을 repo 외부 어디에 표준 설치할지는 사용자 로컬/운영 환경 정책에 따른다.

View File

@@ -0,0 +1,78 @@
# SQLcl VPD 배포/검증/롤백 런북 (#460)
## 사전 점검
```bash
SQLCL_BIN=/path/to/sql \
SQLCL_JAVA_HOME=/path/to/jdk \
./run.sh backoffice-env-check
```
확인 항목:
- SQLcl 버전이 출력된다.
- Java 11 이상이 출력된다.
- DB 현재 사용자가 의도한 schema다. 예: `ADMIN`.
- `CB_AGENT_DOC_VPD_FILTER` 상태가 `VALID`다.
- ORDS endpoint가 200/401/403 중 하나를 반환한다. 404면 base URL 또는 path가 맞지 않는다.
## VPD filter 배포
```bash
SQLCL_BIN=/path/to/sql SQLCL_JAVA_HOME=/path/to/jdk "$SQLCL_BIN" "USER/PASSWORD@TNS"
```
SQLcl 안에서 실행:
```sql
@sql/adb/26_agent_ords_security_dynamic_vpd_filter.sql
SHOW ERRORS FUNCTION cb_agent_doc_vpd_filter
@sql/adb/27_agent_ords_security_dynamic_vpd_filter_test.sql
```
기대 결과:
- function compile 성공
- `SHOW ERRORS` 결과 없음
- `Dynamic VPD filter unit checks passed`
## ORDS 회귀 검증
```bash
SQLCL_BIN=/path/to/sql \
SQLCL_JAVA_HOME=/path/to/jdk \
./run.sh backoffice-vpd-ords-test
```
기대 결과:
- HR: 3행, `DOC_ID=[1,2,6]`, `CONTENTS` 미노출
- SELF: 1행, `DOC_ID=[3]`, `CONTENTS` 미노출
- ALL: 6행, `DOC_ID=[1,2,3,4,5,6]`, `CONTENTS` 노출
- INVALID_TOKEN: HTTP 403 등 성공이 아닌 응답
## 장애 시 확인 순서
1. `./run.sh backoffice-env-check`로 SQLcl/JDK/DB/ORDS 상태를 먼저 확인한다.
2. DB function이 `INVALID``SHOW ERRORS FUNCTION cb_agent_doc_vpd_filter`를 본다.
3. ORDS가 404면 `BACKOFFICE_ORDS_BASE_URL``cb_protected_object.ords_path`를 비교한다.
4. ORDS가 403이면 token hash, 만료시각, revoke 여부를 확인한다.
5. 행 수가 맞지 않으면 `cb_user_role`, `cb_permission`, `cb_permission_rule`을 확인한다.
## 롤백
가장 단순한 롤백은 직전 Git revision의 `26_agent_ords_security_dynamic_vpd_filter.sql`을 다시 적용하는 것이다.
```bash
git show HEAD~1:sql/adb/26_agent_ords_security_dynamic_vpd_filter.sql > /tmp/previous-vpd-filter.sql
SQLCL_BIN=/path/to/sql SQLCL_JAVA_HOME=/path/to/jdk "$SQLCL_BIN" "USER/PASSWORD@TNS"
```
SQLcl 안에서:
```sql
@/tmp/previous-vpd-filter.sql
SHOW ERRORS FUNCTION cb_agent_doc_vpd_filter
```
롤백 후에도 반드시 ORDS 회귀 검증을 다시 실행한다.

10
run.sh
View File

@@ -10,6 +10,7 @@
# ./run.sh tests # 4-user (my/pg/both/none) 로 접속해서 행 필터 검증
# ./run.sh audit # admin 으로 정책/뷰/유저 상태 점검
# ./run.sh backoffice-support # Spring Boot 백오피스 보조 객체 생성
# ./run.sh backoffice-env-check # SQLcl/JDK/DB/ORDS 환경 점검
# ./run.sh backoffice-vpd-ords-test # SQLcl + ORDS VPD/Redaction 회귀 테스트
# ./run.sh all # source → adb → tests → audit
# ./run.sh teardown # ADB 측 객체 + 원격 link/cred 만 정리 (원격 PG/MySQL 데이터는 보존)
@@ -181,6 +182,12 @@ do_backoffice_vpd_ords_test() {
ok "backoffice-vpd-ords-test 완료"
}
do_backoffice_env_check() {
log "=== backoffice-env-check: SQLcl/JDK/DB/ORDS 환경 점검 ==="
bash "$ROOT/scripts/check-sqlcl-backoffice-env.sh"
ok "backoffice-env-check 완료"
}
do_teardown() {
log "=== teardown: ADB 측 객체 + dblink/credential 정리 ==="
warn "원격 PG/MySQL 의 customers 테이블은 건드리지 않습니다 (수동으로 DROP 하세요)"
@@ -233,6 +240,7 @@ case "$CMD" in
tests) do_prereq; do_tests ;;
audit) do_prereq; do_audit ;;
backoffice-support) do_prereq; do_backoffice_support ;;
backoffice-env-check) do_backoffice_env_check ;;
backoffice-vpd-ords-test) do_backoffice_vpd_ords_test ;;
teardown) do_prereq; do_teardown ;;
all)
@@ -253,6 +261,6 @@ case "$CMD" in
ok "=== DDS DONE — Deep Data Security 변형 셋업 + 검증 통과 ==="
;;
*)
die "알 수 없는 명령: $CMD (사용: prereq|source|adb|tests|audit|backoffice-support|backoffice-vpd-ords-test|all|teardown | dds|dds-setup|dds-tests|dds-teardown)"
die "알 수 없는 명령: $CMD (사용: prereq|source|adb|tests|audit|backoffice-support|backoffice-env-check|backoffice-vpd-ords-test|all|teardown | dds|dds-setup|dds-tests|dds-teardown)"
;;
esac

View File

@@ -0,0 +1,82 @@
#!/usr/bin/env bash
# Check SQLcl/JDK/ADB/ORDS prerequisites for the VPD backoffice scripts.
set -Eeuo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
if [[ -f "$ROOT/.env" ]]; then
# shellcheck disable=SC1091
set -a; . "$ROOT/.env"; set +a
fi
SQLCL_BIN="${SQLCL_BIN:-}"
if [[ -z "$SQLCL_BIN" ]]; then
SQLCL_BIN="$(command -v sql || true)"
fi
if [[ -n "${SQLCL_JAVA_HOME:-}" ]]; then
export JAVA_HOME="$SQLCL_JAVA_HOME"
fi
DB_USER="${BACKOFFICE_DB_USERNAME:-${ADB_USER:-}}"
DB_PASSWORD="${BACKOFFICE_DB_PASSWORD:-${ADB_PASSWORD:-}}"
DB_TNS="${ADB_TNS:-}"
ORDS_BASE="${BACKOFFICE_ORDS_BASE_URL:-https://yh0olybn5pqce4n-d8aukro81636mon0.adb.ap-seoul-1.oraclecloudapps.com/ords}"
ORDS_PATH="${BACKOFFICE_REGRESSION_ORDS_PATH:-cb-ords/cb-agent-security/vpd/documents}"
fail() {
echo "[FAIL] $*" >&2
exit 1
}
warn() {
echo "[WARN] $*" >&2
}
pass() {
echo "[PASS] $*"
}
[[ -n "$SQLCL_BIN" && -x "$SQLCL_BIN" ]] || fail "SQLcl을 찾을 수 없습니다. SQLCL_BIN=/path/to/sql 로 지정하세요."
[[ -n "$DB_USER" ]] || fail "BACKOFFICE_DB_USERNAME 또는 ADB_USER가 필요합니다."
[[ -n "$DB_PASSWORD" ]] || fail "BACKOFFICE_DB_PASSWORD 또는 ADB_PASSWORD가 필요합니다."
[[ -n "$DB_TNS" ]] || fail "ADB_TNS가 필요합니다."
echo "[INFO] SQLcl path: $SQLCL_BIN"
"$SQLCL_BIN" -version
if command -v java >/dev/null 2>&1; then
java -version 2>&1 | sed -n '1,3p'
else
warn "java 명령을 PATH에서 찾을 수 없습니다. SQLcl이 자체 Java를 쓰지 않는 환경이면 실패할 수 있습니다."
fi
echo "[INFO] DB user: $DB_USER"
{
printf "%s\n" "WHENEVER SQLERROR EXIT SQL.SQLCODE"
printf "%s\n" "SET SQLFORMAT ansiconsole"
printf "%s\n" "SELECT USER AS current_user FROM dual;"
printf "%s\n" "SELECT object_name, status FROM user_objects WHERE object_name = 'CB_AGENT_DOC_VPD_FILTER';"
printf "%s\n" "exit"
} | "$SQLCL_BIN" -s "$DB_USER/$DB_PASSWORD@$DB_TNS"
pass "DB 접속 및 VPD function 상태 조회 완료"
ORDS_URL="${ORDS_BASE%/}/${ORDS_PATH}?limit=1"
STATUS="$(curl -sS -o /tmp/vpd-backoffice-env-check-ords.json -w "%{http_code}" \
-X POST "$ORDS_URL" \
-H "Content-Type: application/json" \
-d "{}" || true)"
case "$STATUS" in
200|401|403)
pass "ORDS endpoint 응답 확인: HTTP $STATUS"
;;
404)
warn "ORDS endpoint가 404입니다. BACKOFFICE_ORDS_BASE_URL과 ORDS path를 확인하세요: $ORDS_URL"
;;
*)
warn "ORDS endpoint 응답이 예상 밖입니다: HTTP $STATUS ($ORDS_URL)"
;;
esac
echo "[INFO] 다음 검증: ./run.sh backoffice-vpd-ords-test"