-
Notifications
You must be signed in to change notification settings - Fork 14
Use pytricia for ip matching on non-windows machines #547
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
Merged
Merged
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
5724432
is_private_ip: Use IPMatcher
bitterpanda63 6702883
use singleton structure
bitterpanda63 3901f87
add benchmarking script
bitterpanda63 1176b48
Install pytricia
bitterpanda63 a8e2713
Switch ip matcher up: use pytricia
bitterpanda63 9022d86
remove useless code in favor of pytricia
bitterpanda63 e74e49a
pytricia add support for ipv6
bitterpanda63 1070aa0
linting
bitterpanda63 e2b38c9
re-lock sample apps
bitterpanda63 c94a60c
Allow for a "freeze()" command to be run
bitterpanda63 42d84c2
update benchmark to freeze
bitterpanda63 5290817
update is_private_ip to test frozen
bitterpanda63 6f7ed36
freeze should return IPMatcher
bitterpanda63 52f9261
imds: Use constructor instead
bitterpanda63 857c89c
bypassed_ips: use constructor instead
bitterpanda63 7ff8990
is_private_ip use constructor
bitterpanda63 750fcb1
IPMatcher always freeze on init
bitterpanda63 92658ca
ip matcher benhcmakr update: is always frozen on init
bitterpanda63 a5b4216
remove .freeze() incompat
bitterpanda63 3469410
finally remove the freeze command from IPMatcher
bitterpanda63 d7f0c98
Add a preparse function to IPMatcher
bitterpanda63 0b7a825
Fix thread_cache_test cases because add is now not working anymore
bitterpanda63 ccdcd46
check ipv4 mapped ipv6
bitterpanda63 5944920
Fix one test case in ip_matcher
bitterpanda63 0474f04
change py version
bitterpanda63 18535ab
Revert "change py version"
bitterpanda63 dc9988f
add ip_matcher_fallback back in
bitterpanda63 c17f6ec
install pytricia only if the platform is not windows, if the platform…
bitterpanda63 245723c
re-lock
bitterpanda63 3fcd7b4
Update comment explaining why we have the fallback
bitterpanda63 a258f30
also put app start in the re-try github action
bitterpanda63 8d117fb
add the removed test cases back in
bitterpanda63 b2380ec
Don't run poetry install quietly
bitterpanda63 8be88b0
install: ignore failures
bitterpanda63 c524a59
Revert "also put app start in the re-try github action"
bitterpanda63 d3ec3b6
Update aikido_zen/helpers/ip_matcher/__init__.py
bitterpanda63 7ae85e9
add comment explaining SystemError
bitterpanda63 178be55
update fallback comment to be clearer
bitterpanda63 4910099
Test an edge case
bitterpanda63 21b30a7
test edge case again
bitterpanda63 a52255f
Update aikido_zen/helpers/net/is_private_ip.py
bitterpanda63 7a4e26d
Update aikido_zen/helpers/net/is_private_ip.py
bitterpanda63 2f83c3e
Apply suggestions from code review
bitterpanda63 42bed16
re-lock newer sample app django-asgi-uvicorn
bitterpanda63 1dd6792
Fix linting errors: remove unused imports
bitterpanda63 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 hidden or 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 hidden or 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 |
|---|---|---|
| @@ -1,49 +1,64 @@ | ||
| """ | ||
| Based on https://github.com/demskie/netparser | ||
| MIT License - Copyright (c) 2019 alex | ||
| """ | ||
|
|
||
| from .shared import parse_base_network, sort_networks, summarize_sorted_networks | ||
| from .sort import binary_search_for_insertion_index | ||
|
|
||
|
|
||
| class IPMatcher: | ||
| def __init__(self, networks=None): | ||
| self.sorted = [] | ||
| if networks is not None: | ||
| subnets = [] | ||
| for s in networks: | ||
| net = parse_base_network(s, False) | ||
| if net and net.is_valid(): | ||
| subnets.append(net) | ||
| sort_networks(subnets) | ||
| self.sorted = summarize_sorted_networks(subnets) | ||
|
|
||
| def has(self, network): | ||
| """ | ||
| Checks if the given IP address is in the list of networks. | ||
| """ | ||
| net = parse_base_network(network, False) | ||
| if not net or not net.is_valid(): | ||
| return False | ||
| idx = binary_search_for_insertion_index(net, self.sorted) | ||
| if idx < 0: | ||
| return False | ||
| if idx < len(self.sorted) and self.sorted[idx].contains(net): | ||
| return True | ||
| if idx - 1 >= 0 and self.sorted[idx - 1].contains(net): | ||
| return True | ||
| return False | ||
|
|
||
| def add(self, network): | ||
| net = parse_base_network(network, False) | ||
| if not net or not net.is_valid(): | ||
| return self | ||
| idx = binary_search_for_insertion_index(net, self.sorted) | ||
| if idx < len(self.sorted) and self.sorted[idx].compare(net) == 0: | ||
| import ipaddress | ||
|
|
||
| try: | ||
| import pytricia | ||
|
|
||
| PYTRICIA_AVAILABLE = True | ||
| except ImportError: | ||
| PYTRICIA_AVAILABLE = False | ||
| from aikido_zen.helpers.logging import logger | ||
|
|
||
| logger.warning( | ||
| "pytricia is not available. This happens on windows devices where pytricia is not supported yet." | ||
| "Using fallback, this may result in slower performance." | ||
| "You can try to install pytricia for better performance: pip install pytricia" | ||
| ) | ||
|
|
||
|
|
||
| def preparse(network: str) -> str: | ||
| # Remove the brackets around IPv6 addresses if they are there. | ||
| network = network.strip("[]") | ||
| try: | ||
| ip = ipaddress.IPv6Address(network) | ||
| if ip.ipv4_mapped: | ||
| return str(ip.ipv4_mapped) | ||
| except ValueError: | ||
| pass | ||
| return network | ||
|
|
||
|
|
||
| if PYTRICIA_AVAILABLE: | ||
|
|
||
| class IPMatcher: | ||
| def __init__(self, networks=None): | ||
| self.trie = pytricia.PyTricia(128) | ||
| if networks is not None: | ||
| for s in networks: | ||
| self._add(s) | ||
| # We freeze in constructor ensuring that after initialization the IPMatcher is always frozen. | ||
| self.trie.freeze() | ||
|
|
||
| def has(self, network): | ||
| try: | ||
| return self.trie.get(preparse(network)) is not None | ||
| except ValueError: | ||
| return False | ||
|
|
||
| def _add(self, network): | ||
| try: | ||
| self.trie[preparse(network)] = True | ||
| except ValueError: | ||
| pass | ||
| except SystemError: | ||
bitterpanda63 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| # SystemError's have been known to occur in the PyTricia library (see issue #34 e.g.), | ||
| # best to play it safe and catch these errors. | ||
| pass | ||
| return self | ||
| self.sorted.insert(idx, net) | ||
| return self | ||
|
|
||
| def is_empty(self): | ||
| return len(self.sorted) == 0 | ||
| def is_empty(self): | ||
| return len(self.trie) == 0 | ||
|
|
||
| else: | ||
| # Fallback to pure Python implementation - this happens on windows machines since pytricia is not | ||
| # fully supported there. | ||
| from aikido_zen.helpers.ip_matcher_fallback import IPMatcher # noqa: F401 | ||
This file contains hidden or 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 hidden or 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,49 @@ | ||
| """ | ||
| Based on https://github.com/demskie/netparser | ||
| MIT License - Copyright (c) 2019 alex | ||
| """ | ||
|
|
||
| from .shared import parse_base_network, sort_networks, summarize_sorted_networks | ||
| from .sort import binary_search_for_insertion_index | ||
|
|
||
|
|
||
| class IPMatcher: | ||
| def __init__(self, networks=None): | ||
| self.sorted = [] | ||
| if networks is not None: | ||
| subnets = [] | ||
| for s in networks: | ||
| net = parse_base_network(s, False) | ||
| if net and net.is_valid(): | ||
| subnets.append(net) | ||
| sort_networks(subnets) | ||
| self.sorted = summarize_sorted_networks(subnets) | ||
|
|
||
| def has(self, network): | ||
| """ | ||
| Checks if the given IP address is in the list of networks. | ||
| """ | ||
| net = parse_base_network(network, False) | ||
| if not net or not net.is_valid(): | ||
| return False | ||
| idx = binary_search_for_insertion_index(net, self.sorted) | ||
| if idx < 0: | ||
| return False | ||
| if idx < len(self.sorted) and self.sorted[idx].contains(net): | ||
| return True | ||
| if idx - 1 >= 0 and self.sorted[idx - 1].contains(net): | ||
| return True | ||
| return False | ||
|
|
||
| def add(self, network): | ||
| net = parse_base_network(network, False) | ||
| if not net or not net.is_valid(): | ||
| return self | ||
| idx = binary_search_for_insertion_index(net, self.sorted) | ||
| if idx < len(self.sorted) and self.sorted[idx].compare(net) == 0: | ||
| return self | ||
| self.sorted.insert(idx, net) | ||
| return self | ||
|
|
||
| def is_empty(self): | ||
| return len(self.sorted) == 0 |
This file contains hidden or 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
File renamed without changes.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.