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.
Files changed (73) hide show
  1. illumio_pylo/API/APIConnector.py +1308 -0
  2. illumio_pylo/API/AuditLog.py +42 -0
  3. illumio_pylo/API/ClusterHealth.py +136 -0
  4. illumio_pylo/API/CredentialsManager.py +286 -0
  5. illumio_pylo/API/Explorer.py +1077 -0
  6. illumio_pylo/API/JsonPayloadTypes.py +240 -0
  7. illumio_pylo/API/RuleSearchQuery.py +128 -0
  8. illumio_pylo/API/__init__.py +0 -0
  9. illumio_pylo/AgentStore.py +139 -0
  10. illumio_pylo/Exception.py +44 -0
  11. illumio_pylo/Helpers/__init__.py +3 -0
  12. illumio_pylo/Helpers/exports.py +508 -0
  13. illumio_pylo/Helpers/functions.py +166 -0
  14. illumio_pylo/IPList.py +135 -0
  15. illumio_pylo/IPMap.py +285 -0
  16. illumio_pylo/Label.py +25 -0
  17. illumio_pylo/LabelCommon.py +48 -0
  18. illumio_pylo/LabelGroup.py +68 -0
  19. illumio_pylo/LabelStore.py +403 -0
  20. illumio_pylo/LabeledObject.py +25 -0
  21. illumio_pylo/Organization.py +258 -0
  22. illumio_pylo/Query.py +331 -0
  23. illumio_pylo/ReferenceTracker.py +41 -0
  24. illumio_pylo/Rule.py +671 -0
  25. illumio_pylo/Ruleset.py +306 -0
  26. illumio_pylo/RulesetStore.py +101 -0
  27. illumio_pylo/SecurityPrincipal.py +62 -0
  28. illumio_pylo/Service.py +256 -0
  29. illumio_pylo/SoftwareVersion.py +125 -0
  30. illumio_pylo/VirtualService.py +17 -0
  31. illumio_pylo/VirtualServiceStore.py +75 -0
  32. illumio_pylo/Workload.py +506 -0
  33. illumio_pylo/WorkloadStore.py +289 -0
  34. illumio_pylo/__init__.py +82 -0
  35. illumio_pylo/cli/NativeParsers.py +96 -0
  36. illumio_pylo/cli/__init__.py +134 -0
  37. illumio_pylo/cli/__main__.py +10 -0
  38. illumio_pylo/cli/commands/__init__.py +32 -0
  39. illumio_pylo/cli/commands/credential_manager.py +168 -0
  40. illumio_pylo/cli/commands/iplist_import_from_file.py +185 -0
  41. illumio_pylo/cli/commands/misc.py +7 -0
  42. illumio_pylo/cli/commands/ruleset_export.py +129 -0
  43. illumio_pylo/cli/commands/update_pce_objects_cache.py +44 -0
  44. illumio_pylo/cli/commands/ven_duplicate_remover.py +366 -0
  45. illumio_pylo/cli/commands/ven_idle_to_visibility.py +287 -0
  46. illumio_pylo/cli/commands/ven_upgrader.py +226 -0
  47. illumio_pylo/cli/commands/workload_export.py +251 -0
  48. illumio_pylo/cli/commands/workload_import.py +423 -0
  49. illumio_pylo/cli/commands/workload_relabeler.py +510 -0
  50. illumio_pylo/cli/commands/workload_reset_names_to_null.py +83 -0
  51. illumio_pylo/cli/commands/workload_used_in_rule_finder.py +80 -0
  52. illumio_pylo/docs/Doxygen +1757 -0
  53. illumio_pylo/tmp.py +104 -0
  54. illumio_pylo/utilities/__init__.py +0 -0
  55. illumio_pylo/utilities/cli.py +10 -0
  56. illumio_pylo/utilities/credentials.example.json +20 -0
  57. illumio_pylo/utilities/explorer_report_exporter.py +86 -0
  58. illumio_pylo/utilities/health_monitoring.py +102 -0
  59. illumio_pylo/utilities/iplist_analyzer.py +148 -0
  60. illumio_pylo/utilities/iplists_stats_duplicates_unused_finder.py +75 -0
  61. illumio_pylo/utilities/resources/iplists-import-example.csv +3 -0
  62. illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
  63. illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +3 -0
  64. illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
  65. illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
  66. illumio_pylo/utilities/ven_compatibility_report_export.py +240 -0
  67. illumio_pylo/utilities/ven_idle_to_illumination.py +344 -0
  68. illumio_pylo/utilities/ven_reassign_pce.py +183 -0
  69. illumio_pylo-0.2.5.dist-info/LICENSE +176 -0
  70. illumio_pylo-0.2.5.dist-info/METADATA +197 -0
  71. illumio_pylo-0.2.5.dist-info/RECORD +73 -0
  72. illumio_pylo-0.2.5.dist-info/WHEEL +5 -0
  73. illumio_pylo-0.2.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,168 @@
