illumio-pylo 0.3.7__py3-none-any.whl → 0.3.9__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 +90 -54
- illumio_pylo/API/JsonPayloadTypes.py +10 -0
- illumio_pylo/Helpers/functions.py +8 -13
- illumio_pylo/IPList.py +5 -9
- illumio_pylo/IPMap.py +3 -3
- illumio_pylo/Label.py +0 -1
- illumio_pylo/LabelCommon.py +1 -1
- illumio_pylo/LabelStore.py +24 -25
- illumio_pylo/LabeledObject.py +4 -5
- illumio_pylo/Organization.py +1 -3
- illumio_pylo/ReferenceTracker.py +0 -3
- illumio_pylo/Rule.py +2 -2
- illumio_pylo/Ruleset.py +7 -7
- illumio_pylo/RulesetStore.py +1 -1
- illumio_pylo/SecurityPrincipal.py +0 -5
- illumio_pylo/Workload.py +4 -13
- illumio_pylo/WorkloadStoreSubClasses.py +7 -10
- illumio_pylo/__init__.py +1 -1
- illumio_pylo/cli/__init__.py +0 -2
- illumio_pylo/cli/commands/credential_manager.py +7 -18
- illumio_pylo/cli/commands/iplist_analyzer.py +3 -9
- illumio_pylo/cli/commands/iplist_import_from_file.py +57 -34
- illumio_pylo/cli/commands/ruleset_export.py +16 -20
- illumio_pylo/cli/commands/update_pce_objects_cache.py +0 -1
- illumio_pylo/cli/commands/utils/LabelCreation.py +2 -2
- illumio_pylo/cli/commands/utils/misc.py +3 -2
- illumio_pylo/cli/commands/ven_compatibility_report_export.py +4 -14
- illumio_pylo/cli/commands/ven_duplicate_remover.py +26 -32
- illumio_pylo/cli/commands/ven_idle_to_visibility.py +2 -4
- illumio_pylo/cli/commands/ven_upgrader.py +1 -2
- illumio_pylo/cli/commands/workload_import.py +16 -18
- illumio_pylo/cli/commands/workload_reset_names_to_null.py +12 -14
- illumio_pylo/cli/commands/workload_update.py +28 -32
- illumio_pylo/cli/commands/workload_used_in_rule_finder.py +5 -5
- illumio_pylo/tmp.py +1 -0
- illumio_pylo/utilities/resources/workloads-import-example.csv +1 -1
- illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
- {illumio_pylo-0.3.7.dist-info → illumio_pylo-0.3.9.dist-info}/METADATA +4 -4
- illumio_pylo-0.3.9.dist-info/RECORD +72 -0
- {illumio_pylo-0.3.7.dist-info → illumio_pylo-0.3.9.dist-info}/WHEEL +1 -1
- illumio_pylo-0.3.7.dist-info/RECORD +0 -72
- {illumio_pylo-0.3.7.dist-info → illumio_pylo-0.3.9.dist-info}/LICENSE +0 -0
- {illumio_pylo-0.3.7.dist-info → illumio_pylo-0.3.9.dist-info}/top_level.txt +0 -0
illumio_pylo/Rule.py
CHANGED
|
@@ -264,7 +264,7 @@ class RuleServiceContainer(pylo.Referencer):
|
|
|
264
264
|
self._direct_services: List[DirectServiceInRule] = []
|
|
265
265
|
self._cached_port_map: Optional[PortMap] = None
|
|
266
266
|
|
|
267
|
-
def load_from_json(self, data_list: List[RuleServiceReferenceObjectJsonStructure|RuleDirectServiceReferenceObjectJsonStructure]):
|
|
267
|
+
def load_from_json(self, data_list: List[RuleServiceReferenceObjectJsonStructure | RuleDirectServiceReferenceObjectJsonStructure]):
|
|
268
268
|
ss_store = self.owner.owner.owner.owner.ServiceStore # make it a local variable for fast lookups
|
|
269
269
|
|
|
270
270
|
for data in data_list:
|
|
@@ -312,7 +312,7 @@ class RuleServiceContainer(pylo.Referencer):
|
|
|
312
312
|
|
|
313
313
|
for i in range(0, len(self._direct_services)):
|
|
314
314
|
if self._direct_services[i] is service:
|
|
315
|
-
del
|
|
315
|
+
del self._direct_services[i]
|
|
316
316
|
return True
|
|
317
317
|
return False
|
|
318
318
|
|
illumio_pylo/Ruleset.py
CHANGED
|
@@ -26,10 +26,10 @@ class RulesetScope:
|
|
|
26
26
|
result = ''
|
|
27
27
|
for scope in self.scope_entries.keys():
|
|
28
28
|
if len(result) < 1:
|
|
29
|
-
result += scope.to_string(label_separator,use_href=use_href)
|
|
29
|
+
result += scope.to_string(label_separator, use_href=use_href)
|
|
30
30
|
else:
|
|
31
31
|
result += scope_separator
|
|
32
|
-
result += scope.to_string(label_separator,use_href=use_href)
|
|
32
|
+
result += scope.to_string(label_separator, use_href=use_href)
|
|
33
33
|
|
|
34
34
|
return result
|
|
35
35
|
|
|
@@ -39,6 +39,7 @@ class RulesetScope:
|
|
|
39
39
|
return True
|
|
40
40
|
return False
|
|
41
41
|
|
|
42
|
+
|
|
42
43
|
class RulesetScopeEntry:
|
|
43
44
|
|
|
44
45
|
__slots__ = ['owner', '_labels']
|
|
@@ -48,7 +49,7 @@ class RulesetScopeEntry:
|
|
|
48
49
|
self._labels: Dict[str, Union['pylo.Label', 'pylo.LabelGroup']] = {}
|
|
49
50
|
|
|
50
51
|
def load_from_json(self, data: List[RulesetScopeEntryLineJsonStructure]):
|
|
51
|
-
#log.error(pylo.nice_json(data))
|
|
52
|
+
# log.error(pylo.nice_json(data))
|
|
52
53
|
l_store = self.owner.owner.owner.owner.LabelStore
|
|
53
54
|
for label_json in data:
|
|
54
55
|
label_entry = label_json.get('label')
|
|
@@ -64,7 +65,8 @@ class RulesetScopeEntry:
|
|
|
64
65
|
if label is None:
|
|
65
66
|
raise pylo.PyloEx("Cannot find label with href '{}' in Ruleset '{}' scope: {}".format(href_entry,
|
|
66
67
|
self.owner.owner.name,
|
|
67
|
-
|
|
68
|
+
pylo.nice_json(
|
|
69
|
+
data)))
|
|
68
70
|
|
|
69
71
|
if label.type not in self.owner.owner.owner.owner.LabelStore.label_types_as_set:
|
|
70
72
|
raise pylo.PyloEx("Unsupported label type '{}' named '{}' in scope of ruleset '{}'/'{}'".format(label.type_string(),
|
|
@@ -103,8 +105,7 @@ class RulesetScopeEntry:
|
|
|
103
105
|
"""
|
|
104
106
|
return {label.href: label for label in self._labels.values()}
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
def to_string(self, label_separator = '|', use_href=False):
|
|
108
|
+
def to_string(self, label_separator='|', use_href=False):
|
|
108
109
|
string = ''
|
|
109
110
|
for label_type in self.owner.owner.owner.owner.LabelStore.label_types:
|
|
110
111
|
label = self._labels.get(label_type)
|
|
@@ -192,7 +193,6 @@ class Ruleset:
|
|
|
192
193
|
rules.append(rule)
|
|
193
194
|
return rules
|
|
194
195
|
|
|
195
|
-
|
|
196
196
|
def load_from_json(self, data: RulesetObjectJsonStructure):
|
|
197
197
|
if 'name' not in data:
|
|
198
198
|
raise pylo.PyloEx("Cannot find Ruleset name in JSON data: \n" + pylo.Helpers.nice_json(data))
|
illumio_pylo/RulesetStore.py
CHANGED
|
@@ -26,7 +26,6 @@ class SecurityPrincipal(pylo.ReferenceTracker):
|
|
|
26
26
|
self.deleted = data['deleted']
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
class SecurityPrincipalStore:
|
|
31
30
|
def __init__(self, owner: 'pylo.Organization'):
|
|
32
31
|
self.owner = owner
|
|
@@ -59,7 +58,3 @@ class SecurityPrincipalStore:
|
|
|
59
58
|
|
|
60
59
|
def find_by_href(self, href: str) -> Optional[SecurityPrincipal]:
|
|
61
60
|
return self.itemsByHRef.get(href)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
illumio_pylo/Workload.py
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import Optional, List, Union
|
|
4
3
|
|
|
5
|
-
import illumio_pylo as pylo
|
|
6
4
|
from illumio_pylo.API.JsonPayloadTypes import WorkloadObjectJsonStructure, WorkloadObjectCreateJsonStructure
|
|
7
|
-
from illumio_pylo import log
|
|
8
5
|
from .AgentStore import VENAgent
|
|
9
6
|
from .Helpers import *
|
|
10
7
|
from .Exception import PyloEx
|
|
@@ -43,8 +40,6 @@ class WorkloadApiUpdateStack:
|
|
|
43
40
|
return len(self.json_payload)
|
|
44
41
|
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
43
|
class Workload(pylo.ReferenceTracker, pylo.Referencer, LabeledObject):
|
|
49
44
|
|
|
50
45
|
__slots__ = ['owner', 'name', 'href', 'forced_name', 'hostname', 'description', 'interfaces', 'online', 'os_id',
|
|
@@ -127,10 +122,10 @@ class Workload(pylo.ReferenceTracker, pylo.Referencer, LabeledObject):
|
|
|
127
122
|
self.ven_agent = self.owner.owner.AgentStore.create_ven_agent_from_workload_record(self, agent_json)
|
|
128
123
|
self.online = data['online']
|
|
129
124
|
self.os_id = data.get('os_id')
|
|
130
|
-
#if self.os_id is None:
|
|
125
|
+
# if self.os_id is None:
|
|
131
126
|
# raise PyloEx("Workload named '{}' has no os_id record:\n%s".format(self.name), data)
|
|
132
127
|
self.os_detail = data.get('os_detail')
|
|
133
|
-
#if self.os_detail is None:
|
|
128
|
+
# if self.os_detail is None:
|
|
134
129
|
# raise PyloEx("Workload named '{}' has no os_detail record:\n%s".format(self.name), data)
|
|
135
130
|
|
|
136
131
|
self.description = data.get('description')
|
|
@@ -162,7 +157,7 @@ class Workload(pylo.ReferenceTracker, pylo.Referencer, LabeledObject):
|
|
|
162
157
|
if not self.deleted:
|
|
163
158
|
raise pylo.PyloObjectNotFound(
|
|
164
159
|
"Workload '%s'/'%s' is referencing label href '%s' which does not exist" % (
|
|
165
|
-
|
|
160
|
+
self.name, self.href, href))
|
|
166
161
|
|
|
167
162
|
self.set_label(label_object)
|
|
168
163
|
# print("Workload '%s'/'%s' is referencing label '%s'/'%s'" % (self.name, self.hostname, label_object.type, label_object.name))
|
|
@@ -206,11 +201,9 @@ class Workload(pylo.ReferenceTracker, pylo.Referencer, LabeledObject):
|
|
|
206
201
|
def created_at(self) -> str:
|
|
207
202
|
return self.raw_json['created_at']
|
|
208
203
|
|
|
209
|
-
|
|
210
204
|
def created_at_datetime(self) -> datetime:
|
|
211
205
|
return pylo.illumio_date_time_string_to_datetime(self.created_at)
|
|
212
206
|
|
|
213
|
-
|
|
214
207
|
def api_update_description(self, new_description: str):
|
|
215
208
|
if new_description is None or len(new_description) == 0:
|
|
216
209
|
if self.description is None or self.description == '':
|
|
@@ -355,7 +348,6 @@ class Workload(pylo.ReferenceTracker, pylo.Referencer, LabeledObject):
|
|
|
355
348
|
|
|
356
349
|
return labels
|
|
357
350
|
|
|
358
|
-
|
|
359
351
|
def get_appgroup_str(self, separator: str = '|') -> str:
|
|
360
352
|
labels = ''
|
|
361
353
|
|
|
@@ -498,7 +490,7 @@ class WorkloadApiUpdateStackExecutionManager:
|
|
|
498
490
|
if len(self.workloads) == 0:
|
|
499
491
|
return
|
|
500
492
|
|
|
501
|
-
#self split in list of lists of 500
|
|
493
|
+
# self split in list of lists of 500
|
|
502
494
|
batches: List[List[pylo.Workload]] = [self.workloads[i:i + amount_per_batch] for i in range(0, len(self.workloads), amount_per_batch)]
|
|
503
495
|
|
|
504
496
|
for batch in batches:
|
|
@@ -527,7 +519,6 @@ class WorkloadApiUpdateStackExecutionManager:
|
|
|
527
519
|
else:
|
|
528
520
|
self.message[index] = result['message']
|
|
529
521
|
|
|
530
|
-
|
|
531
522
|
def get_all_results(self) -> List[Result]:
|
|
532
523
|
results = []
|
|
533
524
|
for i in range(len(self.workloads)):
|
|
@@ -14,9 +14,8 @@ class UnmanagedWorkloadDraft(LabeledObject):
|
|
|
14
14
|
self.name: str = name
|
|
15
15
|
self.ip: str = ip
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
def __init__(self, owner: 'pylo.WorkloadStore', name: Optional[str] = None, hostname: Optional[str] = None,
|
|
19
|
-
description: Optional[str] = None, ip_single_or_list: Optional[str|Iterable[str]] = None,
|
|
18
|
+
description: Optional[str] = None, ip_single_or_list: Optional[str | Iterable[str]] = None,
|
|
20
19
|
labels: Optional[List['pylo.Label']] = None):
|
|
21
20
|
super().__init__()
|
|
22
21
|
self.owner = owner
|
|
@@ -57,6 +56,7 @@ class UnmanagedWorkloadDraft(LabeledObject):
|
|
|
57
56
|
api_results = api.objects_workload_create_single_unmanaged(self.generate_json_payload())
|
|
58
57
|
return self.owner.add_workload_from_json(api_results)
|
|
59
58
|
|
|
59
|
+
|
|
60
60
|
@dataclass
|
|
61
61
|
class CreationTracker:
|
|
62
62
|
draft: UnmanagedWorkloadDraft
|
|
@@ -70,7 +70,6 @@ class CreationTracker:
|
|
|
70
70
|
class UnmanagedWorkloadDraftMultiCreatorManager:
|
|
71
71
|
def __init__(self, owner: 'pylo.WorkloadStore'):
|
|
72
72
|
|
|
73
|
-
|
|
74
73
|
self.owner = owner
|
|
75
74
|
self.drafts: List[UnmanagedWorkloadDraft] = []
|
|
76
75
|
self._external_tracker_ids: List[Any] = []
|
|
@@ -84,7 +83,9 @@ class UnmanagedWorkloadDraftMultiCreatorManager:
|
|
|
84
83
|
self._external_tracker_ids.append(external_tracker_id)
|
|
85
84
|
return draft
|
|
86
85
|
|
|
87
|
-
def create_all_in_pce(self, amount_created_per_batch
|
|
86
|
+
def create_all_in_pce(self, amount_created_per_batch=500, retrieve_workloads_after_creation=False) \
|
|
87
|
+
-> List[CreationTracker]:
|
|
88
|
+
|
|
88
89
|
results: List[CreationTracker] = []
|
|
89
90
|
|
|
90
91
|
if retrieve_workloads_after_creation:
|
|
@@ -98,7 +99,6 @@ class UnmanagedWorkloadDraftMultiCreatorManager:
|
|
|
98
99
|
|
|
99
100
|
return results
|
|
100
101
|
|
|
101
|
-
|
|
102
102
|
batches: List[List[UnmanagedWorkloadDraft]] = []
|
|
103
103
|
|
|
104
104
|
# slice the drafts into arrays of arrays of size=amount_created_per_batch
|
|
@@ -112,7 +112,7 @@ class UnmanagedWorkloadDraftMultiCreatorManager:
|
|
|
112
112
|
|
|
113
113
|
api = self.owner.owner.connector
|
|
114
114
|
|
|
115
|
-
try
|
|
115
|
+
try:
|
|
116
116
|
api_results = api.objects_workload_create_bulk_unmanaged(multi_create_payload)
|
|
117
117
|
for i in range(len(api_results)):
|
|
118
118
|
if api_results[i]["status"] == "created":
|
|
@@ -133,7 +133,4 @@ class UnmanagedWorkloadDraftMultiCreatorManager:
|
|
|
133
133
|
success=False,
|
|
134
134
|
message=str(e)))
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
return results
|
|
136
|
+
return results
|
illumio_pylo/__init__.py
CHANGED
illumio_pylo/cli/__init__.py
CHANGED
|
@@ -65,7 +65,6 @@ def run(forced_command_name: Optional[str] = None):
|
|
|
65
65
|
add_native_parser_to_argparse(parser, command.native_parsers)
|
|
66
66
|
selected_command = command
|
|
67
67
|
|
|
68
|
-
|
|
69
68
|
# version is a special command that does not require a PCE
|
|
70
69
|
# if first argument is --version, we print the version and exit
|
|
71
70
|
if len(sys.argv) > 1:
|
|
@@ -94,7 +93,6 @@ def run(forced_command_name: Optional[str] = None):
|
|
|
94
93
|
|
|
95
94
|
print("* Started Pylo CLI version {}".format(pylo.__version__))
|
|
96
95
|
|
|
97
|
-
|
|
98
96
|
if not selected_command.credentials_manager_mode:
|
|
99
97
|
timer_start = time.perf_counter()
|
|
100
98
|
# credential_profile_name is required for all commands except the credential manager
|
|
@@ -13,7 +13,6 @@ from illumio_pylo.API.CredentialsManager import get_all_credentials, create_cred
|
|
|
13
13
|
get_credentials_from_file, encrypt_api_key_with_paramiko_ssh_key_chacha20poly1305, \
|
|
14
14
|
decrypt_api_key_with_paramiko_ssh_key_chacha20poly1305, get_supported_keys_from_ssh_agent, is_encryption_available
|
|
15
15
|
|
|
16
|
-
from illumio_pylo import log
|
|
17
16
|
from . import Command
|
|
18
17
|
|
|
19
18
|
|
|
@@ -31,17 +30,17 @@ def fill_parser(parser: argparse.ArgumentParser):
|
|
|
31
30
|
|
|
32
31
|
create_parser = sub_parser.add_parser('create', help='Create a new credential')
|
|
33
32
|
create_parser.add_argument('--name', required=False, type=str, default=None,
|
|
34
|
-
|
|
33
|
+
help='Name of the credential')
|
|
35
34
|
create_parser.add_argument('--fqdn', required=False, type=str, default=None,
|
|
36
|
-
|
|
35
|
+
help='FQDN of the PCE')
|
|
37
36
|
create_parser.add_argument('--port', required=False, type=int, default=None,
|
|
38
|
-
|
|
37
|
+
help='Port of the PCE')
|
|
39
38
|
create_parser.add_argument('--org', required=False, type=int, default=None,
|
|
40
|
-
|
|
39
|
+
help='Organization ID')
|
|
41
40
|
create_parser.add_argument('--api-user', required=False, type=str, default=None,
|
|
42
|
-
|
|
41
|
+
help='API user')
|
|
43
42
|
create_parser.add_argument('--verify-ssl', required=False, type=bool, default=None,
|
|
44
|
-
|
|
43
|
+
help='Verify SSL')
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
def __main(args, **kwargs):
|
|
@@ -92,7 +91,6 @@ def __main(args, **kwargs):
|
|
|
92
91
|
if wanted_verify_ssl is None:
|
|
93
92
|
wanted_verify_ssl = click.prompt('> Verify SSL/TLS certificate? Y/N', type=bool)
|
|
94
93
|
|
|
95
|
-
|
|
96
94
|
print()
|
|
97
95
|
print("Recap:")
|
|
98
96
|
print("Name: {}".format(wanted_name))
|
|
@@ -103,7 +101,6 @@ def __main(args, **kwargs):
|
|
|
103
101
|
print("Verify SSL: {}".format(wanted_verify_ssl))
|
|
104
102
|
print()
|
|
105
103
|
|
|
106
|
-
|
|
107
104
|
# prompt of API key from user input, single line, hidden
|
|
108
105
|
api_key = click.prompt('> API Key', hide_input=True)
|
|
109
106
|
|
|
@@ -145,11 +142,9 @@ def __main(args, **kwargs):
|
|
|
145
142
|
else:
|
|
146
143
|
print(" * encryption is not available (no SSH agent or compatible key found), storing API key in plain text...")
|
|
147
144
|
|
|
148
|
-
|
|
149
145
|
cwd = os.getcwd()
|
|
150
146
|
create_in_current_workdir = click.prompt('> Create in current workdir ({})? If not then user homedir will be used. Y/N '.format(cwd), type=bool)
|
|
151
147
|
|
|
152
|
-
|
|
153
148
|
print("* Creating credential...", flush=True, end="")
|
|
154
149
|
if create_in_current_workdir:
|
|
155
150
|
file_path = create_credential_in_file(file_full_path=cwd, data=credentials_data)
|
|
@@ -192,9 +187,7 @@ def __main(args, **kwargs):
|
|
|
192
187
|
command_object = Command(command_name, __main, fill_parser, credentials_manager_mode=True)
|
|
193
188
|
|
|
194
189
|
|
|
195
|
-
def print_keys(keys: list[paramiko.AgentKey], display_index
|
|
196
|
-
|
|
197
|
-
args_for_print = []
|
|
190
|
+
def print_keys(keys: list[paramiko.AgentKey], display_index=True) -> None:
|
|
198
191
|
|
|
199
192
|
column_properties = [ # (name, width)
|
|
200
193
|
("ID#", 4),
|
|
@@ -207,11 +200,9 @@ def print_keys(keys: list[paramiko.AgentKey], display_index = True) -> None:
|
|
|
207
200
|
# remove tuple with name "ID#"
|
|
208
201
|
column_properties = [item for item in column_properties if item[0] != "ID#"]
|
|
209
202
|
|
|
210
|
-
|
|
211
203
|
table = PrettyTable()
|
|
212
204
|
table.field_names = [item[0] for item in column_properties]
|
|
213
205
|
|
|
214
|
-
|
|
215
206
|
for i, key in enumerate(keys):
|
|
216
207
|
display_values = []
|
|
217
208
|
if display_index:
|
|
@@ -223,5 +214,3 @@ def print_keys(keys: list[paramiko.AgentKey], display_index = True) -> None:
|
|
|
223
214
|
table.add_row(display_values)
|
|
224
215
|
|
|
225
216
|
print(table)
|
|
226
|
-
|
|
227
|
-
|
|
@@ -8,9 +8,11 @@ from . import Command
|
|
|
8
8
|
command_name = "iplist-analyzer"
|
|
9
9
|
objects_load_filter = ['iplists', 'workloads']
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
def fill_parser(parser: argparse.ArgumentParser):
|
|
12
13
|
pass
|
|
13
14
|
|
|
15
|
+
|
|
14
16
|
def __main(args, org: pylo.Organization, **kwargs):
|
|
15
17
|
now = datetime.now()
|
|
16
18
|
report_file = 'iplist-analyzer_{}.csv'.format(now.strftime("%Y%m%d-%H%M%S"))
|
|
@@ -24,7 +26,6 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
24
26
|
|
|
25
27
|
csv_report: pylo.ArrayToExport = pylo.ArrayToExport(csv_report_headers)
|
|
26
28
|
|
|
27
|
-
|
|
28
29
|
# <editor-fold desc="Building Workloads ip4 Cache">
|
|
29
30
|
workloads_ip4maps_cache: Dict[pylo.Workload, pylo.IP4Map] = {}
|
|
30
31
|
print(" * Building Workloads IP4 mapping... ", end='')
|
|
@@ -43,13 +44,11 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
43
44
|
print("OK")
|
|
44
45
|
# </editor-fold>
|
|
45
46
|
|
|
46
|
-
|
|
47
47
|
print(" * Now analyzing IPLists:", flush=True)
|
|
48
48
|
for (iplist, ip_map) in iplists_ip4maps_cache.items():
|
|
49
49
|
add_iplist_to_report(iplist, workloads_ip4maps_cache, csv_report)
|
|
50
50
|
|
|
51
51
|
print(" ** DONE **")
|
|
52
|
-
|
|
53
52
|
print()
|
|
54
53
|
print(" * Writing report file '{}' ... ".format(report_file), end='', flush=True)
|
|
55
54
|
csv_report.write_to_csv(report_file)
|
|
@@ -62,11 +61,9 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
62
61
|
print("\n** WARNING: no entry matched your filters so reports are empty !\n")
|
|
63
62
|
|
|
64
63
|
|
|
65
|
-
|
|
66
64
|
command_object = Command(command_name, __main, fill_parser, objects_load_filter)
|
|
67
65
|
|
|
68
66
|
|
|
69
|
-
|
|
70
67
|
def add_iplist_to_report(iplist: pylo.IPList, workloads_ip4maps_cache: Dict[pylo.Workload, pylo.IP4Map],
|
|
71
68
|
csv_report: pylo.ArrayToExport):
|
|
72
69
|
|
|
@@ -92,8 +89,7 @@ def add_iplist_to_report(iplist: pylo.IPList, workloads_ip4maps_cache: Dict[pylo
|
|
|
92
89
|
print("matched workload {}".format(workload.get_name()))
|
|
93
90
|
matched_workloads.append(workload)
|
|
94
91
|
appgroup_tracker[workload.get_appgroup_str()] = True
|
|
95
|
-
#print(ip_map.print_to_std(header="after subtraction", padding=" "))
|
|
96
|
-
|
|
92
|
+
# print(ip_map.print_to_std(header="after subtraction", padding=" "))
|
|
97
93
|
|
|
98
94
|
new_row['ip4_uncovered_count'] = ip_map.count_ips()
|
|
99
95
|
new_row['covered_workloads_count'] = len(matched_workloads)
|
|
@@ -101,5 +97,3 @@ def add_iplist_to_report(iplist: pylo.IPList, workloads_ip4maps_cache: Dict[pylo
|
|
|
101
97
|
new_row['covered_workloads_appgroups'] = pylo.string_list_to_text(appgroup_tracker.keys(), "\n")
|
|
102
98
|
|
|
103
99
|
csv_report.add_line_from_object(new_row)
|
|
104
|
-
|
|
105
|
-
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
1
3
|
import illumio_pylo as pylo
|
|
2
4
|
import argparse
|
|
3
5
|
import sys
|
|
6
|
+
import click
|
|
4
7
|
from .utils.misc import make_filename_with_timestamp
|
|
5
8
|
from . import Command
|
|
9
|
+
from ...API.JsonPayloadTypes import IPListObjectCreationJsonStructure
|
|
6
10
|
|
|
7
11
|
command_name = 'iplist-import'
|
|
8
12
|
objects_load_filter = ['iplists']
|
|
@@ -14,20 +18,32 @@ def fill_parser(parser: argparse.ArgumentParser):
|
|
|
14
18
|
parser.add_argument('--input-file-delimiter', type=str, required=False, default=',',
|
|
15
19
|
help='CSV field delimiter')
|
|
16
20
|
|
|
21
|
+
parser.add_argument('--output-dir', '-o', type=str, required=False, default='output',
|
|
22
|
+
help='Directory where the output files will be saved')
|
|
23
|
+
|
|
17
24
|
parser.add_argument('--ignore-if-iplist-exists', action='store_true',
|
|
18
25
|
help='If an IPList with same same exists, ignore CSV entry')
|
|
19
26
|
|
|
20
27
|
parser.add_argument('--network-delimiter', type=str, required=False, default=',', nargs='?', const=True,
|
|
21
28
|
help='If an IPList with same same exists, ignore CSV entry')
|
|
22
29
|
|
|
30
|
+
parser.add_argument('--proceed', '-p', action='store_true',
|
|
31
|
+
help='If set, the script will proceed with the creation of iplists')
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
input_file_delimiter = args['input_file_delimiter']
|
|
27
|
-
ignore_if_iplist_exists = args['ignore_if_iplist_exists']
|
|
28
|
-
network_delimiter = args['network_delimiter']
|
|
33
|
+
parser.add_argument('--no-confirmation-required', '-n', action='store_true',
|
|
34
|
+
help='If set, the script will proceed with the creation of iplists without asking for confirmation')
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
|
|
37
|
+
def __main(args, org: pylo.Organization, **kwargs):
|
|
38
|
+
setting_input_file = args['input_file']
|
|
39
|
+
settings_input_file_delimiter = args['input_file_delimiter']
|
|
40
|
+
settings_ignore_if_iplist_exists = args['ignore_if_iplist_exists']
|
|
41
|
+
settings_network_delimiter = args['network_delimiter']
|
|
42
|
+
settings_proceed = args['proceed']
|
|
43
|
+
settings_no_confirmation_required = args['no_confirmation_required']
|
|
44
|
+
settings_output_dir: str = args['output_dir']
|
|
45
|
+
|
|
46
|
+
output_file_prefix = make_filename_with_timestamp('import-iplists-results_', settings_output_dir)
|
|
31
47
|
output_file_csv = output_file_prefix + '.csv'
|
|
32
48
|
output_file_excel = output_file_prefix + '.xlsx'
|
|
33
49
|
|
|
@@ -44,8 +60,8 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
44
60
|
pylo.file_clean(output_file_csv)
|
|
45
61
|
pylo.file_clean(output_file_excel)
|
|
46
62
|
|
|
47
|
-
print(" * Loading CSV input file '{}'...".format(
|
|
48
|
-
csv_data = pylo.CsvExcelToObject(
|
|
63
|
+
print(" * Loading CSV input file '{}'...".format(setting_input_file), flush=True, end='')
|
|
64
|
+
csv_data = pylo.CsvExcelToObject(setting_input_file, expected_headers=csv_expected_fields, csv_delimiter=settings_input_file_delimiter)
|
|
49
65
|
print('OK')
|
|
50
66
|
print(" - CSV has {} columns and {} lines (headers don't count)".format(csv_data.count_columns(), csv_data.count_lines()))
|
|
51
67
|
# print(pylo.nice_json(csv_data._objects))
|
|
@@ -71,7 +87,7 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
71
87
|
sys.exit(1)
|
|
72
88
|
else:
|
|
73
89
|
csv_object['**not_created_reason**'] = 'Found duplicated name in PCE'
|
|
74
|
-
if not
|
|
90
|
+
if not settings_ignore_if_iplist_exists:
|
|
75
91
|
pylo.log.error("PCE contains iplists with duplicates name from CSV: '{}' at line #{}. Please fix CSV or look for --options to ignore it".format(lower_name, csv_object['*line*']))
|
|
76
92
|
sys.exit(1)
|
|
77
93
|
print(" - WARNING: CSV has an entry for iplist name '{}' at line #{} but it exists already in the PCE. It will be ignored.".format(lower_name, csv_object['*line*']))
|
|
@@ -89,28 +105,28 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
89
105
|
ignored_objects_count += 1
|
|
90
106
|
|
|
91
107
|
print(' * Preparing Iplist JSON data...')
|
|
92
|
-
iplists_json_data = []
|
|
108
|
+
iplists_json_data: List[IPListObjectCreationJsonStructure] = []
|
|
93
109
|
for data in csv_objects_to_create:
|
|
94
|
-
new_iplist = {}
|
|
110
|
+
new_iplist: IPListObjectCreationJsonStructure = {}
|
|
95
111
|
iplists_json_data.append(new_iplist)
|
|
96
112
|
|
|
97
113
|
if len(data['name']) < 1:
|
|
98
114
|
raise pylo.PyloEx('Iplist at line #{} is missing a name in CSV'.format(data['*line*']))
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
|
|
116
|
+
new_iplist['name'] = str(data['name'])
|
|
101
117
|
|
|
102
118
|
if len(data['description']) > 0:
|
|
103
|
-
new_iplist['description'] = data['description']
|
|
119
|
+
new_iplist['description'] = str(data['description'])
|
|
104
120
|
|
|
105
121
|
if len(data['networks']) < 1:
|
|
106
122
|
print('Iplist at line #{} has empty networks list'.format(data['*line*']))
|
|
107
123
|
sys.exit(1)
|
|
108
124
|
|
|
109
|
-
|
|
125
|
+
settings_network_delimiter = settings_network_delimiter.replace("\\n", "\n")
|
|
110
126
|
ip_ranges = []
|
|
111
127
|
new_iplist['ip_ranges'] = ip_ranges
|
|
112
128
|
|
|
113
|
-
for network_string in data['networks'].rsplit(
|
|
129
|
+
for network_string in data['networks'].rsplit(settings_network_delimiter):
|
|
114
130
|
network_string = network_string.strip(" \r\n") # cleanup trailing characters
|
|
115
131
|
|
|
116
132
|
exclusion = False
|
|
@@ -155,31 +171,38 @@ def __main(args, org: pylo.Organization, **kwargs):
|
|
|
155
171
|
|
|
156
172
|
print(" * DONE")
|
|
157
173
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
if settings_proceed is False:
|
|
175
|
+
print(" * Dry-run mode, no changes will be made to the PCE. Use --proceed to actually create the iplists")
|
|
176
|
+
|
|
177
|
+
else:
|
|
178
|
+
if not settings_no_confirmation_required:
|
|
179
|
+
print(" * WARNING: You are about to create {} IPLists in the PCE. Are you sure you want to proceed?".format(len(iplists_json_data)))
|
|
180
|
+
click.confirm("Do you want to proceed with the creation of these labels?", abort=True)
|
|
181
|
+
|
|
182
|
+
print(" * Creating {} IPLists".format(len(iplists_json_data)))
|
|
183
|
+
total_created_count = 0
|
|
184
|
+
total_failed_count = 0
|
|
161
185
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
186
|
+
for index in range(0, len(iplists_json_data)):
|
|
187
|
+
json_blob: IPListObjectCreationJsonStructure = iplists_json_data[index]
|
|
188
|
+
print(" - Pushing new iplist '{}' to PCE (#{} of {})... ".format(json_blob['name'], index+1, len(iplists_json_data)), end='', flush=True)
|
|
189
|
+
result = org.connector.objects_iplist_create(json_blob)
|
|
190
|
+
print("OK")
|
|
167
191
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
192
|
+
href = result.get('href')
|
|
193
|
+
if href is None:
|
|
194
|
+
raise pylo.PyloEx('API returned unexpected response which is missing a HREF:', result)
|
|
171
195
|
|
|
172
|
-
|
|
173
|
-
|
|
196
|
+
total_created_count += 1
|
|
197
|
+
csv_objects_to_create[index]['href'] = href
|
|
198
|
+
|
|
199
|
+
csv_data.save_to_csv(output_file_csv, csv_created_fields)
|
|
200
|
+
csv_data.save_to_excel(output_file_excel, csv_created_fields)
|
|
174
201
|
|
|
175
202
|
csv_data.save_to_csv(output_file_csv, csv_created_fields)
|
|
176
203
|
csv_data.save_to_excel(output_file_excel, csv_created_fields)
|
|
177
204
|
|
|
178
|
-
|
|
179
|
-
csv_data.save_to_excel(output_file_excel, csv_created_fields)
|
|
180
|
-
|
|
181
|
-
print(" * DONE - {} created with success, {} failures and {} ignored. A report was created in {} and {}".format(total_created_count, total_failed_count, ignored_objects_count, output_file_csv, output_file_excel))
|
|
205
|
+
print(" * DONE - {} created with success, {} failures and {} ignored. A report was created in {} and {}".format(total_created_count, total_failed_count, ignored_objects_count, output_file_csv, output_file_excel))
|
|
182
206
|
|
|
183
207
|
|
|
184
208
|
command_object = Command(command_name, __main, fill_parser, load_specific_objects_only=objects_load_filter)
|
|
185
|
-
|
|
@@ -11,23 +11,24 @@ command_name = 'rule-export'
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def fill_parser(parser: argparse.ArgumentParser):
|
|
14
|
-
parser.add_argument('--format', '-f', required=False, default='excel',choices=['csv', 'excel'],
|
|
15
|
-
|
|
14
|
+
parser.add_argument('--format', '-f', required=False, default='excel', choices=['csv', 'excel'],
|
|
15
|
+
help='Output file format')
|
|
16
|
+
parser.add_argument('--output-dir', '-o', required=False, default='output',
|
|
17
|
+
help='Directory where to save the output file')
|
|
16
18
|
parser.add_argument('--prefix-objects-with-type', nargs='?', const=True, default=False,
|
|
17
19
|
help='Prefix objects with their type (e.g. "label:mylabel")')
|
|
18
20
|
parser.add_argument('--object-types-as-section', action='store_true', default=False,
|
|
19
21
|
help="Consumer and providers will show objects types section headers, example:" + os.linesep +
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
"LABELS: " + os.linesep +
|
|
23
|
+
"R-WEB" + os.linesep +
|
|
24
|
+
"A-FUSION" + os.linesep +
|
|
25
|
+
"IPLISTS: " + os.linesep +
|
|
26
|
+
"Private_Networks" + os.linesep +
|
|
27
|
+
"Public_NATed")
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def __main(args: Dict, org: pylo.Organization, **kwargs):
|
|
29
|
-
|
|
30
|
-
setting_prefix_objects_with_type: bool|str = args['prefix_objects_with_type']
|
|
31
|
+
setting_prefix_objects_with_type: bool | str = args['prefix_objects_with_type']
|
|
31
32
|
setting_object_types_as_section: bool = args['prefix_objects_with_type']
|
|
32
33
|
settings_output_file_format = args['format']
|
|
33
34
|
settings_output_dir = args['output_dir']
|
|
@@ -69,12 +70,12 @@ def __main(args: Dict, org: pylo.Organization, **kwargs):
|
|
|
69
70
|
if scope_str[-1] == "\n":
|
|
70
71
|
scope_str = scope_str[:-1]
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
providers_str = rule.providers.members_to_str("\n",
|
|
73
|
+
consumers_str = rule.consumers.members_to_str("\n",
|
|
74
|
+
prefix_objects_with_type=setting_prefix_objects_with_type,
|
|
75
|
+
object_types_as_section=setting_object_types_as_section)
|
|
76
|
+
providers_str = rule.providers.members_to_str("\n",
|
|
77
|
+
prefix_objects_with_type=setting_prefix_objects_with_type,
|
|
76
78
|
object_types_as_section=setting_object_types_as_section)
|
|
77
|
-
|
|
78
79
|
|
|
79
80
|
data = {'ruleset': ruleset.name, 'scope': scope_str,
|
|
80
81
|
'consumers': consumers_str,
|
|
@@ -126,8 +127,3 @@ def prepare_csv_report_object(output_file_format: Literal['excel', 'csv'], setti
|
|
|
126
127
|
|
|
127
128
|
|
|
128
129
|
command_object = Command(command_name, __main, fill_parser)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
@@ -30,7 +30,7 @@ def generate_list_of_labels_to_create(csv_data: Iterable[Dict[str, Union[bool, s
|
|
|
30
30
|
real_case: str
|
|
31
31
|
type: str
|
|
32
32
|
|
|
33
|
-
name_cache: Dict[str,LabelExistsRecord] = {}
|
|
33
|
+
name_cache: Dict[str, LabelExistsRecord] = {}
|
|
34
34
|
|
|
35
35
|
for label in org.LabelStore.get_labels():
|
|
36
36
|
if label.name is not None:
|
|
@@ -98,4 +98,4 @@ def create_labels(labels_to_be_created: List[LabelToBeCreatedRecord], org: pylo.
|
|
|
98
98
|
" - Pushing '{}' with type '{}' to the PCE... ".format(label_to_create['name'], label_to_create['type']),
|
|
99
99
|
end='', flush=True)
|
|
100
100
|
org.LabelStore.api_create_label(label_to_create['name'], label_to_create['type'])
|
|
101
|
-
print("OK")
|
|
101
|
+
print("OK")
|