到目前爲止,不少公司對堡壘機依然不太感冒,實際上是沒有充分認識到堡壘機在IT管理中的重要做用的,不少人以爲,堡壘機就是跳板機,其實這個認識是不全面的,跳板功能只是堡壘機所具有的功能屬性中的其中一項而已,下面我就給你們介紹一下堡壘機的重要性,以幫助你們參考本身公司的業務是否須要部署堡壘機。mysql
堡壘機有如下兩個相當重要的功能:ios
當你公司的服務器變的愈來愈多後,須要操做這些服務器的人就確定不僅是一個運維人員,同時也可能包括多個開發人員,那麼這麼多的人操做業務系統,若是權限分配不當就會存在很大的安全風險,舉幾個場景例子:git
設想大家公司有300臺Linux服務器,A開發人員須要登陸其中5臺WEB服務器查看日誌或進行問題追蹤等事務,同時對另外10臺hadoop服務器有root權限,在有300臺服務器規模的網絡中,按常理來說你是已經使用了ldap權限統一認證的,你如何使這個開發人員只能以普通用戶的身份登陸5臺web服務器,而且同時容許他以管理員的身份登陸另外10臺hadoop服務器呢?而且同時他對其它剩下的200多臺服務器沒有訪問權限github
目前據我瞭解,不少公司的運維團隊爲了方面,整個運維團隊的運維人員仍是共享同一套root密碼,這樣內部信任機制雖然使你們的工做方便了,但同時存在着極大的安全隱患,不少狀況下,一個運維人員只須要管理固定數量的服務器,畢竟公司分爲不一樣的業務線,不一樣的運維人員管理的業務線也不一樣,但若是共享一套root密碼,其實就等於無限放大了每一個運維人員的權限,也就是說,若是某個運維人員想幹壞事的話,他能夠在幾分鐘內把整個公司的業務停轉,甚至數據都給刪除掉。爲了下降風險,因而有人想到,把不一樣業務線的root密碼改掉就ok了麼,也就是每一個業務線的運維人員只知道本身的密碼,這固然是最簡單有效的方式,但問題是若是你同時用了ldap,這樣作又比較麻煩,即便你設置了root不經過ldap認證,那新問題就是,每次有運維人員離職,他所在的業務線的密碼都須要從新改一次。web
其實上面的問題,我以爲能夠很簡單的經過堡壘機來實現,收回全部人員的直接登陸服務器的權限,全部的登陸動做都經過堡壘機受權,運維人員或開發人員不知道遠程服務器的密碼,這些遠程機器的用戶信息都綁定在了堡壘機上,堡壘機用戶只能看到他能用什麼權限訪問哪些遠程服務器。sql
在回收了運維或開發人員直接登陸遠程服務器的權限後,其實就等於大家公司生產系統的全部認證過程都經過堡壘機來完成了,堡壘機等於成了大家生產系統的SSO(single sign on)模塊了。你只須要在堡壘機上添加幾條規則就能實現如下權限控制了:shell
容許A開發人員經過普通用戶登陸5臺web服務器,經過root權限登陸10臺hadoop服務器,但對其他的服務器無任務訪問權限數據庫
多個運維人員能夠共享一個root帳戶,可是依然能分辨出分別是誰在哪些服務器上操做了哪些命令,由於堡壘機帳戶是每一個人獨有的,也就是說雖然全部運維人員共享了一同一個遠程root帳戶,但因爲他們用的堡壘帳戶都是本身獨有的,所以依然能夠經過堡壘機控制每一個運維人員訪問不一樣的機器。ubuntu
審計管理其實很簡單,就是把用戶的全部操做都紀錄下來,以備往後的審計或者事故後的追責。在紀錄用戶操做的過程當中有一個問題要注意,就是這個紀錄對於操做用戶來說是不可見的,什麼意思?就是指,不管用戶願不肯意,他的操做都會被紀錄下來,而且,他本身若是不想操做被紀錄下來,或想刪除已紀錄的內容,這些都是他作不到的,這就要求操做日誌對用戶來說是不可見和不可訪問的,經過堡壘機就能夠很好的實現。windows
堡壘機的主要做用權限控制和用戶行爲審計,堡壘機就像一個城堡的大門,城堡裏的全部建築就是你不一樣的業務系統 , 每一個想進入城堡的人都必須通過城堡大門並通過大門守衛的受權,每一個進入城堡的人必須且只能嚴格按守衛的分配進入指定的建築,且每一個建築物還有本身的權限訪問控制,不一樣級別的人能夠到建築物裏不一樣樓層的訪問級別也是不同的。還有就是,每一個進入城堡的人的全部行爲和足跡都會被嚴格的監控和紀錄下來,一旦發生犯罪事件,城堡管理人員就能夠經過這些監控紀錄來追蹤責任人。
堡壘要想成功徹底記到他的做用,只靠堡壘機自己是不夠的, 還須要一系列安全上對用戶進行限制的配合,堡壘機部署上後,同時要確保你的網絡達到如下條件:
設計表結構
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)
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 }
settiongs.py
1 Conn_Params = "mysql+pymysql://root:123456@192.168.211.129/JBSdb?charset=utf8"
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
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
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:])
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
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()
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
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)
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)
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) #建立全部表結構
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
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
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
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
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
完整示例代碼 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 。。。設計表結構---能執行,能記錄,能看