POSA_LEAKSMS/docs/OPERATIONS_SECURITY_CHECKLIST.md
유창욱 90f121e14c chore: import codebase with security hardening
SHT30 온습도 모니터링 시스템 전체 소스(서버 PHP, STM32 펌웨어, SQL, 테스트).
전체 코드리뷰에서 도출된 보안 하드닝 10건 반영:
- 요청 서명 HMAC-SHA256 전환(펌웨어 sig.c/서버 config.php/호스트 패리티 동시)
- 재전송 방어 + 기본 API_KEY fail-closed + 디바이스 문자열 정제(api/sensor_data.php)
- 오프라인 SMS 중복 발송 경합 제거(cron_heartbeat.php, 원자적 선점)
- CSV 수식 주입 방지(monthly_report.php), 감사로그 회전 락(retention_cleanup.php)
- 브루트포스 카운터 원자화(login.php), 예시 TOTP 비밀키 무효화, 마이그레이션 멱등화

_backup/(하드코딩 실 비밀값 포함)·config.local.php·런타임 상태는 .gitignore 제외.
2026-06-20 09:37:40 +09:00

128 lines
6.7 KiB
Markdown

# 운영·보안 점검표
작성일: 2026-06-10
대상: 서버실 온습도(SHT30) 모니터링 시스템 v2606 운영 담당자
이 문서는 보안대책서 첨부자료와 월간 운영 점검에 함께 사용할 체크리스트입니다. 원문 API 키, SMS 키, DB 비밀번호, 관리자 비밀번호는 기록하지 않습니다.
## 1. 점검 주기
| 주기 | 점검 목적 | 보관 증적 |
|---|---|---|
| 일일 | 온습도 임계 경보, 장비 오프라인, SMS 실패 여부 확인 | 대시보드 화면 또는 이상 없음 기록 |
| 주간 | STM32 보고 수신 상태, 최근 측정값, 측정 공백 여부 확인 | 대시보드 온습도 추이, `sensor_metric` 최근 기록 |
| 월간 | 보안통제 매트릭스 점검, 백업, 수신자 현행화 | 보안 증적 보고서, 월간 보고서, 백업 목록 |
| 월간 | 관리자 MFA, 감사로그, 보관기간 정리 확인 | MFA 등록 확인표, `php/var/admin_audit.log`, retention 실행 결과 |
| 변경 시 | API 키, 서버 경로, 수신자, 임계값, 네트워크 변경 검증 | 변경 승인 기록, 재점검 결과 |
## 2. 월간 운영 점검
| 영역 | 점검 항목 | 정상 기준 | 증적 |
|---|---|---|---|
| 서비스 상태 | `dashboard.php` 접속 | 최신 온습도와 센서 상태 표시 | 대시보드 캡처 |
| 설치 점검 | `setup_wizard.php` 접속 | 중요 항목 0건 또는 조치계획 기록 | 설치 점검 캡처 |
| 보안 증적 | `security_evidence.php` 접속 | 운영 점검 결과와 보안통제 매트릭스 출력 | Markdown 다운로드 |
| 월간 보고 | `monthly_report.php` 조회 | 임계 경보, 복귀, 오프라인, SMS 현황 표시 | PDF 또는 CSV |
| 장비 상태 | `sensor_status`(`sensor_id=2`) | 최근 수신 시각이 `HEARTBEAT_TIMEOUT_SEC` 이내 | 대시보드 센서 카드 |
| 측정 수집 | `sensor_metric` | 5분 주기 측정값 누적 | 온습도 추이 캡처 |
| SMS | 최근 실패 | 반복 실패 없음 | `sms_log` 또는 대시보드 |
| 임계 설정 | `METRIC_*` | 기관 기준과 일치 | `config.local.php` 발췌(값만) |
| 백업 | DB/설정 백업 | 정해진 주기대로 백업 존재 | 백업 파일 목록 |
| 관리자 MFA | `ADMIN_TOTP_SECRET` | 인증 앱 등록 완료 | MFA 등록 확인표 |
| 감사로그 | `php/var/admin_audit.log` | 로그인/로그아웃/MFA 등록 기록 존재 | 감사로그 파일 |
## 3. 서버 점검 명령
브라우저에서 다음 화면을 확인합니다.
```text
https://your-domain.example/raspi_leck_detecter/setup_wizard.php
https://your-domain.example/raspi_leck_detecter/security_evidence.php
https://your-domain.example/raspi_leck_detecter/security_evidence.php?format=md
https://your-domain.example/raspi_leck_detecter/monthly_report.php
```
응답 헤더는 운영 서버에서 확인합니다.
```bash
curl -I https://your-domain.example/raspi_leck_detecter/login.php
```
## 4. STM32 펌웨어 점검
USART3(PD8/PD9, 115200) 콘솔 로그로 다음을 확인합니다.
- I2C1 초기화 및 SHT30 주소 0x44 응답
- 최근 측정값(온도/습도)과 주기 보고
- 네트워크/SNTP/TLS 핸드셰이크 및 서버 200 응답
- 상태 LED(PD12) 패턴: 정상 보고=느린 토글 / 망 단절·TLS 실패=빠른 점멸
장비가 `HEARTBEAT_TIMEOUT_SEC`(기본 1200초=20분)을 초과해 보고를 멈추면 서버가 오프라인으로 판정하고 SMS를 발송합니다.
## 5. 온습도 임계 경보 점검
| 항목 | 확인 내용 | 기록 |
|---|---|---|
| 임계 초과 감지 | 측정값이 임계 초과 시 `metric_status` 경보가 기록되는가 | 감지 시각/항목 |
| SMS 발송 | 수신자가 임계 경보 SMS를 받는가 | 수신 시각 |
| 쿨다운 | 동일 종류 경보가 30분 내 중복 발송되지 않는가 | `sms_log` 간격 |
| 정상복귀 | 히스테리시스 포함 정상 회복 시 복귀 SMS 1회 발송되는가 | 복귀 시각 |
| 보고서 반영 | 월간 보고서에 경보/복귀가 반영되는가 | 보고서 파일 |
## 6. 조치 기준
| 상태 | 조치 |
|---|---|
| 임계 경보 발생 | 당일 원인 확인 후 조치 결과 기록(공조/환기/장비 점검) |
| SMS 반복 실패 | Cafe24 SMS 잔액, 발신번호, secure key, 수신자 확인 |
| 장비 오프라인 | 전원, LAN 연결, PHY 링크, 펌웨어 콘솔 로그 확인 |
| 온습도 미수집 | I2C 배선(PB6/PB7, 0x44), 4.7kΩ 풀업, `sensor_metric` 테이블 확인 |
| HTTPS/TLS 미확인 | Cafe24 SSL 설정, 펌웨어 CA 반영, SNTP 시간 동기 확인 |
| 백업 미수행 | 백업 주기 재설정 및 다음 월 점검에 포함 |
## 7. 관리자 MFA
`config.local.php``ADMIN_TOTP_SECRET`을 설정합니다. 이 값은 Google Authenticator, Microsoft Authenticator, Authy 등 TOTP 인증 앱에 등록한 Base32 비밀키와 같아야 합니다.
```php
'ADMIN_TOTP_SECRET' => 'replace-with-base32-secret',
'MFA_SETUP_TOKEN' => 'replace-with-temporary-random-token',
```
운영자는 관리자 비밀번호와 인증 앱 6자리 코드를 모두 입력해야 로그인할 수 있습니다. 담당자 변경 시 비밀번호를 재설정하고 TOTP 비밀키도 새로 발급합니다.
초기 등록은 다음 주소에서 진행합니다. `MFA_SETUP_TOKEN`은 최초 등록 또는 교체 작업 때만 임시로 설정하고, 등록 완료 후 빈 값으로 바꾸거나 삭제합니다.
```text
https://your-domain.example/raspi_leck_detecter/setup_mfa.php?token=임시토큰
```
화면의 수동 입력 키를 Google Authenticator에 등록한 뒤 6자리 코드를 확인하고, 검증된 `ADMIN_TOTP_SECRET` 줄을 `config.local.php`에 반영합니다. 보안상 외부 QR 생성 API를 쓰지 않으며 비밀키를 외부 서버로 전송하지 않습니다.
로그인 성공/실패, 로그아웃, MFA 등록 검증은 `php/var/admin_audit.log`에 감사로그로 기록합니다.
## 8. 보관기간 정리
먼저 dry-run으로 삭제 대상을 확인합니다.
```bash
php retention_cleanup.php --dry-run
```
결과를 검토한 뒤 운영 백업이 완료된 상태에서만 실제 정리를 수행합니다.
```bash
php retention_cleanup.php --execute
```
기본 보관기간은 SMS 로그 365일, 센서 로그 365일, 온습도 측정값 365일, 관리자 감사로그 365일입니다. 기관 기준이 다르면 `config.local.php``SMS_LOG_RETENTION_DAYS`, `SENSOR_LOG_RETENTION_DAYS`, `SENSOR_METRIC_RETENTION_DAYS`, `ADMIN_AUDIT_RETENTION_DAYS`로 조정합니다.
## 9. 백업·복구 증적 생성
백업 파일 목록과 복구 테스트 결과는 다음 명령으로 Markdown 증적을 생성합니다.
```bash
php scripts/backup_evidence.php --backup-dir /path/to/backups --restore-test "YYYY-MM restore OK"
```
복구 테스트 결과에는 DB 복구, 관리자 로그인, SMS 테스트, 월간 보고서 조회, 온습도 측정값 표시 결과를 포함합니다.