到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多人觉得,堡垒机就是跳板机,其实这个认识是不全面的,跳板功能只是堡垒机所具备的功能属性中的其中一项而已,下面我就给大家介绍一下堡垒机的重要性,以帮助大家参考自己公司的业务是否需要部署堡垒机。
当你公司的服务器变的越来越多后,需要操作这些服务器的人就肯定不只是一个运维人员,同时也可能包括多个开发人员,那么这么多的人操作业务系统,如果权限分配不当就会存在很大的安全风险,举几个场景例子:
其实上面的问题,我觉得可以很简单的通过堡垒机来实现,收回所有人员的直接登录服务器的权限,所有的登录动作都通过堡垒机授权,运维人员或开发人员不知道远程服务器的密码,这些远程机器的用户信息都绑定在了堡垒机上,堡垒机用户只能看到他能用什么权限访问哪些远程服务器。
在回收了运维或开发人员直接登录远程服务器的权限后,其实就等于你们公司生产系统的所有认证过程都通过堡垒机来完成了,堡垒机等于成了你们生产系统的SSO(single sign on)模块了。你只需要在堡垒机上添加几条规则就能实现以下权限控制了:
审计管理其实很简单,就是把用户的所有操作都纪录下来,以备日后的审计或者事故后的追责。在纪录用户操作的过程中有一个问题要注意,就是这个纪录对于操作用户来讲是不可见的,什么意思?就是指,无论用户愿不愿意,他的操作都会被纪录下来,并且,他自己如果不想操作被纪录下来,或想删除已纪录的内容,这些都是他做不到的,这就要求操作日志对用户来讲是不可见和不可访问的,通过堡垒机就可以很好的实现。
堡垒机的主要作用权限控制和用户行为审计,堡垒机就像一个城堡的大门,城堡里的所有建筑就是你不同的业务系统 , 每个想进入城堡的人都必须经过城堡大门并经过大门守卫的授权,每个进入城堡的人必须且只能严格按守卫的分配进入指定的建筑,且每个建筑物还有自己的权限访问控制,不同级别的人可以到建筑物里不同楼层的访问级别也是不一样的。还有就是,每个进入城堡的人的所有行为和足迹都会被严格的监控和纪录下来,一旦发生犯罪事件,城堡管理人员就可以通过这些监控纪录来追踪责任人。?
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'),)
BindHost2UserProfile = Table('bindhost_2_userprofile',Column('uerprofile_id',ForeignKey('user_profile.id'),)
Group2UserProfile = Table('group_2_userprofile',Column('userprofile_id',)
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),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,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,autoincrement=True)
hostname = Column(String(64),nullable=False)
ip_addr = Column(String(128),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,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,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",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',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)
'''
所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
https://github.com/triaquae/py3_training/tree/master/%E5%A0%A1%E5%9E%92%E6%9C%BA?