diff --git a/docs/overview/installation.rst b/docs/overview/installation.rst index 8144358..813ba4d 100644 --- a/docs/overview/installation.rst +++ b/docs/overview/installation.rst @@ -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 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 diff --git a/pipeline/recon-pipeline.py b/pipeline/recon-pipeline.py index 49fa296..a54c7fe 100755 --- a/pipeline/recon-pipeline.py +++ b/pipeline/recon-pipeline.py @@ -63,6 +63,7 @@ def cluge_package_imports(name, package): get_scans, scan_parser, install_parser, + uninstall_parser, status_parser, database_parser, db_detach_parser, @@ -322,15 +323,24 @@ def do_scan(self, args): self.add_dynamic_parser_arguments() - @cmd2.with_argparser(install_parser) - def do_install(self, args): - """ Install any/all of the libraries/tools necessary to make the recon-pipeline function. """ + def _get_dict(self): + """Retrieves tool dict if available""" # imported tools variable is in global scope, and we reassign over it later global tools 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": # show all tools have been queued for installation [ @@ -343,8 +353,6 @@ def do_install(self, args): self.do_install(tool) return - if persistent_tool_dict.exists(): - tools = pickle.loads(persistent_tool_dict.read_bytes()) if tools.get(args.tool).get("dependencies"): # get all of the requested tools dependencies @@ -374,7 +382,7 @@ def do_install(self, args): if addl_env_vars is not None: 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 # print each command being run @@ -420,6 +428,69 @@ def do_install(self, args): ) # 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")) @cmd2.with_argparser(status_parser) diff --git a/pipeline/recon/__init__.py b/pipeline/recon/__init__.py index 8da6d0f..8b36116 100644 --- a/pipeline/recon/__init__.py +++ b/pipeline/recon/__init__.py @@ -7,6 +7,7 @@ from .config import top_udp_ports, top_tcp_ports, defaults, web_ports from .parsers import ( install_parser, + uninstall_parser, scan_parser, status_parser, database_parser, diff --git a/pipeline/recon/parsers.py b/pipeline/recon/parsers.py index cdee6ab..183f1dd 100644 --- a/pipeline/recon/parsers.py +++ b/pipeline/recon/parsers.py @@ -10,6 +10,9 @@ install_parser = cmd2.Cmd2ArgumentParser() 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 status_parser = cmd2.Cmd2ArgumentParser() diff --git a/pipeline/tools/amass.yaml b/pipeline/tools/amass.yaml index 62c1219..4036742 100644 --- a/pipeline/tools/amass.yaml +++ b/pipeline/tools/amass.yaml @@ -1,10 +1,13 @@ installed: false dependencies: [go] 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}"} -commands: +install_commands: - !join [*gotool, get github.com/OWASP/Amass/v3/...] +uninstall_commands: +- !join [rm, *path] + diff --git a/pipeline/tools/aquatone.yaml b/pipeline/tools/aquatone.yaml index 1f0662f..38a251b 100644 --- a/pipeline/tools/aquatone.yaml +++ b/pipeline/tools/aquatone.yaml @@ -1,12 +1,15 @@ installed: false tools: &tools !get_default "{tools-dir}" -path: &aqua !join_path [*tools, aquatone] +path: &path !join_path [*tools, aquatone] -commands: +install_commands: - 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 - bash -c 'if [[ ! $(which unzip) ]]; then sudo apt install -y zip; fi' - unzip /tmp/aquatone/aquatone.zip -d /tmp/aquatone -- !join [mv /tmp/aquatone/aquatone, *aqua] +- !join [mv /tmp/aquatone/aquatone, *path] - 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' + +uninstall_commands: +- !join [rm, *path] \ No newline at end of file diff --git a/pipeline/tools/go.yaml b/pipeline/tools/go.yaml index 9d5dea4..d44fc8c 100644 --- a/pipeline/tools/go.yaml +++ b/pipeline/tools/go.yaml @@ -2,7 +2,10 @@ installed: false bashrc: &bashrc !join_path [!get_default "{home}", .bashrc] 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 - !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'"] + +uninstall_commands: +- !join [sudo, rm, -r, !get_default "{goroot}"] diff --git a/pipeline/tools/gobuster.yaml b/pipeline/tools/gobuster.yaml index 122347d..35edbc4 100644 --- a/pipeline/tools/gobuster.yaml +++ b/pipeline/tools/gobuster.yaml @@ -1,8 +1,12 @@ installed: false dependencies: [go, seclists] 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}"} +home: &home !get_default "{home}" -commands: +install_commands: - !join [*gotool, get github.com/OJ/gobuster] + +uninstall_commands: +- !join [rm, *path] diff --git a/pipeline/tools/luigi-service.yaml b/pipeline/tools/luigi-service.yaml index d8676c3..ff974de 100644 --- a/pipeline/tools/luigi-service.yaml +++ b/pipeline/tools/luigi-service.yaml @@ -2,11 +2,17 @@ installed: false project-dir: &proj !get_default "{project-dir}" service-file: &svcfile !join_path [*proj, luigid.service] -commands: +install_commands: - !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 start 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 \ No newline at end of file diff --git a/pipeline/tools/masscan.yaml b/pipeline/tools/masscan.yaml index 8f0b349..4078353 100644 --- a/pipeline/tools/masscan.yaml +++ b/pipeline/tools/masscan.yaml @@ -1,10 +1,13 @@ installed: false 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 - make -s -j -C /tmp/masscan -- !join [mv /tmp/masscan/bin/masscan, *masscan] +- !join [mv /tmp/masscan/bin/masscan, *path] - 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] \ No newline at end of file diff --git a/pipeline/tools/recursive-gobuster.yaml b/pipeline/tools/recursive-gobuster.yaml index a4c7358..8b267b2 100644 --- a/pipeline/tools/recursive-gobuster.yaml +++ b/pipeline/tools/recursive-gobuster.yaml @@ -1,10 +1,13 @@ installed: false dependencies: [gobuster] 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] -commands: +install_commands: - !join ["bash -c 'if [ -d", *parent, "]; then cd", *parent, "&& git fetch --all && git pull; else git clone https://github.com/epi052/recursive-gobuster.git", - *parent, " ; fi'"] \ No newline at end of file + *parent, "; fi'"] + +uninstall_commands: +- !join [sudo, rm, -r, *parent] diff --git a/pipeline/tools/searchsploit.yaml b/pipeline/tools/searchsploit.yaml index 5820341..0785c9b 100644 --- a/pipeline/tools/searchsploit.yaml +++ b/pipeline/tools/searchsploit.yaml @@ -3,15 +3,18 @@ dependencies: [exploitdb] home: &home !get_default "{home}" tools: &tools !get_default "{tools-dir}" 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"] homesploit: &homesploit !join_path [*home, ".searchsploit_rc"] sed-command: &sedcom !join_empty ["'s#/opt#", *tools, "#g'"] -commands: -- !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then ln -fs /usr/share/exploitdb", - *exploitdb, "&& ln -fs $(which searchsploit)", *searchsploit, +install_commands: +- !join ["bash -c 'if [ -d /usr/share/exploitdb ]; then sudo ln -fs /usr/share/exploitdb", + *exploitdb, "&& sudo ln -fs $(which searchsploit)", *path, "; 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", *homesploit, "]; then sed -i", *sedcom, *homesploit, "; fi'"] + +uninstall_commands: +- !join [sudo, rm, -r, *exploitdb] diff --git a/pipeline/tools/seclists.yaml b/pipeline/tools/seclists.yaml index f32e2e0..995f916 100644 --- a/pipeline/tools/seclists.yaml +++ b/pipeline/tools/seclists.yaml @@ -1,8 +1,11 @@ installed: false tools: &tools !get_default "{tools-dir}" -path: &secfile !join_path [*tools, seclists] +path: &path !join_path [*tools, seclists] -commands: -- !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;", - "else git clone https://github.com/danielmiessler/SecLists.git", *secfile, "; fi'"] \ No newline at end of file +install_commands: + - !join ["bash -c 'if [[ -d /usr/share/seclists ]]; then ln -s /usr/share/seclists", + *path, "; elif [[ -d", *path, "]] ; then cd", *path, "&& git fetch --all && git pull;", + "else git clone https://github.com/danielmiessler/SecLists.git", *path, "; fi'"] + +uninstall_commands: + - !join [sudo, rm, -r, *path] diff --git a/pipeline/tools/subjack.yaml b/pipeline/tools/subjack.yaml index 97158e9..2177aab 100644 --- a/pipeline/tools/subjack.yaml +++ b/pipeline/tools/subjack.yaml @@ -1,10 +1,13 @@ installed: false dependencies: [go] 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}"} fingerprints: !join_path [!get_default "{gopath}", src/github.com/haccer/subjack/fingerprints.json] -commands: +install_commands: - !join [*gotool, get github.com/haccer/subjack] + +uninstall_commands: +- !join [rm, *path] diff --git a/pipeline/tools/tko-subs.yaml b/pipeline/tools/tko-subs.yaml index 222efc3..35b40f4 100644 --- a/pipeline/tools/tko-subs.yaml +++ b/pipeline/tools/tko-subs.yaml @@ -1,9 +1,12 @@ installed: false dependencies: [go] 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}"} 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] + +uninstall_commands: +- !join [rm, *path] diff --git a/pipeline/tools/waybackurls.yaml b/pipeline/tools/waybackurls.yaml index da9358b..1008719 100644 --- a/pipeline/tools/waybackurls.yaml +++ b/pipeline/tools/waybackurls.yaml @@ -1,8 +1,11 @@ installed: false dependencies: [go] 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}"} -commands: -- !join [*gotool, get, github.com/tomnomnom/waybackurls] \ No newline at end of file +install_commands: +- !join [*gotool, get, github.com/tomnomnom/waybackurls] + +uninstall_commands: +- !join [rm, *path] \ No newline at end of file diff --git a/pipeline/tools/webanalyze.yaml b/pipeline/tools/webanalyze.yaml index 2361718..4c444ac 100644 --- a/pipeline/tools/webanalyze.yaml +++ b/pipeline/tools/webanalyze.yaml @@ -1,8 +1,11 @@ installed: false dependencies: [go] 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}"} -commands: +install_commands: - !join [*gotool, get github.com/rverton/webanalyze/...] + +uninstall_commands: +- !join [rm, *path] diff --git a/tests/test_tools_install/test_tools_install_command.py b/tests/test_tools_install/test_tools_install_command.py index 8888ef7..30d2d60 100644 --- a/tests/test_tools_install/test_tools_install_command.py +++ b/tests/test_tools_install/test_tools_install_command.py @@ -26,17 +26,22 @@ def onerror(func, path, exc_info): shutil.rmtree(self.tmp_path, onerror=onerror) - def perform_install(self, tools_dict, tool_name, exists=False): - pickle.dump(tools_dict, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb")) + 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")) tool = Path(tools_dict.get(tool_name).get("path")) - - if exists is False: + if install and exists is False: assert tool.exists() is False + elif not install and exists is True: + assert tool.exists() is True - utils.run_cmd(self.shell, f"install {tool_name}") - - 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): # install go in tmp location @@ -44,7 +49,7 @@ def setup_go_test(self, tool_name, tool_dict): dependency_path = f"{self.shell.tools_dir}/go/bin/go" 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 tmp_go_path = f"{self.shell.tools_dir}/mygo" @@ -54,6 +59,8 @@ def setup_go_test(self, tool_name, tool_dict): 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)["installed"] = False + return tool_dict def test_install_masscan(self): @@ -63,21 +70,26 @@ def test_install_masscan(self): tool_path = f"{self.shell.tools_dir}/{tool}" 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("commands")[4] = f"sudo setcap CAP_NET_RAW+ep {tool_path}" + tools_copy.get(tool).get("install_commands")[2] = f"mv /tmp/masscan/bin/masscan {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): tool = "amass" url = "github.com/OWASP/Amass/v3/..." 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.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): tool = "aquatone" @@ -86,9 +98,11 @@ def test_install_aquatone(self): tool_path = f"{self.shell.tools_dir}/{tool}" 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): tool = "go" @@ -97,31 +111,30 @@ def test_install_go(self): tool_path = f"{self.shell.tools_dir}/go/bin/go" 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): tool = "gobuster" dependency = "go" 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.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) - - 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")) + self.perform_add_remove(tools_copy, tool, True, False) + self.perform_add_remove(tools_copy, tool, False, True) + def pause_luigi(self): proc = subprocess.run("systemctl is-enabled luigid.service".split(), stdout=subprocess.PIPE) if proc.stdout.decode().strip() == "enabled": @@ -132,6 +145,17 @@ def test_install_luigi_service(self): if proc.stdout.decode().strip() == "active": 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(): subprocess.run("sudo rm /usr/local/bin/luigid".split()) @@ -161,6 +185,16 @@ def test_install_luigi_service(self): 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"]) def test_install_recursive_gobuster(self, test_input): tool = "recursive-gobuster" @@ -175,15 +209,19 @@ def test_install_recursive_gobuster(self, test_input): tools_copy.get(tool)["path"] = tool_path tools_copy.get(tool)["dependencies"] = None - tools_copy.get(tool).get("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("commands")[0] += "else git clone https://github.com/epi052/recursive-gobuster.git " - tools_copy.get(tool).get("commands")[0] += f"{parent} ; fi'" + tools_copy.get(tool).get("install_commands")[0] = f"bash -c 'if [ -d {parent} ]; " + tools_copy.get(tool).get("install_commands")[0] += f"then cd {parent} && git fetch --all && git pull; " + tools_copy.get(tool).get("install_commands")[ + 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": - self.perform_install(tools_copy, tool, exists=True) + self.perform_add_remove(tools_copy, tool, True, True) 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"]) def test_install_searchsploit(self, test_input): @@ -211,13 +249,15 @@ def test_install_searchsploit(self, test_input): 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'" - tools_copy.get(tool).get("commands")[0] = first_cmd + tools_copy.get(tool).get("install_commands")[0] = first_cmd + + tools_copy.get(tool).get("install_commands")[1] = f"bash -c 'if [ -f {searchsploit_rc_path} ]; " + tools_copy.get(tool).get("install_commands")[1] += f"then cp -n {searchsploit_rc_path} {home_path} ; fi'" - tools_copy.get(tool).get("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")[2] = f"bash -c 'if [ -f {copied_searchsploit_rc} ]; " + tools_copy.get(tool).get("install_commands")[2] += f"then sed -i {sed_cmd} {copied_searchsploit_rc}; fi'" - tools_copy.get(tool).get("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("uninstall_commands")[0] = f"sudo rm -r {dependency_path}" pickle.dump(tools_copy, Path(self.shell.tools_dir / ".tool-dict.pkl").open("wb")) @@ -227,11 +267,13 @@ def test_install_searchsploit(self, test_input): assert not Path(dependency_path).exists() utils.run_cmd(self.shell, f"install {tool}") - assert subprocess.run(f"grep {self.shell.tools_dir} {copied_searchsploit_rc}".split()).returncode == 0 assert Path(copied_searchsploit_rc).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"]) def test_install_seclists(self, test_input): tool = "seclists" @@ -248,53 +290,67 @@ def test_install_seclists(self, test_input): 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'" - 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": - self.perform_install(tools_copy, tool, exists=True) + self.perform_add_remove(tools_copy, tool, True, True) 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): tool = "subjack" url = "github.com/haccer/subjack" 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.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): tool = "tko-subs" url = "github.com/anshumanbh/tko-subs" 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.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): tool = "waybackurls" url = "github.com/tomnomnom/waybackurls" 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.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): tool = "webanalyze" url = "github.com/rverton/webanalyze/..." 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.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) diff --git a/tests/utils.py b/tests/utils.py index 1870b76..c58c868 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -37,4 +37,7 @@ def run_cmd(app, cmd): out = copy_cmd_stdout.getvalue() err = copy_stderr.getvalue() + print(out) + print(err) + return normalize(out), normalize(err)