python学习笔记_week13

1、前景介绍

到目前为止,不少公司对堡垒机依然不太感冒,实际上是没有充分认识到堡垒机在IT管理中的重要做用的,不少人以为,堡垒机就是跳板机,其实这个认识是不全面的,跳板功能只是堡垒机所具有的功能属性中的其中一项而已,下面我就给你们介绍一下堡垒机的重要性,以帮助你们参考本身公司的业务是否须要部署堡垒机。mysql

堡垒机有如下两个相当重要的功能:ios

(一)权限管理

当你公司的服务器变的愈来愈多后,须要操做这些服务器的人就确定不仅是一个运维人员,同时也可能包括多个开发人员,那么这么多的人操做业务系统,若是权限分配不当就会存在很大的安全风险,举几个场景例子:git

  1. 设想大家公司有300台Linux服务器,A开发人员须要登陆其中5台WEB服务器查看日志或进行问题追踪等事务,同时对另外10台hadoop服务器有root权限,在有300台服务器规模的网络中,按常理来说你是已经使用了ldap权限统一认证的,你如何使这个开发人员只能以普通用户的身份登陆5台web服务器,而且同时容许他以管理员的身份登陆另外10台hadoop服务器呢?而且同时他对其它剩下的200多台服务器没有访问权限github

  2. 目前据我了解,不少公司的运维团队为了方面,整个运维团队的运维人员仍是共享同一套root密码,这样内部信任机制虽然使你们的工做方便了,但同时存在着极大的安全隐患,不少状况下,一个运维人员只须要管理固定数量的服务器,毕竟公司分为不一样的业务线,不一样的运维人员管理的业务线也不一样,但若是共享一套root密码,其实就等于无限放大了每一个运维人员的权限,也就是说,若是某个运维人员想干坏事的话,他能够在几分钟内把整个公司的业务停转,甚至数据都给删除掉。为了下降风险,因而有人想到,把不一样业务线的root密码改掉就ok了么,也就是每一个业务线的运维人员只知道本身的密码,这固然是最简单有效的方式,但问题是若是你同时用了ldap,这样作又比较麻烦,即便你设置了root不经过ldap认证,那新问题就是,每次有运维人员离职,他所在的业务线的密码都须要从新改一次。web

其实上面的问题,我以为能够很简单的经过堡垒机来实现,收回全部人员的直接登陆服务器的权限,全部的登陆动做都经过堡垒机受权,运维人员或开发人员不知道远程服务器的密码,这些远程机器的用户信息都绑定在了堡垒机上,堡垒机用户只能看到他能用什么权限访问哪些远程服务器。sql

在回收了运维或开发人员直接登陆远程服务器的权限后,其实就等于大家公司生产系统的全部认证过程都经过堡垒机来完成了,堡垒机等于成了大家生产系统的SSO(single sign on)模块了。你只须要在堡垒机上添加几条规则就能实现如下权限控制了:shell

  1. 容许A开发人员经过普通用户登陆5台web服务器,经过root权限登陆10台hadoop服务器,但对其他的服务器无任务访问权限数据库

  2. 多个运维人员能够共享一个root帐户,可是依然能分辨出分别是谁在哪些服务器上操做了哪些命令,由于堡垒机帐户是每一个人独有的,也就是说虽然全部运维人员共享了一同一个远程root帐户,但因为他们用的堡垒帐户都是本身独有的,所以依然能够经过堡垒机控制每一个运维人员访问不一样的机器。ubuntu

(二)审计管理

审计管理其实很简单,就是把用户的全部操做都纪录下来,以备往后的审计或者事故后的追责。在纪录用户操做的过程当中有一个问题要注意,就是这个纪录对于操做用户来说是不可见的,什么意思?就是指,不管用户愿不肯意,他的操做都会被纪录下来,而且,他本身若是不想操做被纪录下来,或想删除已纪录的内容,这些都是他作不到的,这就要求操做日志对用户来说是不可见和不可访问的,经过堡垒机就能够很好的实现。windows

2、堡垒机架构 

