TaegisXDR Deprecated
Deprecated. Use TaegisXDR v2 instead.
Data Enrichment & Threat Intelligence · Secureworks
Details
| ID | TaegisXDR |
|---|---|
| Provider | Sophos |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/python3:3.10.12.65389 |
| Supported Modules | Agentix XSIAM |
README
Configure Taegis XDR in Cortex
| Parameter | Description | Required |
|---|---|---|
| Taegis Environment | The environment to utilize | True |
| Client ID | Client ID as described in the Taegis Documentation | True |
| Client Secret | Client Secret as described in the Taegis Documentation | True |
| Use system proxy settings | Defines whether the system proxy is used or not | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
taegis-archive-investigation
Base Command
!taegis-archive-investigation
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | The investigation id to archive | True |
Command Example
!taegis-archive-investigation id=c207ca4c-8a78-4408-a056-49f05d6eb77d
Context Example
{
"TaegisXDR": {
"ArchivedInvestigation": {
"id": "c207ca4c-8a78-4408-a056-49f05d6eb77d"
}
}
}
taegis-create-comment
Base Command
!taegis-create-comment
Inputs
| Argument Name | Description | Required |
|---|---|---|
| comment | The comment string to add to the investigation | True |
| parent_id | The investigation ID to add the comment to | True |
Command Example
!taegis-create-comment comment="This is a test comment" parent_id="219da0ee-8642-4363-827c-8a6fbd479082"
Context Example
{
"TaegisXDR": {
"CommentCreate": {
"id": "593fa115-abad-4a52-9fc4-2ec403a8a1e4"
}
}
}
taegis-create-investigation
Base Command
!taegis-create-investigation
Inputs
| Argument Name | Description | Required |
|---|---|---|
| description | The subject or description of the investigation | True |
| priority | The priority for the investigiation [Default: 3] | False |
Command Example
!taegis-create-investigation priority=1 description="XSOAR Created Investigation"
Context Example
{
"TaegisXDR": {
"Investigation": {
"id": "593fa115-abad-4a52-9fc4-2ec403a8a1e4"
}
}
}
taegis-execute-playbook
Base Command
!taegis-execute-playbook
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Playbook instance ID to execute | True |
| inputs | JSON object of inputs to pass into the playbook execution | False |
Command Example
!taegis-execute-playbook id=UGxheWJvb2tJbnN0YW5jZTphZDNmNzBlZi1mN2U0LTQ0OWYtODJiMi1hYWQwMjQzZTA2NTg=
!taegis-execute-playbook id=UGxheWJvb2tJbnN0YW5jZTphZDNmNzBlZi1mN2U0LTQ0OWYtODJiMi1hYWQwMjQzZTA2NTg= inputs=`{'myvar': 'myval'}`
Context Example
{
"id": "UGxheWJvb2tFeGVjdXRpb246NGYwZDZiNGQtNWNiZS00NDkxLTg3YzYtMDZkNjkxYzMwMTg4"
}
taegis-fetch-alerts
Base Command
!taegis-fetch-alerts
Input
| Argument Name | Description | Default | Required |
|---|---|---|---|
| ids | A list of alerts by IDs | 936c1cc1-db8f-430c-837c-1c914fcca35a |
False |
| limit | Number of results to when ids is not defined |
10 |
False |
| offset | The result to start from when ids is not defined |
0 |
False |
| cql_query | The query to utilize when searching for Alerts | from alert severity >= 0.6 and status='OPEN' |
False |
Command Examples
!taegis-fetch-alerts ids=`["6594e97f-a898-5b28-82b2-ea03293cdaa1"]`
Context Example
{
"TaegisXDR": {
"Alerts": [
{
"id": "c4f33b53-eaba-47ac-8272-199af0f7935b",
"metadata": {
"title": "Test Alert",
"description": "This is a test alert",
"severity": 0.5,
}
}
]
}
}
taegis-fetch-assets
Base Command
!taegis-fetch-assets
Input
| Argument Name | Description | Default | Required |
|---|---|---|---|
| page | 0 |
False | |
| page_size | 10 |
False | |
| endpoint_type | False | ||
| host_id | ID of the asset to fetch | e43b545a-580a-4047-b489-4338c1cc4ba1 |
False |
| hostname | False | ||
| investigation_id | False | ||
| ip_address | False | ||
| mac_address | False | ||
| os_family | False | ||
| os_version | False | ||
| sensor_version | False | ||
| username | False |
Command Examples
!taegis-fetch-assets
!taegis-fetch-assets page=1 page_size=5
!taegis-fetch-assets hostname=MyHostname01
!taegis-fetch-assets host_id=e43b545a-580a-4047-b489-4338c1cc4ba1
Context Example
{
"TaegisXDR": {
"Assets": [
{
"id": "",
"ingestTime": "",
"createdAt": "",
"updatedAt": "",
"deletedAt": "",
"biosSerial": "",
"firstDiskSerial": "",
"systemVolumeSerial": "",
"sensorVersion": "",
"endpointPlatform": "",
"hostnames": [{"id": ", "hostname": ""],
"architecture": "",
"osFamily": "",
"osVersion": "",
"osDistributor": "",
"osRelease": "",
"systemType": "",
"osCodename": "",
"kernelRelease": "",
"kernelVersion": "",
"tags": [ "key": "", "tag": ""],
"endpointType": "",
"hostId": "",
"sensorId": "",
}
]
}
}
taegis-fetch-comment
Base Command
!taegis-fetch-comment
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the comment to fetch | True |
Command Example
!taegis-fetch-comment id=ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f
Context Example
{
"TaegisXDR": {
"Comment": {
"author_user": {
"email_normalized": "myuser@email.com",
"given_name": "John",
"family_name": "Smith",
"id": "auth0|000000000000000000000001",
},
"id": "ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f",
"comment": "This is a comment in an investigation",
"created_at": "2022-01-01T13:04:57.17234Z",
"deleted_at": None,
"modified_at": None,
"parent_id": "c2e09554-833e-41a1-bc9d-8160aec0d70d",
"parent_type": "investigation",
}
}
}
taegis-fetch-comments
Base Command
!taegis-create-comments
Inputs
| Argument Name | Description | Required |
|---|---|---|
| parent_id | The investigation ID to fetch comments for | True |
Command Example
!taegis-fetch-comments parent_id=c2e09554-833e-41a1-bc9d-8160aec0d70d
Context Example
{
"TaegisXDR": {
"Comments": [
{
"author_user": {
"email_normalized": "myuser@email.com",
"given_name": "John",
"family_name": "Smith",
"id": "auth0|000000000000000000000001",
},
"id": "ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f",
"comment": "This is a comment in an investigation",
"created_at": "2022-01-01T13:04:57.17234Z",
"deleted_at": None,
"modified_at": None,
"parent_id": "c2e09554-833e-41a1-bc9d-8160aec0d70d",
"parent_type": "investigation",
},
{
"author_user": {
"email_normalized": "myuser@email.com",
"given_name": "John",
"family_name": "Smith",
"id": "auth0|000000000000000000000001",
},
"id": "ff9ca818-4749-4ccb-883a-2ccc6f6c1234",
"comment": "This is another comment",
"created_at": "2022-01-02T13:04:57.17234Z",
"deleted_at": None,
"modified_at": None,
"parent_id": "c2e09554-833e-41a1-bc9d-8160aec0d70d",
"parent_type": "investigation",
}
]
}
}
taegis-fetch-endpoint
Base Command
!taegis-fetch-endpoint
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Endpoint ID to fetch | True |
Command Example
!taegis-fetch-endpoint id=ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f
Context Example
{
"TaegisXDR": {
"assetEndpointInfo": {
"hostId": "",
"hostName": "",
"actualIsolationStatus": "",
"allowedDomain": "",
"desiredIsolationStatus": "",
"firstConnectTime": "",
"moduleHealth": {
"enabled": ""
"lastRunningTime": "",
"moduleDisplayName": "",
}
"lastConnectAddress": "",
"lastConnectTime": "",
"sensorVersion": ""
}
}
}
taegis-fetch-investigation
Base Command
!taegis-fetch-investigation
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Investigation ID to lookup | True |
Command Example
!taegis-fetch-investigation id=936c1cc1-db8f-430c-837c-1c914fcca35a
Context Example
{
"TaegisXDR": {
"Investigations": [
{
"archived_at": None,
"created_at": "2022-02-02T13:53:35Z",
"description": "Test Investigation",
"id": "c2e09554-833e-41a1-bc9d-8160aec0d70d",
"key_findings": "",
"priority": 2,
"service_desk_id": "",
"service_desk_type": "",
"status": "Open",
"alerts2": [],
"url": "https://ctpx.secureworks.com/investigations/c2e09554-833e-41a1-bc9d-8160aec0d70d",
}
]
}
}
taegis-fetch-investigation-alerts
Base Command
!taegis-fetch-investigation-alerts
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Investigation ID to lookup | True |
Command Example
!taegis-fetch-investigation-alerts id=936c1cc1-db8f-430c-837c-1c914fcca35a
Context Example
{
"TaegisXDR": {
"InvestigationAlerts": [
{
"id": "c4f33b53-eaba-47ac-8272-199af0f7935b",
"description": "Test Alert",
"message": "This is a test alert",
"severity": 0.5,
}
]
}
}
taegis-fetch-investigations
Base Command
!taegis-fetch-investigations
Inputs
| Argument Name | Description | Required |
|---|---|---|
| page | False | |
| page_size | False |
Command Example
!taegis-fetch-investigations
Context Example
{
"TaegisXDR": {
"Investigations": [
{
"description": "Test Investigation",
"id": "c2e09554-833e-41a1-bc9d-8160aec0d70d",
"key_findings": "",
"priority": 2,
"service_desk_id": "",
"service_desk_type": "",
"status": "Open"
}
]
}
}
taegis-fetch-playbook-execution
Base Command
!taegis-fetch-playbook-execution
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Playbook execution ID to fetch | True |
Command Example
!taegis-fetch-playbook-execution id=UGxheWJvb2tFeGVjdXRpb246NGYwZDZiNGQtNWNiZS00NDkxLTg3YzYtMDZkNjkxYzMwMTg4
Context Example
{
"TaegisXDR": {
"PlaybookExecution": {
"createdAt": "2022-01-01T13:51:24Z",
"executionTime": 1442,
"id": "UGxheWJvb2tFeGVjdXRpb246NGYwZDZiNGQtNWNiZS00NDkxLTg3YzYtMDZkNjkxYzMwMTg4",
"inputs": {
"alert": {
"message": "Test Alert",
}
},
"instance": {
"name": "Test Alert Instance",
"playbook": {
"name": "Taegis.PagerDutyAlertEvent"
}
},
"outputs": "d6b65662-c1da-4109-8553-c5664918c952",
"state": "Completed",
"updatedAt": "2022-01-01T13:51:31Z"
}
}
}
taegis-fetch-users
Base Command
!taegis-fetch-users
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | The id of the user, in auth0 format |
False |
| The email of the user | False | |
| status | The users to find based on status | False |
| page | False | |
| page_size | False |
Command Example
!taegis-fetch-users id="auth0|123456"
Context Example
{
"TaegisXDR": {
"Users": [
{
"email": "myuser@email.com",
"family_name": "Smith",
"given_name": "John",
"status": "Registered",
"user_id": "auth0|123456"
}
]
}
}
taegis-isolate-asset
Base Command
!taegis-isolate-asset
Input
| Argument Name | Description | Default | Required |
|---|---|---|---|
| id | ID of the asset to isolate | e43b545a-580a-4047-b489-4338c1cc4ba1 |
True |
| reason | The reason for the isolation | See ticket 12345 |
True |
Command Examples
!taegis-isolate-asset id="e43b545a-580a-4047-b489-4338c1cc4ba1" reason="See ticket 12345"
Context Example
{
"TaegisXDR": {
"AssetIsolation": {
"id": "e43b545a-580a-4047-b489-4338c1cc4ba1"
}
}
}
taegis-update-alert-status
Base Command
!taegis-update-alert-status
Input
| Argument Name | Description | Default | Required |
|---|---|---|---|
| ids | A comma-separated list of alerts by IDs | alert://priv:crowdstrike:11772:1666269058114:59284e28-4ec8-542b-a4a1-452c3688bc1a |
True |
| status | The status to update the alert(s) with | FALSE_POSITIVE |
True |
| reason | A comment/reason for the alert status update | See ticket 13245 |
False |
Permitted Status Values
- FALSE_POSITIVE
- NOT_ACTIONABLE
- OPEN
- TRUE_POSITIVE_BENIGN
- TRUE_POSITIVE_MALICIOUS
Command Examples
!taegis-update-alert-status ids="alert://priv:crowdstrike:11772:1677742145475:07e2d9cc-0a04-55ec-890a-97f39d63698e" status=NOT_ACTIONABLE reason="Test Reason"
Context Example
{
"TaegisXDR": {
"AlertStatusUpdate": {
"reason": "feedback updates successfully applied",
"resolution_status": "SUCCESS"
}
}
}
taegis-update-comment
Base Command
!taegis-update-comment
Inputs
| Argument Name | Description | Required |
|---|---|---|
| comment | The comment string to add to the investigation | True |
| id | The comment ID to update | True |
Command Example
!taegis-update-comment id="ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f" comment="Newly updated comment"
Context Example
{
"TaegisXDR": {
"CommentUpdate": {
"id": "593fa115-abad-4a52-9fc4-2ec403a8a1e4"
}
}
}
taegis-update-investigation
Base Command
!taegis-update-investigation
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | Investigation ID to update | True |
| key_findings | False | |
| prioirity | The priority of the Investigation (1-5) | False |
| service_desk_id | An ID or ticket # to relate to an Investigation | False |
| service_desk_type | The type of id related to an investigation (e.g. Jira) | False |
| status | The current status of the Investigation | False |
| assignee_id | The id of a user to assign, in auth0|12345 format |
False |
Note: At least 1 of the above inputs (in addition to id) must be defined
Permitted Status Values
- Active
- Awaiting Action
- Closed: Authorized Activity
- Closed: Confirmed Security Incident
- Closed: False Positive Alert
- Closed: Inconclusive
- Closed: Informational
- Closed: Not Vulnerable
- Closed: Threat Mitigated
- Open
- Suspended
Command Example
!taegis-update-investigation id="936c1cc1-db8f-430c-837c-1c914fcca35a" priority=3 status="Open" service_desk_id="XDR-1234" service_desk_type="Jira"
Context Example
{
"TaegisXDR": {
"InvestigationUpdate": {
"id": "c2e09554-833e-41a1-bc9d-8160aec0d70d"
}
}
}
taegis-unarchive-investigation
Base Command
!taegis-unarchive-investigation
Inputs
| Argument Name | Description | Required |
|---|---|---|
| id | The investigation id to unarchive | True |
Command Example
!taegis-unarchive-investigation id=c207ca4c-8a78-4408-a056-49f05d6eb77d
Context Example
{
"TaegisXDR": {
"UnarchivedInvestigation": {
"id": "c207ca4c-8a78-4408-a056-49f05d6eb77d"
}
}
}
Configuration parameters
environment— Taegis Environment (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsclient_id— Client ID (required)client_secret— Client Secret (required)isFetch— Fetch incidentsmax_fetch— Maximum number of incidents per fetchfirst_fetch— First fetch time intervalincidentFetchInterval— Incidents Fetch IntervalincidentType— Incident typeinclude_assets— Include Assets in Fetch
Commands (18)
-
taegis-archive-investigationArchive an investigation
-
taegis-create-commentCreate a comment on an investigation
-
taegis-create-investigationCreate an Investigation within Taegis
-
taegis-execute-playbookExecutes a Taegis playbook instance
-
taegis-fetch-alertsList Taegis alerts by ID
-
taegis-fetch-assetsFetch assets based on search criteria
-
taegis-fetch-commentFetch comment by comment ID
-
taegis-fetch-commentsFetch comments by Parent Type and ID
-
taegis-fetch-endpointFetch endpoint information
-
taegis-fetch-investigationFetch all investigations or a specific investigation
-
taegis-fetch-investigation-alertsFetch Alert IDs related to a specific investigation
-
taegis-fetch-playbook-executionFetch the results of a Taegis playbook instance execution
-
taegis-fetch-usersFetch a user by ID or email address
-
taegis-isolate-assetIsolate a specific asset
-
taegis-unarchive-investigationUnarchive an investigation
-
taegis-update-alert-statusUpdate the status of an alert
-
taegis-update-commentUpdate an existing comment
-
taegis-update-investigationUpdate an existing investigation
import pytest from CommonServerPython import DemistoException from TaegisXDR import ( Client, execute_playbook_command, fetch_alerts_command, fetch_assets_command, create_comment_command, fetch_comment_command, fetch_comments_command, update_comment_command, fetch_endpoint_command, fetch_incidents, fetch_investigation_command, fetch_investigation_alerts_command, fetch_users_command, fetch_playbook_execution_command, isolate_asset_command, create_investigation_command, update_investigation_command, archive_investigation_command, unarchive_investigation_command, update_alert_status_command, test_module as connectivity_test, ) from test_data.data import * ''' UTILITY FUNCTIONS ''' def mock_client(requests_mock, mock_response): base_url = "https://api.ctpx.secureworks.com" requests_mock.post(f"{base_url}/graphql", json=mock_response) requests_mock.get(f"{base_url}/assets/version", json=mock_response) client = Client( client_id="TestID", client_secret="TestSecret", base_url=base_url, ) return client ''' TESTS ''' def test_execute_playbook(requests_mock): """Tests taegis-execute-playbook command function """ client = mock_client(requests_mock, EXECUTE_PLAYBOOK_RESPONSE) args = { "id": TAEGIS_PLAYBOOK_INSTANCE_ID, "inputs": { "MyInput": "MyValue", } } response = execute_playbook_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == TAEGIS_PLAYBOOK_EXECUTION_ID with pytest.raises(ValueError, match="Cannot execute playbook, missing playbook_id"): assert execute_playbook_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) client = mock_client(requests_mock, EXECUTE_PLAYBOOK_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to execute playbook: must be defined"): assert execute_playbook_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_fetch_alerts(requests_mock): client = mock_client(requests_mock, FETCH_ALERTS_RESPONSE) args = { "limit": 1, "offset": 0, "cql_query": "from alert severity >= 0.6 and status='OPEN'", } # Test with no IDs set response = fetch_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_ALERT assert len(response.outputs) == len([TAEGIS_ALERT]) def test_fetch_alerts_by_id(requests_mock): """Tests taegis-fetch-alert command function """ client = mock_client(requests_mock, FETCH_ALERTS_BY_ID_RESPONSE) # Test with IDs set (list) args = { "ids": ["alert://priv:crowdstrike:11772:1666247222095:4e41ec02-ca53-5ff7-95cc-eda434221ba6"] } response = fetch_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_ALERT assert len(response.outputs) == len([TAEGIS_ALERT]) # Test with IDs set (comma separated list) args = { "ids": "alert://priv:crowdstrike:11772:1666247222095:4e41ec02-ca53-5ff7-95cc-eda434221ba6" } response = fetch_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_ALERT assert len(response.outputs) == len([TAEGIS_ALERT]) def test_fetch_assets(requests_mock): """Tests taegis-fetch-assets command function """ client = mock_client(requests_mock, FETCH_ASSETS_RESPONSE) args = { "page": 0, "page_size": 1, } response = fetch_assets_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == [TAEGIS_ASSET] # Test allowed search fields args = { "host_id": TAEGIS_ASSET["hostId"] } response = fetch_assets_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_ASSET assert len(response.outputs) == len([TAEGIS_ASSET]) # Asset Query Failure client = mock_client(requests_mock, FETCH_ASSETS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to fetch assets:"): assert fetch_assets_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_create_comment(requests_mock): """Tests taegis-create-comment command function """ client = mock_client(requests_mock, CREATE_COMMENT_RESPONSE) # comment not set with pytest.raises(ValueError, match="Cannot create comment, comment cannot be empty"): assert create_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # parent_id not set with pytest.raises(ValueError, match="Cannot create comment, parent_id cannot be empty"): assert create_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args={"comment": "test"}) args = { "comment": FETCH_COMMENT_RESPONSE["data"]["comment"]["comment"], "parent_id": FETCH_COMMENT_RESPONSE["data"]["comment"]["parent_id"], "parent_type": "bad_parent_type", } # Invalid parent type with pytest.raises(ValueError, match="The provided comment parent type, bad_parent_type, is not valid."): assert create_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) args["parent_type"] = "investigation" # # Successful fetch - Comment created response = create_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == CREATE_COMMENT_RESPONSE["data"]["createComment"] # Comment creation failed client = mock_client(requests_mock, CREATE_UPDATE_COMMENT_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to create comment:"): assert create_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_fetch_comment_by_id(requests_mock): """Tests taegis-fetch-comment command function """ client = mock_client(requests_mock, FETCH_COMMENT_RESPONSE) # comment_id not set with pytest.raises(ValueError, match="Cannot fetch comment, missing comment_id"): assert fetch_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) args = {"id": "ff9ca818-4749-4ccb-883a-2ccc6f6c9e0f"} # Successful fetch - Comment found response = fetch_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == FETCH_COMMENT_RESPONSE["data"]["comment"] # Comment not found client = mock_client(requests_mock, {}) with pytest.raises(ValueError, match="Could not locate comment by provided ID"): assert fetch_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_fetch_comments_by_parent(requests_mock): """Tests taegis-fetch-comments command function """ client = mock_client(requests_mock, FETCH_COMMENTS_RESPONSE) # comment_id not set with pytest.raises(ValueError, match="Cannot fetch comments, missing parent_id"): assert fetch_comments_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) args = { "parent_id": "c2e09554-833e-41a1-bc9d-8160aec0d70d", "parent_type": "bad_parent_type", } # Invalid parent type with pytest.raises(ValueError, match="The provided comment parent type, bad_parent_type, is not valid."): assert fetch_comments_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # Successful fetch args["parent_type"] = "investigation" response = fetch_comments_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == FETCH_COMMENTS_RESPONSE["data"]["commentsByParent"] # Comment not found, bad response client = mock_client(requests_mock, FETCH_COMMENTS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to fetch comments:"): assert fetch_comments_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_update_comment(requests_mock): """Tests taegis-update-comment command function """ client = mock_client(requests_mock, UPDATE_COMMENT_RESPONSE) # comment not set with pytest.raises(ValueError, match="Cannot update comment, comment id cannot be empty"): assert update_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # comment_id not set with pytest.raises(ValueError, match="Cannot update comment, comment cannot be empty"): assert update_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args={"id": "test"}) args = { "comment": FETCH_COMMENT_RESPONSE["data"]["comment"]["comment"], "id": FETCH_COMMENT_RESPONSE["data"]["comment"]["id"], } # # Successful fetch - Comment created response = update_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == UPDATE_COMMENT_RESPONSE["data"]["updateComment"] # Comment creation failed client = mock_client(requests_mock, CREATE_UPDATE_COMMENT_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to locate/update comment:"): assert update_comment_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_fetch_endpoint(requests_mock): """Tests taegis-fetch-endpoint command function """ client = mock_client(requests_mock, FETCH_ENDPOINT_RESPONSE) # comment_id not set with pytest.raises(ValueError, match="Cannot fetch endpoint information, missing id"): assert fetch_endpoint_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) args = {"id": "110d1fd3a23c95c0120d0d10451cb001"} # Successful fetch - Endpoint found response = fetch_endpoint_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == FETCH_ENDPOINT_RESPONSE["data"]["assetEndpointInfo"] # Endpoint not found client = mock_client(requests_mock, FETCH_ENDPOINT_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to fetch endpoint information"): assert fetch_endpoint_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_connectivity(requests_mock): response = {"revision": "1e9c12c7f3f51d5ecc0da91d1ac8bcb27e3566a7", "timestamp": "2022-01-01T17:02:01Z"} client = mock_client(requests_mock, response) assert connectivity_test(client=client) == "ok" def test_fetch_incidents(requests_mock): """Tests taegis-fetch-incidents command function """ client = mock_client(requests_mock, FETCH_INCIDENTS_RESPONSE) response = fetch_incidents(client=client) assert response[0]['name'] == FETCH_INCIDENTS_RESPONSE["data"]["allInvestigations"][0]['description'] with pytest.raises(ValueError, match="Max Fetch must be between 1 and 200"): assert fetch_incidents(client=client, max_fetch=0) with pytest.raises(ValueError, match="Max Fetch must be between 1 and 200"): assert fetch_incidents(client=client, max_fetch=201) # Failure from Taegis API client = mock_client(requests_mock, FETCH_INCIDENTS_BAD_RESPONSE) error = f"Error when fetching investigations: {FETCH_INCIDENTS_BAD_RESPONSE['errors'][0]['message']}" with pytest.raises(DemistoException, match=error): assert fetch_incidents(client=client, max_fetch=200) # Ignore incidents that have been archived FETCH_INCIDENTS_RESPONSE["data"]["allInvestigations"][0]["archived_at"] = "2022-02-03T13:53:35Z" client = mock_client(requests_mock, FETCH_INCIDENTS_RESPONSE) response = fetch_incidents(client=client) assert len(response) == 0 def test_fetch_investigaton(requests_mock): """Tests taegis-fetch-investigation command function Test fetching of a single incident """ client = mock_client(requests_mock, FETCH_INVESTIGATION_RESPONSE) args = { "id": "c2e09554-833e-41a1-bc9d-8160aec0d70d", "page": 0, "page_sie": 1, } response = fetch_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_INVESTIGATION # Investigation not found client = mock_client(requests_mock, {}) response = fetch_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert len(response.outputs) == 0 def test_fetch_investigatons(requests_mock): """Tests taegis-fetch-investigations command function Test fetching of all incidents """ client = mock_client(requests_mock, FETCH_INVESTIGATIONS) args = { "page": 0, "page_size": 1, } response = fetch_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == [TAEGIS_INVESTIGATION] def test_fetch_investigation_alerts(requests_mock): """Tests taegis-fetch-investigation-alerts command function """ client = mock_client(requests_mock, FETCH_INVESTIGATION_ALERTS_RESPONSE) args = { "id": "c2e09554-833e-41a1-bc9d-8160aec0d70d", } response = fetch_investigation_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_ALERT assert len(response.outputs) == len([TAEGIS_ALERT]) # No alerts returned client = mock_client(requests_mock, {}) response = fetch_investigation_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert len(response.outputs) == 0 # Investigation ID not provided with pytest.raises(ValueError, match="Cannot fetch investigation, missing investigation_id"): assert fetch_investigation_alerts_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) def test_fetch_playbook_execution(requests_mock): """Tests taegis-fetch-playbook-execution command function """ client = mock_client(requests_mock, FETCH_PLAYBOOK_EXECUTION_RESPONSE) args = { "id": TAEGIS_PLAYBOOK_EXECUTION_ID, } response = fetch_playbook_execution_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == TAEGIS_PLAYBOOK_EXECUTION client = mock_client(requests_mock, FETCH_PLAYBOOK_EXECUTION_RESPONSE) with pytest.raises(ValueError, match="Cannot fetch playbook execution, missing execution id"): assert fetch_playbook_execution_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) client = mock_client(requests_mock, FETCH_PLAYBOOK_EXECUTION_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to fetch playbook execution"): assert fetch_playbook_execution_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_create_investigation(requests_mock): """Tests taegis-create-investigation command function """ client = mock_client(requests_mock, CREATE_INVESTIGATION_RESPONSE) args = { "description": "Test Investigation", "priority": 3, } response = create_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == CREATE_INVESTIGATION_RESPONSE["data"]["createInvestigation"]["id"] # Investigation creation failed client = mock_client(requests_mock, FETCH_INCIDENTS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to create investigation:"): assert create_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_update_investigation(requests_mock): """Tests taegis-update-investigation command function """ client = mock_client(requests_mock, UPDATE_INVESTIGATION_RESPONSE) args = { "id": UPDATE_INVESTIGATION_RESPONSE["data"]["updateInvestigation"]["id"], "description": "Test Investigation Updated", "priority": 2, "status": "Active", } response = update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == args["id"] # investigation_id not set with pytest.raises(ValueError, match="Cannot fetch investigation without investigation_id defined"): assert update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # Investigation update failure client = mock_client(requests_mock, FETCH_COMMENTS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to locate/update investigation"): assert update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # Invalid investigation status args["status"] = "BadStatus" bad_status = r"The provided status, BadStatus, is not valid for updating an investigation. Supported Status Values:.*" with pytest.raises(ValueError, match=bad_status): assert update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # Invalid Assignee ID Format args["assignee_id"] = "BadAssigneeIDFormat" invalid_fields = r"assignee_id MUST be in 'auth0|12345' format or '@secureworks'" with pytest.raises(ValueError, match=invalid_fields): assert update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # No valid update fields set args = {"id": UPDATE_INVESTIGATION_RESPONSE["data"]["updateInvestigation"]["id"]} invalid_fields = r"No valid investigation fields provided. Supported Update Fields:.*" with pytest.raises(ValueError, match=invalid_fields): assert update_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_archive_investigation(requests_mock): """Tests taegis-archive-investigation command function """ client = mock_client(requests_mock, INVESTIGATION_ARCHIVE_RESPONSE) # Test Archiving args = {"id": TAEGIS_INVESTIGATION["id"]} response = archive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == args["id"] assert response.raw_response["data"]["archiveInvestigation"] # investigation id not set with pytest.raises(ValueError, match="Cannot archive investigation, missing investigation id"): assert archive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # Investigation archive not found client = mock_client(requests_mock, INVESTIGATION_ARCHIVE_ALREADY_COMPLETE) with pytest.raises(ValueError, match="Could not locate investigation with id:.*"): assert archive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_unarchive_investigation(requests_mock): """Tests taegis-unarchive-investigation command function """ client = mock_client(requests_mock, INVESTIGATION_UNARCHIVE_RESPONSE) # Test Unarchiving args = {"id": TAEGIS_INVESTIGATION["id"]} response = unarchive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == args["id"] assert response.raw_response["data"]["unArchiveInvestigation"] # investigation id not set with pytest.raises(ValueError, match="Cannot unarchive investigation, missing investigation id"): assert unarchive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # Investigation is not archived client = mock_client(requests_mock, INVESTIGATION_ARCHIVE_ALREADY_COMPLETE) response = unarchive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs["id"] == args["id"] assert response.outputs["status"] == "Investigation is not currently archived" # Could not find investigation by investigation id args = {"id": "InvalidInvestigationId"} client = mock_client(requests_mock, INVESTIGATION_NOT_ARCHIVED_RESPONSE) with pytest.raises(ValueError, match="Could not locate investigation with id:.*"): assert unarchive_investigation_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_isolate_asset(requests_mock): """Tests taegis-isolate-asset command function """ client = mock_client(requests_mock, ISOLATE_ASSET_RESPONSE) # asset id not set with pytest.raises(ValueError, match="Cannot isolate asset, missing id"): assert isolate_asset_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) args = {"id": TAEGIS_ASSET["id"]} # reason not set with pytest.raises(ValueError, match="Cannot isolate asset, missing reason"): assert isolate_asset_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) args["reason"] = "My isolation reason" # Successful isolation response = isolate_asset_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == ISOLATE_ASSET_RESPONSE["data"]["isolateAsset"] # Endpoint not found client = mock_client(requests_mock, ISOLATE_ASSET_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to isolate asset"): assert isolate_asset_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_fetch_users(requests_mock): client = mock_client(requests_mock, FETCH_USERS_RESPONSE) args = { "limit": 1, "page_size": 0, } response = fetch_users_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_USER assert len(response.outputs) == len([TAEGIS_USER]) client = mock_client(requests_mock, FETCH_USERS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to fetch user information:"): assert fetch_users_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # Test user search by email client = mock_client(requests_mock, FETCH_USERS_RESPONSE) args["email"] = TAEGIS_USER["email"] response = fetch_users_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_USER assert len(response.outputs) == len([TAEGIS_USER]) # Test user search by auth0 user id client = mock_client(requests_mock, FETCH_USER_RESPONSE) args["id"] = TAEGIS_USER["user_id"] args.pop("email") response = fetch_users_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs[0] == TAEGIS_USER assert len(response.outputs) == len([TAEGIS_USER]) # Invalid id Format args["id"] = "BadAssigneeIDFormat" invalid_fields = r"id MUST be in 'auth0|12345' format" with pytest.raises(ValueError, match=invalid_fields): assert fetch_users_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) def test_update_alert_status(requests_mock): """Tests taegis-update-alert-status command function """ client = mock_client(requests_mock, UPDATE_ALERT_STATUS_RESPONSE) args = {"ids": TAEGIS_ALERT['id']} # alert ids not set with pytest.raises(ValueError, match="Alert IDs must be defined"): assert update_alert_status_command(client=client, env=TAEGIS_ENVIRONMENT, args={}) # status not set with pytest.raises(ValueError, match="Alert status must be defined"): assert update_alert_status_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) args["status"] = "Bad Status" with pytest.raises(ValueError, match="The provided status, Bad Status, is not valid for updating an alert"): assert update_alert_status_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) # Successful update args["status"] = "NOT_ACTIONABLE" response = update_alert_status_command(client=client, env=TAEGIS_ENVIRONMENT, args=args) assert response.outputs == UPDATE_ALERT_STATUS_RESPONSE["data"]["alertsServiceUpdateResolutionInfo"] # Alert not updated client = mock_client(requests_mock, UPDATE_ALERT_STATUS_BAD_RESPONSE) with pytest.raises(ValueError, match="Failed to locate/update alert"): assert update_alert_status_command(client=client, env=TAEGIS_ENVIRONMENT, args=args)