实验环境:RHEL5.8 32Bit

sudo详解

·Linux的用户只有两类

    1,管理员用户

    2,普通用户

·sudo

    我们学过的su(switch user)命令是用来切换用户身份的命令,而sudo命令是一种切换用户来执行某种操作的命令,sudo COMMAND,该命令可以使得我们的当前用户以另外一个用户的身份去执行某个命令,但是并不需要切换到目标用户的身份,只不过在执行对应命令的那一刻,当前用户暂时拥有了目标用户的权限,这种机制有一点类似于SUID,二者同样表示的都是在执行命令的时候使用的不是当前用户的身份而是目标用户的身份,而且不用切换至目标用户的身份,却可以以目标用户的身份去执行某条命令,但是当前用户使用sudo所能执行的命令仅仅限于目标用户定义给当前用户的那些命令,其它未定义的命令就算使用了sudo也不能使用,事实上sudo就是用来定义某个用户能够以目标用户(未必是管理员,但是该用户我们可以自己指定)的身份通过某主机执行某条命令的机制,说的通俗一点就是谁可以以另外哪一个人的身份在哪个主机上执行哪个命令,但是这种机制有一种安全措施,只要某用户想要使用目标用户定义给他的可以使用的管理系统类命令的时候,必须向服务器提供他自己的密码,这种安全机制可以防范别人恶意冒充某用户使用sudo利用目标用户的身份去执行一些系统管理类的命令,以上就是sudo提供给我们的所有管理功能,总的来说,sudo的功能就是管理员所有可以执行的命令或者其他用户所有可以执行的命令都可以授权给另外一个用户来执行,一般来讲我们使用sudo的时候,都是将管理员用户的身份授权给其他用户来执行一些系统管理类命令。

·sudo的配置文件

    sudo的配置文件是/etc/sudoers,这个文件的安全性很重要,所以为了避免其他用户查看该文件,这个文件的权限是440:

    

wKiom1hR7vmxWDU5AAAMeARV0SI411.png


    只有root用户和root组中的用户可以查看该文件,由于该文件中定义了哪个用户可以执行哪些系统管理类的命令,故该文件的内容不能被其他用户任意查看,又由于该文件是只读的,所以我们不可以手动去修改该文件,但是sudo给我们提供了一个专门的命令用来编辑/etc/sudoers这个文件,这个命令叫做visudo,而且该命令还可以去检查该文件中的语法的正确性:

    

wKiom1hR7_DxdFhQAAAKKuQSE-E494.png


    该命令默认就是去编辑/etc/sudoers这个文件,如果我们想要去编辑其他文件的话,可以使用-f选项来指定其他文件:

    

wKiom1hR8OyCdvePAAAsdfsOgKo429.png


    /etc/sudoers这个配置文件的语法格式其实很简单,如果不是语法自身的某些关键字定义的某些功能的话,那么它的每一行通常表示定义了一个sudo条目,而一个sudo条目其实就是定义了哪个用户能够以另外哪个用户的身份在哪些主机上执行哪些命令的意思。

·sudo条目的语法格式

    who(谁)  which_hosts(能够在哪些主机上)=(runas(以谁的身份))  COMMAND(运行哪些命令)

        which_hosts表示的不是在其他主机上面去执行我们要执行的命令,而是指定的其它主机可以在我们本地主机执行相关的命令:

    

     1 ## Sudoers allows particular users to run various commands as
     2 ## the root user, without needing the root password.
     3 ##
     4 ## Examples are provided at the bottom of the file for collections
     5 ## of related commands, which can then be delegated out to particular
     6 ## users or groups.
     7 ##
     8 ## This file must be edited with the 'visudo' command.
     9 
     10 ## Host Aliases
     11 ## Groups of machines. You may prefer to use hostnames (perhap using
     12 ## wildcards for entire domains) or IP addresses instead.
     13 # Host_Alias     FILESERVERS = fs1, fs2
     14 # Host_Alias     MAILSERVERS = smtp, smtp2
     15 
     16 ## User Aliases
     17 ## These aren't often necessary, as you can use regular groups
     18 ## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
     19 ## rather than USERALIAS
     20 # User_Alias ADMINS = jsmith, mikem
     21 
     22 
     23 ## Command Aliases
     24 ## These are groups of related commands...
     25 
     26 ## Networking
     27 #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
     28 
     29 ## Installation and management of software
     30 #Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum
     31 
     32 ## Services
     33 #Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig
     34 
     35 ## Updating the locate database
     36 #Cmnd_Alias LOCATE = /usr/bin/updatedb
     37
     38 ## Storage
     39 #Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /        bin/umount
     40 
     41 ## Delegating permissions
     42 #Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp
     43 
     44 ## Processes
     45 #Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall
     46 
     47 ## Drivers
     48 #Cmnd_Alias DRIVERS = /sbin/modprobe
     49 
     50 # Defaults specification
     51 
     52 #
     53 # Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
     54 #         You have to run "ssh -t hostname sudo <cmd>".
     55 #
     56 Defaults    requiretty
     57 
     58 #
     59 # Refuse to run if unable to disable echo on the tty. This setting should also be
     60 # changed in order to be able to use sudo without a tty. See requiretty above.
     61 #
     62 Defaults   !visiblepw
     63 
     64 Defaults    env_reset
     65 Defaults    env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR \
     66                         LS_COLORS MAIL PS1 PS2 QTDIR USERNAME \
     67                         LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION \
     68                         LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC \
     69                         LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS \
     70                         _XKB_CHARSET XAUTHORITY"
     71 
     72 ## Next comes the main part: which users can run what software on
     73 ## which machines (the sudoers file can be shared between multiple
     74 ## systems).
     75 ## Syntax:
     76 ##
     77 ##  user    MACHINE=COMMANDS
     78 ##
     79 ## The COMMANDS section may have other options added to it.
     80 ##
     81 ## Allow root to run any commands anywhere
     82 root    ALL=(ALL(表示一种宏,是一种通配符,表示任意的意思))   ALL
         ->该条目表示管理员用户可以以任意用户的身份通过任意主机在我们本地主机执行任意命令
     83 
     84 ## Allows members of the 'sys' group to run networking, software,
     85 ## service management apps and more.
     86 # %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS
     87 
     88 ## Allows people in group wheel to run all commands
     89 # %wheel    ALL=(ALL)   ALL
     90 
     91 ## Same thing without a password
     92 # %wheel    ALL=(ALL)   NOPASSWD: ALL
     93 
     94 ## Allows members of the users group to mount and unmount the
     95 ## cdrom as root
     96 # %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom
     97 
     98 ## Allows members of the users group to shutdown this system
     99 # %users  localhost=/sbin/shutdown -h now
     100

    我们还可以在/etc/sudoers文件中使用Defaults关键字来定义一些默认属性。