堡垒机的主要做用权限控制和用户行为审计,堡垒机就像一个城堡的大门,城堡里的全部建筑就是你不一样的业务系统 , 每一个想进入城堡的人都必须通过城堡大门并通过大门守卫的受权,每一个进入城堡的人必须且只能严格按守卫的分配进入指定的建筑,且每一个建筑物还有本身的权限访问控制,不一样级别的人能够到建筑物里不一样楼层的访问级别也是不同的。还有就是,每一个进入城堡的人的全部行为和足迹都会被严格的监控和纪录下来,一旦发生犯罪事件,城堡管理人员就能够经过这些监控纪录来追踪责任人。 

 

 

堡垒要想成功彻底记到他的做用,只靠堡垒机自己是不够的, 还须要一系列安全上对用户进行限制的配合,堡垒机部署上后,同时要确保你的网络达到如下条件:

  • 全部人包括运维、开发等任何须要访问业务系统的人员,只能经过堡垒机访问业务系统
    • 回收全部对业务系统的访问权限,作到除了堡垒机管理人员,没有人知道业务系统任何机器的登陆密码
    • 网络上限制全部人员只能经过堡垒机的跳转才能访问业务系统 
  • 确保除了堡垒机管理员以外,全部其它人对堡垒机自己无任何操做权限,只有一个登陆跳转功能
  • 确保用户的操做纪录不能被用户本身以任何方式获取到并篡改 

3、堡垒机功能实现需求

业务需求:

  1. 兼顾业务安全目标与用户体验,堡垒机部署后,不该使用户访问业务系统的访问变的复杂,不然工做将很难推动,由于没人喜欢改变现状,尤为是改变后生活变得更艰难
  2. 保证堡垒机稳定安全运行, 没有100%的把握,不要上线任何新系统,即便有100%把握,也要作好最坏的打算,想好故障预案

功能需求:

  1. 全部的用户操做日志要保留在数据库中
  2. 每一个用户登陆堡垒机后,只须要选择具体要访问的设置,就链接上了,不须要再输入目标机器的访问密码
  3. 容许用户对不一样的目标设备有不一样的访问权限,例:
    1. 对10.0.2.34 有mysql 用户的权限
    2. 对192.168.3.22 有root用户的权限
    3. 对172.33.24.55 没任何权限
  4. 分组管理,便可以对设置进行分组,容许用户访问某组机器,但对组里的不一样机器依然有不一样的访问权限 

 设计表结构

 

ssh公钥登陆过程

使用密码登陆,每次都必须输入密码,很是麻烦。好在SSH还提供了公钥登陆,能够省去输入密码的步骤。

所谓"公钥登陆",原理很简单,就是用户将本身的公钥储存在远程主机上。登陆的时候,远程主机会向用户发送一段随机字符串,用户用本身的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,若是成功,就证实用户是可信的,直接容许登陆shell,再也不要求密码。

这种方法要求用户必须提供本身的公钥。若是没有现成的,能够直接用ssh-keygen生成一个:

  $ ssh-keygen

运行上面的命令之后,系统会出现一系列提示,能够一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),若是担忧私钥的安全,这里能够设置一个。

运行结束之后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。

这时再输入下面的命令,将公钥传送到远程主机host上面:

  $ ssh-copy-id user@host

好了,今后你再登陆,就不须要输入密码了。

s_it.py

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

