guardia-itsm/.claude/skills/dr-automation/SKILL.md
DESKTOP-TKLFCPRython 2ed703aad9 feat(itsm): DR 자동화 · 네트워크 장비 관리 · CSAP 자동 점검 3종 추가
## 구현 내용

### 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>
2026-05-31 09:24:51 +09:00

5.4 KiB

name description
dr-automation GUARDiA DR(재해복구) 자동화 구현 스킬. DR 시나리오 관리, Failover 실행, 백업 무결성 검증, 복구 테스트, RTO/RPO 추적 기능을 FastAPI + paramiko 패턴으로 구현한다. 다음 상황에서 반드시 사용: (1) 'DR 구현', '재해복구', 'Failover', 'RTO/RPO' 관련 요청; (2) dr.py 라우터 또는 core/dr_engine.py 작업; (3) 백업 무결성 검증, 복구 테스트 구현; (4) DR 대시보드 구현; (5) 다시 실행, 업데이트, 보완 요청. paramiko SSH 패턴과 SQLAlchemy async 패턴을 따른다.

DR 자동화 구현 스킬

구현 대상 파일

  • itsm/core/dr_engine.py — DR 비즈니스 로직
  • itsm/routers/dr.py — FastAPI 라우터

핵심 구현 원칙

  1. Fail-Safe 시퀀스: 스냅샷 → 대기서버 활성화 → 서비스 전환 → 헬스체크 → 롤백(실패 시)
  2. 자격증명 보호: paramiko 접속 시 IP/계정 노출 금지, AES 복호화 후 메모리만 사용
  3. 비동기: asyncio.create_subprocess_exec + paramiko를 run_in_executor로 래핑
  4. 감사 기록: 모든 DR 작업은 tb_audit_log에 기록

DB 모델 (models.py에 추가)

class DRScenario(Base):
    __tablename__ = "tb_dr_scenario"
    id               = Column(Integer, primary_key=True)
    name             = Column(String(100), nullable=False)
    scenario_type    = Column(String(30))   # SITE_FAILURE | SERVER_FAILURE | DATA_CORRUPTION
    primary_server_id = Column(Integer, ForeignKey("tb_server_info.id"))
    standby_server_id = Column(Integer, ForeignKey("tb_server_info.id"))
    rto_minutes      = Column(Integer)      # 목표 RTO (분)
    rpo_minutes      = Column(Integer)      # 목표 RPO (분)
    failover_steps   = Column(JSON)         # 페일오버 실행 단계 목록
    healthcheck_url  = Column(String(255))
    last_test_at     = Column(DateTime)
    last_test_result = Column(String(20))   # PASS | FAIL | PARTIAL
    is_active        = Column(Boolean, default=True)
    created_at       = Column(DateTime, default=func.now())

class DRTest(Base):
    __tablename__ = "tb_dr_test"
    id              = Column(Integer, primary_key=True)
    scenario_id     = Column(Integer, ForeignKey("tb_dr_scenario.id"))
    test_type       = Column(String(20))    # BACKUP_VERIFY | FAILOVER_SIM | RECOVERY
    status          = Column(String(20))    # RUNNING | PASS | FAIL | PARTIAL
    rto_actual      = Column(Integer)       # 실제 RTO (분)
    rpo_actual      = Column(Integer)       # 실제 RPO (분)
    result_detail   = Column(JSON)          # 단계별 결과
    started_at      = Column(DateTime, default=func.now())
    completed_at    = Column(DateTime)
    triggered_by    = Column(String(100))

core/dr_engine.py 구현 패턴

import asyncio, hashlib, time
from datetime import datetime
from typing import Optional
import paramiko
from sqlalchemy.ext.asyncio import AsyncSession

from core.ssh_exec import _get_server_credentials  # 기존 AES 복호화 함수 재사용
from models import DRScenario, DRTest, Server

class DREngine:
    async def verify_backup(self, db: AsyncSession, server_name: str) -> dict:
        """백업 파일 무결성 검증 (SHA-256 체크)."""
        # 1. 서버 정보 조회 (ip_addr, ssh_user, os_pw_enc)
        # 2. AES 복호화로 자격증명 획득
        # 3. paramiko SSH 접속
        # 4. backup_path 하위 최신 파일 SHA-256 계산
        # 5. 결과 반환 (파일명, 크기, 해시, 경로 미노출)
        ...

    async def run_recovery_test(self, db: AsyncSession, scenario_id: int,
                                 triggered_by: str) -> DRTest:
        """복구 테스트 실행."""
        # 1. 시나리오 조회
        # 2. DRTest 레코드 생성 (status=RUNNING)
        # 3. failover_steps 순서대로 SSH 명령 실행
        # 4. 각 단계 결과 result_detail에 누적
        # 5. healthcheck_url 응답 확인
        # 6. RTO 계산 (started_at ~ 헬스체크 성공)
        # 7. DRTest status 업데이트 (PASS/FAIL/PARTIAL)
        ...

    def calculate_rto_rpo(self, tests: list[DRTest]) -> dict:
        """최근 5회 테스트 기반 RTO/RPO 통계."""
        ...

routers/dr.py 엔드포인트 구조

GET  /api/dr/scenarios              목록 (ENGINEER 이상)
POST /api/dr/scenarios              등록 (ADMIN 전용)
GET  /api/dr/scenarios/{id}         상세
PUT  /api/dr/scenarios/{id}         수정 (ADMIN 전용)
POST /api/dr/test                   복구 테스트 실행 (ENGINEER 이상)
GET  /api/dr/test/{id}              테스트 결과 조회
GET  /api/dr/tests                  테스트 이력 목록
POST /api/dr/backup-verify          백업 무결성 검증 (ENGINEER 이상)
POST /api/dr/failover/{scenario_id} Failover 실행 (ADMIN 전용, 승인 필요)
GET  /api/dr/rto-rpo                RTO/RPO 현황 대시보드
GET  /api/dr/dashboard              DR 전체 현황

보안 규칙

  • Failover 실행은 require_admin_role 의존성 필수
  • 백업 검증은 ENGINEER 이상 허용
  • 서버 IP/경로를 API 응답 body에 포함하지 않는다
  • SSH 자격증명은 core/ssh_exec.py의 기존 AES 복호화 함수 재사용

헬스체크 URL 검증 방법

import httpx
async with httpx.AsyncClient(verify=False, timeout=10) as client:
    resp = await client.get(scenario.healthcheck_url)
    return resp.status_code == 200