Skip to content
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

Containment based queries optimized #537

Merged
merged 20 commits into from
Jul 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
773fb84
Optimized implementation of EquivalenceQuery.
tanyaveksler Jun 4, 2023
c5bf934
Added VacuityQuery and RedundancyQuery optimized implementation.
tanyaveksler Jun 20, 2023
aab6396
Added VacuityQuery and RedundancyQuery optimized implementation.
tanyaveksler Jun 20, 2023
54d3343
Ignoring 'complex function' lint error.
tanyaveksler Jun 11, 2023
adba6dd
Added VacuityQuery and RedundancyQuery optimized implementation.
tanyaveksler Jun 20, 2023
ab3a82e
Removed redundant method.
tanyaveksler Jun 13, 2023
c9393ee
Added VacuityQuery and RedundancyQuery optimized implementation.
tanyaveksler Jun 20, 2023
da98a3f
Fixed domain updating mechanism per rule (to avoid activating multipl…
tanyaveksler Jun 20, 2023
9cd810e
Fixed lint errors
tanyaveksler Jun 20, 2023
ac4f679
Enabled strongEquivalence optimized implementation.
tanyaveksler Jun 20, 2023
cbe8d1f
Implemented optimized ContainmentQuery.
tanyaveksler Jun 25, 2023
ac38097
Enabled optimized TwoContainmentQuery and PermitsQuery.
tanyaveksler Jun 25, 2023
6e632b5
Fixed small inaccuracy in handling host endpoints in optimized solution.
tanyaveksler Jun 27, 2023
af4c84f
Merge branch 'equivalence-based-queries-optmized' into containment-ba…
tanyaveksler Jun 27, 2023
a5ef8b8
Merge with master.
tanyaveksler Jul 4, 2023
4682ee7
Merge branch 'master' into containment-based-queries-optmized
tanyaveksler Jul 9, 2023
23188ae
Merge branch 'master' into containment-based-queries-optmized
tanyaveksler Jul 11, 2023
b1cf11f
Protecting optimized props policy members from direct access; accessi…
tanyaveksler Jul 11, 2023
e507368
Added implemented queries to run_all_tests.py
tanyaveksler Jul 16, 2023
0dd276a
Merge branch 'master' into containment-based-queries-optmized
tanyaveksler Jul 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions nca/Resources/CalicoNetworkPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,26 @@ def _update_opt_props_by_order(self, is_ingress):
for rule in self.ingress_rules if is_ingress else self.egress_rules:
props = rule.optimized_props.copy()
if rule.action == CalicoPolicyRule.ActionType.Allow:
props -= self.optimized_deny_ingress_props if is_ingress else self.optimized_deny_egress_props
props -= self.optimized_pass_ingress_props if is_ingress else self.optimized_pass_egress_props
props -= self._optimized_deny_ingress_props if is_ingress else self._optimized_deny_egress_props
props -= self._optimized_pass_ingress_props if is_ingress else self._optimized_pass_egress_props
if is_ingress:
self.optimized_allow_ingress_props |= props
self._optimized_allow_ingress_props |= props
else:
self.optimized_allow_egress_props |= props
self._optimized_allow_egress_props |= props
elif rule.action == CalicoPolicyRule.ActionType.Deny:
props -= self.optimized_allow_ingress_props if is_ingress else self.optimized_allow_egress_props
props -= self.optimized_pass_ingress_props if is_ingress else self.optimized_pass_egress_props
props -= self._optimized_allow_ingress_props if is_ingress else self._optimized_allow_egress_props
props -= self._optimized_pass_ingress_props if is_ingress else self._optimized_pass_egress_props
if is_ingress:
self.optimized_deny_ingress_props |= props
self._optimized_deny_ingress_props |= props
else:
self.optimized_deny_egress_props |= props
self._optimized_deny_egress_props |= props
elif rule.action == CalicoPolicyRule.ActionType.Pass:
props -= self.optimized_allow_ingress_props if is_ingress else self.optimized_allow_egress_props
props -= self.optimized_deny_ingress_props if is_ingress else self.optimized_deny_egress_props
props -= self._optimized_allow_ingress_props if is_ingress else self._optimized_allow_egress_props
props -= self._optimized_deny_ingress_props if is_ingress else self._optimized_deny_egress_props
if is_ingress:
self.optimized_pass_ingress_props |= props
self._optimized_pass_ingress_props |= props
else:
self.optimized_pass_egress_props |= props
self._optimized_pass_egress_props |= props

def sync_opt_props(self):
"""
Expand Down Expand Up @@ -169,17 +169,16 @@ def allowed_connections_optimized(self, is_ingress):
and the peer set of captured peers by this policy.
:rtype: tuple (ConnectivityProperties, ConnectivityProperties, PeerSet)
"""
self.sync_opt_props()
res_conns = OptimizedPolicyConnections()
if is_ingress:
res_conns.allowed_conns = self.optimized_allow_ingress_props.copy()
res_conns.denied_conns = self.optimized_deny_ingress_props.copy()
res_conns.pass_conns = self.optimized_pass_ingress_props.copy()
res_conns.allowed_conns = self.optimized_allow_ingress_props().copy()
res_conns.denied_conns = self.optimized_deny_ingress_props().copy()
res_conns.pass_conns = self.optimized_pass_ingress_props().copy()
res_conns.captured = self.selected_peers if self.affects_ingress else Peer.PeerSet()
else:
res_conns.allowed_conns = self.optimized_allow_egress_props.copy()
res_conns.denied_conns = self.optimized_deny_egress_props.copy()
res_conns.pass_conns = self.optimized_pass_egress_props.copy()
res_conns.allowed_conns = self.optimized_allow_egress_props().copy()
res_conns.denied_conns = self.optimized_deny_egress_props().copy()
res_conns.pass_conns = self.optimized_pass_egress_props().copy()
res_conns.captured = self.selected_peers if self.affects_egress else Peer.PeerSet()
return res_conns

Expand Down
5 changes: 2 additions & 3 deletions nca/Resources/IngressPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def sync_opt_props(self):
return
self._init_opt_props()
for rule in self.egress_rules:
self.optimized_allow_egress_props |= rule.optimized_props
self._optimized_allow_egress_props |= rule.optimized_props
self.optimized_props_in_sync = True

def allowed_connections(self, from_peer, to_peer, is_ingress):
Expand Down Expand Up @@ -110,13 +110,12 @@ def allowed_connections_optimized(self, is_ingress):
and the peer set of captured peers by this policy.
:rtype: tuple (ConnectivityProperties, ConnectivityProperties, PeerSet)
"""
self.sync_opt_props()
res_conns = OptimizedPolicyConnections()
if is_ingress:
res_conns.allowed_conns = ConnectivityProperties.make_empty_props()
res_conns.captured = PeerSet()
else:
res_conns.allowed_conns = self.optimized_allow_egress_props.copy()
res_conns.allowed_conns = self.optimized_allow_egress_props().copy()
res_conns.captured = self.selected_peers if self.affects_egress else PeerSet()
return res_conns

Expand Down
15 changes: 7 additions & 8 deletions nca/Resources/IstioNetworkPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ def sync_opt_props(self):
self._init_opt_props()
for rule in self.ingress_rules:
if self.action == IstioNetworkPolicy.ActionType.Allow:
self.optimized_allow_ingress_props |= rule.optimized_props
self._optimized_allow_ingress_props |= rule.optimized_props
elif self.action == IstioNetworkPolicy.ActionType.Deny:
self.optimized_deny_ingress_props |= rule.optimized_props
self._optimized_deny_ingress_props |= rule.optimized_props

self.optimized_allow_egress_props = ConnectivityProperties.get_all_conns_props_per_domain_peers()
self._optimized_allow_egress_props = ConnectivityProperties.get_all_conns_props_per_domain_peers()
self.optimized_props_in_sync = True

def allowed_connections(self, from_peer, to_peer, is_ingress):
Expand Down Expand Up @@ -122,15 +122,14 @@ def allowed_connections_optimized(self, is_ingress):
and the peer set of captured peers by this policy.
:rtype: tuple (ConnectivityProperties, ConnectivityProperties, PeerSet)
"""
self.sync_opt_props()
res_conns = OptimizedPolicyConnections()
if is_ingress:
res_conns.allowed_conns = self.optimized_allow_ingress_props.copy()
res_conns.denied_conns = self.optimized_deny_ingress_props.copy()
res_conns.allowed_conns = self.optimized_allow_ingress_props().copy()
res_conns.denied_conns = self.optimized_deny_ingress_props().copy()
res_conns.captured = self.selected_peers
else:
res_conns.allowed_conns = self.optimized_allow_egress_props.copy()
res_conns.denied_conns = self.optimized_deny_egress_props.copy()
res_conns.allowed_conns = self.optimized_allow_egress_props().copy()
res_conns.denied_conns = self.optimized_deny_egress_props().copy()
res_conns.captured = PeerSet()
return res_conns

Expand Down
13 changes: 6 additions & 7 deletions nca/Resources/IstioSidecar.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ def sync_opt_props(self):
if self.optimized_props_in_sync:
return
self._init_opt_props()
self.optimized_allow_ingress_props = ConnectivityProperties.get_all_conns_props_per_domain_peers()
self._optimized_allow_ingress_props = ConnectivityProperties.get_all_conns_props_per_domain_peers()
for rule in self.egress_rules:
self.optimized_allow_egress_props |= rule.optimized_props
self._optimized_allow_egress_props |= rule.optimized_props
self.optimized_props_in_sync = True

def allowed_connections(self, from_peer, to_peer, is_ingress):
Expand Down Expand Up @@ -100,15 +100,14 @@ def allowed_connections(self, from_peer, to_peer, is_ingress):
return PolicyConnections(True, allowed_conns=ConnectionSet())

def allowed_connections_optimized(self, is_ingress):
self.sync_opt_props()
res_conns = OptimizedPolicyConnections()
if is_ingress:
res_conns.allowed_conns = self.optimized_allow_ingress_props.copy()
res_conns.denied_conns = self.optimized_deny_ingress_props.copy()
res_conns.allowed_conns = self.optimized_allow_ingress_props().copy()
res_conns.denied_conns = self.optimized_deny_ingress_props().copy()
res_conns.captured = PeerSet()
else:
res_conns.allowed_conns = self.optimized_allow_egress_props.copy()
res_conns.denied_conns = self.optimized_deny_egress_props.copy()
res_conns.allowed_conns = self.optimized_allow_egress_props().copy()
res_conns.denied_conns = self.optimized_deny_egress_props().copy()
res_conns.captured = self.selected_peers if self.affects_egress else PeerSet()
return res_conns

Expand Down
9 changes: 4 additions & 5 deletions nca/Resources/K8sNetworkPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ def sync_opt_props(self):
return
self._init_opt_props()
for rule in self.ingress_rules:
self.optimized_allow_ingress_props |= rule.optimized_props
self._optimized_allow_ingress_props |= rule.optimized_props
for rule in self.egress_rules:
self.optimized_allow_egress_props |= rule.optimized_props
self._optimized_allow_egress_props |= rule.optimized_props
self.optimized_props_in_sync = True

def allowed_connections(self, from_peer, to_peer, is_ingress):
Expand Down Expand Up @@ -89,13 +89,12 @@ def allowed_connections_optimized(self, is_ingress):
and the peer set of captured peers by this policy.
:rtype: tuple (ConnectivityProperties, ConnectivityProperties, PeerSet)
"""
self.sync_opt_props()
res_conns = OptimizedPolicyConnections()
if is_ingress:
res_conns.allowed_conns = self.optimized_allow_ingress_props.copy()
res_conns.allowed_conns = self.optimized_allow_ingress_props().copy()
res_conns.captured = self.selected_peers if self.affects_ingress else Peer.PeerSet()
else:
res_conns.allowed_conns = self.optimized_allow_egress_props.copy()
res_conns.allowed_conns = self.optimized_allow_egress_props().copy()
res_conns.captured = self.selected_peers if self.affects_egress else Peer.PeerSet()
return res_conns

Expand Down
56 changes: 44 additions & 12 deletions nca/Resources/NetworkPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,45 @@ def __init__(self, name, namespace):
def _init_opt_props(self):
"""
The members below are used for lazy evaluation of policy connectivity properties.
NOTE: THEY CANNOT BE ACCESSED DIRECTLY, ONLY BY 'GETTER' METHODS BELOW!
"""
self.optimized_allow_ingress_props = ConnectivityProperties.make_empty_props()
self.optimized_deny_ingress_props = ConnectivityProperties.make_empty_props()
self.optimized_pass_ingress_props = ConnectivityProperties.make_empty_props()
self.optimized_allow_egress_props = ConnectivityProperties.make_empty_props()
self.optimized_deny_egress_props = ConnectivityProperties.make_empty_props()
self.optimized_pass_egress_props = ConnectivityProperties.make_empty_props()
self._optimized_allow_ingress_props = ConnectivityProperties.make_empty_props()
self._optimized_deny_ingress_props = ConnectivityProperties.make_empty_props()
self._optimized_pass_ingress_props = ConnectivityProperties.make_empty_props()
self._optimized_allow_egress_props = ConnectivityProperties.make_empty_props()
self._optimized_deny_egress_props = ConnectivityProperties.make_empty_props()
self._optimized_pass_egress_props = ConnectivityProperties.make_empty_props()

def optimized_allow_ingress_props(self):
self.sync_opt_props()
return self._optimized_allow_ingress_props

def optimized_deny_ingress_props(self):
self.sync_opt_props()
return self._optimized_deny_ingress_props

def optimized_pass_ingress_props(self):
self.sync_opt_props()
return self._optimized_pass_ingress_props

def optimized_allow_egress_props(self):
self.sync_opt_props()
return self._optimized_allow_egress_props

def optimized_deny_egress_props(self):
self.sync_opt_props()
return self._optimized_deny_egress_props

def optimized_pass_egress_props(self):
self.sync_opt_props()
return self._optimized_pass_egress_props

def sync_opt_props(self):
"""
Implemented by derived policies to compute optimized props of the policy according to the optimized props
of its rules, in case optimized props are not currently synchronized.
"""
return NotImplemented

def __str__(self):
return self.full_name()
Expand All @@ -93,12 +125,12 @@ def __eq__(self, other):
self.selected_peers == other.selected_peers and \
self.ingress_rules == other.ingress_rules and \
self.egress_rules == other.egress_rules and \
self.optimized_allow_ingress_props == other.optimized_allow_ingress_props and \
self.optimized_deny_ingress_props == other.optimized_deny_ingress_props and \
self.optimized_pass_ingress_props == other.optimized_pass_ingress_props and \
self.optimized_allow_egress_props == other.optimized_allow_egress_props and \
self.optimized_deny_egress_props == other.optimized_deny_egress_props and \
self.optimized_pass_egress_props == other.optimized_pass_egress_props
self._optimized_allow_ingress_props == other._optimized_allow_ingress_props and \
self._optimized_deny_ingress_props == other._optimized_deny_ingress_props and \
self._optimized_pass_ingress_props == other._optimized_pass_ingress_props and \
self._optimized_allow_egress_props == other._optimized_allow_egress_props and \
self._optimized_deny_egress_props == other._optimized_deny_egress_props and \
self._optimized_pass_egress_props == other._optimized_pass_egress_props
adisos marked this conversation as resolved.
Show resolved Hide resolved
return False

def __lt__(self, other): # required so we can evaluate the policies according to their order
Expand Down
5 changes: 2 additions & 3 deletions nca/Utils/ExplTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,9 @@ def are_peers_connected(self, src, dst):
{"src_peers": PeerSet({src_peer}), "dst_peers": PeerSet({dst_peer})}) else False

def add_policy_to_peers(self, policy):
policy.sync_opt_props()
for peer in policy.selected_peers:
src_peers, _ = self.extract_peers(policy.optimized_allow_ingress_props)
_, dst_peers = self.extract_peers(policy.optimized_allow_egress_props)
src_peers, _ = self.extract_peers(policy.optimized_allow_ingress_props())
_, dst_peers = self.extract_peers(policy.optimized_allow_egress_props())
peer_name = peer.full_name()
self.add_peer_policy(peer_name, policy.name, dst_peers, src_peers)

Expand Down