Дата обновления перевода 2022-01-03
Как сделать чувствительную информацию секретной¶
Переменные окружения - это наилучший способ хранить конфигурицию, которая зависит от того, где выполняется приложение - к примеру, некоторый API-ключ, который может быть установлен в одном значении при локальной разработке, и в другом значении при производстве.
Когда эти значения чувствительны и должны держаться в тайне, вы можете безопасно хранить их используя систему управления секретами Symfony - иногда называемую “сейфом”.
Note
Система Секретом требует PHP-расширения sodium, которое входит в пакет PHP 7.2. Если вы используете более раннюю версию PHP, вы можете установить PHP-расширение libsodium, или использовать пакет paragonie/sodium_compat.
Генерирование заширофванных ключей¶
Для того, чтобы зашифровывать и расшифровывать секреты, 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
.
Caution
Файл 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
, вы можете сослаться на него так:
- YAML
1 2 3 4 5 6
# config/packages/doctrine.yaml doctrine: dbal: password: '%env(DATABASE_PASSWORD)%' # ... # ...
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<!-- config/packages/doctrine.xml --> <?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/doctrine https://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd"> <doctrine:config> <doctrine:dbal password="%env(DATABASE_PASSWORD)%" /> </doctrine:config> </container>
- PHP
1 2 3 4 5 6 7 8 9
// config/packages/doctrine.php use Symfony\Config\DoctrineConfig; return static function (DoctrineConfig $doctrine) { $doctrine->dbal() ->connection('default') ->password('%env(DATABASE_PASSWORD)%') ; };
Реальное значение не будет выполнено во время прогона: компиляция контейнера и разогрев кеша не нуждаются в ключе расшировки.
Список существующих секретов¶
Все имеют право получить список имент секретов с помощью команды
secrets:list
. Если у вас есть ключ расшифровки, вы также можете
увидеть значения секретов, передав опцию --reveal
:
1 2 3 4 5 6 7 | $ php bin/console secrets:list --reveal
------------------- ------------ --------------------
Имя Значение Локальное значение
------------------- ------------ --------------------
DATABASE_PASSWORD "my secret"
------------------- ------------ --------------------
|
Удаление секретов¶
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 | $ php bin/console secrets:decrypt-to-local --force --env=prod
|
Это запишет все расшифрованные секреты в файл .env.prod.local
. После того,
как это будет сделано, ключ расшифровки не должен оставаться на сервере(ах).
Ротация секретов¶
Команда secrets:generate-keys
предоставляет опцию --rotate
для регенерирования
криптографических ключей. Symfony расшифрует существующие секреты с помощью старого
ключа, сгенерирует новые криптографические ключи и повторно зашифрует секреты с новым
ключом. Для того, чтобы расшифровать предыдущие секреты, разработчику нужен будет
ключ расшифровки.
Конфигурация¶
Система секретов включена по умолчанию и некоторые аспекты ее поведения можно сконфигурировать:
- YAML
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'
- XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<!-- config/packages/framework.xml --> <?xml version="1.0" encoding="UTF-8" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:framework="http://symfony.com/schema/dic/framework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/framework https://symfony.com/schema/dic/framework/framework-1.0.xsd" > <framework:config secret="%env(APP_SECRET)%"> <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" /> </framework:config> </container>
- PHP
1 2 3 4 5 6 7 8 9 10
// config/packages/framework.php use Symfony\Config\FrameworkConfig; return static function (FrameworkConfig $framework) { $framework->secrets() // ->vaultDirectory('%kernel.project_dir%/config/secrets/%kernel.environment%') // ->localDotenvFile('%kernel.project_dir%/.env.%kernel.environment%.local') // ->decryptionEnvVar('base64:default::SYMFONY_DECRYPTION_SECRET') ; };
Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.