Skip to content

Commit

Permalink
[OpsGenie] get alert logs (demisto#28857)
Browse files Browse the repository at this point in the history
* [OpsGenie] get alert logs (demisto#28743)

* master

* reverting crowdstrike.py

* opsgenie get alert logs

* removed _dev

* reverted 2_0_16 and bumped version

* updated version

* added a unit test

* fixed a conflict

* fixed conflicts

* updated version

* alert id

* opsgenie added new commands

* update release notes

* added test data

* removed checkers

* stripped _dev

* menachem requested some changes

* modified the integration

* added descriptions

* added release notes

* update for menachem

* removed duplicate key

* Update the docker images; Update the README file

* Apply suggestions from code review

Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>

---------

Co-authored-by: Enes Özdemir <49711791+ennozdd@users.noreply.github.com>
Co-authored-by: Menachem Weinfeld <mmhw770@gmail.com>
Co-authored-by: Menachem Weinfeld <90556466+mmhw@users.noreply.github.com>
Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com>
  • Loading branch information
5 people authored and xsoar-bot committed Oct 5, 2023
1 parent 5af5fd5 commit de6fb08
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 4 deletions.
67 changes: 65 additions & 2 deletions Packs/OpsGenie/Integrations/OpsGenieV3/OpsGenieV3.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ def add_alert_tag(self, args: dict):
url_suffix=f"/v2/{ALERTS_SUFFIX}/{args.get('alert-id')}/tags",
json_data=args)

def add_alert_note(self, args: dict):
return self._http_request(method='POST',
url_suffix=f"/v2/{ALERTS_SUFFIX}/{args.get('alert_id')}/notes",
json_data=args)

def add_alert_details(self, args: dict):
if not isinstance(args.get('details'), dict):
args['details'] = {key_value.split('=')[0]: key_value.split('=')[1]
for key_value in argToList(args.get('details'))}
return self._http_request(method='POST',
url_suffix=f"/v2/{ALERTS_SUFFIX}/{args.get('alert_id')}/details",
json_data=args)

def remove_alert_tag(self, args: dict):
args['tags'] = argToList(args.get('tags'))
return self._http_request(method='DELETE',
Expand All @@ -182,6 +195,12 @@ def get_alert_attachments(self, args: dict):
url_suffix=f"/v2/{ALERTS_SUFFIX}/"
f"{args.get('alert-id')}/attachments")

def get_alert_logs(self, args: dict):
alert_id = args.get('alert_id')
return self._http_request(method='GET',
url_suffix=f"/v2/{ALERTS_SUFFIX}/"
f"{alert_id}/logs")

def get_schedule(self, args: dict):
if not is_one_argument_given(args.get("schedule_id"), args.get("schedule_name")):
raise DemistoException("Either schedule_id or schedule_name should be provided.")
Expand Down Expand Up @@ -626,6 +645,34 @@ def add_alert_tag(client: Client, args: Dict[str, Any]) -> CommandResults:
return get_request_command(client, args)


def add_alert_note(client: Client, args: Dict[str, Any]) -> CommandResults:
args = {
'request_type': ALERTS_SUFFIX,
'output_prefix': 'OpsGenie.AddAlertNote',
**args
}
data = client.add_alert_note(args)
request_id = data.get("requestId")
if not request_id:
raise ConnectionError(f"Failed to send request - {data}")
args['request_id'] = request_id
return get_request_command(client, args)


def add_alert_details(client: Client, args: Dict[str, Any]) -> CommandResults:
args = {
'request_type': ALERTS_SUFFIX,
'output_prefix': 'OpsGenie.AddAlertDetails',
**args
}
data = client.add_alert_details(args)
request_id = data.get("requestId")
if not request_id:
raise ConnectionError(f"Failed to send request - {data}")
args['request_id'] = request_id
return get_request_command(client, args)


def remove_alert_tag(client: Client, args: Dict[str, Any]) -> CommandResults:
args = {
'request_type': ALERTS_SUFFIX,
Expand All @@ -650,6 +697,17 @@ def get_alert_attachments(client: Client, args: Dict[str, Any]) -> CommandResult
)


def get_alert_logs(client: Client, args: Dict[str, Any]) -> CommandResults:
result = client.get_alert_logs(args)
data = result.get("data")
return CommandResults(
outputs_prefix="OpsGenie.AlertLogs",
outputs=result.get("data"),
readable_output=tableToMarkdown("OpsGenie Logs", data),
raw_response=result
)


def get_schedules(client: Client, args: Dict[str, Any]) -> CommandResults:
schedule = args.get("schedule_id", None) or args.get("schedule_name", None)
result = client.get_schedule(args) if schedule else client.list_schedules()
Expand Down Expand Up @@ -847,10 +905,12 @@ def get_request_command(client: Client, args: Dict[str, Any]) -> CommandResults:
args.get('timeout_in_seconds', DEFAULT_POLL_TIMEOUT))))
else:
results_dict = results.json()
outputs_prefix = args.get("output_prefix", f'OpsGenie.{request_type.capitalize()[:-1]}')
return CommandResults(
outputs_prefix=args.get("output_prefix", f'OpsGenie.{request_type.capitalize()[:-1]}'),
outputs_prefix=outputs_prefix,
outputs=results_dict.get("data"),
readable_output=tableToMarkdown("OpsGenie", results_dict.get('data')),
readable_output=tableToMarkdown(f"OpsGenie - {pascalToSpace(outputs_prefix.split('.')[-1])}",
results_dict.get('data')),
raw_response=results_dict
)

