О чем статья?

Короткая статейка о том, как сгенерировать пароли необходимые для разнообразных сервисов автоматически устанавливаемых с помощью SaltStack.


Трудности генерации паролей.


Очень часто приходится автоматически устанавливать сервисы или приложения, которые требуют указания паролей для доступов к каким-то своим частям (например, к web интерфейсу или к управлению своим API). Не менее часто приходится конфигурировать пользователей баз данных, которые будут затем использоваться в сервисах использующих эти базы и т. д.

Типичная проблема, — генерация паролей для всех подобных случаев. Есть несколько решений этой проблемы:

1. Прописать пароли вручную в pillar файл


pillar/passwords.sls
service1:
  web-access-password: '9KTE2aN11GYOJmZGOoqV'
  db-access-password: '2pGbSlSFkHPY22TwqUus'

Ну и потом в любом другом пилларе или в стейте использовать указанные пароли для генерации доступов.
Все вроде бы нормально и понятно, — но есть одно но — если вы будете распространять стейт использующий указанный пиллар, то пароли будут сохраняться в том же неизменном виде. Мало того, — даже все однотипные серверы, для которых будут применен этот стейт будут иметь одинаковый пароль. Естественно нет смысла объяснять чем это может грозить с точки зрения информационной безопасности.

2. Сгенерировать пароли средствами SaltStack.


Есть одна интересная ф-ция в SaltStack в модуле grains get_or_set_hash, которая может сгенерировать пароль для последующего использования определенного grain. Пароли получаются достаточно комплексными (из-за дефолтного набора символов, которые можно переопределить при вызове), использовать их в стейтах легко (просто считать соответствующий grain с миниона). Единственное, о чем стоит помнить, — генерация пароля происходит только при первом вызове этой ф-ции (и сам пароль помещается в /etc/salt/grains файл), все последующие — будут просто читать этот грейн из файла как если бы вызывался salt['grains.get']('stored-password-grain-name').
Один из самых существенных недостатков этого способа — отсутствие возможности читать сгенерированные таким образом пароли в pillar файлах, что часто бывает полезно при использовании разнообразных формул (SaltStack Formulas).

3. Пред. генерация паролей в pillar файле.

Еще один способ, который я использую достаточно часто — предварительное генерирование паролей с помощью Jinja2.
В общем случае, для пред. генерации используется minion установленный на той же машине что и Salt Master. Если не хочется подключать такой minion к самому мастеру, можно воспользоваться masterless конфигурацией, но я предпочитаю использовать минион подключенным к мастеру, обозначив его grains:roles:local-minion и создав отдельную запись в конфигурации мастера:
master/top.sls
base:
  'roles:local-minion':
    - match: grain
    - local-minion-state


Суть способа пред. генерации паролей заключается в том, чтобы создать jinja шаблон pillar файла с паролем(-лями) примерно такого вида:
master/files/some-srv-password.sls.jinja2
some-srv:
  password: '{{salt['random.get_str'](30)}}'


тут используется ф-ция get_str модуля random.

Следующим шагом будет описание стейта для локального миниона, который генерирует pillar файл с паролями.
master/local-minion-state.sls
passwords-file:
  file.managed:
    - name: /srv/salt/pillar/some-srv-password.sls # или другое место, где pillar файлы могут быть считаны мастером
    - source: salt://files/some-srv-password.sls.jinja2
    - template: jinja


После этого, перед применением стейтов зависящих от наличия пред. генерированных паролей, запускаем описанный стейт:
~# salt-call --local state.sls local-minion-state # masterless
or
~# salt -C 'G@roles:local-minion' state.sls local-minion-state


После исполнения стейта, получим pillar файл содержащий сгенерированный пароль. Для его использования выполним include в другом pillar файле:
pillar/some-srv.sls
include:
  - some-srv-password

some-srv:
  username: Fred
  
  . . .


В итоге, при запросе salt 'minion-with-some-srv-pillar-connected' pillar.items получим примерно такое:
pillar:
  . . . 
  some-srv:
    . . .
    username:
      Fred
    password:
      AoEK8u4Uvo_r9MKtooSUxZV1Y_DLoy


затем доступ к данным пароля можно получить простым вызовом salt['pillar.get']('some-srv:password').

Заключение.


Из-за достаточно большой гибкости системы SaltStack решение этой задачи скорее всего не ограничивается только лишь 3-мя способами описанными в статье, — вполне возможно, что Вы придумаете не менее продуктивный и удобный способ.
В любом случае — надеюсь описанное в статье пригодится начинающим и не только пользователям SaltStack. Удачи!

Комментарии (0)