Сторінка CI/CD змінних — це кладовище забутих секретів. Я знаю, бо щойно провів аудит.
55 змінних. Стільки я знайшов, коли відкрив налаштування GitLab CI/CD для production-сервісу. Connection string у відкритому вигляді. Застарілі паролі, які ніхто не пам'ятає, навіщо створював. Дублюючі токени з трохи різними іменами. Красивий бардак, який всі боялися чіпати.
Знайомо?
Проблема, про яку ніхто не говорить
Ось яка штука з CI/CD змінними: вони накопичуються як пил. Кожен розробник, що торкається пайплайну, додає "ще одну змінну." Ніхто не видаляє, бо ніхто не знає, що зламається. Через півроку маєш 55 змінних, половина з яких — привиди.
Але це гірше, ніж бардак. Це — загроза безпеці.
Connection string лежать в UI GitLab. Навіть "замасковані" — вони в одному неправильно налаштованому джобі від витоку в логи. Креденшали Service Principal, які ротуються... ніколи. Паролі до баз даних, які вивели з експлуатації два спринти тому.
Це не DevOps. Це тікаючий інцидент-репорт.
Аудит
Я зробив те, що ніхто не хотів. Пройшов кожну змінну. Одну за одною. Звірив з реальним YAML пайплайну. Звірив з PowerShell-скриптами деплою. Склав карту: хто що використовує, де і навіщо.
Результат?
- 25 змінних — активно використовуються, необхідні для деплою
- 30 змінних — мертві. Не використовуються. Легасі. Забуті.
- 4 з цих 30 — реальні connection string, які треба було ротувати місяці тому
55% "конфігурації" пайплайну було сміттям. Більше половини.
Міграція: зі змінних у Vault
Connection string не місце в CI/CD змінних. Крапка. Їм місце в Azure Key Vault — централізованому, з контролем доступу, аудитованому, ротованому.
Патерн міграції:
До: Пайплайн читає connection string з GitLab-змінної. Плейнтекст. Керується вручну. Ротується... коли хтось згадає.
Після: Пайплайн аутентифікується в Azure через UAMI (User-Assigned Managed Identity), отримує секрет з Key Vault у рантаймі, використовує, забуває. Жодного плейнтексту в пайплайні. Жодної ручної ротації. Жодного "хто міняв цю змінну минулого вівторка?"
Реалізація напрочуд чиста:
- Зберігаємо імена секретів (не значення) в YAML пайплайну — це просто посилання, не секрети
- Аутентифікуємося в Azure через федеративні токени — нуль збережених креденшалів
- Отримуємо секрети динамічно при деплої —
az keyvault secret show - Використовуємо і забуваємо
Краса в тому, що UAMI означає: пайплайн не зберігає жодного Azure-креденшалу. Жодних паролів Service Principal. Жодних client secret. Ідентіті керується самим Azure. Пайплайн просто каже "я той, хто я є" — і Azure вірить, бо є OIDC federation trust.
Чому UAMI, а не Service Principal
Service Principal — це ізолента Azure-аутентифікації. Працюють, так. Але з багажем:
- Client secret, що закінчуються і ламають пайплайн о 3 ночі
- Церемонії ручної ротації, яких всі бояться
- Креденшали, що зберігаються в черговій CI/CD змінній (що обнулює сенс)
UAMI перевертає модель. Ідентіті призначається ранеру, керується Azure, аутентифікується через OIDC-федерацію. Без секретів. Без ротації. Без інцидентів о 3 ночі, бо хтось забув оновити пароль.
Zero-trust — не маркетинговий термін, коли ти реально це впроваджуєш.
Зачистка
Після міграції секретів у Key Vault я видалив застарілі змінні. Чотири connection string, що місяцями лежали в GitLab — немає їх більше. Потім запропонував очищення решти 26 невикористовуваних змінних після рев'ю скриптів.
Пайплайн навіть не здригнувся. Бо пайплайну вони ніколи не були потрібні.
Найважче в зачистці — усвідомити, скільки з твоєї "критичної конфігурації" — це просто залишки чийогось експерименту дворічної давності.
Чому я навчився
Управління секретами — не разовий проект. Це гігієна. Як чистити зуби — нудно, рутинно, але пропусти — і все згниє.
Кожен пайплайн заслуговує на аудит. Не раз на рік для галочки комплаєнсу. Регулярно. Бо змінні накопичуються, секрети старіють, а те, що було "тимчасовим" у Sprint 12, стає постійним техборгом до Sprint 30.
Кількість змінних у пайплайні обернено пропорційна рівню безпеки команди. Менше змінних — чистіша архітектура.
55 змінних. 25 вижили. Один Key Vault. Нуль секретів у пайплайні.
Так і має бути.