POSA_LEAKSMS/run_tests.sh
cw2007 7fa39406d3 feat(observability): 수집 거부 출처 IP 로그 + 대시보드 노출
수집 거부 카운터는 사유별 숫자만 남겨, "우리 노드 오설정 vs 외부 스캐너"를
구분할 수 없었다. 서명불일치 2건이 우리 노드의 키 불일치인지 인터넷 프로브인지
대시보드만으론 판별 불가했다.

- config.php: 최근 거부 이벤트 링버퍼(var/ingest_reject_events.json, 상한
  INGEST_REJECT_EVENTS_MAX=50, flock 기반 DoS 안전) 추가. record_ingest_rejection()
  이 모든 거부에서 출처 IP(REMOTE_ADDR, 형식검증)를 자동 기록한다. 본문 유래
  값(device_id 등)은 신뢰불가 → ingest_sanitize_token() 으로 제어문자 제거·절단
  (로그 인젝션 방어). var/ 는 .htaccess 로 웹 접근 차단됨.
- api/sensor_data.php: 서명 거부 시 서명모드(raw=키불일치/none=헤더스트립)와
  device_id 를 컨텍스트로 함께 남겨 출처 판별을 돕는다.
- dashboard.php: '수집 거부' 위젯 아래 '최근 거부 출처' 표(시각·IP·사유·모드·
  device_id) 노출. 모든 필드 htmlspecialchars.
- tests/ingest_reject_log_test.php: 로그 인젝션 제거·IP 형식검증 회귀 추가,
  run_tests.sh 등록. security_hardening_test.php 소스 회귀 5종 추가.

주: config.php 에는 작업 트리에 있던 선행 변경(METRIC_SENSOR_IDS — 대시보드
온습도 센서카드 목록)이 함께 포함된다.
2026-07-09 13:43:12 +09:00

55 lines
2.3 KiB
Bash

#!/usr/bin/env bash
# =============================================================================
# run_tests.sh - 전체 회귀 테스트 러너 (CI / 수동)
#
# 실행 대상:
# 1) PHP 단위/회귀 테스트 3종 (tests/*.php)
# 2) 펌웨어 호스트 패리티 (firmware/test/host/parity_test.py)
# - C↔Python↔PHP 서명 패리티(gcc/clang + php 가용 시 C 포함)
#
# php / python3 / gcc 가 없으면 해당 묶음을 SKIP 으로 *명확히* 보고한다(무성 스킵 금지).
# 하나라도 FAIL 이면 종료코드 1.
# =============================================================================
set -u
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
fail=0; ran=0; skipped=0
have() { command -v "$1" >/dev/null 2>&1; }
run_php() { # test_file
local f="$1"
if ! have php; then echo "SKIP (php 없음): ${f}"; skipped=$((skipped+1)); return; fi
echo "── php ${f}"
if php "${ROOT}/${f}"; then ran=$((ran+1)); else echo " FAIL: ${f}"; fail=1; fi
}
echo "=== 1) PHP 회귀 테스트 ==="
run_php tests/raw_body_signature_test.php
run_php tests/security_hardening_test.php
run_php tests/threshold_sms_test.php
run_php tests/cooldown_episode_test.php # 에피소드 인지 쿨다운(복구 후 재발 누락 회귀)
run_php tests/ingest_reject_log_test.php # 수집 거부 출처 로그(IP·로그인젝션 방지)
run_php tests/chaos_drill.php # SMS 실패 주입 경로 드릴
run_php tests/forecast_test.php # 예보(이슬점/회귀/ETA/여유/신선도/위험) 순수함수
echo ""
echo "=== 2) 펌웨어 호스트 패리티 (C↔Python↔PHP) ==="
if have python3 && have php; then
echo "── python3 firmware/test/host/parity_test.py"
if ( cd "${ROOT}/firmware/test/host" && python3 parity_test.py ); then
ran=$((ran+1))
else
echo " FAIL: parity_test.py"; fail=1
fi
if ! have gcc && ! have cc && ! have clang; then
echo " NOTE: C 컴파일러 없음 — 위 패리티는 Python↔PHP 만 검증(C 서명 미컴파일)."
fi
else
echo "SKIP (python3/php 없음): firmware/test/host/parity_test.py"; skipped=$((skipped+1))
fi
echo ""
echo "=== 요약: 실행 ${ran}, 스킵 ${skipped} ==="
if [ "${fail}" -ne 0 ]; then echo "결과: FAIL"; exit 1; fi
if [ "${ran}" -eq 0 ]; then echo "결과: NO-OP (실행된 테스트 없음 — php/python3 설치 필요)"; exit 0; fi
echo "결과: PASS"