updated SSH automator for SaltStack

This commit is contained in:
Manuel Amador (Rudd-O) 2015-12-06 19:48:17 +00:00
parent 9a30a0e29b
commit e23fd6b8e2
3 changed files with 70 additions and 63 deletions

View File

@ -107,15 +107,18 @@ file to edit is in the `dom0` of the target Qubes OS machine, path
You can also integrate this plugin with SaltStack's `salt-ssh` program, by: You can also integrate this plugin with SaltStack's `salt-ssh` program, by:
1. placing the `bombshell-client`, `qrun`, `qssh` and `qscp` commands 1. placing the `bombshell-client`, `qrun` and `qssh` commands
in some directory of your path, then in some directory of your path, then
2. symlinking `ssh` to `qssh` and `scp` to `qscp`. 2. symlinking `ssh` to `qssh` and `scp` to `qssh` again, then
3. adding the `host:` attribute to the roster entry of each one of your
VMs as follows: `<VM name>.__qubes__`.
These commands will transparently attempt to SSH into a host unless it is These fake `ssh` and `scp` commands will transparently attempt to SSH
unresolvable, in which case they will assume it's a VM and fall back to into a host unless the host name ends with `.__qubes__`, in which case
using the `bombshell-client` to communicate with said presumed VM. they will assume it's a VM and fall back to using the `bombshell-client`
SaltStack's SSH-based `salt-ssh` automator will pick these fake SSH and to communicate with said presumed VM. SaltStack's SSH-based `salt-ssh`
SCP clients, and they will work transparently. automator will pick these fake SSH and SCP clients based on the path,
and they will work transparently.
Bug bounties Bug bounties
------------ ------------

View File

@ -1,24 +0,0 @@
#!/usr/bin/env python
import sys
import os
import subprocess
import socket
parms = sys.argv[1:]
try:
parmwithcolons = [x for x in parms if ":" in x][-1]
ipaddr = parmwithcolons.split(":",1)[0]
socket.inet_aton(ipaddr)
os.execv("/usr/bin/scp", ["/usr/bin/scp"] + parms)
except socket.error:
pass
path_to_this_file = os.path.dirname(__file__)
path_to_ssh = os.path.join(path_to_this_file, "qssh")
path_to_ssh = os.path.abspath(path_to_ssh)
scmd = ["/usr/bin/scp"] + ["-S", path_to_ssh] + parms
os.execvp(scmd[0], scmd)

1
bin/qscp Symbolic link
View File

@ -0,0 +1 @@
qssh

View File

@ -4,43 +4,70 @@ import sys
import os import os
import subprocess import subprocess
import socket import socket
import urllib
def find_hostname_and_command(parms):
host = None
rest = parms
while True:
if not rest:
break
if rest[0] == "--":
if host is None:
_, host, rest = rest[0], rest[1], rest[2:]
else:
_, rest = rest[0], rest[1:]
break
elif rest[0].startswith("-o") and len(rest[0]) > 2:
_, rest = rest[0], rest[1:]
elif rest[0].startswith("-o"):
_, rest = rest[0:1], rest[2:]
elif rest[0].startswith("-"):
_, rest = rest[0], rest[1:]
else:
if host is None:
host, rest = rest[0], rest[1:]
else:
break
host, port = urllib.splitport(host)
return host, rest
def is_qubes_host(host):
return host.endswith(".__qubes__")
def get_vmname_and_management_proxy(host):
host = host[:-len(".__qubes__")]
if host.endswith("__"):
host, proxy, _ = host.rsplit("__", 2)
return host, proxy
return host, None
parms = sys.argv[1:] parms = sys.argv[1:]
host, rest = find_hostname_and_command(parms)
try: if os.path.basename(sys.argv[0]) in ("scp", "qscp"):
socket.inet_aton(parms[0]) if not is_qubes_host(host):
os.execv("/usr/bin/ssh", ["/usr/bin/ssh"] + parms) os.execv("/usr/bin/scp", ["/usr/bin/scp"] + parms)
except socket.error:
pass
path_to_bombshell = os.path.abspath(os.path.join(os.path.dirname(__file__), "bombshell-client")) path_to_ssh = os.path.join(path_to_this_file, "qssh")
scmd = ["/usr/bin/scp"] + ["-S", path_to_ssh] + parms
os.execvp(scmd[0], scmd)
host = None else:
rest = parms if not is_qubes_host(host):
while True: os.execv("/usr/bin/ssh", ["/usr/bin/ssh"] + parms)
if not rest:
break
if rest[0] == "--":
if host is None:
_, host, rest = rest[0], rest[1], rest[2:]
else:
_, rest = rest[0], rest[1:]
break
elif rest[0].startswith("-o") and len(rest[0]) > 2:
_, rest = rest[0], rest[1:]
elif rest[0].startswith("-o"):
_, rest = rest[0:1], rest[2:]
elif rest[0].startswith("-"):
_, rest = rest[0], rest[1:]
else:
if host is None:
host, rest = rest[0], rest[1:]
else:
break
cmd = [ path_to_bombshell = os.path.abspath(os.path.join(os.path.dirname(__file__), "bombshell-client"))
vmname, proxy = get_vmname_and_management_proxy(host)
if proxy:
assert 0, "While connecting to %s (VM name %s): management proxy not supported yet" % (host, vmname)
cmd = [
path_to_bombshell, path_to_bombshell,
host, vmname,
] + ["sh", "-c", " ".join(rest)] ] + ["sh", "-c", " ".join(rest)]
os.execvp(cmd[0], cmd)
os.execvp(cmd[0], cmd)