Коллега уволился. Его скрипты - нет
«Оно работало» — два слова, после которых начинается самое интересное.
Никто не смотрел внутрь два года. Незачем было.
Я посмотрел. Там жил призрак уволенного коллеги.
Сам ушёл. Скрипты — остались.
Пролог
Есть системы, которые просто работают. Не трогаешь — не ломается. Gluu был такой системой.
Сервер аутентификации. Три критических приложения висели на нём. Сертификаты обновлялись сами. Пользователи входили сами. Я получил доступ при онбординге и благополучно забыл о его существовании.
Незачем было помнить.
Акт I: Клиент написал
Раннее утро, первый кофе. Slack открыт, но ничего не жду.
Клиент написал: Gluu не работает.
Не алерт. Не автоматика. Живой человек написал в чат. Это значит: всё, что должно было сработать до него — не сработало.
SSL-сертификат истёк. Это как просроченный паспорт: все знают кто ты, но пускать не обязаны. Браузеры и приложения — не пустили.
Система, которая должна была этот сертификат обновлять, существовала в зомби-состоянии: сервер включён, отвечал на пинг и молчал на всё остальное.
И тут выяснилось, что пароль от этого сервера мне при передаче проекта не дали. Не сказали что он есть. Не сказали где лежит. Пришлось тыкать коллег и начальство. Это заняло время. Сертификат продолжал быть истёкшим.
Пароль нашли. Подключиться к серверу всё равно не удалось — он был не совсем мёртв, но точно не жив.
Сделал резервную копию, поднял новый сервер из неё — уже со своим паролем. Вручную запустил обновление сертификата. Gluu заработал. За окном успело стемнеть.
Проблема решена. И вот теперь — пока тихо — я решил посмотреть, на что именно нажал.
Сервер, который занимался обновлением сертификатов, работал круглосуточно. За него платили каждый месяц. Его единственная задача — раз в сутки проверить и при необходимости обновить один сертификат.
Отдельный сервер. Круглосуточно. Ради одной задачи в квартал.
Это как держать машину с включённым мотором круглые сутки, потому что раз в день надо отвезти письмо.
Кандидат на замену.
У меня был опыт похожей задачи на другом проекте — не сервер, а бессерверная функция. Разница принципиальная: сервер работает постоянно и постоянно стоит денег, бессерверная функция запускается только когда нужна — проверила, сделала дело, выключилась. Я взял ту же схему и переписал под текущую: автоматическая проверка раз в сутки, если сертификат истекает — автоматически получает новый и раскладывает куда нужно. Без выделенного сервера, без лишних расходов.
Напоминание в календарь — проверить через 60 дней.
Вроде всё работает.
Акт II: 60 дней спустя — призрак
Напоминание сработало. Проверяю.
Сертификат обновлён везде где нужно. Новый, свежий.
Gluu использует старый.
Полез в документацию — нашёл инструкцию: "делай раз, делай два, получишь результат". Почему так — не написано. Зачем — не написано.
Пошёл смотреть скрипт, который должен был доставить новый сертификат в Gluu. Нашёл адрес — он подключался к тому самому серверу. Который я выключил два месяца назад.
Новая система выпускала сертификат исправно. И передавала его призраку.
Хорошо что я не удалил тот старый сервер — оставил на всякий случай. Включил. Открыл скрипт который там нашёл.
И увидел цепочку.
Чтобы обновить сертификат в Gluu, нужно было: подключиться к промежуточному серверу под именем уволенного коллеги → с него подключиться к самому Gluu тоже под его именем → от его имени запустить скрипт обновления.
Бывшего коллеги.
Сотрудник, который давно ушёл из компании. Его учётная запись на серверах — осталась. Его скрипт — всё ещё запускался каждые 60 дней.
Я открыл этот скрипт.
Двенадцать операций резервного копирования до того, как скрипт делал что-то полезное. Резервные копии писались в ту же папку, которую копировали. Проверок на ошибки — ноль. Верификации результата — ноль. Каждые 60 дней папка с сертификатами обрастала двенадцатью новыми слоями, как кольца на дереве.
Кто-то очень боялся потерять файл. И совсем не боялся уронить прод.
Убрал промежуточный сервер из цепочки — теперь скрипт шёл напрямую к Gluu. Заменил учётные данные. Исправил пути резервных копий. Сертификат обновился.
Поставил напоминание ещё на 60 дней.
Вроде работает. Вроде.
Акт III: Java хранит секреты
Напоминание сработало.
Сертификат свежий везде. В Gluu — старый. Опять.
Но в этот раз я не стал чинить по верхам.
Потянул за нитку — свежий сертификат лежал на диске Gluu. Система его не видела.
Залез в скрипт с фонариком.
Нашёл проблему с перезапуском одного из сервисов — починил. Запустил. Gluu всё равно не верит сертификату. Проверил права на файлы — чисто. Проверил что сертификат собран корректно — да. Импортировал сертификат в хранилище ключей — прошёл.
Сервер утверждает, что всё сделал правильно. И не работает.
Добавил паузы. Добавил проверки. Запустил.
Не работает.
Встал. Налил воды. Сел обратно.
Открыл логи. Километры сообщений об ошибках, написанных для программистов, не для людей. Где-то среди них — одна строка, которая имела значение:
PKIX path validation failed: timestamp check failed
Java считала сертификат просроченным. Я точно знал, что загрузил свежий. Хранилище ключей говорило что всё ок. Java говорила что сертификат старый.
Перечитал. Медленно — не ошибку искал, ошибка была понятна. Искал порядок. Кто раньше, кто позже.
И увидел — не ответ, только след. Но след был.
Сервисы Gluu стартовали одновременно. Один — медленнее остальных. Пока он поднимался и подключался к хранилищу ключей, остальные уже работали. В старом скрипте — хаотичный запуск без пауз. Это был баг. Но именно он давал нужный побочный эффект: медленный сервис успевал подхватить свежий сертификат в момент переподключения.
Я сделал запуск упорядоченным. Детерминированным. Правильным.
Второй баг перестал компенсировать первый. Система упала.
Это называется классика.
Я честно пробовал обойтись без остановки. Не вышло.
Нужна была полная остановка: выключить всё, почистить временные файлы, загрузить новый сертификат, запустить сервисы в правильном порядке с паузами, убедиться что каждый поднялся.
Я переписал скрипт заново. Проверка на каждом шаге. Логирование каждого действия. Ожидание после каждого запуска. Финальный тест — постучался без пароля, получил «иди отсюда». Значит, работает.
И отдельный скрипт для диагностики. И документация — не "делай раз, делай два", а с объяснением что, зачем и почему именно так.
Финал
Договорился о плановой остановке заранее. Назначил на нерабочее время. Предупредил клиента.
Тишина в чате. Клиент ждёт. Я смотрю на терминал.
Запустил вручную — не стал ждать расписания. Система должна была отработать сама. Но я хотел это видеть.
Смотрел как система отрабатывает шаг за шагом: проверка сроков — сертификат истекает. Запрос нового — получен, сохранён. Сигнал дошёл. Подключение к Gluu. Скрипт: остановка, чистка, загрузка, запуск в правильном порядке, пауза, проверка — все процессы запущены. Финальный тест — постучался без пароля, получил «иди отсюда».
Всё прошло автоматически. С первого раза.
Теперь раз в 60 дней система обновляет сертификат. Независимый мониторинг проверяет срок действия — если до истечения меньше 14 дней, приходит алерт. Не письмо об успехе, которое перестаёшь замечать через полгода. Сигнал о проблеме, который требует действия.
Gluu 3.1.8 всё ещё работает. Обновить нельзя — лицензия изменилась, это уже не апгрейд, а новая установка с ручной миграцией. Клиент решил постепенно переходить на другое решение. Когда-то.
Но сейчас система больше не тайна. Есть ранбук — что делать если сломалось. Есть полное описание — как устроено и почему именно так. Есть скрипт диагностики. Следующему инженеру не придётся начинать с нуля.
Оно работает.
Теперь я знаю почему.

«Оно работало» - это два слова, а не три :)