From 582d04d4a4d6c31db7b9ab7d67b1727c6f8b4a2f Mon Sep 17 00:00:00 2001 From: SeaBlooms Date: Wed, 10 Sep 2025 12:51:48 -0600 Subject: [PATCH 1/2] fix for multiple action_configs for alert rule creation --- examples/05_alert_rules_and_smartclasses.py | 34 ++++++++++----------- jupiterone/client.py | 23 ++++++++++---- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/examples/05_alert_rules_and_smartclasses.py b/examples/05_alert_rules_and_smartclasses.py index 24fc0d5..a080dcf 100644 --- a/examples/05_alert_rules_and_smartclasses.py +++ b/examples/05_alert_rules_and_smartclasses.py @@ -36,7 +36,7 @@ def alert_rule_examples(j1): severity="HIGH", j1ql="FIND Database WITH encrypted = false" ) - print(f"Created basic alert rule: {basic_rule['rule']['_id']}\n") + print(f"Created basic alert rule: {basic_rule['id']}\n") # 2. Complex alert rule with multiple conditions print("2. Creating a complex alert rule:") @@ -55,7 +55,7 @@ def alert_rule_examples(j1): AND u.tag.Role != 'admin' """ ) - print(f"Created complex alert rule: {complex_rule['rule']['_id']}\n") + print(f"Created complex alert rule: {complex_rule['id']}\n") return basic_rule, complex_rule @@ -135,7 +135,7 @@ def alert_rule_with_actions_examples(j1): j1ql="FIND Finding WITH severity = 'HIGH'", action_configs=webhook_action_config ) - print(f"Created webhook alert rule: {webhook_rule['rule']['_id']}\n") + print(f"Created webhook alert rule: {webhook_rule['id']}\n") # Create alert rule with multiple actions print("2. Creating alert rule with multiple actions:") @@ -149,7 +149,7 @@ def alert_rule_with_actions_examples(j1): j1ql="FIND Finding WITH severity = ('HIGH' OR 'CRITICAL')", action_configs=multiple_actions ) - print(f"Created multi-action alert rule: {multi_action_rule['rule']['_id']}\n") + print(f"Created multi-action alert rule: {multi_action_rule['id']}\n") return webhook_rule, multi_action_rule @@ -162,16 +162,16 @@ def alert_rule_management_examples(j1, rule_id): print("1. Getting alert rule details:") try: rule_details = j1.get_alert_rule_details(rule_id=rule_id) - print(f"Rule: {rule_details['rule']['name']}") - print(f"Description: {rule_details['rule']['description']}") - print(f"J1QL: {rule_details['rule']['j1ql']}") - print(f"Severity: {rule_details['rule']['severity']}") - print(f"Polling Interval: {rule_details['rule']['pollingInterval']}") + print(f"Rule: {rule_details['name']}") + print(f"Description: {rule_details['description']}") + print(f"J1QL: {rule_details.get('j1ql', 'N/A')}") + print(f"Severity: {rule_details.get('severity', 'N/A')}") + print(f"Polling Interval: {rule_details.get('pollingInterval', 'N/A')}") # Check action configurations - if 'actionConfigs' in rule_details['rule']: + if 'actionConfigs' in rule_details: print("Action Configurations:") - for action in rule_details['rule']['actionConfigs']: + for action in rule_details['actionConfigs']: print(f" Type: {action['type']}") if action['type'] == 'WEBHOOK': print(f" Endpoint: {action['endpoint']}") @@ -208,7 +208,7 @@ def alert_rule_management_examples(j1, rule_id): tag_op="OVERWRITE", severity="INFO" ) - print(f"Updated alert rule: {updated_rule['rule']['_id']}") + print(f"Updated alert rule: {updated_rule['id']}") except Exception as e: print(f"Error updating alert rule: {e}") print() @@ -240,7 +240,7 @@ def smartclass_examples(j1): smartclass_name='ProductionServers', smartclass_description='All production servers across cloud providers' ) - smartclass_id = smartclass['smartclass']['_id'] + smartclass_id = smartclass['id'] print(f"Created SmartClass: {smartclass_id}\n") # 2. Add queries to SmartClass @@ -267,8 +267,8 @@ def smartclass_examples(j1): print("3. Getting SmartClass details:") try: smartclass_details = j1.get_smartclass_details(smartclass_id=smartclass_id) - print(f"SmartClass: {smartclass_details['smartclass']['name']}") - print(f"Description: {smartclass_details['smartclass']['description']}") + print(f"SmartClass: {smartclass_details['tagName']}") + print(f"Description: {smartclass_details['description']}") print(f"Queries: {len(smartclass_details.get('queries', []))}") # List all queries in the SmartClass @@ -410,7 +410,7 @@ def main(): webhook_rule, multi_action_rule = alert_rule_with_actions_examples(j1) # Alert rule management (using the basic rule) - alert_rule_management_examples(j1, basic_rule['rule']['_id']) + alert_rule_management_examples(j1, basic_rule['id']) # SmartClass examples smartclass_id = smartclass_examples(j1) @@ -419,7 +419,7 @@ def main(): natural_language_to_j1ql_examples(j1) # Alert rule evaluation examples - alert_rule_evaluation_examples(j1, basic_rule['rule']['_id']) + alert_rule_evaluation_examples(j1, basic_rule['id']) # Compliance framework examples compliance_framework_examples(j1) diff --git a/jupiterone/client.py b/jupiterone/client.py index 2ce22d7..7e2dbbb 100644 --- a/jupiterone/client.py +++ b/jupiterone/client.py @@ -1030,7 +1030,7 @@ def create_alert_rule( polling_interval: str = None, severity: str = None, j1ql: str = None, - action_configs: Dict = None, + action_configs: Union[Dict, List[Dict]] = None, resource_group_id: str = None, ): """Create Alert Rule Configuration in J1 account""" @@ -1079,7 +1079,10 @@ def create_alert_rule( } if action_configs: - variables["instance"]["operations"][0]["actions"].append(action_configs) + if isinstance(action_configs, list): + variables["instance"]["operations"][0]["actions"].extend(action_configs) + else: + variables["instance"]["operations"][0]["actions"].append(action_configs) response = self._execute_query(CREATE_RULE_INSTANCE, variables=variables) @@ -1106,7 +1109,7 @@ def update_alert_rule( tags: List[str] = None, tag_op: str = None, labels: List[dict] = None, - action_configs: List[dict] = None, + action_configs: Union[Dict, List[Dict]] = None, action_configs_op: str = None, resource_group_id: str = None, ): @@ -1178,15 +1181,23 @@ def update_alert_rule( alert_action_configs = [] base_action = alert_rule_config["operations"][0]["actions"][0] alert_action_configs.append(base_action) - alert_action_configs.extend(action_configs) + + # Handle both single dict and list of dicts + if isinstance(action_configs, list): + alert_action_configs.extend(action_configs) + else: + alert_action_configs.append(action_configs) # update actions field inside operations payload operations[0]["actions"] = alert_action_configs elif action_configs_op == "APPEND": - # update actions field inside operations payload - operations[0]["actions"].extend(action_configs) + # Handle both single dict and list of dicts + if isinstance(action_configs, list): + operations[0]["actions"].extend(action_configs) + else: + operations[0]["actions"].append(action_configs) # update alert severity if provided if severity is not None: From b1ad53be5e38214e9ec35d55191d992786be9721 Mon Sep 17 00:00:00 2001 From: SeaBlooms Date: Wed, 10 Sep 2025 12:55:37 -0600 Subject: [PATCH 2/2] bump version to 1.6.1 bugfix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a66ca36..88eec0c 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="jupiterone", - version="1.6.0", + version="1.6.1", description="A Python client for the JupiterOne API", license="MIT License", author="JupiterOne",