-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9fd63e9
commit b3a85fd
Showing
23 changed files
with
774 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Include other Makefiles for improved functionality | ||
INCLUDE_DIR = ../../tools/Makefiles | ||
MAKEFILES := $(wildcard $(INCLUDE_DIR)/*.mk) | ||
# We can't guarantee customers will have the include files | ||
# - prefix to ignore Makefiles when not present | ||
# https://www.gnu.org/software/make/manual/html_node/Include.html | ||
-include $(MAKEFILES) | ||
|
||
ifneq ($(MAKEFILES),) | ||
$(info [$(YELLOW)*$(NORMAL)] Use ``make menu`` for available targets) | ||
$(info [$(YELLOW)*$(NORMAL)] Including available Makefiles: $(MAKEFILES)) | ||
$(info --) | ||
else | ||
$(warning Makefile includes directory not present: $(INCLUDE_DIR)) | ||
endif | ||
|
||
VERSION?=$(shell grep '^version: ' plugin.spec.yaml | sed 's/version: //') | ||
NAME?=$(shell grep '^name: ' plugin.spec.yaml | sed 's/name: //') | ||
VENDOR?=$(shell grep '^vendor: ' plugin.spec.yaml | sed 's/vendor: //') | ||
CWD?=$(shell basename $(PWD)) | ||
_NAME?=$(shell echo $(NAME) | awk '{ print toupper(substr($$0,1,1)) tolower(substr($$0,2)) }') | ||
PKG=$(VENDOR)-$(NAME)-$(VERSION).tar.gz | ||
|
||
# Set default target explicitly. Make's default behavior is the first target in the Makefile. | ||
# We don't want that behavior due to includes which are read first | ||
.DEFAULT_GOAL := default # Make >= v3.80 (make -version) | ||
|
||
|
||
default: image tarball | ||
|
||
tarball: | ||
$(info [$(YELLOW)*$(NORMAL)] Creating plugin tarball) | ||
rm -rf build | ||
rm -rf $(PKG) | ||
tar -cvzf $(PKG) --exclude=$(PKG) --exclude=tests --exclude=run.sh * | ||
|
||
image: | ||
$(info [$(YELLOW)*$(NORMAL)] Building plugin image) | ||
docker build --pull -t $(VENDOR)/$(NAME):$(VERSION) . | ||
docker tag $(VENDOR)/$(NAME):$(VERSION) $(VENDOR)/$(NAME):latest | ||
|
||
regenerate: | ||
$(info [$(YELLOW)*$(NORMAL)] 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT |
3 changes: 3 additions & 0 deletions
3
velociraptor_legacy/icon_velociraptor_legacy/actions/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT | ||
|
||
from .run.action import Run |
2 changes: 2 additions & 0 deletions
2
velociraptor_legacy/icon_velociraptor_legacy/actions/run/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT | ||
from .action import Run |
92 changes: 92 additions & 0 deletions
92
velociraptor_legacy/icon_velociraptor_legacy/actions/run/action.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
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} |
82 changes: 82 additions & 0 deletions
82
velociraptor_legacy/icon_velociraptor_legacy/actions/run/schema.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# 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) |
2 changes: 2 additions & 0 deletions
2
velociraptor_legacy/icon_velociraptor_legacy/connection/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT | ||
from .connection import Connection |
Oops, something went wrong.