mcp-security-framework 2.0.0__tar.gz → 2.0.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.
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/PKG-INFO +1 -1
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/__init__.py +1 -1
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/security_manager.py +8 -2
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/adapter_example.py +6 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/fastapi_example.py +9 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/gateway_example.py +4 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/microservice_example.py +4 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/__init__.py +123 -5
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/fastapi_middleware.py +7 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/PKG-INFO +1 -1
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/pyproject.toml +1 -1
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/LICENSE +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/README.md +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/cli/__init__.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/cli/cert_cli.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/cli/security_cli.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/constants.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/__init__.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/adapter_wrapper.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/audit_logger.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/auth_manager.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/cert_manager.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/permission_manager.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/rate_limiter.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/security_adapter.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/core/ssl_manager.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/__init__.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/comprehensive_example.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/flask_example.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/examples/standalone_example.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/auth_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/fastapi_auth_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/flask_auth_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/flask_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/mtls_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/rate_limit_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/middleware/security_middleware.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/schemas/__init__.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/schemas/config.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/schemas/models.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/schemas/operation_context.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/schemas/responses.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/utils/__init__.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/utils/cert_utils.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/utils/crypto_utils.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/utils/datetime_compat.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/utils/validation_utils.py +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/SOURCES.txt +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/dependency_links.txt +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/entry_points.txt +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/requires.txt +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework.egg-info/top_level.txt +0 -0
- {mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-security-framework
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.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>
|
|
@@ -738,7 +738,10 @@ class SecurityManager:
|
|
|
738
738
|
return FastAPISecurityMiddleware(self)
|
|
739
739
|
except ImportError as e:
|
|
740
740
|
raise SecurityConfigurationError(
|
|
741
|
-
|
|
741
|
+
"FastAPI middleware requires the 'fastapi' extra, which is not "
|
|
742
|
+
"installed. Install it with: "
|
|
743
|
+
f"pip install 'mcp-security-framework[fastapi]' ({e})",
|
|
744
|
+
error_code=-32007,
|
|
742
745
|
)
|
|
743
746
|
except Exception as e:
|
|
744
747
|
raise SecurityConfigurationError(
|
|
@@ -783,7 +786,10 @@ class SecurityManager:
|
|
|
783
786
|
return FlaskSecurityMiddleware(self, wsgi_app)
|
|
784
787
|
except ImportError as e:
|
|
785
788
|
raise SecurityConfigurationError(
|
|
786
|
-
|
|
789
|
+
"Flask middleware requires the 'flask' extra, which is not "
|
|
790
|
+
"installed. Install it with: "
|
|
791
|
+
f"pip install 'mcp-security-framework[flask]' ({e})",
|
|
792
|
+
error_code=-32009,
|
|
787
793
|
)
|
|
788
794
|
except Exception as e:
|
|
789
795
|
raise SecurityConfigurationError(
|
|
@@ -222,6 +222,15 @@ class FastAPISecurityExample:
|
|
|
222
222
|
|
|
223
223
|
@staticmethod
|
|
224
224
|
def _user_info(identity: AuthResult) -> Dict[str, Any]:
|
|
225
|
+
"""Return a dict of the caller's username and roles for an API response.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
identity: The authentication result containing user information.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
A dict with keys "username" and "roles" for inclusion in
|
|
232
|
+
response bodies.
|
|
233
|
+
"""
|
|
225
234
|
return {"username": identity.username, "roles": identity.roles}
|
|
226
235
|
|
|
227
236
|
# -- routes -------------------------------------------------------------
|
|
@@ -145,6 +145,10 @@ def build_app(security_manager: SecurityManager) -> FastAPI:
|
|
|
145
145
|
|
|
146
146
|
@app.middleware("http")
|
|
147
147
|
async def _security(request: Request, call_next):
|
|
148
|
+
"""
|
|
149
|
+
HTTP middleware hook delegating to the framework's security
|
|
150
|
+
middleware for authentication, rate limiting, and header injection.
|
|
151
|
+
"""
|
|
148
152
|
return await security_middleware(request, call_next)
|
|
149
153
|
|
|
150
154
|
return app
|
|
@@ -165,6 +165,10 @@ def build_service_app(service_name: str, security_manager: SecurityManager) -> F
|
|
|
165
165
|
|
|
166
166
|
@app.middleware("http")
|
|
167
167
|
async def _security(request: Request, call_next):
|
|
168
|
+
"""
|
|
169
|
+
HTTP middleware hook delegating to the framework's security
|
|
170
|
+
middleware for authentication, rate limiting, and header injection.
|
|
171
|
+
"""
|
|
168
172
|
return await security_middleware(request, call_next)
|
|
169
173
|
|
|
170
174
|
return app
|
|
@@ -37,19 +37,137 @@ Not exported, and why:
|
|
|
37
37
|
``SecurityMiddleware`` and available directly through
|
|
38
38
|
``core.rate_limiter.RateLimiter``.
|
|
39
39
|
|
|
40
|
+
Lazy framework binding, and why:
|
|
41
|
+
``fastapi_middleware`` and ``flask_middleware`` import their web
|
|
42
|
+
framework unconditionally at module level, and ``pyproject.toml`` makes
|
|
43
|
+
both frameworks OPTIONAL extras (``mcp-security-framework[fastapi]``,
|
|
44
|
+
``mcp-security-framework[flask]``) precisely so a consumer need not
|
|
45
|
+
install the one they do not use. Importing either name eagerly here,
|
|
46
|
+
in this package's own ``__init__``, would defeat that: merely doing
|
|
47
|
+
``import mcp_security_framework.middleware`` -- which happens before
|
|
48
|
+
any submodule of this package can be reached at all -- would require
|
|
49
|
+
BOTH frameworks to be installed, even for a consumer who asked for
|
|
50
|
+
neither or for only one. That was exactly the shape of the 2.0.0
|
|
51
|
+
defect this module now avoids: installing ``[flask]`` alone still
|
|
52
|
+
raised ``ModuleNotFoundError: No module named 'fastapi'`` on the very
|
|
53
|
+
first import, three frames below anything the consumer wrote.
|
|
54
|
+
|
|
55
|
+
The fix is a module-level ``__getattr__`` (PEP 562): the names below
|
|
56
|
+
are resolved from their owning submodule only when actually looked up
|
|
57
|
+
(``middleware.FlaskSecurityMiddleware``, or the factory functions,
|
|
58
|
+
which resolve the same way), so the cost of a missing framework is
|
|
59
|
+
paid only by a consumer who asks for that framework, and paid as a
|
|
60
|
+
clear ``ImportError`` naming the extra to install -- never as a bare,
|
|
61
|
+
unattributed ``ModuleNotFoundError`` surfacing from package import.
|
|
62
|
+
``__all__`` is unchanged: it still names everything this package
|
|
63
|
+
offers, whether or not the backing framework is installed right now.
|
|
64
|
+
|
|
40
65
|
Author: MCP Security Team
|
|
41
66
|
Version: 1.0.0
|
|
42
67
|
License: MIT
|
|
43
68
|
"""
|
|
44
69
|
|
|
45
|
-
from
|
|
70
|
+
from __future__ import annotations
|
|
71
|
+
|
|
72
|
+
from typing import TYPE_CHECKING, Callable, Optional
|
|
46
73
|
|
|
47
74
|
from ..core.security_manager import SecurityManager
|
|
48
75
|
from .auth_middleware import AuthMiddleware, AuthMiddlewareError
|
|
49
|
-
from .fastapi_middleware import FastAPIMiddlewareError, FastAPISecurityMiddleware
|
|
50
|
-
from .flask_middleware import FlaskMiddlewareError, FlaskSecurityMiddleware
|
|
51
76
|
from .security_middleware import SecurityMiddleware, SecurityMiddlewareError
|
|
52
77
|
|
|
78
|
+
if TYPE_CHECKING:
|
|
79
|
+
# Only for static type checkers/linters resolving the annotations below.
|
|
80
|
+
# Never executed at runtime, so it carries none of the eager-import
|
|
81
|
+
# defect this module fixes -- a type checker already has both
|
|
82
|
+
# frameworks' stubs or is told to ignore missing ones, but a real
|
|
83
|
+
# consumer at import time never reaches this branch.
|
|
84
|
+
from .fastapi_middleware import FastAPISecurityMiddleware
|
|
85
|
+
from .flask_middleware import FlaskSecurityMiddleware
|
|
86
|
+
|
|
87
|
+
# Names resolved lazily by ``__getattr__`` below, and the submodule each is
|
|
88
|
+
# imported from on first access. Kept out of the module namespace until
|
|
89
|
+
# then so that importing this package -- or the OTHER framework's names
|
|
90
|
+
# from it -- never requires a framework the consumer did not ask for.
|
|
91
|
+
_LAZY_ATTRS = {
|
|
92
|
+
"FastAPISecurityMiddleware": (
|
|
93
|
+
".fastapi_middleware",
|
|
94
|
+
"FastAPISecurityMiddleware",
|
|
95
|
+
"fastapi",
|
|
96
|
+
),
|
|
97
|
+
"FastAPIMiddlewareError": (
|
|
98
|
+
".fastapi_middleware",
|
|
99
|
+
"FastAPIMiddlewareError",
|
|
100
|
+
"fastapi",
|
|
101
|
+
),
|
|
102
|
+
"FlaskSecurityMiddleware": (
|
|
103
|
+
".flask_middleware",
|
|
104
|
+
"FlaskSecurityMiddleware",
|
|
105
|
+
"flask",
|
|
106
|
+
),
|
|
107
|
+
"FlaskMiddlewareError": (
|
|
108
|
+
".flask_middleware",
|
|
109
|
+
"FlaskMiddlewareError",
|
|
110
|
+
"flask",
|
|
111
|
+
),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _import_lazy_attr(name: str):
|
|
116
|
+
"""
|
|
117
|
+
Import and return one of ``_LAZY_ATTRS`` on first access.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
name (str): Attribute name being resolved, e.g.
|
|
121
|
+
``"FlaskSecurityMiddleware"``.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
The requested class or exception type, imported from its owning
|
|
125
|
+
submodule.
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
ImportError: If the submodule cannot be imported because the web
|
|
129
|
+
framework it wraps is not installed. The message names the
|
|
130
|
+
extra to install rather than letting the framework's own
|
|
131
|
+
``ModuleNotFoundError`` propagate unattributed.
|
|
132
|
+
"""
|
|
133
|
+
module_name, attr_name, extra = _LAZY_ATTRS[name]
|
|
134
|
+
try:
|
|
135
|
+
module = __import__(f"{__name__}{module_name}", fromlist=[attr_name])
|
|
136
|
+
except ImportError as exc:
|
|
137
|
+
raise ImportError(
|
|
138
|
+
f"{name} requires the '{extra}' extra, which is not installed. "
|
|
139
|
+
f"Install it with: pip install 'mcp-security-framework[{extra}]'"
|
|
140
|
+
) from exc
|
|
141
|
+
return getattr(module, attr_name)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def __getattr__(name: str):
|
|
145
|
+
"""
|
|
146
|
+
Module-level attribute resolution (PEP 562) for framework-specific
|
|
147
|
+
names, deferring their import until something actually asks for them.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
name (str): Attribute being looked up on this module.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
The resolved attribute.
|
|
154
|
+
|
|
155
|
+
Raises:
|
|
156
|
+
AttributeError: If ``name`` is not one this module defines.
|
|
157
|
+
ImportError: If ``name`` needs a web framework that is not
|
|
158
|
+
installed; see :func:`_import_lazy_attr`.
|
|
159
|
+
"""
|
|
160
|
+
if name in _LAZY_ATTRS:
|
|
161
|
+
value = _import_lazy_attr(name)
|
|
162
|
+
globals()[name] = value
|
|
163
|
+
return value
|
|
164
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def __dir__():
|
|
168
|
+
"""Include lazily-resolved names in ``dir()`` output."""
|
|
169
|
+
return sorted(set(globals()) | set(_LAZY_ATTRS))
|
|
170
|
+
|
|
53
171
|
|
|
54
172
|
def create_fastapi_security_middleware(
|
|
55
173
|
security_manager: SecurityManager,
|
|
@@ -77,7 +195,7 @@ def create_fastapi_security_middleware(
|
|
|
77
195
|
>>> middleware = create_fastapi_security_middleware(security_manager)
|
|
78
196
|
>>> app.add_middleware(middleware)
|
|
79
197
|
"""
|
|
80
|
-
return FastAPISecurityMiddleware(security_manager)
|
|
198
|
+
return _import_lazy_attr("FastAPISecurityMiddleware")(security_manager)
|
|
81
199
|
|
|
82
200
|
|
|
83
201
|
def create_flask_security_middleware(
|
|
@@ -115,7 +233,7 @@ def create_flask_security_middleware(
|
|
|
115
233
|
... security_manager, app.wsgi_app
|
|
116
234
|
... )
|
|
117
235
|
"""
|
|
118
|
-
return FlaskSecurityMiddleware(security_manager, wsgi_app)
|
|
236
|
+
return _import_lazy_attr("FlaskSecurityMiddleware")(security_manager, wsgi_app)
|
|
119
237
|
|
|
120
238
|
|
|
121
239
|
def create_auth_middleware(
|
|
@@ -74,6 +74,13 @@ def require_permissions(*permissions: str) -> Any:
|
|
|
74
74
|
"""
|
|
75
75
|
|
|
76
76
|
def _required_permissions_marker() -> None:
|
|
77
|
+
"""
|
|
78
|
+
Carry the declared permissions; it is never called for its result.
|
|
79
|
+
|
|
80
|
+
FastAPI resolves this as a dependency, which is what puts it on the
|
|
81
|
+
route. The middleware finds it there and reads ``__permissions__``
|
|
82
|
+
off it before the handler runs.
|
|
83
|
+
"""
|
|
77
84
|
return None
|
|
78
85
|
|
|
79
86
|
_required_permissions_marker.__permissions__ = list(permissions)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-security-framework
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.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.0.
|
|
7
|
+
version = "2.0.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"}
|
|
File without changes
|
|
File without changes
|
{mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/cli/__init__.py
RENAMED
|
File without changes
|
{mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/cli/cert_cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{mcp_security_framework-2.0.0 → mcp_security_framework-2.0.1}/mcp_security_framework/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|