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

108

Я хотел бы использовать ansible для управления группой существующих серверов. Я создал ansible_hostsфайл и успешно протестировал (с -Kвозможностью) команды, предназначенные только для одного хоста.

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 Playbooks" , в которой говорится

    «Ansible может войти на целевой сервер от имени root и избежать необходимости sudo, или позволить пользователю ansible иметь sudo без пароля, но сама мысль о том, что это может привести к тому, что моя селезенка угрожает вскочить в глотку и заблокировать дыхательную трубку, поэтому я не»

    Мои мысли точно, но тогда как выйти за пределы одного сервера?

  • Ответ № 1227 , «Ansible должен запрашивать пароль sudo для всех пользователей в книге игр», который был закрыт год назад mpdehaan с комментарием «Не видел большого спроса на это, я думаю, что большинство людей судятся только от одного учетную запись пользователя или использование ключей большую часть времени. "

Итак ... как люди используют Ansible в подобных ситуациях? Установка NOPASSWDв /etc/sudoers, повторное использование пароля по хостам или позволяя корневой SSH логин все , кажется , довольно резкое сокращение безопасности.

supervacuo
источник
2
Есть ли причина, по которой вы не используете ключи SSH?
Трондх
22
Я уже использую ключи SSH; они не влияют sudo(который все еще должен требовать пароль).
supervacuo
1
Возможно, это не совсем то, что вы ищете, но в блоках Ubuntu я все еще использую ключи, т.е. помещаю свой открытый ключ в / root / authorized_keys, чтобы войти прямо как root. Очевидный недостаток - разрешить вход с правами root через ssh ... Я также запрещаю вход с паролями через ssh и запускаю fail2ban для дополнительной безопасности.
Senorsmile
27
@senorsmile спасибо за ответ! Не могли бы вы вместо этого превратить это в ответ, чтобы я понизил голосование за то, что вы не прочитали вопрос?
supervacuo
4
т.е.ansible_ssh_password параметр применяется только к паролю SSH (разгадка во имя ...). & Я уже использую SSH-вход на основе ключей.
supervacuo

Ответы:

53

Вы, конечно, сделали свое исследование ...

Судя по всему моему опыту с ansible, то, что вы ищете, не поддерживается. Как вы упомянули, ansible утверждает, что он не требует sudo без пароля, и вы правы, это не так. Но мне еще предстоит увидеть какой-либо способ использования нескольких паролей sudo в пределах ansible, без, конечно, запуска нескольких конфигов.

Итак, я не могу предложить точное решение, которое вы ищете, но вы спросили ...

«Итак ... как люди, использующие Ansible в подобных ситуациях? Установка NOPASSWD в / etc / sudoers, повторное использование пароля на хостах или включение root SSH - все это выглядит довольно радикальным снижением безопасности».

Я могу дать вам один взгляд на это. Мой пример использования - 1 тыс. Узлов в нескольких центрах обработки данных, поддерживающих глобальную фирму SaaS, в которой мне приходится разрабатывать / реализовывать некоторые безумно строгие меры безопасности в зависимости от характера нашего бизнеса. Безопасность - это всегда баланс, больше юзабилити и безопасность, этот процесс ничем не отличается, если вы используете 10 серверов, 1000 или 100 000.

Вы абсолютно правы, чтобы не использовать root-логины через пароль или ssh-ключи. На самом деле, root-вход должен быть полностью отключен, если к серверам подключен сетевой кабель.

Давайте поговорим о повторном использовании пароля на большом предприятии. Разумно ли просить системных администраторов иметь разные пароли на каждом узле? для пары узлов, возможно, но мои администраторы / инженеры взбунтовались бы, если бы им пришлось иметь разные пароли на 1000 узлов. Реализация этого также была бы почти невозможной, каждый пользователь должен был бы где-то хранить свои собственные пароли, мы надеемся, что это будет комбинация клавиш, а не электронная таблица. И каждый раз, когда вы помещаете пароль в место, где его можно извлечь простым текстом, вы значительно снижаете свою безопасность. Я бы предпочел, чтобы они наизусть знали один или два действительно надежных пароля, а не обращались к файлу паролей каждый раз, когда им нужно было войти в систему или вызвать sudo на компьютере.

Таким образом, повторное использование пароля и стандартизация - это то, что является полностью приемлемым и стандартным даже в безопасной среде. В противном случае ldap, keystone и другие службы каталогов не должны существовать.

Когда мы переходим к автоматизированным пользователям, ssh-ключи отлично работают для вас, но вам все равно нужно пройти через sudo. Вы можете выбрать стандартный пароль для автоматизированного пользователя (который во многих случаях приемлем) или включить NOPASSWD, как вы указали. Большинство автоматизированных пользователей выполняют только несколько команд, поэтому вполне возможно и желательно включить NOPASSWD, но только для предварительно утвержденных команд. Я бы посоветовал использовать ваше управление конфигурацией (в данном случае - ansible) для управления файлом sudoers, чтобы вы могли легко обновить список команд без пароля.

Теперь есть несколько шагов, которые вы можете предпринять после начала масштабирования для дальнейшей изоляции риска. Несмотря на то, что у нас около 1000 узлов, не все они являются «производственными» серверами, некоторые являются тестовыми средами и т. Д. Не все администраторы могут получить доступ к рабочим серверам, хотя те, кто может использовать свой одинаковый ключ пользователя / пароль SSO, как и в других местах. , Но автоматизированные пользователи немного более безопасны, например, автоматизированный инструмент, к которому могут обращаться непроизводственные администраторы, имеет пользователя и учетные данные, которые нельзя использовать в производстве. Если вы хотите запустить ansible на всех узлах, вам придется сделать это двумя партиями, один раз для непроизводственного и один раз для производственного.

Мы также используем Puppet, поскольку это инструмент управления конфигурацией, поэтому большинство изменений во всех средах будут вытеснены через него.

Очевидно, что если запрос, который вы цитировали, будет вновь открыт / завершен, то, что вы хотите сделать, будет полностью поддерживаться. Но даже в этом случае безопасность - это процесс оценки рисков и компромисса. Если у вас есть только несколько узлов, для которых вы можете запомнить пароли, не прибегая к пост-заметке, отдельные пароли будут немного более безопасными. Но для большинства из нас это невыполнимый вариант.

Зеб
источник
Спасибо, @Zeb - я представлял, что пользователи с десятками или тысячами серверов будут NOPASSWDв любом случае использовать по соображениям здравого смысла (вероятно, поддерживаются более строгими правилами брандмауэра и т. Д. ), Но хорошо прочитать ваш сценарий использования и мысли об угрозе модель.
supervacuo
16
Один комментарий, тем не менее, на ваше предложение об ограничении «предварительно одобренными» sudoкомандами (что пришло мне в голову, когда я обнаружил, что NOPASSWDэто в значительной степени требуется). К сожалению, это также кажется полностью неподдерживаемым - ansible не дает никаких обещаний относительно прямого вызова, например, chown или mkdirдвоичных файлов, и должен иметь возможность работать sudo /bin/shдля большинства модулей.
супервакуу
Кажется, я вспоминаю, как один из моих инженеров некоторое время назад жаловался на это, это раздражает.
Зеб
36

Начиная с версии Ansible 1.5 можно использовать зашифрованное хранилище для host_vars и других переменных. Это, по крайней мере, позволяет безопасно хранить ansible_sudo_passпеременную для каждого хоста (или для группы) . К сожалению, --ask-vault-passбудет запрашиваться только один пароль хранилища для каждого вызываемого вызова, поэтому вы по-прежнему ограничены одним паролем хранилища для всех хостов, которые вы будете использовать вместе.

Тем не менее, для некоторых целей это может быть лучше, чем иметь один пароль sudo на нескольких хостах, поскольку злоумышленнику, не имеющему доступа к вашим зашифрованным host_vars, все равно потребуется отдельный пароль sudo для каждой машины (или группы компьютеров), на которую он или она атакует.

