Я бы хотел использовать анзибль для управления группой существующих серверов. Я создал ansible_hosts
файл и успешно протестирован (с -K
option) с командами, которые нацелены только на один хост
ansible -i ansible_hosts host1 --sudo -K # + commands ...
Моя проблема сейчас в том, что пароли пользователей на каждом хосте разные, но я не могу найти способ справиться с этим в Ansible.
С помощью -K
, Мне сначала предлагается только один пароль sudo, который затем, кажется, будет испробован для всех последующих хостов без запроса:
host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password
Исследования на данный момент:
а StackOverflow вопрос с одним неверным ответом ("используйте -K
") и один ответ автора:" Обнаружено, что мне нужно sudo без пароля ".
Документы Ansible, в котором говорится: "Использование sudo без пароля упрощает автоматизацию, но это не требуется. "(выделено мной)
этот вопрос безопасности StackExchange который принимает это как прочитанное, что NOPASSWD
необходимо
статья «Масштабируемая и понятная инициализация ...» который говорит:
«для запуска sudo может потребоваться ввести пароль, что является надежным способом навсегда заблокировать Ansible. Простое исправление - запустить visudo на целевом хосте и убедиться, что пользователю, которого Ansible будет использовать для входа в систему, не нужно вводить пароль»
статья "Основные инструкции по работе с Ansible", что говорит
«Ansible может войти на целевой сервер как root и избежать необходимости в sudo, либо позволить пользователю ansible использовать sudo без пароля, но мысль об этом заставляет мою селезенку угрожать вскочить мне в пищевод и заблокировать мое горло, поэтому я не надо "
Мои мысли точно, но как тогда выйти за рамки одного сервера?
доступный выпуск № 1227, «Ansible должен запрашивать пароль sudo для всех пользователей в playbook», который был закрыт год назад mpdehaan с комментарием «Особого спроса на это не было, я думаю, что большинство людей используют sudo только из одной учетной записи или используют ключи большую часть времени. "
Итак ... как люди используют Ansible в подобных ситуациях? Настройка NOPASSWD
в /etc/sudoers
, повторное использование пароля на разных хостах или включение входа в систему по SSH с правами root - все это довольно сильно снижает безопасность.
Вы определенно провели свое исследование ...
Из всего моего опыта работы с ansible то, чего вы хотите достичь, не поддерживается. Как вы упомянули, в ansible указано, что для него не требуется sudo без пароля, и вы правы, это не так. Но мне еще предстоит увидеть какой-либо метод использования нескольких паролей sudo в ansible, конечно, без запуска нескольких конфигураций.
Итак, я не могу предложить точное решение, которое вы ищете, но вы спросили ...
«Итак ... как люди используют Ansible в подобных ситуациях? Установка NOPASSWD в / etc / sudoers, повторное использование пароля на хостах или включение входа в систему по SSH с правами root - все это кажется довольно резким снижением безопасности».
Я могу дать вам одну точку зрения на это. Мой вариант использования - это 1000 узлов в нескольких центрах обработки данных, поддерживающих глобальную SaaS-фирму, в которой я должен разработать / внедрить некоторые безумно строгие меры безопасности в связи с характером нашего бизнеса. Безопасность всегда балансирует, больше удобства использования меньше безопасности, этот процесс ничем не отличается, если вы используете 10 серверов, 1000 или 100000.
Вы абсолютно правы, если не используете root-логины ни по паролю, ни по ssh-ключам. Фактически, вход в систему root должен быть полностью отключен, если к серверам подключен сетевой кабель.
Давайте поговорим о повторном использовании паролей на большом предприятии. Разумно ли просить системных администраторов иметь разные пароли на каждом узле? для пары узлов, возможно, но мои администраторы / инженеры взбунтовались бы, если бы у них были разные пароли на 1000 узлов. Реализовать это также было бы почти невозможно, каждый пользователь должен был бы где-то хранить свои собственные пароли, надеюсь, keypass, а не электронную таблицу. И каждый раз, когда вы помещаете пароль в место, откуда его можно вывести в виде обычного текста, вы значительно снижаете свою безопасность. Я бы предпочел, чтобы они знали наизусть один или два действительно надежных пароля, чем обращались к файлу keypass каждый раз, когда им нужно было войти в систему или вызвать sudo на машине.
Таким образом, повторное использование паролей и стандартизация - это то, что полностью приемлемо и стандартно даже в безопасной среде. В противном случае не было бы необходимости в ldap, keystone и других службах каталогов.
Когда мы переходим к автоматизированным пользователям, ключи ssh отлично работают, но вам все равно нужно пройти через sudo. Вы можете выбрать стандартный пароль для автоматического пользователя (что во многих случаях приемлемо) или включить NOPASSWD, как вы указали. Большинство автоматизированных пользователей выполняют только несколько команд, поэтому вполне возможно и, безусловно, желательно включить NOPASSWD, но только для предварительно утвержденных команд. Я бы предложил использовать ваше управление конфигурацией (в данном случае доступное) для управления файлом sudoers, чтобы вы могли легко обновлять список команд без пароля.
Теперь есть несколько шагов, которые вы можете предпринять после начала масштабирования, чтобы еще больше изолировать риски. Несмотря на то, что у нас около 1000 узлов, не все из них являются «производственными» серверами, некоторые - тестовыми средами и т. Д. Не все администраторы могут получить доступ к производственным серверам, хотя те, которые могут использовать тот же пользовательский / пароль | ключ SSO, как и в других местах. . Но автоматизированные пользователи немного более безопасны, например, автоматизированный инструмент, к которому могут получить доступ непроизводственные администраторы, имеет пользователя и учетные данные, которые нельзя использовать в производственной среде. Если вы хотите запустить ansible на всех узлах, вам придется сделать это двумя партиями: один раз для непроизводственного и один раз для производственного.
Однако мы также используем марионетку, поскольку это принудительный инструмент управления конфигурацией, поэтому большинство изменений во всех средах будут вытеснены через него.
Очевидно, что если указанный вами запрос функции будет повторно открыт / завершен, то, что вы хотите сделать, будет полностью поддержано. Даже в этом случае безопасность - это процесс оценки риска и компромисса. Если у вас есть только несколько узлов, для которых вы можете запомнить пароли, не прибегая к заметкам, отдельные пароли будут немного более безопасными. Но для большинства из нас это невыполнимый вариант.
Начиная с Ansible 1.5, можно использовать зашифрованное хранилище для host_vars и других переменных. Это, по крайней мере, позволяет вам хранить для каждого хоста (или для каждой группы) ansible_sudo_pass
переменная безопасно. К сожалению, --ask-vault-pass
будет запрашивать только один пароль хранилища для каждого вызова, поэтому вы по-прежнему ограничены одним паролем хранилища для всех хостов, которые вы будете использовать вместе.
Тем не менее, для некоторых применений это может быть улучшением по сравнению с использованием одного пароля sudo на нескольких хостах, поскольку злоумышленнику без доступа к вашим зашифрованным host_vars все равно потребуется отдельный пароль sudo для каждой машины (или группы машин), которую он или она атакует.
В Ansible 1.5 можно установить ansible_sudo_pass переменная с использованием lookup('password', …)
:
ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"
Мне это удобнее, чем использовать файлы в host_vars/
по нескольким причинам:
Я действительно использую with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt"
предоставить пароли для развернуть удаленный пользователь (который затем нужен для судо), поэтому они уже присутствуют в файлах (хотя при этих поисках открытого текста теряется значение соли, хранящееся в файле, когда создается хешированное значение).
Это сохраняет в файле только пароли (нет ansible_sudo_pass:
известный открытый текст) для некоторого эпсилон-повышения криптографической безопасности. Что еще более важно, это означает, что вы не шифруете все другие переменные, зависящие от хоста, поэтому их можно прочитать без пароля хранилища.
Помещение паролей в отдельный каталог упрощает сохранение файлов вне системы контроля версий или использование такого инструмента, как мерзавец для хранения их в зашифрованном виде (вы можете использовать это с более ранней версией Ansible, в которой отсутствует функция хранилища). Я использую git-crypt, и, поскольку я проверяю репозиторий только в расшифрованном виде на зашифрованных файловых системах, я не беспокоюсь о хранилище и, следовательно, мне не нужно вводить пароль хранилища. (Использование обоих, конечно, будет более безопасным.)
Вы также можете использовать уважать функционировать с ansible_ssh_pass; это может быть возможно даже с более ранними версиями Ansible, в которых нет ansible_sudo_pass.
С помощью проходить это простой способ предоставить доступ к паролям sudo. pass сохраняет один пароль для каждого файла, что упрощает обмен паролями с помощью git или других методов. Он также безопасен (с использованием GnuPG), и если вы используете gpg-agent, он позволяет вам использовать ansible без ввода пароля при каждом использовании.
Чтобы предоставить пароль, хранящийся как servers/foo
для сервера foo
чтобы быть доступным, используйте его в файле инвентаря следующим образом:
[servers]
foo ansible_sudo=True \
ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"
Учитывая, что вы ранее разблокировали ключ для gpg-agent, он будет работать без пароля без необходимости вводить пароль.
Обновить: В настоящее время в Ansible эта функция встроена через плагин хранилища паролей. Эквивалент приведенному выше будет:
[servers]
foo ansible_sudo=True \
ansible_sudo_pass="{{ lookup('passwordstore', 'servers/foo') }}"
Можно даже создать пароль, если его еще нет, что может быть чрезвычайно полезно.
Тем не менее, это довольно старая ветка:
vars_plugin
для Ansible (довольно полную реализацию можно найти на https://gist.github.com/mfriedenhagen/e488235d732b7becda81), который различает несколько систем аутентификации:Кто опаздывает сюда: ср. https://stackoverflow.com/a/37002802
Per host, in your inventory hosts file (inventory/<inventoryname>/hosts)
[server]
10.0.0.0 ansible_sudo_pass=foobar
Per group, in your inventory groups file (inventory/<inventoryname>/groups)
[server:vars]
ansible_sudo_pass=foobar
Per group, in group vars (group_vars/<groupname>/ansible.yml) and encrypted (ansible-vault create group_vars/<groupname>/ansible.yml)
ansible_sudo_pass: "foobar"
Один из возможных способов сделать это - использовать переменные окружения.
например
pass1=foo pass2=bar ansible-playbook -i production servers.xml
Затем в играх вы можете найти пароль sudo, используя:
lookup('env', 'pass1')
lookup('env', 'pass2')
Это вполне возможно. Вы можете определить свой инвентарь, чтобы использовать переменные для таких вещей, как пароли:
ИНВЕНТАРЬ:
[023_mqtt]
023-softbank-mqtt01 ansible_host=IP.IP.IP.IP ansible_ssh_private_key_file=/path/to/my_key ansible_ssh_user=my_user ansible_become=yes ansible_become_method=sudo ansible_become_pass='{{ my_user_pass }}'
Вам понадобится файл group_vars / 023_mqtt.yaml, в котором находится ваш инвентарь, если вы используете сервер перехода (если он вам нужен):
ansible_ssh_common_args: '-o ProxyCommand="ssh -i /path/to/your/jump_key -W %h:%p -q you_jump_user@IP.IP.IP.IP"'
Наконец, вы определяете хранилище для хранения ваших паролей. Желательно создать его в той же папке, что и ваш файл инвентаря:
ansible-vault create passwds.yaml
[enter a vault pass]
Добавьте пароли:
my_user : 'my_user's sudo password'
Чтобы запустить это, передайте хранилище в качестве дополнительных переменных:
ansible -a "docker ps" -i /path/to/hosts hosts_group --ask-vault-pass --extra-vars '@passwd.yaml'
Я определил это для нескольких хостов, каждый со своим собственным ключом SSH, парольной фразой SSH и паролем SSH SUDO, и он отлично работает. Полную статью можно найти в моем git: