- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스) - Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포 - 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
141 lines
4.9 KiB
Python
141 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
"""GUARDiA ITSM 로그인 방식 확인 및 라이선스 테스트"""
|
|
import paramiko, time, sys, json
|
|
|
|
HOST = '101.79.17.164'; USER = 'root'; PASS = '1q2w3e!Q'
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
client.connect(HOST, username=USER, password=PASS, timeout=15)
|
|
sftp = client.open_sftp()
|
|
|
|
test_py = '''#!/usr/bin/env python3
|
|
import urllib.request, json
|
|
|
|
BASE = "http://localhost:8001"
|
|
|
|
# 로그인 방식 탐색
|
|
login_attempts = [
|
|
("JSON username/password", "POST", "/api/auth/login",
|
|
json.dumps({"username":"admin","password":"1111"}).encode(), "application/json"),
|
|
("JSON username/password (Admin2026)", "POST", "/api/auth/login",
|
|
json.dumps({"username":"admin","password":"Admin@2026!"}).encode(), "application/json"),
|
|
("Form data", "POST", "/api/auth/login",
|
|
"username=admin&password=1111".encode(), "application/x-www-form-urlencoded"),
|
|
]
|
|
|
|
TOKEN = None
|
|
for name, method, path, body, ct in login_attempts:
|
|
req = urllib.request.Request(f"{BASE}{path}", data=body, method=method)
|
|
req.add_header("Content-Type", ct)
|
|
try:
|
|
resp = urllib.request.urlopen(req, timeout=5)
|
|
d = json.loads(resp.read())
|
|
if "access_token" in d:
|
|
TOKEN = d["access_token"]
|
|
print(f"OK 로그인 성공 [{name}]: token={TOKEN[:20]}...")
|
|
break
|
|
else:
|
|
print(f"FAIL [{name}]: {d}")
|
|
except urllib.error.HTTPError as e:
|
|
print(f"FAIL [{name}] HTTP {e.code}: {e.read().decode()[:100]}")
|
|
|
|
if not TOKEN:
|
|
print("모든 로그인 시도 실패")
|
|
exit(1)
|
|
|
|
# 라이선스 API 테스트
|
|
def api(method, path, data=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")
|
|
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
|
|
|
|
print("\\n=== 라이선스 API 테스트 ===")
|
|
RESULTS = []
|
|
|
|
def test(name, fn):
|
|
try:
|
|
r = fn(); ok = True
|
|
except Exception as ex:
|
|
r = str(ex); ok = False
|
|
RESULTS.append((name, ok, str(r)[:80]))
|
|
print(f\'{"OK" if ok else "FAIL"} {name}: {str(r)[:80]}\')
|
|
return r if ok else None
|
|
|
|
# T2: 현재 상태
|
|
test("T2 라이선스 현재 상태", lambda: api("GET", "/api/license/status")[0].get("message"))
|
|
|
|
# T3: 체험 라이선스 (없으면 발급)
|
|
cur, _ = api("GET", "/api/license/status")
|
|
if not cur.get("activated"):
|
|
def t3():
|
|
r,s = api("POST", "/api/license/trial", {"customer":"지오정보기술 체험판","days":7})
|
|
return f"HTTP {s}: {r.get(\'message\', r.get(\'detail\', \'?\'))}"
|
|
test("T3 체험 라이선스 발급 (7일)", t3)
|
|
else:
|
|
RESULTS.append(("T3 체험 라이선스 발급", True, "이미 활성화됨"))
|
|
print("SKIP T3: 이미 활성화됨")
|
|
|
|
# T4: 활성화 후 상태
|
|
def t4():
|
|
r,_ = api("GET", "/api/license/status")
|
|
return f"valid={r.get(\'valid\')}, edition={r.get(\'edition\')}, days={r.get(\'days_remaining\')}"
|
|
test("T4 활성화 후 상태", t4)
|
|
|
|
# T5: 이력
|
|
def t5():
|
|
r,s = api("GET", "/api/license/history")
|
|
return f"HTTP {s}: {len(r) if isinstance(r,list) else \'?\'}건"
|
|
test("T5 라이선스 이력 조회", t5)
|
|
|
|
# T6: 잘못된 키 검증
|
|
def t6():
|
|
r,s = api("POST", "/api/license/verify", {"license_key":"invalid_key"})
|
|
return f"HTTP {s}: {r.get(\'detail\', r.get(\'message\',\'?\'))[:50]}"
|
|
test("T6 잘못된 키 검증 (400/422 예상)", t6)
|
|
|
|
# T7: Manager UI
|
|
try:
|
|
resp7 = urllib.request.urlopen("http://localhost:8090/", timeout=5)
|
|
test("T7 Manager UI", lambda: f"HTTP {resp7.status}")
|
|
except Exception as ex:
|
|
test("T7 Manager UI", lambda: f"ERROR: {str(ex)[:50]}")
|
|
|
|
# T8: Manager API
|
|
try:
|
|
resp8 = urllib.request.urlopen("http://localhost:8002/health", timeout=5)
|
|
d8 = json.loads(resp8.read())
|
|
test("T8 Manager Backend", lambda: d8.get("status","?"))
|
|
except Exception as ex:
|
|
test("T8 Manager Backend", lambda: f"ERROR: {str(ex)[:50]}")
|
|
|
|
print(f"\\n{'='*55}")
|
|
passed = sum(1 for _,ok,_ in RESULTS if ok)
|
|
print(f"결과: {passed}/{len(RESULTS)} PASS")
|
|
for name,ok,detail in RESULTS:
|
|
print(f\' {"OK" if ok else "FAIL"} {name}\')
|
|
print("="*55)
|
|
'''
|
|
with sftp.open('/tmp/test_lic2.py', 'w') as f:
|
|
f.write(test_py)
|
|
sftp.close()
|
|
|
|
chan = client.get_transport().open_session()
|
|
chan.set_combine_stderr(True)
|
|
chan.exec_command('python3 /tmp/test_lic2.py 2>&1')
|
|
start = time.time()
|
|
while not chan.exit_status_ready():
|
|
if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)); sys.stdout.flush()
|
|
if time.time() - start > 30: break
|
|
time.sleep(0.2)
|
|
while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096))
|
|
sys.stdout.flush()
|
|
chan.recv_exit_status()
|
|
client.close()
|