## 구현 내용 ### DR 자동화 (routers/dr.py, core/dr_engine.py) - DR 시나리오 등록/관리 (SERVER_FAILURE | SITE_FAILURE | DATA_CORRUPTION) - 복구 테스트 자동화 (SSH 기반 단계별 실행 + 헬스체크) - 백업 무결성 검증 (SSH → SHA-256 해시 검증) - RTO/RPO 목표 대비 실적 대시보드 - Failover 실행 API (ADMIN 전용) ### 네트워크 장비 관리 (routers/network_devices.py, core/network_scanner.py) - 스위치/라우터/방화벽/L4 장비 인벤토리 (CRUD) - 벤더별 SSH 설정 백업 (Cisco IOS / Huawei VRP / Junos / Linux) - 이전 백업과 unified diff 변경 감지 - 위험 명령어 차단 (write erase, factory-reset 등) - 토폴로지 조회 API ### CSAP 공공기관 보안 자동 점검 (routers/compliance.py 확장, core/csap_checker.py) - CSAP/ISMS-P 기반 25개 항목 자동 점검 - 기술적/운영 보안 자동 검증 (SSH, DB 직접 확인) - 수동 항목 증적 업로드 - Excel/HTML 보고서 자동 생성 - 기관별 준수율 대시보드 (A~D 등급) ### DB 모델 추가 (models.py) - DRScenario, DRTest - NetworkDevice, NetworkConfigBackup - CSAPCheckResult ### 하네스 확장 - 에이전트: dr-coordinator, network-guardian, csap-auditor - 스킬: dr-automation, network-devices, csap-compliance - guardia-orchestrator description에 DR/네트워크/CSAP 트리거 추가 ### 매뉴얼 - 39_DR_네트워크장비_CSAP_운영가이드.md 신규 작성 - 16_API_명세서.md v2.1.0 업데이트 (617개 라우트, 섹션 21~23 추가) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
152 lines
7.8 KiB
Markdown
152 lines
7.8 KiB
Markdown
---
|
|
name: csap-compliance
|
|
description: "GUARDiA CSAP/ISMS-P 공공기관 보안 준수 자동 점검 구현 스킬. 기존 compliance.py를 확장하여 공공기관 보안 체크리스트(100개 항목) 자동 점검, 증적 수집, Excel/HTML 보고서 생성을 구현한다. 다음 상황에서 반드시 사용: (1) 'CSAP', 'ISMS', '보안인증', '공공기관 보안점검' 구현 요청; (2) compliance.py CSAP 고도화 또는 core/csap_checker.py 작업; (3) 보안 점검 보고서, 준수율 대시보드 구현; (4) 증적 수집, 체크리스트 자동화; (5) 다시 실행, 업데이트, 보완 요청."
|
|
---
|
|
|
|
# CSAP 자동 점검 구현 스킬
|
|
|
|
## 구현 대상 파일
|
|
- `itsm/core/csap_checker.py` — CSAP 점검 엔진
|
|
- `itsm/routers/compliance.py` — 기존 파일에 CSAP 엔드포인트 추가
|
|
|
|
## DB 모델 (models.py에 추가)
|
|
|
|
```python
|
|
class CSAPCheckResult(Base):
|
|
__tablename__ = "tb_csap_result"
|
|
id = Column(Integer, primary_key=True)
|
|
scan_id = Column(String(50), nullable=False, index=True) # CSAP-YYYYMMDD-NNN
|
|
inst_id = Column(Integer, ForeignKey("tb_inst_meta.id"))
|
|
item_id = Column(String(20), nullable=False) # M-01, T-15 등
|
|
category = Column(String(20)) # 관리적 | 기술적 | 물리적 | 운영
|
|
item_name = Column(String(200))
|
|
status = Column(String(20)) # PASS|FAIL|PARTIAL|MANUAL_REQUIRED|N_A
|
|
severity = Column(String(20)) # HIGH|MEDIUM|LOW
|
|
finding = Column(Text) # 발견 사항
|
|
evidence = Column(JSON) # 자동 수집 증적 (마스킹 처리)
|
|
recommendation = Column(Text) # 개선 권고
|
|
scanned_at = Column(DateTime, default=func.now())
|
|
```
|
|
|
|
## CSAP 점검 항목 구조 (core/csap_checker.py)
|
|
|
|
```python
|
|
CSAP_ITEMS = [
|
|
# ── 관리적 보안 (M) ────────────────────────────────────────────────
|
|
{"id":"M-01","cat":"관리적","sev":"HIGH","auto":False,
|
|
"name":"정보보호 정책 수립","check":"policy_doc_uploaded"},
|
|
{"id":"M-02","cat":"관리적","sev":"HIGH","auto":False,
|
|
"name":"정보보호 조직 구성","check":"org_chart_uploaded"},
|
|
{"id":"M-03","cat":"관리적","sev":"MEDIUM","auto":True,
|
|
"name":"정보보호 교육 이력","check":"training_records_exist"},
|
|
# ── 기술적 보안 (T) ────────────────────────────────────────────────
|
|
{"id":"T-01","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"계정 잠금 정책 (5회 실패 시 잠금)","check":"account_lockout"},
|
|
{"id":"T-02","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"패스워드 복잡도 정책 (8자 이상+특수문자)","check":"password_policy"},
|
|
{"id":"T-03","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"불필요 서비스 비활성화","check":"unnecessary_services"},
|
|
{"id":"T-04","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"SSH root 직접 로그인 차단","check":"ssh_root_disabled"},
|
|
{"id":"T-05","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"보안 패치 최신화 (30일 이내)","check":"patch_currency"},
|
|
{"id":"T-06","cat":"기술적","sev":"MEDIUM","auto":True,
|
|
"name":"방화벽 룰 최소 권한 원칙","check":"fw_least_privilege"},
|
|
{"id":"T-07","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"암호화 전송 (HTTPS/TLS 1.2 이상)","check":"tls_version"},
|
|
{"id":"T-08","cat":"기술적","sev":"HIGH","auto":True,
|
|
"name":"개인정보 암호화 저장","check":"pii_encryption"},
|
|
# ── 운영 보안 (O) ─────────────────────────────────────────────────
|
|
{"id":"O-01","cat":"운영","sev":"HIGH","auto":True,
|
|
"name":"로그 보존 기간 (6개월 이상)","check":"log_retention"},
|
|
{"id":"O-02","cat":"운영","sev":"HIGH","auto":True,
|
|
"name":"백업 실시 및 무결성 검증","check":"backup_integrity"},
|
|
{"id":"O-03","cat":"운영","sev":"MEDIUM","auto":True,
|
|
"name":"변경 관리 프로세스 이행","check":"change_management"},
|
|
# ── 물리적 보안 (P) ───────────────────────────────────────────────
|
|
{"id":"P-01","cat":"물리적","sev":"MEDIUM","auto":False,
|
|
"name":"출입 통제 시스템 운영","check":"physical_access"},
|
|
{"id":"P-02","cat":"물리적","sev":"HIGH","auto":True,
|
|
"name":"DR 사이트 운영 (RTO/RPO 충족)","check":"dr_test_passed"},
|
|
# ... 총 100개 항목 (실제 구현 시 전체 목록 확장)
|
|
]
|
|
```
|
|
|
|
## 자동 점검 함수 패턴
|
|
|
|
```python
|
|
class CSAPChecker:
|
|
async def check_ssh_root_disabled(self, db, inst_id: int) -> dict:
|
|
"""T-04: SSH root 로그인 차단 확인."""
|
|
# 기관 서버 목록 조회 → 각 서버 SSH 접속 → /etc/ssh/sshd_config 확인
|
|
# PermitRootLogin no 확인
|
|
...
|
|
|
|
async def check_patch_currency(self, db, inst_id: int) -> dict:
|
|
"""T-05: 보안 패치 최신화 (30일 이내 패치 여부)."""
|
|
# SSH → rpm -qa --last | head -20 또는 apt list --upgradable
|
|
...
|
|
|
|
async def check_log_retention(self, db, inst_id: int) -> dict:
|
|
"""O-01: 로그 보존 6개월 이상."""
|
|
# GUARDiA tb_audit_log 최오래된 레코드 날짜 확인
|
|
from sqlalchemy import select, func
|
|
oldest = await db.scalar(select(func.min(AuditLog.created_at)))
|
|
...
|
|
|
|
async def check_backup_integrity(self, db, inst_id: int) -> dict:
|
|
"""O-02: 백업 무결성 (DR 테스트 최근 90일 이내 PASS)."""
|
|
# tb_dr_test에서 최근 PASS 결과 확인
|
|
...
|
|
|
|
async def check_dr_test_passed(self, db, inst_id: int) -> dict:
|
|
"""P-02: DR 테스트 이력."""
|
|
# tb_dr_test에서 최근 1년 이내 PASS 확인
|
|
...
|
|
|
|
def generate_scan_id(self) -> str:
|
|
from datetime import datetime
|
|
now = datetime.now()
|
|
return f"CSAP-{now.strftime('%Y%m%d')}-{now.strftime('%H%M%S')}"
|
|
```
|
|
|
|
## 보고서 생성 패턴
|
|
|
|
```python
|
|
def generate_excel_report(self, results: list, inst_name: str) -> bytes:
|
|
"""openpyxl 기반 Excel 보고서 생성."""
|
|
import openpyxl
|
|
from openpyxl.styles import PatternFill, Font
|
|
wb = openpyxl.Workbook()
|
|
ws = wb.active
|
|
ws.title = "CSAP 점검 결과"
|
|
# 헤더: 항목ID, 카테고리, 항목명, 심각도, 결과, 발견사항, 개선권고
|
|
# 결과별 색상: PASS=녹, FAIL=적, PARTIAL=황
|
|
...
|
|
|
|
def generate_html_report(self, results: list, scan_id: str) -> str:
|
|
"""HTML 점검 보고서 (인쇄 가능, 공문 첨부용)."""
|
|
# 준수율 차트 (SVG inline), 항목별 상세 테이블
|
|
...
|
|
```
|
|
|
|
## compliance.py 추가 엔드포인트
|
|
|
|
```
|
|
POST /api/compliance/csap/scan 전체 자동 점검 (ADMIN 전용)
|
|
GET /api/compliance/csap/items 점검 항목 목록 (category 필터)
|
|
GET /api/compliance/csap/results 최근 점검 결과 요약 목록
|
|
GET /api/compliance/csap/results/{scan_id} 배치 상세 결과
|
|
POST /api/compliance/csap/evidence/{item_id} 수동 증적 업로드
|
|
GET /api/compliance/csap/report/html HTML 보고서 (scan_id 쿼리)
|
|
GET /api/compliance/csap/report/excel Excel 보고서 (scan_id 쿼리)
|
|
GET /api/compliance/csap/dashboard 기관별 준수율 대시보드
|
|
```
|
|
|
|
## 준수율 계산 공식
|
|
```
|
|
자동 점검 통과율 = (PASS + PARTIAL*0.5) / (전체 자동 항목) * 100
|
|
수동 항목 = MANUAL_REQUIRED로 표시, 별도 집계
|
|
전체 준수율 = (자동 통과 항목 수 + 수동 PASS 업로드 수) / 전체 100개 * 100
|
|
```
|