Windows SSH improvements: Caldera in background thanks to WMI. More reliable SSH connections thanks to retries.

pull/3/head
Thorsten Sick 4 years ago
parent 3bcb7ea1f9
commit ad3809092c

@ -436,7 +436,7 @@ class CalderaControl():
# Link, chain and stuff # Link, chain and stuff
def is_operation_finished(self, opid, debug=True): def is_operation_finished(self, opid, debug=False):
""" Checks if an operation finished - finished is not necessary successful ! """ Checks if an operation finished - finished is not necessary successful !
@param opid: Operation id to check @param opid: Operation id to check

@ -477,9 +477,10 @@ class Machine():
src = os.path.join(self.abs_machinepath_external, "splunkd.go") # sandcat.go local name src = os.path.join(self.abs_machinepath_external, "splunkd.go") # sandcat.go local name
self.vm_manager.put(src, dst) self.vm_manager.put(src, dst)
cmd = self.__install_caldera_service_cmd().strip() # cmd = self.__install_caldera_service_cmd().strip()
cmd = self.__wmi_cmd_for_caldera_implant()
print(cmd) print(cmd)
self.vm_manager.remote_run(cmd, disown=False) self.vm_manager.remote_run(cmd, disown=True)
if self.get_os() == "linux": if self.get_os() == "linux":
dst = self.vm_manager.get_playground() dst = self.vm_manager.get_playground()
@ -498,6 +499,20 @@ class Machine():
return self.config.os() return self.config.os()
def __wmi_cmd_for_caldera_implant(self):
""" Creates a windows specific command to start the caldera implant in background using wmi """
playground = self.vm_manager.get_playground()
if playground: # Workaround for Windows: Can not set target dir for fabric-put in Windows. Only default (none=user) dir available.
playground = playground + "\\"
else:
playground = "%userprofile%\\"
url = "http://" + self.caldera_server + ":8888"
res = f'wmic process call create "{playground}splunkd.go -server {url} -group {self.config.caldera_group()} -paw {self.config.caldera_paw()}" '
return res
def __install_caldera_service_cmd(self): def __install_caldera_service_cmd(self):
playground = self.vm_manager.get_playground() playground = self.vm_manager.get_playground()
@ -547,7 +562,7 @@ START {playground}{filename} -server {url} -group {self.config.caldera_group()}
filename = os.path.join(self.abs_machinepath_external, "caldera_agent.bat") filename = os.path.join(self.abs_machinepath_external, "caldera_agent.bat")
with open(filename, "wt") as fh: with open(filename, "wt") as fh:
fh.write(content) fh.write(content)
print(f"{CommandlineColors.OKGREEN}Installed Caldera service {CommandlineColors.ENDC}") print(f"{CommandlineColors.OKGREEN}Installed Caldera server {CommandlineColors.ENDC}")
def set_caldera_server(self, server): def set_caldera_server(self, server):
""" Set the local caldera server config """ """ Set the local caldera server config """

@ -8,7 +8,9 @@ import vagrant
from fabric import Connection from fabric import Connection
import os import os
from app.exceptions import ConfigurationError from app.exceptions import ConfigurationError
from app.exceptions import NetworkError
from invoke.exceptions import UnexpectedExit from invoke.exceptions import UnexpectedExit
import paramiko
# Experiment with paramiko instead of fabric. Seems fabric has some issues with the "put" command to Windows. There seems no fix (just my workarounds). Maybe paramiko is better. # Experiment with paramiko instead of fabric. Seems fabric has some issues with the "put" command to Windows. There seems no fix (just my workarounds). Maybe paramiko is better.
@ -111,11 +113,21 @@ class VagrantPlugin(MachineryPlugin):
print("Vagrant plugin remote run: " + cmd) print("Vagrant plugin remote run: " + cmd)
print("Disown: " + str(disown)) print("Disown: " + str(disown))
result = None result = None
try: retry = 2
result = self.c.run(cmd, disown=disown) while retry > 0:
print(result) try:
except UnexpectedExit: result = self.c.run(cmd, disown=disown)
return "Unexpected Exit" print(result)
except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit):
if retry <= 0:
raise(NetworkError)
else:
self.disconnect()
self.connect()
retry -= 1
print("Got some SSH errors. Retrying")
else:
break
if result and result.stderr: if result and result.stderr:
print("Debug: Stderr: " + str(result.stderr.strip())) print("Debug: Stderr: " + str(result.stderr.strip()))
@ -136,12 +148,23 @@ class VagrantPlugin(MachineryPlugin):
print(f"{src} -> {dst}") print(f"{src} -> {dst}")
res = "" res = ""
try: retry = 2
res = self.c.put(src, dst) while retry > 0:
except UnexpectedExit: try:
pass res = self.c.put(src, dst)
except FileNotFoundError as e: except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit):
print(e) if retry <= 0:
raise (NetworkError)
else:
self.disconnect()
self.connect()
retry -= 1
print("Got some SSH errors. Retrying")
except FileNotFoundError as e:
print(e)
break
else:
break
return res return res
@ -153,11 +176,23 @@ class VagrantPlugin(MachineryPlugin):
""" """
self.connect() self.connect()
res = "" retry = 2
try: while retry > 0:
res = self.c.get(src, dst) try:
except UnexpectedExit: res = self.c.get(src, dst)
pass except (paramiko.ssh_exception.NoValidConnectionsError, UnexpectedExit):
if retry <= 0:
raise (NetworkError)
else:
self.disconnect()
self.connect()
retry -= 1
print("Got some SSH errors. Retrying")
except FileNotFoundError as e:
print(e)
break
else:
break
return res return res

Loading…
Cancel
Save