mcp-security-framework 2.2.0__tar.gz → 2.2.1__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 (57) hide show
  1. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/PKG-INFO +1 -1
  2. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/__init__.py +1 -1
  3. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/ssl_manager.py +24 -0
  4. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/protected_keys_example.py +29 -12
  5. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/schemas/config.py +23 -6
  6. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/PKG-INFO +1 -1
  7. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/pyproject.toml +1 -1
  8. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/LICENSE +0 -0
  9. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/README.md +0 -0
  10. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/cli/__init__.py +0 -0
  11. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/cli/cert_cli.py +0 -0
  12. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/cli/security_cli.py +0 -0
  13. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/constants.py +0 -0
  14. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/__init__.py +0 -0
  15. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/adapter_wrapper.py +0 -0
  16. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/audit_logger.py +0 -0
  17. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/auth_manager.py +0 -0
  18. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/cert_manager.py +0 -0
  19. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/permission_manager.py +0 -0
  20. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/rate_limiter.py +0 -0
  21. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/security_adapter.py +0 -0
  22. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/core/security_manager.py +0 -0
  23. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/__init__.py +0 -0
  24. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/adapter_example.py +0 -0
  25. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/cert_inspection_example.py +0 -0
  26. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/comprehensive_example.py +0 -0
  27. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/crl_retrieval_example.py +0 -0
  28. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/fastapi_example.py +0 -0
  29. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/flask_example.py +0 -0
  30. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/gateway_example.py +0 -0
  31. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/microservice_example.py +0 -0
  32. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/examples/standalone_example.py +0 -0
  33. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/__init__.py +0 -0
  34. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/auth_middleware.py +0 -0
  35. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/fastapi_auth_middleware.py +0 -0
  36. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/fastapi_middleware.py +0 -0
  37. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/flask_auth_middleware.py +0 -0
  38. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/flask_middleware.py +0 -0
  39. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/mtls_middleware.py +0 -0
  40. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/rate_limit_middleware.py +0 -0
  41. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/middleware/security_middleware.py +0 -0
  42. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/schemas/__init__.py +0 -0
  43. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/schemas/models.py +0 -0
  44. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/schemas/operation_context.py +0 -0
  45. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/schemas/responses.py +0 -0
  46. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/__init__.py +0 -0
  47. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/cert_utils.py +0 -0
  48. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/crl_client.py +0 -0
  49. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/crypto_utils.py +0 -0
  50. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/datetime_compat.py +0 -0
  51. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework/utils/validation_utils.py +0 -0
  52. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/SOURCES.txt +0 -0
  53. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/dependency_links.txt +0 -0
  54. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/entry_points.txt +0 -0
  55. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/requires.txt +0 -0
  56. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/mcp_security_framework.egg-info/top_level.txt +0 -0
  57. {mcp_security_framework-2.2.0 → mcp_security_framework-2.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-security-framework
3
- Version: 2.2.0
3
+ Version: 2.2.1
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.2.0"
82
+ __version__ = "2.2.1"
83
83
  __author__ = "Vasiliy Zdanovskiy"
84
84
  __email__ = "vasilyvz@gmail.com"
85
85
  __license__ = "MIT"
@@ -235,10 +235,22 @@ class SSLManager:
235
235
 
236
236
  # Validate required files or data
237
237
  if cert_data is None and not cert_file:
238
+ if self.config.material_from_memory:
239
+ raise SSLConfigurationError(
240
+ "material_from_memory=True but cert_data was not supplied; "
241
+ "provide cert_data as PEM bytes or "
242
+ "set material_from_memory=False"
243
+ )
238
244
  raise SSLConfigurationError(
239
245
  "Server certificate file or data is required"
240
246
  )
241
247
  if key_data is None and not key_file:
248
+ if self.config.material_from_memory:
249
+ raise SSLConfigurationError(
250
+ "material_from_memory=True but key_data was not supplied; "
251
+ "provide key_data as PEM bytes or "
252
+ "set material_from_memory=False"
253
+ )
242
254
  raise SSLConfigurationError(
243
255
  "Server private key file or data is required"
244
256
  )
@@ -423,6 +435,18 @@ class SSLManager:
423
435
  verify_mode = verify_mode or self.config.verify_mode
424
436
  min_version = min_version or self.config.min_tls_version
425
437
 
438
+ # Validate that material_from_memory promises are kept
439
+ if cert_data is None and self.config.material_from_memory:
440
+ raise SSLConfigurationError(
441
+ "material_from_memory=True but cert_data was not supplied; "
442
+ "provide cert_data as PEM bytes or set material_from_memory=False"
443
+ )
444
+ if key_data is None and self.config.material_from_memory:
445
+ raise SSLConfigurationError(
446
+ "material_from_memory=True but key_data was not supplied; "
447
+ "provide key_data as PEM bytes or set material_from_memory=False"
448
+ )
449
+
426
450
  # Check cache (only for file-based contexts)
427
451
  cache_key = None
428
452
  if cert_data is None and key_data is None:
@@ -57,7 +57,7 @@ def _build_certificate_config() -> CertificateConfig:
57
57
 
58
58
  def _build_ssl_config() -> SSLConfig:
59
59
  """Build a temporary SSL configuration for this example."""
60
- return SSLConfig(enabled=True, verify=False)
60
+ return SSLConfig(enabled=True, verify=False, material_from_memory=False)
61
61
 
62
62
 
63
63
  def _create_encrypted_key(password: str) -> tuple:
@@ -88,7 +88,6 @@ def main() -> None:
88
88
  print("=" * 70)
89
89
 
90
90
  cert_config = _build_certificate_config()
91
- ssl_config = _build_ssl_config()
92
91
 
93
92
  # Capability 1: Create a root CA with a passphrase-protected key
94
93
  print("\n1. Creating a root CA with a passphrase-protected private key...")
@@ -182,18 +181,24 @@ def main() -> None:
182
181
  else:
183
182
  raise
184
183
 
185
- # Capability 5: Create SSL context from in-memory cert and key bytes
184
+ # Capability 5: Create SSL context from in-memory bytes (SECURE config)
186
185
  print("\n5. Creating SSL context from in-memory certificate and key bytes...")
187
186
  with open(server_pair.certificate_path, "rb") as f:
188
187
  cert_bytes = f.read()
189
188
  with open(server_pair.private_key_path, "rb") as f:
190
189
  key_bytes = f.read()
191
190
 
192
- ssl_manager = SSLManager(ssl_config)
191
+ secure_ssl_config = SSLConfig(enabled=True, verify=True, material_from_memory=True)
192
+ print(
193
+ f" Config: enabled={secure_ssl_config.enabled}, "
194
+ f"verify={secure_ssl_config.verify}, "
195
+ f"material_from_memory={secure_ssl_config.material_from_memory}"
196
+ )
197
+ ssl_manager = SSLManager(secure_ssl_config)
193
198
  _ = ssl_manager.create_server_context(cert_data=cert_bytes, key_data=key_bytes)
194
- print(" SSL context created from in-memory bytes: SUCCESS")
199
+ print(" SSL context created from in-memory bytes (SECURE): SUCCESS")
195
200
 
196
- # Capability 6: Create SSL context from encrypted in-memory key with password
201
+ # Capability 6: Create SSL context from encrypted in-memory key (SECURE)
197
202
  print("\n6. Creating SSL context from encrypted in-memory key with passphrase...")
198
203
  # Read the original server key and encrypt it
199
204
  with open(server_pair.private_key_path, "rb") as f:
@@ -212,13 +217,21 @@ def main() -> None:
212
217
  )
213
218
 
214
219
  ssl_config_with_password = SSLConfig(
215
- enabled=True, verify=False, key_password="test_pass"
220
+ enabled=True,
221
+ verify=True,
222
+ material_from_memory=True,
223
+ key_password="test_pass",
224
+ )
225
+ print(
226
+ f" Config: enabled={ssl_config_with_password.enabled}, "
227
+ f"verify={ssl_config_with_password.verify}, "
228
+ f"material_from_memory={ssl_config_with_password.material_from_memory}"
216
229
  )
217
230
  ssl_manager_with_pass = SSLManager(ssl_config_with_password)
218
231
  _ = ssl_manager_with_pass.create_server_context(
219
232
  cert_data=cert_bytes, key_data=encrypted_server_key
220
233
  )
221
- print(" SSL context created from encrypted in-memory key: SUCCESS")
234
+ print(" SSL context created from encrypted in-memory key (SECURE): SUCCESS")
222
235
 
223
236
  # Capability 7: Try cert_data without key_data (should fail)
224
237
  print("\n7. Attempting to supply cert_data without key_data (should fail)...")
@@ -231,7 +244,7 @@ def main() -> None:
231
244
  else:
232
245
  raise
233
246
 
234
- # Capability 8: Create a CA workflow entirely from PEM bytes (no disk files)
247
+ # Capability 8: Create CA workflow from PEM bytes (no disk files) SECURE config
235
248
  print("\n8. Running complete CA workflow from PEM bytes (no disk CA files)...")
