Назад | Перейти на главную страницу

Как я могу безопасно реализовать ansible с паролями для каждого хоста?

Я бы хотел использовать анзибль для управления группой существующих серверов. Я создал 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

Исследования на данный момент:

Итак ... как люди используют 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), который различает несколько систем аутентификации:
  • Название системы аутентификации зависит от группы.
  • Используемый логин / пользователь sudo зависит от группы и администратора.
  • Поэтому я извлекаю пользователя из среды администратора и соответствующий пароль через библиотеку python-keyring из сейфа с паролями (мы используем связку ключей Mac OS X, но из документации также поддерживаются kwallet Gnome и _win_crypto).
  • Я установил разрешения для паролей в связке ключей Mac OS X, чтобы уведомить меня о том факте, что программа безопасности командной строки запрашивает доступ к паролю для каждой системы аутентификации, используемой хостами, поэтому я запускаю "ansible -s all -m ping" и получаю два приглашения (по одному для каждой системы аутентификации), где я нажимаю пробел, и ansible берет пароли.

Кто опаздывает сюда: ср. 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:

https://github.com/flow0787/ansible/blob/master/README.md