Как Google проверяет права доступа у миллиардов пользователей и при чём тут SpiceDB
Когда проект вырастает из простой схемы с ролями admin и user, начинается хаос. В микросервисной архитектуре проверка прав часто превращается в запутаную паутину. Один сервис хранит роли в базе, другой проверяет JWT-токены, третий гоняет тяжелые SQL-запросы с десятком JOIN. В OWASP с 2021 года называют сбои разграничения доступа (Broken Access Control) главной угрозой безопасности веб-приложений.
В Google столкнулись с этой проблемой много лет назад. Для Google Drive, YouTube и Cloud IAM компания разработала единую централизованную систему авторизации Zanzibar. В 2019 году инженеры выложили документ с описанием её архитектуры, а команда Authzed взяла эту идею и создала SpiceDB — открытую базу данных для управления правами доступа.
Зачем выносить авторизацию в отдельную базу
Обычные базы данных хорошо хранят бизнес-сущности, но плохо справляются со сложными графами прав. Представьте документ, лежащий в папке, которая находится в другой папке, расшаренной на группу пользователей, куда входит отдельный отдел компании. Вычислить, имеет ли конкретный сотрудник доступ к файлу, средствами обычной СУБД становится больно и долго.
SpiceDB берет эту задачу на себя. Вы отправляете в базу простой запрос: «Может ли пользователь X выполнить действие Y над ресурсом Z?». В ответ приходит быстрый бинарный ответ.
При этом SpiceDB занимается только авторизацией (права доступа) и ничего не знает про аутентификацию (проверку личности). Проверять пароли, логинить пользователей и выдавать токены по-прежнему должен ваш identity provider вроде Keycloak или Auth0.
Как устроен язык схем и связей
Работа с SpiceDB начинается с описания схемы. Схема определяет типы объектов и правила, по которым вычисляются разрешения.
Синтаксис схемы выглядит читаемо и лаконично:
definition user {}
definition folder {
relation parent: folder
relation viewer: user
permission view = viewer + parent->view
}
definition document {
relation folder: folder
relation viewer: user
permission view = viewer + folder->view
}
В этом примере доступ view к документу автоматически получают пользователи, записанные напрямую в viewer, а также те, кто имеет право view на родительскую папку. Цепочка вложенности может быть любой глубины.
Сами данные хранятся в виде отношений (relationships). Это простые факты о системе, например:
folder:finance— объект типа папка с IDfinanceviewer— отношениеuser:mikhail— субъект
Запись такой связи означает, что Михаил стал читателем папки finance.
ReBAC и атрибуты: опыт Netflix
В отличие от классического RBAC (контроль на основе ролей), SpiceDB реализует ReBAC (Relationship-Based Access Control). Доступ определяется через связи между объектами в графе.
Но иногда бизнесу мало просто знать, что пользователь входит в команду. Нужно проверить контекстное условие: например, что человек заходит с корпоративного IP-адреса или запрос отправлен в рабочее время.
Для таких сценариев инженеры Netflix помогли добавить в SpiceDB механизм caveats (оговорки). Это сочетание ReBAC и ABAC (Attribute-Based Access Control). К связи добавляется контекстная функция, которая рассчитывается в момент проверки прав.
Архитектура и работа под нагрузкой
SpiceDB написана на Go и рассчитана на высокие нагрузки. Авторы заявляют о задержке в 5 мс на уровне p95 при миллионах запросов в секунду и миллиардах связей в базе.
В качестве хранилища (datastores) можно подключить привычные СУБД:
- PostgreSQL
- CockroachDB
- MySQL (драйвер для MySQL написала команда авторизации GitHub)
- Google Cloud Spanner
Одна из интересных фич — управление консистентностью на уровне отдельного запроса. Если пользователь только что изменил права доступа и хочет сразу увидеть результат, приложение отправляет запрос с требованием fully consistent данных. Если же мы отрисовываем публичный каталог, где задержка в пару секунд не критична, разрешаем кэширование и снижаем нагрузку на базу.
SpiceDB также умеет отвечать на «обратные» вопросы: «К каким ресурсам у пользователя есть доступ?» или «Кто может просматривать этот документ?». Для этого внутри используются обратные индексы (reverse indexes).
Быстрый старт с Docker и curl
Поднять SpiceDB для экспериментов можно одной командой в Docker:
docker run --rm -p 50051:50051 -p 8443:8443 \
authzed/spicedb serve \
--http-enabled true \
--grpc-preshared-key "somerandomkeyhere"
После запуска загрузим схему через HTTP API:
curl --location 'http://localhost:8443/v1/schema/write' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"schema": "definition user {} \n definition folder { \n relation viewer: user \n permission view = viewer \n }"
}'
Добавим связь, что пользователь anne может просматривать папку budget:
curl --location 'http://localhost:8443/v1/relationships/write' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"updates": [
{
"operation": "OPERATION_TOUCH",
"relationship": {
"resource": { "objectType": "folder", "objectId": "budget" },
"relation": "viewer",
"subject": { "object": { "objectType": "user", "objectId": "anne" } }
}
}
]
}'
Теперь проверим права:
curl --location 'http://localhost:8443/v1/permissions/check' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer somerandomkeyhere' \
--data '{
"resource": { "objectType": "folder", "objectId": "budget" },
"permission": "view",
"subject": { "object": { "objectType": "user", "objectId": "anne" } }
}'
В ответ получим статус PERMISSIONSHIP_HAS_PERMISSION.
Кроме REST и gRPC API разработчики предлагают консольную утилиту zed и браузерную песочницу Playground (play.authzed.com). В ней удобно набросать модель прав, заполнить её тестовыми данными и проверить гипотезы до написания кода.
Кому пригодится этот инструмент
SpiceDB уже крутится в продакшене у Red Hat, IBM, GitPod и Tubi.
Внедрять такую систему в небольшой монолит, где все права ограничиваются админкой и парой ролей, смысла мало — это лишнее усложнение инфраструктуры. Зато инструмент отлично подходит, когда:
- У вас десяток микросервисов, и каждый пытается по-своему проверять права.
- Продуктовая логика требует шеринга файлов, сложных иерархий папок или командных аккаунтов.
- Требуется аудит безопасности и единая точка управления доступом.
Для разворачивания в Kubernetes у Authzed есть официальный оператор. Проект активно развивается, а в репозитории на GitHub уже почти 7000 звёзд.