action_registers.py

 1 from modules import views  2 actions = {  3     'start_session': views.start_session,  4     # 'stop': views.stop_server,
 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 Code

settiongs.py

1 Conn_Params = "mysql+pymysql://root:123456@192.168.211.129/JBSdb?charset=utf8"
View Code

models.py

 1 from sqlalchemy import Table, Column, Integer,String,Enum,DATE, ForeignKey,UniqueConstraint #Enum枚举
 2 from sqlalchemy.orm import relationship  3 from sqlalchemy.ext.declarative import declarative_base  4 from sqlalchemy_utils import ChoiceType,PasswordType #PasswordType 能够md5,但很差使
 5 from sqlalchemy import create_engine  6 # from sqlalchemy.orm import sessionmaker
 7 Base = declarative_base() #基类
 8 user_m2m_bindhost = Table('user_m2m_bindhost', Base.metadata,  9                         Column('userprofile_id',Integer,ForeignKey('user_profile.id')), 10                         Column('bindhost_id',Integer,ForeignKey('bind_host.id')), 11  ) 12 bindhost_m2m_hostgroup = Table('bindhost_m2m_hostgroup', Base.metadata, 13                         Column('bindhost_id',Integer,ForeignKey('bind_host.id')), 14                         Column('hostgroup_id',Integer,ForeignKey('host_group.id')), 15  ) 16 host_m2m_remoteuser = Table('host_m2m_remoteuser', Base.metadata, 17                         Column('host_id',Integer,ForeignKey('host.id')), 18                         Column('remoteuser_id',Integer,ForeignKey('remote_user.id')), 19  ) 20 user_m2m_hostgroup = Table('userprofile_m2m_hostgroup', Base.metadata, 21                         Column('userprofile_id',Integer,ForeignKey('user_profile.id')), 22                         Column('hostgroup_id',Integer,ForeignKey('host_group.id')), 23  ) 24 class Host(Base): 25     __tablename__="host"
26     id=Column(Integer,primary_key=True) 27     hostname=Column(String(64),unique=True) 28     ip=Column(String(64),unique=True) 29     port=Column(Integer,default=22) 30     remote_users=relationship("RemoteUser",secondary=host_m2m_remoteuser,backref="hosts") 31     def __repr__(self): 32         return self.hostname 33 class HostGroup(Base): 34     __tablename__ = "host_group"
35     id = Column(Integer, primary_key=True) 36     name = Column(String(64), unique=True) 37     bind_hosts=relationship("BindHost",secondary="bindhost_m2m_hostgroup",backref="host_groups") 38     def __repr__(self): 39         return self.name 40 class RemoteUser(Base): 41     __tablename__ = "remote_user"
42     __table_args__ = (UniqueConstraint('auth_type', 'username', 'password', name='_user_passwd_uc'),)#联合惟一
43     AuthTypes = [ 44         ('ssh-password', 'SSH/Password'),#第一个是真正存到数据库的,第二个是显示给咱们看的
45         ('ssh-key', 'SSH/KEY'), 46  ] 47     id = Column(Integer, primary_key=True) 48     auth_type = Column(ChoiceType(AuthTypes)) 49     username = Column(String(32), nullable=False) 50     password=Column(String(128)) #没有md5
51     def __repr__(self): 52         return self.username 53 class BindHost(Base): 54     '''
55  192.168.1.11 web bj_group 56  192.168.1.11 mysql sh_group 57     '''
58     __tablename__ = "bind_host"
59     __table_args__ = (UniqueConstraint('host_id', 'remoteuser_id', name='host_remoteuser_uc'),) 60     id = Column(Integer, primary_key=True) 61     host_id = Column(Integer, ForeignKey('host.id')) 62     #group_id = Column(Integer, ForeignKey('group.id'))
63     remoteuser_id = Column(Integer, ForeignKey('remote_user.id')) 64     host=relationship("Host",backref="binf_hosts") 65     #host_group=relationship("HostGroup",backref="bind_hosts")
66     remote_user=relationship("RemoteUser",backref="binf_hosts") 67     def __repr__(self): 68         return "<%s -- %s >"%(self.host.ip, 69  self.remote_user.username, 70  ) 71 class UserProfile(Base): 72     __tablename__ = "user_profile"
73     id = Column(Integer, primary_key=True) 74     username = Column(String(32), unique=True,nullable=False) 75     password = Column(String(128)) 76     bind_hosts=relationship("BindHost",secondary="user_m2m_bindhost",backref="user_profiles") 77     host_groups=relationship("HostGroup",secondary="userprofile_m2m_hostgroup",backref="user_profiles") 78     def __repr__(self): 79         return self.username 80 # class AuditLog(Base):
81 # pass
View Code

models_v2.py

 1 from sqlalchemy import Table, Column, Integer,String,Enum,DATE, ForeignKey,UniqueConstraint #Enum枚举
 2 from sqlalchemy.orm import relationship  3 from sqlalchemy.ext.declarative import declarative_base  4 from sqlalchemy_utils import ChoiceType,PasswordType #PasswordType 能够md5,但很差使
 5 # from sqlalchemy import create_engine
 6 # from sqlalchemy.orm import sessionmaker
 7 Base = declarative_base() #基类
 8 user_m2m_bindhost = Table('user_m2m_bindhost', Base.metadata,  9                         Column('userprofile_id',Integer,ForeignKey('user_profile.id')), 10                         Column('bindhost_id',Integer,ForeignKey('bind_host.id')), 11  ) 12 host_m2m_remoteuser = Table('host_m2m_remoteuser', Base.metadata, 13                         Column('host_id',Integer,ForeignKey('host.id')), 14                         Column('remoteuser_id',Integer,ForeignKey('remote_user.id')), 15  ) 16 class Host(Base): 17     __tablename__="host"
18     id=Column(Integer,primary_key=True) 19     hostname=Column(String(64),unique=True) 20     ip=Column(String(64),unique=True) 21     port=Column(Integer,default=22) 22     remote_users=relationship("RemoteUser",sencondary=host_m2m_remoteuser,backref="hosts") 23     def __repr__(self): 24         return self.hostname 25 class HostGroup(Base): 26     __tablename__ = "host_group"
27     id = Column(Integer, primary_key=True) 28     name = Column(String(64), unique=True) 29     def __repr__(self): 30         return self.name 31 class RemoteUser(Base): 32     __tablename__ = "romote_user"
33     __table_args__ = (UniqueConstraint('auth_type', 'username', 'password', name='_user_passwd_uc'),)#联合惟一
34     AuthTypes = [ 35         ('ssh-passwd', 'SSH/Password'),#第一个是真正存到数据库的,第二个是显示给咱们看的
36         ('ssh-key', 'SSH/KEY'), 37  ] 38     id = Column(Integer, primary_key=True) 39     auth_type = Column(ChoiceType(AuthTypes)) 40     username = Column(String(32), unique=True) 41     password=Column(String(128)) #没有md5
42     def __repr__(self): 43         return self.username 44 class BindHost(Base): 45     '''
46  192.168.1.11 web bj_group 47  192.168.1.11 mysql sh_group 48     '''
49     __tablename__ = "bind_host"
50     __table_args__ = (UniqueConstraint('host_id', 'group_id', 'remoteuser_id', name='host_group_remoteuser_uc'),) 51     id = Column(Integer, primary_key=True) 52     host_id = Column(Integer, ForeignKey('host.id')) 53     group_id = Column(Integer, ForeignKey('group.id')) 54     remoteuser_id = Column(Integer, ForeignKey('remote_user.id')) 55     host=relationship("Host",backref="binf_hosts") 56     host_group=relationship("HostGroup",backref="binf_hosts") 57     remote_user=relationship("RemoteUser",backref="binf_hosts") 58     def __repr__(self): 59         return "<%s -- %s -- %s>"%(self.host.ip, 60  self.remote_user.username, 61  self.host_group.name) 62 class UserProfile(Base): 63     __tablename__ = "user_profile"
64     id = Column(Integer, primary_key=True) 65     username = Column(String(32), unique=True) 66     password = Column(String(128)) 67     bind_hosts=relationship("BindHost",secondary="user_m2m_bindhost",backref="user_profiles") 68     def __repr__(self): 69         return self.username 70 class AuditLog(Base): 71     pass
View Code

actions.py

 1 from conf import settings  2 from conf import action_registers  3 from modules import utils  4 def help_msg():  5     '''
 6  print help msgs  7  :return:  8     '''
 9     print("\033[31;1mAvailable commands:\033[0m") 10     for key in action_registers.actions: 11         print("\t",key) 12 def excute_from_command_line(argvs): 13     if len(argvs) < 2: 14  help_msg() 15  exit() 16     if argvs[1] not in action_registers.actions: 17         utils.print_err("Command [%s] does not exist!" % argvs[1], quit=True) 18     action_registers.actions[argvs[1]](argvs[1:])
View Code

common_filters.py

 1 from models import models  2 from modules.db_conn import engine,session  3 from modules.utils import print_err  4 def bind_hosts_filter(vals):  5     print('**>',vals.get('bind_hosts') )  6     bind_hosts = session.query(models.BindHost).filter(models.Host.hostname.in_(vals.get('bind_hosts'))).all()  7     if not bind_hosts:  8         print_err("none of [%s] exist in bind_host table." % vals.get('bind_hosts'),quit=True)  9     return bind_hosts 10 def user_profiles_filter(vals): 11     user_profiles = session.query(models.UserProfile).filter(models.UserProfile.username.in_(vals.get('user_profiles')) 12  ).all() 13     if not user_profiles: 14         print_err("none of [%s] exist in user_profile table." % vals.get('user_profiles'),quit=True) 15     return  user_profiles
View Code

db_conn.py

1 from sqlalchemy import create_engine,Table 2 from  sqlalchemy.orm import sessionmaker 3 from conf import settings 4 engine = create_engine(settings.Conn_Params) 5 #engine = create_engine(settings.DB_CONN,echo=True)
6 SessionCls = sessionmaker(bind=engine) #建立与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
7 session = SessionCls()
View Code

interactive.py

 1 import socket  2 import sys  3 from paramiko.py3compat import u  4 from models import models  5 import datetime  6 # windows does not have termios...
 7 try:  8     import termios  9     import tty 10     has_termios = True 11 except ImportError: 12     has_termios = False 13 def interactive_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording): 14     if has_termios: 15  posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording) 16     else: 17  windows_shell(chan) 18 def posix_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording): 19     import select 20     oldtty = termios.tcgetattr(sys.stdin) 21     try: 22  tty.setraw(sys.stdin.fileno()) 23  tty.setcbreak(sys.stdin.fileno()) 24         chan.settimeout(0.0) 25         cmd = ''
