embed-client 3.1.0.0__py3-none-any.whl → 3.1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
embed_client/auth.py CHANGED
@@ -17,16 +17,12 @@ from urllib.parse import urlparse
17
17
 
18
18
  # Try to import mcp_security_framework components
19
19
  try:
20
- from mcp_security_framework.core.auth_manager import AuthManager
21
- from mcp_security_framework.core.permission_manager import PermissionManager
22
- from mcp_security_framework.schemas.config import AuthConfig, PermissionConfig
23
- from mcp_security_framework.schemas.models import AuthResult, AuthStatus
24
- from mcp_security_framework.utils.crypto_utils import (
25
- create_jwt_token,
26
- verify_jwt_token,
27
- generate_secure_token,
28
- hash_password,
29
- verify_password
20
+ from mcp_security_framework import (
21
+ AuthManager,
22
+ AuthConfig,
23
+ PermissionConfig,
24
+ PermissionManager,
25
+ SecurityManager
30
26
  )
31
27
  SECURITY_FRAMEWORK_AVAILABLE = True
32
28
  except ImportError:
@@ -106,12 +102,20 @@ class ClientAuthManager:
106
102
  # Create permission config
107
103
  permission_config = PermissionConfig(
108
104
  enabled=self.config.get("security", {}).get("roles_enabled", False),
109
- roles_file=self.config.get("security", {}).get("roles_file")
105
+ roles_file=self.config.get("security", {}).get("roles_file") or "configs/roles.json"
106
+ )
107
+
108
+ # Create security config
109
+ from mcp_security_framework import SecurityConfig
110
+ security_config = SecurityConfig(
111
+ auth=auth_config,
112
+ permissions=permission_config
110
113
  )
111
114
 
112
115
  # Initialize managers
113
- self.permission_manager = PermissionManager(permission_config)
114
- self.auth_manager = AuthManager(auth_config, self.permission_manager)
116
+ self.security_manager = SecurityManager(security_config)
117
+ self.auth_manager = self.security_manager.auth_manager
118
+ self.permission_manager = self.security_manager.permission_manager
115
119
 
116
120
  self.logger.info("Security framework initialized successfully")
117
121
 
@@ -49,10 +49,10 @@ SECURITY MODES EXAMPLES:
49
49
  python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --auth-method jwt --jwt-secret secret --jwt-username admin
50
50
 
51
51
  # 5. mTLS - mutual TLS with client and server certificates
52
- python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --cert-file certs/client.crt --key-file keys/client.key
52
+ python embed_client/example_async_usage.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key
53
53
 
54
54
  # 6. mTLS + Roles - mTLS with role-based access control
55
- python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --cert-file certs/client.crt --key-file keys/client.key --roles admin,user
55
+ python embed_client/example_async_usage.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key --roles admin,user
56
56
 
57
57
  CLIENT FACTORY EXAMPLES:
58
58
  # Automatic security mode detection
@@ -62,14 +62,14 @@ CLIENT FACTORY EXAMPLES:
62
62
  python embed_client/example_async_usage.py --factory-mode https_token --base-url https://localhost --port 9443 --auth-method basic --username user --password pass
63
63
 
64
64
  # mTLS with factory
65
- python embed_client/example_async_usage.py --factory-mode mtls --base-url https://localhost --port 9443 --cert-file certs/client.crt --key-file keys/client.key
65
+ python embed_client/example_async_usage.py --factory-mode mtls --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key
66
66
 
67
67
  SSL/TLS EXAMPLES:
68
68
  # HTTPS with SSL verification disabled
69
69
  python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --ssl-verify-mode CERT_NONE
70
70
 
71
71
  # mTLS with custom CA certificate
72
- python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --cert-file certs/client.crt --key-file keys/client.key --ca-cert-file certs/ca.crt
72
+ python embed_client/example_async_usage.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key --ca-cert-file mtls_certificates/ca/ca.crt
73
73
 
74
74
  # HTTPS with custom SSL settings
75
75
  python embed_client/example_async_usage.py --base-url https://localhost --port 9443 --ssl-verify-mode CERT_REQUIRED --ssl-check-hostname --ssl-check-expiry
@@ -458,7 +458,7 @@ async def demonstrate_security_modes():
458
458
  print(" Use case: High security, client certificate authentication")
459
459
  try:
460
460
  client = ClientFactory.create_mtls_client(
461
- "https://localhost", "client_cert.pem", "client_key.pem", 9443
461
+ "https://localhost", "mtls_certificates/client/embedding-service.crt", "mtls_certificates/client/embedding-service.key", 8443
462
462
  )
463
463
  print(f" ✓ Created mTLS client: {client.base_url}:{client.port}")
464
464
  print(f" ✓ SSL enabled: {client.is_ssl_enabled()}")
@@ -476,7 +476,7 @@ async def demonstrate_security_modes():
476
476
  print(" Use case: Enterprise security, role-based permissions")
477
477
  try:
478
478
  client = ClientFactory.create_mtls_roles_client(
479
- "https://localhost", "client_cert.pem", "client_key.pem", 9443,
479
+ "https://localhost", "mtls_certificates/client/embedding-service.crt", "mtls_certificates/client/embedding-service.key", 8443,
480
480
  roles=["admin", "user"], role_attributes={"department": "IT"}
481
481
  )
482
482
  print(f" ✓ Created mTLS + Roles client: {client.base_url}:{client.port}")
@@ -1,17 +1,9 @@
1
1
  """
2
- Пример использования EmbeddingServiceAsyncClient со всеми режимами безопасности.
2
+ Пример использования EmbeddingServiceAsyncClient со всеми режимами безопасности и ClientFactory.
3
3
 
4
4
  Author: Vasiliy Zdanovskiy
5
5
  email: vasilyvz@gmail.com
6
6
 
7
- Этот пример демонстрирует все 6 режимов безопасности, поддерживаемых embed-client:
8
- 1. HTTP (обычный HTTP без аутентификации)
9
- 2. HTTP + Token (HTTP с аутентификацией по API ключу)
10
- 3. HTTPS (HTTPS с проверкой сертификатов сервера)
11
- 4. HTTPS + Token (HTTPS с сертификатами сервера + аутентификация)
12
- 5. mTLS (взаимный TLS с клиентскими и серверными сертификатами)
13
- 6. mTLS + Роли (mTLS с контролем доступа на основе ролей)
14
-
15
7
  ИСПОЛЬЗОВАНИЕ:
16
8
  # Базовое использование без аутентификации
17
9
  python embed_client/example_async_usage_ru.py --base-url http://localhost --port 8001
@@ -48,18 +40,28 @@ email: vasilyvz@gmail.com
48
40
  # 4. HTTPS + Token - HTTPS с сертификатами сервера + аутентификация
49
41
  python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --auth-method jwt --jwt-secret secret --jwt-username admin
50
42
 
51
- # 5. mTLS - взаимный TLS с клиентскими и серверными сертификатами
52
- python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --auth-method certificate --cert-file certs/client.crt --key-file keys/client.key
43
+ # 5. mTLS - взаимная TLS с сертификатами клиента и сервера
44
+ python embed_client/example_async_usage_ru.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key
45
+
46
+ # 6. mTLS + Roles - mTLS с контролем доступа на основе ролей
47
+ python embed_client/example_async_usage_ru.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key --roles admin,user
48
+
49
+ ПРИМЕРЫ ФАБРИКИ КЛИЕНТОВ:
50
+ # Автоматическое определение режима безопасности
51
+ python embed_client/example_async_usage_ru.py --factory-mode auto --base-url https://localhost --port 9443 --auth-method api_key --api-key key
52
+
53
+ # Создание конкретного режима безопасности
54
+ python embed_client/example_async_usage_ru.py --factory-mode https_token --base-url https://localhost --port 9443 --auth-method basic --username user --password pass
53
55
 
54
- # 6. mTLS + Роли - mTLS с контролем доступа на основе ролей
55
- python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --auth-method certificate --cert-file certs/client.crt --key-file keys/client.key --roles admin,user
56
+ # mTLS с фабрикой
57
+ python embed_client/example_async_usage_ru.py --factory-mode mtls --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key
56
58
 
57
59
  ПРИМЕРЫ SSL/TLS:
58
60
  # HTTPS с отключенной проверкой SSL
59
61
  python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --ssl-verify-mode CERT_NONE
60
62
 
61
63
  # mTLS с пользовательским CA сертификатом
62
- python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --cert-file certs/client.crt --key-file keys/client.key --ca-cert-file certs/ca.crt
64
+ python embed_client/example_async_usage_ru.py --base-url https://localhost --port 8443 --cert-file mtls_certificates/client/embedding-service.crt --key-file mtls_certificates/client/embedding-service.key --ca-cert-file mtls_certificates/ca/ca.crt
63
65
 
64
66
  # HTTPS с пользовательскими настройками SSL
65
67
  python embed_client/example_async_usage_ru.py --base-url https://localhost --port 9443 --ssl-verify-mode CERT_REQUIRED --ssl-check-hostname --ssl-check-expiry
@@ -75,7 +77,7 @@ email: vasilyvz@gmail.com
75
77
  export EMBED_CLIENT_API_KEY=production_key
76
78
  python embed_client/example_async_usage_ru.py
77
79
 
78
- ПРОГРАММНЫЕ ПРИМЕРЫ:
80
+ Пример явного закрытия сессии:
79
81
  import asyncio
80
82
  from embed_client.async_client import EmbeddingServiceAsyncClient
81
83
  from embed_client.config import ClientConfig
@@ -101,29 +103,25 @@ email: vasilyvz@gmail.com
101
103
  'https://localhost', 9443, 'api_key', api_key='key'
102
104
  )
103
105
  await client.close()
104
-
105
- # Метод 5: Использование метода with_auth для динамической аутентификации
106
- client = EmbeddingServiceAsyncClient('http://localhost', 8001)
107
- client = client.with_auth('api_key', api_key='dynamic_key')
108
- await client.close()
109
106
 
110
107
  asyncio.run(main())
111
108
  """
112
109
 
113
- import asyncio
114
- import sys
115
- import os
116
110
  import argparse
111
+ import asyncio
117
112
  import json
113
+ import os
114
+ import sys
118
115
  from typing import Dict, Any, Optional, Union
119
116
 
120
- from embed_client.async_client import EmbeddingServiceAsyncClient, EmbeddingServiceError, EmbeddingServiceConnectionError, EmbeddingServiceHTTPError, EmbeddingServiceConfigError
117
+ from embed_client.async_client import EmbeddingServiceAsyncClient, EmbeddingServiceError, EmbeddingServiceConfigError
121
118
  from embed_client.config import ClientConfig
122
119
  from embed_client.client_factory import (
123
120
  ClientFactory, SecurityMode, create_client, create_client_from_config,
124
121
  create_client_from_env, detect_security_mode
125
122
  )
126
123
 
124
+
127
125
  def get_params():
128
126
  """Парсинг аргументов командной строки и переменных окружения для конфигурации клиента."""
129
127
  parser = argparse.ArgumentParser(description="Пример Embedding Service Async Client - Все режимы безопасности")
@@ -149,33 +147,26 @@ def get_params():
149
147
  parser.add_argument("--cert-file", help="Файл сертификата для аутентификации certificate")
150
148
  parser.add_argument("--key-file", help="Файл ключа для аутентификации certificate")
151
149
 
152
- # SSL/TLS параметры
150
+ # Параметры SSL/TLS
153
151
  parser.add_argument("--ssl-verify-mode", choices=["CERT_NONE", "CERT_OPTIONAL", "CERT_REQUIRED"],
154
- default="CERT_REQUIRED", help="Режим проверки SSL сертификата")
152
+ default="CERT_REQUIRED", help="Режим проверки SSL сертификатов")
155
153
  parser.add_argument("--ssl-check-hostname", action="store_true", default=True,
156
154
  help="Включить проверку имени хоста SSL")
