Created
February 4, 2020 15:54
-
-
Save mbruzek/f5304105b86dc257b0b816f45ce35546 to your computer and use it in GitHub Desktop.
Automating an un-automatable network switch required some creative programming. Create an SSH session inside a pseudo terminal (pty), then read and write the file descriptor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import argparse | |
import getpass | |
import os | |
import pty | |
import re | |
import sys | |
import time | |
commands_iterator = None | |
logfile = None | |
ssh_password = None | |
def interact(fd): | |
""" The function that operates on the pty session's file descriptor. """ | |
password_pattern = b"(.+)@(.+)'s password: " | |
prompt_pattern = b"[$#>]\s+$" | |
# The spawn command recommends reading 1024 bytes at a time. | |
data = os.read(fd, 1024) | |
if re.search(password_pattern, data): | |
# The ssh password prompt signature found, write the password. | |
os.write(fd, (ssh_password + "\n").encode("utf-8")) | |
elif re.search(prompt_pattern, data): | |
# The prompt signature was found, write the next command. | |
os.write(fd, next(commands_iterator).encode("utf-8")) | |
if logfile: | |
logfile.write(data) | |
logfile.flush() | |
return data | |
def main(): | |
""" The main function makes this script an applicaiton. """ | |
parser = argparse.ArgumentParser(description="Use a pseudo terminal (pty) to run a list of commands via ssh.") | |
parser.add_argument("-u", "--user", help="the user to use for ssh") | |
parser.add_argument("-a", "--address", help="the host address to ssh to") | |
parser.add_argument("-p", "--password", help="the ssh password to use") | |
parser.add_argument("file", help="the path to the file of commands") | |
args = parser.parse_args() | |
if not os.path.isfile(args.file): | |
print("The path to the commands file does not exist.") | |
exit(-1) | |
with open(args.file) as commands_file: | |
global command_iterator | |
commands_iterator = iter(commands_file.readlines()) | |
logfilename = "{0}.log".format(os.path.splitext(args.file)[0]) | |
global logfile | |
logfile = open(logfilename, "ab") | |
global ssh_password | |
if args.password: | |
ssh_password = args.password | |
else: | |
ssh_password = getpass.getpass() | |
ssh = [ | |
"ssh", | |
"-o StrictHostKeyChecking=no", | |
"{0}@{1}".format(args.user, args.address) | |
] | |
# Spawn a new ssh session within a pty, the interact function will read and write to the file descriptor. | |
pty.spawn(ssh, interact) | |
print("{0} completed successfully.".format(sys.argv[0])) | |
sys.exit(0) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment