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

preparation to support istio egress gateway #604

Merged
merged 17 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a791e42
Bug fix in livesim: Changed missing pods labels dictionary to set of …
tanyaveksler Aug 22, 2023
21e0e20
Small fixes and preparations for implementing istio egress gateway.
tanyaveksler Sep 19, 2023
9e86069
Merge branch 'master' into 566-support-for-istio-egress-gateway
tanyaveksler Sep 19, 2023
e3ec001
More fixes of handling DNS entries in optimized solution.
tanyaveksler Sep 19, 2023
28a11b9
Uppdating expected results of some livesim tests following the additi…
tanyaveksler Sep 19, 2023
ec40625
Merge with master
tanyaveksler Oct 3, 2023
4386ff5
Small fixes.
tanyaveksler Oct 3, 2023
09013b6
Referencing istio ingress gateway as istio:ingressgateway (to be alig…
tanyaveksler Oct 3, 2023
bfe1466
Changing expected results of some istio ingress/egress gateway tests …
tanyaveksler Oct 8, 2023
1ec20f2
Changing expected results of some istio ingress/egress gateway tests …
tanyaveksler Oct 8, 2023
5e2088d
Merge branch 'master' into 566-support-for-istio-egress-gateway
tanyaveksler Oct 17, 2023
2161bd4
Renamed IngressPolicy to IstioGatewayPolicy.
tanyaveksler Oct 17, 2023
0703d04
Merge branch 'master' into 566-support-for-istio-egress-gateway
tanyaveksler Nov 5, 2023
1ac861d
Renamed IstioGatewayPolicy to GatewayPolicy.
tanyaveksler Nov 7, 2023
df7d0eb
Update nca/Resources/GatewayPolicy.py
tanyaveksler Nov 12, 2023
bed56a4
Update nca/NetworkConfig/NetworkConfigQuery.py
tanyaveksler Nov 12, 2023
4c5e69c
Renamed Ingress layer to Gateway layer.
tanyaveksler Nov 12, 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
4 changes: 4 additions & 0 deletions nca/CoreDS/ConnectionSet.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,10 @@ def split_peer_set_to_fw_rule_elements(peer_set, cluster_info):
res.append(FWRule.IPBlockElement(peer))
peer_set_copy.remove(peer)
continue
elif isinstance(peer, FWRule.DNSEntry):
res.append(FWRule.DNSElement(peer))
peer_set_copy.remove(peer)
continue
ns_peers = PeerSet(cluster_info.ns_dict[peer.namespace])
if ns_peers.issubset(peer_set_copy):
ns_set.add(peer.namespace)
Expand Down
30 changes: 29 additions & 1 deletion nca/NetworkConfig/LiveSim/istio_gateway/istio_gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: Pod
metadata:
name: istio-ingressgateway-livesim
namespace: istio-ingressgateway-ns
namespace: istio-system
labels:
app: istio-ingressgateway
istio: ingressgateway
Expand All @@ -11,4 +11,32 @@ spec:
containers:
- name: istio-proxy
image: auto
---

apiVersion: v1
kind: Pod
metadata:
name: istio-egressgateway-livesim
namespace: istio-system
labels:
app: istio-egressgateway
istio: egressgateway
spec:
serviceAccountName: istio-egressgateway
containers:
- name: istio-proxy
image: auto
---

apiVersion: v1
kind: Service
metadata:
name: istio-egressgateway
namespace: istio-system
spec:
ports:
- port: 443
selector:
app: istio-egressgateway
istio: egressgateway
---
11 changes: 6 additions & 5 deletions nca/NetworkConfig/NetworkLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ def _allowed_xgress_conns(self, from_peer, to_peer, is_ingress):

def _allowed_xgress_conns_optimized(self, is_ingress, peer_container):
res_conns = self.collect_policies_conns_optimized(is_ingress, IstioNetworkLayer.captured_cond_func)
all_peers_and_ips = peer_container.get_all_peers_group(True)
all_peers_no_ips = peer_container.get_all_peers_group()
all_peers_and_ips = peer_container.get_all_peers_group(add_external_ips=True)
all_peers_no_ips = peer_container.get_all_peers_group(add_external_ips=False)
dns_entries = peer_container.get_all_dns_entries()
# for istio initialize non-captured conns with all possible non-TCP connections
# This is a compact way to represent all peers connections, but it is an over-approximation also containing
Expand Down Expand Up @@ -421,8 +421,8 @@ def _allowed_xgress_conns(self, from_peer, to_peer, is_ingress):

def _allowed_xgress_conns_optimized(self, is_ingress, peer_container):
res_conns = OptimizedPolicyConnections()
all_peers_and_ips = peer_container.get_all_peers_group(True)
all_peers_no_ips = peer_container.get_all_peers_group()
all_peers_and_ips = peer_container.get_all_peers_group(add_external_ips=True, include_dns_entries=True)
adisos marked this conversation as resolved.
Show resolved Hide resolved
all_peers_no_ips = peer_container.get_all_peers_group(add_external_ips=False, include_dns_entries=True)
non_captured_conns = None
if is_ingress:
# everything is allowed and non captured
Expand All @@ -431,11 +431,12 @@ def _allowed_xgress_conns_optimized(self, is_ingress, peer_container):
res_conns.all_allowed_conns = non_captured_conns
else:
res_conns = self.collect_policies_conns_optimized(is_ingress)
res_conns.all_allowed_conns = res_conns.allowed_conns
non_captured_peers = all_peers_no_ips - res_conns.captured
if non_captured_peers:
non_captured_conns = ConnectivityProperties.make_conn_props_from_dict({"src_peers": non_captured_peers,
"dst_peers": all_peers_and_ips})
res_conns.all_allowed_conns = res_conns.allowed_conns | non_captured_conns
res_conns.all_allowed_conns |= non_captured_conns
if non_captured_conns and ExplTracker().is_active():
src_peers, dst_peers = ExplTracker().extract_peers(non_captured_conns)
ExplTracker().add_default_policy(src_peers,
Expand Down
4 changes: 2 additions & 2 deletions nca/NetworkConfig/PoliciesFinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ def __init__(self, optimized_run='false'):
self.optimized_run = optimized_run
# following missing resources fields are relevant for "livesim" mode,
# where certain resources are added to enable the analysis
self.missing_istio_gw_pods_with_labels = {}
self.missing_istio_gw_pods_with_labels = set()
self.missing_k8s_ingress_peers = False
self.missing_dns_pods_with_labels = {}
self.missing_dns_pods_with_labels = set()

def set_peer_container(self, peer_container):
"""
Expand Down
20 changes: 10 additions & 10 deletions nca/NetworkConfig/ResourcesHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,24 @@ def get_full_livesim_resource_path(livesim_resource_path):
return os.path.join(current_path, livesim_resource_path)

@staticmethod
def get_relevant_livesim_resources_paths_by_labels_matching(livesim_resource_path, missing_resource_labels_dict):
def get_relevant_livesim_resources_paths_by_labels_matching(livesim_resource_path, missing_resource_labels):
"""
check by labels matching if one of the livesim resources has matching labels for a resource referenced by one
of the parsed policies. If yes, return its path to be added to the configuration, to enable the analysis.
:param str livesim_resource_path: a path to the relevant livesim dir to check for resources
:param dict missing_resource_labels_dict: the labels from parsed policy in the config for
:param list missing_resource_labels: the labels from parsed policy in the config for
adisos marked this conversation as resolved.
Show resolved Hide resolved
which a matching peer was missing
:return: list of paths for relevant livesim resources to add
:rtype list[str]
"""
res = []
resource_full_path = ResourcesHandler.get_full_livesim_resource_path(livesim_resource_path)
livesim_resource_labels = ResourcesParser.parse_livesim_yamls(resource_full_path)
for key in missing_resource_labels_dict.keys():
for (key, value) in missing_resource_labels:
for yaml_path, labels in livesim_resource_labels.items():
if missing_resource_labels_dict.get(key) == labels.get(key):
if (key, value) in labels:
res.append(yaml_path)
return res
return list(dict.fromkeys(res)) # remove duplicates
adisos marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def analyze_livesim(policy_finder):
Expand All @@ -113,12 +113,12 @@ def analyze_livesim(policy_finder):
livesim_configuration_addons.append(resource_full_path)
ResourcesHandler.livesim_information_message('ingress-controller')

# find Istio ingress gateway
# find Istio ingress/egress gateway
istio_gateway_added_resources = ResourcesHandler.get_relevant_livesim_resources_paths_by_labels_matching(
LiveSimPaths.IstioGwCfgPath, policy_finder.missing_istio_gw_pods_with_labels)
if istio_gateway_added_resources:
livesim_configuration_addons += istio_gateway_added_resources
ResourcesHandler.livesim_information_message('Istio-ingress-gateway')
ResourcesHandler.livesim_information_message('Istio-ingress/egress-gateway')

return livesim_configuration_addons

Expand Down Expand Up @@ -367,15 +367,15 @@ def parse_livesim_yamls(path):
for yaml_file in yaml_files:
pods_finder = PodsFinder()
ns_finder = NamespacesFinder()
labels_found = {}
labels_found = set()
for res_code in yaml_file.data:
ns_finder.parse_yaml_code_for_ns(res_code)
pods_finder.namespaces_finder = ns_finder
pods_finder.add_eps_from_yaml(res_code)
for item in ns_finder.namespaces.values():
labels_found.update(item.labels)
labels_found.update(set(item.labels.items()))
for item in pods_finder.peer_set:
labels_found.update(item.labels)
labels_found.update(set(item.labels.items()))
results.update({yaml_file.path: labels_found})
NcaLogger().collect_msgs()

Expand Down
6 changes: 3 additions & 3 deletions nca/Parsers/IstioTrafficResourcesYamlParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ def __init__(self, peer_container):
self.namespace = None
self.gateways = {} # a map from a name to a Gateway
self.virtual_services = {} # a map from a name to a VirtualService
# missing_istio_gw_pods_with_labels is map from key to value of labels
# missing_istio_gw_pods_with_labels is a set of labels - (key,value) pairs
# of gateway resource that has no matching pods
self.missing_istio_gw_pods_with_labels = {}
self.missing_istio_gw_pods_with_labels = set()

def add_gateway(self, gateway):
"""
Expand Down Expand Up @@ -72,7 +72,7 @@ def parse_gateway(self, gateway_resource, gateway_file_name):
for key, val in selector.items():
selector_peers = self.peer_container.get_peers_with_label(key, [val])
if not selector_peers:
self.missing_istio_gw_pods_with_labels[key] = val
self.missing_istio_gw_pods_with_labels.add((key, val))
else:
peers &= selector_peers
if not peers:
Expand Down
6 changes: 3 additions & 3 deletions nca/Parsers/K8sPolicyYamlParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ def __init__(self, policy, peer_container, policy_file_name='', optimized_run='f
self.namespace = None
self.referenced_labels = set()
self.optimized_run = optimized_run
# map from key to value - info about missing resources
self.missing_pods_with_labels = {}
# a set of (key, value) pairs (note, the set may contain pods with labels having same keys but different values
self.missing_pods_with_labels = set()

def check_dns_subdomain_name(self, value, key_container):
"""
Expand Down Expand Up @@ -179,7 +179,7 @@ def parse_label_selector(self, label_selector, namespace_selector=False):
else:
res &= self.peer_container.get_peers_with_label(key, [val])
if not res:
self.missing_pods_with_labels[key] = val
self.missing_pods_with_labels.add((key, val))
keys_set.add(key)
self.referenced_labels.add(':'.join(keys_set))

Expand Down
1 change: 1 addition & 0 deletions nca/Resources/IngressPolicy.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(self, peer_set, connections, opt_props):
"""
:param Peer.PeerSet peer_set: The set of peers this rule allows connection to
:param ConnectionSet connections: The set of connections allowed by this rule
:param ConnectivityProperties opt_props: the optimized connections
"""
self.peer_set = peer_set
self.connections = connections
Expand Down
19 changes: 13 additions & 6 deletions tests/expected_cmdline_output_files/livesim_test_all_dot.dot
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ subgraph cluster_ingress_controller_ns_namespace{
tooltip="Namespace"
"ingress-controller-ns/ingress-controller-livesim(Pod)" [label=<<table border="0" cellspacing="0"><tr><td>ingress-controller-livesim(Pod)</td></tr></table>> shape=box fontcolor=magenta tooltip="Automatically added workload"]
}
subgraph cluster_istio_ingressgateway_ns_namespace{
label="istio-ingressgateway-ns"
subgraph cluster_istio_system_namespace{
label="istio-system"
fontsize=20
fontcolor=blue
tooltip="Namespace"
"istio-ingressgateway-ns/istio-ingressgateway-livesim(Pod)" [label=<<table border="0" cellspacing="0"><tr><td>istio-ingressgateway-livesim(Pod)</td></tr></table>> shape=box fontcolor=magenta tooltip="Automatically added workload"]
"istio-system/istio-egressgateway-livesim(Pod)" [label=<<table border="0" cellspacing="0"><tr><td>istio-egressgateway-livesim(Pod)</td></tr></table>> shape=box fontcolor=magenta tooltip="Automatically added workload"]
"istio-system/istio-ingressgateway-livesim(Pod)" [label=<<table border="0" cellspacing="0"><tr><td>istio-ingressgateway-livesim(Pod)</td></tr></table>> shape=box fontcolor=magenta tooltip="Automatically added workload"]
}
subgraph cluster_kube_system_namespace{
label="kube-system"
Expand All @@ -40,19 +41,25 @@ subgraph cluster_kube_system_namespace{
"0.0.0.0/0" -> "default/foo-app(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"0.0.0.0/0" -> "default/httpbin(Deployment)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"0.0.0.0/0" -> "ingress-controller-ns/ingress-controller-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"0.0.0.0/0" -> "istio-ingressgateway-ns/istio-ingressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"0.0.0.0/0" -> "istio-system/istio-ingressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"default/deployment-A(Deployment)" -> "kube-system/kube-dns-livesim(Pod)"[label="udp53" labeltooltip="UDP 53" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"default/deployment-B(Deployment)" -> "default/deployment-A(Deployment)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=normal]
"default/deployment-B(Deployment)" -> "kube-system/kube-dns-livesim(Pod)"[label="udp53" labeltooltip="UDP 53" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"default/foo-app(Pod)" -> "kube-system/kube-dns-livesim(Pod)"[label="udp53" labeltooltip="UDP 53" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"default/httpbin(Deployment)" -> "kube-system/kube-dns-livesim(Pod)"[label="udp53" labeltooltip="UDP 53" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"ingress-controller-ns/ingress-controller-livesim(Pod)" -> "default/foo-app(Pod)"[label="tcp5678" labeltooltip="TCP {'dst_ports': '5678', 'paths': '/foo(/*)?'}" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-ingressgateway-ns/istio-ingressgateway-livesim(Pod)" -> "default/httpbin(Deployment)"[label="tcp80" labeltooltip="TCP {'dst_ports': '80', 'hosts': 'httpbin.example.com', 'paths': '(/status(/*)?)|(/delay(/*)?)'}" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-system/istio-egressgateway-livesim(Pod)" -> "0.0.0.0/0"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=normal]
"istio-system/istio-egressgateway-livesim(Pod)" -> "default/foo-app(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-system/istio-egressgateway-livesim(Pod)" -> "default/httpbin(Deployment)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-system/istio-egressgateway-livesim(Pod)" -> "ingress-controller-ns/ingress-controller-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-system/istio-egressgateway-livesim(Pod)" -> "istio-system/istio-ingressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"istio-system/istio-ingressgateway-livesim(Pod)" -> "default/httpbin(Deployment)"[label="tcp80" labeltooltip="TCP {'dst_ports': '80', 'hosts': 'httpbin.example.com', 'paths': '(/status(/*)?)|(/delay(/*)?)'}" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"kube-system/kube-dns-livesim(Pod)" -> "0.0.0.0/0"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=normal]
"kube-system/kube-dns-livesim(Pod)" -> "default/foo-app(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"kube-system/kube-dns-livesim(Pod)" -> "default/httpbin(Deployment)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"kube-system/kube-dns-livesim(Pod)" -> "ingress-controller-ns/ingress-controller-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"kube-system/kube-dns-livesim(Pod)" -> "istio-ingressgateway-ns/istio-ingressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
"kube-system/kube-dns-livesim(Pod)" -> "istio-system/istio-egressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=normal]
"kube-system/kube-dns-livesim(Pod)" -> "istio-system/istio-ingressgateway-livesim(Pod)"[label="All" labeltooltip="All" color=darkorange4 fontcolor=darkgreen dir=both arrowhead=normal arrowtail=none]
color=white
label=<<table border="0" cellspacing="0"><tr><td align="text" >Application connectivity graph <br align="left" /></td></tr><tr><td align="text" > <br align="left" /></td></tr><tr><td align="text" > <br align="left" /></td></tr></table>>
labelloc = "b"
Expand Down
11 changes: 7 additions & 4 deletions tests/expected_cmdline_output_files/livesim_test_all_txt.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
final fw rules for query: , config: **:
src: 0.0.0.0/0 dst_ns: [default] dst_pods: [!has(dep)] conn: All connections
src: 0.0.0.0/0 dst_ns: [ingress-controller-ns,istio-ingressgateway-ns,kube-system] dst_pods: [*] conn: All connections
src: 0.0.0.0/0 dst_ns: [ingress-controller-ns,istio-system,kube-system] dst_pods: [*] conn: All connections
src_ns: [default] src_pods: [*] dst_ns: [kube-system] dst_pods: [*] conn: UDP 53
src_ns: [default] src_pods: [dep=A] dst_ns: [default] dst_pods: [dep=B] conn: All connections
src_ns: [default] src_pods: [dep=B] dst_ns: [default] dst_pods: [dep=A] conn: All connections
src_ns: [ingress-controller-ns,kube-system] src_pods: [*] dst_ns: [ingress-controller-ns] dst_pods: [*] conn: All connections
src_ns: [ingress-controller-ns] src_pods: [*] dst_ns: [default] dst_pods: [foo-app] conn: TCP {'dst_ports': '5678', 'paths': '/foo(/*)?'}
src_ns: [istio-ingressgateway-ns,kube-system] src_pods: [*] dst_ns: [istio-ingressgateway-ns] dst_pods: [*] conn: All connections
src_ns: [istio-ingressgateway-ns] src_pods: [*] dst_ns: [default] dst_pods: [httpbin] conn: TCP {'dst_ports': '80', 'hosts': 'httpbin.example.com', 'paths': '(/status(/*)?)|(/delay(/*)?)'}
src_ns: [istio-system] src_pods: [*] dst_ns: [default] dst_pods: [httpbin] conn: TCP {'dst_ports': '80', 'hosts': 'httpbin.example.com', 'paths': '(/status(/*)?)|(/delay(/*)?)'}
src_ns: [istio-system] src_pods: [*] dst_ns: [istio-system] dst_pods: [istio-ingressgateway-livesim] conn: All connections
src_ns: [istio-system] src_pods: [istio-egressgateway-livesim] dst: 0.0.0.0/0 conn: All connections
src_ns: [istio-system] src_pods: [istio-egressgateway-livesim] dst_ns: [default] dst_pods: [!has(dep)] conn: All connections
src_ns: [istio-system] src_pods: [istio-egressgateway-livesim] dst_ns: [ingress-controller-ns,istio-system,kube-system] dst_pods: [*] conn: All connections
src_ns: [kube-system] src_pods: [*] dst: 0.0.0.0/0 conn: All connections
src_ns: [kube-system] src_pods: [*] dst_ns: [default] dst_pods: [!has(dep)] conn: All connections
src_ns: [kube-system] src_pods: [*] dst_ns: [kube-system] dst_pods: [*] conn: All connections
src_ns: [kube-system] src_pods: [*] dst_ns: [istio-system,kube-system] dst_pods: [*] conn: All connections