157
155
  parser.add_argument("--ssl-check-expiry", action="store_true", default=True,
158
- help="Включить проверку срока действия SSL сертификата")
156
+ help="Включить проверку срока действия SSL сертификатов")
159
157
  parser.add_argument("--ca-cert-file", help="Файл CA сертификата для проверки SSL")
160
158
 
161
- # Контроль доступа на основе ролей (для mTLS + Роли)
162
- parser.add_argument("--roles", help="Список ролей через запятую для режима mTLS + Роли")
163
- parser.add_argument("--role-attributes", help="JSON строка атрибутов ролей для режима mTLS + Роли")
159
+ # Контроль доступа на основе ролей (для mTLS + Roles)
160
+ parser.add_argument("--roles", help="Список ролей через запятую для режима mTLS + Roles")
161
+ parser.add_argument("--role-attributes", help="JSON строка атрибутов ролей для режима mTLS + Roles")
164
162
 
165
163
  # Дополнительные параметры
166
164
  parser.add_argument("--timeout", type=float, default=30.0, help="Таймаут запроса в секундах")
167
- parser.add_argument("--demo-mode", action="store_true", help="Запустить в демо режиме (показать все режимы безопасности)")
165
+ parser.add_argument("--demo-mode", action="store_true", help="Запуск в демо режиме (показать все режимы безопасности)")
168
166
 