·sudo的别名机制

    为了便捷的管理sudo,sudo还支持一种叫做别名的机制,这种别名的功能类似于我们之前学习的用户组,只不过我们在sudo中把它称作别名,别名的名字全部都得使用大写英文字母而且仅能使用大写英文字母的组合。

    sudo中支持四种类型的别名:

        1,用户别名(User_Alias)

            如果我们要在sudoers文件中定义sudo条目的时候指定多个用户的时候,我们可以使用用户别名将所有的用户定义为一个用户组,一般来讲,一个用户别名可以包含当前系统上的所有用户,之后我们就可以使用用户别名来一次性的定义一批用户。

            定义方法:

                User_Alias USERS(用户别名的名字,由用户自定义)=user1,user2,...

                    不同的用户名之间使用逗号隔开:

                    

wKioL1hShfShlbByAAAGvpfn8go693.png


                    也可以定义用户组,如果定义用户组的话,表明属于该组的用户全部被定义,并且我们在定义用户组的时候,得在组名前面加上%来标识用户组:

                    

wKiom1hSimDA37OPAAAIPXS8rnU934.png


        我们可以定义到用户别名中的内容包括:

            ->系统用户的用户名

            ->使用%引导的用户组名

            ->还可以是其它已经定义过的用户别名,即用户别名是可以嵌套的

        2,主机别名(Host_Alias)

            使用主机别名来定义一组主机,表示在该主机别名里面的主机都可以在我们本地主机执行相关的命令,同样主机别名的名字也都得使用大写的英文字母,可以定义在主机别名里面的内容包括:

            ->可以是一个主机名

                

wKioL1hSiNPzEwxZAAAHYbjO7HE352.png


            ->也可以是一个ip地址,定义ip地址时所使用的子网掩码可以是NETMASK格式或者是CIDR(PREFIX)格式的都可以

            ->或者是一个网络地址

            ->也可以是其它已经定义的主机别名,主机别名在使用的时候也可以嵌套使用

        3,runas别名(Runas_Alias)

            表示我们可以使用另外哪些用户的身份去执行相关命令,可以定义到runas别名中的内容包括:

            ->可以是用户名

            ->也可以是用户的UID,但是定义UID的时候得使用#来标识UID

            ->也可以是%用户组名

            ->也可以是其他已经定义的runas别名,同样runas别名也可以嵌套使用

        4,COMMAND别名(Cmnd_Alias)

            可以定义到COMMAND别名中的内容包括:

                ->命令名(命令名最好使用命令的绝对路径)

                    

wKiom1hSi-3T2r3XAAAUwfjc16I683.png


                ->可以是目录,如果是目录的话,表示该目录下的所有命令都被定义到COMMAND别名里面

                ->也可以是其它已经定义的别名,COMMAND别名同样可以嵌套使用

    我们也可以混合使用别名,比如说我们定义一个sudo条目的时候,可以只使用用户别名,而其余三个都不使用别名,但是别名必须先定义后使用,这一点和变量的定义是一样的,别名的定义遵循EBNF语法结构,EBNF是一种描述性的语言,这种描述性的语言可以定义一个宏,无论是使用用户别名还是主机别名还是其它几个别名,我们都可以使用"!"取反,例如:

        ! username 表示在定义用户别名的时候,除了该用户的其它用户都生效

