Ротація секретів потрібна регулярно (обмежити шкоду від непоміченого витоку) і негайно після підозри на компрометацію. Складність - не зламати роботу під час заміни.
Загальний принцип - період, коли діють обидва ключі:
- створити новий секрет;
- налаштувати систему приймати і старий, і новий;
- перевести всіх, хто використовує секрет, на новий;
- відкликати старий.
Так працює ротація ключів API партнерів, паролів до бази (два користувачі чи дві паролі в PostgreSQL), підписів вебхуків.
APP_KEY у Laravel шифрує cookie (зокрема сесійну), зашифровані атрибути моделей (каст encrypted), дані Crypt::encrypt(). Проста заміна ключа:
- розлогінить усіх користувачів - старі cookie неможливо розшифрувати;
- зламає зашифровані в базі дані - їх більше неможливо прочитати.
М'яка ротація через APP_PREVIOUS_KEYS:
APP_KEY="base64:новий..."
APP_PREVIOUS_KEYS="base64:старий..."
- шифрування - завжди новим ключем;
- розшифрування - спершу новим, потім по черзі попередніми.
Користувачі лишаються в системі, а сесії поступово перешифровуються новим ключем.
Але дані в базі самі не перешифруються. Значення, зашифровані старим ключем, лишаються такими, доки їх не перезапишуть. Перед тим як прибрати старий ключ із APP_PREVIOUS_KEYS, потрібна міграція даних: прочитати й зберегти кожне зашифроване значення (команда, що проходить по моделях частинами). Інакше видалення старого ключа - знову втрата даних.
Що ще залежить від APP_KEY: підписані URL (URL::signedRoute) - старі посилання стануть недійсними, якщо підпис не перевіряється попередніми ключами; знімки стану Livewire підписані ключем застосунку - відкриті сторінки отримають помилку при наступній дії.
Організаційно:
- менеджер секретів (Vault, AWS Secrets Manager, Doppler, хмарні сховища) - центральне місце, журнал доступу, автоматична ротація для баз даних;
- перелік, де використовується кожен секрет - без нього ротація перетворюється на пошук, що зламалося;
- регламент реагування: хто і як ротує секрети при витоку, скільки часу це займає - відпрацьоване заздалегідь, а не вперше під час інциденту.
Докладніше в документації: Laravel: м'яка ротація ключів шифрування