Управление секретами, ключами API и прочим с помощью Serverless

Originally posted at Serverless on Nov 7th, 2017

Бессерверные приложения часто являются приложениями с полным набором сервисов. Это означает, что вы используете размещенные сервисы для дополнения своих приложений — например, DynamoDB для хранения данных или Mailchimp для отправки электронных писем.

При использовании других сервисов в приложениях Serverless вам часто требуются данные конфигурации, чтобы приложение работало правильно. К ним относятся такие вещи, как ключи API, идентификаторы ресурсов и другие элементы.

В этой заметке мы расскажем о нескольких различных способах работы с этими конфигурационными элементами. В этом посте рассматриваются:

  • Использование переменных окружения в ваших функциях;

  • Работа с секретами для небольших проектов Serverless; и

  • Управление секретами для больших проектов Serverless.

Давайте приступим!

Использование переменных окружения в Lambda

Когда я создавал свои первые веб-приложения, огромное влияние на меня оказал проект 12 Factor App от Heroku — набор из двенадцати принципов для развертывания масштабируемых веб-приложений без статических данных. Я обнаружил, что многие из них напрямую применимы к приложениям Serverless.

Одним из двенадцати факторов было хранение конфигурации в окружении. Рекомендуется использовать переменные среды для конфигурации (например, учетные данные или имена хостов), поскольку их легко изменить между развертываниями без изменения кода.

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

Давайте рассмотрим на примере, как работают переменные окружения. Представьте, что вы создаете бота для Twitter, который проверяет твиты с определенными хэштегами и ретвитит их с небольшими изменениями, подобно боту Serverless Superman. Чтобы опубликовать эти ретвиты, вам нужно получить маркер доступа для подписи ваших запросов.

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

Создайте пустой каталог и добавьте в него следующий файл serverless.yml:

Это простой сервис с единственной функцией superman, которая будет выполнять код для бессерверного бота Superman. Обратите внимание, что в разделе provider у нас есть блок environment — это переменные окружения, которые будут добавлены в наше окружение Lambda.

В Python вы сможете получить доступ к этим переменным окружения в словаре os.environ, где ключ — это имя переменной окружения. Для нашего примера выше это будет выглядеть следующим образом:

В Javascript вы можете получить доступ к переменным окружения из объекта process.env:

И последнее замечание: переменные окружения в блоке провайдера доступны всем функциям сервиса. Вы также можете разграничить переменные окружения на основе каждой функции, добавив переменные окружения в блок функции.

Например, представьте, что вы запустили в Twitter ботов Serverless Superman и Big Data Batman. Поскольку это отдельные аккаунты, у каждого из них будут свои маркеры доступа к Twitter. Вы бы структурировали это следующим образом:

Теперь у нас есть две функции — superman и batman — и каждая из них имеет свой уникальный токен доступа для аутентификации в Twitter. Успехов!

Секреты работы с небольшими командами и проектами

Теперь, когда мы разобрались с основами, давайте немного углубимся в работу с секретами для ваших проектов.

В приведенном выше примере большая проблема заключается в том, что наш маркер доступа находится в открытом виде прямо в файле serverless.yml. Это секретный секрет, который мы не хотим фиксировать в системе управления исходным кодом.

Лучшим вариантом является использование функции параметров панели инструментов Serverless Framework Pro. Если вы уже используете Serverless Framework Pro для мониторинга своих бессерверных служб, то имеет смысл использовать тот же инструмент для централизованного хранения секретов. Это можно легко сделать и на разных этапах (или окружениях).

После входа в систему на панели управления нажмите на «профили» в верхнем левом углу, затем либо выберите один из существующих профилей, которые вы уже назначили для определенного этапа, либо создайте новый. Открыв профиль, вы увидите вкладку «параметры». Именно здесь вы можете добавить любой параметр для данного этапа профиля развертывания. Затем вы можете повторить этот процесс для любого другого этапа, который может понадобиться вашим службам, и добавить значения, характерные для этого этапа.

Но как это работает? Ну, в нашем serverless.yml мы можем ссылаться на эти параметры, используя синтаксис ${param:keyname}. А затем, во время развертывания, Serverless Framework будет считывать значения из нашей конфигурации Serverless Pro и заменять синтаксис переменных фактическими значениями.

Управление секретами для больших проектов и команд

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

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

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

В этом случае я бы рекомендовал использовать AWS Parameter Store для обработки ваших секретов. Он очень прост в использовании и обеспечивает хороший контроль доступа к определенным секретам.

Однако для взаимодействия с Parameter Store вам придется написать код в обработчике Lambda — вы не сможете воспользоваться простыми сокращениями из Serverless Framework.

Вот пример того, как можно получить значение конфигурации из SSM в вашей функции Lambda на Python:

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

Другие соображения

Это лишь поверхностный анализ работы с конфигурацией в большом проекте Serverless. Еще один вопрос, который вы захотите рассмотреть, — это обновление конфигурации в рамках конкретного контейнера Lambda. Поскольку экземпляр Lambda может повторно использоваться во многих вызовах функций, вы захотите периодически обновлять конфигурацию на случай, если она изменилась с момента первоначального запуска экземпляра.

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

Первоначально опубликовано на https://www.serverless.com.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *