catocli 3.0.13__py3-none-any.whl → 3.0.18__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 +8 -8
- catocli/Utils/help_formatter.py +77 -9
- catocli/__init__.py +1 -1
- catocli/parsers/custom/query_eventsFeed/README.md +94 -0
- catocli/parsers/custom/scim/README.md +346 -0
- catocli/parsers/custom/scim/scim_client.py +132 -26
- catocli/parsers/custom/scim/scim_commands.py +14 -56
- catocli/parsers/customParserApiClient.py +7 -0
- catocli/parsers/query_accountMetrics/README.md +9 -9
- catocli/parsers/query_appStats/README.md +9 -9
- catocli/parsers/query_appStatsTimeSeries/README.md +10 -10
- catocli/parsers/query_auditFeed/README.md +9 -9
- catocli/parsers/query_events/README.md +9 -9
- catocli/parsers/query_eventsTimeSeries/README.md +9 -9
- catocli/parsers/query_socketPortMetrics/README.md +9 -9
- catocli/parsers/query_socketPortMetricsTimeSeries/README.md +9 -9
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/METADATA +1 -1
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/RECORD +23 -21
- schema/catolib.py +9 -9
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/WHEEL +0 -0
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/entry_points.txt +0 -0
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/licenses/LICENSE +0 -0
- {catocli-3.0.13.dist-info → catocli-3.0.18.dist-info}/top_level.txt +0 -0
catocli/Utils/clidriver.py
CHANGED
|
@@ -48,22 +48,22 @@ from ..parsers.query_enterpriseDirectory import query_enterpriseDirectory_parse
|
|
|
48
48
|
from ..parsers.query_devices import query_devices_parse
|
|
49
49
|
from ..parsers.query_accountSnapshot import query_accountSnapshot_parse
|
|
50
50
|
from ..parsers.query_catalogs import query_catalogs_parse
|
|
51
|
-
from ..parsers.query_site import query_site_parse
|
|
52
51
|
from ..parsers.query_xdr import query_xdr_parse
|
|
53
|
-
from ..parsers.
|
|
52
|
+
from ..parsers.query_site import query_site_parse
|
|
54
53
|
from ..parsers.query_groups import query_groups_parse
|
|
54
|
+
from ..parsers.query_policy import query_policy_parse
|
|
55
55
|
from ..parsers.mutation_xdr import mutation_xdr_parse
|
|
56
56
|
from ..parsers.mutation_policy import mutation_policy_parse
|
|
57
57
|
from ..parsers.mutation_site import mutation_site_parse
|
|
58
58
|
from ..parsers.mutation_sites import mutation_sites_parse
|
|
59
59
|
from ..parsers.mutation_container import mutation_container_parse
|
|
60
|
-
from ..parsers.mutation_admin import mutation_admin_parse
|
|
61
60
|
from ..parsers.mutation_accountManagement import mutation_accountManagement_parse
|
|
62
61
|
from ..parsers.mutation_sandbox import mutation_sandbox_parse
|
|
63
62
|
from ..parsers.mutation_licensing import mutation_licensing_parse
|
|
64
63
|
from ..parsers.mutation_hardware import mutation_hardware_parse
|
|
65
64
|
from ..parsers.mutation_groups import mutation_groups_parse
|
|
66
65
|
from ..parsers.mutation_enterpriseDirectory import mutation_enterpriseDirectory_parse
|
|
66
|
+
from ..parsers.mutation_admin import mutation_admin_parse
|
|
67
67
|
|
|
68
68
|
def show_version_info(args, configuration=None):
|
|
69
69
|
print(f"catocli version {catocli.__version__}")
|
|
@@ -183,22 +183,22 @@ query_enterpriseDirectory_parser = query_enterpriseDirectory_parse(query_subpars
|
|
|
183
183
|
query_devices_parser = query_devices_parse(query_subparsers)
|
|
184
184
|
query_accountSnapshot_parser = query_accountSnapshot_parse(query_subparsers)
|
|
185
185
|
query_catalogs_parser = query_catalogs_parse(query_subparsers)
|
|
186
|
-
query_site_parser = query_site_parse(query_subparsers)
|
|
187
186
|
query_xdr_parser = query_xdr_parse(query_subparsers)
|
|
188
|
-
|
|
187
|
+
query_site_parser = query_site_parse(query_subparsers)
|
|
189
188
|
query_groups_parser = query_groups_parse(query_subparsers)
|
|
189
|
+
query_policy_parser = query_policy_parse(query_subparsers)
|
|
190
190
|
mutation_xdr_parser = mutation_xdr_parse(mutation_subparsers)
|
|
191
191
|
mutation_policy_parser = mutation_policy_parse(mutation_subparsers)
|
|
192
192
|
mutation_site_parser = mutation_site_parse(mutation_subparsers)
|
|
193
193
|
mutation_sites_parser = mutation_sites_parse(mutation_subparsers)
|
|
194
194
|
mutation_container_parser = mutation_container_parse(mutation_subparsers)
|
|
195
|
-
mutation_admin_parser = mutation_admin_parse(mutation_subparsers)
|
|
196
195
|
mutation_accountManagement_parser = mutation_accountManagement_parse(mutation_subparsers)
|
|
197
196
|
mutation_sandbox_parser = mutation_sandbox_parse(mutation_subparsers)
|
|
198
197
|
mutation_licensing_parser = mutation_licensing_parse(mutation_subparsers)
|
|
199
198
|
mutation_hardware_parser = mutation_hardware_parse(mutation_subparsers)
|
|
200
199
|
mutation_groups_parser = mutation_groups_parse(mutation_subparsers)
|
|
201
200
|
mutation_enterpriseDirectory_parser = mutation_enterpriseDirectory_parse(mutation_subparsers)
|
|
201
|
+
mutation_admin_parser = mutation_admin_parse(mutation_subparsers)
|
|
202
202
|
|
|
203
203
|
|
|
204
204
|
def parse_headers(header_strings):
|
|
@@ -269,7 +269,7 @@ def main(args=None):
|
|
|
269
269
|
if custom_headers:
|
|
270
270
|
configuration.custom_headers.update(custom_headers)
|
|
271
271
|
# Handle account ID override (applies to all commands except raw)
|
|
272
|
-
if
|
|
272
|
+
if args.func.__name__ not in ["createRawRequest"]:
|
|
273
273
|
if hasattr(args, 'accountID') and args.accountID is not None:
|
|
274
274
|
# Command line override takes precedence
|
|
275
275
|
configuration.accountID = args.accountID
|
|
@@ -295,7 +295,7 @@ def main(args=None):
|
|
|
295
295
|
except Exception as e:
|
|
296
296
|
if isinstance(e, AttributeError):
|
|
297
297
|
print('Missing arguments. Usage: catocli <operation> -h')
|
|
298
|
-
if
|
|
298
|
+
if args.v==True:
|
|
299
299
|
print('ERROR: ',e)
|
|
300
300
|
traceback.print_exc()
|
|
301
301
|
else:
|
catocli/Utils/help_formatter.py
CHANGED
|
@@ -94,15 +94,16 @@ class JSONExample:
|
|
|
94
94
|
return [self.command_template.format(command=command_name, json=self.json_data)]
|
|
95
95
|
|
|
96
96
|
def _format_powershell_comprehensive(self, command_name: str) -> List[str]:
|
|
97
|
-
"""Format PowerShell here-string example with
|
|
98
|
-
#
|
|
97
|
+
"""Format PowerShell here-string example with proper quote escaping"""
|
|
98
|
+
# Escape double quotes in JSON for PowerShell compatibility
|
|
99
99
|
escaped_json = self.json_data.replace('"', '\\"')
|
|
100
100
|
|
|
101
|
+
# Use here-string format which handles quotes better in PowerShell
|
|
101
102
|
examples = [
|
|
102
|
-
"# PowerShell:",
|
|
103
|
+
"# PowerShell (using here-string):",
|
|
103
104
|
f"catocli {command_name} @'",
|
|
104
105
|
escaped_json,
|
|
105
|
-
"'@"
|
|
106
|
+
"'@ -p"
|
|
106
107
|
]
|
|
107
108
|
|
|
108
109
|
return examples
|
|
@@ -158,7 +159,7 @@ class JSONExample:
|
|
|
158
159
|
|
|
159
160
|
elif isinstance(obj, str):
|
|
160
161
|
# Use double quotes and escape internal quotes
|
|
161
|
-
escaped_str = obj.replace('"', '
|
|
162
|
+
escaped_str = obj.replace('"', '"')
|
|
162
163
|
return f'"{escaped_str}"'
|
|
163
164
|
elif isinstance(obj, bool):
|
|
164
165
|
return "$true" if obj else "$false"
|
|
@@ -228,8 +229,35 @@ class UniversalHelpFormatter:
|
|
|
228
229
|
for example in readme_examples:
|
|
229
230
|
# Check if this example starts with a comment (lines starting with #)
|
|
230
231
|
if example.startswith('#') and '\n' in example:
|
|
231
|
-
# This is a comment followed by a command -
|
|
232
|
-
|
|
232
|
+
# This is a comment followed by a command - need to format the command part
|
|
233
|
+
lines = example.split('\n', 1)
|
|
234
|
+
if len(lines) == 2:
|
|
235
|
+
comment_line = lines[0]
|
|
236
|
+
command_line = lines[1]
|
|
237
|
+
|
|
238
|
+
# Check if command has JSON and format appropriately
|
|
239
|
+
if '{' in command_line and '}' in command_line:
|
|
240
|
+
json_match = self._extract_json_from_example(command_line)
|
|
241
|
+
if json_match:
|
|
242
|
+
# Create JSONExample and apply platform-specific formatting
|
|
243
|
+
json_example = JSONExample(json_match)
|
|
244
|
+
formatted_commands = json_example.format_for_platform(self.platform_info, command_name)
|
|
245
|
+
# Add comment first, then formatted commands
|
|
246
|
+
help_lines.append(comment_line)
|
|
247
|
+
help_lines.extend(formatted_commands)
|
|
248
|
+
else:
|
|
249
|
+
# JSON extraction failed, format as simple command
|
|
250
|
+
formatted_command = self._format_simple_command_for_platform(command_line)
|
|
251
|
+
help_lines.append(comment_line)
|
|
252
|
+
help_lines.append(formatted_command)
|
|
253
|
+
else:
|
|
254
|
+
# Simple command - apply platform formatting
|
|
255
|
+
formatted_command = self._format_simple_command_for_platform(command_line)
|
|
256
|
+
help_lines.append(comment_line)
|
|
257
|
+
help_lines.append(formatted_command)
|
|
258
|
+
else:
|
|
259
|
+
# Fallback - preserve as-is
|
|
260
|
+
help_lines.append(example)
|
|
233
261
|
elif '{' in example and '}' in example:
|
|
234
262
|
# Check if this is a multi-line JSON example that can be platform-formatted
|
|
235
263
|
json_match = self._extract_json_from_example(example)
|
|
@@ -242,8 +270,9 @@ class UniversalHelpFormatter:
|
|
|
242
270
|
# Preserve as-is if it has comments or JSON extraction fails
|
|
243
271
|
help_lines.append(example)
|
|
244
272
|
else:
|
|
245
|
-
# Simple command examples without JSON
|
|
246
|
-
|
|
273
|
+
# Simple command examples without JSON - apply platform formatting
|
|
274
|
+
formatted_example = self._format_simple_command_for_platform(example)
|
|
275
|
+
help_lines.append(formatted_example)
|
|
247
276
|
help_lines.append("") # Add spacing between examples
|
|
248
277
|
|
|
249
278
|
description_examples = []
|
|
@@ -394,6 +423,45 @@ class UniversalHelpFormatter:
|
|
|
394
423
|
|
|
395
424
|
return unique_examples
|
|
396
425
|
|
|
426
|
+
def _format_simple_command_for_platform(self, example: str) -> str:
|
|
427
|
+
"""Format a simple command example for the current platform"""
|
|
428
|
+
# If it's already a comment or doesn't contain catocli command, return as-is
|
|
429
|
+
if example.startswith('#') or 'catocli' not in example:
|
|
430
|
+
return example
|
|
431
|
+
|
|
432
|
+
# For Windows, we need to adjust command syntax
|
|
433
|
+
if self.platform_info.platform == 'windows':
|
|
434
|
+
if self.platform_info.shell == 'powershell':
|
|
435
|
+
# PowerShell-specific adjustments
|
|
436
|
+
# Convert Unix-style command substitution to PowerShell equivalent
|
|
437
|
+
if '$(cat' in example:
|
|
438
|
+
# Handle different $(cat) variations
|
|
439
|
+
import re
|
|
440
|
+
# Pattern for $(cat file.json) or $(cat < file.json)
|
|
441
|
+
cat_pattern = r'\$\(cat\s*<?\s*([^\)]+)\)'
|
|
442
|
+
def replace_cat(match):
|
|
443
|
+
filename = match.group(1).strip()
|
|
444
|
+
return f'(Get-Content {filename} -Raw)'
|
|
445
|
+
example = re.sub(cat_pattern, replace_cat, example)
|
|
446
|
+
# Handle quotes - PowerShell prefers double quotes for JSON strings
|
|
447
|
+
# But for simple parameter examples, keep single quotes for strings
|
|
448
|
+
return example
|
|
449
|
+
elif self.platform_info.shell == 'cmd':
|
|
450
|
+
# CMD-specific adjustments - CMD has many limitations
|
|
451
|
+
if '$(cat ' in example:
|
|
452
|
+
return "# CMD: Save JSON to file first, then use the file path"
|
|
453
|
+
elif len(example) > 100:
|
|
454
|
+
return "# CMD: Use PowerShell for complex commands - CMD has line length limits"
|
|
455
|
+
# For CMD, convert single quotes to double quotes for JSON
|
|
456
|
+
if "'{" in example and "}'" in example:
|
|
457
|
+
example = example.replace("'{", '"{')
|
|
458
|
+
example = example.replace("}'", '}"')
|
|
459
|
+
# Escape internal double quotes
|
|
460
|
+
# This is complex, so provide a simplification
|
|
461
|
+
return "# CMD: " + example + " (escape internal quotes as needed)"
|
|
462
|
+
|
|
463
|
+
return example
|
|
464
|
+
|
|
397
465
|
def _extract_json_from_example(self, example: str) -> str:
|
|
398
466
|
"""Extract JSON data from a catocli command example"""
|
|
399
467
|
try:
|
catocli/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "3.0.
|
|
1
|
+
__version__ = "3.0.18"
|
|
2
2
|
__cato_host__ = "https://api.catonetworks.com/api/v1/graphql2"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
|
|
2
|
+
## CATO-CLI - Enhanced query.eventsFeed:
|
|
3
|
+
[Click here](https://api.catonetworks.com/documentation/#query-query.eventsFeed) for documentation on this operation.
|
|
4
|
+
|
|
5
|
+
### Basic Usage for query.eventsFeed:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Show help for all available options
|
|
9
|
+
catocli query eventsFeed -h
|
|
10
|
+
|
|
11
|
+
# Standard eventsFeed query (basic GraphQL mode)
|
|
12
|
+
catocli query eventsFeed '{"marker": ""}'
|
|
13
|
+
|
|
14
|
+
# Start from beginning of event queue
|
|
15
|
+
catocli query eventsFeed '{"marker": ""}' -p
|
|
16
|
+
|
|
17
|
+
# Use a JSON file for complex queries
|
|
18
|
+
catocli query eventsFeed "$(cat query.eventsFeed.json)"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Enhanced Usage (with advanced features):
|
|
22
|
+
|
|
23
|
+
The enhanced eventsFeed supports additional features like marker persistence, continuous polling, filtering, and streaming.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Basic enhanced mode: fetch once and print events
|
|
27
|
+
catocli query eventsFeed --print-events --prettify
|
|
28
|
+
|
|
29
|
+
# Start from beginning with run mode (continuous polling)
|
|
30
|
+
catocli query eventsFeed --run --print-events -v
|
|
31
|
+
|
|
32
|
+
# Use marker file for persistent position tracking
|
|
33
|
+
catocli query eventsFeed --marker-file=./events-marker.txt --print-events
|
|
34
|
+
|
|
35
|
+
# Continuous mode with marker persistence
|
|
36
|
+
catocli query eventsFeed --run --marker-file=./events-marker.txt --print-events -v
|
|
37
|
+
|
|
38
|
+
# Filter by event types
|
|
39
|
+
catocli query eventsFeed --print-events --event-types="Connectivity,Security"
|
|
40
|
+
|
|
41
|
+
# Filter by event sub-types
|
|
42
|
+
catocli query eventsFeed --print-events --event-sub-types="Internet Firewall,WAN Firewall"
|
|
43
|
+
|
|
44
|
+
# Network streaming with newlines
|
|
45
|
+
catocli query eventsFeed --run -n 192.168.1.100:8000 --append-new-line -v
|
|
46
|
+
|
|
47
|
+
# Send to Azure Sentinel
|
|
48
|
+
catocli query eventsFeed --run -z "workspace-id:shared-key"
|
|
49
|
+
|
|
50
|
+
# Combined: display locally AND stream to network
|
|
51
|
+
catocli query eventsFeed --run --print-events --prettify -n 192.168.1.100:8000 -anl
|
|
52
|
+
|
|
53
|
+
# With fetch and runtime limits
|
|
54
|
+
catocli query eventsFeed --run --print-events --fetch-limit=50 --runtime-limit=3600
|
|
55
|
+
|
|
56
|
+
# Very verbose debugging
|
|
57
|
+
catocli query eventsFeed --marker-file=./marker.txt --print-events -vv
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
#### Operation Arguments for query.eventsFeed ####
|
|
62
|
+
|
|
63
|
+
##### Core GraphQL Arguments:
|
|
64
|
+
`accountIDs` [ID[]] - (required) List of Unique Account Identifiers.
|
|
65
|
+
`eventFeedFieldFilterInput` [EventFeedFieldFilterInput[]] - (required) N/A
|
|
66
|
+
`fieldNames` [EventFieldName[]] - (required) N/A Default Value: ['access_method', 'account_id', 'action', 'actions_taken', 'ad_name', 'alert_id', 'always_on_configuration', 'analyst_verdict', 'api_name', 'api_type', 'app_activity', 'app_activity_category', 'app_activity_type', 'app_stack', 'application_id', 'application_name', 'application_risk', 'auth_method', 'authentication_type', 'bgp_cato_asn', 'bgp_cato_ip', 'bgp_error_code', 'bgp_peer_asn', 'bgp_peer_ip', 'bgp_route_cidr', 'bgp_suberror_code', 'bypass_duration_sec', 'bypass_method', 'bypass_reason', 'categories', 'cato_app', 'classification', 'client_cert_expires', 'client_cert_name', 'client_class', 'client_version', 'collaborator_name', 'collaborators', 'confidence_level', 'configured_host_name', 'congestion_algorithm', 'connect_on_boot', 'connection_origin', 'connector_name', 'connector_status', 'connector_type', 'container_name', 'correlation_id', 'criticality', 'custom_category_id', 'custom_category_name', 'dest_country', 'dest_country_code', 'dest_group_id', 'dest_group_name', 'dest_ip', 'dest_is_site_or_vpn', 'dest_pid', 'dest_port', 'dest_process_cmdline', 'dest_process_parent_path', 'dest_process_parent_pid', 'dest_process_path', 'dest_site_id', 'dest_site_name', 'detection_name', 'detection_stage', 'device_categories', 'device_certificate', 'device_id', 'device_manufacturer', 'device_model', 'device_name', 'device_os_type', 'device_posture_profile', 'device_type', 'directory_host_name', 'directory_ip', 'directory_sync_result', 'directory_sync_type', 'disinfect_result', 'dlp_fail_mode', 'dlp_profiles', 'dlp_scan_types', 'dns_protection_category', 'dns_query', 'domain_name', 'egress_pop_name', 'egress_site_name', 'email_subject', 'endpoint_id', 'engine_type', 'epp_engine_type', 'epp_profile', 'event_count', 'event_id', 'event_message', 'event_sub_type', 'event_type', 'failure_reason', 'file_hash', 'file_name', 'file_operation', 'file_size', 'file_type', 'final_object_status', 'flows_cardinality', 'full_path_url', 'guest_user', 'host_ip', 'host_mac', 'http_request_method', 'incident_aggregation', 'incident_id', 'indication', 'indicator', 'initial_object_status', 'internalId', 'ip_protocol', 'is_admin', 'is_admin_activity', 'is_compliant', 'is_managed', 'is_sanctioned_app', 'is_sinkhole', 'ISP_name', 'key_name', 'labels', 'link_health_is_congested', 'link_health_jitter', 'link_health_latency', 'link_health_pkt_loss', 'link_type', 'logged_in_user', 'login_type', 'matched_data_types', 'mitre_attack_subtechniques', 'mitre_attack_tactics', 'mitre_attack_techniques', 'network_access', 'network_rule', 'notification_api_error', 'notification_description', 'object_id', 'object_name', 'object_type', 'office_mode', 'os_type', 'os_version', 'out_of_band_access', 'owner', 'pac_file', 'parent_connector_name', 'pop_name', 'precedence', 'processes_count', 'producer', 'projects', 'prompt_action', 'provider_name', 'public_ip', 'qos_priority', 'qos_reported_time', 'quarantine_folder_path', 'quarantine_uuid', 'raw_data', 'recommended_actions', 'reference_url', 'referer_url', 'region_name', 'registration_code', 'resource_id', 'risk_level', 'rule_id', 'rule_name', 'service_name', 'severity', 'sharing_scope', 'sign_in_event_types', 'signature_id', 'socket_interface', 'socket_interface_id', 'socket_new_version', 'socket_old_version', 'socket_reset', 'socket_role', 'socket_serial', 'socket_version', 'split_tunnel_configuration', 'src_country', 'src_country_code', 'src_ip', 'src_is_site_or_vpn', 'src_isp_ip', 'src_pid', 'src_port', 'src_process_cmdline', 'src_process_parent_path', 'src_process_parent_pid', 'src_process_path', 'src_site_id', 'src_site_name', 'static_host', 'status', 'story_id', 'subnet_name', 'subscription_name', 'targets_cardinality', 'tcp_acceleration', 'tenant_id', 'tenant_name', 'tenant_restriction_rule_name', 'threat_confidence', 'threat_name', 'threat_reference', 'threat_score', 'threat_type', 'threat_verdict', 'time', 'time_str', 'title', 'tls_certificate_error', 'tls_error_description', 'tls_error_type', 'tls_inspection', 'tls_rule_name', 'tls_version', 'traffic_direction', 'translated_client_ip', 'translated_server_ip', 'trigger', 'trust_type', 'trusted_networks', 'tunnel_ip_protocol', 'tunnel_protocol', 'upgrade_end_time', 'upgrade_initiated_by', 'upgrade_start_time', 'url', 'user_agent', 'user_awareness_method', 'user_id', 'user_name', 'user_reference_id', 'user_risk_level', 'vendor', 'vendor_collaborator_id', 'vendor_device_id', 'vendor_device_name', 'vendor_event_id', 'vendor_policy_description', 'vendor_policy_id', 'vendor_policy_name', 'vendor_user_id', 'visible_device_id', 'vpn_lan_access', 'vpn_user_email', 'windows_domain_name', 'xff']
|
|
67
|
+
`marker` [String] - (required) Marker to use to get results from
|
|
68
|
+
|
|
69
|
+
##### Enhanced Features Arguments:
|
|
70
|
+
`--run` [Flag] - Enable run mode with continuous polling and advanced features
|
|
71
|
+
`--print-events` [Flag] - Print event records to console
|
|
72
|
+
`--prettify` [Flag] - Prettify JSON output
|
|
73
|
+
`--marker` [String] - Initial marker value (default: "", start of queue)
|
|
74
|
+
`--marker-file` [String] - Marker file location for persistence (default: ./events-marker.txt)
|
|
75
|
+
`--event-types` [String] - Comma-separated list of event types to filter on
|
|
76
|
+
`--event-sub-types` [String] - Comma-separated list of event sub types to filter on
|
|
77
|
+
`--fetch-limit` [Integer] - Stop if a fetch returns less than this number of events (default: 1)
|
|
78
|
+
`--runtime-limit` [Integer] - Stop after this many seconds (default: unlimited)
|
|
79
|
+
`-vv, --very-verbose` [Flag] - Print detailed debug information
|
|
80
|
+
`--append-new-line, -anl` [Flag] - Append newline character (\n) to events sent via -n or -z
|
|
81
|
+
`-n, --stream-events` [String] - Send events to host:port TCP
|
|
82
|
+
`-z, --sentinel` [String] - Send to Azure Sentinel customerid:sharedkey
|
|
83
|
+
`-v` [Flag] - Verbose output (inherited from catocli)
|
|
84
|
+
`-p` [Flag] - Pretty print (inherited from catocli)
|
|
85
|
+
|
|
86
|
+
##### Key Features:
|
|
87
|
+
- **Native Authentication**: Uses ~/.cato profile credentials automatically
|
|
88
|
+
- **Compression**: Leverages catocli's built-in gzip compression for performance
|
|
89
|
+
- **Marker Persistence**: Automatically saves position in event queue
|
|
90
|
+
- **Continuous Polling**: Supports long-running event collection
|
|
91
|
+
- **Advanced Filtering**: Filter by event types and sub-types
|
|
92
|
+
- **Network Streaming**: Stream events to TCP endpoints
|
|
93
|
+
- **Azure Sentinel**: Direct integration with Microsoft Sentinel
|
|
94
|
+
- **Rate Limiting**: Built-in API rate limit handling
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
# SCIM (System for Cross-domain Identity Management) Commands
|
|
2
|
+
|
|
3
|
+
The Cato CLI provides comprehensive support for SCIM operations to manage users and groups via the Cato SCIM API. This enables automated user provisioning and group management for identity providers and custom integrations.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before using SCIM commands, you need to configure SCIM credentials in your profile:
|
|
8
|
+
|
|
9
|
+
1. **SCIM URL**: The SCIM service endpoint provided by Cato
|
|
10
|
+
- Format: `https://scimservice.catonetworks.com:4443/scim/v2/{accountId}/{sourceId}`
|
|
11
|
+
- Example: `https://scimservice.catonetworks.com:4443/scim/v2/12345/67890`
|
|
12
|
+
|
|
13
|
+
2. **SCIM Bearer Token**: Authentication token for SCIM access
|
|
14
|
+
- Example: `cfda146dc7c12345abcde`
|
|
15
|
+
|
|
16
|
+
## Configuration
|
|
17
|
+
|
|
18
|
+
### Add SCIM Credentials to Profile
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Interactive configuration (recommended)
|
|
22
|
+
catocli configure set
|
|
23
|
+
|
|
24
|
+
# Non-interactive configuration
|
|
25
|
+
catocli configure set --scim-url "https://scimservice.catonetworks.com:4443/scim/v2/12345/67890" --scim-token "your-bearer-token"
|
|
26
|
+
|
|
27
|
+
# Add SCIM credentials to specific profile
|
|
28
|
+
catocli configure set --profile production --scim-url "your-scim-url" --scim-token "your-bearer-token"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### View Profile with SCIM Credentials
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
catocli configure show
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For detailed setup instructions, see: [Using the Cato SCIM API for Custom SCIM Apps](https://support.catonetworks.com/hc/en-us/articles/29492743031581-Using-the-Cato-SCIM-API-for-Custom-SCIM-Apps)
|
|
38
|
+
|
|
39
|
+
## User Management Commands
|
|
40
|
+
|
|
41
|
+
### Get All Users
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Get all SCIM users
|
|
45
|
+
catocli scim get_users
|
|
46
|
+
|
|
47
|
+
# With verbose output
|
|
48
|
+
catocli scim get_users --verbose
|
|
49
|
+
|
|
50
|
+
# With pretty-printed JSON
|
|
51
|
+
catocli scim get_users --pretty
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Get Specific User
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Get user by SCIM ID
|
|
58
|
+
catocli scim get_user "6283630dfd7ec758a8bf4b61"
|
|
59
|
+
|
|
60
|
+
# With verbose output
|
|
61
|
+
catocli scim get_user "6283630dfd7ec758a8bf4b61" --verbose
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Find Users
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Find users by email
|
|
68
|
+
catocli scim find_users email "john.doe@company.com"
|
|
69
|
+
|
|
70
|
+
# Find users by username
|
|
71
|
+
catocli scim find_users userName "john.doe"
|
|
72
|
+
|
|
73
|
+
# Find users by given name (first name)
|
|
74
|
+
catocli scim find_users givenName "John"
|
|
75
|
+
|
|
76
|
+
# Find users by family name (last name)
|
|
77
|
+
catocli scim find_users familyName "Doe"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Create User
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Create a new user (password will be auto-generated)
|
|
84
|
+
catocli scim create_user "jane.doe@company.com" "Jane" "Doe" "external123"
|
|
85
|
+
|
|
86
|
+
# Create user with specific password
|
|
87
|
+
catocli scim create_user "jane.doe@company.com" "Jane" "Doe" "external123" --password "SecurePass123!"
|
|
88
|
+
|
|
89
|
+
# Create inactive user
|
|
90
|
+
catocli scim create_user "jane.doe@company.com" "Jane" "Doe" "external123" --inactive
|
|
91
|
+
|
|
92
|
+
# Create active user (default behavior)
|
|
93
|
+
catocli scim create_user "jane.doe@company.com" "Jane" "Doe" "external123" --active
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Update User
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Update user with complete user data (JSON format)
|
|
100
|
+
catocli scim update_user "6283630dfd7ec758a8bf4b61" '{
|
|
101
|
+
"userName": "john.doe@company.com",
|
|
102
|
+
"name": {
|
|
103
|
+
"givenName": "John",
|
|
104
|
+
"familyName": "Doe"
|
|
105
|
+
},
|
|
106
|
+
"emails": [
|
|
107
|
+
{
|
|
108
|
+
"primary": true,
|
|
109
|
+
"value": "john.doe@company.com",
|
|
110
|
+
"type": "work"
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"active": true
|
|
114
|
+
}'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Disable User
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Disable a user by SCIM ID
|
|
121
|
+
catocli scim disable_user "6283630dfd7ec758a8bf4b61"
|
|
122
|
+
|
|
123
|
+
# With verbose output
|
|
124
|
+
catocli scim disable_user "6283630dfd7ec758a8bf4b61" --verbose
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Group Management Commands
|
|
128
|
+
|
|
129
|
+
### Get All Groups
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Get all SCIM groups
|
|
133
|
+
catocli scim get_groups
|
|
134
|
+
|
|
135
|
+
# With verbose output
|
|
136
|
+
catocli scim get_groups --verbose
|
|
137
|
+
|
|
138
|
+
# With pretty-printed JSON
|
|
139
|
+
catocli scim get_groups --pretty
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Get Specific Group
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Get group by SCIM ID
|
|
146
|
+
catocli scim get_group "6283630dfd7ec758a8bf4b62"
|
|
147
|
+
|
|
148
|
+
# With verbose output
|
|
149
|
+
catocli scim get_group "6283630dfd7ec758a8bf4b62" --verbose
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Find Groups
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Find groups by display name
|
|
156
|
+
catocli scim find_group "Development Team"
|
|
157
|
+
|
|
158
|
+
# With verbose output
|
|
159
|
+
catocli scim find_group "Development Team" --verbose
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Create Group
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Create a new group without members
|
|
166
|
+
catocli scim create_group "Marketing Team" "marketing-external-id"
|
|
167
|
+
|
|
168
|
+
# Create group with initial members
|
|
169
|
+
catocli scim create_group "Sales Team" "sales-external-id" '[
|
|
170
|
+
{"value": "6283630dfd7ec758a8bf4b61"},
|
|
171
|
+
{"value": "6283630dfd7ec758a8bf4b62"}
|
|
172
|
+
]'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Update Group
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Update group with complete group data
|
|
179
|
+
catocli scim update_group "6283630dfd7ec758a8bf4b62" '{
|
|
180
|
+
"displayName": "Updated Team Name",
|
|
181
|
+
"members": [
|
|
182
|
+
{
|
|
183
|
+
"value": "6283630dfd7ec758a8bf4b61",
|
|
184
|
+
"display": "john.doe@company.com"
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}'
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Rename Group
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Rename a group
|
|
194
|
+
catocli scim rename_group "6283630dfd7ec758a8bf4b62" "New Team Name"
|
|
195
|
+
|
|
196
|
+
# With verbose output
|
|
197
|
+
catocli scim rename_group "6283630dfd7ec758a8bf4b62" "New Team Name" --verbose
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Disable Group
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Disable a group by SCIM ID
|
|
204
|
+
catocli scim disable_group "6283630dfd7ec758a8bf4b62"
|
|
205
|
+
|
|
206
|
+
# With verbose output
|
|
207
|
+
catocli scim disable_group "6283630dfd7ec758a8bf4b62" --verbose
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Group Membership Management
|
|
211
|
+
|
|
212
|
+
### Add Members to Group
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Add single member to group
|
|
216
|
+
catocli scim add_members "6283630dfd7ec758a8bf4b62" '[{"value": "6283630dfd7ec758a8bf4b61"}]'
|
|
217
|
+
|
|
218
|
+
# Add multiple members to group
|
|
219
|
+
catocli scim add_members "6283630dfd7ec758a8bf4b62" '[
|
|
220
|
+
{"value": "6283630dfd7ec758a8bf4b61"},
|
|
221
|
+
{"value": "6283630dfd7ec758a8bf4b63"},
|
|
222
|
+
{"value": "6283630dfd7ec758a8bf4b64"}
|
|
223
|
+
]'
|
|
224
|
+
|
|
225
|
+
# With verbose output
|
|
226
|
+
catocli scim add_members "group-id" '[{"value": "user-id"}]' --verbose
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Remove Members from Group
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# Remove single member from group
|
|
233
|
+
catocli scim remove_members "6283630dfd7ec758a8bf4b62" '[{"value": "6283630dfd7ec758a8bf4b61"}]'
|
|
234
|
+
|
|
235
|
+
# Remove multiple members from group
|
|
236
|
+
catocli scim remove_members "6283630dfd7ec758a8bf4b62" '[
|
|
237
|
+
{"value": "6283630dfd7ec758a8bf4b61"},
|
|
238
|
+
{"value": "6283630dfd7ec758a8bf4b63"}
|
|
239
|
+
]'
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Common Options
|
|
243
|
+
|
|
244
|
+
All SCIM commands support these common options:
|
|
245
|
+
|
|
246
|
+
- `--verbose` or `-v`: Show detailed output and progress information
|
|
247
|
+
- `--pretty` or `-p`: Pretty print JSON output for better readability
|
|
248
|
+
|
|
249
|
+
## Error Handling
|
|
250
|
+
|
|
251
|
+
If SCIM credentials are missing or invalid, you'll see helpful error messages:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
$ catocli scim get_users
|
|
255
|
+
ERROR: Profile 'default' is missing SCIM credentials: scim_url, scim_token
|
|
256
|
+
Run 'catocli configure set --profile default' to add SCIM credentials.
|
|
257
|
+
For more information, see: https://support.catonetworks.com/hc/en-us/articles/29492743031581-Using-the-Cato-SCIM-API-for-Custom-SCIM-Apps
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## JSON Format Examples
|
|
261
|
+
|
|
262
|
+
### User JSON Structure
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"id": "6283630dfd7ec758a8bf4b61",
|
|
267
|
+
"userName": "john.doe@company.com",
|
|
268
|
+
"name": {
|
|
269
|
+
"givenName": "John",
|
|
270
|
+
"familyName": "Doe"
|
|
271
|
+
},
|
|
272
|
+
"emails": [
|
|
273
|
+
{
|
|
274
|
+
"primary": true,
|
|
275
|
+
"value": "john.doe@company.com",
|
|
276
|
+
"type": "work"
|
|
277
|
+
}
|
|
278
|
+
],
|
|
279
|
+
"active": true
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Group JSON Structure
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"id": "6283630dfd7ec758a8bf4b62",
|
|
288
|
+
"displayName": "Development Team",
|
|
289
|
+
"members": [
|
|
290
|
+
{
|
|
291
|
+
"value": "6283630dfd7ec758a8bf4b61",
|
|
292
|
+
"display": "john.doe@company.com"
|
|
293
|
+
}
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Member Array Format
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
[
|
|
302
|
+
{"value": "6283630dfd7ec758a8bf4b61"},
|
|
303
|
+
{"value": "6283630dfd7ec758a8bf4b62"}
|
|
304
|
+
]
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Integration Examples
|
|
308
|
+
|
|
309
|
+
### Bulk User Creation from CSV
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
#!/bin/bash
|
|
313
|
+
# Read CSV file and create users
|
|
314
|
+
while IFS=',' read -r email given_name family_name; do
|
|
315
|
+
catocli scim create_user "$email" "$given_name" "$family_name" --verbose
|
|
316
|
+
done < users.csv
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Group Membership Sync
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
#!/bin/bash
|
|
323
|
+
# Add users to a group
|
|
324
|
+
GROUP_ID="6283630dfd7ec758a8bf4b62"
|
|
325
|
+
USER_IDS=("6283630dfd7ec758a8bf4b61" "6283630dfd7ec758a8bf4b63")
|
|
326
|
+
|
|
327
|
+
# Build members JSON array
|
|
328
|
+
MEMBERS_JSON="["
|
|
329
|
+
for i in "${!USER_IDS[@]}"; do
|
|
330
|
+
if [ $i -ne 0 ]; then
|
|
331
|
+
MEMBERS_JSON+=","
|
|
332
|
+
fi
|
|
333
|
+
MEMBERS_JSON+="{\"value\": \"${USER_IDS[$i]}\"}"
|
|
334
|
+
done
|
|
335
|
+
MEMBERS_JSON+="]"
|
|
336
|
+
|
|
337
|
+
# Add members to group
|
|
338
|
+
catocli scim add_members "$GROUP_ID" "$MEMBERS_JSON" --verbose
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Support
|
|
342
|
+
|
|
343
|
+
For SCIM API setup and configuration assistance, refer to:
|
|
344
|
+
- [Using the Cato SCIM API for Custom SCIM Apps](https://support.catonetworks.com/hc/en-us/articles/29492743031581-Using-the-Cato-SCIM-API-for-Custom-SCIM-Apps)
|
|
345
|
+
|
|
346
|
+
For CLI-specific issues, use the `--verbose` flag to get detailed error information and check your profile configuration with `catocli configure show`.
|