236
249
 
237
250
  # Create a root CA for this demonstration
@@ -283,9 +296,13 @@ def main() -> None:
283
296
  encryption_algorithm=serialization.NoEncryption(),
284
297
  )
285
298
 
286
- # Now use those bytes through the SSL context
287
- _ = ssl_manager.create_server_context(cert_data=ca_cert_pem, key_data=ca_key_pem)
288
- print(" CA workflow completed entirely in memory: SUCCESS")
299
+ # Now use those bytes through the SSL context with secure config
300
+ secure_ca_config = SSLConfig(enabled=True, verify=True, material_from_memory=True)
301
+ secure_ca_manager = SSLManager(secure_ca_config)
302
+ _ = secure_ca_manager.create_server_context(
303
+ cert_data=ca_cert_pem, key_data=ca_key_pem
304
+ )
305
+ print(" CA workflow completed entirely in memory (SECURE): SUCCESS")
289
306
 
290
307
  msg = "ALL PROTECTED KEY AND IN-MEMORY MATERIAL CAPABILITIES "
291
308
  msg += "DEMONSTRATED SUCCESSFULLY"
@@ -93,6 +93,7 @@ class SSLConfig(BaseModel):
93
93
  client_cert_file: Path to client certificate file
94
94
  client_key_file: Path to client private key file
95
95
  client_key_password: Passphrase for client private key file
96
+ material_from_memory: Certificate and key supplied as PEM bytes, not files
96
97
  verify_mode: SSL verification mode
97
98
  min_tls_version: Minimum TLS version to support
98
99
  max_tls_version: Maximum TLS version to support
@@ -132,6 +133,13 @@ class SSLConfig(BaseModel):
132
133
  default=None, description="Passphrase for client private key file"
133
134
  )
134
135
  verify: bool = Field(default=True, description="Whether to verify SSL certificates")
136
+ material_from_memory: bool = Field(
137
+ default=False,
138
+ description=(
139
+ "Certificate and key are supplied to the context builders as PEM "
140
+ "bytes rather than named by cert_file/key_file"
141
+ ),
142
+ )
135
143
  verify_mode: str = Field(
136
144
  default="CERT_REQUIRED", description="SSL verification mode"
137
145
  )
@@ -223,12 +231,21 @@ class SSLConfig(BaseModel):
223
231
  def validate_ssl_configuration(self) -> Self:
224
232
  """Validate SSL configuration consistency."""
225
233
  if self.enabled:
226
- # If verify is disabled, don't require certificate files
227
- if self.verify and (not self.cert_file or not self.key_file):
228
- raise ValueError(
229
- "SSL enabled with verification but certificate and key files are "
230
- "required"
231
- )
234
+ # If verify is disabled, don't require certificate files or memory flag
235
+ if self.verify and not self.material_from_memory:
236
+ # material_from_memory=False means files are required.
237
+ # material_from_memory=True means bytes will be supplied at call time,
238
+ # so files are not checked here. This keeps the early error for the
239
+ # common case — everyone who configures file paths — and makes the
240
+ # intent visible in the configuration itself, which is where an auditor
241
+ # will look. An explicit opt-in prevents the false positive that occurs
242
+ # when someone sets verify=True in secure-by-default code but hasn't yet
243
+ # assembled the bytes.
244
+ if not self.cert_file or not self.key_file:
245
+ raise ValueError(
246
+ "SSL enabled with verification but certificate and key "
247
+ "files are required"
248
+ )
232
249
  return self
233
250
 
234
251
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-security-framework
3
- Version: 2.2.0
3
+ Version: 2.2.1
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>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mcp-security-framework"
7
- version = "2.2.0"
7
+ version = "2.2.1"
8
8
  description = "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."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}