26         tab_key = False 27         while True: 28             r, w, e = select.select([chan, sys.stdin], [], []) 29             if chan in r: 30                 try: 31                     x = u(chan.recv(1024)) 32                     if tab_key: 33                         if x not in ('\x07' , '\r\n'): 34                             #print('tab:',x)
35                             cmd += x 36                         tab_key = False 37                     if len(x) == 0: 38                         sys.stdout.write('\r\n*** EOF\r\n') 39                         break
40  sys.stdout.write(x) 41  sys.stdout.flush() 42                 except socket.timeout: 43                     pass
44             if sys.stdin in r: 45                 x = sys.stdin.read(1) 46                 if '\r' != x: 47                     cmd +=x 48                 else: 49                     print('cmd->:',cmd) 50                     log_item = models.AuditLog(user_id=user_obj.id, 51                                           bind_host_id=bind_host_obj.id, 52                                           action_type='cmd', 53                                           cmd=cmd , 54                                           date=datetime.datetime.now() 55  ) 56  cmd_caches.append(log_item) 57                     cmd = ''
58                     if len(cmd_caches)>=10: 59  log_recording(user_obj,bind_host_obj,cmd_caches) 60                         cmd_caches = [] 61                 if '\t' == x: 62                     tab_key = True 63                 if len(x) == 0: 64                     break
65  chan.send(x) 66     finally: 67  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) 68 # thanks to Mike Looijmans for this code
69 def windows_shell(chan): 70     import threading 71     sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n") 72     def writeall(sock): 73         while True: 74             data = sock.recv(256) 75             if not data: 76                 sys.stdout.write('\r\n*** EOF ***\r\n\r\n') 77  sys.stdout.flush() 78                 break
79  sys.stdout.write(data) 80  sys.stdout.flush() 81     writer = threading.Thread(target=writeall, args=(chan,)) 82  writer.start() 83     try: 84         while True: 85             d = sys.stdin.read(1) 86             if not d: 87                 break
88  chan.send(d) 89     except EOFError: 90         # user hit ^Z or F6
91         pass
View Code

