• Ansible用户管理与实践

    背景

    用Ansible管理用户或执行命令时,我们或许会受到如下困扰:

    1. 在现网应用中,安全加固后的主机是不允许直接以root用户登陆的,而很多命令又需要root用户来执行。
    2. 我们不希望Ansible可以直接管控所有的目标机器,而是希望通过一个跳板机来管理,这样更安全。
    3. Ansible用于管控安装,不可避免的设计到密码等安全信息,如何用密文加固呢?

    本人在实际应用中也遇到了上述问题,通过实践和查阅官网资料得以解决,特此记录。

    基础拓展

    一、Linux中sudo执行命令的流程

    当我们用简单的useradd命令新添加一个用户以后,这个用户在我们的Linux主机里面相当于是一个黑户,他可以在他自己的家目录底下和有限的权限下做有限的事情,日子过的很憋屈。 有一天当我们想赋予这个用户比较大的权限时,我们通常会给他传说中的sudo权限。 那么这个sudo权限又是怎么回事,它具有哪些特性呢 ?

    1. sudo 能够限制用户只能运行某些命令。
    2. sudo 提供了丰富的日志,详细地记录了每个用户干了什么。它能够将日志传到中心主机或者日志服务器。开启sudo的日志可参考这篇博文
    3. sudo 使用时间戳文件来执行类似的“检票”系统。当用户调用sudo并且输入它的密码时,用户获得了一张存活期为5分钟的票(这个值可以在编译的时候改变)。
    4. sudo 的配置文件是sudoers文件,它允许系统管理员集中的管理用户的使用权限和使用的主机。它所存放的位置默认是在/etc/sudoers,属性必须为0411。
    二、 sudo命令的使用

    用法:  sudo command

    说明:以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行

    参数:sudo  ….

    -V 显示版本编号

    -h 会显示版本编号及指令的使用方式说明

    -l 显示出自己(执行 sudo 的使用者)的权限

    -v 因为 sudo 在第一次执行时或是在 N 分钟内没有执行(N 预设为五)会问密码,这个参数是重新做一次确认,如果超过 N 分钟,也会问密码

    -k 将会强迫使用者在下一次执行 sudo 时问密码(不论有没有超过 N 分钟)

    -b 将要执行的指令放在背景执行

    -p prompt 可以更改问密码的提示语,其中 %u 会代换为使用者的帐号名称, %h 会显示主机名称

    -u username/#uid 不加此参数,代表要以 root 的身份执行指令,而加了此参数,可以以 username 的身份执行指令(#uid 为该 username 的使用者号码)

    -s 执行环境变数中的 SHELL 所指定的 shell ,或是 /etc/passwd 里所指定的 shell

    -H 将环境变数中的 HOME (家目录)指定为要变更身份的使用者家目录(如不加 -u 参数就是系统管理者 root )

    三、sudo的配置

    sudoers 是sudo的主要配置文件,linux下通常在/etc目录下,sudo提供了一个编辑该文件的命令:visudo 来对该文件进行修改。强烈推荐使用该命令修改 sudoers,因为它会帮你校验文件配置是否正确,如果不正确,在保存退出时就会提示你哪段配置出错的。

    /etc/sudoers 的规则可分为两类;一类是别名定义,另一类是授权规则;别名定义并不是必须的,但授权规则是必须的。

    1. 最简单的配置,让普通用户test具有root的所有权限

    执行visudo之后,可以看见缺省只有一条配置:

    root    ALL=(ALL) ALL

    那么你就在下边再加一条配置:

    test      ALL=(ALL) ALL

    这样的话test用户就能执行root权限的所有命令了,以test普通用户登录之后,执行

    sudo -s  或者 sudo su –

    然后输入test用户自己的密码,就可以切换成root用户了。当然也可以直接sudo来执行命令,比如执行:

    sudo ls /root

    这时候也会让test用户输入自己的密码,并且此次输入后,在五分钟(默认的,可以设置)再次以这种sudo方式执行命令则不需要再次输入密码了。

    当然我们也可以让test用户具有root用户的所有权限,并且切换时无需密码验证,只需要在配置文件中如下添加:

    test ALL=(ALL)       NOPASSWD: ALL

    2. 让普通用户test只能在服务器上执行root能执行的某些命令

    最简单的举个例子比如我们可以这样的方式赋予test用户执行启动mysql的权限:

    test ALL=NOPASSWD:/etc/init.d/mysql start

    但是这样有个问题,如果我有N个用户具有M个可以执行的命令的话,那岂不是我要这样写很多行,当然不用,我们可以配置一些Alias,这样在配置权限时,会方便一些:

    配置Host_Alias:就是主机的列表,例如:

    # Host_Alias     FILESERVERS = localhost,st05,st04,10,0,0,4,255.255.255.0,192.168.1.0/24

    # Host_Alias     MAILSERVERS = smtp, smtp2

    注: 我们通过Host_Alias 定义主机别名时,项目可以是主机名、可以是单个ip(整段ip地址也可以),也可以是网络掩码;如果是主机名,必须是多台 机器的网络中,而且这些机器得能通过主机名相互通信访问才有效。
    那什么才算是通过主机名相互通信或访问呢?比如 ping 主机名,或通过远程访问主机名来访问。也可以不用设置主机别名,在定义授权规则时通过ALL来匹配所有可能出现的主机情况。

    配置Cmnd_Alias:就是允许执行的命令的列表,命令前加上!表示不能执行此命令,例如:

    Cmnd_Alias STARTMYSQL=/etc/init.d/mysql,/usr/local/mysql/bin

    Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum

    配置User_Alias:就是具有sudo权限的用户的列表,例如:

    User_Alias ADMINS = kobe,james

    配置Runas_Alias:就是用户以什么身份执行(例如root,或者mysql)的列表,例如:

    Runas_Alias OP=root, mysql

    当这些都定义好了以后,我们就可以方便的配置某些用户具有某些权限了,例如:

    格式:User_Alias  Host_Alias=(Runas_Alias) NOPASSWD: Cmnd_Alias

    例如:ADMINS  MAILSERVERS=(OP) NOPASSWD:STARTMYSQL

    上面这句话的含义就是所有ADMINS组的用户都对MAILSERVERS主机组的主机具有以OP组的身份免密执行STARTMYSQL组的命令权限

    内容

    当我们有如下网络环境和ansible管控需求时:

    %e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2017-04-01-%e4%b8%8b%e5%8d%882-26-20

    如上,我只希望对Ansible暴露我跳板机的外网IP地址,然后通过跳板机来管理的那些web服务器,而这些web服务器并没有远程的root登录权限,跳板机只能通过其他普通用户使用sudo权限进行操作,并且我希望我的ansible配置文件里面不要出现任何密码!

    这个场景岂不是刚好符合我们在背景里面提到的那些问题 ?那怎么解决呢 ?

    基础环境准备:

    1. 参考基础拓展里面的内容,为每台web服务器的新建一个devops用户,并赋予sudo权限,使得跳板机可以通过此用户对web机器进行管理。

    2. 在web机器的IPtables打开对跳板机的特殊端口。

    3. 配置Ansible对跳板机的免密码登录(秘钥登录),方便管理。

    Ansible加密

    这里简单介绍Ansible最基础的加密方式,ansible本身提供ansible-vault命令进行文件级别的加密功能,比如我的hosts文件里面保存了很多密码,那么我可以直接把这个文件加密,ansible-vault的使用方法过于简单,这里就不再详细赘述,详情可参考官方文档翻译地址:http://www.ansible.com.cn/docs/playbooks_vault.html?highlight=vault

    hosts文件配置

    比如,我们的环境中对应的IP地址如下(IP地址纯属虚构):

    %e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2017-04-01-%e4%b8%8b%e5%8d%883-54-02

    那么我们就可以在ansible的hosts配置文件里面这样写入:

    然后就可以试着编辑一个playbook测试,内容如下:

    如上,访问root家目录,然后我们执行以下playbook:

    ansible-playbook test.yml

    %e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2017-04-01-%e4%b8%8b%e5%8d%885-44-23

    报错没有权限,当然没有权限拉,因为我们的devops账户不能直接访问web服务器的root家目录啊,但是我们有sudo权限,那么ansible怎么应用sudo权限呢 ?

    我们先在命令行执行ansible –help 之后即可得到你想要的:

    都是最基本的英文,一目了然,简单看看就知道怎么用了,新版本我们用become参数:

    ansible-playbook  test.yml -b –become-method=sudo –become-user=root -K  -vvv

    Using /etc/ansible/ansible.cfg as config file

    SUDO password:

    如上,提示我们输入sudo密码,即devops用户的密码,然后就执行成功了 !!!

    注:还有一点,sudo命令默认是不能在后台运行的,如果需要在后台运行(比如ansible),就需要将/etc/sudoers文件中以下一行注释掉。

    Defaults    requiretty

    否则在执行时,可能会报如下错误:

    192.168.12.10 | FAILED | rc=0 >>

    MODULE FAILURE

    参考

    http://zxf261.blog.51cto.com/701797/748756

    http://www.linuxidc.com/Linux/2016-08/134451.htm