Skip to content

Commit b3a85fd

Browse files
jbauvinet-r7cmcnally-r7
authored andcommitted
Performed Black.
1 parent 9fd63e9 commit b3a85fd

23 files changed

+774
-0
lines changed

velociraptor_legacy/Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM rapid7/insightconnect-python-3-38-plugin:5
2+
3+
LABEL organization=jbauvinet
4+
LABEL sdk=python
5+
6+
WORKDIR /python/src
7+
8+
ADD ./plugin.spec.yaml /plugin.spec.yaml
9+
ADD ./requirements.txt /python/src/requirements.txt
10+
11+
RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
12+
13+
ADD . /python/src
14+
15+
RUN python setup.py build && python setup.py install
16+
17+
# User to run plugin code. The two supported users are: root, nobody
18+
USER nobody
19+
20+
ENTRYPOINT ["/usr/local/bin/icon_velociraptor_legacy"]

velociraptor_legacy/Makefile

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Include other Makefiles for improved functionality
2+
INCLUDE_DIR = ../../tools/Makefiles
3+
MAKEFILES := $(wildcard $(INCLUDE_DIR)/*.mk)
4+
# We can't guarantee customers will have the include files
5+
# - prefix to ignore Makefiles when not present
6+
# https://www.gnu.org/software/make/manual/html_node/Include.html
7+
-include $(MAKEFILES)
8+
9+
ifneq ($(MAKEFILES),)
10+
$(info [$(YELLOW)*$(NORMAL)] Use ``make menu`` for available targets)
11+
$(info [$(YELLOW)*$(NORMAL)] Including available Makefiles: $(MAKEFILES))
12+
$(info --)
13+
else
14+
$(warning Makefile includes directory not present: $(INCLUDE_DIR))
15+
endif
16+
17+
VERSION?=$(shell grep '^version: ' plugin.spec.yaml | sed 's/version: //')
18+
NAME?=$(shell grep '^name: ' plugin.spec.yaml | sed 's/name: //')
19+
VENDOR?=$(shell grep '^vendor: ' plugin.spec.yaml | sed 's/vendor: //')
20+
CWD?=$(shell basename $(PWD))
21+
_NAME?=$(shell echo $(NAME) | awk '{ print toupper(substr($$0,1,1)) tolower(substr($$0,2)) }')
22+
PKG=$(VENDOR)-$(NAME)-$(VERSION).tar.gz
23+
24+
# Set default target explicitly. Make's default behavior is the first target in the Makefile.
25+
# We don't want that behavior due to includes which are read first
26+
.DEFAULT_GOAL := default # Make >= v3.80 (make -version)
27+
28+
29+
default: image tarball
30+
31+
tarball:
32+
$(info [$(YELLOW)*$(NORMAL)] Creating plugin tarball)
33+
rm -rf build
34+
rm -rf $(PKG)
35+
tar -cvzf $(PKG) --exclude=$(PKG) --exclude=tests --exclude=run.sh *
36+
37+
image:
38+
$(info [$(YELLOW)*$(NORMAL)] Building plugin image)
39+
docker build --pull -t $(VENDOR)/$(NAME):$(VERSION) .
40+
docker tag $(VENDOR)/$(NAME):$(VERSION) $(VENDOR)/$(NAME):latest
41+
42+
regenerate:
43+
$(info [$(YELLOW)*$(NORMAL)] Refreshing schema from plugin.spec.yaml)
44+
insight-plugin refresh
45+
46+
export: image
47+
$(info [$(YELLOW)*$(NORMAL)] Exporting docker image)
48+
@printf "\n ---> Exporting Docker image to ./$(VENDOR)_$(NAME)_$(VERSION).tar\n"
49+
@docker save $(VENDOR)/$(NAME):$(VERSION) | gzip > $(VENDOR)_$(NAME)_$(VERSION).tar
50+
51+
# Make will not run a target if a file of the same name exists unless setting phony targets
52+
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
53+
.PHONY: default tarball image regenerate
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
3+
import os
4+
import json
5+
from sys import argv
6+
7+
Name = "Velociraptor Legacy"
8+
Vendor = "jbauvinet"
9+
Version = "1.0.0"
10+
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"
11+
12+
13+
def main():
14+
if 'http' in argv:
15+
if os.environ.get("GUNICORN_CONFIG_FILE"):
16+
with open(os.environ.get("GUNICORN_CONFIG_FILE")) as gf:
17+
gunicorn_cfg = json.load(gf)
18+
if gunicorn_cfg.get("worker_class", "sync") == "gevent":
19+
from gevent import monkey
20+
monkey.patch_all()
21+
elif 'gevent' in argv:
22+
from gevent import monkey
23+
monkey.patch_all()
24+
25+
import insightconnect_plugin_runtime
26+
from icon_velociraptor_legacy import connection, actions, triggers, tasks
27+
28+
class ICONVelociraptorLegacy(insightconnect_plugin_runtime.Plugin):
29+
def __init__(self):
30+
super(self.__class__, self).__init__(
31+
name=Name,
32+
vendor=Vendor,
33+
version=Version,
34+
description=Description,
35+
connection=connection.Connection()
36+
)
37+
self.add_action(actions.Run())
38+
39+
40+
"""Run plugin"""
41+
cli = insightconnect_plugin_runtime.CLI(ICONVelociraptorLegacy())
42+
cli.run()
43+
44+
45+
if __name__ == "__main__":
46+
main()

velociraptor_legacy/extension.png

14.2 KB
Loading

velociraptor_legacy/help.md

Lines changed: 122 additions & 0 deletions
Large diffs are not rendered by default.

velociraptor_legacy/icon.png

8.11 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
2+
3+
from .run.action import Run
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
2+
from .action import Run
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import json
2+
import paramiko
3+
import base64
4+
import grpc
5+
import io
6+
import time
7+
from pyvelociraptor import api_pb2
8+
from pyvelociraptor import api_pb2_grpc
9+
import insightconnect_plugin_runtime
10+
from .schema import RunInput, RunOutput, Input, Output, Component
11+
12+
# Custom imports below
13+
14+
15+
class Run(insightconnect_plugin_runtime.Action):
16+
def __init__(self):
17+
super(self.__class__, self).__init__(
18+
name="run",
19+
description=Component.DESCRIPTION,
20+
input=RunInput(),
21+
output=RunOutput(),
22+
)
23+
24+
def run(self, params={}):
25+
# START INPUT BINDING - DO NOT REMOVE - ANY INPUTS BELOW WILL UPDATE WITH YOUR PLUGIN SPEC AFTER REGENERATION
26+
# END INPUT BINDING - DO NOT REMOVE
27+
# TODO - If input bindings for connection can be done check to same if it you can do the same here
28+
"""Runs a VQL query against the Velociraptor server.
29+
30+
Args:
31+
config: A dictionary containing the configuration parameters for the Velociraptor server.
32+
query: The VQL query to run.
33+
34+
Returns:
35+
A tuple containing the query, the response, and the query execution logs.
36+
"""
37+
results = {}
38+
try:
39+
# Fill in the SSL params from the api_client config file. You can get such a file:
40+
# velociraptor --config server.config.yaml config api_client > api_client.conf.yaml
41+
api_connection_string = self.connection.api_connection_string
42+
root_certificates_decoded = self.connection.root_certificates_decoded
43+
private_key_decoded = self.connection.private_key_decoded
44+
certificate_chain_decoded = self.connection.certificate_chain_decoded
45+
query = params.get(Input.COMMAND)
46+
creds = grpc.ssl_channel_credentials(
47+
root_certificates=root_certificates_decoded,
48+
private_key=private_key_decoded,
49+
certificate_chain=certificate_chain_decoded,
50+
)
51+
# This option is required to connect to the grpc server by IP - we
52+
# use self signed certs.
53+
options = (
54+
(
55+
"grpc.ssl_target_name_override",
56+
"VelociraptorServer",
57+
),
58+
)
59+
# The first step is to open a gRPC channel to the server..
60+
with grpc.secure_channel(api_connection_string, creds, options) as channel:
61+
stub = api_pb2_grpc.APIStub(channel)
62+
# The request consists of one or more VQL queries. Note that you can collect artifacts by simply naming them using the
63+
# "Artifact" plugin.
64+
request = api_pb2.VQLCollectorArgs(
65+
max_wait=1,
66+
max_row=100,
67+
Query=[
68+
api_pb2.VQLRequest(
69+
Name="ICON Plugin Request",
70+
VQL=query,
71+
)
72+
],
73+
)
74+
# This will block as responses are streamed from the
75+
# server. If the query is an event query we will run this loop
76+
# forever.
77+
logs_list = []
78+
for response in stub.Query(request):
79+
if response.Response:
80+
package = json.loads(response.Response)
81+
logs_list.append(package)
82+
83+
elif response.log:
84+
# Query execution logs are sent in their own messages.
85+
package = time.ctime(response.timestamp / 1000000), response.log
86+
self.logger.info("Command Sent")
87+
results["logs_list"] = logs_list[0]
88+
return {Output.RESULTS: results}
89+
except grpc.RpcError as e:
90+
self.logger.info("Error: ", e)
91+
results["logs_list"] = e
92+
return {Output.RESULTS: results}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
2+
import insightconnect_plugin_runtime
3+
import json
4+
5+
6+
class Component:
7+
DESCRIPTION = "Run Velociraptor command"
8+
9+
10+
class Input:
11+
COMMAND = "command"
12+
13+
14+
class Output:
15+
RESULTS = "results"
16+
17+
18+
class RunInput(insightconnect_plugin_runtime.Input):
19+
schema = json.loads(
20+
r"""
21+
{
22+
"type": "object",
23+
"title": "Variables",
24+
"properties": {
25+
"command": {
26+
"type": "string",
27+
"description": "Command to execute on Velociraptor host",
28+
"order": 1
29+
}
30+
},
31+
"required": [
32+
"command"
33+
],
34+
"definitions": {}
35+
}
36+
"""
37+
)
38+
39+
def __init__(self):
40+
super(self.__class__, self).__init__(self.schema)
41+
42+
43+
class RunOutput(insightconnect_plugin_runtime.Output):
44+
schema = json.loads(
45+
r"""
46+
{
47+
"type": "object",
48+
"title": "Variables",
49+
"properties": {
50+
"results": {
51+
"$ref": "#/definitions/results",
52+
"title": "Results",
53+
"description": "Results",
54+
"order": 1
55+
}
56+
},
57+
"required": [
58+
"results"
59+
],
60+
"definitions": {
61+
"results": {
62+
"type": "object",
63+
"title": "results",
64+
"properties": {
65+
"logs_list": {
66+
"type": "array",
67+
"title": "LOGS_LIST",
68+
"description": "Logs List",
69+
"items": {
70+
"type": "object"
71+
},
72+
"order": 1
73+
}
74+
}
75+
}
76+
}
77+
}
78+
"""
79+
)
80+
81+
def __init__(self):
82+
super(self.__class__, self).__init__(self.schema)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT
2+
from .connection import Connection

0 commit comments

Comments
 (0)