Docker secrets – безопасное хранилище для чувствительных данных
О технологиях

Docker secrets – безопасное хранилище для чувствительных данных

1557
14 минут

В данной статье будет рассмотрена работа чувствительными данными в 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 запросы. Если же «секрета» с паролем не будет, приложение будет выдаваться сообщение об ошибке.

Внедряем и поддерживаем Kubernetes/DevOps
Развертываем и сопровождаем инфраструктуру для бизнес-приложений на базе микросервисов и контейнеров

Создание приложения

Прежде чем переходить к описанию работы с «секретами», давайте создадим демонстрационное приложение. Для этого создайте директорию 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-service-without-secret.png

Сборка образа

После того, как приложение заработало, его необходимо упаковать в контейнер. Для этого необходимо выполнить команду:


$ 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 для того, чтобы гарантировать, что узлы, участвующие в управлении кластером, договариваются о состоянии кластера. Часть этого процесса включает в себя репликацию состояния всех управляющих узлов кластера при помощи журнала.

Docker-Raft.png

Реализация «секретов» в кластере, работающем в 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

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

Docker-service-with-secret.png

Если же запустить ваш сервис без указания ключа —secret, например, командой:


	 $ docker service create --name docker_secrets_example -p 5000:5000 amaksimov/docker_secrets_example:v0.1

То, как и ожидается, ваше приложение об этом сразу же сообщит:

Docker-service-without-secret.png

Добавление “секрета” к уже работающему сервису

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


	 $ docker service rm docker_secrets_example

Обновление “секретов” для сервиса

Также к сожалению, для того, чтобы обновить секрет у сервиса, его придется пересоздать.

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

15 ноября 2022
OpenShift остался без поддержки – как решить проблему российским клиентам
Интерес к семейству ПО для контейнеризации OpenShift был довольно высоким в корпоративном сегменте в прежние годы. По данным мониторинговой службы Datadog, только за прошлый год во всем мире количество пользователей платформ от RedHat увеличилось на 28%. Весной IBM объявил об уходе из России и прекращении поддержки всех программных продуктов для текущих клиентов. Разберемся, насколько критичной оказалась данная ситуация для заказчиков, и какие варианты действий существуют, чтобы минимизировать возможные риски отключения от сервиса.
0 минут
623
25 февраля 2021
Свидетели DevOps: мифы и байки про девопсов и тех, кто их нанимает
Те, кто решил стать девопсом, видят в этой профессии заманчивые перспективы. Это новый уровень мышления, это творчество и возможность создавать, это безграничные просторы для самосовершенствования. Не секрет также, что девопсам хорошо платят. Вместе с тем, вокруг понятия DevOps сформировался некий культ, овеянный мифами и легендами.
0 минут
843
4 декабря 2020
Дайджест обновлений К2 Облака осень 2020 г.
За осень в К2 Облаке многое изменилось. Мы активно писали код и не успевали сообщать обо всех переменах. Постараемся исправиться и информировать вас ASAP, чтобы вы могли сразу же использовать новые фичи.
1 минута
256
scrollup