## 구현 내용 ### 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>
158 lines
6.3 KiB
Markdown
158 lines
6.3 KiB
Markdown
---
|
|
name: network-devices
|
|
description: "GUARDiA 네트워크 장비 관리 구현 스킬. 스위치/라우터/방화벽의 SSH 기반 설정 백업, 변경 감지, 명령 실행, 토폴로지 관리를 FastAPI + paramiko 패턴으로 구현한다. 다음 상황에서 반드시 사용: (1) '네트워크 장비', '스위치', '라우터', '방화벽' 관리 구현 요청; (2) network_devices.py 라우터 또는 core/network_scanner.py 작업; (3) 장비 설정 백업/비교/변경감지 구현; (4) 네트워크 토폴로지 구현; (5) 다시 실행, 업데이트, 보완 요청."
|
|
---
|
|
|
|
# 네트워크 장비 관리 구현 스킬
|
|
|
|
## 구현 대상 파일
|
|
- `itsm/core/network_scanner.py` — 장비 접속/명령 실행/백업 로직
|
|
- `itsm/routers/network_devices.py` — FastAPI 라우터
|
|
|
|
## DB 모델 (models.py에 추가)
|
|
|
|
```python
|
|
class NetworkDevice(Base):
|
|
__tablename__ = "tb_network_device"
|
|
id = Column(Integer, primary_key=True)
|
|
device_name = Column(String(100), nullable=False)
|
|
device_type = Column(String(30)) # SWITCH | ROUTER | FIREWALL | LOAD_BALANCER
|
|
vendor = Column(String(30)) # CISCO | HUAWEI | JUNIPER | PIOLINK | SECUI | RADWARE
|
|
model = Column(String(100))
|
|
os_type = Column(String(30)) # cisco_ios | huawei_vrp | junos | linux
|
|
ip_addr = Column(String(45)) # NOT exposed in API
|
|
ssh_user = Column(String(50)) # NOT exposed
|
|
ssh_pw_enc = Column(Text) # AES-256, NEVER exposed
|
|
ssh_port = Column(Integer, default=22)
|
|
location = Column(String(200))
|
|
inst_id = Column(Integer, ForeignKey("tb_inst_meta.id"))
|
|
is_active = Column(Boolean, default=True)
|
|
last_backup_at = Column(DateTime)
|
|
created_at = Column(DateTime, default=func.now())
|
|
backups = relationship("NetworkConfigBackup", back_populates="device",
|
|
cascade="all, delete-orphan")
|
|
|
|
class NetworkConfigBackup(Base):
|
|
__tablename__ = "tb_network_backup"
|
|
id = Column(Integer, primary_key=True)
|
|
device_id = Column(Integer, ForeignKey("tb_network_device.id"))
|
|
config_text = Column(Text) # 설정 전문 (암호화 선택)
|
|
config_hash = Column(String(64)) # SHA-256
|
|
backup_type = Column(String(20)) # SCHEDULED | MANUAL | PRE_CHANGE
|
|
backed_up_at = Column(DateTime, default=func.now())
|
|
backed_up_by = Column(String(100))
|
|
device = relationship("NetworkDevice", back_populates="backups")
|
|
```
|
|
|
|
## 벤더별 표준 명령어 매핑
|
|
|
|
```python
|
|
DEVICE_COMMANDS = {
|
|
"cisco_ios": {
|
|
"get_config": "show running-config",
|
|
"get_version": "show version",
|
|
"get_interfaces": "show interfaces status",
|
|
"get_vlan": "show vlan brief",
|
|
"get_arp": "show arp",
|
|
"get_route": "show ip route",
|
|
"save_config": "write memory",
|
|
},
|
|
"huawei_vrp": {
|
|
"get_config": "display current-configuration",
|
|
"get_version": "display version",
|
|
"get_interfaces": "display interface brief",
|
|
"get_vlan": "display vlan",
|
|
"get_arp": "display arp all",
|
|
"save_config": "save force",
|
|
},
|
|
"junos": {
|
|
"get_config": "show configuration | display set",
|
|
"get_version": "show version",
|
|
"get_interfaces": "show interfaces terse",
|
|
"get_route": "show route",
|
|
},
|
|
"linux": { # PIOLINK, SECUI 방화벽 (Linux 기반)
|
|
"get_config": "cat /etc/fw/rules.conf 2>/dev/null || iptables-save",
|
|
"get_version": "cat /etc/os-release",
|
|
"get_interfaces": "ip addr show",
|
|
"get_route": "ip route show",
|
|
},
|
|
}
|
|
|
|
# 위험 명령어 차단 목록 (실행 전 검증)
|
|
BLOCKED_COMMANDS = [
|
|
"write erase", "factory-reset", "reload", "reboot",
|
|
"rm -rf", "mkfs", "fdisk", "format",
|
|
"no service", "delete flash:",
|
|
]
|
|
```
|
|
|
|
## core/network_scanner.py 구현 패턴
|
|
|
|
```python
|
|
import asyncio, difflib, hashlib
|
|
import paramiko
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
class NetworkScanner:
|
|
def _is_command_safe(self, command: str) -> bool:
|
|
"""위험 명령어 차단."""
|
|
cmd_lower = command.lower()
|
|
return not any(blocked in cmd_lower for blocked in BLOCKED_COMMANDS)
|
|
|
|
async def execute_command(self, device: NetworkDevice,
|
|
command: str, decrypt_fn) -> dict:
|
|
"""SSH 명령 실행 (벤더 무관 인터페이스)."""
|
|
if not self._is_command_safe(command):
|
|
return {"success": False, "error": "차단된 명령어입니다."}
|
|
# paramiko SSH 접속 → 명령 실행 → stdout 반환
|
|
...
|
|
|
|
async def backup_config(self, db: AsyncSession, device: NetworkDevice,
|
|
backup_type: str, user: str) -> NetworkConfigBackup:
|
|
"""설정 백업: 표준 명령 실행 → DB 저장."""
|
|
config_cmd = DEVICE_COMMANDS.get(device.os_type, {}).get("get_config", "")
|
|
result = await self.execute_command(device, config_cmd, decrypt_fn)
|
|
config_text = result["stdout"]
|
|
config_hash = hashlib.sha256(config_text.encode()).hexdigest()
|
|
backup = NetworkConfigBackup(
|
|
device_id=device.id,
|
|
config_text=config_text,
|
|
config_hash=config_hash,
|
|
backup_type=backup_type,
|
|
backed_up_by=user,
|
|
)
|
|
db.add(backup)
|
|
await db.commit()
|
|
return backup
|
|
|
|
def diff_configs(self, old: str, new: str) -> list[str]:
|
|
"""unified diff 형식으로 설정 변경 사항 반환."""
|
|
return list(difflib.unified_diff(
|
|
old.splitlines(), new.splitlines(),
|
|
lineterm="", n=3,
|
|
))
|
|
```
|
|
|
|
## API 응답에서 민감 정보 제외
|
|
|
|
```python
|
|
class NetworkDeviceOut(BaseModel):
|
|
id: int
|
|
device_name: str
|
|
device_type: str
|
|
vendor: str
|
|
model: Optional[str]
|
|
os_type: str
|
|
# ip_addr, ssh_user, ssh_pw_enc 절대 포함 금지
|
|
location: Optional[str]
|
|
inst_id: Optional[int]
|
|
is_active: bool
|
|
last_backup_at: Optional[datetime]
|
|
```
|
|
|
|
## 설정 차이 탐지 및 알림
|
|
- 스케줄 백업 시 이전 백업과 diff → 변경 감지 시 SSE 이벤트 발행
|
|
- diff 결과가 있으면 tb_audit_log에 "설정 변경 감지" 기록
|
|
- 변경된 라인 수가 10줄 이상이면 MEDIUM 알림, 50줄 이상이면 HIGH 알림
|