本节内容

项目实战:运维堡垒机开发

前景介绍

到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多人觉得,堡垒机就是跳板机,其实这个认识是不全面的,跳板功能只是堡垒机所具备的功能属性中的其中一项而已,下面我就给大家介绍一下堡垒机的重要性,以帮助大家参考自己公司的业务是否需要部署堡垒机。

堡垒机有以下两个至关重要的功能:

权限管理

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

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

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

其实上面的问题,我觉得可以很简单的通过堡垒机来实现,收回所有人员的直接登录服务器的权限,所有的登录动作都通过堡垒机授权,运维人员或开发人员不知道远程服务器的密码,这些远程机器的用户信息都绑定在了堡垒机上,堡垒机用户只能看到他能用什么权限访问哪些远程服务器。

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

  1. 允许A开发人员通过普通用户登录5台web服务器,通过root权限登录10台hadoop服务器,但对其余的服务器无任务访问权限

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

审计管理

审计管理其实很简单,就是把用户的所有操作都纪录下来,以备日后的审计或者事故后的追责。在纪录用户操作的过程中有一个问题要注意,就是这个纪录对于操作用户来讲是不可见的,什么意思?就是指,无论用户愿不愿意,他的操作都会被纪录下来,并且,他自己如果不想操作被纪录下来,或想删除已纪录的内容,这些都是他做不到的,这就要求操作日志对用户来讲是不可见和不可访问的,通过堡垒机就可以很好的实现。

堡垒机架构

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

堡垒要想成功完全记到他的作用,只靠堡垒机本身是不够的, 还需要一系列安全上对用户进行限制的配合,堡垒机部署上后,同时要确保你的网络达到以下条件:

  • 所有人包括运维、开发等任何需要访问业务系统的人员,只能通过堡垒机访问业务系统

    • 回收所有对业务系统的访问权限,做到除了堡垒机管理人员,没有人知道业务系统任何机器的登录密码

    • 网络上限制所有人员只能通过堡垒机的跳转才能访问业务系统

  • 确保除了堡垒机管理员之外,所有其它人对堡垒机本身无任何操作权限,只有一个登录跳转功能

  • 确保用户的操作纪录不能被用户自己以任何方式获取到并篡改 

堡垒机功能实现需求

业务需求:

  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. 分组管理,即可以对设置进行分组,允许用户访问某组机器,但对组里的不同机器依然有不同的访问权限    

设计表结构:

#_*_coding:utf-8_*_
__author__ = 'Alex Li'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,PasswordTypeBase = 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 passAbc123eg. 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)'''

完整示例代码

https://github.com/triaquae/py3_training/tree/master/%E5%A0%A1%E5%9E%92%E6%9C%BA

转载于:https://blog.51cto.com/xiaofengcanyue/1868906

python,day13-堡垒机相关推荐

  1. 基于python的堡垒机

    一 堡垒机的架构 堡垒机的核心架构通常如下图所示: 二.堡垒机的一般执行流程 管理员为用户在服务器上创建账号(将公钥放置服务器,或者使用用户名密码) 用户登陆堡垒机,输入堡垒机用户名密码,显示当前用户 ...

  2. python之堡垒机(第九天)

    本节作业: 通过使用paramiko和sqlalchemy实现堡垒机功能 主要功能实现: 1.用户登录堡垒机后,无需知道密码或密钥可以SSH登录远端服务器: 2.用户对一个组内所有主机批量执行指定命令 ...

  3. Python之堡垒机

    本节内容 项目实战:运维堡垒机开发 前景介绍 到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多人觉得,堡垒机就是跳板机,其实这个认识是不全面的,跳板功 ...

  4. python基础 day13 运维堡垒机开发

    本节内容 项目实战:运维堡垒机开发 前景介绍 到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多人觉得,堡垒机就是跳板机,其实这个认识是不全面的,跳板功 ...

  5. python运维实战--跨堡垒机连接二级服务器上传文件

    python运维实战--跨堡垒机连接二级服务器上传文件 paramiko的有关概念和操作 Welcome to Paramiko! - Paramiko documentation 这个python脚 ...

  6. Python 堡垒机介绍

    堡垒机说明 由于运维行业流动性很高,也为了防止有人在服务中残留后门,照成安全隐患,在这里我们使用堡垒机保证服务器管理安全. 我们知道运维人员在登陆服务时需要登陆用户,从客户端到服务端的过程中堡垒机,将 ...

  7. 审计系统---堡垒机python下ssh的使用

    堡垒机python下ssh的使用 [堡垒机更多参考]http://www.cnblogs.com/alex3714/articles/5286889.html [paramiko的Demo实例]htt ...

  8. python连接linux堡垒机_利用Python Paramiko开发linux堡垒机

    1.Paramiko模块下的demo.py程序 前面利用Python中的Paramiko模块可以进行SSH的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连的,即一 ...

  9. Python之路【第八篇】:堡垒机实例以及数据库操作

    Python之路[第八篇]:堡垒机实例以及数据库操作 堡垒机前戏 开发堡垒机之前,先来学习Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作 SSHClient 用于 ...

  10. 运维堡垒机(跳板机)系统 python

    相信各位对堡垒机(跳板机)不陌生,为了保证服务器安全,前面加个堡垒机,所有ssh连接都通过堡垒机来完成,堡垒机也需要有 身份认证,授权,访问控制,审计等功能,笔者用Python基本实现了上述功能. A ...

最新文章

  1. Jenkins首次安装推荐插件出错 No such plugin: cloudbees-folder 超详细解决方案
  2. 深度神经网络中Inception-ResNet模块介绍
  3. python 作用域 前缀_Python面试题:杂项内容
  4. Selenium+python --获取百度联想词
  5. Jmeter----连接mysql数据库及常见问题处理
  6. OMG!这1010本书的书名都是什么鬼?
  7. loadrunner java_如何使用LoadRunner开发JAVA Vuser
  8. mysql dba命令_mysql DBA:mysqladmin常用命令总结
  9. LeetCode——最小栈
  10. 【POJ 2785】【折半枚举】4 Values whose Sum is 0【暑期 No.6】
  11. python水仙花数的编程代码-Python 求“水仙花数”的方法和具体代码
  12. Android edittext 属性inputtype
  13. java同步器有哪些_java 同步器 Semaphore、
  14. 微信支付服务商接入指引
  15. 全球首只AIGC动画短片发行,日漫风格超治愈!
  16. xshell 免费版
  17. USB过压保护芯片,高输入电压充电器(OVP)
  18. 数据分析系列学习之My SQL(一)初识My SQL
  19. oauth2-authorization-server;oauth2-resource-server;oauth2-client
  20. Power OJ 2844: New contest【模拟】

热门文章

  1. Dremel - Interactive Analysis of WebScale Datasets
  2. Python天天美味(28) - urlopen
  3. sql server 2005 T-SQL BEGIN CONVERSATION TIMER (Transact-SQL)
  4. Django 操作Mysql数据库 对表进行增删改查
  5. (NO.00001)iOS游戏SpeedBoy Lite成形记(九)
  6. OSChina 周日乱弹 —— 表白的终极境界!
  7. iOS开源程序下载链接整理
  8. sqlite3里类似top的用法
  9. 10年追逐技术潮流,差一点儿就两手空空,竹篮打水,留给我的只有经验
  10. nf_hook_slow函数