Expand Down Expand Up @@ -1037,8 +1097,11 @@ def main() -> None:
'opsgenie-get-escalations': get_escalations,
'opsgenie-escalate-alert': escalate_alert,
'opsgenie-add-alert-tag': add_alert_tag,
'opsgenie-add-alert-note': add_alert_note,
'opsgenie-add-alert-details': add_alert_details,
'opsgenie-remove-alert-tag': remove_alert_tag,
'opsgenie-get-alert-attachments': get_alert_attachments,
'opsgenie-get-alert-logs': get_alert_logs,
'opsgenie-get-schedules': get_schedules,
'opsgenie-get-schedule-overrides': get_schedule_overrides,
'opsgenie-get-on-call': get_on_call,
Expand Down
105 changes: 104 additions & 1 deletion Packs/OpsGenie/Integrations/OpsGenieV3/OpsGenieV3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,110 @@ script:
description: Notify name of the routing rule.
- contextPath: OpsGenie.TeamRoutingRule.notify.type
description: Notify type of the routing rule.
dockerimage: demisto/python3:3.10.12.66339
- name: opsgenie-get-alert-logs
description: Gets logs of an OpsGenie Alert.
arguments:
- name: alert_id
required: true
description: Alert ID
outputs:
- contextPath: OpsGenie.AlertLogs.createdAt
description: Time the alert was created.
type: String
- contextPath: OpsGenie.AlertLogs.log
description: Log of the alert.
type: String
- contextPath: OpsGenie.AlertLogs.offset
description: Offset of the alert log.
type: String
- contextPath: OpsGenie.AlertLogs.owner
description: Owner of the alert log.
type: String
- contextPath: OpsGenie.AlertLogs.type
description: Type of the alert log.
type: String
- name: opsgenie-add-alert-note
description: Adds a note to an OpsGenie Alert.
arguments:
- name: alert_id
required: true
description: Alert ID to add the note to.
- name: note
required: true
description: Alert note to add.
- name: user
required: false
description: Display name of the request owner.
- name: source
required: false
description: Display name of the request source.
outputs:
- contextPath: OpsGenie.AddAlertNote.action
description: Action of this request.
type: String
- contextPath: OpsGenie.AddAlertNote.alertId
description: ID of the created alert.
type: String
- contextPath: OpsGenie.AddAlertNote.alias
description: Alias of the created alert.
type: String
- contextPath: OpsGenie.AddAlertNote.integrationId
description: Integration ID of the created alert.
type: String
- contextPath: OpsGenie.AddAlertNote.isSuccess
description: Whether the request was successful.
type: Boolean
- contextPath: OpsGenie.AddAlertNote.processedAt
description: When the request was processed.
type: Date
- contextPath: OpsGenie.AddAlertNote.requestId
description: The ID of the request.
type: String
- contextPath: OpsGenie.AddAlertNote.status
description: The human readable result of the request.
type: String
- contextPath: OpsGenie.AddAlertNote.success
description: Whether the request was successful.
type: Boolean
- name: opsgenie-add-alert-details
description: Adds details to an OpsGenie Alert.
arguments:
- name: alert_id
required: true
description: Alert ID to add the details to.
- name: details
required: true
description: Comma-separated key=value pairs to use as custom properties of the alert. JSON format is also supported when used within an automation. Examples; details="account=pa,hostname=computer01".
type: keyValue
outputs:
- contextPath: OpsGenie.AddAlertDetails.action
description: Action of this request.
type: String
- contextPath: OpsGenie.AddAlertDetails.alertId
description: ID of the created alert.
type: String
- contextPath: OpsGenie.AddAlertDetails.alias
description: Alias of the created alert.
type: String
- contextPath: OpsGenie.AddAlertDetails.integrationId
description: Integration ID of the created alert.
type: String
- contextPath: OpsGenie.AddAlertDetails.isSuccess
description: Whether the request was successful.
type: Boolean
- contextPath: OpsGenie.AddAlertDetails.processedAt
description: When the request was processed.
type: Date
- contextPath: OpsGenie.AddAlertDetails.requestId
description: The ID of the request.
type: String
- contextPath: OpsGenie.AddAlertDetails.status
description: The human readable result of the request.
type: String
- contextPath: OpsGenie.AddAlertDetails.success
description: Whether the request was successful.
type: Boolean
dockerimage: demisto/python3:3.10.12.68300
isfetch: true
script: '-'
type: python
Expand Down
60 changes: 60 additions & 0 deletions Packs/OpsGenie/Integrations/OpsGenieV3/OpsGenieV3_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1031,3 +1031,63 @@ def test_get_team_routing_rules(mocker):
return_value=util_load_json('test_data/get_team_routing_rules.json'))
res = OpsGenieV3.get_team_routing_rules(mock_client, {'team_id': " a6604a9f-b152-54c-b31-1b9741c109"})
assert (res.raw_response == util_load_json('test_data/get_team_routing_rules.json'))


