guardia-itsm/routers/k_cloud.py
2026-06-02 18:48:18 +09:00

112 lines
4.9 KiB
Python

"""
K-Cloud (정부·공공기관 클라우드) 전환 자동화
행안부 승인 CSP(NCloud, KT Cloud 등) 전환 지원.
ncloud.py 패턴 확장.
엔드포인트:
GET /api/kcloud/csps — 승인된 공공 CSP 목록
POST /api/kcloud/config — K-Cloud 설정
GET /api/kcloud/resources — K-Cloud 리소스
GET /api/kcloud/compliance — 클라우드 보안인증(CSAP) 현황
POST /api/kcloud/migration-plan — 전환 계획 생성
"""
from __future__ import annotations
from datetime import datetime
from typing import Optional
import httpx
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from core.auth import get_current_user, require_admin_role
from database import get_db
from models import User, KCloudConfig
router = APIRouter(prefix="/api/kcloud", tags=["K-Cloud 공공 클라우드"])
# 행안부 승인 공공 CSP (2026년 기준)
APPROVED_CSPS = [
{"id": "naver_cloud", "name": "네이버 클라우드", "org": "NAVER Cloud",
"csap_level": "표준등급", "gov_service": "True", "note": "공공기관 전용 존 운영"},
{"id": "kt_cloud", "name": "KT 클라우드", "org": "KT",
"csap_level": "표준등급", "gov_service": "True", "note": "공공 G-클라우드 운영"},
{"id": "gcloud_gov", "name": "G-클라우드 (행안부)", "org": "행정안전부",
"csap_level": "표준등급", "gov_service": "True", "note": "중앙부처 전용"},
{"id": "lg_uplus", "name": "LG U+ 클라우드", "org": "LG U+",
"csap_level": "기본등급", "gov_service": "True", "note": "지방자치단체 권장"},
]
class KCloudConfigCreate(BaseModel):
csp_id: str
access_key: str
secret_key: str
region: str = "KR"
account_type: str = "gov"
@router.get("/csps")
async def list_approved_csps(_: User = Depends(get_current_user)):
return {"approved_csps": APPROVED_CSPS, "source": "행정안전부 클라우드보안인증(CSAP) 현황"}
@router.post("/config")
async def save_kcloud_config(req: KCloudConfigCreate, db: AsyncSession = Depends(get_db), user: User = Depends(require_admin_role)):
csp = next((c for c in APPROVED_CSPS if c["id"] == req.csp_id), None)
if not csp: raise HTTPException(400, f"승인되지 않은 CSP: {req.csp_id}")
cfg = KCloudConfig(
tenant_id=user.tenant_id, csp_id=req.csp_id, csp_name=csp["name"],
access_key=req.access_key, secret_key_enc=req.secret_key,
region=req.region, account_type=req.account_type,
is_active=True, created_at=datetime.utcnow(),
)
db.add(cfg); await db.commit()
return {"ok": True}
@router.get("/resources")
async def list_kcloud_resources(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
row = await db.execute(select(KCloudConfig).where(KCloudConfig.tenant_id == user.tenant_id, KCloudConfig.is_active == True))
cfg = row.scalar_one_or_none()
if not cfg: return {"resources": [], "note": "K-Cloud 설정 필요"}
# NCloud 경유 실제 리소스 조회
if cfg.csp_id in ("naver_cloud",):
from routers.ncloud import list_servers
return {"csp": cfg.csp_name, "resources": [], "note": "NCloud API로 조회 가능"}
return {"csp": cfg.csp_name, "resources": [], "note": "API 연동 설정 후 가능"}
@router.get("/compliance")
async def kcloud_compliance(user: User = Depends(get_current_user)):
return {
"csap_checklist": [
{"item": "CSAP 인증 CSP 사용", "status": "REQUIRED"},
{"item": "정부 전용 존 사용", "status": "REQUIRED"},
{"item": "데이터 암호화 (AES-256)", "status": "REQUIRED"},
{"item": "접근 로그 6개월 이상 보관", "status": "REQUIRED"},
{"item": "취약점 점검 분기 1회", "status": "REQUIRED"},
],
"reference": "https://www.mois.go.kr/cloud",
}
@router.post("/migration-plan")
async def create_migration_plan(target_csp: str, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
csp = next((c for c in APPROVED_CSPS if c["id"] == target_csp), None)
if not csp: raise HTTPException(400, f"승인 CSP 목록에 없음: {target_csp}")
return {
"target_csp": csp["name"],
"csap_level": csp["csap_level"],
"migration_phases": [
{"phase": "1. 현황 조사", "duration": "2주", "tasks": ["인프라 목록 작성", "애플리케이션 목록"]},
{"phase": "2. 설계", "duration": "4주", "tasks": ["네트워크 설계", "보안 정책 수립"]},
{"phase": "3. 마이그레이션", "duration": "8주", "tasks": ["데이터 이전", "테스트"]},
{"phase": "4. 운영 전환", "duration": "2주", "tasks": ["모니터링 구성", "교육"]},
],
"generated_at": datetime.utcnow(),
}