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服务器的账户和密码,这样就比较安全了。