l28.Linux系统权限集中管理项目案例实践

1,122 阅读18分钟

“ 本文正在参加「金石计划 . 瓜分6万现金大奖」 ”

众所周知,Linux系统权限管理是Linux运维工作的重中之重。若服务器不需要团队协作运维管理,那么超级权限可以集中在一个人手中,但是很多时候,企业服务器的数量并不止一台,需要很多运维人员共同管理,甚至还需要为开发人员分配管理服务器的用户账号,因此,如何科学地分配和管理,让每个用户既能达到工作要求,又不会越权访问(获得工作需求以外的权限)就显得非常重要了,本章就来讲讲这方面的方案设计与实施案例。

15.1 sudo配置文件/etc/sudoers深入介绍

sudo命令对应的用户权限授权配置文件为/etc/sudoers,我们可以使用专用工具visudo来完成有关sudo的授权管理配置,使用visudo工具的好处是在添加规则之后,保存退出时会检查授权配置的语法(这一点很重要,曾经有人直接用vim编辑/etc/sudoers,最后配置发生了错误,造成所有普通用户都无法通过sudo执行命令以及切换到超级root上了)。

在授权配置完成以后,可以切换到被授权的用户下,通过sudo -l命令可以查看哪些超级权限命令是可以执行的。

15.1.1 /etc/sudoers配置语法注意事项

  • 命令别名下的成员必须是文件或目录的绝对路径。
  • 别名名称包含大写字母、数字、下划线等,如果是字母则都要大写。
  • 一个别名下包含多个成员,成员与成员之间,通过半角","号进行分割;成员必须是有效且实际存在的。
  • 别名成员受别名类型 Host_Alias、User_Alias、Runas_Alias、Cmnd_Alias的制约,定义什么类型的别名,就要有什么类型的成员与之相配。
  • 别名规则是每行算一个规则,如果一行容不下,则可以通过""来续行。
  • 指定切换的用户要用"()"(括号)括起来。如果省略括号,则默认为root用户;如果括号里是ALL,则代表能够切换到所有用户。
  • 如果希望不需要密码就直接运行命令,则应该加上“NOPASSWD:”参数。
  • 若想禁止某类程序或命令执行,则要在命令动作前面加上“!”号,并且放在允许执行命令的后面。
  • 用户组前面必须加"%"号。

15.1.2 /etc/sudoers配置文件别名知识

sudoers文件中的别名类型(Alias_Type)包括如下四种。

1)Host_Alias,表示定义主机别名,实际配置语法如下:

Host_Alias FILESERVERS = fs1 , fs2  #请注意定义规范,"="号两边最好有空格。
Host_Alias MAILSERVERS = smtp , smtp2   #请注意定义规范,每个成员之间用逗号进行分割。

关于Host_Alias的说明具体如下。

  • 在生产场景中,一般不需要设置主机别名,在定义授权规则时可以通过ALL来匹配所有的主机。

  • 请注意上面定义的规范,有些规范虽然不是必须的,但最好能够按照系统的标准来进行配置,这样可以避免意外问题的发生。

  • 其实,主机名就是一个逻辑上的主机组,当多台服务器共享一个/etc/sudoers的时候就会用到这个主机别名。不过,在实际企业运维中,这个需求几乎是不存在的。

    在sudo实际授权语法规则配置时,第一个ALL的位置就是主机别名的配置位置,示例代码如下:

    root    ALL=(ALL)       ALL #第一个ALL就是主机别名的应用位置。
    

    2)User_Alias,表示定义用户别名,别名成员可以是用户、用户组(用户组前面要加“%”号),实际配置语法如下:

    User_Alias ADMINS = jsmith, mikem, %groupname       #提示:设置用户别名也不是必需的,更多情况下,可以通过“groupname”的方式一次性设定用户组配置,以后若有成员增加,则将新成员加入准备好的用户组就可以了。
    

    3)Runas_Alias,表示定义runas别名,这个别名指定的是授权的“用户身份”,即sudo允许切换到的用户身份。

    Runas_Alias定义的是可以执行sudo命令身份的用户,实际配置语法如下:

    Runas_Alias OP = root
    

    实际工作中都是普通用户需要转换到root身份,普通用户之间权限相同,极少有授权其他普通用户身份的需求。

    4)Cmnd_Alias,表示定义命令别名,命令别名就是定义一个别名,然后别名里面包含一堆命令,即一组相关命令的集合,实际配置语法如下:

## Command Aliases
## These are groups of related commands...
## Networking
Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool
## Installation and management of software
Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum
## Services
Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig
#提示:命令别名就是设置一组可以执行的命令集合,可以将不同类的命令分为不同的组,例如磁盘命令管理组、网络命令管理组等。

15.1.3 别名和授权规则配置语法对应关系说明

在/etc/sudoers配置文件中,别名和配置语法的对应关系间表15-1.

表15-1 /etc/sudoers配置文件中别名和配置语法的对应关系

b15-1.png

在企业运维工作中,什么情况下会使用到别名知识?

解答: 当工作中有很多台服务器,每台服务器又包含多个系统用户,需要对用户权限进行严格管理(关键命令的使用)、分层授权管理用户的时候。

15.1.4 利用别名配置授权实践案例

由于主机别名在工作中极少使用,因此下面的例子中没有使用主机别名,不过其他的别名都有涉及。

15.1.4.1 根据管理员管理功能,定义多个用户别名

1)定义系统管理用户别名为ADMINS,包含成员neteagle、ett及sa组的成员,命令如下:

User_Alias ADMINS = neteagle, ett, %sa  #注意定义的规范

2)定义用户别名NETADMINS来管理网络,包含成员leo和maya,命令如下:

User_Alias NETADMINS = leo, maya    #网络管理员组NETADMINS。

3)定义用户别名USERADMINS来管理系统用户,包含成员zuma,命令如下:

User_Alias USERADMINS = zuma    #用户管理员组USERADMINX。

说明:

为了方便管理,应尽可能使用有意义的名称作为别名,定义时使用大写字符串。另外,所有定义的用户及用户组内包含的用户或成员都不洗是系统中存在的用户或存在的组。

4)检查并创建上述用户及用户组(用户和用户组都必须存在),命令如下:

[root@centos7 ~]# groupadd sa   #添加sa组。
[root@centos7 ~]# useradd leo   #依次添加5个用户。
[root@centos7 ~]# useradd maya
[root@centos7 ~]# useradd zuma
[root@centos7 ~]# useradd ett
[root@centos7 ~]# useradd neteagle

15.1.4.2 根据命令的功能分类定义命令别名

1)定义命令别名USERCMD,包含管理系统用户的相关命令,命令如下:

Cmnd_Alias USERCMD = /usr/sbin/useradd, /user/sbin/userdel, \
/usr/bin/passwd [A-Za-z]*, /bin/chown, /bin/chmod   #用户相关命令组USERCMD

2)定义命令别名DISKCMD,包含管理系统磁盘的相关命令,命令如下:

Cmnd_Alias DISKCMD = /sbin/fdisk, /sbin/parted  #磁盘管理相关命令组DISKCMD

3)定义命令别名NETMAGCMD,包含管理系统网络的相关命令,命令如下:

Cmnd_Alias NETMAGCMD = /sbin/ifconfig, /etc/init.d/network  #网络管理命令组。

说明:

1)所有命令别名下的命令都必须使用绝对路径。

2)命令别名超过一行时,可以通过“\”号换行续写。

3)在定义时,可以使用通配符及正则表达式,例如,/usr/bin/passwd [A-Za-z]*。

15.1.4.3 定义授权用户的别名

runas别名定义的示例代码如下:

Runas_Alias OP = root , neteagle    

说明: runas别名的定义并不多见,且不常用,因为多数都是需要root身份就够了,默认ALL也可以。

15.1.4.4 根据别名配置对应的sudo授权规则

1)管理员别名(ADMINS)可以收起所有命令通过sudo进行管理,示例代码如下:

ADMINS ALL= (OP) DISKCMD,USERCMD,NETMAGCMD

2)用户管理员别名(USERADMINS)可以授权与用户命令别名对应的命令通过sudo进行管理,示例代码如下:

USERADMINS ALL= (OP) USERCMD

3)网络管理员别名(NETADMINS)可以授权与网络命令别名对应的命令通过sudo进行管理,示例代码如下:

NETADMINS ALL= (OP) NETMAGCMD

这样就完成了对不同的用户授权不同的命令集合,并通过sudo进行管理,让用户对应的权限管理得到了细化。怎么样?很简单吧?