1
+ from prettytable import PrettyTable
2
+ import argparse
3
+ import os
4
+
5
+ import paramiko
6
+
7
+ import illumio_pylo as pylo
8
+ import click
9
+ from illumio_pylo.API.CredentialsManager import get_all_credentials, create_credential_in_file, CredentialFileEntry, \
10
+ create_credential_in_default_file, encrypt_api_key_with_paramiko_key, decrypt_api_key_with_paramiko_key
11
+
12
+ from illumio_pylo import log
13
+ from . import Command
14
+
15
+
16
+ command_name = "cred-manager"
17
+ objects_load_filter = None
18
+
19
+
20
+ def fill_parser(parser: argparse.ArgumentParser):
21
+ sub_parser = parser.add_subparsers(dest='sub_command', required=True)
22
+ list_parser = sub_parser.add_parser('list', help='List all credentials')
23
+ create_parser = sub_parser.add_parser('create', help='Create a new credential')
24
+
25
+ create_parser.add_argument('--name', required=True, type=str,
26
+ help='Name of the credential')
27
+ create_parser.add_argument('--fqdn', required=True, type=str,
28
+ help='FQDN of the PCE')
29
+ create_parser.add_argument('--port', required=True, type=int,
30
+ help='Port of the PCE')
31
+ create_parser.add_argument('--org', required=True, type=int,
32
+ help='Organization ID')
33
+ create_parser.add_argument('--api-user', required=True, type=str,
34
+ help='API user')
35
+ create_parser.add_argument('--verify-ssl', required=True, type=bool,
36
+ help='Verify SSL')
37
+
38
+
39
+ def __main(args, **kwargs):
40
+ if args['sub_command'] == 'list':
41
+ credentials = get_all_credentials()
42
+ # sort credentials by name
43
+ credentials.sort(key=lambda x: x.name)
44
+
45
+ # print credentials in a nice table
46
+ table_template = " {:<19} {:<40} {:<22} {:<25}"
47
+ print(table_template.format("Name", "URL", "API User", "Originating File"))
48
+
49
+ for credential in credentials:
50
+ print(table_template.format(credential.name,
51
+ credential.fqdn + ':' + str(credential.port),
52
+ credential.api_user,
53
+ credential.originating_file)
54
+ )
55
+
56
+ elif args['sub_command'] == 'create':
57
+ print("Recap:")
58
+ print("Name: {}".format(args['name']))
59
+ print("FQDN: {}".format(args['fqdn']))
60
+ print("Port: {}".format(args['port']))
61
+ print("Org ID: {}".format(args['org']))
62
+ print("API User: {}".format(args['api_user']))
63
+ print("Verify SSL: {}".format(args['verify_ssl']))
64
+ print()
65
+
66
+ print("* Checking if a credential with the same name already exists...", flush=True, end="")
67
+ credentials = get_all_credentials()
68
+ for credential in credentials:
69
+ if credential.name == args['name']:
70
+ raise pylo.PyloEx("A credential named '{}' already exists".format(args['name']))
71
+ print("OK!")
72
+
73
+ # prompt of API key from user input, single line, hidden
74
+ api_key = click.prompt('> API Key', hide_input=True)
75
+
76
+ credentials_data: CredentialFileEntry = {
77
+ "name": args['name'],
78
+ "fqdn": args['fqdn'],
79
+ "port": args['port'],
80
+ "org_id": args['org'],
81
+ "api_user": args['api_user'],
82
+ "verify_ssl": args['verify_ssl'],
83
+ "api_key": api_key
84
+ }
85
+
86
+ encrypt_api_key = click.prompt('> Encrypt API? Y/N', type=bool)
87
+ if encrypt_api_key:
88
+ print("Available keys (ECDSA NISTPXXX keys and a few others are not supported and will be filtered out):")
89
+ ssh_keys = paramiko.Agent().get_keys()
90
+ # filter out ECDSA NISTPXXX and sk-ssh-ed25519@openssh.com
91
+ ssh_keys = get_supported_keys_from_ssh_agent()
92
+
93
+ # display a table of keys
94
+ print_keys(keys=ssh_keys, display_index=True)
95
+ print()
96
+
97
+ index_of_selected_key = click.prompt('> Select key by ID#', type=click.IntRange(0, len(ssh_keys)-1))
98
+ selected_ssh_key = ssh_keys[index_of_selected_key]
99
+ print("Selected key: {} | {} | {}".format(selected_ssh_key.get_name(),
100
+ selected_ssh_key.get_fingerprint().hex(),
101
+ selected_ssh_key.comment))
102
+ print(" * encrypting API key with selected key (you may be prompted by your SSH agent for confirmation or PIN code) ...", flush=True, end="")
103
+ encrypted_api_key = encrypt_api_key_with_paramiko_key(ssh_key=selected_ssh_key, api_key=api_key)
104
+ print("OK!")
105
+ print(" * trying to decrypt the encrypted API key...", flush=True, end="")
106
+ decrypted_api_key = decrypt_api_key_with_paramiko_key(encrypted_api_key_payload=encrypted_api_key)
107
+ if decrypted_api_key != api_key:
108
+ raise pylo.PyloEx("Decrypted API key does not match original API key")
109
+ print("OK!")
110
+ credentials_data["api_key"] = encrypted_api_key
111
+
112
+
113
+ cwd = os.getcwd()
114
+ create_in_current_workdir = click.prompt('> Create in current workdir ({})? If not then user homedir will be used. Y/N '.format(cwd), type=bool)
115
+
116
+
117
+ print("* Creating credential...", flush=True, end="")
118
+ if create_in_current_workdir:
119
+ file_path = create_credential_in_file(file_full_path=cwd, data=credentials_data)
120
+ else:
121
+ file_path = create_credential_in_default_file(data=credentials_data)
122
+
123
+ print("OK! ({})".format(file_path))
124
+
125
+
126
+ command_object = Command(command_name, __main, fill_parser, credentials_manager_mode=True)
127
+
128
+
129
+ def get_supported_keys_from_ssh_agent() -> list[paramiko.AgentKey]:
130
+ keys = paramiko.Agent().get_keys()
131
+ # filter out ECDSA NISTPXXX and sk-ssh-ed25519
132
+ # RSA and ED25519 keys are reported to be working
133
+ return [key for key in keys if not (key.get_name().startswith("ecdsa-sha2-nistp") or
134
+ key.get_name().startswith("sk-ssh-ed25519"))]
135
+
136
+ def print_keys(keys: list[paramiko.AgentKey], display_index = True) -> None:
137
+
138
+ args_for_print = []
139
+
140
+ column_properties = [ # (name, width)
141
+ ("ID#", 4),
142
+ ("Type", 20),
143
+ ("Fingerprint", 40),
144
+ ("Comment", 48)
145
+ ]
146
+
147
+ if not display_index:
148
+ # remove tuple with name "ID#"
149
+ column_properties = [item for item in column_properties if item[0] != "ID#"]
150
+
151
+
152
+ table = PrettyTable()
153
+ table.field_names = [item[0] for item in column_properties]
154
+
155
+
156
+ for i, key in enumerate(keys):
157
+ display_values = []
158
+ if display_index:
159
+ display_values.append(i)
160
+ display_values.append(key.get_name())
161
+ display_values.append(key.get_fingerprint().hex())
162
+ display_values.append(key.comment)
163
+
164
+ table.add_row(display_values)
165
+
166
+ print(table)
167
+
168
+
@@ -0,0 +1,185 @@
1
+ import illumio_pylo as pylo
2
+ import argparse
3
+ import sys
4
+ from .misc import make_filename_with_timestamp
5
+ from . import Command
6
+
7
+ command_name = 'iplist-import'
8
+ objects_load_filter = ['iplists']
9
+
10
+
11
+ def fill_parser(parser: argparse.ArgumentParser):
12
+ parser.add_argument('--input-file', '-i', type=str, required=True,
13
+ help='CSV or Excel input filename')
14
+ parser.add_argument('--input-file-delimiter', type=str, required=False, default=',',
15
+ help='CSV field delimiter')
16
+
17
+ parser.add_argument('--ignore-if-iplist-exists', action='store_true',
18
+ help='If an IPList with same same exists, ignore CSV entry')
19
+
20
+ parser.add_argument('--network-delimiter', type=str, required=False, default=',', nargs='?', const=True,
21
+ help='If an IPList with same same exists, ignore CSV entry')
22
+
23
+
24
+ def __main(args, org: pylo.Organization, **kwargs):
25
+ input_file = args['input_file']
26
+ input_file_delimiter = args['input_file_delimiter']
27
+ ignore_if_iplist_exists = args['ignore_if_iplist_exists']
28
+ network_delimiter = args['network_delimiter']
29
+
30
+ output_file_prefix = make_filename_with_timestamp('import-iplists-results_')
31
+ output_file_csv = output_file_prefix + '.csv'
32
+ output_file_excel = output_file_prefix + '.xlsx'
33
+
34
+ csv_expected_fields = [
35
+ {'name': 'name', 'optional': False},
36
+ {'name': 'description', 'optional': True},
37
+ {'name': 'networks', 'optional': False, 'type': 'array_of_strings'}
38
+ ]
39
+
40
+ csv_created_fields = csv_expected_fields.copy()
41
+ csv_created_fields.append({'name': 'href'})
42
+ csv_created_fields.append({'name': '**not_created_reason**'})
43
+
44
+ pylo.file_clean(output_file_csv)
45
+ pylo.file_clean(output_file_excel)
46
+
47
+ print(" * Loading CSV input file '{}'...".format(input_file), flush=True, end='')
48
+ csv_data = pylo.CsvExcelToObject(input_file, expected_headers=csv_expected_fields, csv_delimiter=input_file_delimiter)
49
+ print('OK')
50
+ print(" - CSV has {} columns and {} lines (headers don't count)".format(csv_data.count_columns(), csv_data.count_lines()))
51
+ # print(pylo.nice_json(csv_data._objects))
52
+
53
+ print(" * Checking for iplist name collisions:", flush=True)
54
+ name_cache = {}
55
+ for iplist in org.IPListStore.items_by_href.values():
56
+ if iplist.name is not None and len(iplist.name) > 0:
57
+ lower_name = iplist.name.lower()
58
+ if lower_name not in name_cache:
59
+ name_cache[lower_name] = {'pce': True}
60
+ else:
61
+ print(" - Warning duplicate found in the PCE for IPList name: {}".format(iplist.name))
62
+
63
+ for csv_object in csv_data.objects():
64
+ if csv_object['name'] is not None and len(csv_object['name']) > 0:
65
+ lower_name = csv_object['name'].lower()
66
+ if lower_name not in name_cache:
67
+ name_cache[lower_name] = {'csv': True}
68
+ else:
69
+ if 'csv' in name_cache[lower_name]:
70
+ pylo.log.error('CSV contains iplists with duplicates name: {}'.format(lower_name))
71
+ sys.exit(1)
72
+ else:
73
+ csv_object['**not_created_reason**'] = 'Found duplicated name in PCE'
74
+ if not ignore_if_iplist_exists:
75
+ 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
+ sys.exit(1)
77
+ 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*']))
78
+
79
+ del name_cache
80
+ print(" * DONE", flush=True)
81
+
82
+ # Listing objects to be created (filtering out inconsistent ones)
83
+ csv_objects_to_create = []
84
+ ignored_objects_count = 0
85
+ for csv_object in csv_data.objects():
86
+ if '**not_created_reason**' not in csv_object:
87
+ csv_objects_to_create.append(csv_object)
88
+ else:
89
+ ignored_objects_count += 1
90
+
91
+ print(' * Preparing Iplist JSON data...')
92
+ iplists_json_data = []
93
+ for data in csv_objects_to_create:
94
+ new_iplist = {}
95
+ iplists_json_data.append(new_iplist)
96
+
97
+ if len(data['name']) < 1:
98
+ raise pylo.PyloEx('Iplist at line #{} is missing a name in CSV'.format(data['*line*']))
99
+ else:
100
+ new_iplist['name'] = data['name']
101
+
102
+ if len(data['description']) > 0:
103
+ new_iplist['description'] = data['description']
104
+
105
+ if len(data['networks']) < 1:
106
+ print('Iplist at line #{} has empty networks list'.format(data['*line*']))
107
+ sys.exit(1)
108
+
109
+ network_delimiter = network_delimiter.replace("\\n", "\n")
110
+ ip_ranges = []
111
+ new_iplist['ip_ranges'] = ip_ranges
112
+
113
+ for network_string in data['networks'].rsplit(network_delimiter):
114
+ network_string = network_string.strip(" \r\n") # cleanup trailing characters
115
+
116
+ exclusion = False
117
+ if network_string.find('!') == 0:
118
+ exclusion = True
119
+ network_string = network_string[1:]
120
+
121
+ split_dash = network_string.split('-')
122
+ if len(split_dash) > 2:
123
+ pylo.log.error('Iplist at line #{} has invalid network entry: {}'.format(data['*line*'], network_string))
124
+ sys.exit(1)
125
+ if len(split_dash) == 2:
126
+ ip_ranges.append({'from_ip': split_dash[0], 'to_ip': split_dash[1], 'exclusion': exclusion})
127
+ continue
128
+
129
+ split_slash = network_string.split('/')
130
+ if len(split_slash) > 2:
131
+ pylo.log.error('Iplist at line #{} has invalid network entry: {}'.format(data['*line*'], network_string))
132
+ sys.exit(1)
133
+ if len(split_slash) == 2:
134
+ if len(split_slash[1]) > 2:
135
+ pylo.log.error('Iplist at line #{} has invalid network mask in CIDR {}'.format(data['*line*'], network_string))
136
+ sys.exit(1)
137
+ ip_ranges.append({'from_ip': split_slash[0]+'/'+split_slash[1], 'exclusion': exclusion})
138
+ continue
139
+ else:
140
+ is_ip4 = pylo.is_valid_ipv4(network_string)
141
+ is_ip6 = pylo.is_valid_ipv6(network_string)
142
+
143
+ if not is_ip4 and not is_ip6:
144
+ pylo.log.error('Iplist at line #{} has invalid address format: {}'.format(data['*line*'], network_string))
145
+ sys.exit(1)
146
+ ip_ranges.append({'from_ip': network_string, 'exclusion': exclusion})
147
+ continue
148
+
149
+ if len(ip_ranges) == 0:
150
+ pylo.log.error('Iplist at line #{} has no network entry'.format(data['*line*']))
151
+ sys.exit(1)
152
+
153
+ print(" - iplist '{}' extracted with {} with networks".format(new_iplist['name'], len(new_iplist['ip_ranges'])))
154
+ # print(new_iplist)
155
+
156
+ print(" * DONE")
157
+
158
+ print(" * Creating {} IPLists".format(len(iplists_json_data)))
159
+ total_created_count = 0
160
+ total_failed_count = 0
161
+
162
+ for index in range(0, len(iplists_json_data)):
163
+ json_blob = iplists_json_data[index]
164
+ print(" - Pushing new iplist '{}' to PCE (#{} of {})... ".format(json_blob['name'], index+1, len(iplists_json_data)), end='', flush=True)
165
+ result = org.connector.objects_iplist_create(json_blob)
166
+ print("OK")
167
+
168
+ href = result.get('href')
169
+ if href is None:
170
+ raise pylo.PyloEx('API returned unexpected response which is missing a HREF:', result)
171
+
172
+ total_created_count += 1
173
+ csv_objects_to_create[index]['href'] = href
174
+
175
+ csv_data.save_to_csv(output_file_csv, csv_created_fields)
176
+ csv_data.save_to_excel(output_file_excel, csv_created_fields)
177
+
178
+ csv_data.save_to_csv(output_file_csv, csv_created_fields)
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))
182
+
183
+
184
+ command_object = Command(command_name, __main, fill_parser, load_specific_objects_only=objects_load_filter)
185
+
@@ -0,0 +1,7 @@
1
+ from datetime import datetime
2
+ import illumio_pylo as pylo
3
+
4
+
5
+ def make_filename_with_timestamp(prefix: str):
6
+ now = datetime.now()
7
+ return prefix + now.strftime("%Y%m%d-%H%M%S")
@@ -0,0 +1,129 @@
1
+ import argparse
2
+ import os
3
+ from typing import Dict, List
4
+
5
+ import illumio_pylo as pylo
6
+ from .misc import make_filename_with_timestamp
7
+ from . import Command
8
+
9
+ command_name = 'rule-export'
10
+
11
+
12
+ def fill_parser(parser: argparse.ArgumentParser):
13
+ parser.add_argument('--format', '-f', required=False, default='excel',choices=['csv', 'excel'], help='Output file format')
14
+ parser.add_argument('--output', '-o', required=False, default='.', help='Directory where to save the output file')
15
+ parser.add_argument('--prefix-objects-with-type', nargs='?', const=True, default=False,
16
+ help='Prefix objects with their type (e.g. "label:mylabel")')
17
+ parser.add_argument('--object-types-as-section', action='store_true', default=False,
18
+ help="Consumer and providers will show objects types section headers, example:" + os.linesep +
19
+ "LABELS: " + os.linesep +
20
+ "R-WEB" + os.linesep +
21
+ "A-FUSION" + os.linesep +
22
+ "IPLISTS: " + os.linesep +
23
+ "Private_Networks" + os.linesep +
24
+ "Public_NATed")
25
+
26
+
27
+
28
+ def __main(options: Dict, org: pylo.Organization, **kwargs):
29
+ csv_report_headers: List[pylo.ExcelHeader] = \
30
+ [{'name': 'ruleset', 'max_width': 40},
31
+ {'name': 'scope', 'max_width': 50},
32
+ {'name': 'type', 'max_width': 10},
33
+ {'name': 'consumers', 'max_width': 80},
34
+ {'name': 'providers', 'max_width': 80},
35
+ {'name': 'services', 'max_width': 30},
36
+ {'name': 'options', 'max_width': 40},
37
+ {'name': 'ruleset_url', 'max_width': 40, 'wrap_text': False},
38
+ {'name': 'ruleset_href', 'max_width': 30, 'wrap_text': False}
39
+ ]
40
+
41
+ setting_prefix_objects_with_type: bool|str = options['prefix_objects_with_type']
42
+ if setting_prefix_objects_with_type is False:
43
+ print(" * Prefix for object types are disabled")
44
+ else:
45
+ print(" * Prefix for object types are enabled")
46
+
47
+ setting_object_types_as_section: bool = options['prefix_objects_with_type']
48
+ if setting_object_types_as_section is False:
49
+ print(" * Object types as section are disabled")
50
+ else:
51
+ print(" * Object types as section are enabled")
52
+
53
+ output_file_format = options.get('format')
54
+ if output_file_format == "excel":
55
+ output_file_extension = ".xlsx"
56
+ elif output_file_format == "csv":
57
+ output_file_extension = ".csv"
58
+ else:
59
+ raise Exception("Unknown output file format: %s" % output_file_format)
60
+
61
+ output_file_name = options.get('output') + os.sep + make_filename_with_timestamp('rule_export_') + output_file_extension
62
+ output_file_name = os.path.abspath(output_file_name)
63
+
64
+ csv_report = pylo.ArraysToExcel()
65
+ sheet = csv_report.create_sheet('rulesets', csv_report_headers, force_all_wrap_text=True, multivalues_cell_delimiter=',')
66
+
67
+ for ruleset in org.RulesetStore.rulesets:
68
+ for rule in ruleset.rules_ordered_by_type:
69
+ rule_options = []
70
+ if not rule.enabled:
71
+ rule_options.append('disabled')
72
+ if rule.secure_connect:
73
+ rule_options.append('secure-connect')
74
+ if rule.stateless:
75
+ rule_options.append('stateless')
76
+ if rule.machine_auth:
77
+ rule_options.append('machine_auth')
78
+
79
+ scope_str = ''
80
+ for scope in ruleset.scopes.scope_entries.values():
81
+ if len(scope_str) > 0:
82
+ scope_str += "\n"
83
+ if scope.is_all_all_all():
84
+ scope_str += "*ALL LABELS*"
85
+ continue
86
+ for label in scope.labels_sorted_by_type:
87
+ scope_str += f"{label.name}\n"
88
+ # remove last \n from scope
89
+ if scope_str[-1] == "\n":
90
+ scope_str = scope_str[:-1]
91
+
92
+
93
+ consumers_str = rule.consumers.members_to_str("\n", prefix_objects_with_type=setting_prefix_objects_with_type,
94
+ object_types_as_section=setting_object_types_as_section)
95
+ providers_str = rule.providers.members_to_str("\n", prefix_objects_with_type=setting_prefix_objects_with_type,
96
+ object_types_as_section=setting_object_types_as_section)
97
+
98
+
99
+ data = {'ruleset': ruleset.name, 'scope': scope_str,
100
+ 'consumers': consumers_str,
101
+ 'providers': providers_str,
102
+ 'services': rule.services.members_to_str("\n"),
103
+ 'options': pylo.string_list_to_text(rule_options, "\n"),
104
+ 'ruleset_href': ruleset.href,
105
+ 'ruleset_url': ruleset.get_ruleset_url()}
106
+ if rule.is_extra_scope():
107
+ data['type'] = 'extra'
108
+ else:
109
+ data['type'] = 'intra'
110
+ sheet.add_line_from_object(data)
111
+
112
+ if output_file_format == "csv":
113
+ print(" * Writing export file '{}' ... ".format(output_file_name), end='', flush=True)
114
+ sheet.write_to_csv(output_file_name)
115
+ print("DONE")
116
+ elif output_file_format == "excel":
117
+ print(" * Writing export file '{}' ... ".format(output_file_name), end='', flush=True)
118
+ csv_report.write_to_excel(output_file_name)
119
+ print("DONE")
120
+ else:
121
+ raise pylo.PyloEx("Unknown format: '{}'".format(options['format']))
122
+
123
+
124
+ command_object = Command(command_name, __main, fill_parser)
125
+
126
+
127
+
128
+
129
+
@@ -0,0 +1,44 @@
1
+ import logging
2
+ import argparse
3
+ import illumio_pylo as pylo
4
+ import os
5
+ import datetime
6
+ import json
7
+
8
+ from illumio_pylo import log
9
+ from . import Command
10
+
11
+
12
+ command_name = "pce-objects-cache-updater"
13
+ objects_load_filter = None
14
+
15
+
16
+ def fill_parser(parser: argparse.ArgumentParser):
17
+ parser.add_argument('--include-deleted-workloads', action='store_true',
18
+ help='should deleted workloads be downloaded as well')
19
+
20
+
21
+ def __main(args, org: pylo.Organization = None, connector: pylo.APIConnector = None, config_data=None, **kwargs):
22
+
23
+ # filename should be like 'cache_xxx.yyy.zzz.json'
24
+ filename = 'cache_' + connector.name + '.json'
25
+
26
+ timestamp = datetime.datetime.now(datetime.timezone.utc)
27
+
28
+ json_content = {'generation_date': timestamp.isoformat(),
29
+ 'pce_version': connector.get_software_version_string(),
30
+ 'data': config_data,
31
+ }
32
+
33
+ with open(filename, 'w') as outfile:
34
+ json.dump(json_content, outfile)
35
+
36
+ size = os.path.getsize(filename)
37
+
38
+ print("\nPCE objects and settings were saved to file '%s' with a size of %iKB" % (filename, int(size/1024)))
39
+
40
+ print()
41
+
42
+
43
+ command_object = Command(command_name, __main, fill_parser, skip_pce_config_loading=True)
44
+