Uninstall command (#66)

* Add do_uninstall function

* uninstall f/ amass/aqua/go

* uninstall functional on all tools

* Add in missed fixes from rebase

* solve permission issue

* Removes un-needed vars from yaml

* Resolves go test issues

* adds framework for uninstall tests

* Fixes uninstall tests for Go tools

* Adds uninstall testing for luigi and improves uninstall

* Adds uninstall testing for searchsploit

* Update installation documentation
This commit is contained in:
Ryan Good
2020-06-26 19:04:43 -05:00
committed by GitHub
parent 9e863a2260
commit 1ad3adca82
19 changed files with 272 additions and 93 deletions

View File

@@ -62,6 +62,8 @@ up the pipeline.
The installer maintains a (naive) list of installed tools at ``~/.local/recon-pipeline/tools/.tool-dict.pkl``. The installer in no way attempts to be a package manager. It knows how to execute the steps necessary to install its tools. Beyond that, it's The installer maintains a (naive) list of installed tools at ``~/.local/recon-pipeline/tools/.tool-dict.pkl``. The installer in no way attempts to be a package manager. It knows how to execute the steps necessary to install its tools. Beyond that, it's
like Jon Snow, **it knows nothing**. like Jon Snow, **it knows nothing**.
Tools can also be uninstalled using the ``uninstall all`` command. It is also possible to individually uninstall them in the same manner as shown above.
.. raw:: html .. raw:: html
<script id="asciicast-294414" src="https://asciinema.org/a/294414.js" async></script> <script id="asciicast-294414" src="https://asciinema.org/a/294414.js" async></script>

View File

@@ -63,6 +63,7 @@ from .recon import ( # noqa: F401,E402
get_scans, get_scans,
scan_parser, scan_parser,
install_parser, install_parser,
uninstall_parser,
status_parser, status_parser,
database_parser, database_parser,
db_detach_parser, db_detach_parser,
@@ -322,15 +323,24 @@ class ReconShell(cmd2.Cmd):
self.add_dynamic_parser_arguments() self.add_dynamic_parser_arguments()
@cmd2.with_argparser(install_parser) def _get_dict(self):
def do_install(self, args): """Retrieves tool dict if available"""
""" Install any/all of the libraries/tools necessary to make the recon-pipeline function. """
# imported tools variable is in global scope, and we reassign over it later # imported tools variable is in global scope, and we reassign over it later
global tools global tools
persistent_tool_dict = self.tools_dir / ".tool-dict.pkl" persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"
if persistent_tool_dict.exists():
tools = pickle.loads(persistent_tool_dict.read_bytes())
return tools
@cmd2.with_argparser(install_parser)
def do_install(self, args):
""" Install any/all of the libraries/tools necessary to make the recon-pipeline function. """
tools = self._get_dict()
if args.tool == "all": if args.tool == "all":
# show all tools have been queued for installation # show all tools have been queued for installation
[ [
@@ -343,8 +353,6 @@ class ReconShell(cmd2.Cmd):
self.do_install(tool) self.do_install(tool)
return return
if persistent_tool_dict.exists():
tools = pickle.loads(persistent_tool_dict.read_bytes())
if tools.get(args.tool).get("dependencies"): if tools.get(args.tool).get("dependencies"):
# get all of the requested tools dependencies # get all of the requested tools dependencies
@@ -374,7 +382,7 @@ class ReconShell(cmd2.Cmd):
if addl_env_vars is not None: if addl_env_vars is not None:
addl_env_vars.update(dict(os.environ)) addl_env_vars.update(dict(os.environ))
for command in tools.get(args.tool).get("commands"): for command in tools.get(args.tool).get("install_commands"):
# run all commands required to install the tool # run all commands required to install the tool
# print each command being run # print each command being run
@@ -420,6 +428,69 @@ class ReconShell(cmd2.Cmd):
) )
# store any tool installs/failures (back) to disk # store any tool installs/failures (back) to disk
persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"
pickle.dump(tools, persistent_tool_dict.open("wb"))
@cmd2.with_argparser(uninstall_parser)
def do_uninstall(self, args):
""" Uninstall any/all of the libraries/tools used by recon-pipeline"""
tools = self._get_dict()
if args.tool == "all":
# show all tools have been queued for installation
[
self.poutput(style(f"[-] {x} queued", fg="bright_white"))
for x in tools.keys()
if tools.get(x).get("installed")
]
for tool in tools.keys():
self.do_uninstall(tool)
return
if not tools.get(args.tool).get("installed"):
return self.poutput(style(f"[!] {args.tool} is not installed.", fg="yellow"))
else:
retvals = list()
self.poutput(style(f"[*] Removing {args.tool}...", fg="bright_yellow"))
if not tools.get(args.tool).get("uninstall_commands"):
self.poutput(style(f"[*] {args.tool} removal not needed", fg="bright_yellow"))
return
for command in tools.get(args.tool).get("uninstall_commands"):
self.poutput(style(f"[=] {command}", fg="cyan"))
proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if err:
self.poutput(style(f"[!] {err.decode().strip()}", fg="bright_red"))
retvals.append(proc.returncode)
if all(x == 0 for x in retvals):
# all return values in retvals are 0, i.e. all exec'd successfully; tool has been uninstalled
self.poutput(style(f"[+] {args.tool} removed!", fg="bright_green"))
tools[args.tool]["installed"] = False
else:
# unsuccessful tool removal
tools[args.tool]["installed"] = True
self.poutput(
style(
f"[!!] one (or more) of {args.tool}'s commands failed and may have not been removed properly; check output from the offending command above...",
fg="bright_red",
bold=True,
)
)
# store any tool installs/failures (back) to disk
persistent_tool_dict = self.tools_dir / ".tool-dict.pkl"
pickle.dump(tools, persistent_tool_dict.open("wb")) pickle.dump(tools, persistent_tool_dict.open("wb"))
@cmd2.with_argparser(status_parser) @cmd2.with_argparser(status_parser)

View File

@@ -7,6 +7,7 @@ from .nmap import ThreadedNmapScan, SearchsploitScan
from .config import top_udp_ports, top_tcp_ports, defaults, web_ports from .config import top_udp_ports, top_tcp_ports, defaults, web_ports
from .parsers import ( from .parsers import (
install_parser, install_parser,
uninstall_parser,
scan_parser, scan_parser,
status_parser, status_parser,
database_parser, database_parser,

View File

@@ -10,6 +10,9 @@ from ..tools import tools
install_parser = cmd2.Cmd2ArgumentParser() install_parser = cmd2.Cmd2ArgumentParser()
install_parser.add_argument("tool", help="which tool to install", choices=list(tools.keys()) + ["all"]) install_parser.add_argument("tool", help="which tool to install", choices=list(tools.keys()) + ["all"])
# options for ReconShell's 'uninstall' command
uninstall_parser = cmd2.Cmd2ArgumentParser()
uninstall_parser.add_argument("tool", help="which tool to uninstall", choices=list(tools.keys()) + ["all"])
# options for ReconShell's 'status' command # options for ReconShell's 'status' command
status_parser = cmd2.Cmd2ArgumentParser() status_parser = cmd2.Cmd2ArgumentParser()

View File

@@ -1,10 +1,13 @@
installed: false installed: false
dependencies: [go] dependencies: [go]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/amass] path: &path !join_path [!get_default "{gopath}", "bin/amass"]
environ: {"GO111MODULE": "on", "GOPATH": !get_default "{gopath}"} environ: {"GO111MODULE": "on", "GOPATH": !get_default "{gopath}"}
commands: install_commands:
- !join [*gotool, get github.com/OWASP/Amass/v3/...] - !join [*gotool, get github.com/OWASP/Amass/v3/...]
uninstall_commands:
- !join [rm, *path]

View File

@@ -1,12 +1,15 @@
installed: false installed: false
tools: &tools !get_default "{tools-dir}" tools: &tools !get_default "{tools-dir}"
path: &aqua !join_path [*tools, aquatone] path: &path !join_path [*tools, aquatone]
commands: install_commands:
- mkdir /tmp/aquatone - mkdir /tmp/aquatone
- wget -q https://github.com/michenriksen/aquatone/releases/download/v1.7.0/aquatone_linux_amd64_1.7.0.zip -O /tmp/aquatone/aquatone.zip - wget -q https://github.com/michenriksen/aquatone/releases/download/v1.7.0/aquatone_linux_amd64_1.7.0.zip -O /tmp/aquatone/aquatone.zip
- bash -c 'if [[ ! $(which unzip) ]]; then sudo apt install -y zip; fi' - bash -c 'if [[ ! $(which unzip) ]]; then sudo apt install -y zip; fi'
- unzip /tmp/aquatone/aquatone.zip -d /tmp/aquatone - unzip /tmp/aquatone/aquatone.zip -d /tmp/aquatone
- !join [mv /tmp/aquatone/aquatone, *aqua] - !join [mv /tmp/aquatone/aquatone, *path]
- rm -rf /tmp/aquatone - rm -rf /tmp/aquatone
- bash -c 'found=false; for loc in {/usr/bin/google-chrome,/usr/bin/google-chrome-beta,/usr/bin/google-chrome-unstable,/usr/bin/chromium-browser,/usr/bin/chromium}; do if [[ $(which $loc) ]]; then found=true; break; fi ; done; if [[ $found = false ]]; then sudo apt install -y chromium-browser ; fi' - bash -c 'found=false; for loc in {/usr/bin/google-chrome,/usr/bin/google-chrome-beta,/usr/bin/google-chrome-unstable,/usr/bin/chromium-browser,/usr/bin/chromium}; do if [[ $(which $loc) ]]; then found=true; break; fi ; done; if [[ $found = false ]]; then sudo apt install -y chromium-browser ; fi'
uninstall_commands:
- !join [rm, *path]

View File

@@ -2,7 +2,10 @@ installed: false
bashrc: &bashrc !join_path [!get_default "{home}", .bashrc] bashrc: &bashrc !join_path [!get_default "{home}", .bashrc]
path: &gotool !join_path [!get_default "{goroot}", go/bin/go] path: &gotool !join_path [!get_default "{goroot}", go/bin/go]
commands: install_commands:
- wget -q https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz -O /tmp/go.tar.gz - wget -q https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz -O /tmp/go.tar.gz
- !join [tar -C, !get_default "{goroot}", -xvf /tmp/go.tar.gz] - !join [tar -C, !get_default "{goroot}", -xvf /tmp/go.tar.gz]
- !join ["bash -c 'if [ ! $(grep $(dirname", *gotool, ")", *bashrc, ") ]; then echo PATH=${PATH}:$(dirname", *gotool, ") >>", *bashrc, "; fi'"] - !join ["bash -c 'if [ ! $(grep $(dirname", *gotool, ")", *bashrc, ") ]; then echo PATH=${PATH}:$(dirname", *gotool, ") >>", *bashrc, "; fi'"]
uninstall_commands:
- !join [sudo, rm, -r, !get_default "{goroot}"]

View File

@@ -1,8 +1,12 @@
installed: false installed: false
dependencies: [go, seclists] dependencies: [go, seclists]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/gobuster] path: &path !join_path [!get_default "{gopath}", bin/gobuster]
environ: {"GOPATH": !get_default "{gopath}"} environ: {"GOPATH": !get_default "{gopath}"}
home: &home !get_default "{home}"
commands: install_commands:
- !join [*gotool, get github.com/OJ/gobuster] - !join [*gotool, get github.com/OJ/gobuster]
uninstall_commands:
- !join [rm, *path]

View File

@@ -2,11 +2,17 @@ installed: false
project-dir: &proj !get_default "{project-dir}" project-dir: &proj !get_default "{project-dir}"
service-file: &svcfile !join_path [*proj, luigid.service] service-file: &svcfile !join_path [*proj, luigid.service]
commands: install_commands:
- !join [sudo cp, *svcfile, /lib/systemd/system/luigid.service] - !join [sudo cp, *svcfile, /lib/systemd/system/luigid.service]
- !join [sudo cp, *svcfile, $(which luigid), /usr/local/bin] - !join [sudo cp, $(which luigid), /usr/local/bin]
- sudo systemctl daemon-reload - sudo systemctl daemon-reload
- sudo systemctl start luigid.service - sudo systemctl start luigid.service
- sudo systemctl enable luigid.service - sudo systemctl enable luigid.service
uninstall_commands:
- sudo systemctl disable luigid.service
- sudo systemctl stop luigid.service
- sudo rm /lib/systemd/system/luigid.service
- sudo rm /usr/local/bin/luigid /usr/local/bin/luigid.service
shell: true shell: true

View File

@@ -1,10 +1,13 @@
installed: false installed: false
tools: &tools !get_default "{tools-dir}" tools: &tools !get_default "{tools-dir}"
path: &masscan !join_path [*tools, masscan] path: &path !join_path [*tools, masscan]
commands: install_commands:
- git clone https://github.com/robertdavidgraham/masscan /tmp/masscan - git clone https://github.com/robertdavidgraham/masscan /tmp/masscan
- make -s -j -C /tmp/masscan - make -s -j -C /tmp/masscan
- !join [mv /tmp/masscan/bin/masscan, *masscan] - !join [mv /tmp/masscan/bin/masscan, *path]
- rm -rf /tmp/masscan - rm -rf /tmp/masscan
- !join [sudo setcap CAP_NET_RAW+ep, *masscan] - !join [sudo setcap CAP_NET_RAW+ep, *path]
uninstall_commands:
- !join [rm, *path]

View File

@@ -1,10 +1,13 @@
installed: false installed: false
dependencies: [gobuster] dependencies: [gobuster]
tools: &tools !get_default "{tools-dir}" tools: &tools !get_default "{tools-dir}"
path: !join_path [*tools, recursive-gobuster/recursive-gobuster.pyz] path: &path !join_path [*tools, recursive-gobuster/recursive-gobuster.pyz]
recursive-parent: &parent !join_path [*tools, recursive-gobuster] recursive-parent: &parent !join_path [*tools, recursive-gobuster]
commands: install_commands:
- !join ["bash -c 'if [ -d", *parent, "]; then cd", *parent, - !join ["bash -c 'if [ -d", *parent, "]; then cd", *parent,
"&& git fetch --all && git pull; else git clone https://github.com/epi052/recursive-gobuster.git", "&& git fetch --all && git pull; else git clone https://github.com/epi052/recursive-gobuster.git",
*parent, " ; fi'"] *parent, "; fi'"]
uninstall_commands:
- !join [sudo, rm, -r, *parent]

View File

@@ -3,15 +3,18 @@ dependencies: [exploitdb]
home: &home !get_default "{home}" home: &home !get_default "{home}"
tools: &tools !get_default "{tools-dir}" tools: &tools !get_default "{tools-dir}"
exploitdb-file: &exploitdb !get_tool_path "{exploitdb[path]}" exploitdb-file: &exploitdb !get_tool_path "{exploitdb[path]}"
path: &searchsploit !join_path [*tools, exploitdb/searchsploit] path: &path !join_path [*tools, exploitdb/searchsploit]
searchsploit-rc: &ss_rc !join_path [*exploitdb, ".searchsploit_rc"] searchsploit-rc: &ss_rc !join_path [*exploitdb, ".searchsploit_rc"]
homesploit: &homesploit !join_path [*home, ".searchsploit_rc"] homesploit: &homesploit !join_path [*home, ".searchsploit_rc"]
sed-command: &sedcom !join_empty ["'s#/opt#", *tools, "#g'"] sed-command: &sedcom !join_empty ["'s#/opt#", *tools, "#g'"]
commands: install_commands:
- !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then ln -fs /usr/share/exploitdb", - !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then sudo ln -fs /usr/share/exploitdb",
*exploitdb, "&& ln -fs $(which searchsploit)", *searchsploit, *exploitdb, "&& sudo ln -fs $(which searchsploit)", *path,
"; elif [ -d", *exploitdb, "]; then cd", *exploitdb, "; elif [ -d", *exploitdb, "]; then cd", *exploitdb,
"&& git fetch --all && git pull; else git clone https://github.com/offensive-security/exploitdb.git", *exploitdb, "; fi'"] "&& git fetch --all && git pull; else git clone https://github.com/offensive-security/exploitdb.git", *exploitdb, ; fi']
- !join ["bash -c 'if [ -f", *ss_rc, "]; then cp -n", *ss_rc, *home, "; fi'"] - !join ["bash -c 'if [ -f", *ss_rc, "]; then cp -n", *ss_rc, *home, "; fi'"]
- !join ["bash -c 'if [ -f", *homesploit, "]; then sed -i", *sedcom, *homesploit, "; fi'"] - !join ["bash -c 'if [ -f", *homesploit, "]; then sed -i", *sedcom, *homesploit, "; fi'"]
uninstall_commands:
- !join [sudo, rm, -r, *exploitdb]

View File

@@ -1,8 +1,11 @@
installed: false installed: false
tools: &tools !get_default "{tools-dir}" tools: &tools !get_default "{tools-dir}"
path: &secfile !join_path [*tools, seclists] path: &path !join_path [*tools, seclists]
commands: install_commands:
- !join ["bash -c 'if [[ -d /usr/share/seclists ]]; then ln -s /usr/share/seclists", - !join ["bash -c 'if [[ -d /usr/share/seclists ]]; then ln -s /usr/share/seclists",
*secfile, "; elif [[ -d", *secfile, "]] ; then cd", *secfile, "&& git fetch --all && git pull;", *path, "; elif [[ -d", *path, "]] ; then cd", *path, "&& git fetch --all && git pull;",
"else git clone https://github.com/danielmiessler/SecLists.git", *secfile, "; fi'"] "else git clone https://github.com/danielmiessler/SecLists.git", *path, "; fi'"]
uninstall_commands:
- !join [sudo, rm, -r, *path]

View File

@@ -1,10 +1,13 @@
installed: false installed: false
dependencies: [go] dependencies: [go]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/subjack] path: &path !join_path [!get_default "{gopath}", bin/subjack]
environ: {"GOPATH": !get_default "{gopath}"} environ: {"GOPATH": !get_default "{gopath}"}
fingerprints: !join_path [!get_default "{gopath}", src/github.com/haccer/subjack/fingerprints.json] fingerprints: !join_path [!get_default "{gopath}", src/github.com/haccer/subjack/fingerprints.json]
commands: install_commands:
- !join [*gotool, get github.com/haccer/subjack] - !join [*gotool, get github.com/haccer/subjack]
uninstall_commands:
- !join [rm, *path]

