mcp-security-framework 2.3.1__tar.gz → 2.3.2__tar.gz

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 (67) hide show
  1. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/PKG-INFO +1 -1
  2. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/__init__.py +1 -1
  3. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/cert_manager.py +5 -1
  4. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/ssl_manager.py +52 -14
  5. mcp_security_framework-2.3.2/mcp_security_framework/examples/tls_certificate_regressions_example.py +1197 -0
  6. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/schemas/config.py +28 -0
  7. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/PKG-INFO +1 -1
  8. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/pyproject.toml +1 -1
  9. mcp_security_framework-2.3.1/mcp_security_framework/examples/tls_certificate_regressions_example.py +0 -142
  10. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/LICENSE +0 -0
  11. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/README.md +0 -0
  12. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/cli/__init__.py +0 -0
  13. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/cli/cert_cli.py +0 -0
  14. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/cli/security_cli.py +0 -0
  15. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/constants.py +0 -0
  16. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/__init__.py +0 -0
  17. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/adapter_wrapper.py +0 -0
  18. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/audit_logger.py +0 -0
  19. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/auth_manager.py +0 -0
  20. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/permission_manager.py +0 -0
  21. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/rate_limiter.py +0 -0
  22. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/security_adapter.py +0 -0
  23. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/core/security_manager.py +0 -0
  24. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/__init__.py +0 -0
  25. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/adapter_example.py +0 -0
  26. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/auth_methods_example.py +0 -0
  27. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/cert_inspection_example.py +0 -0
  28. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/certificate_roles_example.py +0 -0
  29. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/comprehensive_example.py +0 -0
  30. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/crl_retrieval_example.py +0 -0
  31. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/fastapi_example.py +0 -0
  32. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/flask_example.py +0 -0
  33. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/gateway_example.py +0 -0
  34. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/microservice_example.py +0 -0
  35. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/protected_keys_example.py +0 -0
  36. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/examples/standalone_example.py +0 -0
  37. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/__init__.py +0 -0
  38. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/auth_middleware.py +0 -0
  39. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/fastapi_auth_middleware.py +0 -0
  40. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/fastapi_middleware.py +0 -0
  41. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/flask_auth_middleware.py +0 -0
  42. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/flask_middleware.py +0 -0
  43. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/mtls_middleware.py +0 -0
  44. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/rate_limit_middleware.py +0 -0
  45. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/middleware/security_middleware.py +0 -0
  46. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/schemas/__init__.py +0 -0
  47. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/schemas/models.py +0 -0
  48. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/schemas/operation_context.py +0 -0
  49. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/schemas/responses.py +0 -0
  50. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/__init__.py +0 -0
  51. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/__init__.py +0 -0
  52. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/chain.py +0 -0
  53. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/errors.py +0 -0
  54. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/inspection.py +0 -0
  55. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/parsing.py +0 -0
  56. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/revocation.py +0 -0
  57. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/cert_utils/roles.py +0 -0
  58. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/crl_client.py +0 -0
  59. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/crypto_utils.py +0 -0
  60. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/datetime_compat.py +0 -0
  61. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework/utils/validation_utils.py +0 -0
  62. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/SOURCES.txt +0 -0
  63. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/dependency_links.txt +0 -0
  64. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/entry_points.txt +0 -0
  65. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/requires.txt +0 -0
  66. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/mcp_security_framework.egg-info/top_level.txt +0 -0
  67. {mcp_security_framework-2.3.1 → mcp_security_framework-2.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-security-framework
3
- Version: 2.3.1
3
+ Version: 2.3.2
4
4
  Summary: Universal security framework for microservices with SSL/TLS, authentication, authorization, and rate limiting. Added extensible security adapter system for custom operation validation, structured audit logging, and operation context support. Comprehensive test coverage with 1104+ tests. Fully backward compatible. Requires cryptography>=42.0.0 for certificate operations.
5
5
  Author-email: Vasiliy Zdanovskiy <vasilyvz@gmail.com>
6
6
  Maintainer-email: Vasiliy Zdanovskiy <vasilyvz@gmail.com>
@@ -79,7 +79,7 @@ from mcp_security_framework.schemas.responses import (
79
79
  )
80
80
 
81
81
  # Version information
82
- __version__ = "2.3.1"
82
+ __version__ = "2.3.2"
83
83
  __author__ = "Vasiliy Zdanovskiy"
84
84
  __email__ = "vasilyvz@gmail.com"
85
85
  __license__ = "MIT"
@@ -2129,8 +2129,12 @@ class CertificateManager:
2129
2129
  )
2130
2130
 
2131
2131
  # Add Subject Alternative Name extension if common name looks like a domain
2132
+ # or an IP literal. Reuse _subject_alt_name so an IP-literal common_name
2133
+ # (e.g. "127.0.0.1") is encoded as x509.IPAddress, never x509.DNSName.
2132
2134
  if "." in common_name and not common_name.startswith("*"):
2133
- san_extension = x509.SubjectAlternativeName([x509.DNSName(common_name)])
2135
+ san_extension = x509.SubjectAlternativeName(
2136
+ [_subject_alt_name(common_name)]
2137
+ )
2134
2138
  csr_builder = csr_builder.add_extension(san_extension, critical=False)
