Skip to content

Commit

Permalink
Merge branch 'master' into bug_in_HC_set
Browse files Browse the repository at this point in the history
  • Loading branch information
tanyaveksler authored Jul 9, 2023
2 parents 476fe3d + 7335253 commit 0efbbe6
Show file tree
Hide file tree
Showing 31 changed files with 9,786 additions and 58 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ The arguments to `--resource_list` and to `--base_resource_list` should be one o
- `--output_endpoints`\
Choose endpoints type in output (pods/deployments).\
*default:* deployments
- `--explain`\
A pair of node names (comma separated) to explain the policies affecting their connection or lack of it. Relevant only for connectivity query.\
Connections including IP-Blocks will show only the configurations of the node in that connection (since, IP-Blocks does
not have configurations). IP-Blocks should be places in CIDR format as seen in the query results (run the connectivity query first, to see the nodes there).\
e.g. default/pod-A1,default/deployment-B1.
- `--print_ipv6`\
include IPv6 range in the query results even when the policies of the config do not contain any IPv6 addresses.

Expand Down
18 changes: 9 additions & 9 deletions docs/SchemeFileFormat.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ For example: `my_set/prod_ns/deny_all_policy`. If there are multiple policies na
#### <a name="outputconfig"></a>Output Configuration object
The supported entries in the outputConfiguration object are as follows:

