Коды ошибок
Общие коды ошибок для официально поддерживаемых DAT клиентских библиотек.
Каждому коду присвоены два значения — влияние и повтор, а некоторым дополнительно ставится метка подозрение.
Влияние — урон для сервиса
Это критерий для алертов. Смотрим только на одно: «сервис сейчас стоит или нет».
| Влияние | Значение | Пример |
|---|---|---|
| Критично | Сервис или отдельная функция останавливается. Выдача невозможна, синхронизация окончательно провалена, инициализация не прошла | На сервере выдачи нет ни одного пригодного сертификата |
| Частично | Часть запросов или циклов падает, но сервис продолжает работать. Обычно восстанавливается сам | Один цикл CMS провалился. Работа продолжается на прежних сертификатах |
| Без влияния | Один запрос отклонён — и на этом всё | Пришёл подделанный токен. Отфильтровали и забыли |
Без влияния — не повод для алерта. Если каждый неверный ввод обязана проверять вся дежурная смена, алерты теряют смысл.
Подозрение — расследуйте, если повторяется
Коды с меткой Подозрение в единичном случае являются частью нормальной эксплуатации. Клиент в любой момент может прислать неверное значение, и отфильтровать его — прямая обязанность библиотеки.
Но если такие ошибки идут постоянно или лавиной из одного источника, причина одна из двух.
- Ошибка конфигурации — неверный деплой, остался клиент старой версии, сертификаты разошлись.
- Попытка взлома — подмена токена или ключа ради прохождения проверки, либо перебор в поисках валидного значения.
Поэтому такие коды правильно вести как метрику по количеству. Оповещать имеет смысл только при превышении порога.
Повтор
| Повтор | Значение |
|---|---|
| Временно | Повтор после backoff решает проблему |
| Постоянно | Повторять запрещено. Нужно исправить конфигурацию или ввод |
| Состояние | Это сигнал, а не ошибка |
Токен
Проблемы самой строки полученного токена.
DAT_TOKEN_MALFORMED Частей, разделённых точкой, не пять; либо expire не чисто десятичное; либо cid не чисто шестнадцатеричное; либо plain или secure не base64url; либо числовое поле вышло за диапазон целого.
arrow_forwardОтклонить запрос
DAT_TOKEN_EXPIREDexpire <= now. Ровно в срок — уже истёк: при expire == now токен считается просроченным.
arrow_forwardИнициировать перевыпуск токена
DAT_TOKEN_UNKNOWNОшибка токена, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Истечение и ошибка формата — обязательно разные вещи
Реакции прямо противоположны: истечение — это нормальное завершение срока жизни, достаточно обновить токен; ошибка формата означает, что токен изначально не наш, и его нужно отклонить.
Разбор сначала фиксирует структуру, и только потом смотрит значения. Строка вроде "1.2.3" с нехваткой частей — это не просроченный токен, а вообще не токен, поэтому DAT_TOKEN_MALFORMED.
Знак в поле expire, например +100, — тоже ошибка формата, а не истечение. Допускаются только чистые ASCII-цифры.
Сертификат
Проблемы формата строки сертификата и того, можно ли использовать этот сертификат прямо сейчас.
DAT_CERT_MALFORMED Частей, разделённых точкой, не восемь; либо не удалось разобрать cid, start, duration, ttl; либо поле ключа не base64url; либо start + duration + ttl вышло за u64.
arrow_forwardПереразвернуть сертификат
DAT_CERT_EXPIREDstart + duration + ttl < now. Полностью истёкшее состояние: невозможны ни выдача, ни проверка.
arrow_forwardОбновить сертификат
DAT_CERT_NOT_YET_ISSUABLEnow < start. Окно выдачи ещё не открылось.
arrow_forwardПодождать
DAT_CERT_ISSUANCE_ENDEDnow > start + duration, но ttl ещё остался. Выдача невозможна, доступна только проверка.
arrow_forwardРазвернуть новый сертификат
DAT_CERT_VERIFY_ONLYСертификат содержит только открытый ключ, без приватного ключа подписи. Проверка работает, выдача невозможна.
arrow_forwardПроверить настройки деплоя
DAT_CERT_NOT_FOUND Сертификата, соответствующего cid из токена, нет в наличии. Это подделанный токен либо неверный деплой.
arrow_forwardОтклонить запрос
DAT_CERT_NOT_SYNCED Этот cid ещё не получен из CMS. Возникает ненадолго сразу после развёртывания нового сертификата.
arrow_forwardПовторить после синхронизации
DAT_CERT_DUPLICATE_CID В импортируемом списке один и тот же cid встречается дважды или более.
arrow_forwardПроверить ответ сервера
DAT_CERT_UNKNOWNОшибка сертификата, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
DAT_CERT_NOT_FOUND и DAT_CERT_NOT_SYNCED внешне выглядят одинаково, но реакции разные. В первом случае это cid, который мы никогда не выпускали, — ожидание не поможет; во втором достаточно дождаться синхронизации.
Единичный DAT_CERT_NOT_FOUND достаточно просто отфильтровать, но резкий рост означает, что деплой разошёлся либо ходят поддельные токены.
Подпись
DAT_SIG_MISMATCHПроверка подписи завершилась несовпадением. Значение HMAC отличается либо ECDSA verify вернул false.
arrow_forwardЗаблокировать сессию, записать в security-лог
DAT_SIG_MALFORMED Часть с подписью пуста; либо не base64url; либо длина ECDSA r‖s не соответствует кривой; либо не удалось преобразование в DER.
arrow_forwardОтклонить запрос
DAT_SIG_KEY_MISSINGПопытка подписать ключом verify-only. В рантайме приватного ключа нет.
arrow_forwardПроверить настройки сервера выдачи
DAT_SIG_BACKENDСама операция подписи или проверки не смогла выполниться. Неверный тип ключа, освобождённый handle, внутренняя ошибка криптобиблиотеки.
arrow_forwardПроверить тип ключа и библиотеку
DAT_SIG_UNKNOWNОшибка подписи, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Не смешивайте несовпадение и отказ бэкенда
У этих двух кодов оси прямо противоположны.
DAT_SIG_MISMATCH— пришедшая подпись просто не совпала, поэтому влияния на сервис нет, зато при повторении это повод для подозрения.DAT_SIG_BACKEND— сама операция проверки не отработала, то есть это наша проблема, и к подозрениям она не относится.
Если сообщать о неверном типе ключа или баге библиотеки как о «несовпадении подписи», то ситуация со сломанным собственным кодом попадёт в метрики атак. И наоборот: если настоящая подделка классифицируется как ошибка бэкенда, она целиком выпадет из метрик подозрений.
Шифрование
Проблемы шифрования и расшифровки полезной нагрузки secure.
DAT_CRYPTO_TAG_MISMATCHТег аутентификации AES-GCM не совпадает. Либо secure был изменён, либо ключ сертификата другой.
arrow_forwardЗаблокировать сессию, записать в security-лог
DAT_CRYPTO_DATA_INVALID Шифротекст не пуст, но короче или равен IV (12 байт); либо вход превысил предел реализации (INT_MAX и т. п.).
arrow_forwardОтклонить запрос
DAT_CRYPTO_BACKENDОперация шифрования или расшифровки не смогла выполниться. Платформа без поддержки GCM либо сбой инициализации контекста.
arrow_forwardПроверить поддержку платформы
DAT_CRYPTO_UNKNOWNОшибка шифрования или расшифровки, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Пустая полезная нагрузка secure не является ошибкой. Пустой вход даёт пустой выход и не порождает никакого кода.
На пути, где проверка подписи пропускается, тег GCM — единственная проверка целостности. Поэтому DAT_CRYPTO_TAG_MISMATCH не объединяется одним кодом с остальными сбоями расшифровки.
Ключ
DAT_KEY_INVALID Длина ключа не соответствует заявленному алгоритму (HMAC 32/48/64, AES 16/32); либо точка не лежит на кривой; либо d ∉ [1,n-1]; либо формат не несжатый (0x04); либо приватный и открытый ключи не являются парой.
arrow_forwardЗаменить ключ
DAT_KEY_VERIFY_ONLY_UNSUPPORTEDЗапрошен экспорт verify-only для семейства HMAC.
arrow_forwardСменить алгоритм
DAT_KEY_UNKNOWNОшибка ключа, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Три похожих, но разных случая:
| Код | Значение |
|---|---|
DAT_KEY_VERIFY_ONLY_UNSUPPORTED | Структурное ограничение алгоритма. HMAC симметричен, понятия открытого ключа у него нет |
DAT_SIG_KEY_MISSING | Состояние в рантайме. В этом ключе прямо сейчас нет приватной части |
DAT_CERT_VERIFY_ONLY | Форма развёртывания. Этот сертификат развёрнут только для проверки |
Менеджер
Состояние объекта, который хранит сертификаты и использует их для выдачи и проверки.
DAT_MANAGER_NO_CERTIFICATEНет ни одного сертификата. Либо импорт ещё не выполнялся, либо первая синхронизация с CMS не удалась.
arrow_forwardПроверить подключение к CMS
DAT_MANAGER_NO_ISSUABLE_CERTIFICATEСертификаты есть, но ни один из них сейчас не пригоден для выдачи. Причина передаётся вместе с ошибкой.
arrow_forwardРешать по причине (cause) — таблица ниже
DAT_MANAGER_DISPOSEDИспользован уже освобождённый менеджер или сертификат.
arrow_forwardИсправить вызывающий код
DAT_MANAGER_UNKNOWNОшибка менеджера, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Причина (cause) у DAT_MANAGER_NO_ISSUABLE_CERTIFICATE — одна из четырёх. Для каждой причины нужны совершенно разные действия.
| Причина | Значение | Повтор | Что делать |
|---|---|---|---|
DAT_CERT_NOT_YET_ISSUABLE | До начала окна выдачи | Временно | Разрешится само, если подождать |
DAT_CERT_ISSUANCE_ENDED | Окно выдачи закрыто, доступна только проверка | Постоянно | Нужно развернуть новый сертификат |
DAT_CERT_EXPIRED | Все имеющиеся истекли | Постоянно | Нужно обновить сертификаты |
DAT_CERT_VERIFY_ONLY | Все имеющиеся — только для проверки | Постоянно | Ошибка настроек деплоя |
Если сервер выдачи настроен получать только сертификаты для проверки, будет DAT_CERT_VERIFY_ONLY. Ожидание не поможет никогда, поэтому повторять не нужно.
Конфигурация
Проблемы значений, переданных вызывающей стороной. Все коды семейства CONFIG — ошибки, требующие правки кода; если они возникают в проде, значит деплой сделан неверно.
DAT_CONFIG_ALG_UNSUPPORTED Неизвестное имя алгоритма. Должно точно совпадать с записью в формате протокола (ECDSA-P256, IV-AES256-GCM).
arrow_forwardПроверить имя алгоритма
DAT_CONFIG_ARGUMENT_INVALID Обязательный аргумент равен null; либо вне допустимого диапазона (отрицательное время, interval <= 0); либо неподдерживаемый тип (в языках с динамической типизацией в payload передано число или булево); либо подписываемое тело пусто.
arrow_forwardИсправить вызывающий код
DAT_CONFIG_URI_INVALIDURI сервера CMS не соответствует спецификации: не разбирается, схема не http/https, либо присутствуют путь или query.
arrow_forwardИсправить URI
DAT_CONFIG_UNKNOWNОшибка конфигурации, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Внутренние
Проблемы среды исполнения и рантайма.
DAT_INTERNAL_UNAVAILABLE Криптографического бэкенда или API рантайма нет вовсе. Отсутствует crypto.subtle, платформа без поддержки AES-GCM, версия рантайма ниже требуемой.
arrow_forwardПроверить деплой и платформу
DAT_INTERNAL_UNKNOWNСбой выделения памяти, сбой генерации случайных чисел, сбой захвата блокировки, попадание в ветку, спроектированную как недостижимая.
arrow_forwardПроверить логи
DAT_INTERNAL_UNAVAILABLE решается исправлением среды развёртывания, а DAT_INTERNAL_UNKNOWN — обычно сбой рантайма либо баг библиотеки.
Синхронизация CMS
Если синхронизация CMS не используется, эти коды не появляются.
DAT_CMS_UNREACHABLEСбой DNS, отказ в соединении, сбой TLS, таймаут. Таймаут не имеет отдельного кода и включён сюда — потому что реакция та же самая.
arrow_forwardПовторить после backoff
DAT_CMS_UNAUTHORIZEDСервер ответил 401. Токена нет либо он неверный.
arrow_forwardПроверить настройку токена
DAT_CMS_FORBIDDENСервер ответил 403. Токен валиден, но прав на этот эндпоинт нет.
arrow_forwardПроверить уровень токена
DAT_CMS_ENDPOINT_NOT_FOUNDСервер ответил 404. URL неверный.
arrow_forwardПроверить настройку URL
DAT_CMS_SERVER_ERRORСервер ответил 5xx.
arrow_forwardПовторить после backoff
DAT_CMS_HTTP_STATUSОтвет не 2xx и не подходит ни под один из случаев выше.
arrow_forwardПроверить код состояния
DAT_CMS_MALFORMEDВ ответе нет строки версии; либо строка версии не чисто десятичная; либо она вышла за диапазон.
arrow_forwardПроверить версию сервера
DAT_CMS_IMPORT_FAILED Ответ получен, но применить сертификаты не удалось. Причина содержится в cause.
arrow_forwardПроверить CERT_* / KEY_* в cause
DAT_CMS_VERSION_RESETСервер вернул версию более раннюю, чем наша. Это указание на полную повторную синхронизацию.
arrow_forwardОбрабатывается автоматически
DAT_CMS_NOT_SYNCEDСостояние, в котором синхронизация ещё ни разу не прошла успешно.
arrow_forwardДождаться первой синхронизации
DAT_CMS_SYNC_IN_PROGRESSПредыдущая синхронизация ещё выполняется, поэтому текущий цикл пропущен. Это не ошибка.
DAT_CMS_NOT_SUPPORTEDФункциональность CMS не включена в сборку. Не активирован feature либо не подключён CURL.
arrow_forwardПроверить опции сборки
DAT_CMS_UNKNOWNОшибка CMS, не попавшая ни в одну из категорий выше.
arrow_forwardПроверить логи
Коды, при которых синхронизация признаётся окончательно провалившейся (UNAUTHORIZED, FORBIDDEN, ENDPOINT_NOT_FOUND, MALFORMED, IMPORT_FAILED), все критичны. Повтор их не решает, а сертификаты продолжают истекать, поэтому без вмешательства сервис неизбежно остановится.
Напротив, UNREACHABLE и SERVER_ERROR — частичные. Работа продолжается на прежних сертификатах, и в следующем цикле всё восстанавливается само. Но при непрерывных сбоях это в итоге переходит в критичное. Настраивайте алерт по числу подряд идущих неудач.
Сбой синхронизации не выбрасывается исключением
Даже если первая синхронизация провалилась, менеджер возвращается штатно — потому что лучше синхронизироваться позже, чем никогда. Вместо этого сбой остаётся доступным для запроса состоянием.
| Клиент | Как получить |
|---|---|
| Rust | manager.last_error().await |
| Go | manager.LastError() |
| JavaScript | manager.lastError() |
| Python | manager.last_error() |
| Ruby | manager.last_error |
| Java/Kotlin | manager.lastError |
| C# | manager.LastError |
| C/C++ | dat_cms_manager_last_error(m) |
Если успеха не было ни разу — DAT_CMS_NOT_SYNCED, при нормальной работе — пусто.
Сервер
Коды, которые выдаёт сервер CMS. Клиент эти коды не создаёт, а только принимает.
DAT_AUTH_UNAUTHORIZED Отсутствует заголовок Authorization, либо токен не зарегистрирован ни на одном уровне.
DAT_AUTH_FORBIDDENТокен зарегистрирован, но его уровень не соответствует требуемому для этого эндпоинта.
DAT_AUTH_DISABLEDНе настроен ни один токен, поэтому аутентификация отключена целиком. Открытым без аутентификации оказывается даже API выдачи сертификатов. В ответах не появляется, пишется только в лог запуска.
arrow_forwardНемедленно настроить токен
DAT_REQ_MALFORMEDНе удаётся разобрать параметры пути или query, либо аргумент вне допустимого диапазона (отрицательный delay, срок более 10 лет и т. п.).
DAT_REQ_ALG_UNSUPPORTEDИмя алгоритма в пути запроса неизвестно.
DAT_REQ_NOT_FOUNDТакого маршрута нет либо метод не тот.
DAT_REQ_TOO_LARGEПревышен размер тела запроса.
DAT_REQ_UNKNOWNОшибка запроса, не попавшая ни в одну из категорий выше.
DAT_STORE_UNAVAILABLEОбрыв соединения с БД, исчерпание пула соединений, конкуренция за блокировку, таймаут. Единственный код, использующий 503 — это сигнал, по которому клиент понимает: «здесь достаточно подождать».
arrow_forwardПовторить после backoff
DAT_STORE_UNKNOWNСбой чтения или записи, отсутствие таблицы, несоответствие схемы, повреждение сохранённой строки сертификата.
arrow_forwardПроверить состояние БД
Конверт ответа:
{
"code": "DAT_REQ_ALG_UNSUPPORTED",
"details": { "algorithm": "BOGUS-ALG" }
}Ошибки, возникающие при создании и обработке сертификатов, сервер отдаёт теми же общими кодами, что описаны выше (DAT_CERT_*, DAT_KEY_*, DAT_CONFIG_*).
Когда приходит код сервера
Клиент оборачивает код сервера в собственный код CMS, а оригинал сохраняет в cause.
| Что получено | HTTP | Код, который выдаёт клиент |
|---|---|---|
DAT_AUTH_UNAUTHORIZED | 401 | DAT_CMS_UNAUTHORIZED |
DAT_AUTH_FORBIDDEN | 403 | DAT_CMS_FORBIDDEN |
DAT_REQ_NOT_FOUND | 404 | DAT_CMS_ENDPOINT_NOT_FOUND |
DAT_REQ_* (остальные) | 400·405·413 | DAT_CMS_HTTP_STATUS |
DAT_STORE_UNAVAILABLE | 503 | DAT_CMS_SERVER_ERROR |
DAT_STORE_UNKNOWN | 500 | DAT_CMS_SERVER_ERROR |
| (понижение версии) | 200 | DAT_CMS_VERSION_RESET |
Поиск по симптомам
| Симптом | Код |
|---|---|
| Сразу после входа работает, а через некоторое время отказ | DAT_TOKEN_EXPIRED — срок жизни токена истёк. Достаточно перевыпустить |
| Проверка падает только на отдельных серверах | DAT_CERT_NOT_SYNCED — этот сервер ещё не получил новый CID |
| Один и тот же токен отвергают все серверы | DAT_CERT_NOT_FOUND — это CID, который мы никогда не выпускали |
| Сервер выдачи не может создать токен | DAT_MANAGER_NO_ISSUABLE_CERTIFICATE + DAT_CERT_VERIFY_ONLY — развёрнут вариант verify-only |
| Выдача падает только сразу после запуска | DAT_MANAGER_NO_CERTIFICATE — это до первой синхронизации. Скоро разрешится |
| Синхронизация CMS постоянно падает | DAT_CMS_UNAUTHORIZED — токен неверный. Повторы не помогут |
| Не приходит ни одного сертификата | DAT_CMS_ENDPOINT_NOT_FOUND — опечатка в URL |
| Падает только на конкретной платформе | DAT_INTERNAL_UNAVAILABLE — нет криптографического бэкенда |
| Резко выросло число неудачных проверок | DAT_SIG_MISMATCH — единичный случай безвреден, но лавина означает попытку подделки |
| Расшифровка secure внезапно перестала работать | DAT_CRYPTO_TAG_MISMATCH — разошлись сертификаты либо попытка подмены |
| Предупреждение в логе запуска CMS | DAT_AUTH_DISABLED — аутентификация выключена. API выдачи открыт |
Приложение
Синтаксис кода
DAT_<область>_<причина>- Если одна и та же причина возникает в разных областях, имя причины совпадает.
DAT_TOKEN_MALFORMEDиDAT_CERT_MALFORMEDотличаются только объектом, смысл у них один. _UNKNOWN— только запасной вариант для своей области. Он не используется в значении «неизвестный алгоритм» (для этого есть_UNSUPPORTED).- Строка кода — это публичный контракт. Сообщение можно менять свободно, код — нет.
| Категория | Префикс кода |
|---|---|
| Токен | DAT_TOKEN_ |
| Сертификат | DAT_CERT_ |
| Подпись | DAT_SIG_ |
| Шифрование | DAT_CRYPTO_ |
| Ключ | DAT_KEY_ |
| Менеджер | DAT_MANAGER_ |
| Конфигурация | DAT_CONFIG_ |
| Внутренние | DAT_INTERNAL_ |
| Синхронизация CMS | DAT_CMS_ |
| Сервер | DAT_AUTH_ · DAT_REQ_ · DAT_STORE_ |
Доступ по клиентам
| Клиент | Тип ошибки | Код | Класс повтора | Событие безопасности |
|---|---|---|---|---|
| Rust | DatError enum | err.code() | err.retry() | err.security_event() |
| Go | *dat.Error | err.Code | dat.Retry(err) | dat.SecurityEvent(err) |
| JavaScript | DatError extends Error | e.code | e.retry | e.securityEvent |
| Python | DatError(ValueError, RuntimeError) | e.code | e.retry | e.security_event |
| Ruby | Saro::Dat::Error | e.code | e.retry | e.security_event? |
| Java/Kotlin | DatException | e.code | e.retry | e.securityEvent |
| C# | DatException | e.Code | e.Retry | e.SecurityEvent |
| C/C++ | dat_error_t | dat_error_code(e) | dat_error_retry(e) | dat_error_is_security_event(e) |
| Сервер CMS | JSON-конверт | поле code | — | — |
Событие безопасности возвращает true только для двух кодов, где подделка или подмена установлены точно (DAT_SIG_MISMATCH, DAT_CRYPTO_TAG_MISMATCH). Метка подозрение в этом документе охватывает более широкий круг (включая подделанные токены, ключи и запросы) и пока является лишь документной классификацией, не выведенной в API клиентов.
Класс влияния — тоже документная классификация. Один и тот же код бьёт по-разному в зависимости от места возникновения: например, DAT_KEY_INVALID не влияет ни на что при фильтрации входящего токена, но при чтении сертификата во время синхронизации CMS обрушивает всю синхронизацию.
Первопричина не теряется. DAT_MANAGER_NO_ISSUABLE_CERTIFICATE и DAT_CMS_IMPORT_FAILED передают причину через цепочку исключений соответствующего языка (cause / __cause__ / InnerException / Unwrap()).
В C/C++ сохраняются и числовые значения
Прежние числовые значения dat_error_t оставлены ради совместимости ABI, но эталоном является строковый код. Библиотека больше не возвращает старые значения, поэтому сравнение вида err == DAT_ERROR_INVALID_DAT не сработает. Сверяйтесь через dat_error_code(e).
В C нет цепочек исключений, поэтому причина запрашивается отдельно через dat_manager_issuable_cause().