illumio-pylo 0.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- illumio_pylo/API/APIConnector.py +1308 -0
- illumio_pylo/API/AuditLog.py +42 -0
- illumio_pylo/API/ClusterHealth.py +136 -0
- illumio_pylo/API/CredentialsManager.py +286 -0
- illumio_pylo/API/Explorer.py +1077 -0
- illumio_pylo/API/JsonPayloadTypes.py +240 -0
- illumio_pylo/API/RuleSearchQuery.py +128 -0
- illumio_pylo/API/__init__.py +0 -0
- illumio_pylo/AgentStore.py +139 -0
- illumio_pylo/Exception.py +44 -0
- illumio_pylo/Helpers/__init__.py +3 -0
- illumio_pylo/Helpers/exports.py +508 -0
- illumio_pylo/Helpers/functions.py +166 -0
- illumio_pylo/IPList.py +135 -0
- illumio_pylo/IPMap.py +285 -0
- illumio_pylo/Label.py +25 -0
- illumio_pylo/LabelCommon.py +48 -0
- illumio_pylo/LabelGroup.py +68 -0
- illumio_pylo/LabelStore.py +403 -0
- illumio_pylo/LabeledObject.py +25 -0
- illumio_pylo/Organization.py +258 -0
- illumio_pylo/Query.py +331 -0
- illumio_pylo/ReferenceTracker.py +41 -0
- illumio_pylo/Rule.py +671 -0
- illumio_pylo/Ruleset.py +306 -0
- illumio_pylo/RulesetStore.py +101 -0
- illumio_pylo/SecurityPrincipal.py +62 -0
- illumio_pylo/Service.py +256 -0
- illumio_pylo/SoftwareVersion.py +125 -0
- illumio_pylo/VirtualService.py +17 -0
- illumio_pylo/VirtualServiceStore.py +75 -0
- illumio_pylo/Workload.py +506 -0
- illumio_pylo/WorkloadStore.py +289 -0
- illumio_pylo/__init__.py +82 -0
- illumio_pylo/cli/NativeParsers.py +96 -0
- illumio_pylo/cli/__init__.py +134 -0
- illumio_pylo/cli/__main__.py +10 -0
- illumio_pylo/cli/commands/__init__.py +32 -0
- illumio_pylo/cli/commands/credential_manager.py +168 -0
- illumio_pylo/cli/commands/iplist_import_from_file.py +185 -0
- illumio_pylo/cli/commands/misc.py +7 -0
- illumio_pylo/cli/commands/ruleset_export.py +129 -0
- illumio_pylo/cli/commands/update_pce_objects_cache.py +44 -0
- illumio_pylo/cli/commands/ven_duplicate_remover.py +366 -0
- illumio_pylo/cli/commands/ven_idle_to_visibility.py +287 -0
- illumio_pylo/cli/commands/ven_upgrader.py +226 -0
- illumio_pylo/cli/commands/workload_export.py +251 -0
- illumio_pylo/cli/commands/workload_import.py +423 -0
- illumio_pylo/cli/commands/workload_relabeler.py +510 -0
- illumio_pylo/cli/commands/workload_reset_names_to_null.py +83 -0
- illumio_pylo/cli/commands/workload_used_in_rule_finder.py +80 -0
- illumio_pylo/docs/Doxygen +1757 -0
- illumio_pylo/tmp.py +104 -0
- illumio_pylo/utilities/__init__.py +0 -0
- illumio_pylo/utilities/cli.py +10 -0
- illumio_pylo/utilities/credentials.example.json +20 -0
- illumio_pylo/utilities/explorer_report_exporter.py +86 -0
- illumio_pylo/utilities/health_monitoring.py +102 -0
- illumio_pylo/utilities/iplist_analyzer.py +148 -0
- illumio_pylo/utilities/iplists_stats_duplicates_unused_finder.py +75 -0
- illumio_pylo/utilities/resources/iplists-import-example.csv +3 -0
- illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
- illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +3 -0
- illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
- illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
- illumio_pylo/utilities/ven_compatibility_report_export.py +240 -0
- illumio_pylo/utilities/ven_idle_to_illumination.py +344 -0
- illumio_pylo/utilities/ven_reassign_pce.py +183 -0
- illumio_pylo-0.2.5.dist-info/LICENSE +176 -0
- illumio_pylo-0.2.5.dist-info/METADATA +197 -0
- illumio_pylo-0.2.5.dist-info/RECORD +73 -0
- illumio_pylo-0.2.5.dist-info/WHEEL +5 -0
- illumio_pylo-0.2.5.dist-info/top_level.txt +1 -0
illumio_pylo/tmp.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import illumio_pylo as pylo
|
|
3
|
+
|
|
4
|
+
log = logging.getLogger('Pylo')
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def init_logger():
|
|
8
|
+
console_logger = logging.StreamHandler()
|
|
9
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
10
|
+
console_logger.setFormatter(formatter)
|
|
11
|
+
log.addHandler(console_logger)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
init_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def log_set_debug():
|
|
18
|
+
log.setLevel(logging.DEBUG)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def log_set_info():
|
|
22
|
+
log.setLevel(logging.INFO)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def log_set_warning():
|
|
26
|
+
log.setLevel(logging.WARNING)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def get_logger():
|
|
30
|
+
return log
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def find_connector_or_die(obj):
|
|
34
|
+
connector = obj.__dict__.get('connector') # type: pylo.APIConnector
|
|
35
|
+
if connector is None:
|
|
36
|
+
owner = obj.__dict__.get('owner')
|
|
37
|
+
if owner is None:
|
|
38
|
+
raise Exception("Could not find a Connector object")
|
|
39
|
+
return find_connector_or_die(owner)
|
|
40
|
+
|
|
41
|
+
return connector
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class IDTranslationTable:
|
|
45
|
+
"""docstring fo ID_TranslationTable."""
|
|
46
|
+
|
|
47
|
+
def __init__(self):
|
|
48
|
+
self.OldToNew = {}
|
|
49
|
+
self.NewToOld = {}
|
|
50
|
+
|
|
51
|
+
self.sourcesSorting = {}
|
|
52
|
+
self.destSorting = {}
|
|
53
|
+
|
|
54
|
+
def add_source(self, key, value):
|
|
55
|
+
if key in self.sourcesSorting:
|
|
56
|
+
raise Exception("Duplicate key '%s'" % key)
|
|
57
|
+
self.sourcesSorting[key] = value
|
|
58
|
+
|
|
59
|
+
find = self.destSorting.get(key)
|
|
60
|
+
if find is None:
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
self.OldToNew[value] = find
|
|
64
|
+
self.NewToOld[find] = value
|
|
65
|
+
|
|
66
|
+
def add_destination(self, key, value):
|
|
67
|
+
if key in self.destSorting:
|
|
68
|
+
raise Exception("Duplicate key '%s'" % key)
|
|
69
|
+
self.destSorting[key] = value
|
|
70
|
+
|
|
71
|
+
find = self.sourcesSorting.get(key)
|
|
72
|
+
if find is None:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
self.OldToNew[find] = value
|
|
76
|
+
self.NewToOld[value] = find
|
|
77
|
+
|
|
78
|
+
def find_new(self, old):
|
|
79
|
+
return self.OldToNew.get(old)
|
|
80
|
+
|
|
81
|
+
def find_new_or_die(self, old):
|
|
82
|
+
ret = self.OldToNew.get(old)
|
|
83
|
+
if ret is None:
|
|
84
|
+
raise Exception("Cannot find a match in the table for key '{}'".format(old))
|
|
85
|
+
return ret
|
|
86
|
+
|
|
87
|
+
def find_old(self, new):
|
|
88
|
+
return self.NewToOld.get(new)
|
|
89
|
+
|
|
90
|
+
def find_old_or_die(self, new):
|
|
91
|
+
ret = self.NewToOld.get(new)
|
|
92
|
+
if ret is None:
|
|
93
|
+
raise Exception("Cannot find a match in the table for key {]".format(new))
|
|
94
|
+
return ret
|
|
95
|
+
|
|
96
|
+
def stats_to_str(self, padding = ''):
|
|
97
|
+
msg = '{}source entries:{}\n{}destination entries:{}\n{}translation entries:{}'.\
|
|
98
|
+
format( padding, len(self.sourcesSorting),
|
|
99
|
+
padding, len(self.destSorting),
|
|
100
|
+
padding, len(self.NewToOld))
|
|
101
|
+
return msg
|
|
102
|
+
|
|
103
|
+
def keys_old(self):
|
|
104
|
+
return
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# this is here only for the convenience of building binaries
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
# in case user wants to run this utility while having a version of pylo already installed
|
|
7
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
|
|
8
|
+
import illumio_pylo.cli
|
|
9
|
+
|
|
10
|
+
illumio_pylo.cli.run()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "prod",
|
|
4
|
+
"hostname": "pce-prod.company.com",
|
|
5
|
+
"port": 9443,
|
|
6
|
+
"api_user": "apiuser_xxxxx",
|
|
7
|
+
"api_key": "xxxxxxxx",
|
|
8
|
+
"org_id": 1,
|
|
9
|
+
"verify_ssl": true
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "dev",
|
|
13
|
+
"hostname": "pce-dev.company.com",
|
|
14
|
+
"port": 8443,
|
|
15
|
+
"api_user": "apiuser_xxxxx",
|
|
16
|
+
"api_key": "xxxxxxxx",
|
|
17
|
+
"org_id": 3,
|
|
18
|
+
"verify_ssl": false
|
|
19
|
+
}
|
|
20
|
+
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
import math
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
|
|
8
|
+
import illumio_pylo as pylo
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# <editor-fold desc="Argparse stuff">
|
|
12
|
+
parser = argparse.ArgumentParser(description='TODO LATER', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
13
|
+
parser.add_argument('--pce', type=str, required=True,
|
|
14
|
+
help='hostname of the PCE')
|
|
15
|
+
parser.add_argument('--debug', '-d', action='store_true',
|
|
16
|
+
help='extra debugging messages for developers')
|
|
17
|
+
|
|
18
|
+
parser.add_argument('--consumer-labels', '-cl', type=str, nargs='+', required=False, default=False,
|
|
19
|
+
help='extra debugging messages for developers')
|
|
20
|
+
# </editor-fold>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
args = vars(parser.parse_args())
|
|
24
|
+
|
|
25
|
+
if args['debug']:
|
|
26
|
+
pylo.log_set_debug()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
hostname = args['pce']
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
now = datetime.now()
|
|
33
|
+
report_file = 'explorer-results_{}.csv'.format(now.strftime("%Y%m%d-%H%M%S"))
|
|
34
|
+
report_file_excel = 'explorer-results_{}.xlsx'.format(now.strftime("%Y%m%d-%H%M%S"))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
csv_report_headers = ['name', 'hostname', 'role', 'app', 'env', 'loc', 'href']
|
|
38
|
+
csv_report = pylo.ArrayToExport(csv_report_headers)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# <editor-fold desc="PCE Configuration Download and Parsing">
|
|
42
|
+
org = pylo.Organization(1)
|
|
43
|
+
fake_config = pylo.Organization.create_fake_empty_config()
|
|
44
|
+
|
|
45
|
+
print(" * Looking for credentials for PCE '{}'... ".format(hostname), end="", flush=True)
|
|
46
|
+
connector = pylo.APIConnector.create_from_credentials_in_file(hostname, request_if_missing=True)
|
|
47
|
+
print("OK!")
|
|
48
|
+
|
|
49
|
+
print(" * Downloading Labels listing from the PCE... ", end="", flush=True)
|
|
50
|
+
fake_config['labels'] = connector.objects_label_get()
|
|
51
|
+
print("OK!")
|
|
52
|
+
|
|
53
|
+
print(" * Parsing PCE data ... ", end="", flush=True)
|
|
54
|
+
org.pce_version = connector.version
|
|
55
|
+
org.connector = connector
|
|
56
|
+
org.load_from_json(fake_config)
|
|
57
|
+
print("OK!")
|
|
58
|
+
|
|
59
|
+
# </editor-fold>
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
print(" - Now building query parameters:")
|
|
63
|
+
if args['consumer_labels'] is not False:
|
|
64
|
+
print(" - Consumer labels were provided:")
|
|
65
|
+
else:
|
|
66
|
+
print(" - No Consumer label provided")
|
|
67
|
+
|
|
68
|
+
explorer_filters = connector.ExplorerFilterSetV1(max_results=2)
|
|
69
|
+
|
|
70
|
+
print(" - Querying PCE...", end='', flush=True)
|
|
71
|
+
search_results = connector.explorer_search(explorer_filters)
|
|
72
|
+
print(" OK!")
|
|
73
|
+
print(pylo.nice_json(search_results))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
print()
|
|
77
|
+
print(" * Writing report file '{}' ... ".format(report_file), end='', flush=True)
|
|
78
|
+
csv_report.write_to_csv(report_file)
|
|
79
|
+
print("DONE")
|
|
80
|
+
print(" * Writing report file '{}' ... ".format(report_file_excel), end='', flush=True)
|
|
81
|
+
csv_report.write_to_excel(report_file_excel)
|
|
82
|
+
print("DONE")
|
|
83
|
+
|
|
84
|
+
if csv_report.lines_count() < 1:
|
|
85
|
+
print("\n** WARNING: no entry matched your filters so reports are empty !\n")
|
|
86
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
import math
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
|
|
8
|
+
import illumio_pylo as pylo
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# <editor-fold desc="Argparse stuff">
|
|
12
|
+
parser = argparse.ArgumentParser(description='TODO LATER', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
13
|
+
parser.add_argument('--pce', type=str, required=True,
|
|
14
|
+
help='hostname of the PCE')
|
|
15
|
+
parser.add_argument('--pick-report-hostname', '-p', type=str, required=False, default=None,
|
|
16
|
+
help='if script cannot guess which PCE hostname you were looking for, use this option to force it')
|
|
17
|
+
parser.add_argument('--debug', action='store_true',
|
|
18
|
+
help='extra debugging messages for developers')
|
|
19
|
+
# </editor-fold>
|
|
20
|
+
|
|
21
|
+
args = vars(parser.parse_args())
|
|
22
|
+
|
|
23
|
+
if args['debug']:
|
|
24
|
+
pylo.log_set_debug()
|
|
25
|
+
|
|
26
|
+
hostname = args['pce']
|
|
27
|
+
|
|
28
|
+
pylo.log.debug(" * Looking for credentials for PCE '{}'... ".format(hostname))
|
|
29
|
+
connector = pylo.APIConnector.create_from_credentials_in_file(hostname, request_if_missing=True)
|
|
30
|
+
pylo.log.debug("OK!")
|
|
31
|
+
|
|
32
|
+
pylo.log.debug(" * Getting cluster health details... ")
|
|
33
|
+
health_collection = connector.cluster_health_get(return_object=True)
|
|
34
|
+
pylo.log.debug("OK!")
|
|
35
|
+
|
|
36
|
+
picked_hostname = connector.hostname
|
|
37
|
+
if args['pick_report_hostname'] is not None:
|
|
38
|
+
picked_hostname = args['pick_report_hostname']
|
|
39
|
+
|
|
40
|
+
health_data = health_collection.get(picked_hostname)
|
|
41
|
+
|
|
42
|
+
if health_data is None:
|
|
43
|
+
pylo.log.error("No report for hostname '{}' was found in the collection! The following were available: {}.\n"
|
|
44
|
+
"You can use --pick-report-hostname to force usage of specific one.".format(picked_hostname, pylo.string_list_to_text(health_collection.keys())))
|
|
45
|
+
sys.exit(1)
|
|
46
|
+
|
|
47
|
+
pylo.log.debug("Status details:\n{}\n".format(health_data.to_string()))
|
|
48
|
+
|
|
49
|
+
warning_messages = []
|
|
50
|
+
error_messages = []
|
|
51
|
+
|
|
52
|
+
if health_data.status_is_warning():
|
|
53
|
+
warning_messages.append("Cluster has reported global 'warning' status read the entire report or issues troubleshooting command to get more details")
|
|
54
|
+
elif health_data.status_is_error():
|
|
55
|
+
warning_messages.append("Cluster has reported global 'error' status read the entire report or issues troubleshooting command to get more details")
|
|
56
|
+
|
|
57
|
+
broken_nodes = {}
|
|
58
|
+
working_nodes = {}
|
|
59
|
+
|
|
60
|
+
for node in health_data.nodes_dict.values():
|
|
61
|
+
if node.is_offline_or_unreachable():
|
|
62
|
+
broken_nodes[node] = node
|
|
63
|
+
warning_messages.append("Node {}/{}/IP:{} is offline or not reachable by other members".format(node.name, node.type, node.ip_address))
|
|
64
|
+
else:
|
|
65
|
+
working_nodes[node] = node
|
|
66
|
+
|
|
67
|
+
for node in working_nodes.values():
|
|
68
|
+
troubled_services = node.get_troubled_services()
|
|
69
|
+
if len(troubled_services) > 0:
|
|
70
|
+
broken_nodes[node] = node
|
|
71
|
+
warning_messages.append("Node '{}'/{}/IP:{} has several non-functional services: {}".format(node.name, node.type, node.ip_address, pylo.string_list_to_text(troubled_services)))
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
data1_is_broken = False
|
|
75
|
+
data0_is_broken = False
|
|
76
|
+
for node in broken_nodes:
|
|
77
|
+
if node.type == 'data0':
|
|
78
|
+
data0_is_broken = True
|
|
79
|
+
if node.type == 'data1':
|
|
80
|
+
data1_is_broken = True
|
|
81
|
+
|
|
82
|
+
if data1_is_broken or data0_is_broken:
|
|
83
|
+
error_messages.append("Data1 or Data0 is down so Database has no resiliency anymore, please fix this situation as soon as possible.")
|
|
84
|
+
|
|
85
|
+
report = {'warning_messages': warning_messages, 'error_messages': error_messages}
|
|
86
|
+
|
|
87
|
+
if len(error_messages) > 0:
|
|
88
|
+
report['general_status'] = "error"
|
|
89
|
+
exit_code = 1
|
|
90
|
+
elif len(warning_messages) > 0:
|
|
91
|
+
report['general_status'] = "warning"
|
|
92
|
+
exit_code = 2
|
|
93
|
+
else:
|
|
94
|
+
report['general_status'] = "normal"
|
|
95
|
+
exit_code = 0
|
|
96
|
+
|
|
97
|
+
print("{}".format(pylo.nice_json(report)))
|
|
98
|
+
|
|
99
|
+
exit(exit_code)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
import math
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Dict, List, Any
|
|
7
|
+
|
|
8
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
|
|
9
|
+
import illumio_pylo as pylo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# <editor-fold desc="Argparse stuff">
|
|
13
|
+
parser = argparse.ArgumentParser(description='TODO LATER', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
14
|
+
parser.add_argument('--pce', type=str, required=True,
|
|
15
|
+
help='hostname of the PCE')
|
|
16
|
+
parser.add_argument('--dev-use-cache', type=bool, nargs='?', required=False, default=False, const=True,
|
|
17
|
+
help='For developers only')
|
|
18
|
+
parser.add_argument('--debug', '-d', type=bool, nargs='?', required=False, default=False, const=True,
|
|
19
|
+
help='extra debugging messages for developers')
|
|
20
|
+
parser.add_argument('--verbose', '-v', action='store_true',
|
|
21
|
+
help='')
|
|
22
|
+
|
|
23
|
+
# </editor-fold>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
args = vars(parser.parse_args())
|
|
27
|
+
|
|
28
|
+
if args['debug']:
|
|
29
|
+
pylo.log_set_debug()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
hostname = args['pce']
|
|
33
|
+
verbose = args['verbose']
|
|
34
|
+
use_cached_config = args['dev_use_cache']
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
now = datetime.now()
|
|
38
|
+
report_file = 'iplist-analyzer_{}.csv'.format(now.strftime("%Y%m%d-%H%M%S"))
|
|
39
|
+
report_file_excel = 'iplist-analyzer_{}.xlsx'.format(now.strftime("%Y%m%d-%H%M%S"))
|
|
40
|
+
|
|
41
|
+
filter_csv_expected_fields = []
|
|
42
|
+
filter_data = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
csv_report_headers = ['name', 'members', 'ip4_mapping', 'ip4_count', 'ip4_uncovered_count', 'covered_workloads_count',
|
|
46
|
+
'covered_workloads_list', 'covered_workloads_appgroups', 'href']
|
|
47
|
+
|
|
48
|
+
csv_report = pylo.ArrayToExport(csv_report_headers)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# <editor-fold desc="PCE Configuration Download and Parsing">
|
|
52
|
+
org = pylo.Organization(1)
|
|
53
|
+
if use_cached_config:
|
|
54
|
+
print(" * Loading cached PCE data from disk...")
|
|
55
|
+
org.load_from_cache_or_saved_credentials(hostname)
|
|
56
|
+
print("OK!")
|
|
57
|
+
else:
|
|
58
|
+
print(" * Looking for credentials for PCE '{}'... ".format(hostname), end="", flush=True)
|
|
59
|
+
connector = pylo.APIConnector.create_from_credentials_in_file(hostname, request_if_missing=True)
|
|
60
|
+
print("OK!")
|
|
61
|
+
|
|
62
|
+
print(" * Downloading objects data from the PCE... ", end="", flush=True)
|
|
63
|
+
config = connector.get_pce_objects()
|
|
64
|
+
print("OK!")
|
|
65
|
+
|
|
66
|
+
print(" * Parsing PCE objects data ... ", end="", flush=True)
|
|
67
|
+
org.pce_version = connector.version
|
|
68
|
+
org.connector = connector
|
|
69
|
+
org.load_from_json(config)
|
|
70
|
+
print("OK!")
|
|
71
|
+
|
|
72
|
+
print(" * PCE data statistics:\n{}".format(org.stats_to_str(padding=' ')))
|
|
73
|
+
# </editor-fold>
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def add_iplist_to_report(iplist: pylo.IPList):
|
|
77
|
+
|
|
78
|
+
appgroup_tracker: Dict[str, bool] = {}
|
|
79
|
+
|
|
80
|
+
print(" - {}/{}".format(iplist.name, iplist.href))
|
|
81
|
+
|
|
82
|
+
ip_map = iplist.get_ip4map()
|
|
83
|
+
#print(ip_map.print_to_std(padding=" "))
|
|
84
|
+
|
|
85
|
+
new_row = {
|
|
86
|
+
'name': iplist.name,
|
|
87
|
+
'href': iplist.href,
|
|
88
|
+
'members': iplist.get_raw_entries_as_string_list(separator="\n"),
|
|
89
|
+
'ip4_mapping': ip_map.to_string_list(),
|
|
90
|
+
'ip4_count': ip_map.count_ips()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
matched_workloads: List[pylo.Workload] = []
|
|
94
|
+
|
|
95
|
+
for workload, wkl_map in workloads_ip4maps_cache.items():
|
|
96
|
+
affected_rows = ip_map.substract(wkl_map)
|
|
97
|
+
if affected_rows > 0:
|
|
98
|
+
print("matched workload {}".format(workload.get_name()))
|
|
99
|
+
matched_workloads.append(workload)
|
|
100
|
+
appgroup_tracker[workload.get_appgroup_str()] = True
|
|
101
|
+
#print(ip_map.print_to_std(header="after substraction", padding=" "))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
new_row['ip4_uncovered_count'] = ip_map.count_ips()
|
|
105
|
+
new_row['covered_workloads_count'] = len(matched_workloads)
|
|
106
|
+
new_row['covered_workloads_list'] = pylo.string_list_to_text(matched_workloads, "\n")
|
|
107
|
+
new_row['covered_workloads_appgroups'] = pylo.string_list_to_text(appgroup_tracker.keys(), "\n")
|
|
108
|
+
|
|
109
|
+
csv_report.add_line_from_object(new_row)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# <editor-fold desc="Building Workloads ip4 Cache">
|
|
113
|
+
workloads_ip4maps_cache: Dict[pylo.Workload, pylo.IP4Map] = {}
|
|
114
|
+
print(" * Building Workloads IP4 mapping... ", end='')
|
|
115
|
+
for workload in org.WorkloadStore.get_managed_workloads_list():
|
|
116
|
+
ip_map = workload.get_ip4map_from_interfaces()
|
|
117
|
+
workloads_ip4maps_cache[workload] = ip_map
|
|
118
|
+
print("OK")
|
|
119
|
+
# </editor-fold>
|
|
120
|
+
|
|
121
|
+
# <editor-fold desc="Building IPLists ip4 Cache">
|
|
122
|
+
iplists_ip4maps_cache: Dict[pylo.IPList, pylo.IP4Map] = {}
|
|
123
|
+
print(" * Building IPLists IP4 mapping... ", end='')
|
|
124
|
+
for iplist in org.IPListStore.items_by_href.values():
|
|
125
|
+
ip_map = iplist.get_ip4map()
|
|
126
|
+
iplists_ip4maps_cache[iplist] = ip_map
|
|
127
|
+
print("OK")
|
|
128
|
+
# </editor-fold>
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
print(" * Now analyzing IPLists:", flush=True)
|
|
132
|
+
for (iplist, ip_map) in iplists_ip4maps_cache.items():
|
|
133
|
+
add_iplist_to_report(iplist)
|
|
134
|
+
|
|
135
|
+
print(" ** DONE **")
|
|
136
|
+
|
|
137
|
+
print()
|
|
138
|
+
print(" * Writing report file '{}' ... ".format(report_file), end='', flush=True)
|
|
139
|
+
csv_report.write_to_csv(report_file)
|
|
140
|
+
print("DONE")
|
|
141
|
+
print(" * Writing report file '{}' ... ".format(report_file_excel), end='', flush=True)
|
|
142
|
+
csv_report.write_to_excel(report_file_excel)
|
|
143
|
+
print("DONE")
|
|
144
|
+
|
|
145
|
+
if csv_report.lines_count() < 1:
|
|
146
|
+
print("\n** WARNING: no entry matched your filters so reports are empty !\n")
|
|
147
|
+
|
|
148
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
|
|
5
|
+
import illumio_pylo as pylo
|
|
6
|
+
import argparse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
parser = argparse.ArgumentParser(description='TODO LATER')
|
|
10
|
+
parser.add_argument('--pce', type=str, required=True,
|
|
11
|
+
help='hostname of the PCE')
|
|
12
|
+
|
|
13
|
+
args = vars(parser.parse_args())
|
|
14
|
+
|
|
15
|
+
hostname = args['pce']
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
org = pylo.Organization(1)
|
|
19
|
+
|
|
20
|
+
print("Loading PCE configuration from '{}' or cached file... ".format(hostname), end="", flush=True)
|
|
21
|
+
org.load_from_cache_or_saved_credentials(hostname, prompt_for_api_key_if_missing=True)
|
|
22
|
+
print("OK!\n")
|
|
23
|
+
|
|
24
|
+
unique_hashes = {}
|
|
25
|
+
unique_ipranges = {}
|
|
26
|
+
total_ipranges = 0
|
|
27
|
+
unused_iplists = []
|
|
28
|
+
|
|
29
|
+
for iplist in org.IPListStore.items_by_href.values():
|
|
30
|
+
#print("- handling of iplist '{}' with {} members".format(iplist.name, iplist.count_entries()))
|
|
31
|
+
entries_hash = ""
|
|
32
|
+
for entry in sorted(iplist.raw_entries):
|
|
33
|
+
total_ipranges += 1
|
|
34
|
+
|
|
35
|
+
entries_hash += entry + ' '
|
|
36
|
+
if entry not in unique_ipranges:
|
|
37
|
+
unique_ipranges[entry] = [iplist]
|
|
38
|
+
else:
|
|
39
|
+
unique_ipranges[entry].append(iplist)
|
|
40
|
+
|
|
41
|
+
#print(" - hash: {}".format(entries_hash))
|
|
42
|
+
|
|
43
|
+
if entries_hash in unique_hashes:
|
|
44
|
+
unique_hashes[entries_hash].append(iplist)
|
|
45
|
+
else:
|
|
46
|
+
unique_hashes[entries_hash] = [iplist]
|
|
47
|
+
|
|
48
|
+
if iplist.count_references() == 0:
|
|
49
|
+
unused_iplists.append(iplist)
|
|
50
|
+
|
|
51
|
+
#print(pylo.nice_json(iplist.raw_json))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
print("*** Listing Unused IPLists ***")
|
|
55
|
+
for iplist in unused_iplists:
|
|
56
|
+
print(" - '{}' HREF:{}".format(iplist.name, iplist.href))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
print("*** Listing Duplicate IPLists ***")
|
|
60
|
+
for hash in unique_hashes:
|
|
61
|
+
if len(unique_hashes[hash]) <= 1:
|
|
62
|
+
continue
|
|
63
|
+
print(" - hash {}'".format(hash))
|
|
64
|
+
for iplist in unique_hashes[hash]:
|
|
65
|
+
print(" - {} HREF:{}".format(iplist.name, iplist.href))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
print("\nIPlist count: {}\nUnique iplists: {}\nIPRanges count: {}\nUnique IPRanges: {}".format(org.IPListStore.count(),
|
|
69
|
+
len(unique_hashes),
|
|
70
|
+
total_ipranges,
|
|
71
|
+
len(unique_ipranges)
|
|
72
|
+
))
|
|
73
|
+
print("Unused IPlists: {}".format(len(unused_iplists)))
|
|
74
|
+
|
|
75
|
+
print("\nGeneric Config statistics:\n{}".format(org.stats_to_str()))
|
|
Binary file
|
|
Binary file
|