Принципы построения систем потоковой аналитики
Проектирование систем потоковой аналитики и потоковой обработки данных имеет свои нюансы, свои проблемы и свой технологический стек. Об этом мы поговорили в очередном открытом уроке, прошедшим накануне запуска курса «Data Engineer».
На вебинаре обсудили:
Когда нужна потоковая обработка? Stream vs Batch
Прежде всего, следует разобраться, когда нам нужна потоковая, а когда пакетная обработка. Давайте поясним сильные и слабые стороны этих подходов.
Итак, минусы пакетной обработки (batch):
Пример 2. Аналитика для веб-портала:
Таким образом, во втором примере лучше использовать стримы.
Элементы СПОД
Инженеры обработки данных захватывают, перемещают, доставляют, преобразовывают и хранят эти самые данные (да-да, хранить данные — это тоже активный процесс!).
Следовательно, чтобы построить систему потоковой обработки данных (СПОД), нам будут нужны следующие элементы:
Инструменты для обработки потоков данных
На роль загрузчика данных у нас есть несколько «кандидатов»:
Apache Flume
Первый, о ком поговорим — это Apache Flume — инструмент для транспортировки данных между различными источниками и хранилищами.
Выше мы создаём один простейший канал, который “сидит” на порту, берёт оттуда данные и просто их логирует. В принципе, для описания одного процесса это ещё нормально, но когда у вас таких процессов десятки, конфигурационный файл превращается в ад. Кто-то добавляет некие визуальные конфигураторы, но зачем мучиться, если есть инструменты, которые делают это из коробки? Например, те же NiFi и StreamSets.
Apache NiFi
По сути, выполняет ту же роль, что и Flume, но уже с визуальным интерфейсом, что большой плюс, особенно когда процессов много.
Пару фактов о NiFi
У нас есть поле для творчества и этапы обработки данных, которые мы туда накидываем. Есть много коннекторов на все возможные системы и т. д.
StreamSets
Это тоже система управления потоком данных с визуальным интерфейсом. Она разработана выходцами из Cloudera, легко устанавливается в виде Parcel на CDH, имеет особую версию SDC Edge для сбора данных с устройств.
Состоит из двух компонент:
Неприятный момент — у StreamSets есть как бесплатная, так и платная части.
Шина обмена данными
Теперь давайте разберёмся, куда мы эти данные будем заливать. Претенденты:
Во всех остальных случаях, Kafka — отличный выбор. По сути, это брокер сообщений с горизонтальным масштабированием и огромной пропускной способностью. Он отлично интегрирован во всю экосистему инструментов для работы с данными и выдерживает большие нагрузки. Обладает универсальнейшим интерфейсом и является кровеносной системой нашей обработки данных.
Внутри Kafka делится на Topic — некий отдельный поток данных из сообщений с одинаковой схемой или, хотя бы, с одинаковым назначением.
Чтобы обсудить следующий нюанс, нужно вспомнить, что источники данных могут немного различаться. Очень важен формат данных:
Отдельного упоминания заслуживает формат сериализации данных Apache Avro. Система использует JSON для определения структуры данных (схемы), которые сериализуются в компактный бинарный формат. Следовательно, мы экономим огромное количество данных, а сериализация/десериализация происходит дешевле.
Вроде бы всё неплохо, но наличие отдельных файлов со схемами порождает проблему, так как нам нужно между разными системами обмениваться файлами. Казалось бы, это просто, но когда вы работаете в разных отделах, ребята на другом конце могут что-нибудь поменять и успокоиться, а у вас всё поломается.
Чтобы не передавать все эти файлы на флешках, дискетах и наскальных рисунках, существует специальный сервис — Schema registry. Это сервис для синхронизации avro-схем между сервисами, которые пишут и читают из Kafka.
В терминах Kafka продюсер — это тот, кто пишет, консьюмер — тот, кто потребляет (читает) данные.
Хранилище данных
Претенденты (на самом деле вариантов много больше, но возьмем лишь несколько):
Как этого добиться в стриминговых системах:
Что касается ClickHouse, то это аналитическая база данных от Yandex. Её главное назначение — аналитика на таблице, наполняемой большим потоком сырых данных. Из плюсов — есть движок ReplacingMergeTree для дедупликации по ключу (дедупликация предназначена для экономии места и может оставлять дубликаты в некоторых случаях, нужно учитывать нюансы).
Остаётся добавить несколько слов про Divolte. Если помните, мы говорили о том, что некоторые данные нужно захватывать. Если вам нужно быстро и на коленке организовать аналитику для какого-нибудь портала, то Divolte — отличный сервис для захвата пользовательских событий на веб-странице через JavaScript.
Практический пример
Что попытаемся сделать? Попробуем построить пайплайн, чтобы в реальном времени собирать Clickstream-данные. Clickstream — виртуальный след, который пользователь оставляет во время нахождения на вашем сайте. Будем захватывать данные с помощью Divolte, а писать их в Kafka.
Для работы нужен Docker, плюс потребуется клонировать следующий репозиторий. Всё происходящее будет запущено в контейнерах. Чтобы согласованно запустить сразу несколько контейнеров будет использоваться docker-compose.yml. Кроме того, есть Dockerfile, собирающий наш StreamSets с определёнными зависимостями.
Также есть три папки:
Для запуска вводим следующую команду:
И наслаждаемся тем, как медленно, но верно запускаются контейнеры. После запуска мы можем перейти по адресу http://localhost:18630/ и сразу же потрогать Divolte:
Итак, у нас есть Divolte, который уже получил какие-то события и записал их в Kafka. Попробуем их высчитать с помощью StreamSets: http://localhost:18630/ (пароль/логин — admin/admin).
Чтобы не мучиться, лучше импортировать Pipeline, назвав его, к примеру, clickstream_pipeline. А из папки examples импортируем clickstream.json. Если всё ок, увидим следующую картину:
Итак, мы создали connection к Кафке, прописали, какая Кафка нам нужна, прописали, какой топик нас интересует, потом выбрали те поля, которые нас интересуют, потом поставили слив в Кафку, прописав, в какую Кафку и какой топик. Отличия в том, что в одном случае, Data format — это Avro, а во втором — просто JSON.
Идём дальше. Мы можем, например, сделать превью, которое захватит в реальном времени из Кафки определённые записи. Далее всё записываем.
Выполнив запуск, увидим, что у нас в Кафку летит поток событий, причём это происходит в реал-тайме:
Теперь можно сделать для этих данных хранилище в ClickHouse. Чтобы работать с ClickHouse, можно использовать простой нативный клиент, выполнив следующую команду:
Обратите внимание — в этой строке указана сеть, к которой нужно подключаться. И в зависимости от того, как у вас называется папка с репозиторием, название сети у вас может отличаться. В общем случае команда будет следующей:
Список сетей можно посмотреть командой:
Что же, осталось всего ничего:
1. Сначала «подпишем» наш ClickHouse на Кафку, «объяснив ему», какого формата данные там нам нужны:
2. Теперь создадим реальную таблицу, куда будем класть итоговые данные:
3. А потом обеспечим связь между этими двумя таблицами:
4. А теперь выберем необходимые поля:
В итоге выбор из целевой таблицы даст нужный нам результат.
Вот и всё, это был простейший Clickstream, который можно построить. Если хотите выполнить вышеописанные шаги самостоятельно, смотрите видео целиком.
PipelineDB: работа с потоками данных
В предыдущих публикациях мы уже затрагивали проблему обработки событий в реальном масштабе времени. Сегодня мы хотели бы вновь вернутся к этой теме и рассказать о новом и весьма интересном инструменте — потоковой СУБД PipelineDB.
PipelineDB основана на кодовой базе PostgreSQL 9.4 и полностью с ней совместима. Её первый релиз состоялся в июле 2015 года, а в январе 2016 вышла в свет enterprise-версия.
Ниже мы сравним PipelineDB с существующими решениями аналогичного плана, приведём краткую инструкцию по установке и первичной настройке, а также разберём практический пример.
Обработка данных в реальном времени: экскурс в историю
Принцип работы PipelineDB можно сформулировать так: «постоянные запросы, кратковременные данные». В реляционных СУБД всё обстоит ровно наоборот: «кратковременные запросы, постоянные данные. В PipelineDB данные не хранятся, а поступают в потоке; их обработка происходит «на лету», в движении.
Первые попытки создания инструментов для обработки данных в движении восходят к концу 1980-х годов, когда появились так называемые активные базы данных (Active Database Systems). Они представляли собой расширения к существующим СУБД для обработки событий при помощи триггеров и правил. В качестве примера решений подобного плана можно назвать HiPAC, Starburst или ODE.
Широкого распространения они, однако, не получили: сфера их применения была достаточно узкой, а синтаксис правил — слишком сложным и запутанным.
В 1990-х — начале 2000-х появились системы управления потоками данных (Data Stream Management Systems): TelegraphCQ (форк PostgreSQL), StreamBase, StreamSQL. Принцип работы этих инструментов заключался в следующем: при помощи так называемых оконных операторов (window operators) потоки преобразовывались в таблицы, по отношению к которому затем можно было применять SQL-запросы.
Появление таких решений было несомненным шагом вперёд, но они не могли обеспечить высокую скорость и производительность при работе с большими потоками данных.
Инструменты, ориентированные на обработку данных без хранения, получили распространение в течение последних 5 — 6 лет. Из самых известных примеров следует выделить, в частности, Storm и Heron. Из появившихся относительно недавно — Apache Calcite. Все эти решения характеризуются сложностью установки и настройки, а также очень высоким порогом вхождения.
Преимущества PipelineDB перед упомянутыми выше инструментами очевидны:
Рассмотрим, как в PipelineDB строится работа с потоками данных. Начнём с анализа двух важнейших понятий: «непрерывное представление» и «поток».
Потоки и непрерывные представления
«Поток» и «непрерывное представление» — главные абстракции PipelineDB.
Поток — это последовательность событий. Запись событий в поток осуществляется точно так же, как запись в таблицы в реляционных ДБ (подробнее об этом см. здесь). Когда событие поступает в поток, к нему добавляется временная метка (timestamp).
Потоки в PipelineDB выполняют вспомогательную функцию, которая заключается в поставке данных для непрерывных представлений. В отличии от таблиц, для потоков не нужно создавать схемы. В поток можно записывать данные, пока он взаимодействует хотя бы с одним непрерывным представлением.
Непрерывное представление (англ. continuous view) — это выборка из потоков и таблиц, обновляемая по мере поступления новых данных. В непрерывные представления попадают события, отбираемые по определённым параметрам.
Чтобы лучше понять, как работает PipelineDB, приведём несколько примеров непрерывных представлений.
Вот так, например, можно создать непрерывное представление для ежедневного подсчёта числа уникальных посетителей, приходящих на сайт по внешним ссылкам:
Ещё один пример — подсчёт числа показов рекламы на сайте за последние 5 минут:
Как видим, непрерывные представления имеют следующую форму:
При создании непрерывного представления по отношению к потокам выполняется операция SELECT; с её помощью отбираются данные, соответствующие требуемым параметрам.
Основные теоретические сведения, необходимые для понимания принципов работы PipelineDB, мы изложили. Переходим к практической части. Сначала мы опишем процедуру установки и первичной настройки PipelineDB, а затем перейдём к практическому примеру.
Установка и первичная настройка
Процедуру установки PipelineDB мы будем описывать на материале OC Ubuntu 14.04. Если вы используете другой дистрибутив Linux, обратитесь к официальной документации.
Чтобы установить PipelineDB, достаточно выполнить две команды:
После этого инициализируем сервер PipelineDB:
Основные настройки PipelineDB хранятся в файле pipelinedb.conf. Они почти не отличаются от соответствующих настроек PostgreSQL.
По умолчанию PipelineDB не может принимать соединения с удалённых хостов. Чтобы изменить эту настройку, откроем файл pipelinedb.conf, найдём в нём раздел Connections and Authentication, расскомментируем первую строку и отредактируем её следующим образом:
После этого пропишем конкретные хосты в файле pg_hba.conf:
Если нам нужно принимать соединения со всех возможных хостов, эта строка должна выглядеть так:
Вот и всё. PipelineDB готова к работе.
Чтобы запустить её в фоновом режиме, выполним следующую команду:
Практический пример: анализируем статистику Википедии
Мы разобрали необходимую теорию, а также описали процедуры установки и первичной настройки PipelineDB. Переходим к особенностям использования PipelineDB на практике.
Мы рассмотрим интересный пример, который приводится в официальной документации PipelineDB: анализ статистики обращений к страницам Википедии и смежных проектов в час (Wiktionary, Wikisources, Wikibooks и другим). Эта статистика размещена в открытом доступе. Информация о каждом обращении представлена в виде записи, состоящей из следующих полей:
Нас будут интересовать максимальное, минимальное и среднее количество обращений к странице в течение часа, а также 99-й перцентиль обращений.
Активируем выполнение непрерывных запросов:
После этого создадим непрерывное представление:
В приведённой команде указано, что мы будем получать данные для непрерывного представления из потока wiki_stream. Чтобы создать такой поток, нам потребуется загрузить с сайта данные, разархивировать, записать в стандартный вывод, а после этого передать PipelineDB с помощью команды COPY:
Отметим, что объём данных очень велик (они хранятся в виде архивов по 80-90 MБ каждый), и их загрузка может занять продолжительное время. Загрузку можно остановить в любой момент нажатием стандартной комбинации клавиш Ctrl+C.
По завершении загрузки выполним команду:
Результат будет представлен в виде таблицы (приводим лишь небольшой фрагмент):
Заключение
PipelineDB — интересный и перспективный продукт. Надеемся, что он будет успешно развиваться и в дальнейшем.
Если у вас есть опыт использования PipelineDB на практике — будем рады, если вы поделитесь опытом в комментариях.
Для желающих узнать больше приводим несколько полезных ссылок:
Всех, кто по тем или иным причинам не может оставлять комментарии здесь, приглашаем в наш блог.
PipelineDB: работа с потоками данных
Ниже мы сравним PipelineDB с существующими решениями аналогичного плана, приведём краткую инструкцию по установке и первичной настройке, а также разберём практический пример.
Обработка данных в реальном времени: экскурс в историю
Принцип работы PipelineDB можно сформулировать так: «постоянные запросы, кратковременные данные». В реляционных СУБД всё обстоит ровно наоборот: «кратковременные запросы, постоянные данные. В PipelineDB данные не хранятся, а поступают в потоке; их обработка происходит «на лету», в движении.
Преимущества PipelineDB перед упомянутыми выше инструментами очевидны:
Рассмотрим, как в PipelineDB строится работа с потоками данных. Начнём с анализа двух важнейших понятий: «непрерывное представление» и «поток».
Потоки и непрерывные представления
«Поток» и «непрерывное представление» — главные абстракции PipelineDB.
Поток — это последовательность событий. Запись событий в поток осуществляется точно так же, как запись в таблицы в реляционных ДБ (подробнее об этом см. здесь ). Когда событие поступает в поток, к нему добавляется временная метка (timestamp).
Потоки в PipelineDB выполняют вспомогательную функцию, которая заключается в поставке данных для непрерывных представлений. В отличии от таблиц, для потоков не нужно создавать схемы. В поток можно записывать данные, пока он взаимодейстсвует хотя бы с одним непрерывным представлением.
Непрерывное представление (англ. continuous view) — это выборка из потоков и таблиц, обновляемая по мере поступления новых данных. В непрерывные представления попадают события, отбираемые по определённым параметрам.
Чтобы лучше понять, как работает PipelineDB, приведём несколько примеров непрерывных представлений.
Вот так, например, можно создать непрерывное представление для ежедневного подсчёта числа уникальных посетителей, приходящих на сайт по внешним ссылкам:
Ещё один пример — подсчёт числа показов рекламы на сайте за последние 5 минут:
Как видим, непрерывные представления имеют следующую форму:
При создании непрерывного представления по отношению к потокам выполняется операция SELECT, с помощью которой отбираются данные, соответствующие требуемым параметрам.
Основные теоретические сведения, необходимые для понимания принципов работы PipelineDB, мы изложили. Переходим к практической части. Сначала мы опишем процедуру установки и первичной настройки PipelineDB, а затем перейдём к практическим примерам.
Установка и первичная настройка
Чтобы установить PipelineDB, достаточно выполнить две команды:
После этого инициализируем сервер PipelineDB:
Основные настройки PipelineDB хранятся в файле pipelinedb.conf. Они почти не отличаются от соответствующих настроек PostgreSQL.
По умолчанию PipelineDB не может принимать соединения с удалённых хостов. Чтобы изменить эту настройку, откроем файл pipelinedb.conf, найдём в нём раздел Connections and Authentication, расскомментируем первую строку и отредактируем её следующим образом:
После этого пропишем конкретные хосты в файле pg_hba.conf:
Если нам нужно принимать соединения со всех возможных хостов, эта строка должна выглядеть так:
Вот и всё. PipelineDB готова к работе.
Чтобы запустить её в фоновом режиме, выполним следующую команду:
Практический пример: анализируем статистику Википедии
Мы разобрали необходимую теорию, а также описали процедуры установки и первичной настройки PipelineDB. Переходим к особенностям использования PipelineDB на практике.
Нас будут интересовать максимальное, минимальное и среднее количество обращений к странице в течение часа, а также 99-й перцентиль обращений.
Активируем выполнение непрерывных запросов:
После этого создадим непрерывное представление:
В приведённой команде указано, что мы будем получать данные для непрерывного представления из потока wiki_stream. Чтобы создать такой поток, нам потребуется загрузить с сайта данные, разархивировать, записать в стандартный вывод, а после этого передать PipelineDB с помощью команды COPY:
Отметим, что объём данных очень велик (они хранятся в виде архивов по 80-90 MБ каждый), и их загрузка может занять продолжительное время. Загрузку можно остановить в любой момент нажатием стандартной комбинации клавиш Ctrl+C.
По завершении загрузки выполним команду:
Результат будет представлен в виде таблицы (приводим лишь небольшой фрагмент):
Заключение
PipelineDB — интересный и перспективный продукт. Надеемся, что он будет успешно развиваться и в дальнейшем.
Если у вас есть опыт использования PipelineDB на практике — будем рады, если вы поделитесь опытом в комментариях.
Для желающих узнать больше приводим несколько полезных ссылок:
Google’s Certificate Transparency как источник данных для предотвращения атак
Мы подготовили перевод статьи Райана Сирса об обработке логов Google’s Certificate Transparency, состоящей из двух частей. В первой части дается общее представление о структуре логов и приводится пример кода на Python для парсинга записей из этих логов. Вторая часть посвящена получению всех сертификатов из доступных логов и настройке системы Google BigQuery для хранения и организации поиска по полученным данным.
С момента написания оригинала прошло уже три года и с тех пор количество доступных логов и, соответственно, записей в них возросло многократно. Тем более важно правильно подойти к обработке логов, если целью является максимизация количества получаемых данных.
Часть 1. Parsing Certificate Transparency Logs Like a Boss
Чтобы понять, с какими объемами данных придется иметь дело, давайте посмотрим, сколько записей содержится в каждом логе из списка с сайта CTL:
На выходе получаем:
285,037,607 на момент написания статьи. Это не такой большой объем данных, но все равно придется приложить определенные усилия, чтобы эффективно организовать хранение и поиск по сертификатам. Подробнее об этом во второй части.
Стоит отметить, что API выдает количество записей в логе, значительную часть которых составляют PreCerts (о них далее) и не представляют особого интереса. Также важно учитывать, что сертификаты могут дублироваться между разными логами, к примеру, данный сертификат присутствует одновременно в 6 различных логах, поддерживаемых Chrome. Таким образом, реальное число сертификатов значительно меньше, чем суммарное число записей в логах.
Тем не менее, на момент написания перевода, учитывая только логи, удовлетворяющие политике Google и включенные в Chrome, в списке присутствует 46 логов, содержащие в сумме 6,861,473,804 записей, что уже потребует значительных ресурсов для полной обработки.
Анатомия CTL
Получение записей из CTL осуществляется по HTTP, что позволит нам легко получать данные с помощью современных библиотек. К сожалению, сами данные в записях представляют собой запутанные бинарные структуры, что несколько усложняет процесс парсинга. Пример записи в логе:
Про PreCerts
Мне потребовалось довольно много времени, чтобы разобраться, что вообще такое PreCert (можете попробовать сами, почитайте RFC, и, по всей видимости, я такой не один. Сохраню вам кучу времени на раздумья и поиски в гугле и сформулирую назначение PreCerts следующим образом:
PreCerts это отдельный тип сертификата, выпускаемого CA до того, как тот выпустит “настоящий” сертификат. Фактически, это копия исходного сертификата, но содержащая специальное расширение x509 v3, называемое poison и отмеченное как критическое. Таким образом, сертификат не будет валидирован как платформами, распознающими это расширение, и знающими что это PreCert, так и платформами, которые это расширение не распознают.
Мой опыт в ИБ говорит о том, что такая мера не сильно эффективна, хотя бы потому, что баги при парсинге x509/ASN.1 встречаются довольно часто и отдельные реализации могут быть уязвимы к различным махинациям, которые в конечном счете позволят валидировать PreCert. Я понимаю, зачем это было сделано, но складывается ощущение, что полностью убрать PreCerts и оставлять в CTL только сертификаты, действительно выпущенные CA, было бы намного разумнее.
Парсим бинарные структуры
Как для человека, занимающегося реверс-инжинирингом и время от времени участвующего в разных CTF, задача парсинга бинарных структур для меня не нова. Большинство людей в таких случаях обращаются к модулю struct, но много лет назад, во время работы на Филлипа Мартина, он познакомил меня с отличной библиотекой Construct, которая заметно упрощает парсинг подобных структур. Ниже приведены структуры, которые я использовал для парсинга, а также пример их использования для обработки записей:
Получаем массив X509 сертификатов из цепочки с сертификатом из leaf_input в качестве первого элемента
Как можете заметить, Construct позволяет довольно легко определять бинарные структуры на Python.
Часть 2. Retrieving, Storing and Querying 250M+ Certificates Like a Boss
Сбор сертификатов
На момент написания перевода большинство логов Google (Argon, Xenon, Aviator, Icarus, Pilot, Rocketeer, Skydiver) предоставляют лишь по 32 записи для каждого запроса, но для ускорения получения записей можно одновременно отправлять несколько запросов на один и тот же лог, насколько позволяет пропускная способность, но работает такой подход не для всех логов.
Отдельные логи позволяют получать по 1024 и более записей за раз, но большинство CTL, помимо Google, выдает по 256 записей за один запрос.
Так как задача одновременно IO-bound (получение записей по http) и CPU-bound (парсинг сертификатов), для эффективной обработки необходимо будет подключить как асинхронность, так и многопроцессность.
Так как не было никаких инструментов, которые позволили бы легко и безболезненно получить и распарсить все CTL (помимо не особо примечательной утилиты от Google, было решено потратить немного времени и написать свой инструмент, который соответствовал бы всем нашим потребностям. Результатом стал Axeman, который использует asyncio и замечательную библиотеку aioprocessing для загрузки, парсинга и сохранения сертификатов в несколько CSV файлов, ограничиваясь при этом только скоростью интернет-соединения.
Эксплуатация облака
После получения инстанса (_прим. перев._ так в Google Cloud называются VM) c 16 ядрами, 32Гб памяти и SSD на 750Гб (спасибо Google за бесплатные 300$ на счете для новых аккаунтов!), я запустил Axeman, который загрузил все сертификаты меньше чем за сутки и сохранил результаты в /tmp/certificates/$CTL_DOMAIN/
Где хранить все эти данные?
На начальном этапе для осуществления хранения и поиска по данным был выбран Postgres, но, хотя я и не сомневаюсь, что с правильной схемой Postgres легко бы справился с 250 миллионами записей (в отличии от моей первой попытки, в которой на один запрос уходило примерно 20 минут!), я начал искать решения, которые:
позволяют дешево хранить большой объем данных
обеспечивают быстрый поиск
позволяют легко обновлять данные
Вариантов было несколько, но с точки зрения стоимости, почти все рассмотренные варианты (AWS RDS, Heroku Postgres, Google Cloud SQL) были весьма затратны. К счастью, так как наши данные в принципе никогда не изменяются, у нас появляется дополнительная гибкость в выборе платформы для размещения данных.
В целом, это как раз тот тип поиска по данным, который прекрасно ложится на модель map/reduce с использованием, к примеру, Spark или Hadoop Pig. Просматривая предложения различных провайдеров в категории “big data” (хотя в нашей задаче данных явно мало для включения в эту категорию), я наткнулся на Google BigQuery, который удовлетворяет всем обозначенным параметрам.
Скармливаем данные BigQuery
Загрузка данных в BigQuery осуществляется довольно легко, благодаря предоставляемой Google утилите gsutil. Создаем новый бакет для наших сертификатов:
И видим следующий результат в нашем бакете:
Далее создаем новый датасет в BigQuery:
Теперь мы можем импортировать данные из хранилища в наш новый датасет. К сожалению, в BigQuery нет кнопки “пожалуйста, импортируй все папки рекурсивно”, так что придется импортировать каждый CTL отдельно, но занимает это не так долго. Создаем таблицу и импортируем наш первый лог (обратите особое внимание на отмеченные настройки):
Так как схема нужна всякий раз при импорте очередного лога, воспользуемся опцией “Edit as Text”. Использованная схема:
Далее просто повторяем процесс для каждого лога. Убедитесь, что каждый импорт завершился успешно (ошибки обычно можно игнорировать, просто убедитесь, что вы задали адекватное значения для максимального количества ошибок). В итоге должен получиться примерно такой датасет:
Что в итоге получилось
Настало время пожинать плоды наших трудов и опробовать систему на различных запросах.
В последнее время часто говорят о доменах, использующих punycode и связанных с ними омоглифных атаках. Попробуем следующий запрос:
И всего через 15 секунд получаем результат со всеми punycode доменами из всех известных CTL!
Рассмотрим другой пример. Попробуем получить все сертификаты доменов Coinbase, записанные в Certificate Transparency:
Всего через две секунды получаем все интересующие нас результаты:
Небольшая загадка
Проводя исследования, я обнаружил нечто странное. Домен flowers-to-the-world.com постоянно возникал в различных логах. Практически каждый лог имел огромное число сертификатов, содержащих этот домен:
Whois позволяет определить, что этот домен принадлежит Google, так что мне интересно, не является ли это частью какой-то тестовой рутины. Если вы инженер Google, который может разузнать что-то у товарищей, занимающихся Certificate Transparency, было бы очень интересно услышать об этом.
Ответ инженера Google в комментариях под оригинальным постом
Ответ инженера Google в комментариях под оригинальным постом
Привет, Райан. Пишет Пол Хэдфилд из команды Certificate Transparency.
flowers-to-the-world.com действительно принадлежит Google. Мы используем этот домен чтобы генерировать сертификаты, которые затем добавляются в каждый CTL в рамках периодической проверки логов на соответствие стандартам RFC6962. Проверка проводится с целью удостоверится, что логи работают в соответствии со стандартами и имеют приемлемый аптайм.
Наблюдаемое распределение количества раз, которое домен встретился в каждом логе, является в основном функцией от того, сколько этот лог существует, но также зависит от того, насколько быстро лог может добавить новый сертификат в свое дерево Меркла.






