白日依山尽,黄河入海流。欲穷千里目,更上一层楼。 -- 唐·王之涣

Jumpserver堡垒机问题和Bug汇总

欢迎关注个人公众号 DailyOps

源站地址 Jumpserver堡垒机问题和Bug汇总

背景

最近在使用堡垒机过程中发现几个问题,这里做个汇总,希望能对大家有所帮助

问题1、账号不存在,提示”您输入的用户名或者密码不对,请重新输入“,最终错误次数超限,被”锁定“

问题2、配置了”动态用户名(用户名是动态的,登录资产时使用当前用户的用户名登录)“ 会 覆盖主机上同名的SA账号(具有sudo高权限的管理账号)即使从授权中取消该动态用户权限配置

问题3、celery task状态刷新一会online一会offline,导致资产推送系统用户的时候卡死问题

接下来我们一次描述和解答

不存在的账号被锁定

出现的问题是因为运维给开发人员开通账号的时候名字写错,比如开发叫 betty1210,结果运维失误导致告诉开发人员你的账号是betty1211,然后开发人员就开始了艰难的登录之旅

问题发现之旅

1、后台存在账号 betty1210 ,开发使用 betty1211 频繁登录被锁定
在这里插入图片描述

2、管理员登录后台发现,后台实际无 betty1211 用户,存在的是 betty1210 用户;也当然有效用户 betty1210没有被锁定
在这里插入图片描述在这里插入图片描述
3、然后尝试把 正确用户 betty1210 修改为 错误用户betty1211 ,发现 用户 betty1211 被锁定

在这里插入图片描述

问题总结

个人觉得一般遇到这种问题,大家普通的都会认定是密码不对,然后复制不行,就水写一个个打上去等等尝试,但是账号如果不存在直接提示说该用户不存在 多友好,也不用在怀疑自己密码那些输错了,各种尝试… …

所以各位在设计用户模块的可以站在用户的角度思考下。


动态用户Bug

这个真的是个Bug

背景

起初公司内部是通过ansible批量管理系统,ansible会给管理员推送SA权限的个人账号,方便管理同时也做好审计日志记录是哪个管理员做的操作

在测试Jumpserver堡垒机的动态用户的时候给管理员James(假设这里管理员叫James)也分配了该系统用户

注意:动态用户时系统用户的一个类别

之后测试通过之后管理员取消了该动态用户的权限授权,在之后通过镜像(为了方便,特殊SA账号集成到了镜像中)创建新的主机之后发现James账号的SA权限丢失。

—–> 咋就丢了呢?

1、通过分析主机的passwd 和 group 分析发现时间是在主机创建之后,Jumpserver同步系统账号的时间吻合,怀疑是Jumpserver导致

2、创建测试账号JamesTest分配动态用户权限,然后再回收该权限

3、Jumpserver在测试主机上推送动态用户,发现还是会给该主机继续推送JamesTest 动态用户

也验证了确实是Jumpserver的问题导致

4、分析问题

由于篇幅问题,这里简化分析过程,看大家的反馈,有必要的话会整理个更加详细的分析过程

  • 主要是通过浏览器发现在新增 资产授权的时候,调用 api/v1/perms/asset-permissions/ 通过该接口定位到文件perms/api/asset/asset_permission.py
1
2
3
4
5
6
7
8
class AssetPermissionViewSet(OrgBulkModelViewSet):
"""
资产授权列表的增删改查api
"""
... ...
model = AssetPermission
serializer_class = serializers.AssetPermissionSerializer
... ...
  • 注意到model AssetPermission中 system_users关联了assets.SystemUser,而且有个users_display属性
1
2
3
4
5
6
7
class AssetPermission(BasePermission):
... ...
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user"))
... ...
def users_display(self):
names = [user.username for user in self.users.all()]
return names
  • perms/serializers/asset/permission.py 文件中分析 AssetPermissionViewSet 中的 serializer_class AssetPermissionSerializer 的 perform_display_create 中知道授权中涉及到的用户、用户组、资产、资产节点、系统用户都是通过这里进行创建的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class AssetPermissionSerializer(BulkOrgResourceModelSerializer):
... ...
def perform_display_create(self, instance, **kwargs):
# 用户
users_to_set = User.objects.filter(
Q(name__in=kwargs.get('users_display')) | Q(username__in=kwargs.get('users_display'))
).distinct()
instance.users.add(*users_to_set)
# 用户组
user_groups_to_set = UserGroup.objects.filter(name__in=kwargs.get('user_groups_display')).distinct()
instance.user_groups.add(*user_groups_to_set)
# 资产
assets_to_set = Asset.objects.filter(
Q(ip__in=kwargs.get('assets_display')) | Q(hostname__in=kwargs.get('assets_display'))
).distinct()
instance.assets.add(*assets_to_set)
# 节点
nodes_to_set = Node.objects.filter(full_value__in=kwargs.get('nodes_display')).distinct()
instance.nodes.add(*nodes_to_set)

