Задача прилетіла одним рядком: півсотні з гаком AWS Lambda-функцій на Python 3.8, і до end of life рантайму лишалися місяці. На папері апгрейд рантайму Python 3.8, у якого добігає кінця підтримка, — це просто зміна версії. Насправді ж, щойно AWS перестає патчити застарілий рантайм, кожна незакрита вразливість стає особисто твоєю. До цих функцій ніхто не торкався понад рік. Уся колективна мудрість вміщалася у три слова: «Працює — не чіпай».

Знамениті останні слова.

Розкриваємо капсули часу

Я почав там, де починається будь-який чесний аудит, — із CloudWatch. Частота викликів, error rate, дати останніх змін. Усе, що не спрацьовувало 90 днів, ішло до списку кандидатів на видалення: найшвидша міграція — це функція, яку ти видалив. Потім я відкрив тих, хто вцілів.

Це був не апгрейд Python. Це була археологія. Кожна функція — маленька капсула часу з підписом «написав опівночі й більше не повертався». Ось що було всередині:

  • Захардкоджені креди — навіть не змінні оточення, а сирі рядки прямо в коді. В одній лежали доступи до бази ще з 2019 року.
  • Застарілі бібліотеки з відомими CVE, не запінені ні до чого.
  • Нуль тестів на всі п'ятдесят із гаком функцій. Не благенький сьют. Нуль.
  • IAM-ролі з Action: "*", Resource: "*" — навстіж, усі до однієї.
  • Функції, що ходять у RDS через відкритий інтернет, без жодної VPC-ізоляції.
  • Документація, що дорівнювала імені функції. І все.

Чому не «великий вибух»

Спокуса — переписати все одразу, смикнути рубильник і молитися. Цей фільм я вже бачив. Тому пішов по одній функції за раз.

Кожна отримувала однаковий набір процедур: рантайм із 3.8 на 3.11, кожна залежність запінена й перевірена на відомі CVE, а спільні бібліотеки винесені в Lambda layers — щоб наступне оновлення робилося в одному місці, а не в п'ятдесяти. Потім я писав тести — для більшості це були перші тести в їхньому житті — і документацію, яка пояснювала, навіщо функція існує, а не лише що вона робить. Саме «навіщо» й потрібне наступному інженеру о третій ночі.

Розкатка — canary-деплой зі зсувом трафіку: 5 відсотків, потім 25, потім повний перехід, з автоматичним відкатом, якщо підскакував error rate. Жодного великого вибуху. Жодних молитов. Якщо функція косячила на 5 відсотках трафіку, до решти 95 вона не доходила.

Security hardening тим самим заходом

Раз уже я й так був усередині кожної функції, лагодити рантайм і лишати решту гнити було б посадовим злочином. Тому гарденінг ішов паралельно:

  • IAM переписаний з нуля за принципом least privilege. Жодних wildcard. Кожна роль отримала рівно ті права, що функція використовує, і жодним більше.
  • Захардкоджені креди переїхали в Secrets Manager, з ротацією й підтягуванням у рантаймі.
  • Функції з доступом до бази заведені у VPC з приватними сабнетами — і RDS перестав стирчати у відкритий інтернет.

Результат

П'ятдесят із гаком функцій по тому:

  • Кожна функція на підтримуваному рантаймі.
  • Нуль даунтайму за всю міграцію.
  • Нуль wildcard-політик в IAM.
  • Нуль захардкоджених секретів.
  • Справжні тести. Документація, за яку наступний інженер мене не проклинатиме.

І невеликий бонус, якого я не чекав: cold start'и зменшилися, бо Python 3.11 просто швидший за 3.8. Нудна рутинна задача тихцем зробила платформу проворнішою.

«Не чіпай» — це страх, а не стратегія

Ось що забувають любителі serverless. «Serverless» не означає «без обслуговування» — це означає, що обслуговування невидиме, доки рантайм не доходить до end of life і все не відвалюється. Сервера, на який можна тицьнути пальцем, немає, тому борг ховається ще краще.

«Не чіпай» — це технічний борг мовою страху. Кожен день, що ти ігноруєш рантайм на end of life, набігають відсотки — доки не приходять до сплати у вигляді інциденту з безпекою чи пейджа о третій ночі. Кожна система «не чіпай» у твоєму стеку — це майбутній алерт, що тебе розбудить.

Тож обери одну цього тижня. Найстарішу, найстрашнішу, ту, яку краще не чіпати. Відкрий. Прочитай. Прожени тести. Або виявиться, що все гаразд, і спатимеш спокійніше, або знайдеш креди з 2019-го раніше, ніж їх знайде атакувальник.

Яка система у твоєму стеку найстаріша й найбільш незаймана прямо зараз?