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
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from typing import Dict, List, Any
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
import illumio_pylo as pylo
|
|
5
|
+
from .misc import make_filename_with_timestamp
|
|
6
|
+
from . import Command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
command_name = 'ven-upgrade'
|
|
10
|
+
objects_load_filter = ['workloads', 'labels']
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fill_parser(parser: argparse.ArgumentParser):
|
|
14
|
+
parser.add_argument('--filter-env-label', type=str, required=False, default=None,
|
|
15
|
+
help='Filter agents by environment labels (separated by commas)')
|
|
16
|
+
parser.add_argument('--filter-loc-label', type=str, required=False, default=None,
|
|
17
|
+
help='Filter agents by location labels (separated by commas)')
|
|
18
|
+
parser.add_argument('--filter-app-label', type=str, required=False, default=None,
|
|
19
|
+
help='Filter agents by application labels (separated by commas)')
|
|
20
|
+
parser.add_argument('--filter-role-label', type=str, required=False, default=None,
|
|
21
|
+
help='Filter agents by role labels (separated by commas)')
|
|
22
|
+
|
|
23
|
+
parser.add_argument('--filter-ven-versions', nargs='+', type=str, required=False, default=None,
|
|
24
|
+
help='Filter agents by versions (separated by spaces)')
|
|
25
|
+
|
|
26
|
+
parser.add_argument('--filter-on-href-from-file', type=str, required=False, default=None,
|
|
27
|
+
help='Filter agents on workload href found in specific csv file')
|
|
28
|
+
|
|
29
|
+
parser.add_argument('--confirm', action='store_true',
|
|
30
|
+
help='Request upgrade of the Agents')
|
|
31
|
+
|
|
32
|
+
parser.add_argument('--target-version', type=str, required=True,
|
|
33
|
+
help='Request upgrade of the Agents')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def __main(args, org: pylo.Organization, **kwargs):
|
|
37
|
+
settings_href_filter_file = args['filter_on_href_from_file']
|
|
38
|
+
request_upgrades = args['confirm']
|
|
39
|
+
|
|
40
|
+
minimum_supported_version = pylo.SoftwareVersion("18.3.0-0")
|
|
41
|
+
|
|
42
|
+
href_filter_data = None
|
|
43
|
+
if settings_href_filter_file is not None:
|
|
44
|
+
print(" * Loading CSV input file '{}'...".format(settings_href_filter_file), flush=True, end='')
|
|
45
|
+
href_filter_data = pylo.CsvExcelToObject(settings_href_filter_file, expected_headers=[{'name': 'href', 'optional': False}])
|
|
46
|
+
print('OK')
|
|
47
|
+
print(" - CSV has {} columns and {} lines (headers don't count)".format(href_filter_data.count_columns(), href_filter_data.count_lines()), flush=True)
|
|
48
|
+
|
|
49
|
+
print(" * Listing VEN Agents TOTAL count per version:")
|
|
50
|
+
version_count = {}
|
|
51
|
+
for agent in org.AgentStore.items_by_href.values():
|
|
52
|
+
if agent.software_version.version_string in version_count:
|
|
53
|
+
version_count[agent.software_version.version_string] += 1
|
|
54
|
+
else:
|
|
55
|
+
version_count[agent.software_version.version_string] = 1
|
|
56
|
+
|
|
57
|
+
for version_string in sorted(version_count.keys()):
|
|
58
|
+
count = version_count[version_string]
|
|
59
|
+
if minimum_supported_version.is_greater_than(pylo.SoftwareVersion(version_string)):
|
|
60
|
+
print(" - {}: {} *NOT SUPPORTED*".format(version_string.ljust(12, ' '), count))
|
|
61
|
+
else:
|
|
62
|
+
print(" - {}: {}".format(version_string.ljust(12, ' '), count))
|
|
63
|
+
print(" - TOTAL: {} Agents".format(len(org.AgentStore.items_by_href)))
|
|
64
|
+
|
|
65
|
+
target_version_string = args['target_version']
|
|
66
|
+
print(" * Parsing target version '{}'".format(target_version_string))
|
|
67
|
+
target_version = pylo.SoftwareVersion(target_version_string)
|
|
68
|
+
|
|
69
|
+
print(" * Parsing filters")
|
|
70
|
+
|
|
71
|
+
env_label_list = {}
|
|
72
|
+
if args['filter_env_label'] is not None:
|
|
73
|
+
print(" * Environment Labels specified")
|
|
74
|
+
for raw_label_name in args['filter_env_label'].split(','):
|
|
75
|
+
print(" - label named '{}'".format(raw_label_name), end='', flush=True)
|
|
76
|
+
label = org.LabelStore.find_label_by_name_and_type(raw_label_name, pylo.label_type_env)
|
|
77
|
+
if label is None:
|
|
78
|
+
print("NOT FOUND!")
|
|
79
|
+
raise pylo.PyloEx("Cannot find label named '{}'".format(raw_label_name))
|
|
80
|
+
else:
|
|
81
|
+
print("found")
|
|
82
|
+
env_label_list[label] = label
|
|
83
|
+
|
|
84
|
+
loc_label_list = {}
|
|
85
|
+
if args['filter_loc_label'] is not None:
|
|
86
|
+
print(" * Location Labels specified")
|
|
87
|
+
for raw_label_name in args['filter_loc_label'].split(','):
|
|
88
|
+
print(" - label named '{}' ".format(raw_label_name), end='', flush=True)
|
|
89
|
+
label = org.LabelStore.find_label_by_name_and_type(raw_label_name, pylo.label_type_loc)
|
|
90
|
+
if label is None:
|
|
91
|
+
print("NOT FOUND!")
|
|
92
|
+
raise pylo.PyloEx("Cannot find label named '{}'".format(raw_label_name))
|
|
93
|
+
else:
|
|
94
|
+
print("found")
|
|
95
|
+
loc_label_list[label] = label
|
|
96
|
+
|
|
97
|
+
app_label_list = {}
|
|
98
|
+
if args['filter_app_label'] is not None:
|
|
99
|
+
print(" * Application Labels specified")
|
|
100
|
+
for raw_label_name in args['filter_app_label'].split(','):
|
|
101
|
+
print(" - label named '{}' ".format(raw_label_name), end='', flush=True)
|
|
102
|
+
label = org.LabelStore.find_label_by_name_and_type(raw_label_name, pylo.label_type_app)
|
|
103
|
+
if label is None:
|
|
104
|
+
print("NOT FOUND!")
|
|
105
|
+
raise pylo.PyloEx("Cannot find label named '{}'".format(raw_label_name))
|
|
106
|
+
else:
|
|
107
|
+
print("found")
|
|
108
|
+
app_label_list[label] = label
|
|
109
|
+
|
|
110
|
+
role_label_list = {}
|
|
111
|
+
if args['filter_role_label'] is not None:
|
|
112
|
+
print(" * Role Labels specified")
|
|
113
|
+
for raw_label_name in args['filter_role_label']:
|
|
114
|
+
print(" - label named '{}' ".format(raw_label_name), end='', flush=True)
|
|
115
|
+
label = org.LabelStore.find_label_by_name_and_type(raw_label_name, pylo.label_type_role)
|
|
116
|
+
if label is None:
|
|
117
|
+
print("NOT FOUND!")
|
|
118
|
+
raise pylo.PyloEx("Cannot find label named '{}'".format(raw_label_name))
|
|
119
|
+
else:
|
|
120
|
+
print("found")
|
|
121
|
+
role_label_list[label] = label
|
|
122
|
+
|
|
123
|
+
filter_versions = {}
|
|
124
|
+
if args['filter_ven_versions'] is not None:
|
|
125
|
+
print(" * VEN versions specified")
|
|
126
|
+
for raw_version_name in args['filter_ven_versions']:
|
|
127
|
+
if len(raw_version_name) < 0:
|
|
128
|
+
raise pylo.PyloEx("Unsupported version provided: '{}'".format(raw_version_name))
|
|
129
|
+
parsed_version = pylo.SoftwareVersion(raw_version_name)
|
|
130
|
+
print(" - version '{}' ".format(raw_version_name), end='', flush=True)
|
|
131
|
+
filter_versions[raw_version_name] = parsed_version
|
|
132
|
+
|
|
133
|
+
print(" * Filter out VEN Agents which aren't matching filters:")
|
|
134
|
+
agents = org.AgentStore.items_by_href.copy()
|
|
135
|
+
|
|
136
|
+
for agent_href in list(agents.keys()):
|
|
137
|
+
agent = agents[agent_href]
|
|
138
|
+
workload = agent.workload
|
|
139
|
+
|
|
140
|
+
if href_filter_data is not None:
|
|
141
|
+
workload_href_found = False
|
|
142
|
+
for href_entry in href_filter_data.objects():
|
|
143
|
+
workload_href = href_entry['href']
|
|
144
|
+
if workload_href is not None and workload_href == workload.href:
|
|
145
|
+
workload_href_found = True
|
|
146
|
+
break
|
|
147
|
+
if not workload_href_found:
|
|
148
|
+
pylo.log.debug(" - workload '{}' is not listed the CSV/Excel file".format(workload.get_name()))
|
|
149
|
+
del agents[agent_href]
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
if len(env_label_list) > 0 and (workload.env_label is None or workload.env_label not in env_label_list):
|
|
153
|
+
pylo.log.debug(" - workload '{}' does not match env_label filters, it's out!".format(workload.get_name()))
|
|
154
|
+
del agents[agent_href]
|
|
155
|
+
continue
|
|
156
|
+
if len(loc_label_list) > 0 and (workload.loc_label is None or workload.loc_label not in loc_label_list):
|
|
157
|
+
pylo.log.debug(" - workload '{}' does not match loc_label filters, it's out!".format(workload.get_name()))
|
|
158
|
+
del agents[agent_href]
|
|
159
|
+
continue
|
|
160
|
+
if len(app_label_list) > 0 and (workload.app_label is None or workload.app_label not in app_label_list):
|
|
161
|
+
pylo.log.debug(" - workload '{}' does not match app_label filters, it's out!".format(workload.get_name()))
|
|
162
|
+
del agents[agent_href]
|
|
163
|
+
continue
|
|
164
|
+
if len(role_label_list) > 0 and (workload.role_label is None or workload.role_label not in role_label_list):
|
|
165
|
+
pylo.log.debug(" - workload '{}' does not match role_label filters, it's out!".format(workload.get_name()))
|
|
166
|
+
del agents[agent_href]
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
if agent.software_version.version_string not in filter_versions:
|
|
170
|
+
pylo.log.debug(" - workload '{}' does not match the version filter, it's out!".format(workload.get_name()))
|
|
171
|
+
del agents[agent_href]
|
|
172
|
+
continue
|
|
173
|
+
|
|
174
|
+
# Hiding versions which are higher than the one requested for upgrade
|
|
175
|
+
if agent.software_version > target_version:
|
|
176
|
+
pylo.log.debug(" - workload '{}' has a higher version of VEN ({}) than requested, it's out".format(workload.get_name(), workload.ven_agent.software_version.version_string))
|
|
177
|
+
del agents[agent_href]
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
# Hiding unsupported versions
|
|
181
|
+
if agent.software_version.is_lower_than(minimum_supported_version):
|
|
182
|
+
pylo.log.debug(" - workload '{}' has incompatible version of VEN ({}), it's out".format(workload.get_name(), workload.ven_agent.software_version.version_string))
|
|
183
|
+
del agents[agent_href]
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
print("\n * DONE\n")
|
|
187
|
+
|
|
188
|
+
print(" * Listing VEN Agents FILTERED count per version:")
|
|
189
|
+
version_count = {}
|
|
190
|
+
for agent in agents.values():
|
|
191
|
+
if agent.software_version.version_string in version_count:
|
|
192
|
+
version_count[agent.software_version.version_string] += 1
|
|
193
|
+
else:
|
|
194
|
+
version_count[agent.software_version.version_string] = 1
|
|
195
|
+
|
|
196
|
+
for version_string in sorted(version_count.keys()):
|
|
197
|
+
count = version_count[version_string]
|
|
198
|
+
print(" - {}: {}".format(version_string.ljust(12, ' '), count))
|
|
199
|
+
print(" - TOTAL: {} Agents".format(len(agents)))
|
|
200
|
+
|
|
201
|
+
if args['use_cache']:
|
|
202
|
+
print("\n\n *** SKIPPING Upgrade process as --use-cache option was used!")
|
|
203
|
+
sys.exit(0)
|
|
204
|
+
|
|
205
|
+
if not request_upgrades:
|
|
206
|
+
print("\n\n *** SKIPPING Upgrade process as option '--confirm' was not used")
|
|
207
|
+
sys.exit(0)
|
|
208
|
+
|
|
209
|
+
if len(agents) < 1:
|
|
210
|
+
print("\n\n *** After filtering there is no Agent left for the upgrade process")
|
|
211
|
+
sys.exit(0)
|
|
212
|
+
|
|
213
|
+
print("\n *** Now Requesting Agents Upgrades from the PCE ***")
|
|
214
|
+
agent_count = 0
|
|
215
|
+
for agent in agents.values():
|
|
216
|
+
agent_count += 1
|
|
217
|
+
print(" - Agent #{}/{}: wkl NAME:'{}' HREF:{} Labels:{}".format(agent_count, len(agents), agent.workload.get_name(),
|
|
218
|
+
agent.workload.href,
|
|
219
|
+
agent.workload.get_labels_str())
|
|
220
|
+
)
|
|
221
|
+
org.connector.objects_workload_agent_upgrade(agent.workload.href, target_version_string)
|
|
222
|
+
|
|
223
|
+
print("\n \n** All Agents Upgraded **\n")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
command_object = Command(command_name, __main, fill_parser, objects_load_filter)
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
from typing import List, Dict
|
|
2
|
+
|
|
3
|
+
import illumio_pylo as pylo
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from .misc import make_filename_with_timestamp
|
|
8
|
+
from . import Command
|
|
9
|
+
|
|
10
|
+
command_name = 'workload-export'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExtraColumn:
|
|
14
|
+
class ColumnDescription:
|
|
15
|
+
def __init__(self, name: str, nice_name: str):
|
|
16
|
+
self.name = name
|
|
17
|
+
self.nice_name = nice_name
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
extra_columns.append(self)
|
|
21
|
+
|
|
22
|
+
def column_description(self) -> ColumnDescription:
|
|
23
|
+
raise NotImplementedError()
|
|
24
|
+
|
|
25
|
+
def get_value(self, workload: pylo.Workload, org: pylo.Organization) -> str:
|
|
26
|
+
raise NotImplementedError()
|
|
27
|
+
|
|
28
|
+
def apply_cli_args(self, parser: argparse.ArgumentParser):
|
|
29
|
+
raise NotImplementedError()
|
|
30
|
+
|
|
31
|
+
def post_process_cli_args(self, args: Dict[str, any], org: pylo.Organization):
|
|
32
|
+
raise NotImplementedError()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
extra_columns: List[ExtraColumn] = []
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def fill_parser(parser: argparse.ArgumentParser):
|
|
39
|
+
parser.add_argument('--output', required=False, default='.')
|
|
40
|
+
|
|
41
|
+
parser.add_argument('--verbose', '-v', action='store_true',
|
|
42
|
+
help='')
|
|
43
|
+
|
|
44
|
+
parser.add_argument('--filter-file', '-i', type=str, required=False, default=None,
|
|
45
|
+
help='CSV or Excel input filename')
|
|
46
|
+
parser.add_argument('--filter-file-delimiter', type=str, required=False, default=',',
|
|
47
|
+
help='CSV field delimiter')
|
|
48
|
+
parser.add_argument('--filter-fields', type=str, required=False, default=None, choices=['hostname', 'app', 'ip'], nargs="+",
|
|
49
|
+
help='Fields on which you want to filter on')
|
|
50
|
+
parser.add_argument('--keep-filters-in-report', action='store_true',
|
|
51
|
+
help='If you want to keep filters information in the export file (to do a table joint for example)')
|
|
52
|
+
parser.add_argument('--save-location', type=str, required=False, default='./',
|
|
53
|
+
help='The folder where this script will save generated Excel report')
|
|
54
|
+
parser.add_argument('--csv-output-only', action='store_true',
|
|
55
|
+
help='Generate only the CSV output file, no Excel file')
|
|
56
|
+
parser.add_argument('--excel-output-only', action='store_true',
|
|
57
|
+
help='Generate only the Excel output file, no CSV file')
|
|
58
|
+
|
|
59
|
+
for extra_column in extra_columns:
|
|
60
|
+
extra_column.apply_cli_args(parser)
|
|
61
|
+
|
|
62
|
+
def __main(args, org: pylo.Organization, **kwargs):
|
|
63
|
+
|
|
64
|
+
filter_file = args['filter_file']
|
|
65
|
+
filter_file_delimiter = args['filter_file_delimiter']
|
|
66
|
+
filter_fields = args['filter_fields']
|
|
67
|
+
filter_keep_in_report = args['keep_filters_in_report']
|
|
68
|
+
save_location = args['save_location']
|
|
69
|
+
verbose = args['verbose']
|
|
70
|
+
csv_output_only = args['csv_output_only']
|
|
71
|
+
excel_output_only = args['excel_output_only']
|
|
72
|
+
# print(args['filter_fields'])
|
|
73
|
+
|
|
74
|
+
output_file_prefix = make_filename_with_timestamp('workload_export_')
|
|
75
|
+
output_file_csv = save_location + '/' + output_file_prefix + '.csv'
|
|
76
|
+
output_file_excel = save_location + '/' + output_file_prefix + '.xlsx'
|
|
77
|
+
|
|
78
|
+
csv_report_headers = ['name', 'hostname', 'role', 'app', 'env', 'loc', 'online', 'managed',
|
|
79
|
+
'status', 'agent.last_heartbeat', 'agent.sec_policy_sync_state', 'agent.sec_policy_applied_at',
|
|
80
|
+
'href', 'agent.href']
|
|
81
|
+
|
|
82
|
+
for extra_column in extra_columns:
|
|
83
|
+
csv_report_headers.append(extra_column.column_description().name)
|
|
84
|
+
print(" - adding extra column from external plugin: " + extra_column.column_description().name)
|
|
85
|
+
|
|
86
|
+
filter_csv_expected_fields = []
|
|
87
|
+
filter_data = None
|
|
88
|
+
|
|
89
|
+
if filter_file is not None:
|
|
90
|
+
if filter_fields is None:
|
|
91
|
+
pylo.log.error("A filter file was provided but you didn't specify on which fields they should apply")
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
if len(filter_fields) < 1:
|
|
94
|
+
pylo.log.error("A filter file was provided but you specified an empty filter-fields option")
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
for field in filter_fields:
|
|
97
|
+
filter_csv_expected_fields.append({'name': field, 'optional': False})
|
|
98
|
+
|
|
99
|
+
print(" * Loading filterCSV input file '{}'...".format(filter_file), flush=True, end='')
|
|
100
|
+
filter_data = pylo.CsvExcelToObject(filter_file, expected_headers=filter_csv_expected_fields, csv_delimiter=filter_file_delimiter)
|
|
101
|
+
print('OK')
|
|
102
|
+
print(" - CSV has {} columns and {} lines (headers don't count)".format(filter_data.count_columns(), filter_data.count_lines()))
|
|
103
|
+
|
|
104
|
+
if filter_keep_in_report:
|
|
105
|
+
for field in filter_data._detected_headers:
|
|
106
|
+
csv_report_headers.append('_' + field)
|
|
107
|
+
|
|
108
|
+
csv_report = pylo.ArraysToExcel()
|
|
109
|
+
csv_sheet = csv_report.create_sheet('workloads', csv_report_headers, force_all_wrap_text=True)
|
|
110
|
+
|
|
111
|
+
all_workloads = org.WorkloadStore.itemsByHRef.copy()
|
|
112
|
+
used_filters = {}
|
|
113
|
+
|
|
114
|
+
def add_workload_to_report(wkl: pylo.Workload = None, filter=None, filter_append_prefix='_'):
|
|
115
|
+
labels = workload.get_labels_str_list()
|
|
116
|
+
|
|
117
|
+
def none_or_date(date):
|
|
118
|
+
if date is None:
|
|
119
|
+
return None
|
|
120
|
+
return datetime.strftime(date, '%Y-%m-%d %H:%M:%S')
|
|
121
|
+
|
|
122
|
+
if wkl is not None:
|
|
123
|
+
new_row = {
|
|
124
|
+
'name': wkl.forced_name,
|
|
125
|
+
'hostname': wkl.hostname,
|
|
126
|
+
'role': labels[0],
|
|
127
|
+
'app': labels[1],
|
|
128
|
+
'env': labels[2],
|
|
129
|
+
'loc': labels[3],
|
|
130
|
+
'href': wkl.href,
|
|
131
|
+
'online': wkl.online,
|
|
132
|
+
'managed': not wkl.unmanaged,
|
|
133
|
+
'status': wkl.get_status_string(),
|
|
134
|
+
}
|
|
135
|
+
if wkl.ven_agent is not None:
|
|
136
|
+
new_row['agent.href'] = wkl.ven_agent.href
|
|
137
|
+
new_row['agent.sec_policy_sync_state'] = wkl.ven_agent.get_status_security_policy_sync_state()
|
|
138
|
+
new_row['agent.last_heartbeat'] = none_or_date(wkl.ven_agent.get_last_heartbeat_date())
|
|
139
|
+
new_row['agent.sec_policy_applied_at'] = none_or_date(wkl.ven_agent.get_status_security_policy_applied_at())
|
|
140
|
+
|
|
141
|
+
for extra_column in extra_columns:
|
|
142
|
+
new_row[extra_column.column_description().name] = extra_column.get_value(wkl, org)
|
|
143
|
+
else:
|
|
144
|
+
new_row = {}
|
|
145
|
+
|
|
146
|
+
if filter is not None:
|
|
147
|
+
used_filters[filter['*line*']] = True
|
|
148
|
+
for field in filter:
|
|
149
|
+
new_row[filter_append_prefix + field] = filter[field]
|
|
150
|
+
|
|
151
|
+
csv_sheet.add_line_from_object(new_row)
|
|
152
|
+
|
|
153
|
+
print(" * Listing and Filtering ({}) workloads now".format(len(all_workloads)))
|
|
154
|
+
|
|
155
|
+
for workload in all_workloads.values():
|
|
156
|
+
if verbose:
|
|
157
|
+
print(" - Processing Wkl {}|{}".format(workload.hostname, workload.href))
|
|
158
|
+
if filter_data is not None:
|
|
159
|
+
matched_filters = 0
|
|
160
|
+
|
|
161
|
+
for filter_data_row in filter_data.objects():
|
|
162
|
+
# print(" - trying filter : ")
|
|
163
|
+
# print(filter_data_row)
|
|
164
|
+
filter_all_columns_matched = True
|
|
165
|
+
for filter_field_from_csv in filter_data_row:
|
|
166
|
+
if not filter_all_columns_matched:
|
|
167
|
+
break
|
|
168
|
+
|
|
169
|
+
if filter_field_from_csv not in filter_fields:
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
# print(" field filter={} will be evaluated".format(filter_field_from_csv))
|
|
173
|
+
|
|
174
|
+
if filter_field_from_csv not in filter_data_row:
|
|
175
|
+
pylo.log.error("Filter field '{}' not found in CSV file".format(filter_field_from_csv))
|
|
176
|
+
sys.exit(1)
|
|
177
|
+
|
|
178
|
+
current_filter = filter_data_row[filter_field_from_csv]
|
|
179
|
+
if current_filter is None:
|
|
180
|
+
# print(' it was empty!')
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
if filter_field_from_csv == 'hostname':
|
|
184
|
+
hostname_in_csv = pylo.hostname_from_fqdn(current_filter).lower()
|
|
185
|
+
workload_hostname = pylo.hostname_from_fqdn(workload.hostname).lower()
|
|
186
|
+
# print(" : comparing filter entry {} with wkl entry {}".format(hostname_in_csv, workload_hostname))
|
|
187
|
+
if hostname_in_csv != workload_hostname:
|
|
188
|
+
filter_all_columns_matched = False
|
|
189
|
+
break
|
|
190
|
+
elif filter_field_from_csv == 'app':
|
|
191
|
+
if current_filter is None or current_filter == '':
|
|
192
|
+
continue
|
|
193
|
+
else:
|
|
194
|
+
if workload.app_label is None or workload.app_label.name.lower() != current_filter.lower():
|
|
195
|
+
filter_all_columns_matched = False
|
|
196
|
+
break
|
|
197
|
+
elif filter_field_from_csv == 'ip':
|
|
198
|
+
found_ip = False
|
|
199
|
+
for interface in workload.interfaces:
|
|
200
|
+
if current_filter == interface.ip:
|
|
201
|
+
found_ip = True
|
|
202
|
+
break
|
|
203
|
+
if not found_ip:
|
|
204
|
+
filter_all_columns_matched = False
|
|
205
|
+
break
|
|
206
|
+
else:
|
|
207
|
+
# we don't support this filter type so we exit with an error
|
|
208
|
+
pylo.log.error("Filter field '{}' is not supported".format(filter_field_from_csv))
|
|
209
|
+
sys.exit(1)
|
|
210
|
+
|
|
211
|
+
if filter_all_columns_matched:
|
|
212
|
+
add_workload_to_report(workload, filter_data_row)
|
|
213
|
+
matched_filters += 1
|
|
214
|
+
|
|
215
|
+
if matched_filters > 0:
|
|
216
|
+
if verbose:
|
|
217
|
+
print(" - matched {} filters".format(matched_filters))
|
|
218
|
+
|
|
219
|
+
else:
|
|
220
|
+
add_workload_to_report(workload)
|
|
221
|
+
|
|
222
|
+
print(" ** All workloads have been processed, {} were added in the report".format(csv_sheet.lines_count()))
|
|
223
|
+
|
|
224
|
+
if filter_keep_in_report:
|
|
225
|
+
print(" * Adding unmatched filters back into the report as request...", flush=True, end='')
|
|
226
|
+
count_unused_filters = 0
|
|
227
|
+
for filter_data_row in filter_data.objects():
|
|
228
|
+
if filter_data_row['*line*'] not in used_filters:
|
|
229
|
+
count_unused_filters += 1
|
|
230
|
+
add_workload_to_report(wkl=None, filter=filter_data_row)
|
|
231
|
+
print(" DONE! ({} found)".format(count_unused_filters))
|
|
232
|
+
|
|
233
|
+
print()
|
|
234
|
+
print(" * Writing report file '{}' ... ".format(output_file_csv), end='', flush=True)
|
|
235
|
+
if not excel_output_only:
|
|
236
|
+
csv_sheet.write_to_csv(output_file_csv)
|
|
237
|
+
print("DONE")
|
|
238
|
+
else:
|
|
239
|
+
print("SKIPPED (use --csv-output-only to write CSV file or no option for both)")
|
|
240
|
+
print(" * Writing report file '{}' ... ".format(output_file_excel), end='', flush=True)
|
|
241
|
+
if not csv_output_only:
|
|
242
|
+
csv_report.write_to_excel(output_file_excel)
|
|
243
|
+
print("DONE")
|
|
244
|
+
else:
|
|
245
|
+
print("SKIPPED (use --excel-output-only to write Excel file or no option for both)")
|
|
246
|
+
|
|
247
|
+
if csv_sheet.lines_count() < 1:
|
|
248
|
+
print("\n** WARNING: no entry matched your filters so reports are empty !\n")
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
command_object = Command(command_name, __main, fill_parser)
|