Глава 2. Защита вашей секретной информации в Ansible

{Прим. пер.: рекомендуем сразу обращаться к нашему более полному переводу 3 издания вышедшего в марте 2019 существенно переработанного и дополненного Полного руководства Ansible Джеймса Фримана и Джесса Китинга}

Секретная информация подразумевает оставаться секретной. Будь это полномочия регистрации для некоторой облачной службы, или пароли для ресурсов базы данных, они секретны по некоторой причине. Если они попадут в плохие руки, они могут быть использованы для обнаружения коммерческой тайны, частных данных пользователя, создания некоей инфраструктуры для подлых целей или чего ещё хуже. Всё что может представлять ценность для вас или вашей организации на протяжении времён, деньги, а также головную боль! В этой главе мы рассмотрим как с помощью Ansible сохранять вашу секретную информацию:

  • Шифрование неподвижных данных

  • Защита секретной информации при работе с нею

Шифрование неподвижных данных

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

Это создаёт некий риск, однако! Ваша секретная информация располагается где- то в вашей файловой системе в обычном тексте. Именно это является физическим и цифровым риском. Физически этот компьютер может быть взят у вас и залапать секретные данные. Цифровым способом любое вредоносное программное обеспечение, которое прорвёт ограждение может считать любые данные учётных записей ваших пользователей для получения доступа. Если вы применяете некую систему контроля исходного кода, вся инфраструктура, которая размещает это репозиторий, также находится в зоне большого риска.

К счастью, Ansible предоставляет некие средства для защиты ваших данных в их состоянии покоя. Этим средством является Vault. Данное средство позволяет шифровать текстовые файлы с тем, чтобы они хранились в состоянии покоя в некотором закрытом формате. Без наличия определённого ключа или значительной вычислительной мощности эти данные не поддаются расшифровке.

Ключевыми уроками для изучения при работе с зашифрованными данными в состоянии покоя являются:

  • Верные цели шифрования

  • Создание новых шифрованных файлов

  • Шифрование имеющихся открытых файлов

  • Изменение зашифрованных файлов

  • Изменение определённого пароля на файлах

  • Дешифрация зашифрованных файлов

  • Исполнение ansible-playbook, ссылающейся на зашифрованные файлы

Вещи, которые может шифровать Vault

Само средство Vault может применяться для шифрования любых файлов с структурированными данными, применяемыми Ansible. Это по существу любой файл YAML (или JSON), который Ansible применяет в процессе своей работы. Они могут включать в себя:

  • файлы group_vars/

  • файлы host_vars/

  • цели include_vars

  • цели vars_files

  • цели --extra-vars

  • переменные роли

  • значения по умолчанию роли

  • файлы задач

  • файлы обработчиков

  • исходные файлы для модуля copy

Если такой файл может быть выражен в YAML и считан Ansible, или если этот файл должен быть передан модулем copy, это точно некий файл для шифрования его с помощью Vault. Поскольку весь файл целиком будет не читаемым в состоянии покоя, следует позаботиться о том, чтобы не переусердствовать с выбором подлежащих шифрованию файлов. Любые операции управления версиями будут выполняться с зашифрованным содержимым, что очень сильно затруднит независимое рассмотрение. В качестве наилучшего практического опыта следует шифровать как можно меньшее количество возможных данных, что может даже означать перемещение некоторых переменных в отдельный самостоятельный файл.

Создание новых зашифрованных файлов

Для создания новых файлов Ansible предоставляет некую новую программу, ansible-vault. Эта программа применяется для создания и взаимодействия с шифрованными Vault файлами. Той процедурой, которая создаёт шифрованные файлы, является процедура create:

 

Рисунок 2.1



Чтобы создать некий новый файл, вам необходимо знать две вещи наперёд. Самой первой является тот пароль, который Vault должен применять для шифрования этого файла, а второй является название самого файла. Когда эта информация предоставлена, ansible-vault запустит некий текстовый редактор, который определён в вашей переменной среды EDITOR. Когда вы сохраните этот файл и выйдите из данного редактора, ansible-vault воспользуется предоставленным паролем в качестве ключа для шифрования данного файла шифром AES256.

[Замечание]Замечание