15.2 企业环境中用户权限集中管理项目案例

15.2.1 企业运维问题现状

当前公司里的服务器或虚拟机数量达到上百台时,各个服务器上的管理人员将会很多(开发+运维+架构+DBA+产品+市场等,他们都有用户权限),在大家登陆使用Linux服务器时,不同职能的员工操作水平不同,因此导致操作很不规范,比如,root权限泛滥(几乎大部分人员都有root权限),文件等经常莫名其妙地丢失等。此外,老手和新员工对服务器的熟知程度也不相同,这些都使得公司服务器的安全存在很大的不稳定性及操作安全隐患。据调查,企业服务器环境下,50%以上的安全问题都来自于内部,而不是外部。为了解决单个用户管理权限过大的现状,现提出针对Linux服务器用户权限集中管理的解决方案。

15.2.2 项目需求分析

我们既希望超级用户root的密码掌握在少数或唯一的管理员手中,又希望多个系统管理员或相关的拥有权限的人员,能够完成更多更复杂的自身职能相关的工作,并且不至于有越权操作导致系统安全隐患。

那么,如何实现多个系统管理员都能管理系统而又不让超级权限泛滥的需求呢?这就需要采用sudo管理来替代以往的方式,或者结合su命令来完成这样的苛刻且必要的企业服务器用户管理需求了。

15.2.3 项目需求具体实现说明

针对公司里的不同部门,根据员工的具体工作职能(例如,开发、运维和数据库管理员)。分等级、分层次地实现对Linux服务器管理的权限最小化、规范化。这样既能减少了运维管理成本,消除了安全隐患,又提高了工作效率,从而实现高质量、快速化地完成项目进度,以及日常系统维护工作。

15.2.4 项目实施过程

说明:实施方案一般是由积极主动发现问题的运维人员提出问题,然后写好解决方案,再召集大家讨论可行性,最后确定方案,实施部署,之后就是后期的总结维护了。

思想:在提出问题之前,一定要想到如何解决,并给出解决方案。

假设现状你以及写完了权限规划文档(见附录A和附录B)。

做项目,相当于一次变法:变法是有代价的,取得“老大”(运维总监、技术总监)的支持极其重要。

15.2.4.1 信息采集(含整个方案流程)

1)召集相关部门的领导,通过会议讨论,或者是与各组领导沟通以确定权限管理方案的可行性。

需要支持的人员:运维经理或总监、CTO、各部门组的领导。作为运维人员,拿着类似本书介绍的项目方案(本章内容),通过会议形式为大家讲解文档,以期取得各部门组领导的支持和认可,这才是项目能够得以最终实施的前提。当然,即使实施不了,你的能力也得到了锻炼,各部门组领导对你积极主动思考问题的态度也会另眼相看的。

2)确定方案的可行性之后,会议负责人汇总、提交、审核所有相关员工对Linux服务器的权限需求。

取得各部门组领导的支持后,通过发邮件或者联系相关人员取得相应的权限信息。比如说,请各个部门的经理整理归类本部门需要登录Linux权限的人员名单、职位、以及负责的业务及权限等,如果无法清楚描述权限细节,就描述所负责的业务细节,这样,运维人员就可以确定各相关人员具体需要的权限了(见表15-2)。

3)按照需要执行的Linux命令程序及公司业务服务来规划权限和人员的对应配置。

主要是运维人员根据上面收集的人员名单、需要的业务及权限角色,并根据对应的账号配置权限,实际上就是配置sudo配置文件。

4)权限方案一旦实施之后,所有的员工都必须通过《员工Linux服务器管理权限申请表》来申请对应的权限,确定审批流程,规范化管理。这里实施权限方案之后一定要控制住后期的权限申请流程,否则,大家不按要求来,即使方案实施完也会半途而废的。

5)撰写操作说明,对各部门人员进行操作讲解。通过sudo执行命令,若会涉及PATH变量问题,则运维需要提前处理好。

表15-2 信息采集表格

b15-2.png

15.2.4.2 收集员工职能和对应的权限

收集员工职能和对应权限的过程需要召集大家开会确定,或者请各组领导安排人员进行统计汇总。将需要权限的人员及对应的工作职责交给运维人员,又运维人员优化职位所对应的系统权限,具体见表15-3至15-7.