169
167
  args = parser.parse_args()
170
168
 
171
- # Сохраняем demo_mode в args для дальнейшего использования
172
- args.demo_mode = args.demo_mode
173
-
174
- # Если запрошен демо режим, возвращаем args напрямую
175
- if args.demo_mode:
176
- return args
177
-
178
- # Если указан файл конфигурации, загружаем его
169
+ # Если предоставлен файл конфигурации, загружаем его
179
170
  if args.config:
180
171
  try:
181
172
  config = ClientConfig()
@@ -190,7 +181,7 @@ def get_params():
190
181
  port = args.port or int(os.environ.get("EMBED_CLIENT_PORT", "8001"))
191
182
 
192
183
  if not base_url or not port:
193
- print("Ошибка: base_url и port должны быть указаны через аргументы --base-url/--port или переменные окружения EMBED_CLIENT_BASE_URL/EMBED_CLIENT_PORT.")
184
+ print("Ошибка: base_url и port должны быть предоставлены через аргументы --base-url/--port или переменные окружения EMBED_CLIENT_BASE_URL/EMBED_CLIENT_PORT.")
194
185
  sys.exit(1)
195
186
 
196
187
  # Строим словарь конфигурации
@@ -213,7 +204,7 @@ def get_params():
213
204
  if api_key:
