Як зробити чутливу інформацію секретною

Дата оновлення перекладу 2024-05-09

Як зробити чутливу інформацію секретною

Змінні середовища - це найкращий спосіб зберігати конфігурацію, яка залежить від того, де виконується додаток - наприклад, деякий 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
$ APP_RUNTIME_ENV=prod php bin/console secrets:generate-keys

Це згенерує 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, ви можете послатися на нього так:

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 способи зробити це:

  1. Завантаження файлу:

Перша опція - скопіювати ключ розшифровки виробництва
config/secrets/prod/prod.decrypt.private.php на ваш сервер.

  1. Використання змінної середовища

Другий спосіб - встановити змінну середовища 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'