def create(self, validated_data):
... ...
instance = super().create(validated_data)
self.perform_display_create(instance, **display)
return instance
  • 核心就是instance.users.add,通过之前的model关联关系,知道会把用户和它具有的系统用户报错在中间表 assets_systemuser_users中,

  • 这里的create进行了perform重写,会写入相关表,但是delete做的时候没有做特殊处理,那么它就只会清理当前model对应的表,也就是perms_assetpermission_users

  • 然后在 资产管理->系统用户->对应的动态用户 打开进入到”资产列表中”点击主机后面的”推送“按钮 ,如下图所示,
    在这里插入图片描述我们发现调用的接口是 /api/v1/assets/system-users/261a5b51-b33a-4461-8c99-4c07c49cedae/tasks/,主要涉及到 SystemUserViewSetSystemUser model ,系统用户和用户的联系管理就保存在 表 assets_systemuser_users 中,而 授权清理的时候也没有清理这个表

分析到这里,就知道授权清理存在Bug,只是删除了当前model对应的表数据,但是关联的 systemuser 而产生的中间表数据未清理

解决

知道对应的userid 和 systemuserid 从表 assets_systemuser_users 中清理相关数据,然后重新推送,发现推送记录中已经没有了JamesTest用户


Celery 僵死

Celery的任务监控位于堡垒机 ”作业中心“下的”任务监控“ 中,点击打开新的页面如下图所示
在这里插入图片描述
刷新页面这里的status状态一会Online,一会又会Offline,如果尝试推送系统用户,那么遇到的页面的就是**满屏幕的省略号**

主要的原因就是celery僵死导致

1
2
3
[root@devops-jumpserver-vm ]# ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]'
Z+ 26724 18914 [celery] <defunct>
Z+ 26681 23138 [celery] <defunct>

尝试清理僵尸进程,发现导致jumpserver掉线,

1
2
3
[root@devops-jumpserver-vm ]# kill -HUP `ps -A -ostat,ppid`|grep -e '^[Zz]'|awk '{print $2}'
Connection to devops-jumpserver-vm closed by remote host.
Connection to devops-jumpserver-vm closed.

这里需要注意📢:

堡垒机一般都是内网使用,如果一旦出现问题导致不可访问,那就是灾难性的,想登录堡垒机所在主机去排查修复都不可能了,所以一定要有一个备选方案,比如:在堡垒机出现问题的时候可以通过临时绑定一个公网IP然后远程公网SSH登录去修复问题

登录Jumpserver尝试重启Jumpserver服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# status 发现堡垒机的状态都是 unhealthy 
[root@devops-jumpserver-vm ]# ./jmsctl.sh status
Name Command State Ports
----------------------------------------------------------------------------------------------------------
jms_celery ./entrypoint.sh start task Up (unhealthy) 8070/tcp, 8080/tcp
jms_core ./entrypoint.sh start web Up (unhealthy) 8070/tcp, 8080/tcp
jms_koko ./entrypoint.sh Up (unhealthy) 2222/tcp, 5000/tcp
jms_lion /usr/bin/supervisord Up (unhealthy) 4822/tcp
jms_nginx /docker-entrypoint.sh ngin ... Up (unhealthy) 0.0.0.0:22022->2222/tcp, 0.0.0.0:80->80/tcp
# 尝试重启
[root@devops-jumpserver-vm ]# ./jmsctl.sh restart
Stopping jms_core ... done
Stopping jms_koko ... done
Stopping jms_lion ... done
Stopping jms_nginx ... done
Stopping jms_celery ... done

jms_core is up-to-date
ERROR: for koko Container "9f501157b5db" is unhealthy.
ERROR: for lion Container "9f501157b5db" is unhealthy.
ERROR: for celery Container "9f501157b5db" is unhealthy.
ERROR: for nginx Container "9f501157b5db" is unhealthy.
ERROR: Encountered errors while bringing up the project.

重启失败,发现对应的容器也出现了unhealthy状态
尝试重启docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 重启docker
[root@devops-jumpserver-vm ]# systemctl restart docker

# 成功之后在重启Jumpserver
[root@devops-jumpserver-vm ]# ./jmsctl.sh restart
# 最后检查 Jumpserver的服务正常,访问恢复
[root@devops-jumpserver-vm ]# ./jmsctl.sh status
Name Command State Ports
--------------------------------------------------------------------------------------------------------
jms_celery ./entrypoint.sh start task Up (healthy) 8070/tcp, 8080/tcp
jms_core ./entrypoint.sh start web Up (healthy) 8070/tcp, 8080/tcp
jms_koko ./entrypoint.sh Up (healthy) 2222/tcp, 5000/tcp
jms_lion /usr/bin/supervisord Up (healthy) 4822/tcp
jms_nginx /docker-entrypoint.sh ngin ... Up (healthy) 0.0.0.0:22022->2222/tcp, 0.0.0.0:80->80/tcp

看到此处,欢迎点赞、转发,大家一起学习成长哦~

技术文章看累了,来个美图养养眼

在这里插入图片描述

作者

Colin

发布于

2021-12-17

许可协议