Skip to content

De widget #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Packs/Code42/Integrations/Code42/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## [Unreleased]
Added new commands:
- **Code42GetDepartingEmployeeAlerts** automation script which gets departing employees with alerts.
- **code42-alert-search** that searches alerts by username.
- **code42-departingemployee-get-all** that gets all the employees on the Departing Employee List.
- **code42-highriskemployee-add** that takes a username and adds the employee to the High Risk Employee List.
- **code42-highriskemployee-remove** that takes a username and remove the employee from the High Risk Employee List.
Expand Down
28 changes: 27 additions & 1 deletion Packs/Code42/Integrations/Code42/Code42.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
FileCategory,
)
from py42.sdk.queries.alerts.alert_query import AlertQuery
from py42.sdk.queries.alerts.filters import DateObserved, Severity, AlertState
from py42.sdk.queries.alerts.filters import DateObserved, Severity, AlertState, Actor as AlertActor

# Disable insecure warnings
requests.packages.urllib3.disable_warnings()
Expand Down Expand Up @@ -216,6 +216,10 @@ def fetch_alerts(self, start_time, event_severity_filter):
res = self._sdk.alerts.search(query)
return res["alerts"]

def search_alerts(self, username):
query = AlertQuery(AlertActor.eq(username))
return self._sdk.alerts.search(query)["alerts"]

def get_alert_details(self, alert_id):
res = self._sdk.alerts.get_details(alert_id)["alerts"]
if not res:
Expand Down Expand Up @@ -509,6 +513,27 @@ def alert_resolve_command(client, args):
return_error(create_command_error_message(demisto.command(), e))


def alert_search_command(client, args):
username = args["username"]
try:
alerts = client.search_alerts(username)
alert_context = []
for alert in alerts:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

room for list comprehension....

alert_context = [map_to_code42_alert_context(alert) for alert in alerts]

alert_context.append(map_to_code42_alert_context(alert))
readable_outputs = tableToMarkdown(
"Code42 Security Alert Search",
alert_context,
headers=SECURITY_ALERT_HEADERS,
)
return (
readable_outputs,
{"Code42.SecurityAlert": alert_context},
alerts
)

except Exception as e:
return_error(create_command_error_message(demisto.command(), e))