| Field | Description | Value |
|------------------|-----------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|
| outputFormat | Output format specification. | string [ txt / yaml / csv / md / dot / jpg/ txt_no_fw_rules] |
| outputPath | A file path to redirect output into. | string |
| outputEndpoints | Choose endpoints type in output. | string [ pods / deployments ] |
| subset | A dict object with the defined subset elements to display in the output | [subset](#subset) object |
| fullExplanation | Choose if to print all counterexamples causing the query result in the output | bool |
| excludeIPv6Range | If the policies of the config do not contain any IPv6 addresses, do not include IPv6 range in the query results | bool [default: True] |

| Field | Description | Value |
|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|
| outputFormat | Output format specification. | string [ txt / yaml / csv / md / dot / jpg/ txt_no_fw_rules] |
| outputPath | A file path to redirect output into. | string |
| outputEndpoints | Choose endpoints type in output. | string [ pods / deployments ] |
| subset | A dict object with the defined subset elements to display in the output | [subset](#subset) object |
| fullExplanation | Choose if to print all counterexamples causing the query result in the output | bool |
| excludeIPv6Range | If the policies of the config do not contain any IPv6 addresses, do not include IPv6 range in the query results | bool [default: True] |
| explain | A pair of node names (comma separated) to explain the policies affecting their connection or lack of it. Relevant only for connectivityMap query. Connections including IP-Blocks will show only the configurations of the node in that connection (since, IP-Blocks does not have configurations). IP-Blocks should be places in CIDR format as seen in the query results (run the connectivity query first, to see the nodes there). | string [ ns/node1,ns/node2 ] |

#### <a name="subset"></a>Subset object
The supported entries in the subset object are as follows:
Expand Down
2 changes: 1 addition & 1 deletion nca/FWRules/ConnectivityGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def get_connectivity_dot_format_str(self, connectivity_restriction=None):

dot_graph = DotGraph(name)
peers_groups = self._get_equals_groups()
# we are going to treat a a peers_group as one peer.
# we are going to treat a peers_group as one peer.
# the first peer in the peers_group is representing the group
# we will add the text of all the peers in the group to this peer
for peers_group, group_connection in peers_groups:
Expand Down
3 changes: 2 additions & 1 deletion nca/FWRules/FWRule.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,8 @@ def get_pod_str(self):
"""
:return: string for the field src_pods or dst_pods in representation for txt rule format
"""
return f'[{self._get_pods_names()}]'
sorted_pods_names = ', '.join(sorted(self._get_pods_names().split(', ')))
return f'[{sorted_pods_names}]'

def _get_pods_names(self):
res = ''
Expand Down
2 changes: 1 addition & 1 deletion nca/FWRules/InteractiveConnectivityGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def read_input_file(self):
"""
try:
with open(self.input_svg_file) as svg_file:
self.soup = BeautifulSoup(svg_file.read(), 'xml')
self.soup = BeautifulSoup(svg_file.read(), 'html')
except Exception as e:
print(f'Failed to open file: {self.input_svg_file}\n{e} for reading', file=sys.stderr)

Expand Down
3 changes: 3 additions & 0 deletions nca/FileScanners/GenericTreeScanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class YamlFile:

class ObjectWithLocation:
line_number = 0
path = ''
column_number = 0


Expand All @@ -36,13 +37,15 @@ def to_yaml_objects(yaml_node):
if isinstance(yaml_node, yaml.SequenceNode):
res = YamlList()
res.line_number = yaml_node.start_mark.line
res.path = yaml_node.start_mark.name
res.column_number = yaml_node.start_mark.column
for obj in yaml_node.value:
res.append(to_yaml_objects(obj))
return res
if isinstance(yaml_node, yaml.MappingNode):
res = YamlDict()
res.line_number = yaml_node.start_mark.line + 1
res.path = yaml_node.start_mark.name
res.column_number = yaml_node.start_mark.column + 1
for obj in yaml_node.value:
res[obj[0].value] = to_yaml_objects(obj[1])
Expand Down
3 changes: 3 additions & 0 deletions nca/NetworkConfig/NetworkConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from nca.CoreDS.ConnectivityProperties import ConnectivityProperties
from nca.Resources.NetworkPolicy import NetworkPolicy, OptimizedPolicyConnections
from .NetworkLayer import NetworkLayersContainer, NetworkLayerName
from nca.Utils.ExplTracker import ExplTracker


@dataclass
Expand Down Expand Up @@ -275,6 +276,8 @@ def allowed_connections_optimized(self, layer_name=None):
:return: allowed_conns: all allowed connections for relevant peers.
:rtype: OptimizedPolicyConnections
"""
if ExplTracker().is_active():
ExplTracker().set_peers(self.peer_container.peer_set)
if layer_name is not None:
if layer_name not in self.policies_container.layers:
return self.policies_container.layers.empty_layer_allowed_connections_optimized(self.peer_container,
Expand Down
33 changes: 31 additions & 2 deletions nca/NetworkConfig/NetworkConfigQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
PoliciesAndRulesExplanations, PodsListsExplanations, ConnectionsDiffExplanation, IntersectPodsExplanation, \
PoliciesWithCommonPods, PeersAndConnections, ComputedExplanation
from .NetworkLayer import NetworkLayerName
from nca.Utils.ExplTracker import ExplTracker


class QueryType(Enum):
Expand Down Expand Up @@ -805,17 +806,24 @@ def compute_connectivity_output_optimized(self):
"dst_peers": opt_peers_to_compare})
base_peers_num = len(opt_peers_to_compare)
subset_peers = self.compute_subset(opt_peers_to_compare)
all_peers = subset_peers
if len(subset_peers) != base_peers_num:
# remove connections where both of src_peers and dst_peers are out of the subset
subset_conns = ConnectivityProperties.make_conn_props_from_dict({"src_peers": subset_peers}) | \
ConnectivityProperties.make_conn_props_from_dict({"dst_peers": subset_peers})
all_conns_opt &= subset_conns
src_peers, dst_peers = ExplTracker().extract_peers(all_conns_opt)
all_peers = src_peers | dst_peers
all_conns_opt = self.config.filter_conns_by_peer_types(all_conns_opt, opt_peers_to_compare)
expl_conns = all_conns_opt
if self.config.policies_container.layers.does_contain_layer(NetworkLayerName.Istio):
output_res, opt_fw_rules_tcp, opt_fw_rules_non_tcp = \
self.get_props_output_split_by_tcp(all_conns_opt, opt_peers_to_compare)
expl_conns, _ = self.convert_props_to_split_by_tcp(all_conns_opt)
else:
output_res, opt_fw_rules = self.get_props_output_full(all_conns_opt, opt_peers_to_compare)
if ExplTracker().is_active():
ExplTracker().set_connections_and_peers(expl_conns, all_peers)
return output_res, opt_fw_rules, opt_fw_rules_tcp, opt_fw_rules_non_tcp

def exec(self):
Expand Down Expand Up @@ -900,7 +908,9 @@ def get_props_output_full(self, props, peers_to_compare):
if self.output_config.outputFormat in ['dot', 'jpg']:
dot_full = self.dot_format_from_props(props, peers_to_compare)
return dot_full, None
# TODO - handle 'txt_no_fw_rules' output format
if self.output_config.outputFormat == 'txt_no_fw_rules':
conns_wo_fw_rules = self.txt_no_fw_rules_format_from_props(props, peers_to_compare)
return conns_wo_fw_rules, None
# handle other formats
formatted_rules, fw_rules = self.fw_rules_from_props(props, peers_to_compare)
return formatted_rules, fw_rules
Expand Down Expand Up @@ -966,7 +976,12 @@ def get_props_output_split_by_tcp(self, props, peers_to_compare):
# concatenate the two graphs into one dot file
res_str = dot_tcp + dot_non_tcp
return res_str, None, None
# TODO - handle 'txt_no_fw_rules' output format
if self.output_config.outputFormat in ['txt_no_fw_rules']:
txt_no_fw_rules_tcp = self.txt_no_fw_rules_format_from_props(props_tcp, peers_to_compare, connectivity_tcp_str)
txt_no_fw_rules_non_tcp = self.txt_no_fw_rules_format_from_props(props_non_tcp, peers_to_compare,
connectivity_non_tcp_str)
res_str = txt_no_fw_rules_tcp + txt_no_fw_rules_non_tcp
return res_str, None, None
# handle formats other than dot and txt_no_fw_rules
formatted_rules_tcp, fw_rules_tcp = self.fw_rules_from_props(props_tcp, peers_to_compare, connectivity_tcp_str)
formatted_rules_non_tcp, fw_rules_non_tcp = self.fw_rules_from_props(props_non_tcp, peers_to_compare,
Expand Down Expand Up @@ -1033,6 +1048,20 @@ def dot_format_from_props(self, props, peers, connectivity_restriction=None):
conn_graph.add_edges_from_cube_dict(props.get_connectivity_cube(cube), self.config.peer_container)
return conn_graph.get_connectivity_dot_format_str(connectivity_restriction)

def txt_no_fw_rules_format_from_props(self, props, peers, connectivity_restriction=None):
"""
:param ConnectivityProperties props: properties describing allowed connections
:param PeerSet peers: the peers to consider for dot output
:param Union[str,None] connectivity_restriction: specify if connectivity is restricted to
TCP / non-TCP , or not
:rtype str
:return the connectivity map in txt_no_fw_rules format, considering connectivity_restriction if required
"""
conn_graph = ConnectivityGraph(peers, self.config.get_allowed_labels(), self.output_config)
for cube in props:
conn_graph.add_edges_from_cube_dict(props.get_connectivity_cube(cube), self.config.peer_container)
return conn_graph.get_connections_without_fw_rules_txt_format(connectivity_restriction)

def fw_rules_from_connections_dict(self, connections, peers_to_compare, connectivity_restriction=None):
"""
:param dict connections: the connections' dict (map from connection-set to peer pairs)
Expand Down
14 changes: 10 additions & 4 deletions nca/NetworkConfig/NetworkConfigQueryRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from nca.Resources.NetworkPolicy import NetworkPolicy
from .NetworkConfig import NetworkConfig
from . import NetworkConfigQuery
from nca.Utils.ExplTracker import ExplTracker


@dataclass
Expand Down Expand Up @@ -40,9 +41,9 @@ def compute_final_results(self, output_format):
extracts the final query results from self variables
from self.query_iterations_output computes the final str output of the query,
other results returned as is from query_result.
:param str output_format: the output format to form the final output
if output format is json, dumps the output list into one-top-leveled string
if output format is yaml, dumps the output list into str of a list of yaml objects
:param str output_format: the output format to form the final output.
if output format is json, dumps the output list into one-top-leveled string.
if output format is yaml, dumps the output list into str of a list of yaml objects.
otherwise, writes the output list items split by \n
:return the results: numerical result, output - str , num of not executed
:rtype: int, str, int
Expand Down Expand Up @@ -169,7 +170,12 @@ def _run_query_for_each_config(self):
query_result = QueryResult()
for config in self.configs_array:
query_result.update(self._execute_one_config_query(self.query_name, self._get_config(config)))
return query_result.compute_final_results(self.output_configuration.outputFormat)
expl_out = ''
if ExplTracker().is_active() and self.output_configuration.explain and \
ExplTracker().is_output_format_supported(self.output_configuration.outputFormat):
expl_out = '\n\nExplainability results:\n'+ExplTracker().explain(self.output_configuration.explain.split(','))
numerical_result, output, num_not_executed = query_result.compute_final_results(self.output_configuration.outputFormat)
return numerical_result, output + expl_out, num_not_executed

def _run_query_on_configs_vs_base_config(self, cmd_line_flag):
query_result = QueryResult()
Expand Down
Loading

0 comments on commit 0efbbe6

Please sign in to comment.