diff --git a/plugins/threatcrowd/.CHECKSUM b/plugins/threatcrowd/.CHECKSUM deleted file mode 100644 index d17c245145..0000000000 --- a/plugins/threatcrowd/.CHECKSUM +++ /dev/null @@ -1,35 +0,0 @@ -{ - "spec": "9921207995aaa22ea93684c7aa90c646", - "manifest": "baf0292d7a4758277caca26988c3c46e", - "setup": "11084a954368da2f00d3036e1579f3a9", - "schemas": [ - { - "identifier": "address/schema.py", - "hash": "7076baf3659c6088bac326921aa472c3" - }, - { - "identifier": "av/schema.py", - "hash": "23f2862a64d3c838e331d07aa1c99532" - }, - { - "identifier": "domain/schema.py", - "hash": "3152eedf927ca16b24dbd07b45334d5c" - }, - { - "identifier": "email/schema.py", - "hash": "8b8b74fc6a32842159b0bdf7f4151435" - }, - { - "identifier": "hash/schema.py", - "hash": "fe1ccde1095bc012e9fcd07448190a82" - }, - { - "identifier": "votes/schema.py", - "hash": "f978922026e2538dfcda22ce390b2832" - }, - { - "identifier": "connection/schema.py", - "hash": "653ae167218c479b1fbf01bb60b44727" - } - ] -} \ No newline at end of file diff --git a/plugins/threatcrowd/.dockerignore b/plugins/threatcrowd/.dockerignore deleted file mode 100755 index 93dc53fb01..0000000000 --- a/plugins/threatcrowd/.dockerignore +++ /dev/null @@ -1,9 +0,0 @@ -unit_test/**/* -unit_test -examples/**/* -examples -tests -tests/**/* -**/*.json -**/*.tar -**/*.gz \ No newline at end of file diff --git a/plugins/threatcrowd/Dockerfile b/plugins/threatcrowd/Dockerfile deleted file mode 100755 index 6382bdd487..0000000000 --- a/plugins/threatcrowd/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM rapid7/insightconnect-python-3-38-plugin:4 -# Refer to the following documentation for available SDK parent images: https://docs.rapid7.com/insightconnect/sdk-guide/#sdk-guide - -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 nobody - -ENTRYPOINT ["/usr/local/bin/icon_threatcrowd"] diff --git a/plugins/threatcrowd/Makefile b/plugins/threatcrowd/Makefile deleted file mode 100644 index cb85f96b6c..0000000000 --- a/plugins/threatcrowd/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# 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 diff --git a/plugins/threatcrowd/bin/icon_threatcrowd b/plugins/threatcrowd/bin/icon_threatcrowd deleted file mode 100755 index 9f8738ed72..0000000000 --- a/plugins/threatcrowd/bin/icon_threatcrowd +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# GENERATED BY KOMAND SDK - DO NOT EDIT -import os -import json -from sys import argv - -Name = "Threat Crowd" -Vendor = "rapid7" -Version = "4.0.0" -Description = "Threat Crowd is an open source search engine for threats. Using the Threat Crowd plugin for Rapid7 InsightConnect, users can search by domain, IP address, email address, and other information to discover threats" - - -def main(): - if 'http' in argv: - if os.environ.get("GUNICORN_CONFIG_FILE"): - with open(os.environ.get("GUNICORN_CONFIG_FILE")) as gf: - gunicorn_cfg = json.load(gf) - if gunicorn_cfg.get("worker_class", "sync") == "gevent": - from gevent import monkey - monkey.patch_all() - elif 'gevent' in argv: - from gevent import monkey - monkey.patch_all() - - import insightconnect_plugin_runtime - from icon_threatcrowd import connection, actions, triggers - - class ICONThreatcrowd(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.Address()) - - self.add_action(actions.Av()) - - self.add_action(actions.Domain()) - - self.add_action(actions.Email()) - - self.add_action(actions.Hash()) - - self.add_action(actions.Votes()) - - - """Run plugin""" - cli = insightconnect_plugin_runtime.CLI(ICONThreatcrowd()) - cli.run() - - -if __name__ == "__main__": - main() diff --git a/plugins/threatcrowd/extension.png b/plugins/threatcrowd/extension.png deleted file mode 100644 index b5d423f31d..0000000000 Binary files a/plugins/threatcrowd/extension.png and /dev/null differ diff --git a/plugins/threatcrowd/help.md b/plugins/threatcrowd/help.md deleted file mode 100644 index 0914916bbe..0000000000 --- a/plugins/threatcrowd/help.md +++ /dev/null @@ -1,393 +0,0 @@ -# Description - -[AlienVault ThreatCrowd](https://www.threatcrowd.org/) is an open source search engine for threats. -Using the Threat Crowd plugin for Rapid7 InsightConnect, users can search by domain, IP address, email address, -and other information to discover and enrich information about threats in real-time. - -# Key Features - -* Gather threat intelligence about MD5 or SHA1 hashes, IP addresses, antivirus software, domain names, and email addresses -* Submit votes for malicious indicators - -# Requirements - -_This plugin does not contain any requirements._ - -# Supported Product Versions - -* Threatcrowd API 2022-11-02 - -# Documentation - -## Setup - -The connection configuration accepts the following parameters: - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|ssl_verification|boolean|True|True|Indicates whether to verify SSL certificate or not|None|True| - -Example input: - -``` -{ - "ssl_verification": true -} -``` - -## Technical Details - -### Actions - -#### Vote - -This action is used to submit votes for malicious entities. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|entity|string|None|True|URL, Email or IP|None|user@example.com| -|vote|boolean|None|True|Vote malicious|None|False| - -Example input: - -``` -{ - "entity": "user@example.com", - "vote": false -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|status|string|True|Status code, 200 is successful| - -Example output: - -``` -{ - "status": "200" -} -``` - -#### Hash Lookup - -This action is used to search a hash string for malicious threats. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|hash|string|None|True|Hash to search - MD5 and SHA1 supported|None|9de5069c5afe602b2ea0a04b66beb2c0| - -Example input: - -``` -{ - "hash": "9de5069c5afe602b2ea0a04b66beb2c0" -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|domains|[]string|False|List of domains| -|found|boolean|True|Whether search returned results| -|hashes|hash|False|List of hashes| -|ips|[]string|False|List of IP addresses| -|permalink|string|False|Permalink URL| -|references|[]string|False|List of references| -|scans|[]string|False|List of scans| - -Example output: - -``` -{ - "domains": [ - "hpservice.homepc.it", - "facebook.controlliamo.com" - ], - "found": true, - "hashes": { - "md5": "31d0e421894004393c48de1769744687", - "sha1": "4f0eb746d81a616fb9bdff058997ef47a4209a76" - }, - "ips": [ - "8.8.8.8" - ], - "permalink": "https://www.threatcrowd.org/malware.php?md5=31d0e421894004393c48de1769744687", - "references": [], - "scans": [ - "Error Scanning File", - "Malware-gen*Win32*Malware-gen", - "Gen*Variant.Symmi.50061", - "W32/Trojan.VSQD-1927", - "BDS/Plugx.266990", - "Gen*Variant.Symmi.50061", - "Gen*Variant.Symmi.50061", - "Win32/Korplug.CF", - "W32/FakeAV.CX", - "Generic11_c.CDQL", - "Trojan.SuspectCRC*Backdoor.Win32.Gulpix", - "Riskware ( 0040eff71 )", - "Trojan.Win32.Generic*Backdoor.Win32.Gulpix.yk", - "Backdoor*Win32/Plugx", - "Gen*Variant.Symmi.50061[ZP]" - ] -} -``` - -#### Email Lookup - -This action is used to search a email for malicious threats. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|email|string|None|True|Email to search|None|user@example.com| - -Example input: - -``` -{ - "email": "user@example.com" -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|domains|[]string|False|List of domains| -|found|boolean|True|Whether search returned results| -|permalink|string|False|Permalink URL| -|references|[]string|False|List of references| - -Example output: - -``` -{ - "domains": [ - "porta-kiln.com" - ], - "found": true, - "permalink": "https://www.threatcrowd.org/email.php?email=user@example.com", - "references": [] -} -``` - -#### Domain Lookup - -This action is used to search a domain for malicious threats. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|domain|string|None|True|Domain to search|None|https://example.com| - -Example input: - -``` -{ - "domain": "https://example.com" -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|domains|[]resolutions|False|List of domains| -|emails|[]string|False|List of emails| -|found|boolean|True|Whether search returned results| -|hashes|[]string|False|List of hashes| -|malicious|string|False|Category| -|permalink|string|False|Permalink URL| -|references|[]string|False|List of references| -|subdomains|[]string|False|List of subdomains| - -Example output: - -``` -{ - "domains": [ - { - "ip_address": "-", - "last_resolved": "2016-02-17" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2017-03-03" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2018-04-30" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2020-07-24" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2019-12-28" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2017-07-13" - } - ], - "emails": [ - "user@example.com" - ], - "found": true, - "hashes": [], - "malicious": "Malicious", - "permalink": "https://www.threatcrowd.org/domain.php?domain=1119.leke.cn", - "references": [], - "subdomains": [] -} - -``` - -#### AntiVirus Lookup - -This action is used to search for known malicious antiviruses. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|antivirus|string|None|True|Antivirus to search|None|plugx| - -Example input: - -``` -{ - "antivirus": "plugx" -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|found|boolean|True|Whether search returned results| -|hashes|[]string|False|List of hashes| -|permalink|string|False|Permalink URL| -|references|[]string|False|List of references| - -Example output: - -``` -{ - "found": true, - "hashes": [ - "31d0e421894004393c48de1769744687", - "5cd3f073caac28f915cf501d00030b31", - "bbd9acdd758ec2316855306e83dba469", - "ef9d8cd06de03bd5f07b01c1cce9761f", - "06bd026c77ce6ab8d85b6ae92bb34034", - "2af64ba808c79dccd2c1d84f010b22d7" - ], - "permalink": "https://www.threatcrowd.org/listMalware.php?antivirus=plugx", - "references": [] -} - -``` - -#### Address Lookup - -This action is used to search an IP for malicious threats. - -##### Input - -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|domain|string|None|True|IP to search|None|198.51.100.1| - -Example input: - -``` -{ - "domain": "198.51.100.1" -} -``` - -##### Output - -|Name|Type|Required|Description| -|----|----|--------|-----------| -|domains|[]domains|False|List of domains| -|found|boolean|True|Whether search returned results| -|hashes|[]string|False|List of hashes| -|malicious|string|False|Category| -|permalink|string|False|Permalink URL| -|references|[]string|False|List of references| -|resolutions|[]string|False|List of resolutions| - -Example output: - -``` -{ - "domains": [ - { - "domain": "example.com", - "last_resolved": "2018-09-03" - }, - { - "domain": "example2.com", - "last_resolved": "2018-07-14" - }, - { - "domain": "example3.com", - "last_resolved": "2020-06-17" - } - ], - "found": true, - "hashes": [], - "malicious": "50/50 chance malicious", - "permalink": "https://www.threatcrowd.org/ip.php?ip=13.33.17.182", - "references": [] -} -``` - -### Triggers - -_This plugin does not contain any triggers._ - -### Custom Output Types - -_This plugin does not contain any custom output types._ - -## Troubleshooting - -All lookup actions return a boolean variable called `found` that contains either `true` or `false` as a value. -This variable can be used in automated decisions to check if ThreatCrowd has information on a host before trying to do something with it. - -# Version History - -* 4.0.0 - Plugin is made Obsolete -* 3.1.0 - Connection: Add SSL Verification boolean field that indicates whether to verify SSL certificate or not | Add unittests -* 3.0.3 - Add PluginException for case 'Too many connections' response from server | Change IP address in api.py file -* 3.0.2 - Add source and license URLs in plugin spec | Set `USER` to `nobody` in Dockerfile -* 3.0.1 - Add Hash input conversion to lowercase in the Hash action to match API requirements -* 3.0.0 - Update to use the `insightconnect-python-3-38-plugin:4` Docker image | Improve error handling | Changed `Exception` to `PluginException` | Update actions to return appropriate JSON | Move test from actions to connection | Update plugin.spec.yaml to include `cloud_ready` | Use input and output constants | Add example input and output | Added "f" strings | Rename `search_hash` input in Hash Lookup action to `hash` -* 2.0.2 - Updated help.md for the Extension Library -* 2.0.1 - New spec and help.md format for the Extension Library -* 2.0.0 - Rename "Antivirus Lookup" to "AntiVirus Lookup" -* 1.0.0 - Fix locking bug where actions hang indefinitely | Update to v2 Python plugin architecture | Support web server mode -* 0.1.1 - SSL bug fix in SDK -* 0.1.0 - Initial plugin - -# Links - -## References - -* [ThreatCrowd](https://www.threatcrowd.org/) -* [ThreatCrowd API](https://github.com/AlienVault-OTX/ApiV2) diff --git a/plugins/threatcrowd/icon.png b/plugins/threatcrowd/icon.png deleted file mode 100644 index 1df6328277..0000000000 Binary files a/plugins/threatcrowd/icon.png and /dev/null differ diff --git a/plugins/threatcrowd/icon_threatcrowd/__init__.py b/plugins/threatcrowd/icon_threatcrowd/__init__.py deleted file mode 100755 index bace8db897..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/__init__.py deleted file mode 100755 index 261e500b66..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .address.action import Address -from .av.action import Av -from .domain.action import Domain -from .email.action import Email -from .hash.action import Hash -from .votes.action import Votes diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/address/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/address/__init__.py deleted file mode 100755 index 3201300f0d..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/address/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Address diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/address/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/address/action.py deleted file mode 100755 index 1e34623ffc..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/address/action.py +++ /dev/null @@ -1,41 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import AddressInput, AddressOutput, Output, Input, Component - -# Custom imports below -import socket -from insightconnect_plugin_runtime.exceptions import PluginException - - -class Address(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="address", description=Component.DESCRIPTION, input=AddressInput(), output=AddressOutput() - ) - - def ip_check(self, address): - try: - socket.inet_aton(address) - return True - except socket.error: - self.logger.error("The IP address is invalid, please provide a valid IPv4 address") - raise PluginException( - cause=f"An invalid IPv4 address was provided: {address}.", - assistance="Please update the action input to include a valid IPv4 address.", - ) - - def run(self, params={}): - self.ip_check(params.get(Input.DOMAIN)) - data = self.connection.client.search_address(params.get(Input.DOMAIN)) - - if not data or int(data["response_code"]) == 0: - self.logger.info("ThreatCrowd API did not return any matches.") - return {Output.FOUND: False} - - return { - Output.DOMAINS: insightconnect_plugin_runtime.helper.clean_list(data["resolutions"]), - Output.HASHES: insightconnect_plugin_runtime.helper.clean_list(data["hashes"]), - Output.MALICIOUS: self.connection.client.verdict(data["votes"]), - Output.PERMALINK: data["permalink"], - Output.REFERENCES: insightconnect_plugin_runtime.helper.clean_list(data["references"]), - Output.FOUND: True, - } diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/address/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/address/schema.py deleted file mode 100755 index f692065d52..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/address/schema.py +++ /dev/null @@ -1,135 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Search an IP for malicious threats" - - -class Input: - DOMAIN = "domain" - - -class Output: - DOMAINS = "domains" - FOUND = "found" - HASHES = "hashes" - MALICIOUS = "malicious" - PERMALINK = "permalink" - REFERENCES = "references" - RESOLUTIONS = "resolutions" - - -class AddressInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domain": { - "type": "string", - "title": "Domain", - "description": "IP to search", - "order": 1 - } - }, - "required": [ - "domain" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class AddressOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domains": { - "type": "array", - "title": "Domains", - "description": "List of domains", - "items": { - "$ref": "#/definitions/domains" - }, - "order": 1 - }, - "found": { - "type": "boolean", - "title": "Found", - "description": "Whether search returned results", - "order": 7 - }, - "hashes": { - "type": "array", - "title": "Hashes", - "description": "List of hashes", - "items": { - "type": "string" - }, - "order": 3 - }, - "malicious": { - "type": "string", - "title": "Malicious", - "description": "Category", - "order": 5 - }, - "permalink": { - "type": "string", - "title": "Permalink", - "description": "Permalink URL", - "order": 6 - }, - "references": { - "type": "array", - "title": "References", - "description": "List of references", - "items": { - "type": "string" - }, - "order": 4 - }, - "resolutions": { - "type": "array", - "title": "Resolutions", - "description": "List of resolutions", - "items": { - "type": "string" - }, - "order": 2 - } - }, - "required": [ - "found" - ], - "definitions": { - "domains": { - "type": "object", - "title": "domains", - "properties": { - "domain": { - "type": "string", - "title": "Domain", - "description": "Domain", - "order": 1 - }, - "last_resolved": { - "type": "string", - "title": "Last Resolved", - "description": "Last resolved", - "order": 2 - } - } - } - } -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/av/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/av/__init__.py deleted file mode 100755 index 4971b2c3e3..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/av/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Av diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/av/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/av/action.py deleted file mode 100755 index 35b54ad64a..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/av/action.py +++ /dev/null @@ -1,24 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import AvInput, AvOutput, Input, Output, Component - -# Custom imports below - - -class Av(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="av", description=Component.DESCRIPTION, input=AvInput(), output=AvOutput() - ) - - def run(self, params={}): - data = self.connection.client.antivirus_lookup(params.get(Input.ANTIVIRUS)) - if not data or int(data["response_code"]) == 0: - self.logger.info("ThreatCrowd API did not return any matches.") - return {Output.FOUND: False} - - return { - Output.HASHES: insightconnect_plugin_runtime.helper.clean_list(data["hashes"]), - Output.PERMALINK: data["permalink"], - Output.REFERENCES: insightconnect_plugin_runtime.helper.clean_list(data["references"]), - Output.FOUND: True, - } diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/av/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/av/schema.py deleted file mode 100755 index 7f11f6ff47..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/av/schema.py +++ /dev/null @@ -1,88 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Search for known malicious antiviruses" - - -class Input: - ANTIVIRUS = "antivirus" - - -class Output: - FOUND = "found" - HASHES = "hashes" - PERMALINK = "permalink" - REFERENCES = "references" - - -class AvInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "antivirus": { - "type": "string", - "title": "Antivirus", - "description": "Antivirus to search", - "order": 1 - } - }, - "required": [ - "antivirus" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class AvOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "found": { - "type": "boolean", - "title": "Found", - "description": "Whether search returned results", - "order": 4 - }, - "hashes": { - "type": "array", - "title": "Hashes", - "description": "List of hashes", - "items": { - "type": "string" - }, - "order": 1 - }, - "permalink": { - "type": "string", - "title": "Permalink", - "description": "Permalink URL", - "order": 3 - }, - "references": { - "type": "array", - "title": "References", - "description": "List of references", - "items": { - "type": "string" - }, - "order": 2 - } - }, - "required": [ - "found" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/domain/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/domain/__init__.py deleted file mode 100755 index 1e47e5985a..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/domain/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Domain diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/domain/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/domain/action.py deleted file mode 100755 index 0895d4a8da..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/domain/action.py +++ /dev/null @@ -1,40 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import DomainInput, DomainOutput, Input, Output, Component - -# Custom imports below - - -class Domain(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="domain", description=Component.DESCRIPTION, input=DomainInput(), output=DomainOutput() - ) - - def run(self, params={}): - data = self.connection.client.search_domain(self._url_check(params.get(Input.DOMAIN))) - - if not data or int(data["response_code"]) == 0: - self.logger.info("Run: ThreatCrowd API did not return any matches.") - return {Output.FOUND: False} - - return { - Output.DOMAINS: insightconnect_plugin_runtime.helper.clean_list(data["resolutions"]), - Output.EMAILS: insightconnect_plugin_runtime.helper.clean_list(data["emails"]), - Output.HASHES: insightconnect_plugin_runtime.helper.clean_list(data["hashes"]), - Output.MALICIOUS: self.connection.client.verdict(data["votes"]), - Output.PERMALINK: data["permalink"], - Output.REFERENCES: insightconnect_plugin_runtime.helper.clean_list(data["references"]), - Output.SUBDOMAINS: insightconnect_plugin_runtime.helper.clean_list(data["subdomains"]), - Output.FOUND: True, - } - - @staticmethod - def _url_check(url): - if url.startswith("http://"): - url = url.replace("http://", "").split("/")[0] - return url - if url.startswith("https://"): - url = url.replace("https://", "").split("/")[0] - return url - url = url.split("/")[0] - return url diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/domain/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/domain/schema.py deleted file mode 100755 index 0e5a57e0d8..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/domain/schema.py +++ /dev/null @@ -1,145 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Search a domain for malicious threats" - - -class Input: - DOMAIN = "domain" - - -class Output: - DOMAINS = "domains" - EMAILS = "emails" - FOUND = "found" - HASHES = "hashes" - MALICIOUS = "malicious" - PERMALINK = "permalink" - REFERENCES = "references" - SUBDOMAINS = "subdomains" - - -class DomainInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domain": { - "type": "string", - "title": "Domain", - "description": "Domain to search", - "order": 1 - } - }, - "required": [ - "domain" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class DomainOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domains": { - "type": "array", - "title": "Domains", - "description": "List of domains", - "items": { - "$ref": "#/definitions/resolutions" - }, - "order": 1 - }, - "emails": { - "type": "array", - "title": "Emails", - "description": "List of emails", - "items": { - "type": "string" - }, - "order": 3 - }, - "found": { - "type": "boolean", - "title": "Found", - "description": "Whether search returned results", - "order": 8 - }, - "hashes": { - "type": "array", - "title": "Hashes", - "description": "List of hashes", - "items": { - "type": "string" - }, - "order": 2 - }, - "malicious": { - "type": "string", - "title": "Malicious", - "description": "Category", - "order": 6 - }, - "permalink": { - "type": "string", - "title": "Permalink", - "description": "Permalink URL", - "order": 7 - }, - "references": { - "type": "array", - "title": "References", - "description": "List of references", - "items": { - "type": "string" - }, - "order": 5 - }, - "subdomains": { - "type": "array", - "title": "Sub Domains", - "description": "List of subdomains", - "items": { - "type": "string" - }, - "order": 4 - } - }, - "required": [ - "found" - ], - "definitions": { - "resolutions": { - "type": "object", - "title": "resolutions", - "properties": { - "ip_address": { - "type": "string", - "title": "IP Address", - "description": "IP address", - "order": 1 - }, - "last_resolved": { - "type": "string", - "title": "Last Resolved", - "description": "Last resolved", - "order": 2 - } - } - } - } -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/email/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/email/__init__.py deleted file mode 100755 index ece9d5af89..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/email/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Email diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/email/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/email/action.py deleted file mode 100755 index 48ed249165..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/email/action.py +++ /dev/null @@ -1,33 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import EmailInput, EmailOutput, Input, Output, Component -from insightconnect_plugin_runtime.exceptions import PluginException - -# Custom imports below -import validators - - -class Email(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="email", description=Component.DESCRIPTION, input=EmailInput(), output=EmailOutput() - ) - - def run(self, params={}): - if not validators.email(params.get(Input.EMAIL)): - self.logger.info("User input was not an email.") - raise PluginException( - cause="A valid e-mail address was not provided.", - assistance="Update this action with valid e-mail input.", - ) - - data = self.connection.client.search_email(params.get(Input.EMAIL)) - if not data or int(data["response_code"]) == 0: - self.logger.info("ThreatCrowd API did not return any matches.") - return {Output.FOUND: False} - - return { - Output.DOMAINS: insightconnect_plugin_runtime.helper.clean_list(data["domains"]), - Output.PERMALINK: data["permalink"], - Output.REFERENCES: insightconnect_plugin_runtime.helper.clean_list(data["references"]), - Output.FOUND: True, - } diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/email/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/email/schema.py deleted file mode 100755 index 79fac8d4a4..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/email/schema.py +++ /dev/null @@ -1,88 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Search a email for malicious threats" - - -class Input: - EMAIL = "email" - - -class Output: - DOMAINS = "domains" - FOUND = "found" - PERMALINK = "permalink" - REFERENCES = "references" - - -class EmailInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "email": { - "type": "string", - "title": "Email", - "description": "Email to search", - "order": 1 - } - }, - "required": [ - "email" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class EmailOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domains": { - "type": "array", - "title": "Domains", - "description": "List of domains", - "items": { - "type": "string" - }, - "order": 1 - }, - "found": { - "type": "boolean", - "title": "Found", - "description": "Whether search returned results", - "order": 4 - }, - "permalink": { - "type": "string", - "title": "Permalink", - "description": "Permalink URL", - "order": 3 - }, - "references": { - "type": "array", - "title": "References", - "description": "List of references", - "items": { - "type": "string" - }, - "order": 2 - } - }, - "required": [ - "found" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/hash/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/hash/__init__.py deleted file mode 100755 index 08c1be9018..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/hash/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Hash diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/hash/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/hash/action.py deleted file mode 100755 index 82678ba7bd..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/hash/action.py +++ /dev/null @@ -1,42 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import HashInput, HashOutput, Input, Output, Component -from insightconnect_plugin_runtime.exceptions import PluginException - -# Custom imports below -import validators - - -class Hash(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="hash", description=Component.DESCRIPTION, input=HashInput(), output=HashOutput() - ) - - @staticmethod - def _is_not_valid_hash(hash): - if validators.md5(hash) or validators.sha1(hash): - return False - - return True - - def run(self, params={}): - if self._is_not_valid_hash(params.get(Input.HASH)): - raise PluginException( - cause="An invalid or unsupported hash type was provided.", assistance="Please enter a MD5 or SHA1 hash." - ) - - data = self.connection.client.search_hash(params.get(Input.HASH).lower()) - - if int(data["response_code"]) == 0: - self.logger.info("ThreatCrowd API did not return any matches.") - return {Output.FOUND: False} - - return { - Output.DOMAINS: insightconnect_plugin_runtime.helper.clean_list(data["domains"]), - Output.HASHES: {"sha1": data["sha1"], "md5": data["md5"]}, - Output.IPS: insightconnect_plugin_runtime.helper.clean_list(data["ips"]), - Output.PERMALINK: data["permalink"], - Output.REFERENCES: insightconnect_plugin_runtime.helper.clean_list(data["references"]), - Output.SCANS: insightconnect_plugin_runtime.helper.clean_list(data["scans"]), - Output.FOUND: True, - } diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/hash/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/hash/schema.py deleted file mode 100755 index d37b2169b0..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/hash/schema.py +++ /dev/null @@ -1,139 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Search a hash string for malicious threats" - - -class Input: - HASH = "hash" - - -class Output: - DOMAINS = "domains" - FOUND = "found" - HASHES = "hashes" - IPS = "ips" - PERMALINK = "permalink" - REFERENCES = "references" - SCANS = "scans" - - -class HashInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "hash": { - "type": "string", - "title": "Search Hash", - "description": "Hash to search - MD5 and SHA1 supported", - "order": 1 - } - }, - "required": [ - "hash" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class HashOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "domains": { - "type": "array", - "title": "Domains", - "description": "List of domains", - "items": { - "type": "string" - }, - "order": 4 - }, - "found": { - "type": "boolean", - "title": "Found", - "description": "Whether search returned results", - "order": 7 - }, - "hashes": { - "$ref": "#/definitions/hash", - "title": "Hashes", - "description": "List of hashes", - "order": 2 - }, - "ips": { - "type": "array", - "title": "IPs", - "description": "List of IP addresses", - "items": { - "type": "string" - }, - "order": 3 - }, - "permalink": { - "type": "string", - "title": "Permalink", - "description": "Permalink URL", - "order": 6 - }, - "references": { - "type": "array", - "title": "References", - "description": "List of references", - "items": { - "type": "string" - }, - "order": 5 - }, - "scans": { - "type": "array", - "title": "Scans", - "description": "List of scans", - "items": { - "type": "string" - }, - "order": 1 - } - }, - "required": [ - "found" - ], - "definitions": { - "hash": { - "type": "object", - "title": "hash", - "properties": { - "md5": { - "type": "string", - "title": "MD5 Hash", - "description": "MD5 hash value", - "order": 1 - }, - "sha1": { - "type": "string", - "title": "SHA1 Hash", - "description": "SHA1 hash value", - "order": 2 - } - }, - "required": [ - "md5", - "sha1" - ] - } - } -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/votes/__init__.py b/plugins/threatcrowd/icon_threatcrowd/actions/votes/__init__.py deleted file mode 100755 index 7119c52ea8..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/votes/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .action import Votes diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/votes/action.py b/plugins/threatcrowd/icon_threatcrowd/actions/votes/action.py deleted file mode 100755 index f18b1dbb5b..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/votes/action.py +++ /dev/null @@ -1,55 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import VotesInput, VotesOutput, Input, Output, Component -from insightconnect_plugin_runtime.exceptions import PluginException - -# Custom imports below -import socket -from urllib.parse import urlparse -import validators - - -class Votes(insightconnect_plugin_runtime.Action): - def __init__(self): - super(self.__class__, self).__init__( - name="votes", description=Component.DESCRIPTION, input=VotesInput(), output=VotesOutput() - ) - - @staticmethod - def url_ip_check(entity): - if not entity.startswith("http://"): - entity = "http://" + entity - - address = urlparse(entity).netloc - try: - socket.gethostbyname(address) - return address - except Exception as e: - raise PluginException( - cause="Failed to cast vote.", - assistance="User input must be either a valid email, URL or IP address.", - data=e, - ) - - def entity_check(self, entity): - # check if entity is email - if validators.email(entity): - return entity - - # check if entity is IP or URL - return self.url_ip_check(entity) - - @staticmethod - def parse_vote(vote): - vote_convert = {True: 1, False: 0} - return vote_convert[vote] - - def run(self, params={}): - vote = self.parse_vote(params.get(Input.VOTE)) - entity = params.get(Input.ENTITY) - data = self.connection.client.vote_malicious(vote, self.entity_check(entity)) - - if not data or int(data.status_code) > 200: - self.logger.error("ThreatCrowd API did not return any matches") - raise PluginException(cause="Vote submission failed for unknown reason.") - - return {Output.STATUS: str(data.status_code)} diff --git a/plugins/threatcrowd/icon_threatcrowd/actions/votes/schema.py b/plugins/threatcrowd/icon_threatcrowd/actions/votes/schema.py deleted file mode 100755 index fd99532547..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/actions/votes/schema.py +++ /dev/null @@ -1,69 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Component: - DESCRIPTION = "Submit votes for malicious entities" - - -class Input: - ENTITY = "entity" - VOTE = "vote" - - -class Output: - STATUS = "status" - - -class VotesInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "entity": { - "type": "string", - "title": "Entitiy", - "description": "URL, Email or IP", - "order": 2 - }, - "vote": { - "type": "boolean", - "title": "Vote", - "description": "Vote malicious", - "order": 1 - } - }, - "required": [ - "entity", - "vote" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) - - -class VotesOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "status": { - "type": "string", - "title": "Status", - "description": "Status code, 200 is successful", - "order": 1 - } - }, - "required": [ - "status" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/connection/__init__.py b/plugins/threatcrowd/icon_threatcrowd/connection/__init__.py deleted file mode 100755 index a515dcf6b0..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/connection/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from .connection import Connection diff --git a/plugins/threatcrowd/icon_threatcrowd/connection/connection.py b/plugins/threatcrowd/icon_threatcrowd/connection/connection.py deleted file mode 100755 index d101815f31..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/connection/connection.py +++ /dev/null @@ -1,32 +0,0 @@ -import insightconnect_plugin_runtime -from .schema import ConnectionSchema, Input - -# Custom imports below -from insightconnect_plugin_runtime.exceptions import ConnectionTestException -from icon_threatcrowd.util.api import ThreadCrowdAPI - - -class Connection(insightconnect_plugin_runtime.Connection): - def __init__(self): - super(self.__class__, self).__init__(input=ConnectionSchema()) - self.client = None - - def connect(self, params={}): - self.ssl_verification = params.get(Input.SSL_VERIFICATION, True) - self.client = ThreadCrowdAPI(self.ssl_verification, self.logger) - - def test(self): - try: - if self.client.health_check(): - return {"success": True} - else: - raise ConnectionTestException( - cause="An unexpected error occurred during the API request.", - assistance="Check that https://threatcrowd.org is reachable or please contact support.", - ) - except Exception: - self.logger.error("An unexpected error occurred during the API request") - raise ConnectionTestException( - cause="An unexpected error occurred during the API request.", - assistance="Check that https://threatcrowd.org is reachable or please contact support.", - ) diff --git a/plugins/threatcrowd/icon_threatcrowd/connection/schema.py b/plugins/threatcrowd/icon_threatcrowd/connection/schema.py deleted file mode 100755 index e2ebafca2f..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/connection/schema.py +++ /dev/null @@ -1,31 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -import insightconnect_plugin_runtime -import json - - -class Input: - SSL_VERIFICATION = "ssl_verification" - - -class ConnectionSchema(insightconnect_plugin_runtime.Input): - schema = json.loads(""" - { - "type": "object", - "title": "Variables", - "properties": { - "ssl_verification": { - "type": "boolean", - "title": "Verify SSL Certificate", - "description": "Indicates whether to verify SSL certificate or not", - "default": true, - "order": 1 - } - }, - "required": [ - "ssl_verification" - ] -} - """) - - def __init__(self): - super(self.__class__, self).__init__(self.schema) diff --git a/plugins/threatcrowd/icon_threatcrowd/triggers/__init__.py b/plugins/threatcrowd/icon_threatcrowd/triggers/__init__.py deleted file mode 100755 index bace8db897..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/triggers/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT diff --git a/plugins/threatcrowd/icon_threatcrowd/util/__init__.py b/plugins/threatcrowd/icon_threatcrowd/util/__init__.py deleted file mode 100755 index bace8db897..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/util/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT diff --git a/plugins/threatcrowd/icon_threatcrowd/util/api.py b/plugins/threatcrowd/icon_threatcrowd/util/api.py deleted file mode 100755 index 41ee19eb64..0000000000 --- a/plugins/threatcrowd/icon_threatcrowd/util/api.py +++ /dev/null @@ -1,83 +0,0 @@ -import json -import time -from logging import Logger - -import requests -from insightconnect_plugin_runtime.exceptions import PluginException - - -class ThreadCrowdAPI: - def __init__(self, ssl_verification: bool = True, logger: Logger = None): - self.ssl_verification = ssl_verification - self.logger = logger - self.url = "https://www.threatcrowd.org/searchApi/v2" - - def health_check(self): - return self._call_api("GET", f"{self.url}/ip/report/?ip=54.192.230.36", full_response=True).status_code == 200 - - def search_address(self, domain): - return self._call_api("GET", f"{self.url}/ip/report/", params={"ip": domain}) - - def antivirus_lookup(self, antivirus): - return self._call_api("GET", f"{self.url}/antivirus/report/", params={"antivirus": antivirus}) - - def search_domain(self, domain): - return self._call_api("GET", f"{self.url}/domain/report/", params={"domain": domain}) - - def search_email(self, email): - return self._call_api("GET", f"{self.url}/email/report/", params={"email": email}) - - def search_hash(self, search_hash): - return self._call_api("GET", f"{self.url}/file/report/", params={"resource": search_hash}) - - def vote_malicious(self, vote, entity): - return self._call_api( - "GET", "https://www.threatcrowd.org/vote.php", params={"vote": vote, "value": entity}, full_response=True - ) - - def _call_api(self, method, url, params=None, json_data=None, full_response: bool = False): # noqa: C901 - response = {"text": ""} - seconds_to_wait = 5 - try: - i = 0 - while i < 10: - response = requests.request(method, url, json=json_data, params=params, verify=self.ssl_verification) - i += 1 - if 200 <= response.status_code < 300 and "Too many connections" in response.text: - self.logger.info(f"Too many connections to ThreatCrowd. Waiting {seconds_to_wait} seconds.") - time.sleep(seconds_to_wait) - else: - break - if response.status_code == 404 or (200 <= response.status_code < 300 and not response.text): - raise PluginException(preset=PluginException.Preset.NOT_FOUND) - if response.status_code == 500: - raise PluginException(preset=PluginException.Preset.SERVER_ERROR) - if response.status_code == 503: - raise PluginException(preset=PluginException.Preset.SERVICE_UNAVAILABLE) - if response.status_code >= 400: - response_data = response.json() - raise PluginException(preset=PluginException.Preset.UNKNOWN, data=response_data.get("message", "")) - - if 200 <= response.status_code < 300: - if "Too many connections" in response.text: - raise PluginException( - cause="ThreatCrowd server return 'too many connections' error. ", - assistance="Please wait and try again.", - ) - if full_response: - return response - - return response.json() - - raise PluginException(preset=PluginException.Preset.UNKNOWN, data=response.text) - except json.decoder.JSONDecodeError as error: - self.logger.info(f"Invalid JSON: {error}") - raise PluginException(preset=PluginException.Preset.INVALID_JSON, data=response.text) - except requests.exceptions.HTTPError as error: - self.logger.info(f"Call to Thread Crowd failed: {error}") - raise PluginException(preset=PluginException.Preset.UNKNOWN, data=response.text) - - @staticmethod - def verdict(vote): - vote_verdict = {1: "Not malicious", 0: "50/50 chance malicious", -1: "Malicious"} - return vote_verdict[vote] diff --git a/plugins/threatcrowd/plugin.spec.yaml b/plugins/threatcrowd/plugin.spec.yaml deleted file mode 100644 index a6ade736be..0000000000 --- a/plugins/threatcrowd/plugin.spec.yaml +++ /dev/null @@ -1,294 +0,0 @@ -plugin_spec_version: v2 -extension: plugin -products: [insightconnect] -name: threatcrowd -title: Threat Crowd -description: Threat Crowd is an open source search engine for threats. Using the Threat Crowd plugin for Rapid7 InsightConnect, users can search by domain, IP address, email address, and other information to discover threats -version: 4.0.0 -vendor: rapid7 -support: rapid7 -supported_versions: ["Threatcrowd API 2022-11-02"] -status: [obsolete] -cloud_ready: true -resources: - source_url: https://github.com/rapid7/insightconnect-plugins/tree/master/plugins/threatcrowd - license_url: https://github.com/rapid7/insightconnect-plugins/blob/master/LICENSE - vendor_url: https://www.threatcrowd.org/ -tags: -- antivirus -- domain -- api -hub_tags: - use_cases: [threat_detection_and_response, data_enrichment] - keywords: [antivirus, domain, api, cloud_enabled] - features: [] -types: - domains: - domain: - title: Domain - type: string - description: Domain - required: false - last_resolved: - title: Last Resolved - type: string - description: Last resolved - required: false - resolutions: - ip_address: - title: IP Address - type: string - description: IP address - required: false - last_resolved: - title: Last Resolved - type: string - description: Last resolved - required: false - hash: - md5: - title: MD5 Hash - description: MD5 hash value - type: string - required: true - sha1: - title: SHA1 Hash - description: SHA1 hash value - type: string - required: true -connection: - ssl_verification: - title: Verify SSL Certificate - description: Indicates whether to verify SSL certificate or not - type: boolean - required: true - default: true - example: true -actions: - domain: - title: Domain Lookup - description: Search a domain for malicious threats - input: - domain: - title: Domain - type: string - description: Domain to search - required: true - example: https://example.com - output: - domains: - title: Domains - description: List of domains - type: '[]resolutions' - required: false - hashes: - title: Hashes - description: List of hashes - type: '[]string' - required: false - emails: - title: Emails - description: List of emails - type: '[]string' - required: false - subdomains: - title: Sub Domains - description: List of subdomains - type: '[]string' - required: false - references: - title: References - description: List of references - type: '[]string' - required: false - malicious: - title: Malicious - description: Category - type: string - required: false - permalink: - title: Permalink - description: Permalink URL - type: string - required: false - found: - title: Found - description: Whether search returned results - type: boolean - required: true - email: - title: Email Lookup - description: Search a email for malicious threats - input: - email: - title: Email - type: string - description: Email to search - required: true - example: user@example.com - output: - domains: - title: Domains - description: List of domains - type: '[]string' - required: false - references: - title: References - description: List of references - type: '[]string' - required: false - permalink: - title: Permalink - description: Permalink URL - type: string - required: false - found: - title: Found - description: Whether search returned results - type: boolean - required: true - address: - title: Address Lookup - description: Search an IP for malicious threats - input: - domain: - title: Domain - type: string - description: IP to search - required: true - example: 198.51.100.1 - output: - domains: - title: Domains - description: List of domains - type: '[]domains' - required: false - resolutions: - title: Resolutions - description: List of resolutions - type: '[]string' - required: false - hashes: - title: Hashes - description: List of hashes - type: '[]string' - required: false - references: - title: References - description: List of references - type: '[]string' - required: false - malicious: - title: Malicious - description: Category - type: string - required: false - permalink: - title: Permalink - description: Permalink URL - type: string - required: false - found: - title: Found - description: Whether search returned results - type: boolean - required: true - av: - title: AntiVirus Lookup - description: Search for known malicious antiviruses - input: - antivirus: - title: Antivirus - type: string - description: Antivirus to search - required: true - example: plugx - output: - hashes: - title: Hashes - description: List of hashes - type: '[]string' - required: false - references: - title: References - description: List of references - type: '[]string' - required: false - permalink: - title: Permalink - description: Permalink URL - type: string - required: false - found: - title: Found - description: Whether search returned results - type: boolean - required: true - hash: - title: Hash Lookup - description: Search a hash string for malicious threats - input: - hash: - title: Search Hash - type: string - description: Hash to search - MD5 and SHA1 supported - required: true - example: 9de5069c5afe602b2ea0a04b66beb2c0 - output: - scans: - title: Scans - description: List of scans - type: '[]string' - required: false - hashes: - title: Hashes - description: List of hashes - type: hash - required: false - ips: - title: IPs - description: List of IP addresses - type: '[]string' - required: false - domains: - title: Domains - description: List of domains - type: '[]string' - required: false - references: - title: References - description: List of references - type: '[]string' - required: false - permalink: - title: Permalink - description: Permalink URL - type: string - required: false - found: - title: Found - description: Whether search returned results - type: boolean - required: true - votes: - title: Vote - description: Submit votes for malicious entities - input: - vote: - title: Vote - description: Vote malicious - type: boolean - required: true - example: false - entity: - title: Entitiy - description: URL, Email or IP - type: string - required: true - example: user@example.com - output: - status: - title: Status - description: Status code, 200 is successful - type: string - required: true diff --git a/plugins/threatcrowd/requirements.txt b/plugins/threatcrowd/requirements.txt deleted file mode 100755 index 381caf976d..0000000000 --- a/plugins/threatcrowd/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -# List third-party dependencies here, separated by newlines. -# All dependencies must be version-pinned, eg. requests==1.2.0 -# See: https://pip.pypa.io/en/stable/user_guide/#requirements-files -validators==0.15.0 -parameterized==0.8.1 \ No newline at end of file diff --git a/plugins/threatcrowd/setup.py b/plugins/threatcrowd/setup.py deleted file mode 100755 index 904d805d9a..0000000000 --- a/plugins/threatcrowd/setup.py +++ /dev/null @@ -1,14 +0,0 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT -from setuptools import setup, find_packages - - -setup(name="threatcrowd-rapid7-plugin", - version="4.0.0", - description="Threat Crowd is an open source search engine for threats. Using the Threat Crowd plugin for Rapid7 InsightConnect, users can search by domain, IP address, email address, and other information to discover threats", - author="rapid7", - author_email="", - url="", - packages=find_packages(), - install_requires=['insightconnect-plugin-runtime'], # Add third-party dependencies to requirements.txt, not here! - scripts=['bin/icon_threatcrowd'] - ) diff --git a/plugins/threatcrowd/unit_test/__init__.py b/plugins/threatcrowd/unit_test/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/threatcrowd/unit_test/mock.py b/plugins/threatcrowd/unit_test/mock.py deleted file mode 100644 index e8a43e8df5..0000000000 --- a/plugins/threatcrowd/unit_test/mock.py +++ /dev/null @@ -1,75 +0,0 @@ -import json -import os -from typing import Callable -from unittest import mock - -import requests -from icon_threatcrowd.connection.schema import Input - -STUB_CONNECTION = {Input.SSL_VERIFICATION: True} - -STUB_RESPONSE_TEXT = "RESPONSE" - - -class MockResponse: - def __init__(self, filename: str, status_code: int, text: str = STUB_RESPONSE_TEXT) -> None: - self.filename = filename - self.status_code = status_code - self.text = text - - def json(self): - with open( - os.path.join(os.path.dirname(os.path.realpath(__file__)), f"responses/{self.filename}.json.resp") - ) as file: - return json.load(file) - - -def mocked_request(side_effect: Callable) -> None: - mock_function = requests - mock_function.request = mock.Mock(side_effect=side_effect) - - -def mock_conditions(url: str, status_code: int) -> MockResponse: - if status_code == 201: - return MockResponse("invalid_json", status_code) - elif status_code == 401: - return MockResponse("empty_response", status_code) - if url == "https://www.threatcrowd.org/searchApi/v2/ip/report/?ip=54.192.230.36": - return MockResponse("empty_response", status_code) - elif url == "https://www.threatcrowd.org/searchApi/v2/ip/report/": - return MockResponse("address", status_code) - elif url == "https://www.threatcrowd.org/searchApi/v2/antivirus/report/": - return MockResponse("av", status_code) - elif url == "https://www.threatcrowd.org/searchApi/v2/domain/report/": - return MockResponse("domain", status_code) - elif url == "https://www.threatcrowd.org/searchApi/v2/email/report/": - return MockResponse("email", status_code) - elif url == "https://www.threatcrowd.org/searchApi/v2/file/report/": - return MockResponse("hash", status_code) - elif url == "https://www.threatcrowd.org/vote.php": - return MockResponse("empty_response", status_code) - raise Exception("Response has been not implemented") - - -def mock_request_200(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 200) - - -def mock_request_201_invalid_json(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 201) - - -def mock_request_401(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 401) - - -def mock_request_404(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 404) - - -def mock_request_500(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 500) - - -def mock_request_503(*args, **kwargs) -> MockResponse: - return mock_conditions(args[1], 503) diff --git a/plugins/threatcrowd/unit_test/responses/address.json.resp b/plugins/threatcrowd/unit_test/responses/address.json.resp deleted file mode 100644 index d64cc4bb71..0000000000 --- a/plugins/threatcrowd/unit_test/responses/address.json.resp +++ /dev/null @@ -1,21 +0,0 @@ -{ - "response_code": 200, - "resolutions": [ - { - "domain": "example.com", - "last_resolved": "2018-09-03" - }, - { - "domain": "example2.com", - "last_resolved": "2018-07-14" - }, - { - "domain": "example3.com", - "last_resolved": "2020-06-17" - } - ], - "hashes": [], - "votes": 0, - "permalink": "https://www.threatcrowd.org/ip.php?ip=13.33.17.182", - "references": [] -} diff --git a/plugins/threatcrowd/unit_test/responses/av.json.resp b/plugins/threatcrowd/unit_test/responses/av.json.resp deleted file mode 100644 index 435e748648..0000000000 --- a/plugins/threatcrowd/unit_test/responses/av.json.resp +++ /dev/null @@ -1,14 +0,0 @@ -{ - "response_code": 200, - "found": true, - "hashes": [ - "31d0e421894004393c48de1769744687", - "5cd3f073caac28f915cf501d00030b31", - "bbd9acdd758ec2316855306e83dba469", - "ef9d8cd06de03bd5f07b01c1cce9761f", - "06bd026c77ce6ab8d85b6ae92bb34034", - "2af64ba808c79dccd2c1d84f010b22d7" - ], - "permalink": "https://www.threatcrowd.org/listMalware.php?antivirus=plugx", - "references": [] -} diff --git a/plugins/threatcrowd/unit_test/responses/domain.json.resp b/plugins/threatcrowd/unit_test/responses/domain.json.resp deleted file mode 100644 index b9c9197640..0000000000 --- a/plugins/threatcrowd/unit_test/responses/domain.json.resp +++ /dev/null @@ -1,38 +0,0 @@ -{ - "response_code": 200, - "resolutions": [ - { - "ip_address": "-", - "last_resolved": "2016-02-17" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2017-03-03" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2018-04-30" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2020-07-24" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2019-12-28" - }, - { - "ip_address": "198.51.100.1", - "last_resolved": "2017-07-13" - } - ], - "emails": [ - "user@example.com" - ], - "found": true, - "hashes": [], - "votes": -1, - "permalink": "https://www.threatcrowd.org/domain.php?domain=1119.leke.cn", - "references": [], - "subdomains": [] -} diff --git a/plugins/threatcrowd/unit_test/responses/email.json.resp b/plugins/threatcrowd/unit_test/responses/email.json.resp deleted file mode 100644 index cb3c1efeae..0000000000 --- a/plugins/threatcrowd/unit_test/responses/email.json.resp +++ /dev/null @@ -1,7 +0,0 @@ -{ - "response_code": 200, - "domains": ["porta-kiln.com"], - "found": true, - "permalink": "https://www.threatcrowd.org/email.php?email=user@example.com", - "references": [] -} diff --git a/plugins/threatcrowd/unit_test/responses/empty_response.json.resp b/plugins/threatcrowd/unit_test/responses/empty_response.json.resp deleted file mode 100644 index 554af76bb2..0000000000 --- a/plugins/threatcrowd/unit_test/responses/empty_response.json.resp +++ /dev/null @@ -1 +0,0 @@ -{"message": "Empty"} diff --git a/plugins/threatcrowd/unit_test/responses/hash.json.resp b/plugins/threatcrowd/unit_test/responses/hash.json.resp deleted file mode 100644 index d676d0c4a9..0000000000 --- a/plugins/threatcrowd/unit_test/responses/hash.json.resp +++ /dev/null @@ -1,32 +0,0 @@ -{ - "response_code": 200, - "domains": [ - "hpservice.homepc.it", - "facebook.controlliamo.com" - ], - "found": true, - "md5": "31d0e421894004393c48de1769744687", - "sha1": "4f0eb746d81a616fb9bdff058997ef47a4209a76", - "ips": [ - "8.8.8.8" - ], - "permalink": "https://www.threatcrowd.org/malware.php?md5=31d0e421894004393c48de1769744687", - "references": [], - "scans": [ - "Error Scanning File", - "Malware-gen*Win32*Malware-gen", - "Gen*Variant.Symmi.50061", - "W32/Trojan.VSQD-1927", - "BDS/Plugx.266990", - "Gen*Variant.Symmi.50061", - "Gen*Variant.Symmi.50061", - "Win32/Korplug.CF", - "W32/FakeAV.CX", - "Generic11_c.CDQL", - "Trojan.SuspectCRC*Backdoor.Win32.Gulpix", - "Riskware ( 0040eff71 )", - "Trojan.Win32.Generic*Backdoor.Win32.Gulpix.yk", - "Backdoor*Win32/Plugx", - "Gen*Variant.Symmi.50061[ZP]" - ] -} diff --git a/plugins/threatcrowd/unit_test/responses/invalid_json.json.resp b/plugins/threatcrowd/unit_test/responses/invalid_json.json.resp deleted file mode 100644 index 8ad0dfd4a7..0000000000 --- a/plugins/threatcrowd/unit_test/responses/invalid_json.json.resp +++ /dev/null @@ -1 +0,0 @@ -INVALID_JSON diff --git a/plugins/threatcrowd/unit_test/test_address.py b/plugins/threatcrowd/unit_test/test_address.py deleted file mode 100644 index f23afcfeda..0000000000 --- a/plugins/threatcrowd/unit_test/test_address.py +++ /dev/null @@ -1,77 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase, mock -from unittest.mock import Mock - -from icon_threatcrowd.actions.address import Address -from icon_threatcrowd.actions.address.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestAddress(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Address() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.DOMAIN: "198.51.100.1"} - - @mock.patch("icon_threatcrowd.actions.address.Address.ip_check") - def test_address_ok(self, mocked_ip_check: Mock) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = { - "domains": [ - {"domain": "example.com", "last_resolved": "2018-09-03"}, - {"domain": "example2.com", "last_resolved": "2018-07-14"}, - {"domain": "example3.com", "last_resolved": "2020-06-17"}, - ], - "found": True, - "hashes": [], - "malicious": "50/50 chance malicious", - "permalink": "https://www.threatcrowd.org/ip.php?ip=13.33.17.182", - "references": [], - } - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, PluginException.causes[PluginException.Preset.INVALID_JSON]), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - @mock.patch("icon_threatcrowd.actions.address.Address.ip_check") - def test_address_exception(self, mock_request: Callable, exception: str, mocked_ip_check: Mock) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - ) diff --git a/plugins/threatcrowd/unit_test/test_av.py b/plugins/threatcrowd/unit_test/test_av.py deleted file mode 100644 index ccfc5c553e..0000000000 --- a/plugins/threatcrowd/unit_test/test_av.py +++ /dev/null @@ -1,75 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.actions.av import Av -from icon_threatcrowd.actions.av.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestAv(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Av() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.ANTIVIRUS: "plugx"} - - def test_av_ok(self) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = { - "found": True, - "hashes": [ - "31d0e421894004393c48de1769744687", - "5cd3f073caac28f915cf501d00030b31", - "bbd9acdd758ec2316855306e83dba469", - "ef9d8cd06de03bd5f07b01c1cce9761f", - "06bd026c77ce6ab8d85b6ae92bb34034", - "2af64ba808c79dccd2c1d84f010b22d7", - ], - "permalink": "https://www.threatcrowd.org/listMalware.php?antivirus=plugx", - "references": [], - } - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, PluginException.causes[PluginException.Preset.INVALID_JSON]), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - def test_address_exception(self, mock_request: Callable, exception: str) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - ) diff --git a/plugins/threatcrowd/unit_test/test_connection.py b/plugins/threatcrowd/unit_test/test_connection.py deleted file mode 100644 index a8f64b4a57..0000000000 --- a/plugins/threatcrowd/unit_test/test_connection.py +++ /dev/null @@ -1,46 +0,0 @@ -import os -import sys - -sys.path.append(os.path.abspath("../")) -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.connection.connection import Connection -from insightconnect_plugin_runtime.exceptions import ConnectionTestException -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestConnection(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - def test_connection_ok(self): - mocked_request(mock_request_200) - response = self.connection.test() - expected_response = {"success": True} - self.assertEqual(response, expected_response) - - @parameterized.expand( - [(mock_request_401,), (mock_request_404,), (mock_request_500,), (mock_request_503,)], - ) - def test_connection_exception(self, mock_request: Callable) -> None: - mocked_request(mock_request) - with self.assertRaises(ConnectionTestException) as context: - self.connection.test() - self.assertEqual( - context.exception.cause, - "An unexpected error occurred during the API request.", - ) diff --git a/plugins/threatcrowd/unit_test/test_domain.py b/plugins/threatcrowd/unit_test/test_domain.py deleted file mode 100644 index 8cd26396fb..0000000000 --- a/plugins/threatcrowd/unit_test/test_domain.py +++ /dev/null @@ -1,79 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.actions.domain import Domain -from icon_threatcrowd.actions.domain.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestDomain(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Domain() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.DOMAIN: "https://example.com"} - - def test_domain_ok(self) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = { - "domains": [ - {"ip_address": "-", "last_resolved": "2016-02-17"}, - {"ip_address": "198.51.100.1", "last_resolved": "2017-03-03"}, - {"ip_address": "198.51.100.1", "last_resolved": "2018-04-30"}, - {"ip_address": "198.51.100.1", "last_resolved": "2020-07-24"}, - {"ip_address": "198.51.100.1", "last_resolved": "2019-12-28"}, - {"ip_address": "198.51.100.1", "last_resolved": "2017-07-13"}, - ], - "emails": ["user@example.com"], - "found": True, - "hashes": [], - "malicious": "Malicious", - "permalink": "https://www.threatcrowd.org/domain.php?domain=1119.leke.cn", - "references": [], - "subdomains": [], - } - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, PluginException.causes[PluginException.Preset.INVALID_JSON]), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - def test_domain_exception(self, mock_request: Callable, exception: str) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - ) diff --git a/plugins/threatcrowd/unit_test/test_email.py b/plugins/threatcrowd/unit_test/test_email.py deleted file mode 100644 index 1fa9fd8f0e..0000000000 --- a/plugins/threatcrowd/unit_test/test_email.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.actions.email import Email -from icon_threatcrowd.actions.email.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestEmail(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Email() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.EMAIL: "user@example.com"} - - def test_email_ok(self) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = { - "domains": ["porta-kiln.com"], - "found": True, - "permalink": "https://www.threatcrowd.org/email.php?email=user@example.com", - "references": [], - } - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, PluginException.causes[PluginException.Preset.INVALID_JSON]), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - def test_email_exception(self, mock_request: Callable, exception: str) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - ) diff --git a/plugins/threatcrowd/unit_test/test_hash.py b/plugins/threatcrowd/unit_test/test_hash.py deleted file mode 100644 index 5a4b5c7d95..0000000000 --- a/plugins/threatcrowd/unit_test/test_hash.py +++ /dev/null @@ -1,87 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.actions.hash import Hash -from icon_threatcrowd.actions.hash.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestHash(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Hash() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.HASH: "9de5069c5afe602b2ea0a04b66beb2c0"} - - def test_hash_ok(self) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = { - "domains": ["hpservice.homepc.it", "facebook.controlliamo.com"], - "found": True, - "hashes": {"md5": "31d0e421894004393c48de1769744687", "sha1": "4f0eb746d81a616fb9bdff058997ef47a4209a76"}, - "ips": ["8.8.8.8"], - "permalink": "https://www.threatcrowd.org/malware.php?md5=31d0e421894004393c48de1769744687", - "references": [], - "scans": [ - "Error Scanning File", - "Malware-gen*Win32*Malware-gen", - "Gen*Variant.Symmi.50061", - "W32/Trojan.VSQD-1927", - "BDS/Plugx.266990", - "Gen*Variant.Symmi.50061", - "Gen*Variant.Symmi.50061", - "Win32/Korplug.CF", - "W32/FakeAV.CX", - "Generic11_c.CDQL", - "Trojan.SuspectCRC*Backdoor.Win32.Gulpix", - "Riskware ( 0040eff71 )", - "Trojan.Win32.Generic*Backdoor.Win32.Gulpix.yk", - "Backdoor*Win32/Plugx", - "Gen*Variant.Symmi.50061[ZP]", - ], - } - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, PluginException.causes[PluginException.Preset.INVALID_JSON]), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - def test_hash_exception(self, mock_request: Callable, exception: str) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - ) diff --git a/plugins/threatcrowd/unit_test/test_votes.py b/plugins/threatcrowd/unit_test/test_votes.py deleted file mode 100644 index a9c3dda8ae..0000000000 --- a/plugins/threatcrowd/unit_test/test_votes.py +++ /dev/null @@ -1,63 +0,0 @@ -import os -import sys - -from insightconnect_plugin_runtime.exceptions import PluginException - -sys.path.append(os.path.abspath("../")) - -import logging -from typing import Callable -from unittest import TestCase - -from icon_threatcrowd.actions.votes import Votes -from icon_threatcrowd.actions.votes.schema import Input -from icon_threatcrowd.connection.connection import Connection -from parameterized import parameterized - -from unit_test.mock import ( - STUB_CONNECTION, - mock_request_200, - mock_request_201_invalid_json, - mock_request_401, - mock_request_404, - mock_request_500, - mock_request_503, - mocked_request, -) - - -class TestVotes(TestCase): - def setUp(self) -> None: - self.connection = Connection() - self.connection.logger = logging.getLogger("connection logger") - self.connection.connect(STUB_CONNECTION) - - self.action = Votes() - self.action.connection = self.connection - self.action.logger = logging.getLogger("action logger") - - self.payload = {Input.ENTITY: "user@example.com", Input.VOTE: False} - - def test_votes_ok(self) -> None: - mocked_request(mock_request_200) - response = self.action.run(self.payload) - expected_response = {"status": "200"} - self.assertEqual(expected_response, response) - - @parameterized.expand( - [ - (mock_request_201_invalid_json, "Vote submission failed for unknown reason."), - (mock_request_401, PluginException.causes[PluginException.Preset.UNKNOWN]), - (mock_request_404, PluginException.causes[PluginException.Preset.NOT_FOUND]), - (mock_request_500, PluginException.causes[PluginException.Preset.SERVER_ERROR]), - (mock_request_503, PluginException.causes[PluginException.Preset.SERVICE_UNAVAILABLE]), - ], - ) - def test_votes_exception(self, mock_request: Callable, exception: str) -> None: - mocked_request(mock_request) - with self.assertRaises(PluginException) as context: - self.action.run(self.payload) - self.assertEqual( - context.exception.cause, - exception, - )