Здесь я хотел бы поделиться мыслями по поводу использования ansible2.1 в среде с ограниченными sudo правами (ansible+limited sudo), a именно использование ansible пользователями у которых есть только ограниченный набор sudo команд. К таким пользователям можно отнести например, девелоперов и саппорот команды. Особенно яркое разделение ролей можно увидеть в крупных компаниях, где есть например админы с root правами (отвечают за инфраструктуру и provisioning серверов), где есть operations команды (отвечают за поддержку приложений, баз данных и т.д), девелоперы (отвечают за деплой и траблшутинг приложений). У этих “бесправных” пользователей есть определенный набор sudo команд, которых в принципе достаточно для выполнения своих задач. Но когда ферма приложения состоит из 50 серверов и хостится где-нибудь в AWS+Autoscaling, и есть необходимость отрестартить сервис, то ansible с его AWS инвентори сильно облегчит работу. Но как я уже упомянул есть проблема, а именно если пользователю разрешен только ограниченный набор sudo команд, то использование ansible не всегда будет возможным, т.к ansible отсылает на сервер Python код который нужно выполнить, а /usr/bin/python не добавлен в sudo. Можно попробовать использовать модуль raw, но и тут есть проблема, ansible попытается выполнить команду через /bin/sh –c, а /bin/sh или /bin/bash также не добавлены в sudo.
Это можно увидеть если запустить ansible с –vvv ключем.
[roonyk@ ansible]$ ansible hosts -m raw -a "/bin/netstat -ltupn" --become --ask-become-pass -k -vvv
Using /home/roonyk/ansible/ansible.cfg as config file
SSH password:
SUDO password[defaults to SSH password]:
<10.242.39.205> ESTABLISH SSH CONNECTION FOR USER: roonyk
<10.242.39.205> SSH: EXEC sshpass -d11 ssh -C -q -o ControlMaster=auto -o ControlPersist=1800s -o User=roonyk -o ConnectTimeout=10 -o ControlPath=/home/roonyk/.ansible/cp/%h-%r -tt 10.242.39.205 'sudo -H -S -p "[sudo via ansible, key=zjzgvjphdogumqoudyuncoypfwlabpvu] password: " -u root /bin/bash -c '"'"'echo BECOME-SUCCESS-zjzgvjphdogumqoudyuncoypfwlabpvu; /bin/netstat -ltupn'"'"''
10.242.39.205 | FAILED | rc=1 >>
Sorry, user roonyk is not allowed to execute '/bin/bash -c echo BECOME-SUCCESS-zjzgvjphdogumqoudyuncoypfwlabpvu; /bin/netstat -ltupn' as root on ip-10-242-39-205.us-east-1.aws.cloud.test.com.
[roonyk@ ansible]$
Можно попросить администраторов добавить /usr/bin/python и /bin/bash в sudo, но по различным причинам они скорее всего не согласятся на это (особенно в крупных компаниях).
Но можно попробовать написать свой connection plugin который немного переопределит метод make_become_cmd отвечающий за формат засылаемых команд.
В моем случае это файлик ssh_sudo.py который необходимо поместить в папку connection_plugins и добавить путь к этой папке в конфигурационном файле. Также в конфигурационном файле в качестве транспорта указать свой свой ssh_sudo.
transport = ssh_sudo
connection_plugins = ./connection_plugins
Код самого плагина – файл ssh_sudo.py :
import ansible.constants as C
import ansible.plugins.connection.ssh as SSH
import pipes
class Connection (SSH.Connection):
def __init__(self, play_context, *args, **kwargs):
super (Connection, self).__init__(play_context, *args, **kwargs)
self._make_become_cmd = self._play_context.make_become_cmd
self._play_context.make_become_cmd = self.make_become_cmd
def make_become_cmd (self, cmd, executable = None):
becomecmd = self._make_become_cmd(cmd, executable=None)
if cmd.split('=')[0] == 'sudo':
command = cmd.split('=')[1]
exe = self._play_context.become_method
flags = getattr(C, 'DEFAULT_%s_FLAGS' % self._play_context.become_method.upper(), None)
prompt = self._play_context.prompt
user = self._play_context.become_user
success_key = self._play_context.success_key
sudocmd = '%s -k && setsid %s %s-p "%s" -u %s %s;' 'rc=$?; echo %s; exit $rc' % \
(exe, exe, flags.replace('-n',''), prompt, user, command, success_key)
becomecmd = '$SHELL -c ' + pipes.quote (sudocmd)
return (becomecmd)
Теперь запустив ansible увидим что команда выполнилась.
[roonyk@EPBYMINW4969 ansible]$ ansible hosts -m raw -a "sudo=/bin/netstat -ltupn" --become --ask-become-pass -k -vvv
Using /home/roonyk/ansible/ansible.cfg as config file
SSH password:
SUDO password[defaults to SSH password]:
<10.242.39.205> ESTABLISH SSH CONNECTION FOR USER: roonyk
<10.242.39.205> SSH: EXEC sshpass -d11 ssh -C -q -o ControlMaster=auto -o ControlPersist=1800s -o User=roonyk -o ConnectTimeout=10 -o ControlPath=/home/roonyk/.ansible/cp/%h-%r -tt 10.242.39.205 '$SHELL -c '"'"'sudo -k && setsid sudo -H -S -p "[sudo via ansible, key=yfutrphrslijpnomjaxgqahoqiigoupt] password: " -u root /bin/netstat -ltupn;rc=$?; echo BECOME-SUCCESS-yfutrphrslijpnomjaxgqahoqiigoupt; exit $rc'"'"''
10.242.39.205 | SUCCESS | rc=0 >>
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:46911 0.0.0.0:* LISTEN 967/rpc.statd
tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 11717/java
tcp 0 0 0.0.0.0:5666 0.0.0.0:* LISTEN 8227/nrpe
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN 1069/snmpd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 927/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1775/sshd
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 3646/master
tcp 0 0 :::5666 :::* LISTEN 8227/nrpe
tcp 0 0 :::43874 :::* LISTEN 967/rpc.statd
tcp 0 0 :::111 :::* LISTEN 927/rpcbind
tcp 0 0 :::80 :::* LISTEN 7441/fcgi-
tcp 0 0 :::22 :::* LISTEN 1775/sshd
udp 0 0 0.0.0.0:33151 0.0.0.0:* 967/rpc.statd
udp 0 0 0.0.0.0:161 0.0.0.0:* 1069/snmpd
udp 0 0 0.0.0.0:678 0.0.0.0:* 927/rpcbind
udp 0 0 0.0.0.0:68 0.0.0.0:* 825/dhclient
udp 0 0 127.0.0.1:719 0.0.0.0:* 967/rpc.statd
udp 0 0 0.0.0.0:111 0.0.0.0:* 927/rpcbind
udp 0 0 10.242.39.205:123 0.0.0.0:* 1675/ntpd
udp 0 0 127.0.0.1:123 0.0.0.0:* 1675/ntpd
udp 0 0 0.0.0.0:123 0.0.0.0:* 1675/ntpd
udp 0 0 :::678 :::* 927/rpcbind
udp 0 0 :::59621 :::* 967/rpc.statd
udp 0 0 :::111 :::* 927/rpcbind
udp 0 0 fe80::83a:72ff:fec6:c747:123 :::* 1675/ntpd
udp 0 0 ::1:123 :::* 1675/ntpd
udp 0 0 :::123 :::* 1675/ntpd
[roonyk@ ansible]$
.
Комментарии