diff --git a/plugins/velociraptor_legacy/Dockerfile b/plugins/velociraptor_legacy/Dockerfile new file mode 100644 index 0000000000..5a5e31731f --- /dev/null +++ b/plugins/velociraptor_legacy/Dockerfile @@ -0,0 +1,20 @@ +FROM rapid7/insightconnect-python-3-38-plugin:5 + +LABEL organization=jbauvinet +LABEL sdk=python + +WORKDIR /python/src + +ADD ./plugin.spec.yaml /plugin.spec.yaml +ADD ./requirements.txt /python/src/requirements.txt + +RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + +ADD . /python/src + +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_velociraptor_legacy"] diff --git a/plugins/velociraptor_legacy/Makefile b/plugins/velociraptor_legacy/Makefile new file mode 100644 index 0000000000..cdbcdb1721 --- /dev/null +++ b/plugins/velociraptor_legacy/Makefile @@ -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)] Refreshing schema from plugin.spec.yaml) + insight-plugin refresh + +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/velociraptor_legacy/bin/icon_velociraptor_legacy b/plugins/velociraptor_legacy/bin/icon_velociraptor_legacy new file mode 100644 index 0000000000..99664fa289 --- /dev/null +++ b/plugins/velociraptor_legacy/bin/icon_velociraptor_legacy @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +import os +import json +from sys import argv + +Name = "Velociraptor Legacy" +Vendor = "jbauvinet" +Version = "1.0.0" +Description = "Velociraptor is a unique, advanced open-source endpoint monitoring, digital forensic and cyber response platform. It provides you with the ability to more effectively respond to a wide range of digital forensic and cyber incident response investigations and data breaches" + + +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_velociraptor_legacy import connection, actions, triggers, tasks + + class ICONVelociraptorLegacy(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.Run()) + + + """Run plugin""" + cli = insightconnect_plugin_runtime.CLI(ICONVelociraptorLegacy()) + cli.run() + + +if __name__ == "__main__": + main() diff --git a/plugins/velociraptor_legacy/extension.png b/plugins/velociraptor_legacy/extension.png new file mode 100644 index 0000000000..84bb0cdb98 Binary files /dev/null and b/plugins/velociraptor_legacy/extension.png differ diff --git a/plugins/velociraptor_legacy/help.md b/plugins/velociraptor_legacy/help.md new file mode 100644 index 0000000000..6a54f7a287 --- /dev/null +++ b/plugins/velociraptor_legacy/help.md @@ -0,0 +1,122 @@ +# Description + +Velociraptor is a unique, advanced open-source endpoint monitoring, digital forensic and cyber response platform. It provides you with the ability to more effectively respond to a wide range of digital forensic and cyber incident response investigations and data breaches + +# Key Features + +* dfir + +# Requirements + +* Velociraptor API Conf(velociraptor --config velociraptor.config.yaml config api_client --name rapid7 --role +administrator api.config.yaml) + +# Supported Product Versions + +* 1.0.0 + +# Documentation + +## Setup + +The connection configuration accepts the following parameters: + +|Name|Type|Default|Required|Description|Enum|Example| +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | +|api_connection_string|string|None|True|Velociraptor API Connection Address|None|x.x.x.x:8001| +|ca_certificate|credential_secret_key|None|True|A base64 encoded CA_Certificate Key|None|{'privateKey': 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ=='}| +|client_cert|credential_secret_key|None|True|A base64 encoded Client_Cert Key|None|{'privateKey': 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ=='}| +|client_private_key|credential_secret_key|None|True|A base64 encoded Client_Private Key|None|{'privateKey': 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ=='}| +|username|string|None|True|User to run command as|None|rapid7| + +Example input: + +``` +{ + "api_connection_string": "x.x.x.x:8001", + "ca_certificate": { + "privateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==" + }, + "client_cert": { + "privateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==" + }, + "client_private_key": { + "privateKey": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==" + }, + "username": "rapid7" +} +``` + +## Technical Details + +### Actions + + +#### Run Velociraptor Command + +Run Velociraptor command + +##### Input + +|Name|Type|Default|Required|Description|Enum|Example| +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | +|command|string|None|True|Command to execute on Velociraptor host|None|SELECT * FROM host()| + +Example input: + +``` +{ + "command": "SELECT * FROM host()" +} +``` + +##### Output + +|Name|Type|Required|Description|Example| +| :--- | :--- | :--- | :--- | :--- | +|results|results|True|Results|None| + +Example output: + +``` +{ + "results": { + "LOGS_LIST": [ + {} + ] + } +} +``` +### Triggers + +*This plugin does not contain any triggers.* +### Tasks + +*This plugin does not contain any tasks.* + +### Custom Types + +**results** + +|Name|Type|Default|Required|Description|Example| +| :--- | :--- | :--- | :--- | :--- | :--- | +|LOGS_LIST|[]object|None|None|Logs List|None| + + +## Troubleshooting + +*There is no troubleshooting for this plugin.* + +# Version History + +* 1.0.0 - Initial plugin + +# Links + +* [Velociraptor Product Page](https://docs.velociraptor.app) +* [Base64 Encode/Decode Page](https://www.base64encode.org/) + +## References + +* [Velociraptor Product Page](https://docs.velociraptor.app) +* [Base64 Encode/Decode Page](https://www.base64encode.org/) diff --git a/plugins/velociraptor_legacy/icon.png b/plugins/velociraptor_legacy/icon.png new file mode 100644 index 0000000000..f1c022030f Binary files /dev/null and b/plugins/velociraptor_legacy/icon.png differ diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/__init__.py new file mode 100644 index 0000000000..797e426edf --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/__init__.py @@ -0,0 +1 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/__init__.py new file mode 100644 index 0000000000..f3bd269977 --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/__init__.py @@ -0,0 +1,4 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + +from .run.action import Run + diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/__init__.py new file mode 100644 index 0000000000..598a34c70c --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/__init__.py @@ -0,0 +1,2 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +from .action import Run diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/action.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/action.py new file mode 100644 index 0000000000..a2a9e4c585 --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/action.py @@ -0,0 +1,85 @@ +import json +import paramiko +import base64 +import grpc +import io +import time +from pyvelociraptor import api_pb2 +from pyvelociraptor import api_pb2_grpc +import insightconnect_plugin_runtime +from .schema import RunInput, RunOutput, Input, Output, Component +# Custom imports below + + +class Run(insightconnect_plugin_runtime.Action): + + def __init__(self): + super(self.__class__, self).__init__( + name="run", + description=Component.DESCRIPTION, + input=RunInput(), + output=RunOutput()) + + def run(self, params={}): + # START INPUT BINDING - DO NOT REMOVE - ANY INPUTS BELOW WILL UPDATE WITH YOUR PLUGIN SPEC AFTER REGENERATION + # END INPUT BINDING - DO NOT REMOVE + # TODO - If input bindings for connection can be done check to same if it you can do the same here + """Runs a VQL query against the Velociraptor server. + + Args: + config: A dictionary containing the configuration parameters for the Velociraptor server. + query: The VQL query to run. + + Returns: + A tuple containing the query, the response, and the query execution logs. + """ + results = {} + try: + # Fill in the SSL params from the api_client config file. You can get such a file: + # velociraptor --config server.config.yaml config api_client > api_client.conf.yaml + api_connection_string = self.connection.api_connection_string + root_certificates_decoded = self.connection.root_certificates_decoded + private_key_decoded = self.connection.private_key_decoded + certificate_chain_decoded = self.connection.certificate_chain_decoded + query = params.get(Input.COMMAND) + creds = grpc.ssl_channel_credentials( + root_certificates = root_certificates_decoded, + private_key = private_key_decoded, + certificate_chain = certificate_chain_decoded) + # This option is required to connect to the grpc server by IP - we + # use self signed certs. + options = (('grpc.ssl_target_name_override', "VelociraptorServer",),) + # The first step is to open a gRPC channel to the server.. + with grpc.secure_channel(api_connection_string, + creds, options) as channel: + stub = api_pb2_grpc.APIStub(channel) + # The request consists of one or more VQL queries. Note that you can collect artifacts by simply naming them using the + # "Artifact" plugin. + request = api_pb2.VQLCollectorArgs( + max_wait=1, + max_row=100, + Query=[api_pb2.VQLRequest( + Name="ICON Plugin Request", + VQL=query, + )], + ) + # This will block as responses are streamed from the + # server. If the query is an event query we will run this loop + # forever. + logs_list = [] + for response in stub.Query(request): + if response.Response: + package = json.loads(response.Response) + logs_list.append(package) + + elif response.log: + # Query execution logs are sent in their own messages. + package = time.ctime(response.timestamp / 1000000), response.log + self.logger.info("Command Sent") + results["logs_list"] = logs_list[0] + return {Output.RESULTS: results} + except grpc.RpcError as e: + self.logger.info("Error: ",e) + results["logs_list"] = e + return {Output.RESULTS: results} + diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/schema.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/schema.py new file mode 100644 index 0000000000..62aa3c09fe --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/actions/run/schema.py @@ -0,0 +1,78 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +import insightconnect_plugin_runtime +import json + + +class Component: + DESCRIPTION = "Run Velociraptor command" + + +class Input: + COMMAND = "command" + + +class Output: + RESULTS = "results" + + +class RunInput(insightconnect_plugin_runtime.Input): + schema = json.loads(r""" + { + "type": "object", + "title": "Variables", + "properties": { + "command": { + "type": "string", + "description": "Command to execute on Velociraptor host", + "order": 1 + } + }, + "required": [ + "command" + ], + "definitions": {} +} + """) + + def __init__(self): + super(self.__class__, self).__init__(self.schema) + + +class RunOutput(insightconnect_plugin_runtime.Output): + schema = json.loads(r""" + { + "type": "object", + "title": "Variables", + "properties": { + "results": { + "$ref": "#/definitions/results", + "title": "Results", + "description": "Results", + "order": 1 + } + }, + "required": [ + "results" + ], + "definitions": { + "results": { + "type": "object", + "title": "results", + "properties": { + "logs_list": { + "type": "array", + "title": "LOGS_LIST", + "description": "Logs List", + "items": { + "type": "object" + }, + "order": 1 + } + } + } + } +} + """) + + def __init__(self): + super(self.__class__, self).__init__(self.schema) diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/__init__.py new file mode 100644 index 0000000000..c78d3356be --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/__init__.py @@ -0,0 +1,2 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +from .connection import Connection diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/connection.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/connection.py new file mode 100644 index 0000000000..7fb063d436 --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/connection.py @@ -0,0 +1,90 @@ +import json +import paramiko +import base64 +import grpc +import io +import time +from pyvelociraptor import api_pb2 +from pyvelociraptor import api_pb2_grpc +import insightconnect_plugin_runtime +from .schema import ConnectionSchema, Input +# Custom imports below + + +class Connection(insightconnect_plugin_runtime.Connection): + + def __init__(self): + super(self.__class__, self).__init__(input=ConnectionSchema()) + + def connect(self, params): + # START INPUT BINDING - DO NOT REMOVE - ANY INPUTS BELOW WILL UPDATE WITH YOUR PLUGIN SPEC AFTER REGENERATION + # TODO: generate bound input variables for the user, to help handhold the user + # TODO: ex. self.api_key = params.get(Input.API_KEY) + # END INPUT BINDING - DO NOT REMOVE + self.logger.info("Connect: Connecting...") + """Runs a VQL query against the Velociraptor server. + + Args: + config: A dictionary containing the configuration parameters for the Velociraptor server. + query: The VQL query to run. + + Returns: + A tuple containing the query, the response, and the query execution logs. + """ + + try: + # Fill in the SSL params from the api_client config file. You can get such a file: + # velociraptor --config server.config.yaml config api_client > api_client.conf.yaml + api_connection_string = self.parameters["api_connection_string"] + root_certificates_decoded = base64.b64decode(self.parameters["ca_certificate"]["secretKey"]) + private_key_decoded = base64.b64decode(self.parameters["client_private_key"]["secretKey"]) + certificate_chain_decoded = base64.b64decode(self.parameters["client_cert"]["secretKey"]) + query = "SELECT * FROM info()" + creds = grpc.ssl_channel_credentials( + root_certificates = root_certificates_decoded, + private_key = private_key_decoded, + certificate_chain = certificate_chain_decoded) + # This option is required to connect to the grpc server by IP - we + # use self signed certs. + options = (('grpc.ssl_target_name_override', "VelociraptorServer",),) + # The first step is to open a gRPC channel to the server.. + with grpc.secure_channel(api_connection_string, + creds, options) as channel: + stub = api_pb2_grpc.APIStub(channel) + + # The request consists of one or more VQL queries. Note that + # you can collect artifacts by simply naming them using the + # "Artifact" plugin. + request = api_pb2.VQLCollectorArgs( + max_wait=1, + max_row=100, + Query=[api_pb2.VQLRequest( + Name="ICON Plugin Request", + VQL=query, + )], + ) + # This will block as responses are streamed from the + # server. If the query is an event query we will run this loop + # forever. + logs_list = [] + for response in stub.Query(request): + if response.Response: + package = json.loads(response.Response) + logs_list.append(package) + + elif response.log: + # Query execution logs are sent in their own messages. + package = time.ctime(response.timestamp / 1000000), response.log + self.logger.info("Connection Successful") + self.api_connection_string = self.parameters["api_connection_string"] + self.root_certificates_decoded = base64.b64decode(self.parameters["ca_certificate"]["secretKey"]) + self.private_key_decoded = base64.b64decode(self.parameters["client_private_key"]["secretKey"]) + self.certificate_chain_decoded = base64.b64decode(self.parameters["client_cert"]["secretKey"]) + self.username = self.parameters["username"] + except grpc.RpcError as e: + self.logger.info("Error: ",e) + self.api_connection_string = self.parameters["api_connection_string"] + self.root_certificates_decoded = base64.b64decode(self.parameters["ca_certificate"]["secretKey"]) + self.private_key_decoded = base64.b64decode(self.parameters["client_private_key"]["secretKey"]) + self.certificate_chain_decoded = base64.b64decode(self.parameters["client_cert"]["secretKey"]) + self.username = self.parameters["username"] diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/schema.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/schema.py new file mode 100644 index 0000000000..284dca21b6 --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/connection/schema.py @@ -0,0 +1,77 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +import insightconnect_plugin_runtime +import json + + +class Input: + API_CONNECTION_STRING = "api_connection_string" + CA_CERTIFICATE = "ca_certificate" + CLIENT_CERT = "client_cert" + CLIENT_PRIVATE_KEY = "client_private_key" + USERNAME = "username" + + +class ConnectionSchema(insightconnect_plugin_runtime.Input): + schema = json.loads(r""" + { + "type": "object", + "title": "Variables", + "properties": { + "api_connection_string": { + "type": "string", + "description": "Velociraptor API Connection Address", + "order": 2 + }, + "ca_certificate": { + "$ref": "#/definitions/credential_secret_key", + "description": "A base64 encoded CA_Certificate Key", + "order": 3 + }, + "client_cert": { + "$ref": "#/definitions/credential_secret_key", + "description": "A base64 encoded Client_Cert Key", + "order": 4 + }, + "client_private_key": { + "$ref": "#/definitions/credential_secret_key", + "description": "A base64 encoded Client_Private Key", + "order": 5 + }, + "username": { + "type": "string", + "description": "User to run command as", + "order": 1 + } + }, + "required": [ + "api_connection_string", + "ca_certificate", + "client_cert", + "client_private_key", + "username" + ], + "definitions": { + "credential_secret_key": { + "id": "credential_secret_key", + "type": "object", + "title": "Credential: Secret Key", + "description": "A shared secret key", + "required": [ + "secretKey" + ], + "properties": { + "secretKey": { + "type": "string", + "title": "Secret Key", + "description": "The shared secret key", + "format": "password", + "displayType": "password" + } + } + } + } +} + """) + + def __init__(self): + super(self.__class__, self).__init__(self.schema) diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/tasks/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/tasks/__init__.py new file mode 100644 index 0000000000..7020c9a4ad --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/tasks/__init__.py @@ -0,0 +1,2 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/triggers/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/triggers/__init__.py new file mode 100644 index 0000000000..7020c9a4ad --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/triggers/__init__.py @@ -0,0 +1,2 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + diff --git a/plugins/velociraptor_legacy/icon_velociraptor_legacy/util/__init__.py b/plugins/velociraptor_legacy/icon_velociraptor_legacy/util/__init__.py new file mode 100644 index 0000000000..797e426edf --- /dev/null +++ b/plugins/velociraptor_legacy/icon_velociraptor_legacy/util/__init__.py @@ -0,0 +1 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT diff --git a/plugins/velociraptor_legacy/plugin.spec.yaml b/plugins/velociraptor_legacy/plugin.spec.yaml new file mode 100644 index 0000000000..52bfac3fc1 --- /dev/null +++ b/plugins/velociraptor_legacy/plugin.spec.yaml @@ -0,0 +1,84 @@ +plugin_spec_version: v2 +extension: plugin +products: [insightconnect] +name: velociraptor_legacy +title: Velociraptor Legacy +description: Velociraptor is a unique, advanced open-source endpoint monitoring, digital + forensic and cyber response platform. It provides you with the ability to more effectively + respond to a wide range of digital forensic and cyber incident response investigations + and data breaches +version: 1.0.0 +version_history: ['1.0.0 - Initial plugin'] +requirements: ['Velociraptor API Conf(velociraptor --config velociraptor.config.yaml + config api_client --name rapid7 --role administrator api.config.yaml)'] +key_features: ['dfir'] +supported_versions: ['1.0.0'] +references: ['[Velociraptor Product Page](https://docs.velociraptor.app)', '[Base64 + Encode/Decode Page](https://www.base64encode.org/)'] +Links: ['#https://docs.velociraptor.app'] +vendor: jbauvinet +support: community +status: [] +enable_cache: true +resources: + vendor_url: https://docs.velociraptor.app/ + license_url: https://github.com/rapid7/insightconnect-plugins/blob/master/LICENSE +tags: +- dfir +- velociraptor +hub_tags: + use_cases: ['threat_detection_and_response'] + keywords: ['dfir'] + features: [] +sdk: + type: full + version: 5 + user: nobody +types: + results: + logs_list: + title: LOGS_LIST + description: Logs List + type: '[]object' +connection: + username: + type: string + description: User to run command as + required: true + example: rapid7 + api_connection_string: + type: string + description: Velociraptor API Connection Address + required: true + example: x.x.x.x:8001 + ca_certificate: + type: credential_secret_key + description: A base64 encoded CA_Certificate Key + required: true + example: {privateKey: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==} + client_cert: + type: credential_secret_key + description: A base64 encoded Client_Cert Key + required: true + example: {privateKey: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==} + client_private_key: + type: credential_secret_key + description: A base64 encoded Client_Private Key + required: true + example: {privateKey: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBakdub1V0ZlBIcXZYM1BJVTZOOUZLbXdRM1psK05vYVdiNHlNTGh1ZGtkRUJKM0F1CitJOFFkbHFES0JtNjU2VWVPQ2gzci9pOWUwVUxLeGtYREZmS21jM3AyV3YrMGxWT1lHdnhaRktVd0tIMHJpQUwKQTRpbXlZdUwvZndlT1NHU25RbGdZS3I5OUhjaVRCSWRMMTVTWjMyVGpZYitQRFpCbCs2elFzdzJIWU5KY3FNagppY2lDN0NBajZnQjlTTzh4MXZNc1JrVStycUt1YzJyOFVrK3FoRUN3OHpSNEs2NndGdVlNMTdzR1VNWFVxL3BICldkaUV2TzNxL21kSzQ3TnJ4NWkyYmFDN281UlhzcEtIWXk2WGVyNFZibmlwbDREZ0FLa2FOT0wwMmErWnYzOFEKbCt4eTl3ZG1XcVVJYk1pcVNiai9rNnh4RGlQUWtUUisvMDMyZVFJREFRQUJBb0lCQUVrUHpwQlV0UFFickozTgo1UzFyQjcxVUw4NXUwT3FrUzJETnZCODl4VmFiYjBOTEwxV3NjMzl5QjI3MVBIak9SUlFwa21XaFEwOENGUmFlCjNveFFuaDQ3cytPck94UE15WlNJZGptaWNyNXRSempYZVlPa05rMEc3SmdDK09MM1lpZU9PblR5WkdReEhVcUIKM21mSVo0NXNIRHYzTXhDM2xwZnMzNS94VEhNOEUvZ1cvZ1RmdlUzUWJvUWFMMXEvdGFSUVlFSHZnaXV0d2RaMApzRUZ0SjhlQXdPQkFCWGlWM1FQeG5BUWdJcHdZcGJpY2wzQUsxNWdzNUVOSzRSbmdpMmJJN2hkbU13RFdhNnQvCmcwQ1AwVGl0eUZxMDVKVW1uYXo0d2VrWHhENUVCbTc3NkVZTlNveFRDYVN6VE1Zd1pDSVRycVhsNlk0L29nZVQKdVZTbTlaRUNnWUVBN0c4Q3l5REtEVEJZb0l5RWtuSlZLU3d1ZWxPQTJlZHhtVnlLTDhoTG9QaXExUW9TSC9OMQozMG5OL0dWY3ZEN1FFRDRwL3UwWGFNdVBtMkhWaHVYd3h1L3Q5ajExRFZsS1A3UXNIOXU0cEpLeml3Nk5tVjVOCi85K21jamRXQUg1QnFhSnRtcEYwdW9ac1drNDFKVmUwZkE3YTNGQ3JYcDFVL0dEOUJLU0FEMDBDZ1lFQW1BaW8KQ2hFaDcrcEQ3dnV0Rjg1dStGcWJkalkrS215RmVUUGQyNzE3UDZpNVY2QzZsVnBjbk03dm9abEd5MGZqb2FsZAplOW50bTBWVThGWmtVSWloS1B6VzkvTFNBVjhCZ08rdlNRck4vSU1FbURxb2w5NTlJeHhJLzZ5emtZNUp3WVJQCm1sd29OelUwZWtjSHpnMGV1N0RBMXV6UmZ2NEYxTlVXK1F5bFJkMENnWUVBenIwN09oZFAxanlDSXREOFUzbjYKRVdoNnM2ZzBzVlY1dGRwL1VzelhwTWdMeVFGblc5enRJdlJNVS9qbUlBemtybTlORllhSHc3REx2OWpLZDR5MAovNTlvK3JvK2tnK1RweVNLdU1qT0tjbkZpVUNPZko5RG9Rd1ZaU1lSNDVpREhpdlRueWExWlN5SnJtVllmM0N6CmR3OGVQU3VremJUUlRXWVptR2VuT3JrQ2dZRUFob082TWRZQXdlWHpIMEo4WHNEZVBFem1tY3ZhYXV6RGwzNUYKZ0lPQXhjMUIxMzgxTnFuUm9VZ1NpMWN6Wk82QlArcTY5TGJYM1BhVjlXTnF0RHArNU9YNFNUOEZnZ01PTUlkZwovbTVaM0Y0THRhakl2RDQxVjloUjJpMXlYNG1XUm1zTGgxYWNtbVF2dnpTVGVrTHZlejhqRDhaT2dWNjl5QmFWCmtkc1hhOTBDZ1lFQWsrNmdocFhOa3UxMlVBTmY5TUg4bG9OKzM1L2lQZWVvcWYwTVk1Rk1WUll4MTBaQTkxTGgKaWVBY3pWaGlxenhDdEhXaExBNFN4RTk2MmVnK2ppL2F3a1M0a1hMQ011WklFU0UrakZjN3B0VW1KamxzT1dqdgo4L2RxVUg1eWpSS3MycXhrQldHNEhtVDNOeDZBOHNZSXJVWXh5cVZMQnBHOHlLbmdibmFZUFY0PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==} +actions: + run: + title: Run Velociraptor Command + description: Run Velociraptor command + input: + command: + description: Command to execute on Velociraptor host + type: string + required: true + example: SELECT * FROM host() + output: + results: + title: Results + description: Results + type: results + required: true diff --git a/plugins/velociraptor_legacy/requirements.txt b/plugins/velociraptor_legacy/requirements.txt new file mode 100644 index 0000000000..5c7104eb96 --- /dev/null +++ b/plugins/velociraptor_legacy/requirements.txt @@ -0,0 +1,7 @@ +# 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 +paramiko==3.3.1 +grpcio==1.59.2 +grpcio.tools==1.59.2 +pyvelociraptor==0.1.8 diff --git a/plugins/velociraptor_legacy/setup.py b/plugins/velociraptor_legacy/setup.py new file mode 100644 index 0000000000..ac1849c407 --- /dev/null +++ b/plugins/velociraptor_legacy/setup.py @@ -0,0 +1,14 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +from setuptools import setup, find_packages + + +setup(name="velociraptor_legacy-jbauvinet-plugin", + version="1.0.0", + description="Velociraptor is a unique, advanced open-source endpoint monitoring, digital forensic and cyber response platform. It provides you with the ability to more effectively respond to a wide range of digital forensic and cyber incident response investigations and data breaches", + author="jbauvinet", + author_email="", + url="", + packages=find_packages(), + install_requires=['insightconnect-plugin-runtime'], # Add third-party dependencies to requirements.txt, not here! + scripts=['bin/icon_velociraptor_legacy'] + ) diff --git a/plugins/velociraptor_legacy/unit_test/__init__.py b/plugins/velociraptor_legacy/unit_test/__init__.py new file mode 100644 index 0000000000..797e426edf --- /dev/null +++ b/plugins/velociraptor_legacy/unit_test/__init__.py @@ -0,0 +1 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT diff --git a/plugins/velociraptor_legacy/unit_test/test_run.py b/plugins/velociraptor_legacy/unit_test/test_run.py new file mode 100644 index 0000000000..7d985eb070 --- /dev/null +++ b/plugins/velociraptor_legacy/unit_test/test_run.py @@ -0,0 +1,20 @@ +import sys +import os +sys.path.append(os.path.abspath('../')) + +from unittest import TestCase +from icon_velociraptor_legacy.connection.connection import Connection +from icon_velociraptor_legacy.actions.run import Run +import json +import logging + + +class TestRun(TestCase): + def test_run(self): + """ + DO NOT USE PRODUCTION/SENSITIVE DATA FOR UNIT TESTS + + TODO: Implement test cases here + """ + + self.fail("Unimplemented Test Case")