forked from ovh/the-bastion-ansible-wrapper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsshwrapper.py
executable file
·115 lines (100 loc) · 3.4 KB
/
sshwrapper.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3
import getpass
import os
import sys
from lib import find_executable, get_hostvars, get_var_within, manage_conf_file
def main():
argv = list(sys.argv[1:]) # Copy
bastion_user = None
bastion_host = None
bastion_port = None
remote_user = None
remote_port = 22
default_configuration_file = "/etc/ovh/bastion/config.yml"
cmd = argv.pop()
host = argv.pop()
# check if bastion_vars are passed as env vars in the playbook
# may be usefull if the ansible controller manage many bastions
# example :
# - hosts: all
# gather_facts: false
# environment:
# BASTION_USER: "{{ bastion_user }}"
# BASTION_HOST: "{{ bastion_host }}"
# BASTION_PORT: "{{ bastion_port }}"
#
# will result as : ... '/bin/sh -c '"'"'BASTION_USER=my_bastion_user BASTION_HOST=my_bastion_host BASTION_PORT=22 /usr/bin/python3 && sleep 0'"'"''
for i in list(cmd.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]
# in some cases (AWX in a non containerised environment for instance), the environment is overridden by the job
# so we are not able to get the BASTION vars
# if some vars are still undefined, try to load them from a configuration file
bastion_host, bastion_port, bastion_user = manage_conf_file(
os.environ.get("BASTION_CONF_FILE", default_configuration_file),
bastion_host,
bastion_port,
bastion_user,
)
# 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 = get_var_within(
hostvar.get("bastion_port", os.environ.get("BASTION_PORT", 22)), hostvar
)
bastion_user = get_var_within(
hostvar.get(
"bastion_user", os.environ.get("BASTION_USER", getpass.getuser())
),
hostvar,
)
bastion_host = get_var_within(
hostvar.get("bastion_host", os.environ.get("BASTION_HOST")), hostvar
)
for i, e in enumerate(argv):
if e.startswith("User="):
remote_user = e.split("=")[-1]
argv[i] = "User={}".format(bastion_user)
elif e.startswith("Port="):
remote_port = e.split("=")[-1]
argv[i] = "Port={}".format(bastion_port)
# syscall exec
args = (
[
"ssh",
"-p",
bastion_port,
"-q",
"-o",
"StrictHostKeyChecking=no",
"-l",
bastion_user,
bastion_host,
"-T",
]
+ argv
+ [
"--",
"-q",
"-T",
"--never-escape",
"--user",
remote_user,
"--port",
remote_port,
host,
"--",
cmd,
]
)
os.execv(
find_executable("ssh"), # full path mandatory
[str(e).strip() for e in args], # execv() arg 2 must contain only strings
)
if __name__ == "__main__":
main()