2135
2139
 
2136
2140
  # Build and sign CSR
@@ -432,9 +432,27 @@ class SSLManager:
432
432
  if key_data is None:
433
433
  client_key_file = client_key_file or self.config.client_key_file
434
434
  ca_cert_file = ca_cert_file or self.config.ca_cert_file
435
- verify_mode = verify_mode or self.config.verify_mode
436
435
  min_version = min_version or self.config.min_tls_version
437
436
 
437
+ # Validate client_cert_file/client_key_file compatibility (bug B6),
438
+ # on the EFFECTIVE values resolved just above (call-site argument or
439
+ # config fallback). Skipped when cert_data/key_data supply the pair
440
+ # instead: cert_data/key_data are already validated all-or-none
441
+ # above, and both loading branches below try cert_data/key_data
442
+ # FIRST, falling back to client_cert_file/client_key_file only when
443
+ # cert_data/key_data are absent — so a lone client_cert_file/
444
+ # client_key_file value is never actually used together with
445
+ # cert_data/key_data. Raised here, once, before the cache lookup
446
+ # and before any context is built, so it covers both the CERT_NONE
447
+ # branch and the verifying branch below and no partially
448
+ # configured context is ever cached.
449
+ if cert_data is None and key_data is None:
450
+ if bool(client_cert_file) != bool(client_key_file):
451
+ raise SSLConfigurationError(
452
+ "client_cert_file and client_key_file must be provided "
453
+ "together; got one without the other"
454
+ )
455
+
438
456
  # Validate that material_from_memory promises are kept
439
457
  if cert_data is None and self.config.material_from_memory:
440
458
  raise SSLConfigurationError(
@@ -447,17 +465,13 @@ class SSLManager:
447
465
  "provide key_data as PEM bytes or set material_from_memory=False"
448
466
  )
449
467
 
450
- # Check cache (only for file-based contexts)
451
- cache_key = None
452
- if cert_data is None and key_data is None:
453
- cache_key = (
454
- f"client_{ca_cert_file}_{client_cert_file}_{client_key_file}"
455
- f"_{verify_mode}_{min_version}"
456
- )
457
- if cache_key in self._contexts:
458
- return self._contexts[cache_key]
459
-
460
- # Determine actual verify mode (explicit parameter takes precedence)
468
+ # Determine actual verify mode. Precedence (bug B5):
469
+ # 1) an explicit call-site verify_mode argument
470
+ # 2) self.config.verify is False -> CERT_NONE
471
+ # 3) self.config.verify_mode
472
+ # NOTE: verify_mode must NOT be defaulted from self.config.verify_mode
473
+ # before this check runs, otherwise it is never falsy here and
474
+ # self.config.verify is never consulted (bug B5's root cause).
461
475
  actual_verify_mode = (
462
476
  verify_mode
463
477
  if verify_mode
@@ -466,6 +480,30 @@ class SSLManager:
466
480
  )
467
481
  )
468
482
 
483
+ # Effective check_hostname actually applied to the context: always
484
+ # False when verification is disabled (ssl refuses check_hostname=True
485
+ # with CERT_NONE), otherwise the configured value (bug B1).
486
+ effective_check_hostname = (
487
+ False
488
+ if actual_verify_mode == "CERT_NONE"
489
+ else bool(self.config.check_hostname)
490
+ )
491
+
492
+ # Check cache (only for file-based contexts). The key must reflect
493
+ # the RESOLVED verify mode and the check_hostname actually applied
494
+ # to the context (bugs B1, B5c) so that mutating
495
+ # manager.config.check_hostname or manager.config.verify between
496
+ # two calls on the same instance, with the raw inputs otherwise
497
+ # unchanged, never returns a context built for different values.
498
+ cache_key = None
499
+ if cert_data is None and key_data is None:
500
+ cache_key = (
501
+ f"client_{ca_cert_file}_{client_cert_file}_{client_key_file}"
502
+ f"_{actual_verify_mode}_{effective_check_hostname}_{min_version}"
503
+ )
504
+ if cache_key in self._contexts:
505
+ return self._contexts[cache_key]
506
+
469
507
  # Check if verification is disabled
470
508
  if actual_verify_mode == "CERT_NONE":
471
509
  # For disabled verification or CERT_NONE, create a basic context
@@ -518,7 +556,7 @@ class SSLManager:
518
556
  else:
519
557
  # For other modes, use default context with verification
520
558
  context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
521
- context.check_hostname = bool(self.config.check_hostname)
559
+ context.check_hostname = effective_check_hostname
522
560
  context.verify_mode = self._get_verify_mode(actual_verify_mode)
523
561
 
524
562
  # Set minimum TLS version
@@ -583,7 +621,7 @@ class SSLManager:
583
621
  "ca_cert_file": ca_cert_file,
584
622
  "client_cert_file": client_cert_file,
585
623
  "cert_data_provided": cert_data is not None,
586
- "verify_mode": verify_mode,
624
+ "verify_mode": actual_verify_mode,
587
625
  "min_version": min_version,
588
626
  },
589
627
  )