·如何定义sudo条目

    假设我们现在想要使得hadoop用户能够以root用户的身份去执行useradd和usermod命令,实现的方法如下:

    

wKiom1hSlDjgkHjmAAAr20YVa9I169.png


    执行完该命令后我们发现,我们无法使用该命令,原因是hadoop用户没有在root用户的sudoers文件里面定义,所以我们只有在root用户的sudoers文件里面定义了该条目之后才能使用该命令,我们可以在root用户下使用visudo命令定义即可,将该条目定义在root用户的sudoers文件的最后一行即可:

    

wKioL1hSlo3jpfpwAAAHiR4G-e8025.png


        ALL是一种宏,一种通配符,可以表示所有主机,也可以表示所有用户,还可以表示所有命令,并且hadoop用户只能只用我们定义给它的这两个命令,其余的命令无法执行:

        

wKioL1hSlvmxtCJnAAAVL0iXsDs213.png


        

wKiom1hSl4iQxgBTAAASTgaZa-k132.png


        温故:usermod -s命令可以修改用户的默认shell:

            

wKioL1hSl_GxBy3aAAAVYhCY1ro087.png


        我们在第一次使用sudo命令的时候系统会要求我们输入当前用户的密码:

            

wKiom1hSmF2DDgSyAAANU3U7_4g159.png


        但是当当前用户第一次认证通过的时候系统会将当前用户的认证信息记录下来并让它的有效期为5分钟,所以我们使用sudo命令在第一次输入了密码之后的5分钟之内再次使用sudo命令的时候,就不用再次输入当前用户的密码了,这是sudo的一种安全机制:

        

wKiom1hSmWiTESCbAAAYmGvUMUQ553.png


        但是为了避免在这仅有的5分钟之内,有人恶意的使用我们的sudo命令的时候,sudo给我们提供了一个-k选项,-k选项表示无论我们每次使用sudo命令的间隔有多长,都得输入当前用户的密码,即使得我们每次使用sudo命令时的输入的认证信息失效,并在下一次使用的时候重新进行认证:

        

wKiom1hSnBzjt5MOAABSUf6_aZE552.png


        最安全的用法就是我们在每次使用sudo命令的时候都带上-k选项,-k选项表示使得认证信息失效,我们可以在每次执行sudo命令的时候都使用-k选项,这样即使我们在执行sudo命令的那一刻输入了认证信息,系统也不会将该认证信息记录下来。

    作为一个普通用户来讲,我们可以使用sudo -l命令来列出当前用户所有可以使用的sudo类命令:

    

wKiom1hSnLHy-JfxAAA-VHicIaE100.png


    作为管理员,我们去定义sudo条目的时候,也可以使得普通用户在使用sudo命令的时候一直都不用输入密码,我们只需在定义sudo条目的时候,在命令前面加上标签(TAG)即可,格式:

                who  which_hosts=(runas)  TAG:command

        这些标签中最常用的就是NOPASSWD,这个标签表示任何用户在使用sudo命令的时候都不用输入密码去验证,所有位于该标签后面的命令在执行的时候都不用输入密码去验证:

        

wKioL1hSogPyHeXMAAAIuhexTuM037.png

  

        

wKioL1hSop_xHq71AAAX-JFGFsQ039.png

 

        但是我们如果只希望某些命令在执行时不需要输入密码,而另一些命令在执行的时候需要输入密码,可以在希望不输入密码的命令前面加上NOPASSWD标签,而在希望输入密码的命令前面加上PASSWD标签即可:

        

wKioL1hSo1LSP8wyAAAI2uGowHM619.png


        

wKiom1hSo6XwOUMoAAAc4uf6ICw261.png


        如果我们需要定义的命令有很多,我们完全可以将这些命令全部定义为命令别名:

        

wKiom1hSpQriUZbKAAAYXVd_pwU968.png


        

wKiom1hSpbXSw5uXAABJLGN2JxE684.png


        

wKioL1hSphGQinE_AAAY_GouKnM563.png


        由上图知,虽然我们定义了hadoop用户的用户别名中不能使用passwd root命令去修改root的密码,但是仍然可以修改root的密码,那么这种问题我们该如何解决呢?

        所以我们仅仅简单的在定义sudo条目的时候去取反是不行的,我们可以在定义sudo条目的时候去使用globby通配符*,注意,不是正则表达式通配符,正则表达式通配符"*"表示的是"*"前的字符出现0-任意次,而globby的通配符的"*"表示"*"前的字符至少得出现一次,所以我们像下图中这样修改即可:

        

wKioL1hSskmhfxafAAANxkqM1Rc308.png


        

wKiom1hSspDg9ftTAAAuajxGLvs167.png


        sudo还有一个功能就是,其它任何用户以管理员的身份去执行命令的时候,都会被记录到root用户的日志文件里面,而且会明确说明是哪一个用户以管理员的身份去执行了哪些命令的,/var/log/secure文件里面就记录了这样的信息:

        

wKiom1hSszniejKeAAAZ_Hd-60M378.png