View File

@@ -1,9 +1,12 @@
installed: false installed: false
dependencies: [go] dependencies: [go]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/tko-subs] path: &path !join_path [!get_default "{gopath}", bin/tko-subs]
environ: {"GOPATH": !get_default "{gopath}"} environ: {"GOPATH": !get_default "{gopath}"}
providers: !join_path [!get_default "{gopath}", src/github.com/anshumanbh/tko-subs/providers-data.csv] providers: !join_path [!get_default "{gopath}", src/github.com/anshumanbh/tko-subs/providers-data.csv]
commands: install_commands:
- !join [*gotool, get, github.com/anshumanbh/tko-subs] - !join [*gotool, get, github.com/anshumanbh/tko-subs]
uninstall_commands:
- !join [rm, *path]

View File

@@ -1,8 +1,11 @@
installed: false installed: false
dependencies: [go] dependencies: [go]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/waybackurls] path: &path !join_path [!get_default "{gopath}", bin/waybackurls]
environ: {"GOPATH": !get_default "{gopath}"} environ: {"GOPATH": !get_default "{gopath}"}
commands: install_commands:
- !join [*gotool, get, github.com/tomnomnom/waybackurls] - !join [*gotool, get, github.com/tomnomnom/waybackurls]
uninstall_commands:
- !join [rm, *path]

