Надежно хранить секреты приложения Spring Boot в хранилище HashiCorp?

Я прочитал следующее руководство: Конфигурация хранилища

Хорошо, мы установили сервер Vault и поставили 2 пары секретных свойств:

$ vault kv put secret/gs-vault-config example.username=demouser example.password=demopassword
$ vault kv put secret/gs-vault-config/cloud example.username=clouduser example.password=cloudpassword

Приложение Spring boot имеет следующие свойства (bootstrap.properties):

spring.application.name=gs-vault-config
spring.cloud.vault.token=00000000-0000-0000-0000-000000000000
spring.cloud.vault.scheme=http
spring.cloud.vault.kv.enabled=true

Таким образом, на основе spring.cloud.vault.token приложение может считывать защищенные свойства (имя и пароль), но spring.cloud.vault.token хранится в небезопасном месте - bootstrap.properties, которое хранится в репозитории кода. Не могли бы вы объяснить, почему это безопасно?

P.S.

Как мы выяснили, это небезопасно. Как сделать его безопасным? Я понимаю, что может быть несколько решений, чтобы сделать его безопасным, но мне было бы достаточно одного упрощенного примера.


person gstackoverflow    schedule 17.03.2020    source источник
comment
Почему ваш токен хранится в небезопасном месте?   -  person f1sh    schedule 17.03.2020
comment
@ f1sh Насколько я понял, Vault - безопасное место, но репозиторий github - небезопасное место. Чтобы использовать (для подключения из приложения) безопасное хранилище, мне нужно знать токен, и этот токен хранится в github.   -  person gstackoverflow    schedule 17.03.2020


Ответы (3)


Не могли бы вы объяснить, почему это безопасно?

Ответ в том, что это НЕ безопасно ... если вы делаете это таким образом. Например, в справочном руководстве Spring Vault говорится:

"Внимательно рассмотрите свои требования к безопасности. Проверка подлинности с помощью статического токена подходит, если вы хотите быстро приступить к работе с Сейфом, но статический токен больше не защищен. Любое раскрытие информации посторонним лицам позволяет использовать Сейф с соответствующими ролями токенов."< /эм>

Вы должны либо защитить свои статические токены, либо предоставить им доступ только к «секретам» в хранилище, которым вы рады быть широко известными.

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


Насколько я понимаю изначальная проблема, плохо хранить пароли в файле application.properties на Github.

Так же плохо хранить статический токен Vault в файле application.properties на Github.

В чем разница ?

Разницы почти нет1. Это просто неправильный способ использования Vault.


1. Небольшое преимущество заключается в том, что вы можете аннулировать токен, если случайно обнаружите, что он просочился. Но это не значит, что есть смысл публиковать его намеренно.


Так как же сделать все безопасно?

Во-первых, вы ДОЛЖНЫ защитить компьютеры, на которых будут использоваться секреты. Даже если вы не собираетесь хранить настоящие секреты на диске, вам нужно будет хранить разные секреты (надежно) на каждой из ваших машин, чтобы они могли аутентифицировать себя в том месте, где хранятся настоящие секреты.

Вот пример использования Chef.

  1. Настройте безопасный сервер Chef, на котором хранятся конфигурации для ваших машин; то есть рецепты для всех вещей, которые необходимо установить, описания узлов, чтобы сказать, какие рецепты применять, и т. д.

  2. Когда вы загружаете машину в качестве узла, для машины создается пара ключей, которая регистрируется на сервере Chef. Пара ключей также удерживается на машине и должна надежно удерживаться.

  3. Затем вы используете клиент Chef для запуска рецептов, которые устанавливают и настраивают ваш сервер.

Обратите внимание, что это зависит от наличия должным образом защищенной системы для запуска сервера Chef. Он также полагается на то, что каждый из узлов достаточно защищен, чтобы защитить свои собственные ключи.

Есть и другие способы сделать это, но ничего не сработает, если вы не сможете достаточно защитить свой хост.

