Найти тему

Как я случайно заблокировал 10 000 телефонов в Южной Америке

Перед вами — забавная и поучительная история Шантну Тивари, небрежность которого привела к крайне печальным последствиям: более десяти тысяч телефонов в Южной Америке в один момент оказались заблокированными. Люди не могли даже позвонить, не говоря уж про более сложные действия. О том, как это было — под катом.

Это ужасная история о том, что происходит, когда ваш код/​​тестовые скрипты работают не так, как планировалось. Это также ужасная история о том, как плохо не тестировать свой код. Надеюсь, благодаря ей вы тоже поймёте, что тестовые сценарии требуют такого же внимания и планирования, как и «правильный» код.

Ночь ужасающего скрипта

Как и во многих страшилках, моя началась в пятницу вечером, примерно в 17:15. Я как раз собирался уходить с работы, как вдруг получил email от коллеги:

Помнишь тот скрипт, который мы выкатили вчера? Он заблокировал тысячи телефонов в Южной Америке. Боюсь, нас уволят.

Когда я прочёл сообщение, меня обуял ужас. Это был разгар самоизоляции из-за COVID-19, а я был обычным подрядчиком с чуть ли не устными договорённостями. В случае чего найти новую работу было бы непросто. Но как, чёрт возьми, мой скрипт мог совершить такое?

Небольшая предыстория о телефонной компании K-Pop

Я работал в ИБ-компании в группе автоматизации тестирования. Основным нашим продуктом было приложение, поставляемое операторам мобильной связи. С его помощью оператор мог заблокировать любой свой телефон, если его украли или хозяин переставал своевременно оплачивать покупку.

Приложение создавалось как часть ОС Android, поэтому удалять его было нельзя. Иначе все низкоуровневые функции телефонов переставали работать. То есть владелец телефона не смог бы звонить, пользоваться Wi-Fi и публиковать фотографии в Instagram/Facebook ( ужасно, правда? ). Как только телефон возвращался владельцу/платежи возобновлялись, все функции снова восстанавливались.

Всё просто и удобно. Компания-разработчик даже создала программу, которая помогала операторам понять, какой именно телефон нужно заблокировать. Этот внутренний инструмент работал просто отлично. Я бы даже мог сказать, что это было исключительно благодаря мне, но это слишком высокомерно звучит. Так что работало хорошо в основном благодаря мне.

Но один производитель мобильных телефонов (я назову его K-Pop Phone Manufacturing Company ), базирующийся в Корее, счёл себя слишком гордым, чтобы пользоваться нашим софтом. И требовал работать только на их веб-инструменте. Хозяин — барин. Мне платят, и я работаю с тем, что дают.

В какой момент всё пошло не по плану? Когда друг на друга наложилось несколько факторов.

Медленное крушение

Нашу компания купила одна инвестиционная фирма. Которая хотела не просто отбить вложенные средства, но и подзаработать. Поэтому сроки всех проектов были изменены. Было время, когда мы тестировали три продукта параллельно. И все имели разные требования.

То есть мы тестировали совсем по минимуму, надеясь, что всё идёт хорошо.

Одним из последних тестов была проверка функции блокировки телефонов, данные которых находились в загружаемом оператором CSV-файле. Проще простого. Я написал скрипт на Python, который генерировал несколько случайных телефонных номеров, входил на сервер и блокировал телефоны, а затем входил на другой сервер и проверял результаты. Таким образом, мы смогли протестировать десятки тысяч комбинаций с помощью одного скрипта, выполнение которого заняло всего несколько часов.

Последний скрипт фактически генерировал сотни тысяч случайных номеров, потому что у нас было несколько разных вариантов действий в разных ситуациях.

Вы, наверное, уже сообразили, к чему я веду.

Из-за нехватки времени (или политической воли) мы не проверили, правильно ли написан скрипт. Как только я его допилил, его пустили в работу. Серьёзно, через 10 секунд после нажатия мной кнопки «Сохранить», скрипт запустился на действующих серверах.

Я мог бы проверить свою работу, но это означало, что придётся копаться в коде до поздней ночи. Нет уж, спасибо. Я уже потратил на это несколько ночей и выходных.

Я запустил скрипт — он нормально отработал. Руководители подтвердили, что скрипт делает то, что от него просят. Все были довольны, так как продукт можно будет запустить уже в понедельник, а в выходные не придётся работать.

А потом я получил электронное письмо о том, мы заблокировали тысячи телефонов в Южной Америке: в Перу, Чили и других странах.

Ч-ч-чёрт! КАК!?

Помните, я говорил вам, что телефоны генерируются «случайным образом«? Скрипт случайным образом генерирует 11-значный «номер телефона».