214
205
  config_dict["auth"]["api_keys"] = {"user": api_key}
215
206
  else:
216
- print("Предупреждение: API ключ не указан для аутентификации api_key")
207
+ print("Предупреждение: API ключ не предоставлен для аутентификации api_key")
217
208
 
218
209
  elif args.auth_method == "jwt":
219
210
  jwt_secret = args.jwt_secret or os.environ.get("EMBED_CLIENT_JWT_SECRET")
@@ -227,7 +218,7 @@ def get_params():
227
218
  "password": jwt_password
228
219
  }
229
220
  else:
230
- print("Предупреждение: JWT секрет, имя пользователя или пароль не указаны для аутентификации jwt")
221
+ print("Предупреждение: JWT учетные данные не полностью предоставлены")
231
222
 
232
223
  elif args.auth_method == "basic":
233
224
  username = args.username or os.environ.get("EMBED_CLIENT_USERNAME")
@@ -239,7 +230,7 @@ def get_params():
239
230
  "password": password
240
231
  }
241
232
  else:
242
- print("Предупреждение: Имя пользователя или пароль не указаны для базовой аутентификации")
233
+ print("Предупреждение: Учетные данные базовой аутентификации не полностью предоставлены")
243
234
 
244
235
  elif args.auth_method == "certificate":
245
236
  cert_file = args.cert_file or os.environ.get("EMBED_CLIENT_CERT_FILE")
@@ -251,9 +242,9 @@ def get_params():
251
242
  "key_file": key_file
252
243
  }
253
244
  else:
254
- print("Предупреждение: Файл сертификата или ключа не указан для аутентификации certificate")
245
+ print("Предупреждение: Файлы сертификатов не полностью предоставлены")
255
246
 
256
- # Добавляем SSL конфигурацию если используется HTTPS или указаны SSL параметры
247
+ # Добавляем конфигурацию SSL если используется HTTPS или предоставлены SSL параметры
257
248
  if base_url.startswith("https://") or args.ssl_verify_mode != "CERT_REQUIRED" or args.ca_cert_file:
258
249
  config_dict["ssl"] = {
259
250
  "enabled": True,
@@ -271,7 +262,7 @@ def get_params():
271
262
  if args.key_file:
272
263
  config_dict["ssl"]["key_file"] = args.key_file
273
264
 
274
- # Добавляем контроль доступа на основе ролей для mTLS + Роли
265
+ # Добавляем контроль доступа на основе ролей для mTLS + Roles
275
266
  if args.roles:
276
267
  roles = [role.strip() for role in args.roles.split(",")]
277
268
  config_dict["roles"] = roles
@@ -285,8 +276,9 @@ def get_params():
285
276
 
286
277
  return config_dict
287
278
 
288
- def extract_vectors(result):
289
- """Извлечение эмбеддингов из ответа API, поддерживает старый и новый форматы."""
279
+
280
+ def extract_embeddings(result):
281
+ """Извлечение эмбеддингов из ответа API, поддерживая старый и новый форматы."""
290
282
  # Обработка прямого поля embeddings (совместимость со старым форматом)
291
283
  if "embeddings" in result:
292
284
  return result["embeddings"]
@@ -320,52 +312,159 @@ def extract_vectors(result):
320
312
 
321
313
  raise ValueError(f"Не удается извлечь эмбеддинги из ответа: {result}")
322
314
 
315
+
323
316
  async def run_client_examples(client):
324
317
  """Запуск примеров операций с клиентом."""
325
318
  # Проверка здоровья
326
319
  try:
327
320
  health = await client.health()
328
321
  print("Состояние сервиса:", health)
329
- except EmbeddingServiceConnectionError as e:
330
- print(f"[Ошибка подключения] {e}")
331
- return
332
- except EmbeddingServiceHTTPError as e:
333
- print(f"[HTTP ошибка] {e.status}: {e.message}")
334
- return
335
322
  except EmbeddingServiceError as e:
336
- print("[Другая ошибка]", e)
323
+ print(f"Ошибка при проверке здоровья: {e}")
337
324
  return
338
-
339
- # Запрос эмбеддингов для списка текстов
340
- texts = ["привет мир", "тестовый эмбеддинг"]
325
+
326
+ # Получение схемы OpenAPI
341
327
  try:
342
- result = await client.cmd("embed", params={"texts": texts})
343
- print("Результат эмбеддинга:", result)
344
-
345
- # Извлечение эмбеддингов
346
- embeddings = client.extract_embeddings(result)
347
- print("Эмбеддинги:", embeddings)
348
-
349
- # Извлечение текстов
350
- extracted_texts = client.extract_texts(result)
351
- print("Извлеченные тексты:", extracted_texts)
352
-
353
- # Извлечение чанков
354
- chunks = client.extract_chunks(result)
355
- print("Чанки:", chunks)
356
-
357
- # Извлечение токенов
358
- tokens = client.extract_tokens(result)
359
- print("Токены:", tokens)
360
-
361
- # Извлечение BM25 токенов
362
- bm25_tokens = client.extract_bm25_tokens(result)
363
- print("BM25 токены:", bm25_tokens)
328
+ schema = await client.get_openapi_schema()
329
+ print(f"Версия схемы OpenAPI: {schema.get('info', {}).get('version', 'неизвестно')}")
330
+ except EmbeddingServiceError as e:
331
+ print(f"Ошибка получения схемы OpenAPI: {e}")
332
+
333
+ # Получение доступных команд
334
+ try:
335
+ commands = await client.get_commands()
336
+ print(f"Доступные команды: {commands}")
337
+ except EmbeddingServiceError as e:
338
+ print(f"Ошибка получения команд: {e}")
339
+
340
+ # Тест генерации эмбеддингов
341
+ try:
342
+ texts = ["Привет, мир!", "Это тестовое предложение.", "Сервис эмбеддингов работает!"]
343
+ result = await client.cmd("embed", {"texts": texts})
364
344
 
345
+ if result.get("success"):
346
+ embeddings = extract_embeddings(result)
347
+ print(f"Сгенерировано {len(embeddings)} эмбеддингов")
348
+ print(f"Размерность первого эмбеддинга: {len(embeddings[0]) if embeddings else 0}")
349
+ else:
350
+ print(f"Генерация эмбеддингов не удалась: {result.get('error', 'Неизвестная ошибка')}")
365
351
  except EmbeddingServiceError as e:
366
- print(f"[Ошибка эмбеддинга] {e}")
367
- except ValueError as e:
368
- print(f"Обнаружен старый формат или ошибка извлечения нового формата данных: {e}")
352
+ print(f"Ошибка при генерации эмбеддингов: {e}")
353
+
354
+
355
+ async def demonstrate_security_modes():
356
+ """Демонстрация всех режимов безопасности с использованием ClientFactory."""
357
+ print("=== Демонстрация режимов безопасности ===")
358
+
359
+ # 1. HTTP режим
360
+ print("\n1. HTTP режим (без аутентификации, без SSL):")
361
+ try:
362
+ client = ClientFactory.create_http_client("http://localhost", 8001)
363
+ print(f" Создан HTTP клиент: {client.base_url}:{client.port}")
364
+ print(f" SSL включен: {client.is_ssl_enabled()}")
365
+ print(f" Аутентифицирован: {client.is_authenticated()}")
366
+ await client.close()
367
+ except Exception as e:
368
+ print(f" Ошибка: {e}")
369
+
370
+ # 2. HTTP + Token режим
371
+ print("\n2. HTTP + Token режим (HTTP с API ключом):")
372
+ try:
373
+ client = ClientFactory.create_http_token_client(
374
+ "http://localhost", 8001, "api_key", api_key="demo_key"
375
+ )
376
+ print(f" Создан HTTP + Token клиент: {client.base_url}:{client.port}")
377
+ print(f" SSL включен: {client.is_ssl_enabled()}")
378
+ print(f" Аутентифицирован: {client.is_authenticated()}")
379
+ print(f" Метод аутентификации: {client.get_auth_method()}")
380
+ await client.close()
381
+ except Exception as e:
382
+ print(f" Ошибка: {e}")
383
+
384
+ # 3. HTTPS режим
385
+ print("\n3. HTTPS режим (HTTPS с сертификатами сервера):")
386
+ try:
387
+ client = ClientFactory.create_https_client("https://localhost", 9443)
388
+ print(f" Создан HTTPS клиент: {client.base_url}:{client.port}")
389
+ print(f" SSL включен: {client.is_ssl_enabled()}")
390
+ print(f" Аутентифицирован: {client.is_authenticated()}")
391
+ if client.is_ssl_enabled():
392
+ ssl_config = client.get_ssl_config()
393
+ print(f" SSL конфигурация: {ssl_config}")
394
+ await client.close()
395
+ except Exception as e:
396
+ print(f" Ошибка: {e}")
397
+
398
+ # 4. HTTPS + Token режим
399
+ print("\n4. HTTPS + Token режим (HTTPS с сертификатами сервера + аутентификация):")
400
+ try:
401
+ client = ClientFactory.create_https_token_client(
402
+ "https://localhost", 9443, "basic", username="admin", password="secret"
403
+ )
404
+ print(f" Создан HTTPS + Token клиент: {client.base_url}:{client.port}")
405
+ print(f" SSL включен: {client.is_ssl_enabled()}")
406
+ print(f" Аутентифицирован: {client.is_authenticated()}")
407
+ print(f" Метод аутентификации: {client.get_auth_method()}")
408
+ await client.close()
409
+ except Exception as e:
410
+ print(f" Ошибка: {e}")
411
+
412
+ # 5. mTLS режим
413
+ print("\n5. mTLS режим (взаимная TLS с сертификатами клиента и сервера):")
414
+ try:
415
+ client = ClientFactory.create_mtls_client(
416
+ "https://localhost", "mtls_certificates/client/embedding-service.crt", "mtls_certificates/client/embedding-service.key", 8443
417
+ )
418
+ print(f" Создан mTLS клиент: {client.base_url}:{client.port}")
419
+ print(f" SSL включен: {client.is_ssl_enabled()}")
420
+ print(f" mTLS включен: {client.is_mtls_enabled()}")
421
+ print(f" Аутентифицирован: {client.is_authenticated()}")
422
+ await client.close()
423
+ except Exception as e:
424
+ print(f" Ошибка: {e}")
425
+
426
+ # 6. mTLS + Roles режим
427
+ print("\n6. mTLS + Roles режим (mTLS с контролем доступа на основе ролей):")
428
+ try:
429
+ client = ClientFactory.create_mtls_roles_client(
430
+ "https://localhost", "client_cert.pem", "client_key.pem", 9443,
431
+ roles=["admin", "user"], role_attributes={"department": "IT"}
432
+ )
433
+ print(f" Создан mTLS + Roles клиент: {client.base_url}:{client.port}")
434
+ print(f" SSL включен: {client.is_ssl_enabled()}")
435
+ print(f" mTLS включен: {client.is_mtls_enabled()}")
436
+ print(f" Аутентифицирован: {client.is_authenticated()}")
437
+ await client.close()
438
+ except Exception as e:
439
+ print(f" Ошибка: {e}")
440
+
441
+
442
+ async def demonstrate_automatic_detection():
443
+ """Демонстрация автоматического определения режима безопасности."""
444
+ print("\n=== Автоматическое определение режима безопасности ===")
445
+
446
+ test_cases = [
447
+ ("http://localhost", None, None, None, None, "HTTP"),
448
+ ("http://localhost", "api_key", None, None, None, "HTTP + Token"),
449
+ ("https://localhost", None, None, None, None, "HTTPS"),
450
+ ("https://localhost", "api_key", None, None, None, "HTTPS + Token"),
451
+ ("https://localhost", None, None, "cert.pem", "key.pem", "mTLS"),
452
+ ("https://localhost", None, None, "cert.pem", "key.pem", "mTLS + Roles", {"roles": ["admin"]}),
453
+ ]
454
+
455
+ for case in test_cases:
456
+ if len(case) == 6:
457
+ base_url, auth_method, ssl_enabled, cert_file, key_file, expected = case
458
+ kwargs = {}
459
+ else:
460
+ base_url, auth_method, ssl_enabled, cert_file, key_file, expected, kwargs = case
461
+
462
+ try:
463
+ mode = detect_security_mode(base_url, auth_method, ssl_enabled, cert_file, key_file, **kwargs)
464
+ print(f" {base_url} + {auth_method or 'none'} + {cert_file or 'no cert'} -> {mode} ({expected})")
465
+ except Exception as e:
466
+ print(f" Ошибка определения режима для {base_url}: {e}")
467
+
369
468
 
370
469
  async def main():
371
470
  try:
@@ -373,17 +472,16 @@ async def main():
373
472
 
374
473
  # Проверяем, запрошен ли демо режим
375
474
  if hasattr(config, 'demo_mode') and config.demo_mode:
376
- print("=== Демонстрация всех режимов безопасности ===")
377
- print("Этот режим показывает все 6 режимов безопасности embed-client.")
378
- print("Примечание: Эти примеры создают конфигурации клиентов, но не подключаются к реальным серверам.")
475
+ await demonstrate_security_modes()
476
+ await demonstrate_automatic_detection()
379
477
  return
380
478
 
381
479
  # Создаем клиент на основе режима фабрики
382
480
  if isinstance(config, ClientConfig):
383
- # Используя объект конфигурации
481
+ # Использование объекта конфигурации
384
482
  client = EmbeddingServiceAsyncClient.from_config(config)
385
483
  else:
386
- # Используя словарь конфигурации
484
+ # Использование словаря конфигурации
387
485
  factory_mode = getattr(config, 'factory_mode', 'auto')
388
486
 
389
487
  if factory_mode == "auto":
@@ -440,24 +538,18 @@ async def main():
440
538
  print(f" Поддерживаемые SSL протоколы: {protocols}")
441
539
  print()
442
540
 
443
- # Пример явного открытия/закрытия сессии
541
+ # Пример явного открытия/закрытия
444
542
  print("Пример явного открытия/закрытия сессии:")
445
543
  await client.close()
446
544
  print("Сессия закрыта явно (пример ручного закрытия).\n")
447
545
 
448
- # Используем контекстный менеджер
449
- try:
450
- if isinstance(config, ClientConfig):
451
- async with EmbeddingServiceAsyncClient.from_config(config) as client:
452
- await run_client_examples(client)
453
- else:
454
- async with EmbeddingServiceAsyncClient(config_dict=config) as client:
455
- await run_client_examples(client)
456
-
457
- except EmbeddingServiceError as e:
458
- print(f"[Ошибка EmbeddingService] {e}")
459
- except Exception as e:
460
- print(f"[Неожиданная ошибка] {e}")
546
+ # Использование контекстного менеджера
547
+ if isinstance(config, ClientConfig):
548
+ async with EmbeddingServiceAsyncClient.from_config(config) as client:
549
+ await run_client_examples(client)
550
+ else:
551
+ async with EmbeddingServiceAsyncClient(config_dict=config) as client:
552
+ await run_client_examples(client)
461
553
 
462
554
  except EmbeddingServiceConfigError as e:
463
555
  print(f"Ошибка конфигурации: {e}")
@@ -467,4 +559,4 @@ async def main():
467
559
  sys.exit(1)
468
560
 
469
561
  if __name__ == "__main__":
470
- asyncio.run(main())
562
+ asyncio.run(main())
@@ -17,16 +17,10 @@ from typing import Any, Dict, List, Optional, Union
17
17
 
18
18
  # Try to import mcp_security_framework components
19
19
  try:
20
- from mcp_security_framework.core.ssl_manager import SSLManager as FrameworkSSLManager
21
- from mcp_security_framework.core.cert_manager import CertificateManager
22
- from mcp_security_framework.schemas.config import SSLConfig
23
- from mcp_security_framework.schemas.models import CertificateInfo
24
- from mcp_security_framework.utils.cert_utils import (
25
- extract_certificate_info,
26
- get_certificate_expiry,
27
- is_certificate_self_signed,
28
- parse_certificate,
29
- validate_certificate_chain
20
+ from mcp_security_framework import (
21
+ SSLConfig,
22
+ CertificateInfo,
23
+ SecurityManager
30
24
  )
31
25
  SECURITY_FRAMEWORK_AVAILABLE = True
32
26
  except ImportError:
@@ -84,18 +78,33 @@ class ClientSSLManager:
84
78
  """Initialize mcp_security_framework components."""
85
79
  try:
86
80
  # Create SSL config
81
+ ssl_config_dict = self.config.get("ssl", {})
87
82
  ssl_config = SSLConfig(
88
- enabled=self.config.get("ssl", {}).get("enabled", False),
89
- cert_file=self.config.get("ssl", {}).get("cert_file"),
90
- key_file=self.config.get("ssl", {}).get("key_file"),
91
- ca_cert_file=self.config.get("ssl", {}).get("ca_cert_file"),
92
- verify_mode=self.config.get("ssl", {}).get("verify_mode", "CERT_REQUIRED"),
93
- check_hostname=self.config.get("ssl", {}).get("check_hostname", True),
94
- check_expiry=self.config.get("ssl", {}).get("check_expiry", True)
83
+ enabled=ssl_config_dict.get("enabled", False),
84
+ cert_file=ssl_config_dict.get("cert_file") if ssl_config_dict.get("cert_file") and os.path.exists(ssl_config_dict.get("cert_file")) else None,
85
+ key_file=ssl_config_dict.get("key_file") if ssl_config_dict.get("key_file") and os.path.exists(ssl_config_dict.get("key_file")) else None,
86
+ ca_cert_file=ssl_config_dict.get("ca_cert_file") if ssl_config_dict.get("ca_cert_file") and os.path.exists(ssl_config_dict.get("ca_cert_file")) else None,
87
+ verify_mode=ssl_config_dict.get("verify_mode", "CERT_REQUIRED"),
88
+ check_hostname=ssl_config_dict.get("check_hostname", True),
89
+ check_expiry=ssl_config_dict.get("check_expiry", True)
90
+ )
91
+
92
+ # Create permission config (required by SecurityManager)
93
+ from mcp_security_framework import PermissionConfig
94
+ permission_config = PermissionConfig(
95
+ enabled=False,
96
+ roles_file="configs/roles.json"
97
+ )
98
+
99
+ # Create security config
100
+ from mcp_security_framework import SecurityConfig
101
+ security_config = SecurityConfig(
102
+ ssl=ssl_config,
103
+ permissions=permission_config
95
104
  )
96
105
 
97
106
  # Initialize managers
98
- self.ssl_manager = FrameworkSSLManager(ssl_config)
107
+ self.ssl_manager = SecurityManager(security_config)
99
108
 
100
109
  self.logger.info("Security framework SSL/TLS components initialized successfully")
101
110
 
@@ -1,17 +1,44 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: embed-client
3
- Version: 3.1.0.0
3
+ Version: 3.1.0.1
4
4
  Summary: Async client for Embedding Service API with comprehensive authentication, SSL/TLS, and mTLS support
5
5
  Author-email: Vasiliy Zdanovskiy <vasilyvz@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/vasilyvz/embed-client
8
+ Project-URL: Repository, https://github.com/vasilyvz/embed-client
9
+ Project-URL: Documentation, https://github.com/vasilyvz/embed-client#readme
10
+ Project-URL: Bug Tracker, https://github.com/vasilyvz/embed-client/issues
11
+ Keywords: embedding,async,client,api,authentication,ssl,tls,mtls
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: System :: Networking
6
25
  Requires-Python: >=3.8
7
26
  Description-Content-Type: text/markdown
8
- Requires-Dist: aiohttp
27
+ License-File: LICENSE
28
+ Requires-Dist: aiohttp>=3.8.0
9
29
  Requires-Dist: PyJWT>=2.0.0
10
30
  Requires-Dist: cryptography>=3.0.0
11
31
  Requires-Dist: pydantic>=2.0.0
12
32
  Provides-Extra: test
13
33
  Requires-Dist: pytest; extra == "test"
14
34
  Requires-Dist: pytest-asyncio; extra == "test"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest; extra == "dev"
37
+ Requires-Dist: pytest-asyncio; extra == "dev"
38
+ Requires-Dist: black; extra == "dev"
39
+ Requires-Dist: flake8; extra == "dev"
40
+ Requires-Dist: mypy; extra == "dev"
41
+ Dynamic: license-file
15
42
 
16
43
  # embed-client
17
44
 
@@ -1,16 +1,17 @@
1
1
  embed_client/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
2
2
  embed_client/async_client.py,sha256=Zf08g-i_2ylDj4tt9E1TO9swi-zcozFDr4mJdlfiGSI,40222
3
- embed_client/auth.py,sha256=fw5Lc40GOTuKf4eOeAP6elSRKj6tqCfklbgTCOX1zWU,18317
3
+ embed_client/auth.py,sha256=MMk5XqFIY5htf3Bx0JA_8mJaAiLslpLUIVUaiO84XBw,18310
4
4
  embed_client/auth_examples.py,sha256=QX_QWaaeyBAqvSs9uOP1ZVdAe72gJ91e8AP1e7R-yzQ,7361
5
5
  embed_client/client_factory.py,sha256=-W2nvzMuyyQNu3_nNmALKHT9uL0Z9nMYTxyQ4bgVOFQ,14279
6
6
  embed_client/client_factory_examples.py,sha256=7A2JWkyGEJeOB7p84ijklh8rTyeRUeg2lCIPTfAtahc,11823
7
7
  embed_client/config.py,sha256=CzVmduJjuN82uiaxDyMyXJLS2tNOOlDBGwcO76SWjXg,19922
8
8
  embed_client/config_examples.py,sha256=9aEF8X4h9nbfSV_CORZLrlWM5KEwuwqW6AcQDPguQ7g,6175
9
- embed_client/example_async_usage.py,sha256=hBlFul7aZmcm9VTHC8EsbViIs5TotEJtGAW_tj1_yks,29418
10
- embed_client/example_async_usage_ru.py,sha256=u8yGpA8EQSOzSzwKmIl-HBuxL1A-FFqoxW75h7vy4ak,25065
9
+ embed_client/example_async_usage.py,sha256=dndf79MIqZaHvWzbtKrZVwU7G4a5yNL1JPMnMBEdLBg,29803
10
+ embed_client/example_async_usage_ru.py,sha256=3HeP5YoyGd49dRlxNC-2TAh_GbwSW4jJmoLXMpMIfFs,29899
11
11
  embed_client/ssl_examples.py,sha256=22lTGhK2bqGJ44uUCpc7v2egY4AP3_ar8RMaTb4KBwU,9346
12
- embed_client/ssl_manager.py,sha256=_Z9nq_dquGW-u0lMp2d-ZwyqxuSMKJJx4NUqczY-wsE,16839
13
- embed_client-3.1.0.0.dist-info/METADATA,sha256=PLg0A10U0Lhl1veBD-DKVS13ePLC58AwqBMmHLh3EGU,7347
14
- embed_client-3.1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- embed_client-3.1.0.0.dist-info/top_level.txt,sha256=uG00A4d9o9DFrhiN7goObpeig72Pniby0E7UpDRgyXY,13
16
- embed_client-3.1.0.0.dist-info/RECORD,,
12
+ embed_client/ssl_manager.py,sha256=Ts6-hKxUUNHdW3yldnoykaDblxWtGbIwKdnzPw__30U,17247
13
+ embed_client-3.1.0.1.dist-info/licenses/LICENSE,sha256=6KdtUcTwmTRbJrAmYjVn7e6S-V42ubeDJ-AiVEzZ510,1075
14
+ embed_client-3.1.0.1.dist-info/METADATA,sha256=mvhUNvCDzryNQh68sFeSyGx9ZG9gyypnkPWrNYqxth4,8633
15
+ embed_client-3.1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ embed_client-3.1.0.1.dist-info/top_level.txt,sha256=uG00A4d9o9DFrhiN7goObpeig72Pniby0E7UpDRgyXY,13
17
+ embed_client-3.1.0.1.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Vasiliy Zdanovskiy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.