#!/usr/bin/env python3 """라이선스 API 기능 테스트""" import paramiko, time, sys, json, urllib.request, urllib.parse HOST = '101.79.17.164'; USER = 'root'; PASS = '1q2w3e!Q' BASE = f'http://{HOST}:8001' client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(HOST, username=USER, password=PASS, timeout=15) def ssh(cmd, timeout=15): chan = client.get_transport().open_session() chan.set_combine_stderr(True) chan.exec_command(cmd) start = time.time() while not chan.exit_status_ready(): if time.time() - start > timeout: break time.sleep(0.2) out = b'' while chan.recv_ready(): out += chan.recv(8192) chan.recv_exit_status() return out.decode('utf-8', errors='replace').strip() def api(method, path, data=None, token=None): url = f'{BASE}{path}' body = json.dumps(data).encode() if data else None req = urllib.request.Request(url, data=body, method=method) req.add_header('Content-Type', 'application/json') if token: req.add_header('Authorization', f'Bearer {token}') try: resp = urllib.request.urlopen(req, timeout=10) return json.loads(resp.read()), resp.status except urllib.error.HTTPError as e: return json.loads(e.read()), e.code RESULTS = [] def test(name, fn): try: result = fn() RESULTS.append((name, True, result)) print(f'✅ {name}: {str(result)[:100]}') return result except Exception as e: RESULTS.append((name, False, str(e))) print(f'❌ {name}: {e}') return None # T1: 로그인 params = urllib.parse.urlencode({'username': 'admin', 'password': 'Admin@zioinfo2026!'}) req = urllib.request.Request(f'{BASE}/api/auth/login', data=params.encode(), method='POST') req.add_header('Content-Type', 'application/x-www-form-urlencoded') resp = urllib.request.urlopen(req, timeout=10) token_data = json.loads(resp.read()) TOKEN = token_data.get('access_token', '') print(f'\n=== 라이선스 API 테스트 (서버: {HOST}) ===') print(f'TOKEN: {TOKEN[:25]}...\n') # T2: 현재 상태 test('T2 라이선스 현재 상태', lambda: api('GET', '/api/license/status', token=TOKEN)[0].get('message')) # T3: 체험 이력 확인 prev_status, _ = api('GET', '/api/license/status', token=TOKEN) already_activated = prev_status.get('activated', False) if not already_activated: # T3: 체험 라이선스 발급 def trial_test(): r, s = api('POST', '/api/license/trial', {'customer': '지오정보기술 체험판', 'days': 7}, token=TOKEN) return f"HTTP {s}: {r.get('message', r.get('detail', '?'))}" test('T3 체험 라이선스 발급', trial_test) else: print('T3 체험 라이선스 발급: 이미 활성화됨 — SKIP') RESULTS.append(('T3 체험 라이선스 발급', True, '이미 활성화됨 (기존 유지)')) # T4: 활성화 후 상태 확인 def status_after(): r, _ = api('GET', '/api/license/status', token=TOKEN) return f"valid={r.get('valid')}, edition={r.get('edition')}, days={r.get('days_remaining')}" test('T4 활성화 후 상태', status_after) # T5: 라이선스 이력 def history_test(): r, s = api('GET', '/api/license/history', token=TOKEN) cnt = len(r) if isinstance(r, list) else '?' return f"HTTP {s}: {cnt}건 이력" test('T5 라이선스 이력 조회', history_test) # T6: 키 검증 (유효하지 않은 키) def verify_invalid(): r, s = api('POST', '/api/license/verify', {'license_key': 'invalid_key_test'}, token=TOKEN) return f"HTTP {s}: {r.get('detail', r.get('message', '?'))[:60]}" test('T6 잘못된 키 검증 (400 예상)', verify_invalid) # T7: Manager UI 접속 ui_resp = ssh('curl -s -o /dev/null -w "%{http_code}" http://localhost:8090/licenses 2>/dev/null || ' 'curl -s -o /dev/null -w "%{http_code}" http://localhost:8090/') test('T7 Manager UI (라이선스 페이지)', lambda: f'HTTP {ui_resp}') # T8: GUARDiA Manager API 상태 api_resp = ssh('curl -s http://localhost:8002/health 2>/dev/null') test('T8 Manager Backend 상태', lambda: api_resp[:80]) # 결과 요약 print(f'\n{"="*50}') passed = sum(1 for _, ok, _ in RESULTS if ok) print(f'테스트 결과: {passed}/{len(RESULTS)} PASS') for name, ok, detail in RESULTS: print(f' {"✅" if ok else "❌"} {name}') print('='*50) client.close()