Вопрос или проблема
При попытке запустить модуль ansible на сервере назначения (через become) подключение по SSH, похоже, не использует команду “sudo” для смены пользователя на владельца приложения. Используется правильный удаленный пользователь, но он не использует “sudo” для перехода на учетную запись app-owner. Конфигурация и выполненная команда описаны ниже.
Я ожидаю, что смогу запускать команды и плейбуки ansible на сервере назначения.
На сервере назначения есть 2 пользователя. Пользователь “myapp”, который владеет директориями и демонами приложения, которое мы пытаемся контролировать. Пользователь “inuser” имеет настроенный /usr/bin/sudo в своих разрешенных функциях без входа в систему и имеет /bin/nologin в качестве своей оболочки в /etc/passwd. Пользователь “inuser” не имеет НИКАКИХ других команд/функций в своих разрешенных функциях без входа в систему (и будет сложно добавить какие-либо дополнительные команды без входа в систему).
На сервере контроллера мы запускаем ansible от имени пользователя “build”. Файл /home/build/.ansible.cfg выглядит следующим образом:
[build@ecombuild01 ~]$ echo ""; grep -v "#" ~/.ansible.cfg | grep -v "^$"
[defaults]
inventory = /sites/utils/local/ansible/hosts
library = /sites/utils/local/ansible/modules/
module_utils = /sites/utils/local/ansible/module_utils/
remote_tmp = /sites/utils/tmp/ansible
local_tmp = /sites/utils/tmp/ansible
forks = 50
poll_interval = 3
transport = smart
module_lang = C
gathering = explicit
gather_subset = virtual
gather_timeout = 4
roles_path = /sites/utils/local/ansible/roles
host_key_checking = False
timeout = 4
remote_user = inuser
log_path = /sites/utils/local/var/log/ansible.log
private_key_file = /home/build/.ssh/rsa_sudo
display_skipped_hosts = False
deprecation_warnings = False
bin_ansible_callbacks = True
nocows = 1
retry_files_enabled = False
allow_world_readable_tmpfiles = True
[privilege_escalation]
become=True
become_method=sudo
become_user=myapp
become_ask_pass=False
[paramiko_connection]
pty=False
[ssh_connection]
ssh_args = -q -C -o ControlMaster=auto -o ControlPersist=60s
control_path_dir = /sites/utils/tmp/.ansible/sockets
scp_if_ssh = smart
sftp_batch_mode = True
[accelerate]
[selinux]
[colors]
[diff]
context = 3
При попытке запустить модуль, я вижу следующий вывод:
[build@buildserver:/home/build] ansible -m attApache ecomtest03 -a "action=status" -b --become-method=sudo --become-user=atg -vvv
ansible 2.6.2
config file = /home/build/.ansible.cfg
configured module search path = [u'/sites/utils/local/ansible/modules']
ansible python module location = /sites/utils/Python-2.7.15/lib/python2.7/site-packages/ansible
executable location = /sites/utils/bin/ansible
python version = 2.7.15 (default, Aug 14 2018, 11:48:06) [GCC 4.4.7 20120313 (Red Hat 4.4.7-18)]
Using /home/build/.ansible.cfg as config file
Parsed /sites/utils/local/ansible/hosts inventory source with script plugin
META: ran handlers
<ecomtest03> ESTABLISH SSH CONNECTION FOR USER: inuser
<ecomtest03> SSH: EXEC ssh -vv -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=inuser -o ConnectTimeout=4 ecomtest03 '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `" && echo ansible-tmp-1554330491.64-221707721970475="` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `" ) && sleep 0'"'"''
<ecomtest03> (1, '', 'OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013\ndebug1: Reading configuration data /home/build/.ssh/config
debug1: Applying options for *
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to ecomtest03 [135.163.163.134] port 22.
debug2: fd 3 setting O_NONBLOCK
debug1: fd 3 clearing O_NONBLOCK
debug1: Connection established.
debug2: key_type_from_name: unknown key type \'-----BEGIN\'
debug2: key_type_from_name: unknown key type \'-----END\'
debug1: identity file /home/build/.ssh/id_dsa type 2
debug1: identity file /home/build/.ssh/id_dsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3
debug1: match: OpenSSH_5.3 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.3
debug2: fd 3 setting O_NONBLOCK
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: [email protected],[email protected],[email protected],[email protected],ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,[email protected]
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,[email protected]
debug2: kex_parse_kexinit: hmac-sha1,[email protected],hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,[email protected],hmac-sha1-96
debug2: kex_parse_kexinit: hmac-sha1,[email protected],hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,[email protected],hmac-sha1-96
debug2: kex_parse_kexinit: none,[email protected],zlib
debug2: kex_parse_kexinit: none,[email protected],zlib
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit: first_kex_follows 0
debug2: kex_parse_kexinit: reserved 0
debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,[email protected]
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,[email protected]
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,[email protected],hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,[email protected],hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,[email protected],hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,[email protected],hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,[email protected]
debug2: kex_parse_kexinit: none,[email protected]
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit:
debug2: kex_parse_kexinit: first_kex_follows 0
debug2: kex_parse_kexinit: reserved 0
debug2: mac_setup: found hmac-sha1
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug2: mac_setup: found hmac-sha1
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<2048<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug2: dh_gen_key: priv key bits set: 143/320
debug2: bits set: 1039/2048
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host \'ecomtest03\' is known and matches the RSA host key.
debug1: Found key in /home/build/.ssh/known_hosts:961
debug2: bits set: 1030/2048
debug1: ssh_rsa_verify: signature correct
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug2: key: /home/build/.ssh/id_dsa (0x560cc4d49fb0)
\n#@# !!! WARNING !!!\n#@#\n#@# blah-blah-message-from-system-admins@#\n\n\n\ndebug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure. Minor code may provide more information\nCredentials cache file \'/tmp/krb5cc_901271\' not found\n
debug1: Unspecified GSS failure. Minor code may provide more information\nCredentials cache file \'/tmp/krb5cc_901271\' not found\n
debug2: we did not send a packet, disable method
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug2: we did not send a packet, disable method
debug1: Next authentication method: publickey
debug1: Offering public key: /home/build/.ssh/id_dsa
debug2: we sent a publickey packet, wait for reply
debug1: Server accepts key: pkalg ssh-dss blen 434
debug2: input_userauth_pk_ok: SHA1 fp be:63:7c:0d:66:1a:23:ec:f8:9b:e3:0f:70:e9:eb:a4:e2:a3:26:f5
debug1: read PEM private key done: type DSA
debug1: Authentication succeeded (publickey).
debug2: fd 5 setting O_NONBLOCK
debug2: fd 6 setting O_NONBLOCK
debug1: channel 0: new [client-session]
debug2: channel 0: send open
debug1: Requesting [email protected]
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug1: Sending environment.
debug1: Sending env LC_ALL = C
debug2: channel 0: request env confirm 0
debug1: Sending env LANG = en_US.UTF-8
debug2: channel 0: request env confirm 0
debug1: Sending command: /bin/sh -c \'( umask 77 && mkdir -p "` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `" && echo ansible-tmp-1554330491.64-221707721970475="` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `" ) && sleep 0\'
debug2: channel 0: request exec confirm 1
debug2: fd 3 setting TCP_NODELAY
debug2: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug2: channel 0: rcvd adjust 2097152
debug2: channel_input_status_confirm: type 99 id 0
debug2: exec request accepted on channel 0
debug2: channel 0: rcvd ext data 330
***************************************************\n ********************************************************\n ** Direct network login to this account is disallowed /etc/nologin **\n ********************************************************\n ***************************************************\n\ndebug2: channel 0: written 330 to efd 6
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype [email protected] reply 0
debug2: channel 0: rcvd eow
debug2: channel 0: close_read
debug2: channel 0: input open -> closed
debug2: channel 0: rcvd eof
debug2: channel 0: output open -> drain
debug2: channel 0: obuf empty
debug2: channel 0: close_write
debug2: channel 0: output drain -> closed
debug2: channel 0: rcvd close
debug2: channel 0: almost dead
debug2: channel 0: gc: notify user
debug2: channel 0: gc: user detached
debug2: channel 0: send close
debug2: channel 0: is dead
debug2: channel 0: garbage collecting
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 1 clearing O_NONBLACK
debug1: fd 2 clearing O_NONBLOCK
Transferred: sent 2840, received 4176 bytes, in 3.0 seconds
Bytes per second: sent 933.4, received 1372.4
debug1: Exit status 1
')
ecomtest03 | UNREACHABLE! => {
"changed": false,
"msg": "Ошибка аутентификации или разрешения. В некоторых случаях вы могли бы аутентифицироваться и не имели разрешения на целевой каталог. Рассмотрите возможность изменения удаленного временного пути в ansible.cfg на путь, корень которого находится в \"/tmp\". Не удалось выполнить команду: ( umask 77 && mkdir -p \"` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `\" && echo ansible-tmp-1554330491.64-221707721970475=\"` echo /var/tmp/ansible-tmp-1554330491.64-221707721970475 `\" ), вышли с результатом 1",
"unreachable": true
}
inuser не может создать DEFAULT_LOCAL_TMP, который является “~/.ansible/tmp“. Это вызывает ошибку:
“msg”: “Ошибка аутентификации или разрешения. В некоторых случаях вы могли бы аутентифицироваться и не имели разрешения на целевой каталог. Рассмотрите возможность изменения удаленного временного пути в ansible.cfg на путь, корень которого находится в “/tmp”.
Вариантом было бы исправить проблему, почему inuser не может создать ~/.ansible/tmp. Вероятно, потому, что у пользователя /bin/nologin нет $HOME.
Более простое решение — создать предложенный путь с корнем в /tmp. Например, /tmp/ansible и настроить его в /home/build/.ansible.cfg
local_tmp = /tmp/ansible
Ответ или решение
Для решения проблемы, связанной с использованием Ansible с целью эскалации привилегий (become) при выполнении команд на удаленном сервере, важно рассмотреть несколько аспектов конфигурации и настроек. Данная ситуация подчеркивает проблему с невозможностью Ansible корректно применить команду «sudo» для перехода на пользователя «myapp».
Теория
Основной составляющей в работе Ansible с удаленными серверами является возможность смены текущего пользователя на целевом сервере с помощью механизма «become». Этот механизм позволяет временно повысить привилегии для выполнения задач от имени другого пользователя (в данном случае — «myapp»), что часто требует передачи команды «sudo». Однако для успешного выполнения такого перехода критически важна корректная настройка конфигурационных файлов как на контролирующем сервере, так и на целевом сервере.
Пример
Ваш текущий конфигурационный файл .ansible.cfg
на контролирующем сервере указывает, что удаленной подключение осуществляется от имени пользователя «inuser», а эскалация осуществляется при помощи «sudo» до пользователя «myapp». Однако, ваш вывод показывает сбой при попытке создать временный каталог, который Ansible пытается выполнить как «inuser», не имея соответствующих прав. Это приводит к ошибке «Authentication or permission failure».
Применение
-
Проверка и настройка пути для временных файлов:
- Как указано в выводе ошибки, текущий путь для временных файлов (
remote_tmp
) может быть проблемным. Рекомендуется изменить его на более доступный путь, например,/tmp/ansible
, который, как правило, доступен для всех пользователей.
- Как указано в выводе ошибки, текущий путь для временных файлов (
-
Настройка прав пользователей:
- Убедитесь, что пользователь «inuser» имеет право использовать команду
sudo
для перехода на «myapp» без необходимости ввода пароля. Это можно настроить в файле/etc/sudoers
с помощью таких строк:inuser ALL=(myapp) NOPASSWD:ALL
- Это позволяет автоматически переключаться на пользователя «myapp», избегая пароля, что необходимо для корректного выполнения Ansible задач.
- Убедитесь, что пользователь «inuser» имеет право использовать команду
-
Проверка конфигурации SSH:
- Убедитесь, что
ssh_args
в конфигурации Ansible не блокируют выполнение команд, особенно если используются специфические опции командной строки SSH, которые могут повлиять на поведениеsudo
.
- Убедитесь, что
-
Использование правильного пользователя и метода эскалации:
- В вашей командной строке явное указание параметров
--become-method=sudo --become-user=myapp
указывает на правильную попытку эскалации привилегий, но убедитесь, что это согласуется с настройками в.ansible.cfg
.
- В вашей командной строке явное указание параметров
-
Обновление и тест конфигураций:
- После изменений конфигурационного файла протестируйте с помощью менее привилегированной команды и убедитесь, что она выполняется должным образом. Это позволяет убедиться в отсутствии базовых ошибок в настройке.
В результате выполнения указанных действий, ваш Ansible должен корректно выполнить эскалацию привилегий, и избавит от ошибок при выполнении playbooks или adhoc команд на удаленном сервере. дополнительно, регулярное обновление версий Ansible и компонентов системы может способствовать устранению случайных несоответствий или багов, влияющих на функциональность.
Постарайтесь внимательно следовать инструкциям и тестировать каждый шаг, чтобы убедиться в правильности настроек и получения ожидаемых результатов.