Python 13:程序:堡垒机开发

Posted 水无

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 13:程序:堡垒机开发相关的知识,希望对你有一定的参考价值。

Python 13:程序:堡垒机开发


1、需求

2、表结构

3、readme

4、目录结构

5、代码

6、测试样图 


一、需求

功能需求:

1、所有的用户操作日志要保留在数据库中(先存到redis中防止数据断线丢失)
2、每个用户登录堡垒机后,只需要选择具体要访问的设置,就连接上了,不需要再输入目标机器的访问密码
3、允许用户对不同的目标设备有不同的访问权限,例:
  1、对192.168.1.113有mysql 用户的权限
  2、对192.168.1.105有root用户的权限
  3、对192.168.1.100没任何权限
4、分组管理,即可以对设置进行分组,允许用户访问某组机器,但对组里的不同机器依然有不同的访问权限 

二、表结构

三、readme

 1 作者:zz
 2 版本: 堡垒机 示例版本 v0.1
 3 开发环境: python3.6
 4 
 5 程序介绍
 6 1、所有的用户操作日志要保留在数据库中(先存到redis中防止数据断线丢失)
 7 2、每个用户登录堡垒机后,只需要选择具体要访问的设置,就连接上了,不需要再输入目标机器的访问密码
 8 3、允许用户对不同的目标设备有不同的访问权限,例:
 9   1、对192.168.1.113有mysql 用户的权限
10   2、对192.168.1.105有root用户的权限
11   3、对192.168.1.100没任何权限
12 4、分组管理,即可以对设置进行分组,允许用户访问某组机器,但对组里的不同机器依然有不同的访问权限 
13 
14 使用说明
15 python3 bin/run.py  start_session #启动
16 python3 bin/run.py  syncdb #创建表结构
17 python3 bin/run.py  create_users -f share/examples/new_user.yml #创建堡垒机账户
18 python3 bin/run.py  create_groups -f share/examples/new_groups.yml #创建用户组
19 python3 bin/run.py  create_hosts -f  share/examples/new_hosts.yml #创建远程主机
20 python3 bin/run.py  create_bindhosts -f share/examples/new_bindhosts.yml #创建绑定主机
21 python3 bin/run.py  create_remoteusers -f share/examples/new_remoteusers.yml #创建远程主机登录方式
22 python3 bin/run.py  view_user_record # 审计用户操作命令
readme

四、目录结构

五、代码

1、bin

1 import os,sys
2 
3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
4 print(BASE_DIR)
5 sys.path.append(BASE_DIR)
6 
7 if __name__ == \'__main__\':
8     from modules.actions import excute_from_command_line
9     excute_from_command_line(sys.argv)
run.py

2、conf

 1 from modules import views
 2 
 3 actions = {
 4     \'start_session\': views.start_session, #启动s
 5     \'syncdb\': views.syncdb,  #创建表结构
 6     \'create_users\': views.create_users, #创建堡垒机账户
 7     \'create_groups\': views.create_groups,  #创建用户组
 8     \'create_hosts\': views.create_hosts,  #创建远程主机
 9     \'create_bindhosts\': views.create_bindhosts, #创建绑定主机
10     \'create_remoteusers\': views.create_remoteusers, #创建远程主机登录方式
11     \'view_user_record\': views.user_record_cmd  # 审计用户操作命令
12 }
action_registers.py
1 import os,sys
2 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
3 DB_CONN ="mysql+pymysql://root:123456@192.168.1.113:3306/bljdb?charset=utf8"
settings.py

3、modules

 1 from conf import settings
 2 from conf import action_registers
 3 from modules import utils
 4 
 5 def help_msg():
 6     \'\'\'help\'\'\'
 7     print("\\033[31;1mAvailable commands:\\033[0m")
 8     for key in action_registers.actions:
 9         print("\\t",key)
10 
11 def excute_from_command_line(argvs):
12     if len(argvs) < 2:
13         help_msg()
14         exit()
15     if argvs[1] not in action_registers.actions:
16         utils.print_err("Command [%s] does not exist!" % argvs[1], quit=True)
17     action_registers.actions[argvs[1]](argvs[1:])
actions.py
 1 from  modules import models
 2 from modules.db_conn import engine,session
 3 from modules.utils import print_err
 4 
 5 def bind_hosts_filter(vals):
 6     print(\'**>\',vals.get(\'bind_hosts\') )  #打印绑定主机信息
 7     bind_hosts = session.query(models.BindHost).filter(models.Host.hostname.in_(vals.get(\'bind_hosts\'))).all()  #从数据库中查询对应绑定主机信息
 8     if not bind_hosts: #如果不存在相应信息
 9         print_err("none of [%s] exist in bind_host table." % vals.get(\'bind_hosts\'),quit=True) #打印报错
10     return bind_hosts #返回对应bind_hosts信息
11 
12 def user_profiles_filter(vals):
13     user_profiles = session.query(models.UserProfile).filter(models.UserProfile.username.in_(vals.get(\'user_profiles\'))).all() #从数据库中查询堡垒机用户信息
14     if not user_profiles: #如果不存在相应信息
15         print_err("none of [%s] exist in user_profile table." % vals.get(\'user_profiles\'),quit=True)  #打印报错
16     return  user_profiles  #返回对应用户信息
common_filters.py
1 from sqlalchemy import create_engine,Table
2 from  sqlalchemy.orm import sessionmaker
3 from conf import settings
4 engine = create_engine(settings.DB_CONN)
5 # engine = create_engine(settings.DB_CONN,echo=True)
6 SessionCls = sessionmaker(bind=engine) #创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
7 session = SessionCls()
db_conn.py
 1 #!/usr/bin/env python
 2 
 3 # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com>
 4 #
 5 # This file is part of paramiko.
 6 #
 7 # Paramiko is free software; you can redistribute it and/or modify it under the
 8 # terms of the GNU Lesser General Public License as published by the Free
 9 # Software Foundation; either version 2.1 of the License, or (at your option)
10 # any later version.
11 #
12 # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
15 # details.
16 #
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
19 # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
20 
21 import base64
22 import getpass
23 import os
24 import socket
25 import sys
26 import traceback
27 from paramiko.py3compat import input
28 import paramiko
29 try:
30     import interactive
31 except ImportError:
32     from . import interactive
33 # now, connect and use paramiko Client to negotiate SSH2 across the connection
34 try:
35     client = paramiko.SSHClient()
36     client.load_system_host_keys()
37     client.set_missing_host_key_policy(paramiko.WarningPolicy())
38     print(\'*** Connecting...\')
39     client.connect(hostname, port, username, password)
40     chan = client.invoke_shell()
41     print(repr(client.get_transport()))
42     print(\'*** Here we go!\\n\')
43     interactive.interactive_shell(chan)
44     chan.close()
45     client.close()
46 
47 except Exception as e:
48     print(\'*** Caught exception: %s: %s\' % (e.__class__, e))
49     traceback.print_exc()
50     try:
51         client.close()
52     except:
53         pass
54     sys.exit(1)
demo_simple.py
  1 # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com>
  2 #
  3 # This file is part of paramiko.
  4 #
  5 # Paramiko is free software; you can redistribute it and/or modify it under the
  6 # terms of the GNU Lesser General Public License as published by the Free
  7 # Software Foundation; either version 2.1 of the License, or (at your option)
  8 # any later version.
  9 #
 10 # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
 11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 12 # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 13 # details.
 14 #
 15 # You should have received a copy of the GNU Lesser General Public License
 16 # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
 17 # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 18 
 19 
 20 import socket
 21 import sys
 22 from paramiko.py3compat import u
 23 from  modules import models
 24 import datetime,time
 25 import redis
 26 # windows does not have termios...
 27 try:
 28     import termios
 29     import tty
 30     has_termios = True
 31 except ImportError:
 32     has_termios = False
 33 def interactive_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording):
 34     \'\'\'
 35     :param chan:
 36     :param user_obj:
 37     :param bind_host_obj: 主机
 38     :param cmd_caches: 命令列表
 39     :param log_recording: 日志记录
 40     :return:
 41     \'\'\'
 42     # 判断是否是windows shell
 43     if has_termios:
 44         posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording)
 45     else:
 46         windows_shell(chan)
 47 def posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording):
 48     \'\'\'
 49     :param chan:
 50     :param user_obj:
 51     :param bind_host_obj:
 52     :param cmd_caches:
 53     :param log_recording:
 54     :return:
 55     \'\'\'
 56     import select
 57     oldtty = termios.tcgetattr(sys.stdin)
 58     try:
 59         tty.setraw(sys.stdin.fileno())
 60         tty.setcbreak(sys.stdin.fileno())
 61         chan.settimeout(0.0)
 62         cmd = \'\'
 63         tab_key = False
 64         while True:
 65             r, w, e = select.select([chan, sys.stdin], [], [])
 66             if chan in r:
 67                 try:
 68                     x = u(chan.recv(1024))
 69                     if tab_key:
 70                         if x not in (\'\\x07\' , \'\\r\\n\'):
 71                             #print(\'tab:\',x)
 72                             cmd += x
 73                         tab_key = False
 74                     if len(x) == 0:
 75                         sys.stdout.write(\'\\r\\n*** EOF\\r\\n\')
 76                         # test for redis to mysql
 77                         break
 78                     sys.stdout.write(x)
 79                     sys.stdout.flush()
 80                 except socket.timeout:
 81                     pass
 82             if sys.stdin in r:
 83                 x = sys.stdin.read(1)
 84                 if \'\\r\' != x:
 85                     cmd +=x
 86                 else:
 87                     print(\'cmd->:\',cmd)
 88                     user_record_cmd = user_obj.username + \'cmd\'
 89                     pool = redis.ConnectionPool(host=\'192.168.1.100\', port=6379)
 90                     user_record = [user_obj.id, bind_host_obj.id, \'cmd\', cmd,
 91                                    time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())]
 92                     r = redis.Redis(connection_pool=pool)
 93                     r.lpush(user_record_cmd, user_record)
 94                     cmd = \'\'  #清空cmd
 95                 if \'\\t\' == x:
 96                     tab_key = True
 97                 if len(x) == 0:
 98                     break
 99                 chan.send(x)
100     finally:
101         termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
102 
103 # thanks to Mike Looijmans for this code
104 def windows_shell(chan):
105     import threading
106     sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\\r\\n\\r\\n")
107     def writeall(sock):
108         while True:
109             data = sock.recv(256)
110             if not data:
111                 sys.stdout.write(\'\\r\\n*** EOF ***\\r\\n\\r\\n\')
112                 sys.stdout.flush()
113                 break
114             sys.stdout.write(data.decode())
115             sys.stdout.flush()
116     writer = threading.Thread(target=writeall, args=(chan,))
117     writer.start()
118     try:
119         while True:
120             d = sys.stdin.read(1)
121             if not d:
122                 break
123             chan.send(d)
124     except EOFError:
125         # user hit ^Z or F6
126         pass
interactive.py
  1 from sqlalchemy import create_engine,Table
  2 from sqlalchemy.ext.declarative import declarative_base
  3 from sqlalchemy import Column, Integer, String,ForeignKey,UniqueConstraint,UnicodeText,DateTime
  4 from sqlalchemy.orm import relationship
  5 from sqlalchemy import or_,and_
  6 from sqlalchemy import func
  7 from sqlalchemy_utils import ChoiceType,PasswordType
  8 
  9 Base = declarative_base() #生成一个ORM 基类
 10 
 11 #多对多关联
 12 #多对多关联:绑定主机和用户组
 13 BindHost2Group = Table(\'bindhost_2_group\',Base.metadata,
 14     Column(\'bindhost_id\',ForeignKey(\'bind_host.id\'),primary_key=True),
 15     Column(\'group_id\',ForeignKey(\'groups.id\'),primary_key=True),
 16 )
 17 #多对多关联:绑定主机和堡垒机用户
 18 BindHost2UserProfile = Table(\'bindhost_2_userprofile\',Base.metadata,
 19     Column(\'bindhost_id\',ForeignKey(\'bind_host.id\'),primary_key=True),
 20     Column(\'uerprofile_id\',ForeignKey(\'user_profile.id\'),primary_key=True),
 21 )
 22 #多对多关联:用户组和堡垒机用户
 23 Group2UserProfile = Table(\'group_2_userprofile\',Base.metadata,
 24     Column(\'userprofile_id\',ForeignKey(\'user_profile.id\'),primary_key=True),
 25     Column(\'group_id\',ForeignKey(\'groups.id\'),primary_key=True),
 26 )
 27 
 28 class BindHost(Base):
 29     \'\'\'绑定主机(IP和用户联合唯一),
 30        192.168.1.1 mysql
 31        10.5.1.6    root\'\'\'
 32     __tablename__ = \'bind_host\'  #表名
 33     id = Column(Integer,primary_key=True,autoincrement=True)
 34     host_id = Column(Integer,ForeignKey(\'host.id\'))  #外键关联host.id
 35     remoteuser_id = Column(Integer,ForeignKey(\'remote_user.id\'))  #外键关联remote_user.id
 36 
 37     host = relationship("Host")  #通过host字段查询host表中相关数据
 38     remoteuser = relationship("RemoteUser")  #Python之路,Day13 - 堡垒机

D13——C语言基础学PYTHON

Python_堡垒机开发基础

day13--开发堡垒机

Python自动化开发学习12-堡垒机开发

python 之路,Day27 - 主机管理+堡垒机系统开发