person Stephen C    schedule 17.03.2020
comment
То есть статический токен Vault + не имеет дополнительного смысла по сравнению с Spring Cloud Confing + Spring Cloud Bus? Таким образом, он просто работает как распределенный централизованный источник собственности. Это правильно? Как сохранить секреты безопасности? - person gstackoverflow; 17.03.2020
comment
Невозможно избежать наличия какого-либо секрета (закрытый ключ, пароль, статический токен, физическое устройство, отпечаток пальца или сканирование сетчатки глаза и т. д.), который необходимо хранить в безопасности. Преимущество Vault (и подобных) заключается в том, что вы можете лучше/надежнее хранить секреты, и у вас есть лучший контроль над тем, кто/что может получить к ним доступ. - person Stephen C; 17.03.2020
comment
Не могли бы вы объяснить, почему использование Vault делает хранение секретов более безопасным? Насколько я понимаю изначальная проблема, плохо хранить пароли в application.properties гутхаба. Хорошо — вместо того, чтобы иметь свойства в гутхабе, мы храним токен хранилища в гутхабе и перемещаем свойства в хранилище. Если хакер знает токен, он легко может прочитать все свойства из хранилища. В чем разница ? - person gstackoverflow; 17.03.2020
comment
Не могли бы вы пояснить свою фразу Вы должны либо защитить свои статические токены, либо предоставить им доступ только к секретам в хранилище, которые вы рады широкой известности. - person gstackoverflow; 17.03.2020
comment
Во всяком случае, я не понимаю, где мне хранить токен Vault? Существуют ли какие-либо передовые методы для его достижения? Должен ли я помещать секрет в каждую среду вручную? - person gstackoverflow; 17.03.2020
comment
1) Не вижу ничего непонятного в том, что я там сказал. 2) В безопасном месте. Или не используйте статические токены. 3) satisfice.com/blog/archives/5164 4) Люди используют такие инструменты развертывания, как Марионетка, шеф-повар и т. д. для такого рода вещей. Вы можете загрузить каждый хост с собственным токеном, а затем он сможет извлекать свои секреты из хранилища. Но хост должен быть достаточно безопасным, чтобы хранить свой токен в секрете. Если вы не можете этого добиться, все это бессмысленно. - person Stephen C; 18.03.2020
comment
Мой пункт 3 особенно уместен в этом случае, потому что вы, кажется, ищете так называемую передовую практику, которая позволит вам сделать вашу систему безопасной, не задумываясь об этом. Их не существует в том смысле, в каком они означают слова «лучшая практика». Вы не можете не думать о безопасности. И вы не можете игнорировать некоторые основополагающие истины... такие как необходимость защитить свои системы, прежде чем вы поместите на них какие-либо секреты. - person Stephen C; 18.03.2020
comment
Не могли бы вы привести пример безопасной конфигурации? Я считаю, что пример поможет мне лучше понять эту тему. - person gstackoverflow; 19.03.2020
comment
Я не стараюсь не думать о безопасности. Я просто хочу понять некоторые основы того, КАК достичь этой безопасности. - person gstackoverflow; 19.03.2020
comment
Ну, основная фундаментальная вещь заключается в том, что вы должны защитить токен, пароль или что-то еще, что вы используете для разблокировки хранилища. Искробезопасной конфигурации не существует. - person Stephen C; 19.03.2020

Хранение spring.cloud.vault.token в application.properties, зарегистрированном в VCS (например, Git), может поставить под угрозу все секреты, хранящиеся в Vault.

Решение состоит в том, чтобы не хранить токен Vault в application.properties в виде обычного текста. Есть несколько вариантов.

Удалить токен хранилища из application.properties

Просто удалите spring.cloud.vault.token из application.properties и вместо этого укажите его через системное свойство -Dspring.cloud.vault.token=00000000-0000-0000-0000-000000000000 (при запуске приложения) или переменную среды SPRING_CLOUD_VAULT_TOKEN. Переменная окружения особенно удобна, если вы используете контейнеры (Docker или Kubernetes).

Храните зашифрованный токен Vault в application.properties

Вы можете сохранить свойство spring.cloud.vault.token в application.properties, если оно зашифровано.

Spring Cloud Config поддерживает расшифровку свойств со значениями, начинающимися с {cipher} :

spring.cloud.vault.token={cipher}encrypted_vault_token

Чтобы использовать шифрование и дешифрование свойств, вам понадобятся следующие зависимости (пример для Gradle):

implementation 'org.springframework.cloud:spring-cloud-context:2.2.2.RELEASE'
implementation 'org.bouncycastle:bcprov-jdk15on:1.64'

Симметричное шифрование

Самый простой способ зашифровать свойства — использовать симметричное шифрование.

Придумайте симметричный ключ (например s3cr3t).

Чтобы зашифровать токен Vault, вы можете использовать Spring. Загрузите CLI с помощью Spring Boot Cloud CLI:

curl "https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.2.2.RELEASE/spring-boot-cli-2.2.2.RELEASE-bin.tar.gz" -o spring-boot-cli-bin.tar.gz
tar -xf spring-boot-cli-bin.tar.gz
cd spring-2.2.2.RELEASE
bin/spring install org.springframework.cloud:spring-cloud-cli:2.2.1.RELEASE

bin/spring encrypt 00000000-0000-0000-0000-000000000000 --key s3cr3t
# 507cd1614682535ab8237b448ca73dc74058d3ae9145d63a7381ee67f3046eb1598da6960abdbf2dbf22c47206db5222e45fc74fd6122bc707b61c62f5051e0f

bin/spring decrypt 507cd1614682535ab8237b448ca73dc74058d3ae9145d63a7381ee67f3046eb1598da6960abdbf2dbf22c47206db5222e45fc74fd6122bc707b61c62f5051e0f --key s3cr3t
# 00000000-0000-0000-0000-000000000000

Передайте симметричный ключ приложению в переменной среды ENCRYPT_KEY.

Ключ симметричного шифрования никогда не должен возвращаться в VCS.

Асимметричное шифрование

Рассмотрите асимметричное шифрование с использованием пары открытого и закрытого ключей как более безопасную альтернативу симметричному шифрованию.

Вместо симметричного ключа шифрования вам нужно сгенерировать хранилище ключей (с помощью утилиты keytool, поставляемой с JDK, или openssl).

В bootstrap.properties укажите следующие свойства:

  • encrypt.keyStore.location
  • encrypt.keyStore.password
  • encrypt.keyStore.alias
  • encrypt.keyStore.type

Хранилище ключей должно быть смонтировано в месте, указанном в encrypt.keyStore.location, и никогда не возвращаться в VCS.

Кроме того, пароль, открывающий хранилище ключей, лучше передать в переменной окружения ENCRYPT_KEYSTORE_PASSWORD.

Прочтите об управлении ключами в Spring Cloud Config.

person Evgeniy Khyst    schedule 21.03.2020
comment
Но во всех подходах есть пароль, ключ или что-то, что нужно надежно хранить. Вы не можете обойти это. - person Stephen C; 21.03.2020
comment
Самое простое решение — не хранить мастер-пароль, а держать его только в голове. Или сохраните его в каком-нибудь безопасном месте, таком как AWS Secrets Manager, но введите его вручную. - person Evgeniy Khyst; 21.03.2020
comment
Это решение не подходит для производства. Не работает, если вы не можете ввести пароль при каждой перезагрузке системы. Не работает, если вас сбил зеленый автобус. - person Stephen C; 21.03.2020
comment
Все зависит от того, как выполняется развертывание. Задача состоит в том, чтобы передать мастер-пароль как переменную окружения. В Kubernetes вы можете вручную создать Secret с мастер-паролем и привязать его к переменной среды. Это решение работает с перезагрузками. Хранение мастер-пароля в AWS Secrets Manager решает проблему, если вас сбил автобус. - person Evgeniy Khyst; 21.03.2020

Отвечаю на ваши вопросы

Не могли бы вы объяснить, почему это безопасно?

Это небезопасно! Никогда не помещайте простой секрет в систему контроля версий.

Как мы выяснили, это небезопасно. Как сделать его безопасным?

Некоторые способы повышения безопасности:

  • Используйте переменные окружения вместо файла свойств;
  • Ограничьте доступ на сетевом уровне к серверу Vault только для серверов рабочей нагрузки. Это гарантирует, что никто за пределами этой сети не сможет обменять токен;
  • Vault создает реальные, но временные учетные данные каждый раз, когда используется токен. Уменьшите объем реальных учетных данных до режима только для чтения, когда это возможно;
  • Регулярно меняйте жетон.

Относительно особенностей Spring

Свойства начальной загрузки должны содержать только некритические свойства. Критические свойства можно передать приложению с помощью переменных среды.

spring.cloud.vault.token = ${SPRING_CLOUD_VAULT_TOKEN}

Сводка

Остается вопрос "Кто охраняет ключи?". Но Vault Token на самом деле служит для защиты реальных конфиденциальных данных. В случае утечки токена хранилища вы можете аннулировать только токен.

Улучшить ограничения, откуда приложения могут получить доступ к серверу хранилища, и уменьшить объем реальных учетных данных — это дополнительные способы гарантировать, что только серверы, на которых запущено приложение, могут обмениваться токенами с реальными учетными данными, а реальные учетные данные имеют минимальную возможную привилегию. .

person Anderson Marques    schedule 25.03.2020