И, конечно же, некоторые из этих телефонов были действующими! И из-за того, как я написал скрипт, и из-за какой-то странной особенности IMEI, все эти телефоны были из Южной Америки.

Очень долгая ночь

Всё это я понял уже спустя 15 минут.

«У нас все ещё есть старый CSV-файл, которые использовался при тестировании?», — спросил мой коллега. Мы могли бы снова выкатить скрипт, но на этот раз с настройкой разблокировки.

Разумеется, нет! У меня была только самая свежая версия. Планировалось, что это будет разовая задачка для быстрой проверки.

Был способ обойти проблему: я мог задействовать K-Pop, чтобы скачать рабочий список у них. Вот только компания разрешала загружать только 100 номеров за раз, а мне нужно было загрузить более 10 000 номеров.

Итак, требовался скрипт для загрузки телефонных номеров. И ещё один, чтобы очистить кривые CSV, которые они нам вернули, чтобы не было новых проблем. И третий скрипт для переподключения к серверу и разблокировки всех телефонов.

Мы работали в паре с коллегой, что позволило закончить работу уже к 18:30. К этому времени все телефоны были разблокированы. Менеджер проекта подтвердил разблокировку и я быстренько отключился, пока не нашлись ещё какие-нибудь косяки.

Уроки, которые мы усвоили (или, что более вероятно, не усвоили):

  • Сценарии тестирования требуют такой же заботы и любви, как и обычный код.
  • Вы никогда не должны тестировать критически важный код в сжатые сроки и под высоким давлением. Вне зависимости от того, что думает руководство ( увы, никто не следует этому совету, ведь если вы хотите сохранить свою работу, вы делаете то, что вам сказали, или ищете новую работу в другом месте).
  • Регистрироваться в системе K-Pop было непросто, но после регистрации вы могли заблокировать любой телефон в любой точке мира.

Компания K-Pop благодаря IMEI знала, какой мобильный оператор «владел» телефоном, и, следовательно, несла за него юридическую ответственность. То есть, если вы покупаете телефон у T-Mobile, он регистрируется на них (в нескольких базах данных), и только T-Mobile имеет право блокировать телефон. По крайней мере, до тех пор, пока клиент не внесёт последний платёж за свой телефон или не сменит провайдера.

И всё же K-Pop Central позволял любому желающему блокировать любой телефон, если вы просто знали его номер телефона или IMEI (оба значения нетрудно получить; номер телефона во многих случаях общеизвестен и известен многим людям).

Урок здесь таков: Сделайте несколько чёртовых проверок, прежде чем блокировать чей-то телефон. Вот только я не знаю, применим этот урок ко мне или к K-Pop (скорее всего, к нам обоим).

  • Тестирование следует проводить постепенно. Вместо того, чтобы тестировать окончательную систему, мы должны сначала протестировать каждый компонент. Почему мы этого не сделали? Потому что у нас не было времени.
  • Сценарий, по которому вы единожды проходитесь по упорядоченному массиву (проверяете «лучший случай»), никогда не бывает хорошим. В идеале нам следовало бы подумать о тестировании вариантов, при которых блокируется чужой телефон. Или предусмотреть мошеннический скрипт, который сделает то же самое, что и мы. Это не только хороший контроль качества, но и хорошая безопасность.
  • Мы считали, что, раз наше собственное программное обеспечение проверяет такие вещи, то и софт K-Pop телефона тоже. Фигушки. На Аллаха надейся, а верблюда привязывай.
  • Не тестируйте ничего в продакшене! У нас был сервер разработки и промежуточный сервер, но их даже не подключали к боевому приложению (из-за нехватки времени и нехватки людей). Кроме того, нам нужно было выпустить продукт в ближайшие 2-3 дня, так что «не могли бы вы просто заткнуться и продолжить тестирование, пожалуйста»?

Как я уже сказал, мы не усвоили ни одного из этих уроков, как только продукт был официально выпущен на следующей неделе, мы вернулись к нашим прежним скриптам, сбрасывающим мусор в базы данных и делая вид, что мы «протестировали» код.

Нас не уволили, потому что мы исправили ошибку очень быстро, но что более важно, некоторые менеджеры проектов и топ-менеджеры по продажам делали то же самое: придумывали номера телефонов и блокировали реальные телефоны. Конечно, они делали это вручную, поэтому блокировке подвергались только 3-4 телефона, а мы заблокировали 10 000, но конечный эффект был таким же. Мы все писали в бассейн, в котором плавали.

Все сделали вид, что это просто ошибка. Но ничего страшного, живи и учись, дружище, живи и учись. Тем более что никто особо не пострадал, за исключением рандомного бедняги из Перу, который не смог позвонить по телефону или опубликовать фотографию с дакфейсом в Instagram. Но, согласитесь, это не такая уж и большая беда.