1.Paramiko模块下的demo.py程序
修改后的demo.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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | #!/usr/bin/env python import base64 from binascii import hexlify import getpass import os import select import socket import sys import threading import time import traceback import paramiko import interactive def agent_auth(transport, username): """ Attempt to authenticate to the given transport using any of the private keys available from an SSH agent. """ agent = paramiko.Agent() agent_keys = agent.get_keys() if len(agent_keys) == 0: return for key in agent_keys: print 'Trying ssh-agent key %s' % hexlify(key.get_fingerprint()), try: transport.auth_publickey(username, key) print '... success!' return except paramiko.SSHException: print '... nope.' def manual_auth(username, hostname,pw): '''default_auth = 'p' auth = raw_input('Auth by (p)assword, (r)sa key, or (d)ss key? [%s] ' % default_auth) if len(auth) == 0: auth = default_auth if auth == 'r': default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') path = raw_input('RSA key [%s]: ' % default_path) if len(path) == 0: path = default_path try: key = paramiko.RSAKey.from_private_key_file(path) except paramiko.PasswordRequiredException: password = getpass.getpass('RSA key password: ') key = paramiko.RSAKey.from_private_key_file(path, password) t.auth_publickey(username, key) elif auth == 'd': default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_dsa') path = raw_input('DSS key [%s]: ' % default_path) if len(path) == 0: path = default_path try: key = paramiko.DSSKey.from_private_key_file(path) except paramiko.PasswordRequiredException: password = getpass.getpass('DSS key password: ') key = paramiko.DSSKey.from_private_key_file(path, password) t.auth_publickey(username, key) else: pw = getpass.getpass('Password for %s@%s: ' % (username, hostname)) t.auth_password(username, pw)''' t.auth_password(username,pw) # setup logging paramiko.util.log_to_file('demo.log') username = '' if len(sys.argv) > 1: hostname = sys.argv[1] if hostname.find('@') >= 0: username, hostname = hostname.split('@') else: hostname = raw_input('Hostname: ') if len(hostname) == 0: print '*** Hostname required.' sys.exit(1) port = 22 if hostname.find(':') >= 0: hostname, portstr = hostname.split(':') port = int(portstr) # now connect try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, port)) except Exception, e: print '*** Connect failed: ' + str(e) traceback.print_exc() sys.exit(1) try: t = paramiko.Transport(sock) try: t.start_client() except paramiko.SSHException: print '*** SSH negotiation failed.' sys.exit(1) try: keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) except IOError: try: keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts')) except IOError: print '*** Unable to open host keys file' keys = {} # check server's host key -- this is important. key = t.get_remote_server_key() if not keys.has_key(hostname): print '*** WARNING: Unknown host key!' elif not keys[hostname].has_key(key.get_name()): print '*** WARNING: Unknown host key!' elif keys[hostname][key.get_name()] != key: print '*** WARNING: Host key has changed!!!' sys.exit(1) else: print '*** Host key OK.' # get username '''if username == '': default_username = getpass.getuser() username = raw_input('Username [%s]: ' % default_username) if len(username) == 0: username = default_username''' #changed by xpleaf at 2015.10.9 username = sys.argv[2] password = sys.argv[3] sa_username = sys.argv[4] agent_auth(t, username) if not t.is_authenticated(): manual_auth(username, hostname,password) if not t.is_authenticated(): print '*** Authentication failed. :(' t.close() sys.exit(1) chan = t.open_session() chan.get_pty() chan.invoke_shell() print '*** Here we go!' print interactive.interactive_shell(chan,hostname,username,sa_username) chan.close() t.close() except Exception, e: print '*** Caught exception: ' + str(e.__class__) + ': ' + str(e) traceback.print_exc() try: t.close() except: pass sys.exit(1) |
修改后的interactive.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 | import socket import sys,time # windows does not have termios... try: import termios import tty has_termios = True except ImportError: has_termios = False def interactive_shell(chan,hostname,username,sa_username): if has_termios: posix_shell(chan,hostname,username,sa_username) else: windows_shell(chan) def posix_shell(chan,hostname,username,sa_username): import select date = time.strftime('%Y_%m_%d') #Here is changed! f = file('/tmp/%s_%s_record.log' % (sa_username,date),'a+') #Here is changed! record = [] #Here is changed! oldtty = termios.tcgetattr(sys.stdin) try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) chan.settimeout(0.0) while True: date = time.strftime('%Y_%m_%d %H:%M:%S') #Here is changed! r, w, e = select.select([chan, sys.stdin], [], []) if chan in r: try: x = chan.recv(1024) if len(x) == 0: print '\r\n*** EOF\r\n', break sys.stdout.write(x) sys.stdout.flush() except socket.timeout: pass if sys.stdin in r: x = sys.stdin.read(1) if len(x) == 0: break #print x record.append(x) chan.send(x) if x == '\r': #Here is changed!Follow: #print record cmd = ''.join(record).split('\r')[-2] log = "%s | %s | %s | %s\n" % (hostname,date,sa_username,cmd) f.write(log) f.flush() f.close() #Here is changed!Above: finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) # thanks to Mike Looijmans for this code def windows_shell(chan): import threading sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") def writeall(sock): while True: data = sock.recv(256) if not data: sys.stdout.write('\r\n*** EOF ***\r\n\r\n') sys.stdout.flush() break sys.stdout.write(data) sys.stdout.flush() writer = threading.Thread(target=writeall, args=(chan,)) writer.start() try: while True: d = sys.stdin.read(1) if not d: break chan.send(d) except EOFError: # user hit ^Z or F6 pass |
存放在堡垒主机下的Menus程序,这里命名为run_demo.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 | #!/usr/bin/env python import os,MySQLdb os.system('clear') print '='*35 print '''\033[32;1mWelcome to the Connecting System!\033[0m Choose the Server to connect: 1.DNS Server: 192.168.1.124 2.DHCP Server: 192.168.1.134''' print '='*35 choice = raw_input('Your choice:') if choice == '1': address = '192.168.1.124' elif choice == '2': address = '192.168.1.134' sa_user = 'yonghaoye' try: conn = MySQLdb.connect(host = 'localhost', user = 'root', \ passwd = '123456', db = 'Server_list', port = 3306) cur = conn.cursor() cur.execute("select * from users where sa = '%s'" % sa_user) qur_result = cur.fetchall() for record in qur_result: if record[3] == address: hostname = record[3] username = record[4] password = record[5] cur.close() conn.close() except MySQLdb.Error,e: print 'Mysql Error Msg:',e cmd = 'python /mnt/hgfs/Python/day6/sorftwares/paramiko-1.7.7.1/demos/demo.py %s %s %s %s' % (hostname,username,password,sa_user) os.system(cmd) |
在堡垒主机上添加数据库:
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 | 添加了下面这样的数据库 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | Server_list | | ftp_user | | linkman | | mysql | | performance_schema | | s6py | +--------------------+ 7 rows in set (0.01 sec) mysql> use Server_list Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show tables; +-----------------------+ | Tables_in_Server_list | +-----------------------+ | users | +-----------------------+ 1 row in set (0.00 sec) mysql> describe users; +-----------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | sa | char(20) | NO | | NULL | | | server_name | char(20) | NO | | NULL | | | server_address | char(20) | NO | | NULL | | | server_username | char(20) | NO | | NULL | | | server_password | char(20) | NO | | NULL | | +-----------------+------------------+------+-----+---------+----------------+ 6 rows in set (0.00 sec) mysql> selec * from users; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'selec * from users' at line 1 mysql> select * from users; +----+-----------+-------------+----------------+-----------------+-----------------+ | id | sa | server_name | server_address | server_username | server_password | +----+-----------+-------------+----------------+-----------------+-----------------+ | 1 | yonghaoye | DNS Server | 192.168.1.124 | xpleaf | 123456 | | 2 | yonghaoye | DHCP Server | 192.168.1.134 | public | 123456 | +----+-----------+-------------+----------------+-----------------+-----------------+ 2 rows in set (0.00 sec) |
就不对数据库中的内容做解释说明了,其实看了前面的示意图,再看这里的代码就可以理解了。
在堡垒主机上查看运维人员的命令操作
1 2 3 4 | xpleaf@xpleaf-machine:/tmp$ tail -f yonghaoye_2015_10_10_record.log 192.168.1.124 | 2015_10_10 00:36:44 | yonghaoye | pwd 192.168.1.124 | 2015_10_10 00:36:48 | yonghaoye | whoami 192.168.1.124 | 2015_10_10 00:37:13 | yonghaoye | echo $PATH |
可以看到,在堡垒主机上生成了一个相对应用户的命令记录日志文件,这里可以查看用户执行的每一个命令,需要注意的是,这里记录了用户名“yonghaoye”,是堡垒主机上的用户,并不是Linux服务器上面的,该用户是分配给运维人员的,因此,也再一次看到,运维人员并不知道Linux服务器的账户和密码,这样就比较安全了。