def test_get_alert_logs(mocker):
"""
Given:
- An app client object
- alert_id = 0123456
When:
- Calling function get_alert_notes
Then:
- Ensure the return data is correct
"""
mocker.patch('CommonServerPython.get_demisto_version', return_value={"version": "6.2.0"})
mock_client = OpsGenieV3.Client(base_url="")
mocker.patch.object(mock_client, 'get_alert_logs',
return_value=util_load_json('test_data/get_alert_logs.json'))
res = OpsGenieV3.get_alert_logs(mock_client, {"alert_id": '0123456'})
assert isinstance(res.raw_response, dict)


def test_add_alert_note(mocker):
"""
Given:
- An app client object
- alert_id = 1234
- note = "testdemisto"
When:
- Calling function add_alert_note
Then:
- Ensure the return data is correct
"""
mocker.patch('CommonServerPython.get_demisto_version', return_value={"version": "6.2.0"})
mock_client = OpsGenieV3.Client(base_url="")
mocker.patch.object(mock_client, 'add_alert_note',
return_value=util_load_json('test_data/request.json'))
mocker.patch.object(mock_client, 'get_request',
return_value=util_load_json('test_data/add_alert_note.json', True))
res = OpsGenieV3.add_alert_note(mock_client, {"alert_id": 1234, "note": "testdemisto"})
assert (res.raw_response == util_load_json('test_data/add_alert_note.json'))


