Про использование секретов в Кубернетис

August 10, 2018
kubernetes

Часто начинающие разработчики «грешат» тем, что зашивают в код, коммитят в репозиторий или пишут в базу такие данные как: адреса апи, токены, файлы с ключами, пароли. В английской литературе такие данные называются sensitive data. Если от закоммичивания паролей уже все отказались, то остальное еще можно встретить.

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

Решением является перенос sensitive данных в переменные окружения либо в отдельные файлы с правами на чтение для вашего приложения. Доступ к этим данным в боевом окружении должен быть строго ограничен. Т.е даже разработчик в большинстве случаев не должен иметь доступ к этой информации. Например, стандартный кейс - вашему приложению нужен доступ к базе данных. Правильный алгоритм: вы создаете переменную, из которой приложение будет считывать эти данные, просите своего dba создать новый коннект к базе для вашего приложения, dba передает креденшиалы админам, те в свою очередь зашивают их в переменные окружения сервиса, стартующего ваше приложение либо еще как-то. При такой схеме непосредственный доступ к паролю имеют только два человека: dba и человек ответственный за конфигурацию вашего приложения на продакшене.

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

Объекты типа secret предназначены для хранения sensitive данных: пароли, токены, ключи. Перенос информации в секреты обеспечивает больший контроль над ее использованием и снижает риск случайного изменения или утечки этих данных. Если данные в секрете обновляются, то во всех использующих его приложениях они автоматически тоже обновятся. Секреты могут применяться в двух вариантах: как файловые разделы примонтированные к одному или нескольким контейнерам или как переменные окружения при старте контейнера.

Большое достоинство секретов состоит в том, что один и тот же секрет можно использовать и как переменную окружения, и примонтировать как файл.

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

Для хранения файлов в облаке GoogleStorage используются сущности называемые бакетами. Для доступа к бакету необходимо сгенерирвоать файл с ключом из консоли управления GS. GoogleStorage sdk для Go по умолчанию может брать ключ доступа к бакету из файла, путь к которому лежит в переменной окружения GOOGLE_APPLICATION вашего приложения. Как это сделать показано ниже на части спецификации Кубернетиса:

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

 name: myapi

spec:

 replicas: 1

 template:

  metadata:

   labels:

    service: myapi

  spec:

   containers:

   - name: myapi

   ...

    volumeMounts:

    - name: myapi-gskey

     mountPath: /keys

     readOnly: true

    env:

    - name: GOOGLE_APPLICATION_CREDENTIALS

     value: '/keys/gs_cloud_bucket_key_file'

   volumes:

  - name: myapi-gskey

    secret:

     secretName: my-api

     defaultMode: 0400
     

Сам секрет в Кубернетис можно залить через консоль или через интерфейс управления Кубернетиса:

Управление секретами в Кубернетис

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