Дэниел Нидес
источник
3
ansible_sudo_passВариант кажется новым, тоже - и , кажется, делать то , что я просил. Один пароль хранилища идеально подходит и для моих целей. Спасибо!
supervacuo
Есть ли способ избежать шифрования всех, host_vars используя этот метод? (потенциальное ограничение, отмеченное Алексом Дюпюи)
supervacuo
1
@supervacuo - чтобы избежать шифрования всех переменных хоста, просто используйте каталог var хоста, содержащий main.yml (не зашифрованный) и secret.yml (зашифрованный) - см. последнюю часть этого раздела документации, где говорится о группе «Роли» - та же техника работает для хостов и групповых. Я часто этим пользуюсь, единственное изменение состоит в том, что если секрет нужен только для некоторых игровых книжек, может быть полезно сохранить его в другом дереве целиком и включить через путь, который включает имя хоста или переменной.
RichVel
1
Если я зашифровал значение «ansible_ssh_pass» в хранилище, то мне также нужно дублировать значение «ansible_sudo_pass»? Есть ли способ для второго значения sudo_pass восстановить первое значение 'ssh_pass'?
изумруджава
Хороший
обзор
22

В 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" пароли для удаленного пользователя развертывания (который затем необходим для sudo ), поэтому они уже присутствуют в файлах (хотя при выполнении такого поиска в незашифрованном виде теряется солт-значение, хранящееся в файле, когда генерируется хешированное значение) ,

  • При этом сохраняются только пароли в файле (без ansible_sudo_pass:известного открытого текста) для некоторого повышения криптографической безопасности в эпсилоне. Что еще более важно, это означает, что вы не шифруете все другие специфичные для хоста переменные, поэтому они могут быть прочитаны без пароля хранилища.

  • Помещение паролей в отдельный каталог облегчает защиту файлов от контроля над исходным кодом или использование инструмента, такого как git-crypt, для хранения их в зашифрованном виде (вы можете использовать это с более ранней версией Ansible, в которой отсутствует функция хранилища). Я использую git-crypt, и поскольку я проверяю хранилище только в расшифрованном виде на зашифрованных файловых системах, я не беспокоюсь о хранилище и, следовательно, не должен вводить пароль хранилища. (Использование обоих было бы, конечно, более безопасным.)

Вы также можете использовать функцию поиска с ansible_ssh_pass ; это может быть даже возможно с более ранними версиями Ansible, которые не имеют ansible_sudo_pass .

Алекс Дюпуй
источник
2
Я наконец нашел время, чтобы попробовать это (спасибо!), Но не вижу, как это будет работать без git-crypt; насколько я вижу. Похоже, что Ansible еще не поддерживает использование lookupзашифрованного хранилища. Документы passwordмодуля говорят, что есть некоторая пока недокументированная поддержка зашифрованного хранилища, но я еще не нашел деталей. Есть какие-нибудь подсказки?
Supervacuo
19

Использование 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 без необходимости вводить пароль.

fqxp
источник
3

Это довольно старая тема, тем не менее:

  • Мы используем две разные системы аутентификации, управление машинами осуществляется с локальных рабочих станций в моей команде.
  • Я написал 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 подбирает пароли.
Мирко Фриденхаген
источник
Это выглядит очень аккуратно, спасибо - мне нравится идея не хранить пароли в двух местах. На данный момент я застрял с помощью KeepassX (потому что брелок GNOME не выглядит очень портативным), но, возможно, я смогу сделать python-keepassработу?
supervacuo
Насколько я понимаю, python-keyring - это абстракция для этого, поэтому ваши коллеги могут использовать другие ОС. Или вы храните свою базу данных keepassx на USB-накопителе и должны администрировать ее с рабочих станций с разными ОС?
Мирко Фриденхаген
понимать; Я имел в виду, что мне уже нужно использовать KeepassX, чтобы иметь доступ к паролям в системах, отличных от GNOME, поэтому их хранение gnome-keyringбудет означать хранение дубликатов записей. Тем не менее, это намного приятнее, чем использование NOPASSWD...
supervacuo
0

Один из возможных способов сделать это - использовать переменные среды.

например

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Затем в пьесах вы можете найти пароль sudo, используя:

lookup('env', 'pass1') 
lookup('env', 'pass2') 
Пол Калабро
источник