表15-3 运维组的级别和权限

b15-3.png

表15-4 开发组的级别和权限

b15-4.png

表15-5 架构组的级别和权限

b15-5.png

表15-6 DBA组的级别和权限

b15-6.png

表15-7 网络组的级别和权限

b15-7.png

提示: 如果授权ALL,那么在进行故障排除时,有时会让我们防不胜防。这种先开后关的策略并不是好的策略。比较好的策略,是白名单机制,即只写授权命令,不用ALL。

15.2.4.3 模拟创建用户角色

1)建立3个初级运维,一个高级运维,一个网络工程师,一个运维经理,密码统一是111111。示例代码如下:

for user in chuji001 chuji002 chuji003 net001 senior001 manager001
do
    useradd $user
    echo "111111" |passwd --stdin $user
done

2)建立5个开发人员,属于phpers组。示例代码如下:

groupadd -g 1999 phpers
for n in `seq 5`
do
    useradd -g phpers php00$n
    echo "111111" |passwd --stdin php00$n
done
for user in kaifamanager001 seniorphpers
do
    useradd $user
    echo "111111" |passwd --stdin $user
done    

3)根据前面的表格配置sudoers文件对应的内容。示例代码如下:

##各种别名定义
##Cmnd_Alias by neteagle##2020
Cmnd_Alias CY_CMD_1 = /usr/bin/free, /user/bin/iostat, /usr/bin/top, /bin/hostname, /sbin/inconfig. /bin/netstat, /sbin/route
Cmnd_Alias GY_CMD_1 = /usr/bin/free, /user/bin/iostat, /usr/bin/top, /bin/hostname, /sbin/inconfig. /bin/netstat, /sbin/route, /sbin/iptables, /etc/init.
d/network, /bin/noce, /bin/kill, /usr/bin/kill, /usr/bin/killall, /bin/rpm, /usr/bin/up2date, /usr/bin/yum, /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbi
n/partprobe, /bin/mount, /bin/umount
Cmnd_Alias CK_CMD_1 = /usr/bin/tail /app/log*, /bin/grep /app/log*, \
/bin/cat, /bin/ls
Cmnd_Alias GK_CMD_1 = /sbin/service, /sbin/chkconfig, /bin/tail /app/log*, /bin/grep /app/log*, /bin/cat, /bin/ls, /bin/sh ~/scripts/deploy.sh
Cmnd_Alias GW_CMD_1 = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, \
/usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, \
/sbin/iwconfig, /sbin/mii-tool, /bin/cat /var/log/*
#####################################################################
## User_Alias by neteagle##2020
User_Alias CHUJIADMINS = chuji001,chuji002,chuji003
User_Alias GWNETADMINS = net001
User_Alias CHUJI_KAIFA = %phpers
​
## Runas_Alias by neteagle##2020/10/19
#Runas_Alias OP = root
​
#pri config
senior001                ALL= (OP) GY_CMD_1
manager001               ALL= (ALL) NOPASSWD:ALL
#kaifamanager001 ALL= (ALL) ALL, /usr/bin/passwd [A-Za-z]*,!/usr/bin/passwd root,!/usr/sbin/visudo,!/usr/bin/vi *sudoer*
kaifamanager001 ALL= (ALL) ALL, /usr/bin/passwd [A-Za-z]*,!/usr/bin/passwd root,!/usr/sbin/visudo,!/usr/bin/vim, !/bin/vi,!/usr/bin/sudo su -,!/bin/su
#授权规则
seniorphpers ALL= (OP) GK_CMD_1
CHUJIADMINS  ALL= (OP) CY_CMD_1
GWNETADMINS      ALL= (OP) GW_CMD_1
CHUJI_KAIFA  ALL= (OP) CK_CMD_1
#注意:
1)别名名字要大写。
2)所有命令的路径均要使用全路径,每个命令之间用逗号进行分隔。
3)超过一行用“\”换行。
4)!号表示排除。
5)无法控制Linux Bash内置命令。

15.2.4.4 项目结束其他扫尾工作

1)配置完毕后,需要使用不同的用户登录实战调试测试。

2)调试成功后发邮件通知所有人权限配置生效,并附带操作说明。

3)尽快给参与使用的人,进行培训讲解,以确保大家都能熟练操作。

4)制定新的权限申请流程及申请表(见附录B)。

15.2.4.5 项目结束后的后期维护规则

  • 项目结束后,后期的维护不再是特别紧急的需求,一律走权限申请流程。
  • 服务器多了,可以通过ansible分发软件批量分发/etc/sudoers文件(注意权限和语法检查)。
  • 除了进行权限上的控制,在账户有效时间上也要进行限制,这样才能让安全最大化。
  • 将所有应用服务降权到用普通用户运行,并将所有的程序都放在对应的用户家目录下面。启动的时候也是通过这个账户运行,这样就可以用普通用户权限启动和停止对应服务了。

15.3 记录所有用户执行sudo命令的操作日志

所谓sudo命令日志审计,并不是记录普通用户的普通命令操作,而是记录那些执行sudo命令的用户操作。

15.3.1 企业日志审计解决方案

所谓日志审计,就是记录所有系统及相关用户行为的信息,并且可以自动分析、处理、展示(包括文本或者录像)。

方案1,通过环境变量命令及rsyslog服务进行全部日志审计(审计信息太大,不推荐)。

方案2,通过sudo的配置参数进行日志审计(审计信息较少,效果不错)。

方案3,在bash解释器程序里嵌入一个监视器,让所有被审计的系统用户使用修改过的增加了监视器的特殊bash程序作为解释程序(老男孩教育开源产品)。

方案4,齐治堡垒机:商业产品。

方案5,Python开源产品:开源跳板机(堡垒机)Jumpserver或CrazyEye(Alex老师开源产品),如果读者会Python,那么可以选择更高大上的开源跳板机产品,老男孩教育的课程也会讲解这个方案。

15.3.2 利用sudo配置日志审计

首先增加配置“Defaults logfile=/var/log/sudo.log”到/etc/sudoers中,注意,不包含引号:

[root@centos7 ~]# echo "Defaults logfile=/var/log/sudo.log" >>/etc/sudoers

sudo日志审计代码比较简单,具体如下:

[root@centos7 ~]# tail -1 /etc/sudoers
Defaults logfile=/var/log/sudo.log
[root@centos7 ~]# visudo -c     #检查sudoers文件语法。
/etc/sudoers: parsed OK

此时会自动建立一个/var/log/sudo.log文件(日志中配置的名字),并且文件权限为600(-rw-------),所有者和组均为root(如果看不到日志文件,就退出重新登录看看),实现代码如下:

[root@centos7 ~]# ll /var/log/sudo.log  #这里可能没有这个日志文件,先进行下面操作。
-rw-------. 1 root root 467 Oct 19 17:36 /var/log/sudo.log

配置完成后,就可以测试sudo日志审计配置结果了。

执行useradd neteagle命令创建neteagle用户,并在visudo中进行如下授权操作:

neteagle ALL= (ALL) /bin/ls     #授权neteagle用户以所有用户身份(含root)执行ls命令。

然后,切换到neteagle用户下进行测试,代码如下:

[root@centos7 ~]# su - neteagle     #切换到neteagle用户下。
Last login: Mon Oct 19 17:34:40 CST 2020 on pts/0
[neteagle@centos7 ~]$ ls /root  #不用sudo操作,提示权限不够。
ls: cannot open directory /root: Permission denied  #权限不够。
[neteagle@centos7 ~]$ sudo ls /root #通过sudo执行,可以列出/root下的目录,授权成功。
​
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
​
    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.
​
[sudo] password for neteagle: #输入neteagle用户密码。
anaconda-ks.cfg  #现在就可以看到/root目录下的文件。
[neteagle@centos7 ~]$ logout    #回到root环境。
[root@centos7 ~]# cat /var/log/sudo.log     #以及记录了neteagle的sudo日志执行情况。
Oct 19 17:36:58 : neteagle : TTY=pts/0 ; PWD=/home/neteagle ; USER=root ;
    COMMAND=/bin/ls /root   #哇,好清晰啊。谁做了什么坏事,一眼就能查到。
[root@centos7 ~]# ll /var/log/sudo.log 
-rw-------. 1 root root 467 Oct 19 17:36 /var/log/sudo.log  #root权限,普通用户无法删除和修改。

从测试结果来看,所有的普通用户执行sudo的命令都被记录监控了,这样一旦出现异常行为,就可以通过日志记录进行追查。