View File

@@ -1,8 +1,11 @@
installed: false installed: false
dependencies: [go] dependencies: [go]
go: &gotool !get_tool_path "{go[path]}" go: &gotool !get_tool_path "{go[path]}"
path: !join_path [!get_default "{gopath}", bin/webanalyze] path: &path !join_path [!get_default "{gopath}", bin/webanalyze]
environ: {"GOPATH": !get_default "{gopath}"} environ: {"GOPATH": !get_default "{gopath}"}
commands: install_commands:
- !join [*gotool, get github.com/rverton/webanalyze/...] - !join [*gotool, get github.com/rverton/webanalyze/...]
uninstall_commands:
- !join [rm, *path]

View File

@@ -26,25 +26,30 @@ class TestUnmockedToolsInstall:
shutil.rmtree(self.tmp_path, onerror=onerror) shutil.rmtree(self.tmp_path, onerror=onerror)
def perform_install(self, tools_dict, tool_name, exists=False): def perform_add_remove(self, tools_dict, tool_name, install, exists):
if install:
pickle.dump(tools_dict, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb")) pickle.dump(tools_dict, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb"))
tool = Path(tools_dict.get(tool_name).get("path")) tool = Path(tools_dict.get(tool_name).get("path"))
if install and exists is False:
if exists is False:
assert tool.exists() is False assert tool.exists() is False
elif not install and exists is True:
utils.run_cmd(self.shell, f"install {tool_name}")
assert tool.exists() is True assert tool.exists() is True
if install:
utils.run_cmd(self.shell, f"install {tool_name}")
assert tool.exists() is True
else:
utils.run_cmd(self.shell, f"uninstall {tool_name}")
assert tool.exists() is False
def setup_go_test(self, tool_name, tool_dict): def setup_go_test(self, tool_name, tool_dict):
# install go in tmp location # install go in tmp location
dependency = "go" dependency = "go"
dependency_path = f"{self.shell.tools_dir}/go/bin/go" dependency_path = f"{self.shell.tools_dir}/go/bin/go"
tool_dict.get(dependency)["path"] = dependency_path tool_dict.get(dependency)["path"] = dependency_path
tool_dict.get(dependency).get("commands")[1] = f"tar -C {self.shell.tools_dir} -xvf /tmp/go.tar.gz" tool_dict.get(dependency).get("install_commands")[1] = f"tar -C {self.shell.tools_dir} -xvf /tmp/go.tar.gz"
# handle env for local go install # handle env for local go install
tmp_go_path = f"{self.shell.tools_dir}/mygo" tmp_go_path = f"{self.shell.tools_dir}/mygo"
@@ -54,6 +59,8 @@ class TestUnmockedToolsInstall:
tool_path = f"{tool_dict.get(tool_name).get('environ').get('GOPATH')}/bin/{tool_name}" tool_path = f"{tool_dict.get(tool_name).get('environ').get('GOPATH')}/bin/{tool_name}"
tool_dict.get(tool_name)["path"] = tool_path tool_dict.get(tool_name)["path"] = tool_path
tool_dict.get(tool_name)["installed"] = False
return tool_dict return tool_dict
def test_install_masscan(self): def test_install_masscan(self):
@@ -63,21 +70,26 @@ class TestUnmockedToolsInstall:
tool_path = f"{self.shell.tools_dir}/{tool}" tool_path = f"{self.shell.tools_dir}/{tool}"
tools_copy.get(tool)["path"] = tool_path tools_copy.get(tool)["path"] = tool_path
tools_copy.get(tool).get("commands")[2] = f"mv /tmp/masscan/bin/masscan {tool_path}" tools_copy.get(tool).get("install_commands")[2] = f"mv /tmp/masscan/bin/masscan {tool_path}"
tools_copy.get(tool).get("commands")[4] = f"sudo setcap CAP_NET_RAW+ep {tool_path}" tools_copy.get(tool).get("install_commands")[4] = f"sudo setcap CAP_NET_RAW+ep {tool_path}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_amass(self): def test_install_amass(self):
tool = "amass" tool = "amass"
url = "github.com/OWASP/Amass/v3/..." url = "github.com/OWASP/Amass/v3/..."
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/amass"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get('go').get('path')} get {url}" tools_copy.get(tool).get("install_commands")[0] = f"{tools_copy.get('go').get('path')} get {url}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_aquatone(self): def test_install_aquatone(self):
tool = "aquatone" tool = "aquatone"
@@ -86,9 +98,11 @@ class TestUnmockedToolsInstall:
tool_path = f"{self.shell.tools_dir}/{tool}" tool_path = f"{self.shell.tools_dir}/{tool}"
tools_copy.get(tool)["path"] = tool_path tools_copy.get(tool)["path"] = tool_path
tools_copy.get(tool).get("commands")[4] = f"mv /tmp/aquatone/aquatone {tool_path}" tools_copy.get(tool).get("install_commands")[4] = f"mv /tmp/aquatone/aquatone {tool_path}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_go(self): def test_install_go(self):
tool = "go" tool = "go"
@@ -97,31 +111,30 @@ class TestUnmockedToolsInstall:
tool_path = f"{self.shell.tools_dir}/go/bin/go" tool_path = f"{self.shell.tools_dir}/go/bin/go"
tools_copy.get(tool)["path"] = tool_path tools_copy.get(tool)["path"] = tool_path
tools_copy.get(tool).get("commands")[1] = f"tar -C {self.shell.tools_dir} -xvf /tmp/go.tar.gz" tools_copy.get(tool).get("install_commands")[1] = f"tar -C {self.shell.tools_dir} -xvf /tmp/go.tar.gz"
tools_copy.get(tool).get("uninstall_commands")[0] = f"sudo rm -r {self.shell.tools_dir}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_gobuster(self): def test_install_gobuster(self):
tool = "gobuster" tool = "gobuster"
dependency = "go" dependency = "go"
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/gobuster"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool)["dependencies"] = [dependency] tools_copy.get(tool)["dependencies"] = [dependency]
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get(dependency).get('path')} get github.com/OJ/gobuster" tools_copy.get(tool).get("install_commands")[
0
] = f"{tools_copy.get(dependency).get('path')} get github.com/OJ/gobuster"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_luigi_service(self):
luigi_service = Path("/lib/systemd/system/luigid.service")
if luigi_service.exists():
subprocess.run(f"sudo rm {luigi_service}".split())
tools_copy = tools.copy()
pickle.dump(tools_copy, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb"))
def pause_luigi(self):
proc = subprocess.run("systemctl is-enabled luigid.service".split(), stdout=subprocess.PIPE) proc = subprocess.run("systemctl is-enabled luigid.service".split(), stdout=subprocess.PIPE)
if proc.stdout.decode().strip() == "enabled": if proc.stdout.decode().strip() == "enabled":
@@ -132,6 +145,17 @@ class TestUnmockedToolsInstall:
if proc.stdout.decode().strip() == "active": if proc.stdout.decode().strip() == "active":
subprocess.run("sudo systemctl stop luigid.service".split()) subprocess.run("sudo systemctl stop luigid.service".split())
def test_install_luigi_service(self):
luigi_service = Path("/lib/systemd/system/luigid.service")
self.pause_luigi()
if luigi_service.exists():
subprocess.run(f"sudo rm {luigi_service}".split())
tools_copy = tools.copy()
pickle.dump(tools_copy, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb"))
if Path("/usr/local/bin/luigid").exists(): if Path("/usr/local/bin/luigid").exists():
subprocess.run("sudo rm /usr/local/bin/luigid".split()) subprocess.run("sudo rm /usr/local/bin/luigid".split())
@@ -161,6 +185,16 @@ class TestUnmockedToolsInstall:
assert Path("/usr/local/bin/luigid").exists() assert Path("/usr/local/bin/luigid").exists()
utils.run_cmd(self.shell, "uninstall luigi-service")
proc = subprocess.run("systemctl is-enabled luigid.service".split(), stdout=subprocess.PIPE)
assert proc.stdout.decode().strip() != "enabled"
proc = subprocess.run("systemctl is-active luigid.service".split(), stdout=subprocess.PIPE)
assert proc.stdout.decode().strip() != "active"
assert luigi_service.exists() is False
@pytest.mark.parametrize("test_input", ["install", "update"]) @pytest.mark.parametrize("test_input", ["install", "update"])
def test_install_recursive_gobuster(self, test_input): def test_install_recursive_gobuster(self, test_input):
tool = "recursive-gobuster" tool = "recursive-gobuster"
@@ -175,15 +209,19 @@ class TestUnmockedToolsInstall:
tools_copy.get(tool)["path"] = tool_path tools_copy.get(tool)["path"] = tool_path
tools_copy.get(tool)["dependencies"] = None tools_copy.get(tool)["dependencies"] = None
tools_copy.get(tool).get("commands")[0] = f"bash -c 'if [ -d {parent} ]; " tools_copy.get(tool).get("install_commands")[0] = f"bash -c 'if [ -d {parent} ]; "
tools_copy.get(tool).get("commands")[0] += f"then cd {parent} && git fetch --all && git pull; " tools_copy.get(tool).get("install_commands")[0] += f"then cd {parent} && git fetch --all && git pull; "
tools_copy.get(tool).get("commands")[0] += "else git clone https://github.com/epi052/recursive-gobuster.git " tools_copy.get(tool).get("install_commands")[
tools_copy.get(tool).get("commands")[0] += f"{parent} ; fi'" 0
] += "else git clone https://github.com/epi052/recursive-gobuster.git "
tools_copy.get(tool).get("install_commands")[0] += f"{parent} ; fi'"
tools_copy.get(tool).get("uninstall_commands")[0] = f"sudo rm -r {parent}"
if test_input == "update": if test_input == "update":
self.perform_install(tools_copy, tool, exists=True) self.perform_add_remove(tools_copy, tool, True, True)
else: else:
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
@pytest.mark.parametrize("test_input", ["install", "update"]) @pytest.mark.parametrize("test_input", ["install", "update"])
def test_install_searchsploit(self, test_input): def test_install_searchsploit(self, test_input):
@@ -211,13 +249,15 @@ class TestUnmockedToolsInstall:
first_cmd += f"; elif [ -d {dependency_path} ]; then cd {dependency_path} && git fetch --all && git pull; else " first_cmd += f"; elif [ -d {dependency_path} ]; then cd {dependency_path} && git fetch --all && git pull; else "
first_cmd += f"git clone https://github.com/offensive-security/exploitdb.git {dependency_path}; fi'" first_cmd += f"git clone https://github.com/offensive-security/exploitdb.git {dependency_path}; fi'"
tools_copy.get(tool).get("commands")[0] = first_cmd tools_copy.get(tool).get("install_commands")[0] = first_cmd
tools_copy.get(tool).get("commands")[1] = f"bash -c 'if [ -f {searchsploit_rc_path} ]; " tools_copy.get(tool).get("install_commands")[1] = f"bash -c 'if [ -f {searchsploit_rc_path} ]; "
tools_copy.get(tool).get("commands")[1] += f"then cp -n {searchsploit_rc_path} {home_path} ; fi'" tools_copy.get(tool).get("install_commands")[1] += f"then cp -n {searchsploit_rc_path} {home_path} ; fi'"
tools_copy.get(tool).get("commands")[2] = f"bash -c 'if [ -f {copied_searchsploit_rc} ]; " tools_copy.get(tool).get("install_commands")[2] = f"bash -c 'if [ -f {copied_searchsploit_rc} ]; "
tools_copy.get(tool).get("commands")[2] += f"then sed -i {sed_cmd} {copied_searchsploit_rc}; fi'" tools_copy.get(tool).get("install_commands")[2] += f"then sed -i {sed_cmd} {copied_searchsploit_rc}; fi'"
tools_copy.get(tool).get("uninstall_commands")[0] = f"sudo rm -r {dependency_path}"
pickle.dump(tools_copy, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb")) pickle.dump(tools_copy, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb"))
@@ -227,11 +267,13 @@ class TestUnmockedToolsInstall:
assert not Path(dependency_path).exists() assert not Path(dependency_path).exists()
utils.run_cmd(self.shell, f"install {tool}") utils.run_cmd(self.shell, f"install {tool}")
assert subprocess.run(f"grep {self.shell.tools_dir} {copied_searchsploit_rc}".split()).returncode == 0 assert subprocess.run(f"grep {self.shell.tools_dir} {copied_searchsploit_rc}".split()).returncode == 0
assert Path(copied_searchsploit_rc).exists() assert Path(copied_searchsploit_rc).exists()
assert Path(dependency_path).exists() assert Path(dependency_path).exists()
utils.run_cmd(self.shell, f"uninstall {tool}")
assert Path(dependency_path).exists() is False
@pytest.mark.parametrize("test_input", ["install", "update"]) @pytest.mark.parametrize("test_input", ["install", "update"])
def test_install_seclists(self, test_input): def test_install_seclists(self, test_input):
tool = "seclists" tool = "seclists"
@@ -248,53 +290,67 @@ class TestUnmockedToolsInstall:
first_cmd += f"[[ -d {tool_path} ]] ; then cd {tool_path} && git fetch --all && git pull; " first_cmd += f"[[ -d {tool_path} ]] ; then cd {tool_path} && git fetch --all && git pull; "
first_cmd += f"else git clone https://github.com/danielmiessler/SecLists.git {tool_path}; fi'" first_cmd += f"else git clone https://github.com/danielmiessler/SecLists.git {tool_path}; fi'"
tools_copy.get(tool).get("commands")[0] = first_cmd tools_copy.get(tool).get("install_commands")[0] = first_cmd
tools_copy.get(tool).get("uninstall_commands")[0] = f"sudo rm -r {tool_path}"
if test_input == "update": if test_input == "update":
self.perform_install(tools_copy, tool, exists=True) self.perform_add_remove(tools_copy, tool, True, True)
else: else:
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_subjack(self): def test_install_subjack(self):
tool = "subjack" tool = "subjack"
url = "github.com/haccer/subjack" url = "github.com/haccer/subjack"
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/subjack"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get('go').get('path')} get {url}" tools_copy.get(tool).get("install_commands")[0] = f"{tools_copy.get('go').get('path')} get {url}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_tkosubs(self): def test_install_tkosubs(self):
tool = "tko-subs" tool = "tko-subs"
url = "github.com/anshumanbh/tko-subs" url = "github.com/anshumanbh/tko-subs"
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/tko-subs"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get('go').get('path')} get {url}" tools_copy.get(tool).get("install_commands")[0] = f"{tools_copy.get('go').get('path')} get {url}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_waybackurls(self): def test_install_waybackurls(self):
tool = "waybackurls" tool = "waybackurls"
url = "github.com/tomnomnom/waybackurls" url = "github.com/tomnomnom/waybackurls"
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/waybackurls"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get('go').get('path')} get {url}" tools_copy.get(tool).get("install_commands")[0] = f"{tools_copy.get('go').get('path')} get {url}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)
def test_install_webanalyze(self): def test_install_webanalyze(self):
tool = "webanalyze" tool = "webanalyze"
url = "github.com/rverton/webanalyze/..." url = "github.com/rverton/webanalyze/..."
tools_copy = tools.copy() tools_copy = tools.copy()
tool_path = f"{self.shell.tools_dir}/mygo/bin/webanalyze"
tools_copy.update(self.setup_go_test(tool, tools_copy)) tools_copy.update(self.setup_go_test(tool, tools_copy))
tools_copy.get(tool).get("commands")[0] = f"{tools_copy.get('go').get('path')} get {url}" tools_copy.get(tool).get("install_commands")[0] = f"{tools_copy.get('go').get('path')} get {url}"
tools_copy.get(tool).get("uninstall_commands")[0] = f"rm {tool_path}"
self.perform_install(tools_copy, tool) self.perform_add_remove(tools_copy, tool, True, False)
self.perform_add_remove(tools_copy, tool, False, True)

View File

@@ -37,4 +37,7 @@ def run_cmd(app, cmd):
out = copy_cmd_stdout.getvalue() out = copy_cmd_stdout.getvalue()
err = copy_stderr.getvalue() err = copy_stderr.getvalue()
print(out)
print(err)
return normalize(out), normalize(err) return normalize(out), normalize(err)