Docker secrets – безопасное хранилище для чувствительных данных
Содержание:
- 1. План
- 2. Создание приложения
- 3. Проверка работоспособности приложения
- 4. Сборка образа
- 5. Работа с “секретами” (Docker secrets)
- 6. Создание “секрета” из файла
- 7. Создание “секрета” со стандартных потоков вводавывода
- 8. Просмотр “секретов” кластера
- 9. Удаление “секретов” из кластера
- 10. Управление сервисом с “секретом”. Запуск
- 11. Добавление “секрета” к уже работающему сервису
- 12. Обновление “секретов” для сервиса
В данной статье будет рассмотрена работа чувствительными данными в Docker кластере такими как ключи, пароли и т.д.
Важнейшим элементом для построения безопасных приложений является наличие безопасного способа общения ваших контейнеров друг с другом, а также с другими приложениями и системами. А это в свою очередь первоначально требует безопасного способа управления учетными записями, токенами, паролями, ключами, а также другими видами чувствительной информации, как правило называющейся в приложении просто “секретами”. Начиная с версии 1.13 в Docker начал поддерживаться безопасный способ работы с такими чувствительными данными – Docker secrets. Этот безопасный способ работы реализуется в Docker кластере, работающем в так называемом режиме Swarm mode.
Предполагается, что у вас уже есть Docker кластер, работающий в Swarm mode. А если еще нет, вы легко можете установить его, воспользовавшись инструкциями из статьи “Установка отказоустойчивого Docker Swarm кластера в K2 Cloud“, или же вы можете обновить свой Docker Engine до версии 1.13 и переведя его в этот режим работы, чтобы посмотреть на работу технологии и не устанавливать отдельный кластер:
$ docker swarm init
План
Мы запустим в контейнере простое Flask приложение (похожее на то, что описывалось в статье «Упаковка простого Flask приложения в Docker контейнер»), которое будет считывать переданный ему пароль и выводить его в ответ на http запросы. Если же «секрета» с паролем не будет, приложение будет выдаваться сообщение об ошибке.
Создание приложения
Прежде чем переходить к описанию работы с «секретами», давайте создадим демонстрационное приложение. Для этого создайте директорию docker_secrets_example:
$ mkdir docker_secrets_example
$ cd docker_secrets_example
Создайте в нем файл requirements.txt, содержащий следующую информацию:
click==6.7
Flask==0.12
itsdangerous==0.24
Jinja2==2.9.5
MarkupSafe==0.23
Werkzeug==0.11.15
wheel==0.24.0
Создайте и активируйте виртуальное окружение, а затем установите зависимости
$ virtualenv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
Создайте файл app.py, который будет содержать код нашего приложения
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def index():
try:
db_password = None
f = open('/run/secrets/db-password', 'r')
db_password = f.readline()
except IOError:
pass
finally:
return render_template('index.html', password=db_password)
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
А также необходимо создать директорию templates и поместить внутрь файл index.html со следующим содержимым:
Docker secrets demo
{% if password %}
Your secret password:
{% else %} No password specified! {% endif %}
Внутри рабочей директории создайте файл Dockerfile со следующим содержимым, чтобы иметь возможность собирать ваш Docker образ:
FROM python:2.7
MAINTAINER Andrey Maksimov 'maksimov.andrei@gmail.com'
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
Структура вашего приложения на текущий момент без учета виртуального окружения (venv) будет следующей:
$ tree -I venv docker_secrets_example
docker_secrets_example
├── Dockerfile
├── app.py
├── requirements.txt
└── templates
└── index.html
1 directory, 4 files
Проверка работоспособности приложения
Если на текущий момент вы все сделали правильно, вы можете запустить демонстрационное приложение и проверить его работоспособность, открыв в браузере адрес :
$ python app.py
* Running on (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 237-318-490
127.0.0.1 - - [13/Feb/2017 19:02:46] 'GET / HTTP/1.1' 200 -
127.0.0.1 - - [13/Feb/2017 19:02:47] 'GET /favicon.ico HTTP/1.1' 404 -
При этом в браузере будет отображаться:
Сборка образа
После того, как приложение заработало, его необходимо упаковать в контейнер. Для этого необходимо выполнить команду:
$ docker build -t amaksimov/docker_secrets_example:v0.1 .
Для корректной работы сервисов в Docker Swarm кластере, опубликуйте ваш собранный образ в вашем репозитории:
$ docker push amaksimov/docker_secrets_example:v0.1
Важно: если этого не сделать, в процессе запуска сервиса команда docker service createбудет выдавать сложно интерпретируемую ошибку.
Работа с “секретами” (Docker secrets)
После того, как демонстрационный образ создан, можно переходить непосредственно к работе с «секретами».
«Секреты» используются Docker сервисами посредством установления явной связи между сервисом и самими секретами. Сервисы, напомню, состоят из задач (отдельных контейнеров), которые могут выполняться на любом узле в пределах вашего кластера. Если ваш сервис состоит из нескольких задач (контейнеров), связанный с ним «секрет» будет доступен для всех задач этого сервиса.
Docker Swarm кластер использует Raft Consensus Algorithm для того, чтобы гарантировать, что узлы, участвующие в управлении кластером, договариваются о состоянии кластера. Часть этого процесса включает в себя репликацию состояния всех управляющих узлов кластера при помощи журнала.
Реализация «секретов» в кластере, работающем в Swarm mode режиме, использует алгоритм Raft. «Секреты» в процессе создания записываются в raft-журнал, что позволяет им реплицироваться на каждый из управляющих узлов кластера. До тех пор, пока кластер работает, журнал Raft хранится в памяти каждого управляющего узла и реплицируется в зашифрованном виде.
В процессе запуска нового сервиса в кластере, если в процессе создания ему предоставлена возможность доступа к тому или иному «секрету», происходит монтирование текстового содержимого «секретов» в директорию /run/secrets всем задачам (контейнерам) этого сервиса.
Команда docker secret позволяет нам задать «секреты», которые могут быть использованы сервисами, запущенными в Docker Swarm кластере. Есть два способа создания «секрета».
Создание “секрета” из файла
Создайте в рабочей директории файл password.txt который будет содержать секретную информацию, например, пароль к базе данных this-is-my-super-secret-password. Чтобы дать возможность вашим приложениям использовать этот секретный пароль, выполните коману:
$ docker secret create db-password password.txt
Эта команда создаст «секрет» с именем db-password, используя содержимое файла password.txt
Создание “секрета” со стандартных потоков вводавывода
Также вы можете создавать «секреты», используя информацию со стандартного потока вводавывода:
$ LC_ALL=C < /dev/urandom tr -dc '_A-Z-a-z-0-9' | head -c 32 | docker secret create db-password -
Эта команда также создаст «секрет» db-password, но уже используя сгенерированную информацию из /dev/urandom.
Просмотр “секретов” кластера
Все созданные в кластере секреты могут быть просмотрены при помощи команды:
$ docker secret ls
ID NAME CREATED UPDATED
iokqhuhj7ix9a57joiarivv8n db-password 3 hours ago 3 hours ago
Удаление “секретов” из кластера
Удаление «секретов» также осуществляется достаточно просто:
$ docker secret rm db-password
Управление сервисом с “секретом”. Запуск
Для того, чтобы запустить ваш сервис и передать ему информацию о «секрете», необходимо выполнить команду:
$ docker service create --name docker_secrets_example -p 5000:5000 --secret db-password amaksimov/docker_secrets_example:v0.1
После чего можно будет убедиться в том, что ваше приложение прочитало файл с секретом:
Если же запустить ваш сервис без указания ключа —secret, например, командой:
$ docker service create --name docker_secrets_example -p 5000:5000 amaksimov/docker_secrets_example:v0.1
То, как и ожидается, ваше приложение об этом сразу же сообщит:
Добавление “секрета” к уже работающему сервису
К сожалению, для того, чтобы добавить секрет к сервису, последний придется пересоздать, предварительно выполнив команду:
$ docker service rm docker_secrets_example
Обновление “секретов” для сервиса
Также к сожалению, для того, чтобы обновить секрет у сервиса, его придется пересоздать.
В этой статье мы рассмотрели еще одну возможность Docker, предназначенную для безопасной работы с чувствительными данными ваших приложений. Если у вас возникли какие-либо вопросы, буду рад ответить на них в комментариях в конце статьи.