catocli 2.1.2__py3-none-any.whl → 2.1.4__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.
Potentially problematic release.
This version of catocli might be problematic. Click here for more details.
- catocli/Utils/clidriver.py +18 -18
- catocli/Utils/cliutils.py +165 -0
- catocli/Utils/csv_formatter.py +652 -0
- catocli/__init__.py +1 -1
- catocli/parsers/custom/export_rules/__init__.py +0 -4
- catocli/parsers/custom/export_sites/__init__.py +4 -3
- catocli/parsers/custom/export_sites/export_sites.py +198 -55
- catocli/parsers/custom/import_sites_to_tf/import_sites_to_tf.py +473 -393
- catocli/parsers/customParserApiClient.py +444 -38
- catocli/parsers/custom_private/__init__.py +19 -13
- catocli/parsers/mutation_accountManagement/__init__.py +21 -0
- catocli/parsers/mutation_accountManagement_disableAccount/README.md +15 -0
- catocli/parsers/mutation_admin/__init__.py +12 -0
- catocli/parsers/mutation_container/__init__.py +18 -0
- catocli/parsers/mutation_enterpriseDirectory/__init__.py +8 -0
- catocli/parsers/mutation_groups/__init__.py +6 -0
- catocli/parsers/mutation_hardware/__init__.py +2 -0
- catocli/parsers/mutation_policy/__init__.py +378 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_addRule/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_addSection/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_createPolicyRevision/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_discardPolicyRevision/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_moveRule/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_moveSection/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_publishPolicyRevision/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_removeRule/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_removeSection/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_updatePolicy/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_updateRule/README.md +20 -0
- catocli/parsers/mutation_policy_antiMalwareFileHash_updateSection/README.md +20 -0
- catocli/parsers/mutation_sandbox/__init__.py +4 -0
- catocli/parsers/mutation_site/__init__.py +72 -0
- catocli/parsers/mutation_sites/__init__.py +72 -0
- catocli/parsers/mutation_xdr/__init__.py +6 -0
- catocli/parsers/query_accountBySubdomain/__init__.py +2 -0
- catocli/parsers/query_accountManagement/__init__.py +2 -0
- catocli/parsers/query_accountMetrics/__init__.py +6 -0
- catocli/parsers/query_accountRoles/__init__.py +2 -0
- catocli/parsers/query_accountSnapshot/__init__.py +2 -0
- catocli/parsers/query_admin/__init__.py +2 -0
- catocli/parsers/query_admins/__init__.py +2 -0
- catocli/parsers/query_appStats/__init__.py +6 -0
- catocli/parsers/query_appStatsTimeSeries/README.md +3 -0
- catocli/parsers/query_appStatsTimeSeries/__init__.py +6 -0
- catocli/parsers/query_auditFeed/__init__.py +2 -0
- catocli/parsers/query_catalogs/__init__.py +2 -0
- catocli/parsers/query_container/__init__.py +2 -0
- catocli/parsers/query_devices/README.md +1 -1
- catocli/parsers/query_devices/__init__.py +2 -0
- catocli/parsers/query_enterpriseDirectory/__init__.py +2 -0
- catocli/parsers/query_entityLookup/__init__.py +2 -0
- catocli/parsers/query_events/__init__.py +2 -0
- catocli/parsers/query_eventsFeed/__init__.py +2 -0
- catocli/parsers/query_eventsTimeSeries/__init__.py +2 -0
- catocli/parsers/query_groups/__init__.py +6 -0
- catocli/parsers/query_hardware/README.md +1 -1
- catocli/parsers/query_hardware/__init__.py +2 -0
- catocli/parsers/query_hardwareManagement/__init__.py +2 -0
- catocli/parsers/query_licensing/__init__.py +2 -0
- catocli/parsers/query_policy/__init__.py +37 -0
- catocli/parsers/query_policy_antiMalwareFileHash_policy/README.md +19 -0
- catocli/parsers/query_popLocations/__init__.py +2 -0
- catocli/parsers/query_sandbox/__init__.py +2 -0
- catocli/parsers/query_servicePrincipalAdmin/__init__.py +2 -0
- catocli/parsers/query_site/__init__.py +33 -0
- catocli/parsers/query_siteLocation/__init__.py +2 -0
- catocli/parsers/query_site_siteGeneralDetails/README.md +19 -0
- catocli/parsers/query_socketPortMetrics/__init__.py +2 -0
- catocli/parsers/query_socketPortMetricsTimeSeries/__init__.py +6 -0
- catocli/parsers/query_subDomains/__init__.py +2 -0
- catocli/parsers/query_xdr/__init__.py +4 -0
- catocli/parsers/raw/__init__.py +3 -1
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/METADATA +1 -1
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/RECORD +98 -66
- models/mutation.accountManagement.disableAccount.json +545 -0
- models/mutation.policy.antiMalwareFileHash.addRule.json +2068 -0
- models/mutation.policy.antiMalwareFileHash.addSection.json +1350 -0
- models/mutation.policy.antiMalwareFileHash.createPolicyRevision.json +1822 -0
- models/mutation.policy.antiMalwareFileHash.discardPolicyRevision.json +1758 -0
- models/mutation.policy.antiMalwareFileHash.moveRule.json +1552 -0
- models/mutation.policy.antiMalwareFileHash.moveSection.json +1251 -0
- models/mutation.policy.antiMalwareFileHash.publishPolicyRevision.json +1813 -0
- models/mutation.policy.antiMalwareFileHash.removeRule.json +1204 -0
- models/mutation.policy.antiMalwareFileHash.removeSection.json +954 -0
- models/mutation.policy.antiMalwareFileHash.updatePolicy.json +1834 -0
- models/mutation.policy.antiMalwareFileHash.updateRule.json +1757 -0
- models/mutation.policy.antiMalwareFileHash.updateSection.json +1105 -0
- models/mutation.site.updateSiteGeneralDetails.json +3 -3
- models/mutation.sites.updateSiteGeneralDetails.json +3 -3
- models/query.devices.json +249 -2
- models/query.hardware.json +224 -0
- models/query.policy.antiMalwareFileHash.policy.json +1583 -0
- models/query.site.siteGeneralDetails.json +899 -0
- schema/catolib.py +52 -14
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/WHEEL +0 -0
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/entry_points.txt +0 -0
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/licenses/LICENSE +0 -0
- {catocli-2.1.2.dist-info → catocli-2.1.4.dist-info}/top_level.txt +0 -0
catocli/Utils/clidriver.py
CHANGED
|
@@ -49,18 +49,18 @@ from ..parsers.query_devices import query_devices_parse
|
|
|
49
49
|
from ..parsers.query_catalogs import query_catalogs_parse
|
|
50
50
|
from ..parsers.query_site import query_site_parse
|
|
51
51
|
from ..parsers.query_xdr import query_xdr_parse
|
|
52
|
-
from ..parsers.query_policy import query_policy_parse
|
|
53
52
|
from ..parsers.query_groups import query_groups_parse
|
|
53
|
+
from ..parsers.query_policy import query_policy_parse
|
|
54
54
|
from ..parsers.mutation_xdr import mutation_xdr_parse
|
|
55
|
-
from ..parsers.mutation_site import mutation_site_parse
|
|
56
55
|
from ..parsers.mutation_sites import mutation_sites_parse
|
|
56
|
+
from ..parsers.mutation_site import mutation_site_parse
|
|
57
57
|
from ..parsers.mutation_container import mutation_container_parse
|
|
58
58
|
from ..parsers.mutation_admin import mutation_admin_parse
|
|
59
|
-
from ..parsers.mutation_policy import mutation_policy_parse
|
|
60
59
|
from ..parsers.mutation_accountManagement import mutation_accountManagement_parse
|
|
61
60
|
from ..parsers.mutation_sandbox import mutation_sandbox_parse
|
|
62
|
-
from ..parsers.mutation_groups import mutation_groups_parse
|
|
63
61
|
from ..parsers.mutation_hardware import mutation_hardware_parse
|
|
62
|
+
from ..parsers.mutation_groups import mutation_groups_parse
|
|
63
|
+
from ..parsers.mutation_policy import mutation_policy_parse
|
|
64
64
|
from ..parsers.mutation_enterpriseDirectory import mutation_enterpriseDirectory_parse
|
|
65
65
|
|
|
66
66
|
def show_version_info(args, configuration=None):
|
|
@@ -85,15 +85,6 @@ def show_version_info(args, configuration=None):
|
|
|
85
85
|
else:
|
|
86
86
|
print("Unable to check for updates (check your internet connection)")
|
|
87
87
|
return [{"success": True, "current_version": catocli.__version__, "latest_version": latest_version if not args.current_only else None}]
|
|
88
|
-
|
|
89
|
-
def load_private_settings():
|
|
90
|
-
# Load private settings from ~/.cato/settings.json
|
|
91
|
-
settings_file = os.path.expanduser("~/.cato/settings.json")
|
|
92
|
-
try:
|
|
93
|
-
with open(settings_file, 'r') as f:
|
|
94
|
-
return json.load(f)
|
|
95
|
-
except (FileNotFoundError, json.JSONDecodeError):
|
|
96
|
-
return {}
|
|
97
88
|
|
|
98
89
|
def get_configuration(skip_api_key=False):
|
|
99
90
|
configuration = Configuration()
|
|
@@ -143,6 +134,8 @@ parser = argparse.ArgumentParser(prog='catocli', usage='%(prog)s <operationType>
|
|
|
143
134
|
parser.add_argument('--version', action='version', version=catocli.__version__)
|
|
144
135
|
parser.add_argument('-H', '--header', action='append', dest='headers', help='Add custom headers in "Key: Value" format. Can be used multiple times.')
|
|
145
136
|
parser.add_argument('--headers-file', dest='headers_file', help='Load headers from a file. Each line should contain a header in "Key: Value" format.')
|
|
137
|
+
parser.add_argument('-n', '--stream-events', dest='stream_events', help='Send events over network to host:port TCP')
|
|
138
|
+
parser.add_argument('-z', '--sentinel', dest='sentinel', help='Send events to Sentinel customerid:sharedkey')
|
|
146
139
|
subparsers = parser.add_subparsers()
|
|
147
140
|
|
|
148
141
|
# Version command - enhanced with update checking
|
|
@@ -190,18 +183,18 @@ query_devices_parser = query_devices_parse(query_subparsers)
|
|
|
190
183
|
query_catalogs_parser = query_catalogs_parse(query_subparsers)
|
|
191
184
|
query_site_parser = query_site_parse(query_subparsers)
|
|
192
185
|
query_xdr_parser = query_xdr_parse(query_subparsers)
|
|
193
|
-
query_policy_parser = query_policy_parse(query_subparsers)
|
|
194
186
|
query_groups_parser = query_groups_parse(query_subparsers)
|
|
187
|
+
query_policy_parser = query_policy_parse(query_subparsers)
|
|
195
188
|
mutation_xdr_parser = mutation_xdr_parse(mutation_subparsers)
|
|
196
|
-
mutation_site_parser = mutation_site_parse(mutation_subparsers)
|
|
197
189
|
mutation_sites_parser = mutation_sites_parse(mutation_subparsers)
|
|
190
|
+
mutation_site_parser = mutation_site_parse(mutation_subparsers)
|
|
198
191
|
mutation_container_parser = mutation_container_parse(mutation_subparsers)
|
|
199
192
|
mutation_admin_parser = mutation_admin_parse(mutation_subparsers)
|
|
200
|
-
mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
|
|
201
193
|
mutation_accountManagement_parser = mutation_accountManagement_parse(mutation_subparsers)
|
|
202
194
|
mutation_sandbox_parser = mutation_sandbox_parse(mutation_subparsers)
|
|
203
|
-
mutation_groups_parser = mutation_groups_parse(mutation_subparsers)
|
|
204
195
|
mutation_hardware_parser = mutation_hardware_parse(mutation_subparsers)
|
|
196
|
+
mutation_groups_parser = mutation_groups_parse(mutation_subparsers)
|
|
197
|
+
mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
|
|
205
198
|
mutation_enterpriseDirectory_parser = mutation_enterpriseDirectory_parse(mutation_subparsers)
|
|
206
199
|
|
|
207
200
|
|
|
@@ -285,7 +278,14 @@ def main(args=None):
|
|
|
285
278
|
print(response)
|
|
286
279
|
else:
|
|
287
280
|
if response!=None:
|
|
288
|
-
|
|
281
|
+
# Check if this is CSV output
|
|
282
|
+
if (isinstance(response, list) and len(response) > 0 and
|
|
283
|
+
isinstance(response[0], dict) and "__csv_output__" in response[0]):
|
|
284
|
+
# Print CSV output directly without JSON formatting
|
|
285
|
+
print(response[0]["__csv_output__"], end='')
|
|
286
|
+
else:
|
|
287
|
+
# Standard JSON output
|
|
288
|
+
print(json.dumps(response[0], sort_keys=True, indent=4))
|
|
289
289
|
except KeyboardInterrupt:
|
|
290
290
|
print('Operation cancelled by user (Ctrl+C).')
|
|
291
291
|
exit(130) # Standard exit code for SIGINT
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
General CLI utilities for catocli
|
|
4
|
+
|
|
5
|
+
This module contains general-purpose utility functions used across the catocli
|
|
6
|
+
package, including settings loading and configuration management.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Import for resource handling
|
|
14
|
+
try:
|
|
15
|
+
# Python 3.9+
|
|
16
|
+
from importlib.resources import files
|
|
17
|
+
def get_package_resource(package, filename):
|
|
18
|
+
return files(package).joinpath(filename).read_text(encoding='utf-8')
|
|
19
|
+
except ImportError:
|
|
20
|
+
try:
|
|
21
|
+
# Python 3.7-3.8
|
|
22
|
+
from importlib.resources import read_text
|
|
23
|
+
def get_package_resource(package, filename):
|
|
24
|
+
return read_text(package, filename, encoding='utf-8')
|
|
25
|
+
except ImportError:
|
|
26
|
+
try:
|
|
27
|
+
# Fallback to pkg_resources
|
|
28
|
+
import pkg_resources
|
|
29
|
+
def get_package_resource(package, filename):
|
|
30
|
+
return pkg_resources.resource_string(package, filename).decode('utf-8')
|
|
31
|
+
except ImportError:
|
|
32
|
+
# Final fallback - no package resources available
|
|
33
|
+
def get_package_resource(package, filename):
|
|
34
|
+
raise ImportError("No resource handling module available")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_cli_settings():
|
|
38
|
+
"""
|
|
39
|
+
Load clisettings.json from multiple possible locations:
|
|
40
|
+
1. Package resource (for installed packages)
|
|
41
|
+
2. Repository location (for development)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
dict: The loaded settings or default settings if loading fails
|
|
45
|
+
"""
|
|
46
|
+
settings_locations = [
|
|
47
|
+
# Try package resource first (for installed packages)
|
|
48
|
+
lambda: json.loads(get_package_resource('catocli', 'clisettings.json')),
|
|
49
|
+
# Try repository location (for development)
|
|
50
|
+
lambda: json.load(open(os.path.join(os.path.dirname(__file__), '../../clisettings.json'), 'r', encoding='utf-8'))
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
for i, load_func in enumerate(settings_locations):
|
|
54
|
+
try:
|
|
55
|
+
settings = load_func()
|
|
56
|
+
if settings:
|
|
57
|
+
return settings
|
|
58
|
+
except (FileNotFoundError, json.JSONDecodeError, ImportError, OSError, ModuleNotFoundError) as e:
|
|
59
|
+
# Continue to next location
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
# If all locations fail, return default settings for socket export
|
|
63
|
+
return {}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_cli_settings_path():
|
|
67
|
+
"""
|
|
68
|
+
Get the path to the CLI settings file, trying different locations.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
str or None: Path to the settings file if found, None otherwise
|
|
72
|
+
"""
|
|
73
|
+
possible_paths = [
|
|
74
|
+
# Repository location (for development)
|
|
75
|
+
os.path.join(os.path.dirname(__file__), '../../clisettings.json'),
|
|
76
|
+
# Current directory
|
|
77
|
+
os.path.join(os.getcwd(), 'clisettings.json'),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
for path in possible_paths:
|
|
81
|
+
if os.path.exists(path):
|
|
82
|
+
return path
|
|
83
|
+
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def load_json_file(file_path, encoding='utf-8'):
|
|
88
|
+
"""
|
|
89
|
+
Load a JSON file with error handling.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
file_path (str): Path to the JSON file
|
|
93
|
+
encoding (str): File encoding (default: utf-8)
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
dict or None: The loaded JSON data, or None if loading fails
|
|
97
|
+
"""
|
|
98
|
+
try:
|
|
99
|
+
with open(file_path, 'r', encoding=encoding) as f:
|
|
100
|
+
return json.load(f)
|
|
101
|
+
except (FileNotFoundError, json.JSONDecodeError, OSError) as e:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def save_json_file(data, file_path, encoding='utf-8', indent=2):
|
|
106
|
+
"""
|
|
107
|
+
Save data to a JSON file with error handling.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
data: Data to save
|
|
111
|
+
file_path (str): Path to save the JSON file
|
|
112
|
+
encoding (str): File encoding (default: utf-8)
|
|
113
|
+
indent (int): JSON indentation (default: 2)
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
bool: True if successful, False otherwise
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
# Ensure the directory exists
|
|
120
|
+
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
121
|
+
|
|
122
|
+
with open(file_path, 'w', encoding=encoding) as f:
|
|
123
|
+
json.dump(data, f, indent=indent, ensure_ascii=False)
|
|
124
|
+
return True
|
|
125
|
+
except (OSError, TypeError, ValueError) as e:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def load_private_settings():
|
|
130
|
+
"""
|
|
131
|
+
Load private settings from ~/.cato/settings.json in an OS-compatible way.
|
|
132
|
+
|
|
133
|
+
This function constructs the path to ~/.cato/settings.json using os.path methods
|
|
134
|
+
for cross-platform compatibility (Windows, Mac, Linux).
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
dict: The privateCommands section from the settings file, or empty dict if not found
|
|
138
|
+
"""
|
|
139
|
+
# Use os.path.join for OS-compatible path construction
|
|
140
|
+
cato_dir = os.path.join(os.path.expanduser("~"), ".cato")
|
|
141
|
+
settings_file = os.path.join(cato_dir, "settings.json")
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
with open(settings_file, 'r', encoding='utf-8') as f:
|
|
145
|
+
settings = json.load(f)
|
|
146
|
+
return settings.get('privateCommands', {})
|
|
147
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError, OSError):
|
|
148
|
+
return {}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def ensure_directory_exists(directory_path):
|
|
152
|
+
"""
|
|
153
|
+
Ensure a directory exists, creating it if necessary.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
directory_path (str): Path to the directory
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
bool: True if directory exists or was created successfully
|
|
160
|
+
"""
|
|
161
|
+
try:
|
|
162
|
+
os.makedirs(directory_path, exist_ok=True)
|
|
163
|
+
return True
|
|
164
|
+
except OSError:
|
|
165
|
+
return False
|