ssh_login.py

 1 import base64  2 import getpass  3 import os  4 import socket  5 import sys  6 import traceback  7 from paramiko.py3compat import input  8 from models import models  9 import datetime 10 import paramiko 11 try: 12     import interactive 13 except ImportError: 14     from . import interactive 15 def ssh_login(user_obj,bind_host_obj,mysql_engine,log_recording): 16     # now, connect and use paramiko Client to negotiate SSH2 across the connection
17     try: 18         client = paramiko.SSHClient() 19  client.load_system_host_keys() 20  client.set_missing_host_key_policy(paramiko.WarningPolicy()) 21         print('*** Connecting...') 22         #client.connect(hostname, port, username, password)
23  client.connect(bind_host_obj.host.ip_addr, 24  bind_host_obj.host.port, 25  bind_host_obj.remoteuser.username, 26  bind_host_obj.remoteuser.password, 27                        timeout=30) 28 
29         cmd_caches = [] 30         chan = client.invoke_shell() 31         print(repr(client.get_transport())) 32         print('*** Here we go!\n') 33         cmd_caches.append(models.AuditLog(user_id=user_obj.id, 34                                           bind_host_id=bind_host_obj.id, 35                                           action_type='login', 36                                           date=datetime.datetime.now() 37  )) 38  log_recording(user_obj,bind_host_obj,cmd_caches) 39  interactive.interactive_shell(chan,user_obj,bind_host_obj,cmd_caches,log_recording) 40  chan.close() 41  client.close() 42     except Exception as e: 43         print('*** Caught exception: %s: %s' % (e.__class__, e)) 44  traceback.print_exc() 45         try: 46  client.close() 47         except: 48             pass
49         sys.exit(1)
View Code

