Как сделать чувствительную информацию секретной
Дата обновления перевода 2024-07-16
Как сделать чувствительную информацию секретной
Переменные окружения - это наилучший способ хранить конфигурицию, которая зависит от того, где выполняется приложение - к примеру, некоторый API-ключ, который может быть установлен в одном значении при локальной разработке, и в другом значении при производстве.
Когда эти значения чувствительны и должны держаться в тайне, вы можете безопасно хранить их используя систему управления секретами Symfony - иногда называемую "сейфом".
Note
Система Секретов требует PHP-расширения sodium.
Генерирование заширофванных ключей
Для того, чтобы зашифровывать и расшифровывать секреты, Symfony необходимы криптографические ключи. Для того, чтобы сгенрировать пару ключей, выполните:
1
$ php bin/console secrets:generate-keys
Это сгенерирует пару асимметричных крипторгафических ключей. Каждое
окружение имеет собственный набор ключей.
Предполагая, что вы пишете код локально в окружении dev
, это создаст:
config/secrets/dev/dev.encrypt.public.php
- Используется для шифрования/добавления секретов в сейф. Может быть отправлено безопасно.
config/secrets/dev/dev.decrypt.private.php
-
Используется для расшифровки/чтения ключей из сейфа. Ключ расшифровки
dev
может быть отправлен (предполагая, что в сейфе dev не хранится высокочувствительных секретов), но ключ расшифровкиprod
не нужно отправлять никогда.
Вы можете сгенерировать пару криптографических ключей для окружения prod
,
выполнив следующее:
1
$ php bin/console secrets:generate-keys --env=prod
Это сгенерирует config/secrets/prod/prod.encrypt.public.php
и
config/secrets/prod/prod.decrypt.private.php
.
Danger
Файл prod.decrypt.private.php
высокочувствителен. Ваша команда разработчиков и даже
сервисы Непрерывной интеграции не нуждаются в этом ключе. Если ключ расшифровки был
выявлен (например, от вас ушел бывший сотрудник), вам нужно подумать о создании нового,
путем выполнения secrets:generate-keys --rotate
.
Создание или обновление секретов
Предположим, что вы хотите хранить свой пароль базы данных как секрет. Используя
команду secrets:set
, вы должны добавить этот секрет в сейфы dev
и prod
:
1 2 3 4 5 6 7
# ввод скрыт во время того, как вы печатаете, из соображений безопасности
# установите ваше значение разработки по умолчанию (может быть переопределено локально)
$ php bin/console secrets:set DATABASE_PASSWORD
# установите ваше значение производства
$ php bin/console secrets:set DATABASE_PASSWORD --env=prod
Это создаст новый файл для секрета в config/secrets/dev
и еще один в
config/secrets/prod
. Вы также можете установить секрет несколькими другими
способами:
1 2 3 4 5 6 7 8
# предоставьте файл для считывания секрета
$ php bin/console secrets:set DATABASE_PASSWORD ~/Download/password.json
# или содержание, переданное STDIN
$ echo -n "$DB_PASS" | php bin/console secrets:set DATABASE_PASSWORD -
# или позвольте Symfony сгенерировать рандомное зачение за вас
$ php bin/console secrets:set REMEMBER_ME --random
Note
Для переименовывания секретов команды не существует, так что вам нужно будет создать новый секрет и удалить старый.
Ссылание на секреты в файлах конфигурации
На секретные значения можно ссылаться так же как и на переменные окружения . Будьте осторожны, чтобы случайно не определить и секретное значение, и переменную окружения с одинаковым именем: переменные окружения имеют преимущество над секретами.
Если вы сохранили секрет в DATABASE_PASSWORD
, вы можете сослаться на него так:
1 2 3 4 5 6
# config/packages/doctrine.yaml
doctrine:
dbal:
password: '%env(DATABASE_PASSWORD)%'
# ...
# ...
Реальное значение не будет выполнено во время прогона: компиляция контейнера и разогрев кеша не нуждаются в ключе расшировки.
Список существующих секретов
Все имеют право получить список имент секретов с помощью команды
secrets:list
. Если у вас есть ключ расшифровки, вы также можете
увидеть значения секретов, передав опцию --reveal
:
1 2 3 4 5 6 7
$ php bin/console secrets:list --reveal
------------------- ------------ --------------------
Имя Значение Локальное значение
------------------- ------------ --------------------
DATABASE_PASSWORD "my secret"
------------------- ------------ --------------------
Раскрытие существующих секретов
Если у вас есть ключ расшифровки, команда secrets:reveal
позволяет
раскрыть значение одного секрета.
1 2 3
$ php bin/console secrets:reveal DATABASE_PASSWORD
my secret
7.1
Команда secrets:reveal
была представлена в Symfony 7.1.
Удаление секретов
Symfony предоставляет удобную команду для удаления Секрета:
1
$ php bin/console secrets:remove DATABASE_PASSWORD
Локальные секреты: локальное переопределение секретов
Секреты окружения dev
должны содержать хорошие значения по умолчанию для разработки.
Но иногда разработчику все равно нужно переопределить секретное значение локально во
время разработки.
Большинство команд secrets
- включая secrets:set
- имеют опцию --local
,
которая хранит "секрет" в файле .env.{env}.local
в качестве стандартной переменной
окружения. Чтобы переопределить секрет DATABASE_PASSWORD
локально, выполните:
1
$ php bin/console secrets:set DATABASE_PASSWORD --local
Если вы введете root
, то теперь вы увидите в вашем файле .env.dev.local
следующее:
1
DATABASE_PASSWORD=root
Это переопределит секрет DATABASE_PASSWORD
, так как переменные окружения всегда
главенствуют над секретами.
Список секретов теперь тоже будет содержать локальную переменную:
1 2 3 4 5 6
$ php bin/console secrets:list --reveal
------------------- ------------ --------------------
Имя Значение Локальное значение
------------------- ------------ --------------------
DATABASE_PASSWORD "dev value" "root"
------------------- ------------ --------------------
Symfony также предоставляет команду secrets:decrypt-to-local
, которая расшифровывает
все секреты и сохраняет их в локальном сейфе, и команду secrets:encrypt-from-local
для шифрования всех локальных секретов в сейф.
Секреты в окружении тестирования
Если вы добавите секрет в окружения dev
и prod
, его не будет в окружении
test
. Вы можете создать "сейф" для окружения test
и определить секреты
в нем. Но легче будет установить тестовые значения через файл .env.test
:
1 2
# .env.test
DATABASE_PASSWORD="testing"
Запуск секретов в производство
В связи с тем, что ключи расшифровки никогда не должны отправляться, вам понадобится вручную сохранять этот файл где-то и запускать его. Есть 2 способа сделать это:
- Загрузка файла
Первая опция - скопировать ключ расшифровки производства -
config/secrets/prod/prod.decrypt.private.php
на ваш сервер.
- Использование переменной окружения
Второй способ - установить переменную окружения SYMFONY_DECRYPTION_SECRET
в
зашифрованное значение base64 ключа расшифровки производства. Модным способом
получения значения ключа является:
1 2 3
# эта команда только получает значение ключа; вы должны также установить переменную окружения
# в вашей системе с этим значением (например, `export SYMFONY_DECRYPTION_SECRET=...`)
$ php -r 'echo base64_encode(require "config/secrets/prod/prod.decrypt.private.php");'
Чтобы улучшить производительность (т.е. избежать расшифровки секретов во время прогона), вы можете расшифровать ваши секреты во время запуска в "локальном" сейфе:
1
$ APP_RUNTIME_ENV=prod php bin/console secrets:decrypt-to-local --force
Это запишет все расшифрованные секреты в файл .env.prod.local
. После того,
как это будет сделано, ключ расшифровки не должен оставаться на сервере(ах).
Ротация секретов
Команда secrets:generate-keys
предоставляет опцию --rotate
для регенерирования
криптографических ключей. Symfony расшифрует существующие секреты с помощью старого
ключа, сгенерирует новые криптографические ключи и повторно зашифрует секреты с новым
ключом. Для того, чтобы расшифровать предыдущие секреты, разработчику нужен будет
ключ расшифровки.
Конфигурация
Система секретов включена по умолчанию и некоторые аспекты ее поведения можно сконфигурировать:
1 2 3 4 5 6
# config/packages/framework.yaml
framework:
secrets:
#vault_directory: '%kernel.project_dir%/config/secrets/%kernel.environment%'
#local_dotenv_file: '%kernel.project_dir%/.env.%kernel.environment%.local'
#decryption_env_var: 'base64:default::SYMFONY_DECRYPTION_SECRET'