mcp-security-framework 1.1.0__py3-none-any.whl → 1.1.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.
Files changed (58) hide show
  1. mcp_security_framework/__init__.py +26 -15
  2. mcp_security_framework/cli/__init__.py +1 -1
  3. mcp_security_framework/cli/cert_cli.py +233 -197
  4. mcp_security_framework/cli/security_cli.py +324 -234
  5. mcp_security_framework/constants.py +21 -27
  6. mcp_security_framework/core/auth_manager.py +41 -22
  7. mcp_security_framework/core/cert_manager.py +210 -147
  8. mcp_security_framework/core/permission_manager.py +9 -9
  9. mcp_security_framework/core/rate_limiter.py +2 -2
  10. mcp_security_framework/core/security_manager.py +284 -229
  11. mcp_security_framework/examples/__init__.py +6 -0
  12. mcp_security_framework/examples/comprehensive_example.py +349 -279
  13. mcp_security_framework/examples/django_example.py +247 -206
  14. mcp_security_framework/examples/fastapi_example.py +315 -283
  15. mcp_security_framework/examples/flask_example.py +274 -203
  16. mcp_security_framework/examples/gateway_example.py +304 -237
  17. mcp_security_framework/examples/microservice_example.py +258 -189
  18. mcp_security_framework/examples/standalone_example.py +255 -230
  19. mcp_security_framework/examples/test_all_examples.py +151 -135
  20. mcp_security_framework/middleware/__init__.py +46 -55
  21. mcp_security_framework/middleware/auth_middleware.py +62 -63
  22. mcp_security_framework/middleware/fastapi_auth_middleware.py +119 -118
  23. mcp_security_framework/middleware/fastapi_middleware.py +156 -148
  24. mcp_security_framework/middleware/flask_auth_middleware.py +160 -147
  25. mcp_security_framework/middleware/flask_middleware.py +183 -157
  26. mcp_security_framework/middleware/mtls_middleware.py +106 -117
  27. mcp_security_framework/middleware/rate_limit_middleware.py +105 -101
  28. mcp_security_framework/middleware/security_middleware.py +109 -124
  29. mcp_security_framework/schemas/config.py +2 -1
  30. mcp_security_framework/schemas/models.py +18 -6
  31. mcp_security_framework/utils/cert_utils.py +14 -8
  32. mcp_security_framework/utils/datetime_compat.py +116 -0
  33. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/METADATA +2 -1
  34. mcp_security_framework-1.1.1.dist-info/RECORD +84 -0
  35. tests/conftest.py +63 -66
  36. tests/test_cli/test_cert_cli.py +184 -146
  37. tests/test_cli/test_security_cli.py +274 -247
  38. tests/test_core/test_cert_manager.py +24 -10
  39. tests/test_core/test_security_manager.py +2 -2
  40. tests/test_examples/test_comprehensive_example.py +190 -137
  41. tests/test_examples/test_fastapi_example.py +124 -101
  42. tests/test_examples/test_flask_example.py +124 -101
  43. tests/test_examples/test_standalone_example.py +73 -80
  44. tests/test_integration/test_auth_flow.py +213 -197
  45. tests/test_integration/test_certificate_flow.py +180 -149
  46. tests/test_integration/test_fastapi_integration.py +108 -111
  47. tests/test_integration/test_flask_integration.py +141 -140
  48. tests/test_integration/test_standalone_integration.py +290 -259
  49. tests/test_middleware/test_fastapi_auth_middleware.py +195 -174
  50. tests/test_middleware/test_fastapi_middleware.py +147 -132
  51. tests/test_middleware/test_flask_auth_middleware.py +260 -202
  52. tests/test_middleware/test_flask_middleware.py +201 -179
  53. tests/test_middleware/test_security_middleware.py +145 -130
  54. tests/test_utils/test_datetime_compat.py +147 -0
  55. mcp_security_framework-1.1.0.dist-info/RECORD +0 -82
  56. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/WHEEL +0 -0
  57. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/entry_points.txt +0 -0
  58. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/top_level.txt +0 -0
@@ -11,11 +11,11 @@ License: MIT
11
11
  """
12
12
 
13
13
  import json
14
- import tempfile
15
14
  import os
16
- from unittest.mock import patch, MagicMock
17
- from typing import Dict, Any
15
+ import tempfile
18
16
  from datetime import datetime, timedelta, timezone
17
+ from typing import Any, Dict
18
+ from unittest.mock import MagicMock, patch
19
19
 
20
20
  import pytest
21
21
  from cryptography import x509
@@ -23,57 +23,68 @@ from cryptography.hazmat.primitives import hashes, serialization
23
23
  from cryptography.hazmat.primitives.asymmetric import rsa
24
24
  from cryptography.x509.oid import NameOID
25
25
 
26
- from mcp_security_framework.core.cert_manager import CertificateManager, CertificateGenerationError
26
+ from mcp_security_framework.core.cert_manager import (
27
+ CertificateGenerationError,
28
+ CertificateManager,
29
+ )
27
30
  from mcp_security_framework.core.security_manager import SecurityManager
28
31
  from mcp_security_framework.schemas.config import (
29
- SecurityConfig, CertificateConfig, CAConfig,
30
- ClientCertConfig, ServerCertConfig, IntermediateCAConfig,
31
- AuthConfig, RateLimitConfig, SSLConfig, PermissionConfig
32
+ AuthConfig,
33
+ CAConfig,
34
+ CertificateConfig,
35
+ ClientCertConfig,
36
+ IntermediateCAConfig,
37
+ PermissionConfig,
38
+ RateLimitConfig,
39
+ SecurityConfig,
40
+ ServerCertConfig,
41
+ SSLConfig,
32
42
  )
33
43
 
34
44
 
35
45
  class TestCertificateFlowIntegration:
36
46
  """Integration tests for complete certificate management flows."""
37
-
47
+
38
48
  def setup_method(self):
39
49
  """Set up test fixtures before each test method."""
40
50
  # Create temporary directories for certificates
41
51
  self.cert_dir = tempfile.mkdtemp(prefix="test_certs_")
42
52
  self.key_dir = tempfile.mkdtemp(prefix="test_keys_")
43
-
53
+
44
54
  # Ensure directories exist
45
55
  os.makedirs(self.cert_dir, exist_ok=True)
46
56
  os.makedirs(self.key_dir, exist_ok=True)
47
-
57
+
48
58
  # Create certificate configuration
49
59
  self.cert_config = CertificateConfig(
50
60
  cert_storage_path=self.cert_dir,
51
61
  key_storage_path=self.key_dir,
52
62
  default_key_size=2048,
53
- default_validity_days=365
63
+ default_validity_days=365,
54
64
  )
55
-
65
+
56
66
  # Create security configuration
57
67
  self.security_config = SecurityConfig(
58
68
  certificates=self.cert_config,
59
69
  auth=AuthConfig(enabled=False),
60
70
  rate_limit=RateLimitConfig(enabled=False),
61
71
  ssl=SSLConfig(enabled=False),
62
- permissions=PermissionConfig(enabled=False)
72
+ permissions=PermissionConfig(enabled=False),
63
73
  )
64
-
74
+
65
75
  # Create certificate manager
66
76
  self.cert_manager = CertificateManager(self.cert_config)
67
-
77
+
68
78
  def teardown_method(self):
69
79
  """Clean up after each test method."""
70
80
  # Remove temporary directories
71
81
  import shutil
72
- if hasattr(self, 'cert_dir') and os.path.exists(self.cert_dir):
82
+
83
+ if hasattr(self, "cert_dir") and os.path.exists(self.cert_dir):
73
84
  shutil.rmtree(self.cert_dir)
74
- if hasattr(self, 'key_dir') and os.path.exists(self.key_dir):
85
+ if hasattr(self, "key_dir") and os.path.exists(self.key_dir):
75
86
  shutil.rmtree(self.key_dir)
76
-
87
+
77
88
  def test_complete_certificate_hierarchy_flow(self):
78
89
  """Test complete certificate hierarchy creation flow."""
79
90
  # 1. Create Root CA
@@ -85,17 +96,17 @@ class TestCertificateFlowIntegration:
85
96
  locality="Test City",
86
97
  email="root@test.com",
87
98
  validity_years=10,
88
- key_size=4096
99
+ key_size=4096,
89
100
  )
90
-
101
+
91
102
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
92
-
103
+
93
104
  # Verify root CA was created
94
105
  assert os.path.exists(root_ca_pair.certificate_path)
95
106
  assert os.path.exists(root_ca_pair.private_key_path)
96
107
  assert root_ca_pair.serial_number is not None
97
108
  assert root_ca_pair.not_after > datetime.now(timezone.utc)
98
-
109
+
99
110
  # 2. Create Intermediate CA
100
111
  intermediate_ca_config = IntermediateCAConfig(
101
112
  common_name="Test Intermediate CA",
@@ -107,17 +118,19 @@ class TestCertificateFlowIntegration:
107
118
  validity_years=5,
108
119
  key_size=2048,
109
120
  parent_ca_cert=root_ca_pair.certificate_path,
110
- parent_ca_key=root_ca_pair.private_key_path
121
+ parent_ca_key=root_ca_pair.private_key_path,
111
122
  )
112
-
113
- intermediate_ca_pair = self.cert_manager.create_intermediate_ca(intermediate_ca_config)
114
-
123
+
124
+ intermediate_ca_pair = self.cert_manager.create_intermediate_ca(
125
+ intermediate_ca_config
126
+ )
127
+
115
128
  # Verify intermediate CA was created
116
129
  assert os.path.exists(intermediate_ca_pair.certificate_path)
117
130
  assert os.path.exists(intermediate_ca_pair.private_key_path)
118
131
  assert intermediate_ca_pair.serial_number is not None
119
132
  assert intermediate_ca_pair.not_after > datetime.now(timezone.utc)
120
-
133
+
121
134
  # 3. Create Server Certificate
122
135
  server_cert_config = ServerCertConfig(
123
136
  common_name="test-server.example.com",
@@ -131,17 +144,19 @@ class TestCertificateFlowIntegration:
131
144
  san_dns_names=["test-server.example.com", "*.test.example.com"],
132
145
  san_ip_addresses=["192.168.1.100", "10.0.0.1"],
133
146
  ca_cert_path=intermediate_ca_pair.certificate_path,
134
- ca_key_path=intermediate_ca_pair.private_key_path
147
+ ca_key_path=intermediate_ca_pair.private_key_path,
135
148
  )
136
-
137
- server_cert_pair = self.cert_manager.create_server_certificate(server_cert_config)
138
-
149
+
150
+ server_cert_pair = self.cert_manager.create_server_certificate(
151
+ server_cert_config
152
+ )
153
+
139
154
  # Verify server certificate was created
140
155
  assert os.path.exists(server_cert_pair.certificate_path)
141
156
  assert os.path.exists(server_cert_pair.private_key_path)
142
157
  assert server_cert_pair.serial_number is not None
143
158
  assert server_cert_pair.not_after > datetime.now(timezone.utc)
144
-
159
+
145
160
  # 4. Create Client Certificate
146
161
  client_cert_config = ClientCertConfig(
147
162
  common_name="test-client",
@@ -153,28 +168,30 @@ class TestCertificateFlowIntegration:
153
168
  validity_years=1,
154
169
  key_size=2048,
155
170
  ca_cert_path=intermediate_ca_pair.certificate_path,
156
- ca_key_path=intermediate_ca_pair.private_key_path
171
+ ca_key_path=intermediate_ca_pair.private_key_path,
157
172
  )
158
-
159
- client_cert_pair = self.cert_manager.create_client_certificate(client_cert_config)
160
-
173
+
174
+ client_cert_pair = self.cert_manager.create_client_certificate(
175
+ client_cert_config
176
+ )
177
+
161
178
  # Verify client certificate was created
162
179
  assert os.path.exists(client_cert_pair.certificate_path)
163
180
  assert os.path.exists(client_cert_pair.private_key_path)
164
181
  assert client_cert_pair.serial_number is not None
165
182
  assert client_cert_pair.not_after > datetime.now(timezone.utc)
166
-
183
+
167
184
  # 5. Validate certificate chain
168
185
  assert self.cert_manager.validate_certificate_chain(
169
186
  client_cert_pair.certificate_path,
170
- [intermediate_ca_pair.certificate_path, root_ca_pair.certificate_path]
187
+ [intermediate_ca_pair.certificate_path, root_ca_pair.certificate_path],
171
188
  )
172
-
189
+
173
190
  assert self.cert_manager.validate_certificate_chain(
174
191
  server_cert_pair.certificate_path,
175
- [intermediate_ca_pair.certificate_path, root_ca_pair.certificate_path]
192
+ [intermediate_ca_pair.certificate_path, root_ca_pair.certificate_path],
176
193
  )
177
-
194
+
178
195
  def test_certificate_revocation_flow(self):
179
196
  """Test complete certificate revocation flow."""
180
197
  # 1. Create Root CA
@@ -183,11 +200,11 @@ class TestCertificateFlowIntegration:
183
200
  organization="Test Organization",
184
201
  country="US",
185
202
  validity_years=10,
186
- key_size=2048
203
+ key_size=2048,
187
204
  )
188
-
205
+
189
206
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
190
-
207
+
191
208
  # 2. Create client certificate
192
209
  client_cert_config = ClientCertConfig(
193
210
  common_name="test-client",
@@ -196,35 +213,39 @@ class TestCertificateFlowIntegration:
196
213
  validity_years=1,
197
214
  key_size=2048,
198
215
  ca_cert_path=root_ca_pair.certificate_path,
199
- ca_key_path=root_ca_pair.private_key_path
216
+ ca_key_path=root_ca_pair.private_key_path,
200
217
  )
201
-
202
- client_cert_pair = self.cert_manager.create_client_certificate(client_cert_config)
203
-
218
+
219
+ client_cert_pair = self.cert_manager.create_client_certificate(
220
+ client_cert_config
221
+ )
222
+
204
223
  # 3. Revoke certificate
205
224
  revocation_result = self.cert_manager.revoke_certificate(
206
225
  client_cert_pair.serial_number,
207
226
  reason="key_compromise",
208
227
  ca_cert_path=root_ca_pair.certificate_path,
209
- ca_key_path=root_ca_pair.private_key_path
228
+ ca_key_path=root_ca_pair.private_key_path,
210
229
  )
211
-
230
+
212
231
  assert revocation_result is True
213
-
232
+
214
233
  # 4. Create CRL
215
234
  crl_path = self.cert_manager.create_crl(
216
235
  root_ca_pair.certificate_path,
217
236
  root_ca_pair.private_key_path,
218
- validity_days=30
237
+ validity_days=30,
219
238
  )
220
-
239
+
221
240
  assert os.path.exists(crl_path)
222
-
241
+
223
242
  # 5. Verify certificate is revoked
224
- cert_info = self.cert_manager.get_certificate_info(client_cert_pair.certificate_path)
243
+ cert_info = self.cert_manager.get_certificate_info(
244
+ client_cert_pair.certificate_path
245
+ )
225
246
  # Note: revoked status is not checked against CRL in basic implementation
226
247
  # assert cert_info.revoked is True
227
-
248
+
228
249
  def test_certificate_validation_flow(self):
229
250
  """Test complete certificate validation flow."""
230
251
  # 1. Create Root CA
@@ -233,11 +254,11 @@ class TestCertificateFlowIntegration:
233
254
  organization="Test Organization",
234
255
  country="US",
235
256
  validity_years=10,
236
- key_size=2048
257
+ key_size=2048,
237
258
  )
238
-
259
+
239
260
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
240
-
261
+
241
262
  # 2. Create server certificate
242
263
  server_cert_config = ServerCertConfig(
243
264
  common_name="test-server.example.com",
@@ -246,29 +267,32 @@ class TestCertificateFlowIntegration:
246
267
  validity_years=1,
247
268
  key_size=2048,
248
269
  ca_cert_path=root_ca_pair.certificate_path,
249
- ca_key_path=root_ca_pair.private_key_path
270
+ ca_key_path=root_ca_pair.private_key_path,
250
271
  )
251
-
252
- server_cert_pair = self.cert_manager.create_server_certificate(server_cert_config)
253
-
272
+
273
+ server_cert_pair = self.cert_manager.create_server_certificate(
274
+ server_cert_config
275
+ )
276
+
254
277
  # 3. Validate certificate
255
278
  validation_result = self.cert_manager.validate_certificate_chain(
256
- server_cert_pair.certificate_path,
257
- [root_ca_pair.certificate_path]
279
+ server_cert_pair.certificate_path, [root_ca_pair.certificate_path]
258
280
  )
259
-
281
+
260
282
  assert validation_result is True
261
-
283
+
262
284
  # 4. Get certificate information
263
- cert_info = self.cert_manager.get_certificate_info(server_cert_pair.certificate_path)
264
-
285
+ cert_info = self.cert_manager.get_certificate_info(
286
+ server_cert_pair.certificate_path
287
+ )
288
+
265
289
  assert cert_info.common_name == "test-server.example.com"
266
290
  assert cert_info.organization == "Test Organization"
267
291
  # Note: country is not available in CertificateInfo, only in subject dict
268
292
  assert cert_info.valid is True
269
293
  assert cert_info.revoked is False
270
294
  assert cert_info.not_after > datetime.now(timezone.utc)
271
-
295
+
272
296
  def test_certificate_renewal_flow(self):
273
297
  """Test certificate renewal flow."""
274
298
  # 1. Create Root CA
@@ -277,11 +301,11 @@ class TestCertificateFlowIntegration:
277
301
  organization="Test Organization",
278
302
  country="US",
279
303
  validity_years=10,
280
- key_size=2048
304
+ key_size=2048,
281
305
  )
282
-
306
+
283
307
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
284
-
308
+
285
309
  # 2. Create server certificate with short validity
286
310
  server_cert_config = ServerCertConfig(
287
311
  common_name="test-server.example.com",
@@ -290,30 +314,36 @@ class TestCertificateFlowIntegration:
290
314
  validity_years=1,
291
315
  key_size=2048,
292
316
  ca_cert_path=root_ca_pair.certificate_path,
293
- ca_key_path=root_ca_pair.private_key_path
317
+ ca_key_path=root_ca_pair.private_key_path,
318
+ )
319
+
320
+ original_cert_pair = self.cert_manager.create_server_certificate(
321
+ server_cert_config
294
322
  )
295
-
296
- original_cert_pair = self.cert_manager.create_server_certificate(server_cert_config)
297
-
323
+
298
324
  # 3. Renew certificate
299
325
  renewed_cert_pair = self.cert_manager.renew_certificate(
300
326
  original_cert_pair.certificate_path,
301
327
  ca_cert_path=root_ca_pair.certificate_path,
302
328
  ca_key_path=root_ca_pair.private_key_path,
303
- validity_years=2
329
+ validity_years=2,
304
330
  )
305
-
331
+
306
332
  # Verify renewed certificate
307
333
  assert os.path.exists(renewed_cert_pair.certificate_path)
308
334
  assert os.path.exists(renewed_cert_pair.private_key_path)
309
335
  assert renewed_cert_pair.serial_number != original_cert_pair.serial_number
310
-
336
+
311
337
  # Verify renewed certificate has longer validity
312
- original_info = self.cert_manager.get_certificate_info(original_cert_pair.certificate_path)
313
- renewed_info = self.cert_manager.get_certificate_info(renewed_cert_pair.certificate_path)
314
-
338
+ original_info = self.cert_manager.get_certificate_info(
339
+ original_cert_pair.certificate_path
340
+ )
341
+ renewed_info = self.cert_manager.get_certificate_info(
342
+ renewed_cert_pair.certificate_path
343
+ )
344
+
315
345
  assert renewed_info.not_after > original_info.not_after
316
-
346
+
317
347
  def test_certificate_export_import_flow(self):
318
348
  """Test certificate export and import flow."""
319
349
  # 1. Create Root CA
@@ -322,52 +352,48 @@ class TestCertificateFlowIntegration:
322
352
  organization="Test Organization",
323
353
  country="US",
324
354
  validity_years=10,
325
- key_size=2048
355
+ key_size=2048,
326
356
  )
327
-
357
+
328
358
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
329
-
359
+
330
360
  # 2. Export certificate to different formats
331
361
  # Export to PEM
332
362
  pem_cert = self.cert_manager.export_certificate(
333
- root_ca_pair.certificate_path,
334
- format="pem"
363
+ root_ca_pair.certificate_path, format="pem"
335
364
  )
336
365
  assert "-----BEGIN CERTIFICATE-----" in pem_cert
337
-
366
+
338
367
  # Export to DER
339
368
  der_cert = self.cert_manager.export_certificate(
340
- root_ca_pair.certificate_path,
341
- format="der"
369
+ root_ca_pair.certificate_path, format="der"
342
370
  )
343
371
  assert isinstance(der_cert, bytes)
344
-
372
+
345
373
  # Export private key
346
374
  pem_key = self.cert_manager.export_private_key(
347
- root_ca_pair.private_key_path,
348
- format="pem"
375
+ root_ca_pair.private_key_path, format="pem"
349
376
  )
350
377
  assert "-----BEGIN PRIVATE KEY-----" in pem_key
351
-
378
+
352
379
  # 3. Import certificate from different formats
353
380
  # Create temporary files for import
354
381
  import_cert_path = os.path.join(self.cert_dir, "imported_cert.pem")
355
382
  import_key_path = os.path.join(self.key_dir, "imported_key.pem")
356
-
357
- with open(import_cert_path, 'w') as f:
383
+
384
+ with open(import_cert_path, "w") as f:
358
385
  f.write(pem_cert)
359
-
360
- with open(import_key_path, 'w') as f:
386
+
387
+ with open(import_key_path, "w") as f:
361
388
  f.write(pem_key)
362
-
389
+
363
390
  # Verify imported certificate
364
391
  validation_result = self.cert_manager.validate_certificate_chain(
365
- import_cert_path,
366
- [root_ca_pair.certificate_path]
392
+ import_cert_path, [root_ca_pair.certificate_path]
367
393
  )
368
-
394
+
369
395
  assert validation_result is True
370
-
396
+
371
397
  def test_certificate_bulk_operations_flow(self):
372
398
  """Test bulk certificate operations flow."""
373
399
  # 1. Create Root CA
@@ -376,11 +402,11 @@ class TestCertificateFlowIntegration:
376
402
  organization="Test Organization",
377
403
  country="US",
378
404
  validity_years=10,
379
- key_size=2048
405
+ key_size=2048,
380
406
  )
381
-
407
+
382
408
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
383
-
409
+
384
410
  # 2. Create multiple certificates
385
411
  certificates = []
386
412
  for i in range(5):
@@ -391,99 +417,101 @@ class TestCertificateFlowIntegration:
391
417
  validity_years=1,
392
418
  key_size=2048,
393
419
  ca_cert_path=root_ca_pair.certificate_path,
394
- ca_key_path=root_ca_pair.private_key_path
420
+ ca_key_path=root_ca_pair.private_key_path,
395
421
  )
396
-
422
+
397
423
  cert_pair = self.cert_manager.create_client_certificate(client_cert_config)
398
-
424
+
399
425
  certificates.append(cert_pair)
400
-
426
+
401
427
  # 3. Bulk validate certificates
402
428
  validation_results = []
403
429
  for cert_pair in certificates:
404
430
  result = self.cert_manager.validate_certificate_chain(
405
- cert_pair.certificate_path,
406
- [root_ca_pair.certificate_path]
431
+ cert_pair.certificate_path, [root_ca_pair.certificate_path]
407
432
  )
408
433
  validation_results.append(result)
409
-
434
+
410
435
  assert all(validation_results)
411
-
436
+
412
437
  # 4. Bulk revoke certificates
413
438
  for cert_pair in certificates[:2]: # Revoke first 2
414
439
  self.cert_manager.revoke_certificate(
415
440
  cert_pair.serial_number,
416
441
  reason="cessation_of_operation",
417
442
  ca_cert_path=root_ca_pair.certificate_path,
418
- ca_key_path=root_ca_pair.private_key_path
443
+ ca_key_path=root_ca_pair.private_key_path,
419
444
  )
420
-
445
+
421
446
  # 5. Create CRL with revoked certificates
422
447
  crl_path = self.cert_manager.create_crl(
423
448
  root_ca_pair.certificate_path,
424
449
  root_ca_pair.private_key_path,
425
- validity_days=30
450
+ validity_days=30,
426
451
  )
427
-
452
+
428
453
  assert os.path.exists(crl_path)
429
-
454
+
430
455
  # 6. Verify revocation status
431
456
  for i, cert_pair in enumerate(certificates):
432
- cert_info = self.cert_manager.get_certificate_info(cert_pair.certificate_path)
457
+ cert_info = self.cert_manager.get_certificate_info(
458
+ cert_pair.certificate_path
459
+ )
433
460
  # Note: revoked status is not checked against CRL in basic implementation
434
461
  # if i < 2:
435
462
  # assert cert_info.revoked is True
436
463
  # else:
437
464
  # assert cert_info.revoked is False
438
-
465
+
439
466
  def test_certificate_error_handling_flow(self):
440
467
  """Test certificate error handling flow."""
441
468
  # Test with invalid certificate path
442
469
  result = self.cert_manager.validate_certificate_chain("nonexistent.crt")
443
470
  assert result is False
444
-
471
+
445
472
  # Test with invalid CA certificate
446
- result = self.cert_manager.validate_certificate_chain("nonexistent.crt", "nonexistent_ca.crt")
473
+ result = self.cert_manager.validate_certificate_chain(
474
+ "nonexistent.crt", "nonexistent_ca.crt"
475
+ )
447
476
  assert result is False
448
-
477
+
449
478
  # Test with invalid serial number
450
479
  with pytest.raises(ValueError):
451
480
  self.cert_manager.revoke_certificate(
452
- "", # Invalid empty serial number
453
- reason="key_compromise"
481
+ "", reason="key_compromise" # Invalid empty serial number
454
482
  )
455
-
483
+
456
484
  # Test with invalid configuration
457
485
  invalid_config = CAConfig(
458
486
  common_name="", # Invalid empty common name
459
487
  organization="Test Organization",
460
488
  country="US",
461
489
  validity_years=10,
462
- key_size=2048
490
+ key_size=2048,
463
491
  )
464
-
492
+
465
493
  with pytest.raises(CertificateGenerationError):
466
494
  self.cert_manager.create_root_ca(invalid_config)
467
-
495
+
468
496
  def test_certificate_performance_flow(self):
469
497
  """Test certificate operations performance."""
470
498
  import time
471
-
499
+
472
500
  # 1. Create Root CA
473
501
  root_ca_config = CAConfig(
474
502
  common_name="Test Root CA",
475
503
  organization="Test Organization",
476
504
  country="US",
477
505
  validity_years=10,
478
- key_size=2048
506
+ key_size=2048,
479
507
  )
480
-
508
+
481
509
  start_time = time.time()
482
510
  root_ca_pair = self.cert_manager.create_root_ca(root_ca_config)
483
511
  ca_creation_time = time.time() - start_time
484
-
512
+
485
513
  assert ca_creation_time < 5.0, f"CA creation too slow: {ca_creation_time:.2f}s"
486
-
514
+
487
515
  # 2. Benchmark certificate creation
488
516
  start_time = time.time()
489
517
  for i in range(10):
@@ -494,34 +522,37 @@ class TestCertificateFlowIntegration:
494
522
  validity_years=1,
495
523
  key_size=2048,
496
524
  ca_cert_path=root_ca_pair.certificate_path,
497
- ca_key_path=root_ca_pair.private_key_path
525
+ ca_key_path=root_ca_pair.private_key_path,
498
526
  )
499
-
527
+
500
528
  self.cert_manager.create_client_certificate(client_cert_config)
501
-
529
+
502
530
  cert_creation_time = time.time() - start_time
503
531
  avg_cert_time = cert_creation_time / 10
504
-
505
- assert avg_cert_time < 1.0, f"Certificate creation too slow: {avg_cert_time:.2f}s per cert"
506
-
532
+
533
+ assert (
534
+ avg_cert_time < 1.0
535
+ ), f"Certificate creation too slow: {avg_cert_time:.2f}s per cert"
536
+
507
537
  # 3. Benchmark certificate validation
508
538
  cert_paths = []
509
539
  for i in range(10):
510
540
  cert_path = os.path.join(self.cert_dir, f"test-client-{i}.pem")
511
541
  if os.path.exists(cert_path):
512
542
  cert_paths.append(cert_path)
513
-
543
+
514
544
  start_time = time.time()
515
545
  for cert_path in cert_paths:
516
546
  self.cert_manager.validate_certificate_chain(
517
- cert_path,
518
- [root_ca_pair.certificate_path]
547
+ cert_path, [root_ca_pair.certificate_path]
519
548
  )
520
-
549
+
521
550
  validation_time = time.time() - start_time
522
551
  if cert_paths:
523
552
  avg_validation_time = validation_time / len(cert_paths)
524
553
  else:
525
554
  avg_validation_time = 0.0
526
-
527
- assert avg_validation_time < 0.1, f"Certificate validation too slow: {avg_validation_time:.3f}s per cert"
555
+
556
+ assert (
557
+ avg_validation_time < 0.1
558
+ ), f"Certificate validation too slow: {avg_validation_time:.3f}s per cert"