Все зашифрованные Vault файлы, на которые ссылается некий плейбук должны шифроваться с одним и тем же ключом, в противном случае ansible-vault не сможет их читать.

Ваша программа ansible-vault выдаст приглашение на ввод password в случае если определённый путь к некоторому файлу не был предоставлен в качестве аргумента. Такой файл password может быть либо простым текстом с сохранённым в нём в одной строке пароле, или же это может быть некий исполняемый файл, который выводит необходимый пароль как одну строку в свой стандартный вывод.

Давайте пройдём несколько примеров создания зашифрованных файлов. Вначале мы создадим один и получим приглашение на ввод некого пароля, затем мы предоставим какой- то файл password, а напоследок мы создадим исполняемый для доставки своего пароля.

Приглашение ко вводу пароля

 

Рисунок 2.2



Когда введена фраза пароля, откроется наш редактор и мы получим возможность поместить содержимое в создаваемый файл:

 

Рисунок 2.3



[Замечание]Замечание

В моей системе настроен редактор vim. Ваша система может отличаться и вы можете установить предпочитаемый вами редактор как определённое значение в своеё переменной среды EDITOR.

Теперь мы сохраняем свой файл. Если мы попробуем прочитать его содержимое, мы обнаружим, что оно на самом деле зашифровано с неким необльшим заголовком для последующего применения Ansible:

 

Рисунок 2.4



Файл пароля

Чтобы воспользоваться ansible-vault с неким файлом password, нам вначале нужно создать свой файл password. Это можно сделать простым выводом echo некоего пароля в какой- то файл. Затем мы можем сослаться на этот файл при вызове ansible-vault для создания другого зашифрованного файла:

 

Рисунок 2.5



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

Сценарий пароля

Этот последний пример использует некий сценарий пароля. Он полезен при проектировании некоторой системы, в которой какой- то пароль может быть сохранён в некоторой центральной системе для хранения удостоверений и совместно применяться для сослуживцев по данному дереву плейбука. Каждый сослуживец может иметь его или её собственный пароль для совместного использования хранилища удостоверений и из которой будет выбираться определённый пароль Vault. Наш пример будет намного проще: всего лишь простейший вывод в стандартный выход с некоторым паролем. Такой файл будет сохранён как password.sh. Этот файл нужно пометить как некий исполняемый для Ansible, чтобы воспринимать его таковым:

 

Рисунок 2.6



Шифрование существующих файлов

Все предыдущие примеры имели дело с созданием новых шифрованных файлов с применением определённой процедуры создания. Но что если мы желаем взять некий установившийся файл и зашифровать его? Для этого также имеется некая процедура. Она именуется как encrypt:

 

Рисунок 2.7



Как и ранее, откроется наш редактор с нашим содержимым в простом тексте видимым нам. Как и в случае с create, encrypt ожидает некий password (или файл password) и определённый путь к некоторому файлу. В данном случае, однако, такой файл уже должен иметься. Давайте продемонстрируем это зашифровав некий существующий файл, который мы имеем из предыдущей Главы 1, Архитектура системы и проектирование Ansible, a_vars_file.yaml:

 

Рисунок 2.8



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

[Замечание]Замечание

Попытка зашифровать уже шифрованный файл будет иметь результатом некую ошибку.

Изменение зашифрованных файлов

После того как некий файл был зашифрован с помощью ansible-vault, он не может изменяться напрямую. Открытие этого файла в некотором редакторе имело бы результатом отображение неких зашифрованных данных. Выполнение любых изменений в таком файле разрушит этот файл и Ansible будет не в состоянии считывать его содержимое правильно. Нам требуется некая процедура, которая вначале расшифрует всё содержимое этого файла, позволяя нам изменять его содержимое, а затем зашифрует полученное новое содержимое, прежде чем сохранит его обратно в этот файл. Такая процедура имеется и она называется edit:

 

Рисунок 2.9



Как и раньше, откроется наш редактор с нашим содержимым в обычном текстовом виде, видимом нами. Все знакомые нам варианты вернулись вновь в виде опционального файла/ сценария password и того файла, который можно изменять. Если мы изменяем тот файл, который мы только что зашифровали, мы обнаружим, что ansible-vault открывает наш редактор с неким временным файлом в качестве пути файла. Этот редактор сохранит его и затем ansible-vault зашифрует его и переместит его взамен нашего первоначального файла:

 

Рисунок 2.10



 

Рисунок 2.11



Чередование паролей зашифрованных файлов

Со временм, когда сослуживцы приходят и уходят, будет неплохо чередовать те пароли, которые применяются для шифрования вашей секретной информации. Шифрование хорошо только тогда, когда защищено нужным паролем. ansible-vault предоставляет некую процедуру, которая позволяет нам изменять текущий пароль с названием rekey:

 

Рисунок 2.12



Эта процедура rekey работает во много схоже с процедурой edit. Она принимает некий опциональный файл/ сценарий password и один или более файлов для rekey. Отметим, что хотя вы можете предоставлять некий файл/ сценарий для дешифрации своих существующих файлов, вы не можете предоставлять его для своей новой фразы пароля. Вы получите приглашение на ввод такой новой фразы пароля. Давайте сделаем rekey для нашего файла even_more_secrets.yaml :

 

Рисунок 2.13



Помните, что все ваши шифрованные файлы должны иметь некий соответствующий ключ. Убедитесь, что вы выполнили rekey всех имеющихся файлов за один и тот же раз.

Расшифровка зашифрованных файлов

Если в некоторый момент потребность шифровать файлы исчезла, ansible-vault предоставляет некую процедуру, которую можно применить для удаления шифрования для одного или более зашифрованных файлов. Эта процедура именуется как decrypt:

 

Рисунок 2.14



Опять же, мы должны применить некий опциональный аргумент для файла/ сценария password и затем один или более путей файлов для дешифрации. Давайте дешифруем тот файл, который мы зашифровали ранеее, применив наш файл password:

 

Рисунок 2.15



Исполнение плейбуков Ansible c зашифрованными файлами

Чтобы применять наше зашифрованное содержимое, нам необходимо иметь возможность уведомить ansible-playbook как получить доступ к любым зашифрованным данным, с которыми он может столкнуться. В отличии от ansible-vault, который существует исключительно для того, чтобы иметь дело с шифрацией/ дешифрацией, ansible-playbook имеет более многоплановым и он не будет предполагать, что он имеет дело с зашифрованными данными по умолчанию. имеются два способа указать что могут встречаться зашифрованные данные. Первым является определённый аргумент --ask-vault-pass, который запросит в самом начале исполнения некоторого плейбука необходимый пароль для Vault чтобы разблокировать любые встречающиеся шифрованные файлы. Ansible буде придерживать такой предоставленный пароль в памяти на протяжении всего исполнения данного плейбука. Второй метод состоит в ссылке на некий файл или сценарий password через известный аргумент --vault-password-file.

Давайте создадим некий простой плейбук с названием show_me.yaml, который выведет имеющееся значение своей переменной внутри a_vars_file.yaml, который мы зашифровали в предыдущем примере:


---
- name: show me an encrypted var
  hosts: localhost
  gather_facts: false

  vars_files:
    - a_vars_file.yaml

  tasks:
    - name: print the variable
      debug:
        var: something
 	   
 

Рисунок 2.16



Защита секретной информации при работе

В своём предыдущем разделе этой главы мы обсудили защиту вашей секретной информации в состоянии покоя в определённой файловой системе. Однако, это не относится к варианту, когда Ansible работает с секретными данными. Такие секретные данные могут использоваться в задачах в виде аргументов модуля или в циклах ввода, либо в целом ряде прочих вещей. Это может вызвать передачу данных на remote хосты, протоколироваться в локальные или remote файлы регистрации, или отображаться на экране. Данный раздел текущей главы обсудит стратегии для защиты ваших секретных данных во время работы.

Секретная информация, передаваемая на удалённые хосты

Как мы уже изучали в Главе 1, Архитектура системы и проектирование Ansible, Ansible будет комбинировать код и аргументы модуля и записывать это в некий временный каталог на своём remote хосте. Это означает, что ваши секретные данные передаются по кабелю И записываются в вашу remote файловую систему. Пока вы не применяете некий подключаемый модуль соединения, отличающийся от ssh, все передаваемые по вашему кабелю данные уже шифруются, предоставляя безопасность вашей секретной информации от её исследования простыми средствами перехвата {Прим. пер.: см., например, Python Scapy}. Если вы применяете некий отличающийся от ssh подключаемый модуль соединения, ознакомьтесь с тем шифруются или нет ваши данные при их передаче. Применение любого метода соединения без шифрования является сильно обескураживающим.

