forked from ovh/the-bastion-ansible-wrapper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scpwrapper.py
executable file
·99 lines (85 loc) · 2.76 KB
/
scpwrapper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
import getpass
import os
import sys
from lib import find_executable, get_hostvars
def main():
argv = list(sys.argv[1:]) # Copy
bastion_user = None
bastion_host = None
bastion_port = None
remote_user = None
remote_port = 22
iteration = enumerate(argv)
sshcmdline = []
for i, e in iteration:
if e == "-l":
remote_user = argv[i + 1]
next(iteration)
elif e == "-p":
remote_port = argv[i + 1]
next(iteration)
elif e == "-o" and argv[i + 1].startswith("User="):
remote_user = argv[i + 1].split("=")[-1]
next(iteration)
elif e == "-o" and argv[i + 1].startswith("Port="):
remote_port = argv[i + 1].split("=")[-1]
next(iteration)
elif e == "--":
sshcmdline.extend(argv[i + 1 :])
break
else:
sshcmdline.append(e)
scpcmd = sshcmdline.pop()
host = sshcmdline.pop()
scpcmd = scpcmd.replace("#", "##").replace(" ", "#")
# check if bastion_vars are passed as env vars in the playbook
# may be usefull if the ansible controller manage many bastions
for i in list(scpcmd.split(" ")):
if "bastion_user" in i.lower():
bastion_user = i.split("=")[1]
elif "bastion_host" in i.lower():
bastion_host = i.split("=")[1]
elif "bastion_port" in i.lower():
bastion_port = i.split("=")[1]
# lookup on the inventory may take some time, depending on the source, so use it only if not defined elsewhere
# it seems like some module like template does not send env vars too...
if not bastion_host or not bastion_port or not bastion_user:
hostvar = get_hostvars(host) # dict
bastion_port = hostvar.get("bastion_port", os.environ.get("BASTION_PORT", 22))
bastion_user = hostvar.get(
"bastion_user", os.environ.get("BASTION_USER", getpass.getuser())
)
bastion_host = hostvar.get("bastion_host", os.environ.get("BASTION_HOST"))
# syscall exec
args = (
[
"ssh",
"{}@{}".format(bastion_user, bastion_host),
"-p",
bastion_port,
"-o",
"StrictHostKeyChecking=no",
"-T",
]
+ sshcmdline
+ [
"--",
"--user",
remote_user,
"--port",
remote_port,
"--host",
host,
"--osh",
"scp",
"--scp-cmd",
scpcmd,
]
)
os.execv(
find_executable("ssh"), # absolute path mandatory
[str(e).strip() for e in args], # execv() arg 2 must contain only strings
)
if __name__ == "__main__":
main()