def test_add_alert_details(mocker):
"""
Given:
- An app client object
- Alert-id = 1234
- details = "test=demisto"
When:
- Calling function add_alert_details
Then:
- Ensure the return data is correct
"""
mocker.patch('CommonServerPython.get_demisto_version', return_value={"version": "6.2.0"})
mock_client = OpsGenieV3.Client(base_url="")
mocker.patch.object(mock_client, 'add_alert_details',
return_value=util_load_json('test_data/request.json'))
mocker.patch.object(mock_client, 'get_request',
return_value=util_load_json('test_data/add_alert_details.json', True))
res = OpsGenieV3.add_alert_details(mock_client, {"alert-id": 1234, "details": {'test': 'demisto'}})
assert (res.raw_response == util_load_json('test_data/add_alert_details.json'))
87 changes: 87 additions & 0 deletions Packs/OpsGenie/Integrations/OpsGenieV3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1868,3 +1868,90 @@ Lists team routing rules.
| OpsGenie.TeamRoutingRule.notify.id | unknown | Notify ID of the routing rule. |
| OpsGenie.TeamRoutingRule.notify.name | unknown | Notify name of the routing rule. |
| OpsGenie.TeamRoutingRule.notify.type | unknown | Notify type of the routing rule. |

### opsgenie-get-alert-logs

***
Gets logs of an OpsGenie Alert.

#### Base Command

`opsgenie-get-alert-logs`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| alert_id | Alert ID. | Required |

#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| OpsGenie.AlertLogs.createdAt | String | Time the alert was created. |
| OpsGenie.AlertLogs.log | String | Log of the alert. |
| OpsGenie.AlertLogs.offset | String | Offset of the alert log. |
| OpsGenie.AlertLogs.owner | String | Owner of the alert log. |
| OpsGenie.AlertLogs.type | String | Type of the alert log. |

### opsgenie-add-alert-note

***
Adds a note to an OpsGenie Alert.

#### Base Command

`opsgenie-add-alert-note`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| alert_id | Alert ID to add the note to. | Required |
| note | Alert note to add. | Required |
| user | Display name of the request owner. | Optional |
| source | Display name of the request source. | Optional |

#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| OpsGenie.AddAlertNote.action | String | Action of this request. |
| OpsGenie.AddAlertNote.alertId | String | ID of the created alert. |
| OpsGenie.AddAlertNote.alias | String | Alias of the created alert. |
| OpsGenie.AddAlertNote.integrationId | String | Integration ID of the created alert. |
| OpsGenie.AddAlertNote.isSuccess | Boolean | Whether the request was successful. |
| OpsGenie.AddAlertNote.processedAt | Date | When the request was processed. |
| OpsGenie.AddAlertNote.requestId | String | The ID of the request. |
| OpsGenie.AddAlertNote.status | String | The human readable result of the request. |
| OpsGenie.AddAlertNote.success | Boolean | Whether the request was successful. |

### opsgenie-add-alert-details

***
Adds details to an OpsGenie Alert.

#### Base Command

`opsgenie-add-alert-details`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| alert_id | Alert ID to add the details to. | Required |
| details | Comma-separated key=value pairs to use as custom properties of the alert. JSON format is also supported when used within an automation. Examples; details="account=pa,hostname=computer01". | Required |

#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| OpsGenie.AddAlertDetails.action | String | Action of this request. |
| OpsGenie.AddAlertDetails.alertId | String | ID of the created alert. |
| OpsGenie.AddAlertDetails.alias | String | Alias of the created alert. |
| OpsGenie.AddAlertDetails.integrationId | String | Integration ID of the created alert. |
| OpsGenie.AddAlertDetails.isSuccess | Boolean | Whether the request was successful. |
| OpsGenie.AddAlertDetails.processedAt | Date | When the request was processed. |
| OpsGenie.AddAlertDetails.requestId | String | The ID of the request. |
| OpsGenie.AddAlertDetails.status | String | The human readable result of the request. |
| OpsGenie.AddAlertDetails.success | Boolean | Whether the request was successful. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"data": {
"action": "Add Details",
"alertId": "c3426c26-a3ce-42a5-5d66-06d6el7b3b48l1691404404476",
"alias": "000000-a9ce-42a5-8d66-09d9ef7b3b48-000000",
"integrationId": "000000-eb06-4601-bfab-0000",
"isSuccess": true,
"processedAt": "2023-08-07T13:43:40.414Z",
"status": "Added details",
"success": true
},
"requestId": "c3a83h44-7690-4113-9638-00000000000",
"took": 0.003
}

0 comments on commit de6fb08

Please sign in to comment.