Привет, хабражители. Сегодня хочу поговорить про идентификацию, аутентификацию и авторизацию. В прошлом году я делал достаточно подробный ресерч по этой теме и хочу рассказать о разнице нескольких проектов, которые решают эти вопросы.
В качестве примера будет история про легаси проект. Все не любят легаси. Так бывает, что бросишь проект без присмотра и там люди такого наворотят, что ужас. Так и с одним проектом, который просто собирал данные с гитлаба и жиры для автоматизации своей работы, ведь любая аутсорс/аутстафф компания всегда пилит свою жиру.
Но история эта не про то, какие люди плохие или хорошие а просто про управленческие и технические решения, которые принялись командой при реинжиниринге проекта.
Что
Что не так было с проектом и почему мы вообще решили от него избавляться. Вот четыре всадника апокалипсиса в этом проекте.
Высокая стоимость поддержки. Мы как инженеры всегда стараемся держать минимальный time-to-market, при этом, чтобы стоимость поддержки была минимальной. Но тут что-то пошло не так из-за недостатка технического контроля
Плохая инженерная культура. Тесты не писались, куча костылей и сомнительный способ выбора технологий под меняющиеся требования. Изначально стек был выбран в виде Django+Celery с кучей примочек для асинхронности (сюда бы Go залетел бы со своей асинхронной моделью, но проект не того уровня, к сожалению)
Очень много велосипедов и самописных решений. Я не знаю, как в 2022м году можно стартуя новый проект делать что-то своё, не пользуясь опенсорс решениями или готовыми сервисами, типа Ory, Auth0, Firebase и подобными.
Было все плохо с безопасностью и с политиками разработки. Бекапы передавались для локальной разработки по-старинке, учитывая что это были данные с прода. Передавать дампы с прода - такое себе, если честно
Как
Мы делали проект не для рынка РФ и поэтому мы могли выбрать любой хостинг, какой посчитаем нужным. Решили остановиться на AWS (ведь все сейчас сидят на нём, верно?) Разработку начали с создания документа, где описали все проблемы текстом, варианты решений и заложили сразу несколько принципов
Инженерная культура должна оставаться на хорошем уровне. Мы пишем тесты, идем к самодокументирующемуся коду, документируем решения прямо в коде комментариями (это иногда спасает кучу нервов), делаем код максимально читаемым и понимаемым для человека, чтобы было понятно ПОЧЕМУ, а не как
Стараемся использовать как можно больше от AWS и мы были готовы к вендор локу. Можно запустить базу внутри k8s кластера, но зачем? Денег не сэкономишь, а нужен будет еще админ для всего этого
ISO 27001 compliant наложил ряд ограничений по задокументированной информации и мы решили документацию для разработчиков хранить в папочке doc в корне репозитория. Практика показала, что так просто удобнее. Мы пробовали gitbook, confluence и еще много разных форматов, но всё-таки на gitlab вместе с его поддержкой в Markdown и sequentional diagrams и всего остального вышло хорошо
Modern application framework дал нам ��орошие вопросы для установки границ
What are your business priorities?
What is the worst possible scenario?
What are your immovable constraints?
What data is this solution storing/processing?
What skills does your team have?
What is the timeline for the project?
Что выбирали и как
Выбирали мы между Okta, Auth0, Keycloak и Ory после небольшого ресерча. Требования мы выставили следующие:
Простота в интеграции, хорошее API и хорошая документация. Чистый код, желательно нашего стека (Python+Go)
Возможность управлять учетными данными самим и желательно, чтобы было self-hosted решение, но если будет достаточно безопасно, то можно и рассмотреть вариант интеграции
Достаточно легковесно и нересурсоемко
Подходы API First, Documentation first в разработке у команды, идеально если OpenSource
Auth0 - Из плюсов у них есть Single Sign On, у них API First подход, можно интегрировать с чем угодно достаточно просто, используя их API, но ценник кусался за $23 доллара за месяц за 10к MAU и при этом не получится
Keycloack - из плюсов - это достаточно хорошее enterprise level решение для IAM, оно опенсорсное, но мы не взяли его потому что были проблемы с infinispan и он написан на Java. Для банков с поддержкой вполне себе пойдет, но для нас не очень
Okta - хороший продукт для энтерпрайза, но для маленького проекта это было не очень удобно для нас, потому что не было self-hosted решений и это наложило бы на нас сразу небольшой vendor-lock.
Ory (Ory Kratos для идентификации и Ory Keto для пермишнов) мне полюбились, у них хорошая инженерная культура, мейнтейнеры рядом с сообществом, достаточно активная поддержка в гитхабе и слаке, иногда бывают комьюнити митапы и код написан на Go, при чём достаточно хорошо, после беглого ревью кода.
Интеграция в проект
Мы делали проект на Flask и интеграция Ory Kratos и Ory Keto сводится к тому, что мы добавляем их в docker-compose.yml , пользуемся документацией Ory Keto и Ory Kratos, пишем немного кода на Python и получается примерно следующий код (простой для примера)
"""Public section, including homepage and signup."""
import requests
from flask import Blueprint, render_template, session, redirect, request, abort
from config import settings
blueprint = Blueprint("public", __name__, static_folder="../static")
HTTP_STATUS_FORBIDDEN = 403
@blueprint.route("/", methods=["GET", "POST"])
def home():
"""Home page."""
if 'ory_kratos_session' not in request.cookies:
return redirect(settings.KRATOS_UI_URL)
response = requests.get(
f"{settings.KRATOS_EXTERNAL_API_URL}/sessions/whoami",
cookies=request.cookies
)
active = response.json().get('active')
if not active:
abort(HTTP_STATUS_FORBIDDEN)
email = response.json().get('identity', {}).get('traits', {}).get('email').replace('@', '')
# Check permissions
response = requests.get(
f"{settings.KETO_API_READ_URL}/check",
params={
"namespace": "app",
"object": "homepage",
"relation": "read",
"subject_id": email,
}
)
if not response.json().get("allowed"):
abort(HTTP_STATUS_FORBIDDEN)
return render_template("public/home.html")И всё работает. Весь проект можно посмотреть у меня на гитхабе.
А что используете вы, чтобы идентифицировать пользователей?
