Skip to content

Commit

Permalink
New plugin Cylance Protect with two action: Blacklist and Get Agent D…
Browse files Browse the repository at this point in the history
…etails (#527)

* [SOAR-1397] [SOAR-1430] New plugin Cylance Protect with two action: Blacklist and Get Agent Details

* Use least privileged user

* Update help

* Improve inputs and descriptions

* Update example inputs and fix punctuation

* Add instructions for connection setup

* Minor fix

* Update title in type, acronym

* Update cylance_protect/plugin.spec.yaml

Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>

* Update cylance_protect/icon_cylance_protect/actions/blacklist/action.py

Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>

* Update cylance_protect/help.md

Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>

* Update cylance_protect/help.md

Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>

* Update cylance_protect/help.md

Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>

* Description updates from Mike's review

* Remove unused re import

Co-authored-by: Jon Schipp <30870727+jschipp-r7@users.noreply.github.com>
Co-authored-by: Jon Schipp <jonschipp@gmail.com>
Co-authored-by: Mike Rinehart <32079048+mrinehart-r7@users.noreply.github.com>
  • Loading branch information
4 people committed Jun 11, 2020
1 parent 4f28a3a commit eec6034
Show file tree
Hide file tree
Showing 25 changed files with 1,102 additions and 0 deletions.
19 changes: 19 additions & 0 deletions cylance_protect/.CHECKSUM
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"spec": "31100ce5f063d09a75b19007dd1c6a53",
"manifest": "9c6975231ecafd32b792fb7405a27148",
"setup": "c403ba35414f4d61679a7c226c403f76",
"schemas": [
{
"identifier": "blacklist/schema.py",
"hash": "3815b3ec59bf44113390edeb1e46d929"
},
{
"identifier": "get_agent_details/schema.py",
"hash": "af42365d39f72bdd2d48709b28367255"
},
{
"identifier": "connection/schema.py",
"hash": "7e21c6307043d0f723cedd7679449627"
}
]
}
9 changes: 9 additions & 0 deletions cylance_protect/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
unit_test/**/*
unit_test
examples/**/*
examples
tests
tests/**/*
**/*.json
**/*.tar
**/*.gz
26 changes: 26 additions & 0 deletions cylance_protect/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM rapid7/insightconnect-python-3-38-plugin:4
# Refer to the following documentation for available SDK parent images: https://komand.github.io/python/sdk.html#version

LABEL organization=rapid7
LABEL sdk=python

# Add any custom package dependencies here
# NOTE: Add pip packages to requirements.txt

# End package dependencies

# Add source code
WORKDIR /python/src
ADD ./plugin.spec.yaml /plugin.spec.yaml
ADD . /python/src

# Install pip dependencies
RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

# Install plugin
RUN python setup.py build && python setup.py install

# User to run plugin code. The two supported users are: root, nobody
USER nobody

ENTRYPOINT ["/usr/local/bin/icon_cylance_protect"]
53 changes: 53 additions & 0 deletions cylance_protect/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Include other Makefiles for improved functionality
INCLUDE_DIR = ../tools/Makefiles
MAKEFILES := $(wildcard $(INCLUDE_DIR)/*.mk)
# We can't guarantee customers will have the include files
# - prefix to ignore Makefiles when not present
# https://www.gnu.org/software/make/manual/html_node/Include.html
-include $(MAKEFILES)

ifneq ($(MAKEFILES),)
$(info [$(YELLOW)*$(NORMAL)] Use ``make menu`` for available targets)
$(info [$(YELLOW)*$(NORMAL)] Including available Makefiles: $(MAKEFILES))
$(info --)
else
$(warning Makefile includes directory not present: $(INCLUDE_DIR))
endif

VERSION?=$(shell grep '^version: ' plugin.spec.yaml | sed 's/version: //')
NAME?=$(shell grep '^name: ' plugin.spec.yaml | sed 's/name: //')
VENDOR?=$(shell grep '^vendor: ' plugin.spec.yaml | sed 's/vendor: //')
CWD?=$(shell basename $(PWD))
_NAME?=$(shell echo $(NAME) | awk '{ print toupper(substr($$0,1,1)) tolower(substr($$0,2)) }')
PKG=$(VENDOR)-$(NAME)-$(VERSION).tar.gz

# Set default target explicitly. Make's default behavior is the first target in the Makefile.
# We don't want that behavior due to includes which are read first
.DEFAULT_GOAL := default # Make >= v3.80 (make -version)


default: image tarball

tarball:
$(info [$(YELLOW)*$(NORMAL)] Creating plugin tarball)
rm -rf build
rm -rf $(PKG)
tar -cvzf $(PKG) --exclude=$(PKG) --exclude=tests --exclude=run.sh *

image:
$(info [$(YELLOW)*$(NORMAL)] Building plugin image)
docker build --pull -t $(VENDOR)/$(NAME):$(VERSION) .
docker tag $(VENDOR)/$(NAME):$(VERSION) $(VENDOR)/$(NAME):latest

regenerate:
$(info [$(YELLOW)*$(NORMAL)] Regenerating schema from plugin.spec.yaml)
icon-plugin generate python --regenerate

export: image
$(info [$(YELLOW)*$(NORMAL)] Exporting docker image)
@printf "\n ---> Exporting Docker image to ./$(VENDOR)_$(NAME)_$(VERSION).tar\n"
@docker save $(VENDOR)/$(NAME):$(VERSION) | gzip > $(VENDOR)_$(NAME)_$(VERSION).tar

# Make will not run a target if a file of the same name exists unless setting phony targets
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
.PHONY: default tarball image regenerate
34 changes: 34 additions & 0 deletions cylance_protect/bin/icon_cylance_protect
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env python
# GENERATED BY KOMAND SDK - DO NOT EDIT
import insightconnect_plugin_runtime
from icon_cylance_protect import connection, actions, triggers


Name = "Blackberry CylancePROTECT"
Vendor = "rapid7"
Version = "1.0.0"
Description = "Automate detection and response operations using CylancePROTECT"


class ICONCylanceProtect(insightconnect_plugin_runtime.Plugin):
def __init__(self):
super(self.__class__, self).__init__(
name=Name,
vendor=Vendor,
version=Version,
description=Description,
connection=connection.Connection()
)
self.add_action(actions.Blacklist())

self.add_action(actions.GetAgentDetails())


def main():
"""Run plugin"""
cli = insightconnect_plugin_runtime.CLI(ICONCylanceProtect())
cli.run()


if __name__ == "__main__":
main()
Binary file added cylance_protect/extension.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
158 changes: 158 additions & 0 deletions cylance_protect/help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Description

The [BlackBerry CylancePROTECT](https://www.cylance.com/en-us/platform/products/cylance-protect.html) plugin allows you to automate response operations.

# Key Features

* Get agent details
* Blacklist a malicious hash

# Requirements

* CylancePROTECT configured with an Custom Application

# Documentation

## Setup

You must create a Custom Application by following this procedure from the CylancePROTECT console:

1. Go to the Integrations tab on the Settings page
2. Click "Add Application"
3. Provide a name for the integration and choose the permissions related to the actions you want to use
4. Copy and paste the Application ID, Application Secret, and Tenant ID (from the Integrations tab) into the connection

The connection configuration accepts the following parameters:

|Name|Type|Default|Required|Description|Enum|Example|
|----|----|-------|--------|-----------|----|-------|
|application_id|credential_secret_key|None|True|Application ID for CylancePROTECT instance|None|1abc234d-5efa-6789-bcde-0f1abcde23f5|
|application_secret|credential_secret_key|None|True|Generated token that allows access to Cylance Resources|None|1abc234d-5efa-6789-bcde-0f1abcde23f5|
|tenant_id|credential_secret_key|None|True|The unique tenant ID of the tenant that the device belongs to|None|1abc234d-5efa-6789-bcde-0f1abcde23f5|
|url|string|https://protectapi.cylance.com|True|Web API URL|None|https://protectapi.cylance.com|

Example input:

```
{
"application_id": "1abc234d-5efa-6789-bcde-0f1abcde23f5",
"application_secret": "1abc234d-5efa-6789-bcde-0f1abcde23f5",
"tenant_id": "1abc234d-5efa-6789-bcde-0f1abcde23f5",
"url": "https://protectapi.cylance.com"
}
```

## Technical Details

### Actions

#### Blacklist

This action is used to blacklist (quarantine) a hash globally.

##### Input

|Name|Type|Default|Required|Description|Enum|Example|
|----|----|-------|--------|-----------|----|-------|
|blacklist_state|boolean|None|True|True to blacklist hash, false to unblacklist hash|None|True|
|description|string|Hash Blacklisted from InsightConnect|True|Description for why the hash is blacklisted|None|Hash Blacklisted from InsightConnect|
|hash|string|None|True|Create a blacklist item from a SHA256 hash|None|275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f|

Example input:

```
{
"blacklist_state": true,
"description": "Hash Blacklisted from InsightConnect",
"hash": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f"
}
```

##### Output

|Name|Type|Required|Description|
|----|----|--------|-----------|
|success|boolean|True|Return true if blacklist item was created or deleted|

Example output:

```
{
"success": true
}
```

#### Get Agent Details

This action is used to obtain agent information.

##### Input

|Name|Type|Default|Required|Description|Enum|Example|
|----|----|-------|--------|-----------|----|-------|
|agent|string|None|True|Agent to retrieve device information from. Accepts MAC address, hostname, or agent ID|None|cylance-agent-win12|

Example input:

```
{
"agent": "cylance-agent-win12"
}
```

##### Output

|Name|Type|Required|Description|
|----|----|--------|-----------|
|agent|agent|True|Details for an agent|

Example output:

```
{
"agent": {
"id": "1abc234d-5efa-6789-bcde-0f1abcde23f5",
"name": "NA-TESTX-NAM11",
"host_name": "na-testx-nam11",
"os_version": "Microsoft Windows Server 2012 Standard",
"state": "Online",
"agent_version": "2.0.1540",
"policy": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Default"
},
"last_logged_in_user": "NA-TESTX-NAM11\\Administrator",
"update_available": false,
"background_detection": false,
"is_safe": false,
"date_first_registered": "2020-05-28T14:00:50",
"ip_addresses": [
"198.51.100.100"
],
"mac_addresses": [
"00-60-26-26-D5-19"
]
}
}
```

### Triggers

_This plugin does not contain any triggers._

### Custom Output Types

_This plugin does not contain any custom output types._
## Troubleshooting

_This plugin does not contain any troubleshooting information._

# Version History

* 1.0.0 - Initial plugin

# Links

## References

* [BlackBerry CylancePROTECT](https://www.cylance.com)
Binary file added cylance_protect/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions cylance_protect/icon_cylance_protect/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# GENERATED BY KOMAND SDK - DO NOT EDIT
3 changes: 3 additions & 0 deletions cylance_protect/icon_cylance_protect/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GENERATED BY KOMAND SDK - DO NOT EDIT
from .blacklist.action import Blacklist
from .get_agent_details.action import GetAgentDetails
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# GENERATED BY KOMAND SDK - DO NOT EDIT
from .action import Blacklist
38 changes: 38 additions & 0 deletions cylance_protect/icon_cylance_protect/actions/blacklist/action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import insightconnect_plugin_runtime
from .schema import BlacklistInput, BlacklistOutput, Input, Output, Component
from insightconnect_plugin_runtime.exceptions import PluginException
# Custom imports below


class Blacklist(insightconnect_plugin_runtime.Action):

def __init__(self):
super(self.__class__, self).__init__(
name='blacklist',
description=Component.DESCRIPTION,
input=BlacklistInput(),
output=BlacklistOutput())

def run(self, params={}):
sha1_hash = params.get(Input.HASH)
if params.get(Input.BLACKLIST_STATE) is True:
errors = self.connection.client.create_blacklist_item({
"sha256": sha1_hash,
"list_type": "GlobalQuarantine",
"category": "None",
"reason": params.get(Input.DESCRIPTION)
})
else:
errors = self.connection.client.delete_blacklist_item({
"sha256": sha1_hash,
"list_type": "GlobalQuarantine"
})

if len(errors) != 0:
raise PluginException(cause='The response from the CylancePROTECT API was not in the correct format.',
assistance='Contact support for help. See log for more details',
data=errors)

return {
Output.SUCCESS: True
}

0 comments on commit eec6034

Please sign in to comment.