CounterCraft Deception Director
CounterCraft Deception Solution detects advanced adversaries. Automate counterintelligence campaigns to discover targeted attacks with real-time active response.
Deception & Breach Simulation · CounterCraft Deception Director
Details
| ID | CounterCraft Deception Director |
|---|---|
| Provider | CounterCraft |
| Category | Deception & Breach Simulation |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Overview
CounterCraft Deception Solution detects advanced adversaries. Automate counterintelligence campaigns to discover targeted attacks with real-time active response.
This integration was integrated and tested with version 2.5.13 of CounterCraft Deception Director
CounterCraft Deception Director Playbook
Use Cases
- Query IOCs (objects) in your Deception Director
- Retrieve events from your deception campaigns
- Retrieve configuration from your Deception Director
- Retrieve alerts (notifications) from your Deception Director
- Create new deception campaigns
- Create new deception hosts
- Operate your campaigns, hosts, services and breadcrumbs
Prerequisites
You need to obtain the following Deception Director information.
- Server URL
- API Key
- Secret Key
In order to obtain the API Key and the Secret Key you need to go to the user settings in the Deception Director
and copy both or generate a new pair if they are not already generated.
Configure CounterCraft Deception Director on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for CounterCraft Deception Director.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- Deception Director Domain or IP Address: for example, https://192.168.1.1
- Fetch incidents: if you select this option, your notifications in the Deception Director will be created as Cortex XSOAR incidents.
- Incident type
- API Key for Deception Director connection: paste your API Key.
- Secret Key for Deception Director connection: paste your Secret Key.
- Ignore SSL Warnings: in case the SSL certificate is self-signed.
- Use system proxy settings: in case you need to connect through a proxy.
- Click Test to validate the URLs, token, and connection.
Fetched Incidents Data
Commands
You can execute these commands from the Cortex XSOAR 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.
- countercraft-list-campaigns
- countercraft-list-hosts
- countercraft-list-services
- countercraft-list-breadcrumbs
- countercraft-get-object
- countercraft-get-events
- countercraft-create-campaign
- countercraft-list-dsns
- countercraft-list-providers
- countercraft-create-host-machine
- countercraft-list-incidents
- countercraft-manage-campaign
- countercraft-manage-host
- countercraft-manage-service
- countercraft-manage-breadcrumb
1. countercraft-list-campaigns
List all deception campaigns
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the campaigns you have access to.
Base Command
countercraft-list-campaigns
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Campaign Name | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Campaign.ID | number | Campaign ID |
| CounterCraft.Campaign.Name | string | Campaign Name |
| CounterCraft.Campaign.Description | string | Campaign Description |
| CounterCraft.Campaign.StatusCode | string | Campaign Status |
Command Example
!countercraft-list-campaigns
Human Readable Output
| ID | Name | Description | StatusCode |
|---|---|---|---|
| 1 | AntiPhishing | Gather intelligence from phishers | ACTIVE |
| 2 | External recoinassance | Collect pre-attack evidence | ACTIVE |
| 3 | Internal lateral movement | Detect lateral movement | ACTIVE |
| 4 | DMZ | DMZ activity | ACTIVE |
| 5 | VIP | VIP mobile protection | ACTIVE |
2. countercraft-list-hosts
Lists all deception hosts
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the hosts you have access to.
Base Command
countercraft-list-hosts
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | Campaign ID | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Host.ID | number | Host Id |
| CounterCraft.Host.Name | string | Host Name |
| CounterCraft.Host.Description | string | Host Description |
| CounterCraft.Host.StatusCode | string | Host Status |
| CounterCraft.Host.TypeCode | string | Host Type |
Command Example
!countercraft-list-hosts campaign_id=2
Human Readable Output
| ID | Name | Description | StatusCode | TypeCode |
|---|---|---|---|---|
| 1 | Ubuntu Web | Wordpress | ACTIVE | MACHINE |
| 2 | Azure Windows 2019 | RDP with breadcrumbs | ACTIVE | MACHINE |
| 3 | Office365 tenant | Office365 with domain name | ACTIVE | CLOUD_ENTITY |
| 4 | Apache Struts | Vulnerable Apache Struts | ACTIVE | MACHINE |
| 5 | CFO | CFO persona | ACTIVE | IDENTITY |
3. countercraft-list-services
List services currently deployed on deception hosts
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the services you have access to.
Base Command
countercraft-list-services
Input
| Argument Name | Description | Required |
|---|---|---|
| host_id | Host Id | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Service.ID | number | Service ID |
| CounterCraft.Service.Name | string | Service Name |
| CounterCraft.Service.Description | string | Service.Description |
| CounterCraft.Service.StatusCode | string | Service Status |
| CounterCraft.Service.TypeCode | string | Service Type |
Command Example
!countercraft-list-services host_id=1
Human Readable Output
| ID | Name | Description | StatusCode | TypeCode |
|---|---|---|---|---|
| 1 | Operating system | User events | ACTIVE | SYSTEM |
| 2 | WebApp | Web application | ACTIVE | WEB_SERVER |
| 8 | Tailored Service | Anonymous FTP | ACTIVE | FTP_SERVER |
| 9 | Phishing Sinkhole | Sinkhole | ACTIVE | SMTP_SERVER |
4. countercraft-list-breadcrumbs
List breadcrumbs in a campaign
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the breadcrumbs you have access to.
Base Command
countercraft-list-breadcrumbs
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | Campaign ID | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Breadcrumb.ID | number | Breadcrumb ID |
| CounterCraft.Breadcrumb.Name | string | Breadcrumb Name |
| CounterCraft.Breadcrumb.Description | string | Breadcrumb Description |
| CounterCraft.Breadcrumb.StatusCode | string | Breadcrumb Status |
| CounterCraft.Breadcrumb.TypeCode | string | Breadcrumb Type |
Command Example
!countercraft-list-breadcrumbs campaign_id=1
Human Readable Output
| ID | Name | Description | StatusCode | TypeCode |
|---|---|---|---|---|
| 1 | Fake document | ACTIVE | DOCUMENT | |
| 2 | Mobile App | ACTIVE | MOBILE_APP | |
| 3 | SSL Certificate | ACTIVE | SSL_CERTIFICATE | |
| 4 | LinkedIn_persona | ACTIVE | HONEYTOKEN |
5. countercraft-get-object
Get information about an object (IoC)
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the objects you have access to.
Base Command
countercraft-get-object
Input
| Argument Name | Description | Required |
|---|---|---|
| value | Object value | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Object.ID | number | Object ID |
| CounterCraft.Object.Value | string | Object value |
| CounterCraft.Object.Hits | number | Object hits |
| CounterCraft.Object.Score | number | Object score |
| CounterCraft.Object.TypeCode | string | Object type |
| CounterCraft.Object.FirstSeen | date | Object first seen |
| CounterCraft.Object.LastSeen | date | Object last seen |
| CounterCraft.Object.EventsCount | number | Object events count |
| CounterCraft.Object.Tags | string | Object tags |
Command Example
!countercraft-get-object value=root
Human Readable Output
| Id | 852 |
| Value | root |
| EventsCount | 7 |
| TypeCode | CC_USERNAME |
| Score | 0 |
| FirstSeen | Wed Jan 29 12:33:34 2020 |
| LastSeen | Wed Jan 29 12:53:19 2020 |
| Tags |
6. countercraft-get-events
Get full list of Events
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the objects you have access to.
Base Command
countercraft-get-events
Input
| Argument Name | Description | Required |
|---|---|---|
| criteria | Search criteria | Required |
| max_results | Maximum number of results | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Event.ID | number | Event id |
| CounterCraft.Event.CampaignName | string | Campaign name |
| CounterCraft.Event.CategoryCode | string | Category Code |
| CounterCraft.Event.EventDate | date | Event date |
| CounterCraft.Event.HostName | string | Host name |
| CounterCraft.Event.ServiceName | string | Service name |
| CounterCraft.Event.TypeCode | string | Type |
| CounterCraft.Event.Score | number | Score |
| CounterCraft.Event.Tags | string | Tags |
| CounterCraft.Events.Data | unknown | Data |
Command Example
!countercraft-get-events criteria="type_code:ValidAuth" max_results="1"
Human Readable Output
| Id | 45 | |
| Campaignname | External recoinassance | |
| Hostname | Azure | Windows |
| Servicename | OS Logs (Azure | Windows) |
| Eventdate | Thu Jan 30 08:11:01 2020 | |
| Score | 100 | |
| Typecode | ValidAuth | |
| Data | event: ValidAuth subject: A session was reconnected to a Window Station event_id: 4778 … | |
| Tags | attack.T1078 |
7. countercraft-create-campaign
Create a new deception campaign
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You can only create campaigns if you have the role ARCHITECT.
Base Command
countercraft-create-campaign
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Campaign name | Required |
| description | Campaign description | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Campaign.ID | number | Campaign ID |
| CounterCraft.Campaign.Name | string | Name |
| CounterCraft.Campaign.Description | string | Description |
| CounterCraft.Campaign.StatusCode | string | Status Code |
Command Example
!countercraft-create-campaign name="TestCampaign" description="Test Description"
Human Readable Output
| Id | 5 |
| Name | TestCampaign |
| Description | Test Description |
| StatusCode | DESIGN |
8. countercraft-list-dsns
List Deception Support Nodes (DSNs)
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You can only create campaigns if you have the role ARCHITECT.
Base Command
countercraft-list-dsns
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.DSN.ID | number | ID |
| CounterCraft.DSN.Name | string | Name |
| CounterCraft.DSN.Description | string | Description |
| CounterCraft.DSN.Hostname | string | Hostname |
| CounterCraft.DSN.Port | number | Port |
Command Example
!countercraft-list-dsns
Human Readable Output
| Id | 1 |
| Name | Local DSN |
| Description | Local DSN in the intranet |
| Hostname | 192.168.1.2 |
| Port | 4567 |
9. countercraft-list-providers
List providers (providers for hosts or services i.e. AWS or Office365)
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the providers you have access to.
Base Command
countercraft-list-providers
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| ID | number | ID |
| CounterCraft.Provider.Name | string | Name |
| CounterCraft.Provider.Description | string | Description |
| CounterCraft.Provider.TypeCode | string | Type |
| CounterCraft.Provider.StatusCode | string | Status |
Command Example
!countercraft-list-providers
Human Readable Output
| ID | Name | Description | StatusCode | TypeCode |
|---|---|---|---|---|
| 1 | Splunk | Internal Splunk | HEALTHY | SPLUNK_PROVIDER |
| 3 | Signal | Signal notifications | HEALTHY | SIGNAL_PROVIDER |
| 4 | Office365 | Office365 Tenant | HEALTHY | OFFICE365_PROVIDER |
| 5 | AWS | AWS EC2 | HEALTHY | AWS_PROVIDER |
10. countercraft-create-host-machine
Deploy a new deception host
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to create a host if you are MANAGER in a campaign.
Base Command
countercraft-create-host-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Name | Required |
| description | Description | Optional |
| provider_id | Provider | Required |
| deception_support_node_id | Deception Support Node ID | Required |
| campaign_id | Campaign | Required |
| os_family | Operating System | Required |
| ip_address | IP Address | Required |
| port | Port | Required |
| username | Username | Required |
| password | Password | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Host.Id | number | Host ID |
Command Example
!countercraft-create-host-machine campaign_id=2 deception_support_node_id=1 os_family=linux ip_address=192.168.1.2 port=22 name="Test host" description="Test Description" username="ubuntu" password="ubuntu provider_id=1"
Human Readable Output
| Id | 8 |
| Name | Test Host |
| Description | Test Description |
| StatusCode | DESIGN |
| TypeCode | MACHINE |
11. countercraft-list-incidents
List all incidents currently active
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to list only the incidents you have access to.
Base Command
countercraft-list-incidents
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | Campaign ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Incident.ID | number | Incident ID |
| CounterCraft.Incident.Name | string | Name |
| CounterCraft.Incident.Description | string | Description |
| CounterCraft.Incident.StatusCode | string | Status |
| CounterCraft.Incident.TLPCode | string | TLP code |
Command Example
!countercraft-list-incidents campaign_id=1
Human Readable Output
| ID | Name | Description | StatusCode | TLPCode | Tags |
|---|---|---|---|---|---|
| 1 | APT incident | State-sponsored | OPEN | AMBER | |
| 2 | Internal Fraud | SWIFT apps | CLOSED | AMBER |
12. countercraft-manage-campaign
Manage Campaign parameters
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to manage only the campaigns you have access to.
Base Command
countercraft-manage-campaign
Input
| Argument Name | Description | Required |
|---|---|---|
| campaign_id | Campaign ID | Required |
| operation | Operation | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Campaign.Message | string | Result message |
| CounterCraft.Campaign.ID | number | Campaign ID |
Command Example
!countercraft-manage-campaign campaign_id=5 operation=activate
Human Readable Output
| Id | 5 |
| Message | Campaign is currently in state: PAUSED. Action activate discarded |
13. countercraft-manage-host
Manage a deception host
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to manage only the hosts you have access to.
Base Command
countercraft-manage-host
Input
| Argument Name | Description | Required |
|---|---|---|
| host_id | Host ID | Required |
| operation | Operation | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Host.Message | string | Result message |
| CounterCraft.Host.ID | number | Host ID |
Command Example
!countercraft-manage-campaign host_id=5 operation=activate
Human Readable Output
| Id | 5 |
| Message | Host is currently in state: PAUSED. Action activate discarded |
14. countercraft-manage-service
Manage a deception service
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to manage only the services you have access to.
Base Command
countercraft-manage-service
Input
| Argument Name | Description | Required |
|---|---|---|
| service_id | Service ID | Required |
| operation | Operation | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Service.Message | string | Result message |
| CounterCraft.Service.ID | number | Service ID |
Command Example
!countercraft-manage-campaign service_id=5 operation=activate
Human Readable Output
| Id | 5 |
| Message | Service is currently in state: PAUSED. Action activate discarded |
15. countercraft-manage-breadcrumb
Manage breadcrumb
Required Permissions
Any interaction will be based on your permissions on the Deception Director. Please consult
your Deception Director administrator in you have any questions.
You will be able to manage only the breadcrumbs you have access to.
Base Command
countercraft-manage-breadcrumb
Input
| Argument Name | Description | Required |
|---|---|---|
| breadcrumb_id | Breadcrumb ID | Required |
| operation | Operation | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CounterCraft.Breadcrumb.Message | string | Result message |
| CounterCraft.Breadcrumb.ID | number | Breadcrumb ID |
Command Example
!countercraft-manage-campaign breadcrumb_id=5 operation=activate
Human Readable Output
| Id | 5 |
| Message | Breadcrumb is currently in state: PAUSED. Action activate discarded |
Additional Information
Please check the Deception Director user manual for more guidance on how to use and deploy campaigns.
Configuration parameters
server— Deception Director Domain or IP Address (required)api_key— API Key for Deception Director connection (required)secret_key— Secret Key for Deception Director connection (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Interval
Commands (15)
-
countercraft-create-campaignCreate a new deception campaign.
-
countercraft-create-host-machineDeploy a new deception host.
-
countercraft-get-eventsGet full list of Events.
-
countercraft-get-objectGet information about an object (IoC).
-
countercraft-list-breadcrumbsList breadcrumbs in a campaign.
-
countercraft-list-campaignsList all deception campaigns.
-
countercraft-list-dsnsList Deception Support Nodes (DSNs).
-
countercraft-list-hostsLists all deception hosts.
-
countercraft-list-incidentsList all incidents currently active.
-
countercraft-list-providersList providers (providers for hosts or services i.e. AWS or Office365).
-
countercraft-list-servicesList services currently deployed on deception hosts.
-
countercraft-manage-breadcrumbManage breadcrumb.
-
countercraft-manage-campaignManage Campaign parameters.
-
countercraft-manage-hostManage a deception host.
-
countercraft-manage-serviceManage a deception service.
import demistomock as demisto import pytest from CommonServerPython import formatEpochDate SERVER_URL = "https://1.2.3.4" @pytest.fixture(autouse=True) def get_params(requests_mock, mocker): mocker.patch.object( demisto, "params", return_value={ "server": SERVER_URL, "api_key": "1234567890", "secret_key": "s3cr3t", "insecure": False, }, ) def test_list_dsns_command(requests_mock, mocker): from CounterCraft import list_dsns_command from test_data.api_response import response_dsns as json_response requests_mock.get(f"{SERVER_URL}/api/deception_support_nodes", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_dsns_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Deception Support Node\n|Id|Name|Description|Hostname|Port|\n|---|---|---|---|---|\n| 2 | \ Remote DSN | Remote DSN | 1.2.3.3 | 7080 |\n| 1 | Local network | Local network | thedsn | 7080 |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.DSN(val.ID && val.ID === obj.ID)": [ { "ID": 2, "Name": "Remote DSN", "Description": "Remote DSN", "Hostname": "1.2.3.3", "Port": 7080, }, { "ID": 1, "Name": "Local network", "Description": "Local network", "Hostname": "thedsn", "Port": 7080, }, ] } def test_list_providers_command(requests_mock, mocker): from CounterCraft import list_providers_command from test_data.api_response import response_providers as json_response requests_mock.get(f"{SERVER_URL}/api/providers", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_providers_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Providers\n|Id|Name|Description|Typecode|Statuscode|\n|---|---|---|---|---|\n| 1 | \ ManualMachine | Hosts that are manually created | MANUAL_MACHINE | ACTIVE |\n| 2 | CompanyProvider | \ Hosts that are automatically created when activating breadcrumbs | COMPANY_PROVIDER | ACTIVE |\n| 3 | \ ManualIdentity | Identities that are manually created | MANUAL_IDENTITY | ACTIVE |\n| 4 | ManualRouter | \ Routers that are manually created | MANUAL_ROUTER | ACTIVE |\n| 5 | MISP Provider | | MISP_PROVIDER | ACTIVE |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Provider(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "ManualMachine", "Description": "Hosts that are manually created", "TypeCode": "MANUAL_MACHINE", "StatusCode": "ACTIVE", }, { "ID": 2, "Name": "CompanyProvider", "Description": "Hosts that are automatically created when activating breadcrumbs", "TypeCode": "COMPANY_PROVIDER", "StatusCode": "ACTIVE", }, { "ID": 3, "Name": "ManualIdentity", "Description": "Identities that are manually created", "TypeCode": "MANUAL_IDENTITY", "StatusCode": "ACTIVE", }, { "ID": 4, "Name": "ManualRouter", "Description": "Routers that are manually created", "TypeCode": "MANUAL_ROUTER", "StatusCode": "ACTIVE", }, { "ID": 5, "Name": "MISP Provider", "TypeCode": "MISP_PROVIDER", "StatusCode": "ACTIVE", }, ] } def test_list_campaigns_command(requests_mock, mocker): from CounterCraft import list_campaigns_command from test_data.api_response import response_campaigns as json_response requests_mock.get(f"{SERVER_URL}/api/campaigns", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_campaigns_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Campaigns\n|Id|Name|Description|Statuscode|\n|---|---|---|---|\n| 1 | \ Devel Campaign | Campaign just to be used in devel | DESIGN |\n| 2 | 2nd Campaign | \ Campaign just to be used in devel 2 | DESIGN |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Campaign(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "Devel Campaign", "Description": "Campaign just to be used in devel", "StatusCode": "DESIGN", }, { "ID": 2, "Name": "2nd Campaign", "Description": "Campaign just to be used in devel 2", "StatusCode": "DESIGN", }, ] } def test_list_hosts_command(requests_mock, mocker): from CounterCraft import list_hosts_command from test_data.api_response import response_hosts as json_response requests_mock.get(f"{SERVER_URL}/api/hosts", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_hosts_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Hosts\n|Id|Name|Description|Statuscode|Typecode|\n|---|---|---|---|---|\n| 1 | \ Linux in AWS | Linux machine in AWS | DESIGN | MACHINE |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Host(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "Linux in AWS", "Description": "Linux machine in AWS", "TypeCode": "MACHINE", "StatusCode": "DESIGN", } ], "Host(val.IP && val.IP === obj.IP)": [{"ID": "61daa693-11cf-49a6-8fae-5111f630ee39", "IP": "1.4.5.6"}], } def test_list_services_command(requests_mock, mocker): from CounterCraft import list_services_command from test_data.api_response import response_services as json_response requests_mock.get(f"{SERVER_URL}/api/services", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_services_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Services\n|Id|Name|Description|Statuscode|Typecode|\n|---|---|---|---|---|\n| 1 | \ Employee web portal | <p>-</p> | ACTIVE | WEB_SERVER |\n| 2 | Test | <p>-</p> | DESIGN | WEB_SERVER |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Service(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "Employee web portal", "Description": "<p>-</p>", "TypeCode": "WEB_SERVER", "StatusCode": "ACTIVE", }, { "ID": 2, "Name": "Test", "Description": "<p>-</p>", "TypeCode": "WEB_SERVER", "StatusCode": "DESIGN", }, ] } def test_list_breadcrumbs_command(requests_mock, mocker): from CounterCraft import list_breadcrumbs_command from test_data.api_response import response_breadcrumbs as json_response requests_mock.get(f"{SERVER_URL}/api/breadcrumbs", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_breadcrumbs_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Breadcrumbs\n|Id|Name|Description|Statuscode|Typecode|\n|---|---|---|---|---|\n| 1 | \ Fake Document | <p>-</p> | DESIGN | DOCUMENT |\n| 2 | Fake Mobile App | <p>-</p> | ACTIVE | MOBILE_APP |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Breadcrumb(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "Fake Document", "Description": "<p>-</p>", "TypeCode": "DOCUMENT", "StatusCode": "DESIGN", }, { "ID": 2, "Name": "Fake Mobile App", "Description": "<p>-</p>", "TypeCode": "MOBILE_APP", "StatusCode": "ACTIVE", }, ] } def test_list_incidents_command(requests_mock, mocker): from CounterCraft import list_incidents_command from test_data.api_response import response_incidents as json_response requests_mock.get(f"{SERVER_URL}/api/incidents", json=json_response, status_code=200) mocker.patch.object(demisto, "results") list_incidents_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Incidents\n|Id|Name|Description|Statuscode|Tlpcode|Tags|\n|---|---|---|---|---|---|\n| 1 | \ Invalid auth | Invalid auth incident. | OPEN | GREEN | |\n" ) assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Incident(val.ID && val.ID === obj.ID)": [ { "ID": 1, "Name": "Invalid auth", "Description": "Invalid auth incident.", "StatusCode": "OPEN", "TLPCode": "GREEN", } ] } def test_get_object_command(requests_mock, mocker): from CounterCraft import get_object_command from test_data.api_response import response_objects as json_response mocker.patch.object(demisto, "args", return_value={"value": "1.2.3.3"}) requests_mock.get(f"{SERVER_URL}/api/objects", json=json_response, status_code=200) mocker.patch.object(demisto, "results") get_object_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == f"### Objects\n|Id|Value|Hits|Eventscount|Typecode|Score|Firstseen|Lastseen|Tags|\n|\ ---|---|---|---|---|---|---|---|---|\n| 1411 | 1.2.3.3 | 370 | 168 | CC_IP | 0 | \ {formatEpochDate(json_response['data'][0]['first_seen'])} | {formatEpochDate(json_response['data'][0]['last_seen'])} | |\n" ) # Only dates have been changed results["Contents"][0]["first_seen"] = 1507030039.331 results["Contents"][0]["last_seen"] = 1507313997.703 assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Object(val.ID && val.ID === obj.ID)": [ { "ID": 1411, "Value": "1.2.3.3", "Hits": 370, "Score": 0, "TypeCode": "CC_IP", "FirstSeen": f"{formatEpochDate(json_response['data'][0]['first_seen'])}", "LastSeen": f"{formatEpochDate(json_response['data'][0]['last_seen'])}", "EventsCount": 168, } ] } def test_get_events_command(requests_mock, mocker): from CounterCraft import get_events_command from test_data.api_response import response_events as json_response mocker.patch.object( demisto, "args", return_value={"criteria": "type_code:ValidAuth", "max_results": 1}, ) requests_mock.get(f"{SERVER_URL}/api/events", json=json_response, status_code=200) mocker.patch.object(demisto, "results") get_events_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == f"### Events\n|Id|Campaignname|Categorycode|Hostname|Servicename|Eventdate|Score|\ Typecode|Data|Tags|\n|---|---|---|---|---|---|---|---|---|---|\n| 7882 | Linux Campaign | | \ Ubuntu18.04 | SYSTEM (Ubuntu18.04) | {formatEpochDate(json_response['data'][0]['event_date'])} | 100 | ValidAuth | \ event: ValidAuth<br>subject: Login successful<br>username: ubuntu<br>logon_type: -1<br>process_basename: su | \ attack.T1078 |\n" ) # Only dates have been changed results["Contents"][0]["event_date"] = 1570049630.0 assert results["Contents"] == json_response["data"] assert results["EntryContext"] == { "CounterCraft.Event(val.ID && val.ID === obj.ID)": [ { "ID": 7882, "CampaignName": "Linux Campaign", "HostName": "Ubuntu18.04", "ServiceName": "SYSTEM (Ubuntu18.04)", "EventDate": f"{formatEpochDate(json_response['data'][0]['event_date'])}", "Score": 100, "TypeCode": "ValidAuth", "Data": { "event": "ValidAuth", "subject": "Login successful", "username": "ubuntu", "logon_type": -1, "process_basename": "su", }, "Tags": ["attack.T1078"], } ] } def test_create_campaign_command(requests_mock, mocker): from CounterCraft import create_campaign_command from test_data.api_response import response_campaigns as json_response mocker.patch.object( demisto, "args", return_value={"name": "TestCampaign", "description": "Test Description"}, ) requests_mock.post(f"{SERVER_URL}/api/campaigns", json=json_response["data"][0], status_code=201) mocker.patch.object(demisto, "results") create_campaign_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Campaign\n|Id|Name|Description|Statuscode|\n|---|---|---|---|\n| 1 | Devel Campaign | \ Campaign just to be used in devel | DESIGN |\n" ) assert results["Contents"] == json_response["data"][0] assert results["EntryContext"] == { "CounterCraft.Campaign(val.ID && val.ID === obj.ID)": { "ID": 1, "Name": "Devel Campaign", "Description": "Campaign just to be used in devel", "StatusCode": "DESIGN", } } def test_manage_campaign_command(requests_mock, mocker): from CounterCraft import manage_campaign_command mocker.patch.object( demisto, "args", return_value={"campaign_id": "1", "operation": "activate"}, ) requests_mock.patch( f"{SERVER_URL}/api/campaigns/1", json={"message": "Action successful"}, status_code=200, ) mocker.patch.object(demisto, "results") manage_campaign_command() results = demisto.results.call_args[0][0] assert results["HumanReadable"] == "### Campaign Management\n|Id|Message|\n|---|---|\n| 1 | Action successful |\n" assert results["Contents"] == {"message": "Action successful"} assert results["EntryContext"] == { "CounterCraft.Campaign(val.ID && val.ID === obj.ID)": [{"ID": "1", "Message": "Action successful"}] } def test_create_host_command(requests_mock, mocker): from CounterCraft import create_host_machine_command from test_data.api_response import response_hosts as json_response mocker.patch.object( demisto, "args", return_value={ "name": "TestCampaign", "description": "Test Description", "provider_id": 1, "deception_support_node_id": 1, "campaign_id": 1, "ip_address": "1.1.1.1", "port": 22, "username": "ubuntu", "password": "password", }, ) requests_mock.post(f"{SERVER_URL}/api/hosts", json=json_response["data"][0], status_code=201) mocker.patch.object(demisto, "results") create_host_machine_command() results = demisto.results.call_args[0][0] assert ( results["HumanReadable"] == "### Hosts\n|Id|Name|Description|Statuscode|Typecode|\n|---|---|---|---|---|\n| 1 | \ Linux in AWS | Linux machine in AWS | DESIGN | MACHINE |\n" ) assert results["Contents"] == json_response["data"][0] assert results["EntryContext"] == { "CounterCraft.Host(val.ID && val.ID === obj.ID)": { "ID": 1, "Name": "Linux in AWS", "Description": "Linux machine in AWS", "TypeCode": "MACHINE", "StatusCode": "DESIGN", } } def test_manage_host_command(requests_mock, mocker): from CounterCraft import manage_host_command mocker.patch.object( demisto, "args", return_value={"host_id": "1", "operation": "activate"}, ) requests_mock.patch( f"{SERVER_URL}/api/hosts/1", json={"message": "Action successful"}, status_code=200, ) mocker.patch.object(demisto, "results") manage_host_command() results = demisto.results.call_args[0][0] assert results["HumanReadable"] == "### Host Management\n|Id|Message|\n|---|---|\n| 1 | Action successful |\n" assert results["Contents"] == {"message": "Action successful"} assert results["EntryContext"] == { "CounterCraft.Host(val.ID && val.ID === obj.ID)": { "ID": "1", "Message": "Action successful", } } def test_manage_service_command(requests_mock, mocker): from CounterCraft import manage_service_command mocker.patch.object( demisto, "args", return_value={"service_id": "1", "operation": "activate"}, ) requests_mock.patch( f"{SERVER_URL}/api/services/1", json={"message": "Action successful"}, status_code=200, ) mocker.patch.object(demisto, "results") manage_service_command() results = demisto.results.call_args[0][0] assert results["HumanReadable"] == "### Service Management\n|Id|Message|\n|---|---|\n| 1 | Action successful |\n" assert results["Contents"] == {"message": "Action successful"} assert results["EntryContext"] == { "CounterCraft.Service(val.ID && val.ID === obj.ID)": { "ID": "1", "Message": "Action successful", } } def test_manage_breadcrumb_command(requests_mock, mocker): from CounterCraft import manage_breadcrumb_command mocker.patch.object( demisto, "args", return_value={"breadcrumb_id": "1", "operation": "activate"}, ) requests_mock.patch( f"{SERVER_URL}/api/breadcrumbs/1", json={"message": "Action successful"}, status_code=200, ) mocker.patch.object(demisto, "results") manage_breadcrumb_command() results = demisto.results.call_args[0][0] assert results["HumanReadable"] == "### Breadcrumb Management\n|Id|Message|\n|---|---|\n| 1 | Action successful |\n" assert results["Contents"] == {"message": "Action successful"} assert results["EntryContext"] == { "CounterCraft.Breadcrumb(val.ID && val.ID === obj.ID)": { "ID": "1", "Message": "Action successful", } } def test_fetch_incidents_command(requests_mock, mocker): from CounterCraft import fetch_incidents_command from test_data.api_response import response_alerts as json_response requests_mock.get( f"{SERVER_URL}/api/notifications", json=json_response, status_code=200, ) mocker.patch.object(demisto, "incidents") fetch_incidents_command() incidents = demisto.incidents.call_args[0][0] assert demisto.incidents.call_count == 1 assert len(incidents) == 1 assert incidents[0]["name"] == "Possible mimikatz"