utils.py

 1 import yaml  2 try:  3     from yaml import CLoader as Loader, CDumper as Dumper  4 except ImportError:  5     from yaml import Loader, Dumper  6 def print_err(msg,quit=False):  7     output = "\033[31;1mError: %s\033[0m" % msg  8     if quit:  9  exit(output) 10     else: 11         print(output) 12 def yaml_parser(yml_filename): 13     '''
14  load yaml file and return 15  :param yml_filename: 16  :return: 17     '''
18     #yml_filename = "%s/%s.yml" % (settings.StateFileBaseDir,yml_filename)
19     try: 20         yaml_file = open(yml_filename,'r') 21         data = yaml.load(yaml_file) 22         return data 23     except Exception as e: 24         print_err(e)
View Code

views.py

 1 from models import models  2 from conf import settings  3 from modules.utils import print_err,yaml_parser  4 from modules.db_conn import engine,session  5 from modules import common_filters  6 from modules import ssh_login  7 def auth():  8     '''
 9  do the user login authentication  10  :return:  11     '''
 12     count = 0  13     while count <3:  14         username = input("\033[32;1mUsername:\033[0m").strip()  15         if len(username) ==0:continue
 16         password = input("\033[32;1mPassword:\033[0m").strip()  17         if len(password) ==0:continue
 18         user_obj = session.query(models.UserProfile).filter(models.UserProfile.username==username,  19                                                             models.UserProfile.password==password).first()  20         if user_obj:  21             return user_obj  22         else:  23             print("wrong username or password, you have %s more chances." %(3-count-1))  24             count +=1
 25     else:  26         print_err("too many attempts.")  27 def welcome_msg(user):  28     WELCOME_MSG = '''\033[32;1m  29  ------------- Welcome [%s] login JBSdb -------------  30  \033[0m'''% user.username  31     print(WELCOME_MSG)  32 def log_recording(user_obj,bind_host_obj,logs):  33     '''
 34  flush user operations on remote host into DB  35  :param user_obj:  36  :param bind_host_obj:  37  :param logs: list format [logItem1,logItem2,...]  38  :return:  39     '''
 40     print("\033[41;1m--logs:\033[0m",logs)  41  session.add_all(logs)  42  session.commit()  43 def start_session(argvs):  44     print('going to start sesssion ')  45     user = auth()  46     if user:  47  welcome_msg(user)  48         print(user.bind_hosts)  49         print(user.host_groups)  50         exit_flag = False  51         while not exit_flag:  52             if user.bind_hosts:  53                 print('\033[32;1mz.\tungroupped hosts (%s)\033[0m' %len(user.bind_hosts) )  54             for index,group in enumerate(user.host_groups):  55                 print('\033[32;1m%s.\t%s (%s)\033[0m' %(index,group.name, len(group.bind_hosts)) )  56 
 57             choice = input("[%s]:" % user.username).strip()  58             if len(choice) == 0:continue
 59             if choice == 'z':  60                 print("------ Group: ungroupped hosts ------" )  61                 for index,bind_host in enumerate(user.bind_hosts):  62                     print(" %s.\t%s@%s(%s)"%(index,  63  bind_host.remote_user.username,  64  bind_host.host.hostname,  65  bind_host.host.ip,  66  ))  67                 print("----------- END -----------" )  68             elif choice.isdigit():  69                 choice = int(choice)  70                 if choice < len(user.host_groups):  71                     print("------ Group: %s ------"  % user.host_groups[choice].name )  72                     for index,bind_host in enumerate(user.host_groups[choice].bind_hosts):  73                         print(" %s.\t%s@%s(%s)"%(index,  74  bind_host.remote_user.username,  75  bind_host.host.hostname,  76  bind_host.host.ip,  77  ))  78                     print("----------- END -----------" )  79                     #host selection
 80                     while not exit_flag:  81                         user_option = input("[(b)back, (q)quit, select host to login]:").strip()  82                         if len(user_option)==0:continue
 83                         if user_option == 'b':break
 84                         if user_option == 'q':  85                             exit_flag=True  86                         if user_option.isdigit():  87                             user_option = int(user_option)  88                             if user_option < len(user.host_groups[choice].bind_hosts) :  89                                 print('host:',user.host_groups[choice].bind_hosts[user_option])  90                                 print('audit log:',user.host_groups[choice].bind_hosts[user_option].audit_logs)  91  ssh_login.ssh_login(user,  92  user.host_groups[choice].bind_hosts[user_option],  93  session,  94  log_recording)  95                 else:  96                     print("no this option..")  97 def stop_server(argvs):  98     pass
 99 def create_users(argvs): 100     '''
101  create little_finger access user 102  :param argvs: 103  :return: 104     '''
105     if '-f' in argvs: 106         user_file  = argvs[argvs.index("-f") +1 ] 107     else: 108         print_err("invalid usage, should be:\ncreateusers -f <the new users file>",quit=True) 109     source = yaml_parser(user_file) 110     if source: 111         for key,val in source.items(): 112             print(key,val) 113             obj = models.UserProfile(username=key,password=val.get('password')) 114             # if val.get('groups'):
115             # groups = session.query(models.Group).filter(models.Group.name.in_(val.get('groups'))).all()
116             # if not groups:
117             # print_err("none of [%s] exist in group table." % val.get('groups'),quit=True)
118             # obj.groups = groups
119             # if val.get('bind_hosts'):
120             # bind_hosts = common_filters.bind_hosts_filter(val)
121             # obj.bind_hosts = bind_hosts
122             # #print(obj)
123  session.add(obj) 124  session.commit() 125 def create_groups(argvs): 126     '''
127  create groups 128  :param argvs: 129  :return: 130     '''
131     if '-f' in argvs: 132         group_file  = argvs[argvs.index("-f") +1 ] 133     else: 134         print_err("invalid usage, should be:\ncreategroups -f <the new groups file>",quit=True) 135     source = yaml_parser(group_file) 136     if source: 137         for key,val in source.items(): 138             print(key,val) 139             obj = models.HostGroup(name=key) 140             # if val.get('bind_hosts'):
141             # bind_hosts = common_filters.bind_hosts_filter(val)
142             # obj.bind_hosts = bind_hosts
143             # 144             # if val.get('user_profiles'):
145             # user_profiles = common_filters.user_profiles_filter(val)
146             # obj.user_profiles = user_profiles
147  session.add(obj) 148  session.commit() 149 def create_hosts(argvs): 150     '''
151  create hosts 152  :param argvs: 153  :return: 154     '''
155     if '-f' in argvs: 156         hosts_file  = argvs[argvs.index("-f") +1 ] 157     else: 158         print_err("invalid usage, should be:\ncreate_hosts -f <the new hosts file>",quit=True) 159     source = yaml_parser(hosts_file) 160     if source: 161         print(source) 162         for key,val in source.items(): 163             print(key,val) 164             obj = models.Host(hostname=key,ip=val.get('ip'), port=val.get('port') or 22) 165  session.add(obj) 166  session.commit() 167 def create_bindhosts(argvs): 168     '''
169  create bind hosts 170  :param argvs: 171  :return: 172     '''
173     if '-f' in argvs: 174         bindhosts_file  = argvs[argvs.index("-f") +1 ] 175     else: 176         print_err("invalid usage, should be:\ncreate_hosts -f <the new bindhosts file>",quit=True) 177     source = yaml_parser(bindhosts_file) 178     if source: 179         for key,val in source.items(): 180             #print(key,val)
181             host_obj = session.query(models.Host).filter(models.Host.hostname==val.get('hostname')).first() 182             assert host_obj 183             for item in val['remote_users']: 184                 print(item ) 185                 assert item.get('auth_type') #assert --必须存在,不存在报错
186                 if item.get('auth_type') == 'ssh-password': 187                     remoteuser_obj = session.query(models.RemoteUser).filter( 188                                                         models.RemoteUser.username==item.get('username'), 189                                                         models.RemoteUser.password==item.get('password') 190  ).first() 191                 else: 192                     remoteuser_obj = session.query(models.RemoteUser).filter( 193                                                         models.RemoteUser.username==item.get('username'), 194                                                         models.RemoteUser.auth_type==item.get('auth_type'), 195  ).first() 196                 if not remoteuser_obj: 197                     print_err("RemoteUser obj %s does not exist." % item,quit=True ) 198                 bindhost_obj = models.BindHost(host_id=host_obj.id,remoteuser_id=remoteuser_obj.id) 199  session.add(bindhost_obj) 200                 #for groups this host binds to
201                 if source[key].get('groups'): 202                     group_objs = session.query(models.HostGroup).filter(models.HostGroup.name.in_(source[key].get('groups') )).all() 203                     assert group_objs 204                     print('groups:', group_objs) 205                     bindhost_obj.host_groups = group_objs 206                 #for user_profiles this host binds to
207                 if source[key].get('user_profiles'): 208                     userprofile_objs = session.query(models.UserProfile).filter(models.UserProfile.username.in_( 209                         source[key].get('user_profiles') 210  )).all() 211                     assert userprofile_objs 212                     print("userprofiles:",userprofile_objs) 213                     bindhost_obj.user_profiles = userprofile_objs 214                 #print(bindhost_obj)
215  session.commit() 216 def create_remoteusers(argvs): 217     '''
218  create remoteusers 219  :param argvs: 220  :return: 221     '''
222     if '-f' in argvs: 223         remoteusers_file  = argvs[argvs.index("-f") +1 ] 224     else: 225         print_err("invalid usage, should be:\ncreate_remoteusers -f <the new remoteusers file>",quit=True) 226     source = yaml_parser(remoteusers_file) 227     if source: 228         for key,val in source.items(): 229             print(key,val) 230             obj = models.RemoteUser(username=val.get('username'),auth_type=val.get('auth_type'),password=val.get('password')) 231  session.add(obj) 232  session.commit() 233 def syncdb(argvs): 234     print("Syncing DB....") 235     engine = models.create_engine(settings.Conn_Params, 236                            echo=True) 237     models.Base.metadata.create_all(engine) #建立全部表结构
View Code

