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

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

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


Что

Что не так было с проектом и почему мы вообще решили от него избавляться. Вот четыре всадника апокалипсиса в этом проекте.

  • Высокая стоимость поддержки. Мы как инженеры всегда стараемся держать минимальный time-to-market, при этом, чтобы стоимость поддержки была минимальной. Но тут что-то пошло не так из-за недостатка технического контроля

  • Плохая инженерная культура. Тесты не писались, куча костылей и сомнительный способ выбора технологий под меняющиеся требования. Изначально стек был выбран в виде Django+Celery с кучей примочек для асинхронности (сюда бы Go залетел бы со своей асинхронной моделью, но проект не того уровня, к сожалению)

  • Очень много велосипедов и самописных решений. Я не знаю, как в 2022м году можно стартуя новый проект делать что-то своё, не пользуясь опенсорс решениями или готовыми сервисами, типа Ory, Auth0, Firebase и подобными.

  • Было все плохо с безопасностью и с политиками разработки. Бекапы передавались для локальной разработки по-старинке, учитывая что это были данные с прода. Передавать дампы с прода - такое себе, если честно

Как

Мы делали проект не для рынка РФ и поэтому мы могли выбрать любой хостинг, какой посчитаем нужным. Решили остановиться на AWS (ведь все сейчас сидят на нём, верно?) Разработку начали с создания документа, где описали все проблемы текстом, варианты решений и заложили сразу несколько принципов

  1. Инженерная культура должна оставаться на хорошем уровне. Мы пишем тесты, идем к самодокументирующемуся коду, документируем решения прямо в коде комментариями (это иногда спасает кучу нервов), делаем код максимально читаемым и понимаемым для человека, чтобы было понятно ПОЧЕМУ, а не как

  2. Стараемся использовать как можно больше от AWS и мы были готовы к вендор локу. Можно запустить базу внутри k8s кластера, но зачем? Денег не сэкономишь, а нужен будет еще админ для всего этого

  3. ISO 27001 compliant наложил ряд ограничений по задокументированной информации и мы решили документацию для разработчиков хранить в папочке doc в корне репозитория. Практика показала, что так просто удобнее. Мы пробовали gitbook, confluence и еще много разных форматов, но всё-таки на gitlab вместе с его поддержкой в Markdown и sequentional diagrams и всего остального вышло хорошо

  4. Modern application framework дал нам хорошие вопросы для установки границ

    1. What are your business priorities?

    2. What is the worst possible scenario?

    3. What are your immovable constraints?

    4. What data is this solution storing/processing?

    5. What skills does your team have?

    6. What is the timeline for the project?

Что выбирали и как

Выбирали мы между Okta, Auth0, Keycloak и Ory после небольшого ресерча. Требования мы выставили следующие:

  1. Простота в интеграции, хорошее API и хорошая документация. Чистый код, желательно нашего стека (Python+Go)

  2. Возможность управлять учетными данными самим и желательно, чтобы было self-hosted решение, но если будет достаточно безопасно, то можно и рассмотреть вариант интеграции

  3. Достаточно легковесно и нересурсоемко

  4. Подходы 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")

И всё работает. Весь проект можно посмотреть у меня на гитхабе.

А что используете вы, чтобы идентифицировать пользователей?

Комментарии (12)


  1. Paskin
    14.01.2022 09:30

    А собственный IAM от AWS - рассматривался в качестве кандидата?


    1. Gen1us2k Автор
      14.01.2022 09:44

      Рассматривался. Но у нас не было опыта в использовании его. Ну и мы шли путем, что "Возьмем то, начем умеем программировать и если что починим сами". Делать лок и отдавать данные не имея возможности выгрузить и не зная кода было для нас как-то не очень хорошим решением.


  1. random1st
    14.01.2022 11:10
    +1

    Проводил аналогичный ресерч. Не могу сказать к чему по итогу пришли, но накину немного:

    • Keycloak хорош и в плане интеграции и кастомизации - это и возможность добавления расширений, и возможность использования Gatekeeper для выноса всей интеграции на уровень оркестратора. Ну и понятно, что это Java стек, но вообще он и из коробки достаточно навороченный.

    • Есть еще AWS Cognito - не настолько гибкий, но зато относительно недорогой и с готовыми интеграциями, плюс еще с AWS всегда можно вытащить гранты для стартапов. Ну и странно вообще не рассмотреть его, учитывая задекларированные принципы.

    • Google Firebase тоже неплохой вариант в плане стоимости/возможностей, но нужно проработать сценарии использования в первую очередь.

    • Auth0 пожалуй лучшее коммерческое решение с отлично проработанными практиками по интеграции и документацией. Что касается высокой цены - нужно проговаривать с ними индивидуально (как и с любым SaaS есть возможность договориться об индивидуальных ценах при долгосрочном коммитменте).

    Автор собственно вообще не упомянул, какие протоколы их интересуют (Oauth2, SAML, OpenID Connect) - это важно при выборе решения. И какая интеграция, какие домены разработки, комплайнс, сертификация.

    Опять же - storage, multitenancy и еще много слов на поругаться.


    1. Gen1us2k Автор
      14.01.2022 11:38
      -1

      Keycloak хорош, но он на жаве и их сторадж infinispan может доставить кучу проблем. По протоколам нам нужна была обычная аутентификация для пользователей и управление пермишнами, тему с Oauth2, saml, openID connect я не рассматривал. Нужно было что-то простое и легковесное и в моем случае выбор пал на Ory Kratos/Ory Keto. Так было проще для моего проекта.


      1. random1st
        14.01.2022 11:45
        +1

        Вы до этого infinispan в принципе не доберетесь в небольшом проекте, это детали внутренней реализации. В качестве перзистент хранилища используется RDBMS. Что касается "обычной аутентификации" для пользователей - в таком случае можно было прекрасно оставаться на Django - не вижу смысла переезда. Короче ресерч кроме неочевидного "так проще" отсутствует. Я вижу что-то вроде "мы тут хотим на хайпе все на го, нашли решение, подогнали ответ под вопросы и теперь мы молодцы".


  1. webdevium
    14.01.2022 11:24

    Решили остановиться на AWS (ведь все сейчас сидят на нём, верно?)

    Отнюдь. Множество команд выбирают другие варианты.
    Тем более, AWS самый дорогой среди конкурентов.


    1. random1st
      14.01.2022 11:47
      +3

      Ай, оставьте, AWS дорог только для тех, кому нужны только виртуальные тачки и кто не умеет им грамотно пользоваться в плане менеджмента костов, грантов и готовых сервисов.


  1. Color
    14.01.2022 12:09

    Извините, но не увидел в статье ничего, кроме перечисления возможных решений.

    А что с конфигом ory? Как осуществляется контроль доступов, админский доступ, версионирование? Как реализована интеграция, через интернет? Если да, как ory обезопашивается от несанкционированного доступа, от доса?

    Ну и в целом ожидал того, что в заголовке, то есть "Как я делал IAM на готовых решениях", а не про то, как прикрутить настроенный ory stack к петоновскому приложению, без негатива.


    1. Gen1us2k Автор
      14.01.2022 13:38
      -1

      Звучит как отдельный запрос на еще одну статью) Спасибо за комментарий.


  1. VanKrock
    14.01.2022 15:34

    В dotnet повсеместно используется Identity Server 4, не рассматривали его?


  1. z0mb1ek
    16.01.2022 14:54

    почему не посмотрели в сторону FusionAuth?


    1. Gen1us2k Автор
      16.01.2022 14:54

      Мы как-то не рассмотрели его и он выпал из нашего поля взора