Когда ваши данные переданы, Ansible может записать эти данные открытым способом в имеющуюся файловую систему. Это может произойти если не применяется pipelining (который мы изучали в Главе 1, Архитектура системы и проектирование Ansible), ИЛИ если Ansible получил указание через имеющуюся переменную среды ANSIBLE_KEEP_REMOTE_FILES оставлять remote файлы на месте. Без конвейеризации Ansible запишет сам модуль, код плюс аргументы, в некий временный каталог, который должен быть обнаружен в процессе исполнения. Если произойдёт потеря связи между записывающей этот файл стороной и исполняющей его стороной, такой файл останется в имеющейся remote файловой системе пока не будет удалён вручную. Если Ansible в явном виде получил указание оставлять remote файлы на своём месте, тогда, даже если конвейеризация включена, Ansible запишет и оставит remote файлы на месте. С такими вариантами надо быть настороже с высокочувствительной секретной информацией, даже не смотря на то, что обычно только сам зарегистрированный (или становится таким посредством эскалации полномочий) на данном remote хосте пользователь Ansible должен иметь доступ к такому оставшемуся файлу. Простое удаление всего в вашем пути ~/.ansible/tmp/ для имеющегося пользователя remote будет достаточным для очистки секретной информации.

Секретная информация, протоколируемая в удалённые или локальные файлы

Когда Ansible работает с неким хостом, он попытается регистрировать все действия в syslog (если применяется третий уровень многословности пояснений). Если эти действия осуществляются неким пользователем с соответствующими правами, это вызовет появление неких сообщений в имеющемся файле syslog на таком хосте. Эти сообщения содержат само название модуля и все аргументы, передаваемые совместно с такой командой, которые могут содержать вашу секретную информацию. Чтобы предотвратить такое происшествие, имеется некий ключ воспроизведения и задачи с названием no_log. Установка no_log в значение true предотвратит Ansible от протоколирования своих действий в syslog.

Локально Ansible также может получать указания выполнять протоколирование своих действий. Некая переменная, контролирующая это, имеет название ANSIBLE_LOG_PATH. Без установки данной переменной Ansible будет вести протокол в стандартный вывод. Установка такой переменной в значение некоторого пути, в который может осуществлять запись исполняющий ansible-playbook пользователь, вызовет ведение протокола Ansible по этому пути. Значение многословности такой регистрации соответствует той многословности, с которой выполняется вывод на экран. При уровне многословности один (-v), возвращаемые данные отображаются на экране (и потенциально в вашем локальном файле log). При уровне многословности, поднятом до третьего уровня (-vvv), имеющийся вывод параметров также может отображаться. Поскольку они могут содержать секретную информацию, установка параметра no_log также применима к отображению на экран. Давайте возьмём свой предыдущий пример отображения зашифрованной секретной информации и добавим некий ключ no_log к своему заданию чтобы предотвратить отображение его значений:


---
- name: show me an encrypted var
  hosts: localhost
  gather_facts: false

  vars_files:
    - a_vars_file.yaml

  tasks:
    - name: print the variable
      debug:
        var: something
      no_log: true
 	   

Если мы исполним этот плейбук, мы должны обнаружить, что наши секретные данные защищены:

 

Рисунок 2.17



Ansible выполняет собственную цензуру для предотвращения показа чувствительных данных.

[Замечание]Замечание

Данный ключ no_log может применяться в качестве директивы для неких представителей воспроизведения, роли, блока или задачи.

Выводы

Ansible может работать с чувствительными данными. Важно понимать как эти данные хранятся в покое и как эти данные трактуются при их использовании. При принятии небольших мер предосторожности Ansibl может сохранить вашу секретную информацию в секрете. Шифрование секретной информации при помощи ansible-vault может защитить её при нахождении в спячке в вашей файловой системе или в некотором совместно применяемом репозитории управления исходными кодами. Предотвращение Ansible от задач протоколирования может защитить от утечки данных в файлы remote log или от вывода на экраны.

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