-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filtering request using OpenAPI spec #645
Open
fcollonval
wants to merge
8
commits into
jupyter-server:main
Choose a base branch
from
fcollonval:ft/filter-request
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
9bd423c
PoC filtering using OpenAPI spec
fcollonval ed715ce
Apply review comments and add slash encoder
fcollonval 6b739c9
Add application unit tests
fcollonval 0104946
Lint code
fcollonval 0e031b8
Condition optional dep on Python version
fcollonval f1ecfd2
Make specvalidator optional
fcollonval 6fc0130
Add documentation
fcollonval ccac364
Merge branch 'main' into ft/filter-request
fcollonval File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from typing import Optional, Union | ||
|
||
from openapi_core import create_spec | ||
from tornado import httpclient, httputil | ||
from tornado.log import access_log | ||
from tornado_openapi3 import RequestValidator | ||
|
||
|
||
class FireWall: | ||
fcollonval marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Validate server request against a list of allowed and blocked OpenAPI v3 specifications. | ||
|
||
If allowed and blocked specifications are defined, the request must be allowed and not blocked; | ||
i.e. blocked specification takes precedence. | ||
|
||
Args: | ||
allowed_spec: [optional] Allowed endpoints | ||
blocked_spec: [optional] Blocked endpoints | ||
""" | ||
|
||
def __init__(self, base_url: str, allowed_spec: Optional[dict], blocked_spec: Optional[dict]): | ||
self.__allowed_validator: Optional[RequestValidator] = None | ||
self.__blocked_validator: Optional[RequestValidator] = None | ||
|
||
def add_base_url_server(spec: dict): | ||
servers = spec.get("servers", []) | ||
if not any(map(lambda s: s.get("url") == base_url, servers)): | ||
servers.append({ | ||
"url": base_url | ||
}) | ||
spec["servers"] = servers | ||
|
||
if allowed_spec is not None: | ||
add_base_url_server(allowed_spec) | ||
self.__allowed_validator = RequestValidator(create_spec(allowed_spec)) | ||
if blocked_spec is not None: | ||
add_base_url_server(blocked_spec) | ||
self.__blocked_validator = RequestValidator(create_spec(blocked_spec)) | ||
|
||
def validate( | ||
self, request: Union[httpclient.HTTPRequest, httputil.HTTPServerRequest] | ||
) -> bool: | ||
"""Validate a request against allowed and blocked specifications. | ||
|
||
Args: | ||
request: Request to validate | ||
Returns: | ||
Whether the request is valid or not. | ||
""" | ||
allowed_result = ( | ||
None | ||
if self.__allowed_validator is None | ||
else self.__allowed_validator.validate(request) | ||
) | ||
|
||
blocked_result = ( | ||
None | ||
if self.__blocked_validator is None | ||
else self.__blocked_validator.validate(request) | ||
) | ||
|
||
allowed = (allowed_result is None or len(allowed_result.errors) == 0) | ||
not_blocked = ( | ||
blocked_result is None or len(blocked_result.errors) > 0 | ||
) | ||
|
||
# The error raised if this is not valid will be logged | ||
# So we only give the reason in debug level | ||
if (not (allowed and not_blocked)): | ||
if(not allowed): | ||
# Provides only the first error | ||
access_log.debug(f"Request not allowed: {allowed_result.errors[0]!s}") | ||
elif (not not_blocked): | ||
access_log.debug(f"Request blocked.") | ||
|
||
return allowed and not_blocked |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could just be
if self.template_paths
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I won't change it as it is not modified by this PR.