su提权

2022/02/04 posted in  运维

起因

线上生产环境服务器我们一般是用work账户,使用work账户启动线上服务。同时为方便操作,开发人员一般也可以使用work登录服务器进行操作, 比如查看日志,问题排查打印JVM堆栈,查看GC等。

但方便的同时,往往也意味着会有一些代价,比如误操作kill导致java进程被干掉。 误操作rm命令导致核心服务文件被删掉等。实际线上也发生过类似的问题,开发人员误操作了rm命令导致服务宕机,也有误操作rm命令把数据库删除的。

诉求比较简单:

  1. 对服务部署: 需要有单独的帐号用于服务部署,且权限范围有限。
  2. 对开发人员: 需能登录服务器,并做基本操作。 比如固定目录下文件操作,java进程的排查等等。

对应方案也较简单:

  1. work权限仅对部署机器生效,开发人员无work权限。
  2. 提供readonly权限给开发人员,提供readonly用户读写目录。 因为java进程启动是使用work权限启动的,所以需要能让readonly权限可以对java进程执行常用的排查命令,如jstack/jmap等等。 而这块的实现,可以通过su提权的方式实现。

实操

首先先创建两个帐号,work 和 readonly

# 添加work帐号
useradd -d /home/work -m work
# 设置密码
passwd work

# 添加readonly帐号
useradd -d /home/readonly -m readonly
# 设置密码
passwd readonly

使用work启动java进程

java -jar com.dutycode.api.weixin-0.0.1-SNAPSHOT.jar

查看当前的java进程号,可以看到进程是使用work账户启动

屏幕快照 2020-12-13 22.22.02

切换至readonly账户(或者使用readonly账户登录),当我们使用jstack命令去查看18121这个java进程的时候,会被提示18121: Operation not permitted, 也就是权限受限。

image-20201213222455341

我们需要使用root帐号,对readonly帐号进行提权

# 编辑sudoers
vim /etc/sudoers

# 在文件中新增:
readonly ALL=(work) NOPASSWD:/usr/java/default/bin

# 格式为:
# 格式: 用户    主机名=(目标用户) 命令,!命令(表示此命令不能使用)
# 上面的表示,对readonly,在ALL主机上可以使用work的权限,无需密码去执行/usr/java/default/bin下的命令。

增加提权之后,我们可以使用sudo 来对work用户下的java进程执行jstack命令

sudo -u work /usr/java/default/bin/jstack 18121

便可以在readonly用户下使用jstack对work用户的java进程操作了。

image-20201213225620031

后记

操作提权本身不复杂。 有意思的是,一个公司的发展过程中,在服务器权限上走了很多路。 最开始的work权限,需要帐号密码,到后来的使用kerberos授权方式隐藏掉work密码,再到后来的readonly账户用于登录,经历了很多过程,也见证了公司的业务发展。

从前期的口头约定,变成了现在的系统约束,逐步降低了风险。

关于我及张二蛋又要扯蛋了

    一个不务正业的程序猿及这个程序猿写字的地方,这里可能有技术,有理财,有历史,有总结,有生活,偶尔也扯扯蛋,妥妥的杂货铺,喜欢可关注。
    酒已备好,等你来开
图片