@logger
def departingemployee_add_command(client, args):
departing_date = args.get("departuredate")
Expand Down Expand Up @@ -815,6 +840,7 @@ def main():
commands = {
"code42-alert-get": alert_get_command,
"code42-alert-resolve": alert_resolve_command,
"code42-alert-search": alert_search_command,
"code42-securitydata-search": securitydata_search_command,
"code42-departingemployee-add": departingemployee_add_command,
"code42-departingemployee-remove": departingemployee_remove_command,
Expand Down
35 changes: 34 additions & 1 deletion Packs/Code42/Integrations/Code42/Code42.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ script:
- contextPath: Code42.SecurityAlert.Severity
description: The severity of the alert.
type: string
description: Retrieve alert details by alert ID
description: Retrieve alert details by alert ID.
- name: code42-alert-resolve
arguments:
- name: id
Expand All @@ -252,6 +252,37 @@ script:
description: The alert ID of the resolved alert.
type: string
description: Resolves a Code42 Security alert.
- name: code42-alert-search
arguments:
- name: username
required: true
description: The username for the user to search alerts for.
outputs:
- contextPath: Code42.SecurityAlert.Username
description: The username associated with the alert.
type: string
- contextPath: Code42.SecurityAlert.Occurred
description: The timestamp when the alert occurred.
type: date
- contextPath: Code42.SecurityAlert.Description
description: The description of the alert.
type: string
- contextPath: Code42.SecurityAlert.ID
description: The alert ID.
type: string
- contextPath: Code42.SecurityAlert.Name
description: The alert rule name that generated the alert.
type: string
- contextPath: Code42.SecurityAlert.State
description: The alert state.
type: string
- contextPath: Code42.SecurityAlert.Type
description: The alert type.
type: string
- contextPath: Code42.SecurityAlert.Severity
description: The severity of the alert.
type: string
description: Search alerts by username.
- name: code42-departingemployee-add
arguments:
- name: username
Expand Down Expand Up @@ -362,6 +393,7 @@ script:
type: string
- contextPath: Code42.HighRiskEmployee.RiskTags
description: Risk tags to associate with the High Risk Employee.
description: Add the given risk tags to the user with the given username.
- name: code42-highriskemployee-remove-risk-tags
arguments:
- name: username
Expand All @@ -379,6 +411,7 @@ script:
type: string
- contextPath: Code42.HighRiskEmployee.RiskTags
description: Risk tags to disassociate from the High Risk Employee.
description: Remove the given risk tags from the user with the given username.
dockerimage: demisto/py42:1.0.0.9242
isfetch: true
runonce: false
Expand Down
7 changes: 7 additions & 0 deletions Packs/Code42/Integrations/Code42/Code42_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
map_to_file_context,
alert_get_command,
alert_resolve_command,
alert_search_command,
departingemployee_add_command,
departingemployee_remove_command,
departingemployee_get_all_command,
Expand Down Expand Up @@ -994,6 +995,12 @@ def test_alert_resolve_command(code42_alerts_mock):
assert res["id"] == "36fb8ca5-0533-4d25-9763-e09d35d60610"


def test_alert_search_command(code42_alerts_mock):
client = create_client(code42_alerts_mock)
_, _, res = alert_search_command(client, {"username": "[email protected]"})
assert res == json.loads(MOCK_ALERTS_RESPONSE)["alerts"]


def test_departingemployee_add_command(code42_sdk_mock):
client = create_client(code42_sdk_mock)
_, _, res = departingemployee_add_command(
Expand Down
63 changes: 61 additions & 2 deletions Packs/Code42/Integrations/Code42/integration-Code42.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ script:

from py42.sdk.queries.alerts.alert_query import AlertQuery

from py42.sdk.queries.alerts.filters import DateObserved, Severity, AlertState
from py42.sdk.queries.alerts.filters import DateObserved, Severity, AlertState, Actor as AlertActor


# Disable insecure warnings
Expand Down Expand Up @@ -287,6 +287,10 @@ script:
res = self._sdk.alerts.search(query)
return res["alerts"]

def search_alerts(self, username):
query = AlertQuery(AlertActor.eq(username))
return self._sdk.alerts.search(query)["alerts"]

def get_alert_details(self, alert_id):
res = self._sdk.alerts.get_details(alert_id)["alerts"]
if not res:
Expand Down Expand Up @@ -588,6 +592,27 @@ script:
return_error(create_command_error_message(demisto.command(), e))


def alert_search_command(client, args):
username = args["username"]
try:
alerts = client.search_alerts(username)
alert_context = []
for alert in alerts:
alert_context.append(map_to_code42_alert_context(alert))
readable_outputs = tableToMarkdown(
"Code42 Security Alert Search",
alert_context,
headers=SECURITY_ALERT_HEADERS,
)
return (
readable_outputs,
{"Code42.SecurityAlert": alert_context},
alerts
)

except Exception as e:
return_error(create_command_error_message(demisto.command(), e))

@logger

def departingemployee_add_command(client, args):
Expand Down Expand Up @@ -903,6 +928,7 @@ script:
commands = {
"code42-alert-get": alert_get_command,
"code42-alert-resolve": alert_resolve_command,
"code42-alert-search": alert_search_command,
"code42-securitydata-search": securitydata_search_command,
"code42-departingemployee-add": departingemployee_add_command,
"code42-departingemployee-remove": departingemployee_remove_command,
Expand Down Expand Up @@ -1128,7 +1154,7 @@ script:
- contextPath: Code42.SecurityAlert.Severity
description: The severity of the alert.
type: string
description: Retrieve alert details by alert ID
description: Retrieve alert details by alert ID.
- name: code42-alert-resolve
arguments:
- name: id
Expand All @@ -1139,6 +1165,37 @@ script:
description: The alert ID of the resolved alert.
type: string
description: Resolves a Code42 Security alert.
- name: code42-alert-search
arguments:
- name: username
required: true
description: The username for the user to search alerts for.
outputs:
- contextPath: Code42.SecurityAlert.Username
description: The username associated with the alert.
type: string
- contextPath: Code42.SecurityAlert.Occurred
description: The timestamp when the alert occurred.
type: date
- contextPath: Code42.SecurityAlert.Description
description: The description of the alert.
type: string
- contextPath: Code42.SecurityAlert.ID
description: The alert ID.
type: string
- contextPath: Code42.SecurityAlert.Name
description: The alert rule name that generated the alert.
type: string
- contextPath: Code42.SecurityAlert.State
description: The alert state.
type: string
- contextPath: Code42.SecurityAlert.Type
description: The alert type.
type: string
- contextPath: Code42.SecurityAlert.Severity
description: The severity of the alert.
type: string
description: Search alerts by username.
- name: code42-departingemployee-add
arguments:
- name: username
Expand Down Expand Up @@ -1249,6 +1306,7 @@ script:
type: string
- contextPath: Code42.HighRiskEmployee.RiskTags
description: Risk tags to associate with the High Risk Employee.
description: Add the given risk tags to the user with the given username.
- name: code42-highriskemployee-remove-risk-tags
arguments:
- name: username
Expand All @@ -1266,6 +1324,7 @@ script:
type: string
- contextPath: Code42.HighRiskEmployee.RiskTags
description: Risk tags to disassociate from the High Risk Employee.
description: Remove the given risk tags from the user with the given username.
dockerimage: demisto/py42:1.0.0.9242
isfetch: true
runonce: false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## [Unreleased]
-
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import demistomock as demisto
from CommonServerPython import *


def main():
res = {"total": 0}
res_data = []
top = demisto.args().get("top") or 10

try:
employees = demisto.executeCommand("code42-departingemployee-get-all", {})[0]["Contents"]
res["total"] = len(employees)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are ignoring certain employees later, should we not set total after the for loop?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on what the count represents, if it represents all employees irrespective of whether they have alerts or not then this is ok.


# Get each employee on the Departing Employee List and their total alerts.
for employee in employees:
username = employee["userName"]
alerts = demisto.executeCommand("code42-alert-search", {"username": username})[0]["Contents"]
alerts_count = len(alerts)

# Ignores employees without alerts
if alerts_count:
employee_res = {"Username": username, "Alerts Count": alerts_count}
res_data.append(employee_res)

# Sort such that highest alert counts are first and get top.
res["data"] = sorted(res_data, key=lambda x: x["Alerts Count"], reverse=True)[:top]
demisto.results(res)
except Exception as e:
res["total"] = -1
res["data"] = str(e)

# Submit final results to Cortex XSOAR
demisto.results(res)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need line 27, seems redundant, results method is called twice.


if __name__ in ("__main__", "__builtin__", "builtins"):
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
args:
- defaultValue: 10
description: To limit results to x number of employees with the highest alert count.
name: top
type: number
comment: Gets all departing employees and alerts for each.
commonfields:
id: 468c8e6f-6f50-486f-8cde-7dabe4cbeb2b
version: -1
dependson:
must:
- Code42|||code42-departingemployee-get-all
- Code42|||code42-alerts-search
dockerimage: demisto/py42:1.0.0.9242
enabled: true
name: Code42GetDepartingEmployeeAlerts
pswd: ""
runas: DBotWeakRole
runonce: false
script: ''
scripttarget: 0
subtype: python3
tags: ['dynamic-section', 'widget']
type: python
Empty file.
40 changes: 40 additions & 0 deletions Packs/Code42/Widgets/widget-Departing_Employee_Alerts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"category": "",
"dataType": "scripts",
"dateRange": {
"fromDate": "0001-01-01T00:00:00Z",
"fromDateLicense": "0001-01-01T00:00:00Z",
"period": {
"by": "",
"byFrom": "days",
"byTo": "",
"field": "",
"fromValue": null,
"toValue": null
},
"toDate": "0001-01-01T00:00:00Z"
},
"id": "570ec235-7ee4-43ea-8fc7-eba94a0cca71",
"isPredefined": false,
"name": "Departing Employee Alerts",
"params": {
"tableColumns": [
{
"displayed": true,
"isDefault": true,
"key": "Username"
},
{
"displayed": true,
"isDefault": true,
"key": "Alerts Count"
}
]
},
"query": "Code42GetDepartingEmployeeAlerts",
"size": 0,
"sort": null,
"sortValues": null,
"version": -1,
"widgetType": "table"
}