-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaz_ssh_wrapper.py
85 lines (61 loc) · 2.4 KB
/
az_ssh_wrapper.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
#!/usr/bin/env python3
# SPDX-FileCopyrightText: © 2024 David Wales, South Western Sydney Primary Health Network
#
# SPDX-License-Identifier: MIT
import getopt
import os
import shutil
import sys
def usage():
usage = """
SSH wrapper for az ssh
Usage:
This wrapper emulates OpenSSH, but translates the arguments and
supplies them to az ssh so that it can be used by Ansible as the
ansible_ssh_executable.
It also filters out ControlMaster and ControlPersist options, as these
appear to block for the duration of the specified ControlPersist value
when passed to az ssh. See the following GitHub issue for details:
https://github.com/Azure/azure-cli-extensions/issues/7285
This wrapper supports all arguments supported by OpenSSH 8.9p1:
az-ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
[-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
[-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
[-i identity_file] [-J [user@]host[:port]] [-L address]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-Q query_option] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] destination [command [argument ...]]
See the ssh man page for details.
Example:
az-ssh 1.2.3.4
"""
print(usage)
def opt_filter(opt):
"""Filter out options which cause problems for az ssh
For some reason, setting the Control* options causes az ssh to hang
for the duration of ControlPersist"""
return not (opt[0] == "-o" and opt[1].startswith("Control"))
def main():
options = "46AaCfGgKkMNnqsTtVvXxYyB:b:c:D:E:e:f:I:i:J:L:l:m:O:o:p:Q:R:S:W:w:"
try:
opts, args = getopt.getopt(sys.argv[1:], options)
destination = args.pop(0)
except (getopt.GetoptError, IndexError) as err:
print(f"Error: {err}")
usage()
sys.exit(2)
az_path = shutil.which("az")
# Work around quoting issue on Windows (still works on Linux)
az_path = f'"{az_path}"'
ssh_opts = []
for opt in filter(opt_filter, opts):
# Only keep truthy options. e.g.
# ('-t', '') --> ('t',)
# (Yes, this is important.)
ssh_opts += filter(lambda o: o, opt)
exec_args = [az_path, "ssh", "vm", "--ip", destination]
if ssh_opts or args:
exec_args.extend(["--", *ssh_opts, *args])
os.execvp("az", exec_args)
if __name__ == "__main__":
main()