new_bindhosts.yml

 1 bind1:  2  hostname: ubuntu test  3  remote_users:  4     - user1:  5  username: root  6       auth_type: ssh-key  7       #password: 123
 8     - user2:  9  username: jyh3 10       auth_type: ssh-password 11  password: jyh123 12  groups: 13     - bj_group 14  user_profiles: 15     - jyh 16     - jack 17 bind2: 18  hostname: server2 19  remote_users: 20     - user1: 21  username: root 22       auth_type: ssh-password 23  password: abc123 24  groups: 25     - bj_group 26     - sh_group 27  user_profiles: 28     - rain
View Code

new_groups.yml

 1 bj_group:  2   #bind_hosts:
 3   # - h1
 4   # - h2
 5  user_profiles:  6     - jyh  7 sh_group:  8  user_profiles:  9     - jack 10     - jyh 11     - rain
View Code

new_hosts.yml

1 ubuntu test: 2   ip: 192.168.2.243
3   port: 22
4 server1: 5   ip: 192.168.2.100
6   port: 30000
7 server2: 8   ip: 10.4.4.22
View Code

new_remoteusers.yml

 1 user0:  2   auth_type:  ssh-password  3  username: root  4  password: abc123  5 user1:  6   auth_type:  ssh-password  7  username: root  8  password: jyh123456  9 user2: 10   auth_type:  ssh-key 11  username: root 12   #password: abc!23
13 user3: 14   auth_type:  ssh-password 15  username: jyh3 16   password: jyh123
View Code

new_users.yml

 1 jyh:  2  password: jyh123  3 # groups:
 4 # - web_servers
 5 # - db_servers
 6   #bind_hosts:
 7   # - h1
 8   # - h2
 9   # - h3
10 jack: 11   password: jack123
View Code

完整示例代码 https://github.com/triaquae/py3_training/tree/master/%E5%A0%A1%E5%9E%92%E6%9C%BA

重点是---设计过程,架构,表结构,交互

完善audit  如在action_registers.py中 "audit" : views.log_audit 。。。设计表结构---能执行,能记录,能看

相关文章
相关标签/搜索