當你公司的服務器變的愈來愈多後,須要操做這些服務器的人就確定不僅是一個運維人員,同時也可能包括多個開發人員,那麼這麼多的人操做業務系統,若是權限分配不當就會存在很大的安全風險,舉幾個場景例子:python
設想大家公司有300臺Linux服務器,A開發人員須要登陸其中5臺WEB服務器查看日誌或進行問題追蹤等事務,同時對另外10臺hadoop服務器有root權限,在有300臺服務器規模的網絡中,按常理來說你是已經使用了ldap權限統一認證的,你如何使這個開發人員只能以普通用戶的身份登陸5臺web服務器,而且同時容許他以管理員的身份登陸另外10臺hadoop服務器呢?而且同時他對其它剩下的200多臺服務器沒有訪問權限mysql
目前據我瞭解,不少公司的運維團隊爲了方面,整個運維團隊的運維人員仍是共享同一套root密碼,這樣內部信任機制雖然使你們的工做方便了,但同時存在着極大的安全隱患,不少狀況下,一個運維人員只須要管理固定數量的服務器,畢竟公司分爲不一樣的業務線,不一樣的運維人員管理的業務線也不一樣,但若是共享一套root密碼,其實就等於無限放大了每一個運維人員的權限,也就是說,若是某個運維人員想幹壞事的話,他能夠在幾分鐘內把整個公司的業務停轉,甚至數據都給刪除掉。爲了下降風險,因而有人想到,把不一樣業務線的root密碼改掉就ok了麼,也就是每一個業務線的運維人員只知道本身的密碼,這固然是最簡單有效的方式,但問題是若是你同時用了ldap,這樣作又比較麻煩,即便你設置了root不經過ldap認證,那新問題就是,每次有運維人員離職,他所在的業務線的密碼都須要從新改一次。linux
其實上面的問題,我以爲能夠很簡單的經過堡壘機來實現,收回全部人員的直接登陸服務器的權限,全部的登陸動做都經過堡壘機受權,運維人員或開發人員不知道遠程服務器的密碼,這些遠程機器的用戶信息都綁定在了堡壘機上,堡壘機用戶只能看到他能用什麼權限訪問哪些遠程服務器。web
在回收了運維或開發人員直接登陸遠程服務器的權限後,其實就等於大家公司生產系統的全部認證過程都經過堡壘機來完成了,堡壘機等於成了大家生產系統的SSO(single sign on)模塊了。你只須要在堡壘機上添加幾條規則就能實現如下權限控制了:sql
容許A開發人員經過普通用戶登陸5臺web服務器,經過root權限登陸10臺hadoop服務器,但對其他的服務器無任務訪問權限shell
多個運維人員能夠共享一個root帳戶,可是依然能分辨出分別是誰在哪些服務器上操做了哪些命令,由於堡壘機帳戶是每一個人獨有的,也就是說雖然全部運維人員共享了一同一個遠程root帳戶,但因爲他們用的堡壘帳戶都是本身獨有的,所以依然能夠經過堡壘機控制每一個運維人員訪問不一樣的機器。數據庫
審計管理其實很簡單,就是把用戶的全部操做都紀錄下來,以備往後的審計或者事故後的追責。在紀錄用戶操做的過程當中有一個問題要注意,就是這個紀錄對於操做用戶來說是不可見的,什麼意思?就是指,不管用戶願不肯意,他的操做都會被紀錄下來,而且,他本身若是不想操做被紀錄下來,或想刪除已紀錄的內容,這些都是他作不到的,這就要求操做日誌對用戶來說是不可見和不可訪問的,經過堡壘機就能夠很好的實現。ubuntu
堡壘機的主要做用權限控制和用戶行爲審計,堡壘機就像一個城堡的大門,城堡裏的全部建築就是你不一樣的業務系統 , 每一個想進入城堡的人都必須通過城堡大門並通過大門守衛的受權,每一個進入城堡的人必須且只能嚴格按守衛的分配進入指定的建築,且每一個建築物還有本身的權限訪問控制,不一樣級別的人能夠到建築物裏不一樣樓層的訪問級別也是不同的。還有就是,每一個進入城堡的人的全部行爲和足跡都會被嚴格的監控和紀錄下來,一旦發生犯罪事件,城堡管理人員就能夠經過這些監控紀錄來追蹤責任人。 vim
堡壘要想成功徹底記到他的做用,只靠堡壘機自己是不夠的, 還須要一系列安全上對用戶進行限制的配合,堡壘機部署上後,同時要確保你的網絡達到如下條件:安全
from sqlalchemy import create_engine,Table from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String,ForeignKey,UniqueConstraint from sqlalchemy.orm import relationship from sqlalchemy.orm import sessionmaker from sqlalchemy import or_,and_ from sqlalchemy import func from sqlalchemy_utils import ChoiceType,PasswordType Base = declarative_base() #生成一個SqlORM 基類 engine = create_engine("mysql+mysqldb://root@localhost:3306/test",echo=False) BindHost2Group = Table('bindhost_2_group',Base.metadata, Column('bindhost_id',ForeignKey('bind_host.id'),primary_key=True), Column('group_id',ForeignKey('group.id'),primary_key=True), ) BindHost2UserProfile = Table('bindhost_2_userprofile',Base.metadata, Column('bindhost_id',ForeignKey('bind_host.id'),primary_key=True), Column('uerprofile_id',ForeignKey('user_profile.id'),primary_key=True), ) Group2UserProfile = Table('group_2_userprofile',Base.metadata, Column('userprofile_id',ForeignKey('user_profile.id'),primary_key=True), Column('group_id',ForeignKey('group.id'),primary_key=True), ) class UserProfile(Base): __tablename__ = 'user_profile' id = Column(Integer,primary_key=True,autoincrement=True) username = Column(String(32),unique=True,nullable=False) password = Column(String(128),unique=True,nullable=False) groups = relationship('Group',secondary=Group2UserProfile) bind_hosts = relationship('BindHost',secondary=BindHost2UserProfile) def __repr__(self): return "<UserProfile(id='%s',username='%s')>" % (self.id,self.username) class RemoteUser(Base): __tablename__ = 'remote_user' AuthTypes = [ (u'ssh-passwd',u'SSH/Password'), (u'ssh-key',u'SSH/KEY'), ] id = Column(Integer,primary_key=True,autoincrement=True) auth_type = Column(ChoiceType(AuthTypes)) username = Column(String(64),nullable=False) password = Column(String(255)) __table_args__ = (UniqueConstraint('auth_type', 'username','password', name='_user_passwd_uc'),) def __repr__(self): return "<RemoteUser(id='%s',auth_type='%s',user='%s')>" % (self.id,self.auth_type,self.username) class Host(Base): __tablename__ = 'host' id = Column(Integer,primary_key=True,autoincrement=True) hostname = Column(String(64),unique=True,nullable=False) ip_addr = Column(String(128),unique=True,nullable=False) port = Column(Integer,default=22) bind_hosts = relationship("BindHost") def __repr__(self): return "<Host(id='%s',hostname='%s')>" % (self.id,self.hostname) class Group(Base): __tablename__ = 'group' id = Column(Integer,primary_key=True,autoincrement=True) name = Column(String(64),nullable=False,unique=True) bind_hosts = relationship("BindHost",secondary=BindHost2Group, back_populates='groups' ) user_profiles = relationship("UserProfile",secondary=Group2UserProfile ) def __repr__(self): return "<HostGroup(id='%s',name='%s')>" % (self.id,self.name) class BindHost(Base): '''Bind host with different remote user, eg. 192.168.1.1 mysql passAbc123 eg. 10.5.1.6 mysql pass532Dr! eg. 10.5.1.8 mysql pass532Dr! eg. 192.168.1.1 root ''' __tablename__ = 'bind_host' id = Column(Integer,primary_key=True,autoincrement=True) host_id = Column(Integer,ForeignKey('host.id')) remoteuser_id = Column(Integer,ForeignKey('remote_user.id')) host = relationship("Host") remoteuser = relationship("RemoteUser") groups = relationship("Group",secondary=BindHost2Group,back_populates='bind_hosts') user_profiles = relationship("UserProfile",secondary=BindHost2UserProfile) __table_args__ = (UniqueConstraint('host_id', 'remoteuser_id', name='_bindhost_and_user_uc'),) def __repr__(self): return "<BindHost(id='%s',name='%s',user='%s')>" % (self.id, self.host.hostname, self.remoteuser.username ) Base.metadata.create_all(engine) #建立全部表結構 if __name__ == '__main__': SessionCls = sessionmaker(bind=engine) #建立與數據庫的會話session class ,注意,這裏返回給session的是個class,不是實例 session = SessionCls() #h1 = session.query(Host).filter(Host.hostname=='ubuntu4').first() #hg1 = session.query(HostGroup).filter(HostGroup.name=='t2').first() #h2 = Host(hostname='ubuntu4',ip_addr='192.168.1.21') #h3 = Host(hostname='ubuntu5',ip_addr='192.168.1.24',port=20000) #hg= HostGroup(name='TestServers3',host_id=h3.id) #hg2= HostGroup(name='TestServers2',host_id=h2.id) #hg3= HostGroup(name='TestServers3') #hg4= HostGroup(name='TestServers4') #session.add_all([hg3,hg4]) #h2.host_groups = [HostGroup(name="t1"),HostGroup(name="t2")] #h3.host_groups = [HostGroup(name="t2")] #h1.host_groups.append(HostGroup(name="t3") ) #print(h1.host_groups) #print("hg1:",hg1.host.hostname) #join_res = session.query(Host).join(Host.host_groups).filter(HostGroup.name=='t1').group_by("Host").all() #print('join select:',join_res) #group_by_res = session.query(HostGroup, func.count(HostGroup.name )).group_by(HostGroup.name).all() #print("-------------group by res-----") ''' h1=Host(hostname='h1',ip_addr='1.1.1.1') h2=Host(hostname='h2',ip_addr='1.1.1.2') h3=Host(hostname='h3',ip_addr='1.1.1.3') r1=RemoteUser(auth_type=u'ssh-passwd',username='alex',password='abc123') r2=RemoteUser(auth_type=u'ssh-key',username='alex') g1 = Group(name='g1') g2 = Group(name='g2') g3 = Group(name='g3') session.add_all([h1,h2,h3,r1,r2]) session.add_all([g1,g2,g3]) b1 = BindHost(host_id=1,remoteuser_id=1) b2 = BindHost(host_id=1,remoteuser_id=2) b3 = BindHost(host_id=2,remoteuser_id=2) b4 = BindHost(host_id=3,remoteuser_id=2) session.add_all((b1,b2,b3,b4)) all_groups = session.query(Group).filter().all() #first() all_bindhosts = session.query(BindHost).filter().all() #h1 = session.query(BindHost).filter(BindHost.host_id==1).first() #h1.groups.append(all_groups[1]) #print("h1:",h1) #print("----------->",all_groups.name,all_groups.bind_hosts) u1 = session.query(UserProfile).filter(UserProfile.id==1).first() print('--user:',u1.bind_hosts) print('--user:',u1.groups[0].bind_hosts) #u1.groups = [all_groups[1] ] #u1.bind_hosts.append(all_bindhosts[1]) #u1 = UserProfile(username='alex',password='123') #u2 = UserProfile(username='rain',password='abc!23') #session.add_all([u1,u2]) #b1 = BindHost() session.commit() #print(h2.host_groups) '''
使用密碼登陸,每次都必須輸入密碼,很是麻煩。好在SSH還提供了公鑰登陸,能夠省去輸入密碼的步驟。
所謂"公鑰登陸",原理很簡單,就是用戶將本身的公鑰儲存在遠程主機上。登陸的時候,遠程主機會向用戶發送一段隨機字符串,用戶用本身的私鑰加密後,再發回來。遠程主機用事先儲存的公鑰進行解密,若是成功,就證實用戶是可信的,直接容許登陸shell,再也不要求密碼。
這種方法要求用戶必須提供本身的公鑰。若是沒有現成的,能夠直接用ssh-keygen生成一個:
$ ssh-keygen
運行上面的命令之後,系統會出現一系列提示,能夠一路回車。其中有一個問題是,要不要對私鑰設置口令(passphrase),若是擔憂私鑰的安全,這裏能夠設置一個。
運行結束之後,在$HOME/.ssh/目錄下,會新生成兩個文件:id_rsa.pub和id_rsa。前者是你的公鑰,後者是你的私鑰。
這時再輸入下面的命令,將公鑰傳送到遠程主機host上面:
$ ssh-copy-id user@host
好了,今後你再登陸,就不須要輸入密碼了。
祕鑰生成命令 1.ssh-keygen .ssh/.id_rsa 私鑰 .ssh/.id_rsa.pub 公鑰 2. 把公鑰copy到要登陸的目標機器上 scp -rp id_rsa alex@192.168.10.35:/home/alex/ #把本地文件copy到遠程 scp -rp alex@192.168.10.35:/home/alex/id_rsa /tmp/ #把遠程文件copy到本地 查看當前用戶id, whoami su - alex 切換用戶 cat id_rsa.pub >authorized_keys 讀出id_rsa.pub的內容並寫入到>後的文件,(覆蓋) cat id_rsa.pub >>authorized_keys 讀出id_rsa.pub的內容並寫入到>後的文件,(追加) 3. 在目標機器上,把id_rsa.pub裏的key取出寫入.ssh/authorized_keys
ubuntu系統:
#安裝paramiko sudo pip3 install -i http://pypi.douban.com/simple/ paramiko --trusted-host pypi.douban.com #搜索全部可用的安裝包 sudo apt-cache search openssl #安裝 libssl-dev sudo apt-get install libssl-dev
開機自動加載保壘機程序方法:
在普通用戶家目錄下面:
vim home/taram/.bashrc 把這段代碼加到文件結尾: python3 s3CrazyEye/crazyeye_manager.py run logout