This commit is contained in:
400
tests/test_security_check.py
Normal file
400
tests/test_security_check.py
Normal file
@@ -0,0 +1,400 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Полный тест безопасности и функциональности Emergency Service
|
||||
- Проверка блокировки временных токенов
|
||||
- Проверка работы JWT аутентификации
|
||||
- Полное тестирование всех Emergency API endpoints
|
||||
- Создание и проверка записей экстренных вызовов
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import httpx
|
||||
import websockets
|
||||
from typing import Optional
|
||||
|
||||
class SecurityTest:
|
||||
def __init__(self):
|
||||
self.base_url = "http://localhost:8000" # API Gateway
|
||||
self.emergency_url = "http://localhost:8002" # Emergency Service напрямую
|
||||
self.ws_url = "ws://localhost:8002" # Emergency Service
|
||||
|
||||
async def test_temp_token_rejection(self) -> bool:
|
||||
"""Тестируем, что временные токены отклоняются"""
|
||||
print("🔒 ТЕСТ БЕЗОПАСНОСТИ: Блокировка временных токенов")
|
||||
print("="*60)
|
||||
|
||||
temp_tokens = [
|
||||
"temp_token_for_shadow85@list.ru",
|
||||
"test_token_123",
|
||||
"temp_token_12345",
|
||||
"test_token_admin"
|
||||
]
|
||||
|
||||
all_rejected = True
|
||||
|
||||
for token in temp_tokens:
|
||||
try:
|
||||
ws_url = f"{self.ws_url}/api/v1/emergency/ws/current_user_id?token={token}"
|
||||
print(f"🔍 Тестируем токен: {token[:30]}...")
|
||||
|
||||
# Пытаемся подключиться (должно быть отклонено)
|
||||
async with websockets.connect(ws_url) as websocket:
|
||||
print(f"❌ ПРОБЛЕМА БЕЗОПАСНОСТИ: Токен {token[:30]}... был принят!")
|
||||
all_rejected = False
|
||||
|
||||
except websockets.exceptions.ConnectionClosed as e:
|
||||
if e.code in [1008, 403]: # Policy violation или Forbidden
|
||||
print(f"✅ Токен {token[:30]}... корректно отклонен (код: {e.code})")
|
||||
else:
|
||||
print(f"⚠️ Токен {token[:30]}... отклонен с неожиданным кодом: {e.code}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✅ Токен {token[:30]}... корректно отклонен: {type(e).__name__}")
|
||||
|
||||
return all_rejected
|
||||
|
||||
async def test_jwt_token_acceptance(self) -> bool:
|
||||
"""Тестируем, что настоящие JWT токены принимаются"""
|
||||
print("\n🔓 ТЕСТ: Прием настоящих JWT токенов")
|
||||
print("="*50)
|
||||
|
||||
try:
|
||||
# Получаем настоящий JWT токен
|
||||
async with httpx.AsyncClient() as client:
|
||||
login_data = {
|
||||
"email": "shadow85@list.ru",
|
||||
"password": "R0sebud1985"
|
||||
}
|
||||
|
||||
print("🔐 Получаем JWT токен...")
|
||||
response = await client.post(
|
||||
f"{self.base_url}/api/v1/auth/login",
|
||||
json=login_data,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"❌ Не удалось получить JWT токен: {response.status_code}")
|
||||
return False
|
||||
|
||||
auth_data = response.json()
|
||||
jwt_token = auth_data.get("access_token")
|
||||
|
||||
if not jwt_token:
|
||||
print("❌ JWT токен не найден в ответе")
|
||||
return False
|
||||
|
||||
print(f"✅ JWT токен получен: {jwt_token[:50]}...")
|
||||
|
||||
# Тестируем WebSocket с JWT токеном
|
||||
ws_url = f"{self.ws_url}/api/v1/emergency/ws/current_user_id?token={jwt_token}"
|
||||
print("🔌 Тестируем WebSocket с JWT токеном...")
|
||||
|
||||
async with websockets.connect(ws_url) as websocket:
|
||||
print("✅ JWT токен принят, WebSocket подключен!")
|
||||
|
||||
# Отправляем ping
|
||||
await websocket.send(json.dumps({"type": "ping"}))
|
||||
|
||||
try:
|
||||
response = await asyncio.wait_for(websocket.recv(), timeout=3.0)
|
||||
print(f"📥 Ответ сервера: {response}")
|
||||
except asyncio.TimeoutError:
|
||||
print("⏰ Таймаут, но подключение работает")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка тестирования JWT токена: {e}")
|
||||
return False
|
||||
|
||||
async def test_emergency_endpoints(self) -> bool:
|
||||
"""Полное тестирование всех endpoint'ов экстренных вызовов"""
|
||||
print("\n🚨 ТЕСТ: Полная проверка Emergency API")
|
||||
print("="*60)
|
||||
|
||||
try:
|
||||
# Получаем JWT токен
|
||||
async with httpx.AsyncClient() as client:
|
||||
login_data = {
|
||||
"email": "shadow85@list.ru",
|
||||
"password": "R0sebud1985"
|
||||
}
|
||||
|
||||
print("🔐 Авторизация для тестирования API...")
|
||||
response = await client.post(
|
||||
f"{self.base_url}/api/v1/auth/login",
|
||||
json=login_data,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"❌ Ошибка авторизации: {response.status_code}")
|
||||
return False
|
||||
|
||||
auth_data = response.json()
|
||||
jwt_token = auth_data.get("access_token")
|
||||
headers = {
|
||||
"Authorization": f"Bearer {jwt_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
test_results = {}
|
||||
|
||||
# 1. Создание экстренного вызова (правильный endpoint)
|
||||
print("\n📞 1. Тест создания экстренного вызова...")
|
||||
alert_data = {
|
||||
"alert_type": "medical",
|
||||
"latitude": 55.7558,
|
||||
"longitude": 37.6176,
|
||||
"address": "Красная площадь, Москва",
|
||||
"description": "Тестовый экстренный вызов для проверки API"
|
||||
}
|
||||
|
||||
response = await client.post(
|
||||
f"{self.emergency_url}/api/v1/alert", # Используем правильный endpoint
|
||||
json=alert_data,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
created_alert = response.json()
|
||||
alert_id = created_alert.get("id")
|
||||
print(f"✅ Экстренный вызов создан: ID={alert_id}")
|
||||
test_results["create_alert"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка создания вызова: {response.status_code} - {response.text}")
|
||||
test_results["create_alert"] = False
|
||||
alert_id = None
|
||||
|
||||
# 2. Получение моих вызовов
|
||||
print("\n📋 2. Тест получения моих вызовов...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/alerts/my",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
alerts = response.json()
|
||||
print(f"✅ Получен список моих вызовов: {len(alerts)} записей")
|
||||
test_results["get_my_alerts"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка получения моих вызовов: {response.status_code}")
|
||||
test_results["get_my_alerts"] = False
|
||||
|
||||
# 3. Получение активных вызовов
|
||||
print("\n<EFBFBD> 3. Тест получения активных вызовов...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/alerts/active",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
active_alerts = response.json()
|
||||
print(f"✅ Получен список активных вызовов: {len(active_alerts)} записей")
|
||||
test_results["get_active_alerts"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка получения активных вызовов: {response.status_code}")
|
||||
test_results["get_active_alerts"] = False
|
||||
|
||||
# 4. Создание отчета об экстренной ситуации
|
||||
print("\n📝 4. Тест создания отчета...")
|
||||
report_data = {
|
||||
"incident_type": "suspicious_activity",
|
||||
"latitude": 55.7500,
|
||||
"longitude": 37.6200,
|
||||
"address": "Тверская улица, Москва",
|
||||
"description": "Тестовый отчет о подозрительной активности",
|
||||
"severity": "medium"
|
||||
}
|
||||
|
||||
response = await client.post(
|
||||
f"{self.emergency_url}/api/v1/report",
|
||||
json=report_data,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
created_report = response.json()
|
||||
report_id = created_report.get("id")
|
||||
print(f"✅ Отчет создан: ID={report_id}")
|
||||
test_results["create_report"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка создания отчета: {response.status_code} - {response.text}")
|
||||
test_results["create_report"] = False
|
||||
report_id = None
|
||||
|
||||
# 5. Получение списка отчетов
|
||||
print("\n📊 5. Тест получения списка отчетов...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/reports",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
reports = response.json()
|
||||
print(f"✅ Получен список отчетов: {len(reports)} записей")
|
||||
test_results["get_reports"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка получения отчетов: {response.status_code}")
|
||||
test_results["get_reports"] = False
|
||||
|
||||
# 6. Поиск ближайших вызовов
|
||||
print("\n🗺️ 6. Тест поиска ближайших вызовов...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/alerts/nearby?latitude=55.7558&longitude=37.6176&radius=5",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
nearby_alerts = response.json()
|
||||
print(f"✅ Найдены ближайшие вызовы: {len(nearby_alerts)} в радиусе 5км")
|
||||
test_results["nearby_alerts"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка поиска ближайших: {response.status_code}")
|
||||
test_results["nearby_alerts"] = False
|
||||
|
||||
# 7. Создание проверки безопасности
|
||||
print("\n🛡️ 7. Тест создания проверки безопасности...")
|
||||
safety_data = {
|
||||
"latitude": 55.7600,
|
||||
"longitude": 37.6100,
|
||||
"status": "safe",
|
||||
"message": "Тестовая проверка безопасности - всё в порядке"
|
||||
}
|
||||
|
||||
response = await client.post(
|
||||
f"{self.emergency_url}/api/v1/safety-check",
|
||||
json=safety_data,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
safety_check = response.json()
|
||||
print(f"✅ Проверка безопасности создана: статус={safety_check.get('status')}")
|
||||
test_results["create_safety_check"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка создания проверки: {response.status_code} - {response.text}")
|
||||
test_results["create_safety_check"] = False
|
||||
|
||||
# 8. Получение списка проверок безопасности
|
||||
print("\n<EFBFBD>️ 8. Тест получения проверок безопасности...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/safety-checks",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
safety_checks = response.json()
|
||||
print(f"✅ Получен список проверок: {len(safety_checks)} записей")
|
||||
test_results["get_safety_checks"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка получения проверок: {response.status_code}")
|
||||
test_results["get_safety_checks"] = False
|
||||
|
||||
# 9. Получение статистики
|
||||
print("\n📈 9. Тест получения статистики...")
|
||||
response = await client.get(
|
||||
f"{self.emergency_url}/api/v1/stats",
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
stats = response.json()
|
||||
print(f"✅ Статистика получена: {stats}")
|
||||
test_results["get_statistics"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка получения статистики: {response.status_code}")
|
||||
test_results["get_statistics"] = False
|
||||
|
||||
# 10. Ответ на экстренный вызов (если создан)
|
||||
if alert_id:
|
||||
print(f"\n🆘 10. Тест ответа на вызов ID={alert_id}...")
|
||||
response_data = {
|
||||
"response_type": "help_on_way",
|
||||
"message": "Помощь в пути, держитесь!"
|
||||
}
|
||||
|
||||
response = await client.post(
|
||||
f"{self.emergency_url}/api/v1/alert/{alert_id}/respond",
|
||||
json=response_data,
|
||||
headers=headers
|
||||
)
|
||||
|
||||
if response.status_code in [200, 201]:
|
||||
alert_response = response.json()
|
||||
print(f"✅ Ответ на вызов создан: {alert_response.get('response_type')}")
|
||||
test_results["respond_to_alert"] = True
|
||||
else:
|
||||
print(f"❌ Ошибка ответа на вызов: {response.status_code}")
|
||||
test_results["respond_to_alert"] = False
|
||||
|
||||
# Результат тестирования API
|
||||
total_tests = len(test_results)
|
||||
passed_tests = sum(test_results.values())
|
||||
|
||||
print(f"\n📊 РЕЗУЛЬТАТ ТЕСТИРОВАНИЯ API:")
|
||||
print(f"✅ Пройдено: {passed_tests}/{total_tests} тестов")
|
||||
|
||||
for test_name, result in test_results.items():
|
||||
status = "✅" if result else "❌"
|
||||
print(f" {status} {test_name}")
|
||||
|
||||
return passed_tests == total_tests
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка тестирования Emergency API: {e}")
|
||||
return False
|
||||
|
||||
async def run_security_test(self):
|
||||
"""Запуск полного теста безопасности"""
|
||||
print("🛡️ ЗАПУСК ПОЛНОГО ТЕСТА БЕЗОПАСНОСТИ И ФУНКЦИОНАЛЬНОСТИ")
|
||||
print("="*80)
|
||||
|
||||
# Тест 1: Блокировка временных токенов
|
||||
temp_tokens_blocked = await self.test_temp_token_rejection()
|
||||
|
||||
# Тест 2: Прием JWT токенов
|
||||
jwt_tokens_accepted = await self.test_jwt_token_acceptance()
|
||||
|
||||
# Тест 3: Полная проверка Emergency API
|
||||
emergency_api_working = await self.test_emergency_endpoints()
|
||||
|
||||
# Результат
|
||||
print("\n" + "="*80)
|
||||
print("📊 ПОЛНЫЙ РЕЗУЛЬТАТ ТЕСТИРОВАНИЯ")
|
||||
print("="*80)
|
||||
|
||||
all_tests_passed = temp_tokens_blocked and jwt_tokens_accepted and emergency_api_working
|
||||
|
||||
if all_tests_passed:
|
||||
print("✅ ВСЕ ТЕСТЫ ПРОЙДЕНЫ УСПЕШНО!")
|
||||
print("✅ Безопасность: Временные токены корректно блокируются")
|
||||
print("✅ Аутентификация: JWT токены корректно принимаются")
|
||||
print("✅ Функциональность: Все Emergency API работают")
|
||||
print("🔒 Система полностью готова к продакшену")
|
||||
else:
|
||||
print("❌ ОБНАРУЖЕНЫ ПРОБЛЕМЫ!")
|
||||
if not temp_tokens_blocked:
|
||||
print("❌ Проблема безопасности: Временные токены не блокируются")
|
||||
if not jwt_tokens_accepted:
|
||||
print("❌ Проблема аутентификации: JWT токены не принимаются")
|
||||
if not emergency_api_working:
|
||||
print("❌ Проблема функциональности: Emergency API работают неполностью")
|
||||
print("⚠️ Система НЕ готова к продакшену")
|
||||
|
||||
print(f"\n📈 Статистика тестирования:")
|
||||
print(f" 🔒 Безопасность: {'✅ ПРОЙДЕНО' if temp_tokens_blocked else '❌ ПРОВАЛЕНО'}")
|
||||
print(f" 🔐 Аутентификация: {'✅ ПРОЙДЕНО' if jwt_tokens_accepted else '❌ ПРОВАЛЕНО'}")
|
||||
print(f" 🚨 Emergency API: {'✅ ПРОЙДЕНО' if emergency_api_working else '❌ ПРОВАЛЕНО'}")
|
||||
|
||||
return all_tests_passed
|
||||
|
||||
async def main():
|
||||
"""Главная функция"""
|
||||
tester = SecurityTest()
|
||||
await tester.run_security_test()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user