Что такое OPA?


Это проект, стартовавший в 2016 году, направленный на унификацию применения политик в различных технологиях и системах. Сегодня OPA используется гигантскими игроками в технологической индустрии. Например, Netflix использует OPA для управления доступом к своим внутренним ресурсам API. Chef использует его для предоставления возможностей IAM в своих продуктах для конечных пользователей. Кроме того, многие другие компании, такие как Cloudflare, Pinterest и другие, используют OPA для обеспечения соблюдения политик на своих платформах (например, кластеры Kubernetes). В настоящее время OPA является частью CNCF в качестве инкубационного проекта.


Что предлагает OPA?


Вы можете спросить: как возникла OPA? Какие проблемы пытается решить? Действительно, применение политик в отношении API и микросервисов так же старо, как и сами микросервисы. Никогда не было приложения production уровня, которое не обеспечивало бы какой-либо контроль доступа, авторизацию и применение политик. Чтобы понять роль OPA, рассмотрим следующий вариант использования: ваша компания продает ноутбуки через онлайн-портал. Как и все другие подобные приложения, портал состоит из главной страницы, где клиенты видят последние предложения, возможно, некоторые ограниченные по времени рекламные акции. Если клиенты хотят что-то купить, им необходимо войти в систему или создать учетную запись. Затем они осуществляют платежи с помощью своих кредитных карт или другими способами. Чтобы ваши клиенты постоянно посещали вас, вы предлагаете им подписаться на вашу рассылку новостей, которая может содержать специальные скидки. Кроме того, они могут выбрать получение уведомлений браузера, как только будут объявлены новые продукты. Типичное приложение для онлайн-покупок, не так ли? Теперь давайте изобразим, как этот рабочий процесс будет выглядеть на диаграмме, чтобы визуализировать процесс:



На диаграмме выше показано, как наша система может выглядеть внутри. У нас есть ряд микросервисов, которые взаимодействуют друг с другом для обслуживания наших клиентов. Теперь очевидно, что Боб не должен видеть никаких внутренних механизмов работы системы. Например, он не может просматривать (или даже знать) корзину S3, в которой архивируются платежи, или с какими службами может взаимодействовать API уведомлений. Но как насчет Джона? Он один из наших разработчиков приложений, и ему нужен доступ ко всем микросервисам, чтобы иметь возможность устранять неполадки и отлаживать их при возникновении проблем. Или он? Что, если он случайно (или намеренно) вызовет API-интерфейс службы базы данных, чтобы изменить адрес доставки клиента на другое место? Хуже того, что, если бы у него были разрешения на чтение номеров кредитных карт клиентов? Чтобы устранить эти риски, мы размещаем элемент управления авторизацией поверх каждого из наших микросервисов. Элемент управления проверяет, имеет ли аутентифицированный пользователь необходимые привилегии для выполнения запрошенной операции. Такая система авторизации может быть внутренним, собственным процессом или внешним, как это предусмотрено AWS IAM. Так создается и защищается типичное приложение для микросервисов. Но посмотрите на недостатки использования нескольких разных систем авторизации, особенно по мере роста приложения:


  • Изменение существующих политик или введение новых — это кошмар. Только подумайте, сколько мест вам нужно будет посетить, чтобы предоставить Алисе доступ для чтения ко всем системам хранения. Это означает, что S3, MySQL, MongoDB и, возможно, внешний API, и это лишь некоторые из них.
  • Разработчики не могут применять политики в своих собственных системах. Очевидно, они могут жестко запрограммировать свою логику авторизации в приложении, но это значительно усугубляет ситуацию: попытки унифицировать политики для разных микросервисов очень сложны.
  • В дополнение к предыдущему пункту, введение новой политики для локальных служб может потребовать изменения кода и, таким образом, введения новых версий всех микросервисов.
  • Что, если вы хотите интегрировать политики с существующей базой данных пользователей? Например, интеграция с базой данных HR.
  • Нам нужно визуализировать политику, чтобы убедиться, что она выполняет то, что должна. Это приобретает все большее значение по мере усложнения вашей политики.
  • Современные системы включают в себя множество технологий и сервисов, написанных на разных языках. Например, у вас может быть ядро вашей системы, работающее на Kubernetes, и множество устаревших API-интерфейсов, которые не являются частью кластера, написанного на Java, Ruby и PHP. Каждая платформа имеет собственный механизм авторизации.

Давайте посмотрим на Kubernetes в качестве примера. Если бы всем пользователям был разрешен доступ ко всему кластеру, может произойти множество неприятных вещей, таких как:


  • Предоставление неограниченных запросов и ограничений для всех модулей может привести к выселению случайных модулей из узлов.
  • Получение и использование непроверенных, случайных образов, которые могут содержать уязвимости безопасности или вредоносный контент.
  • Использование контроллеров Ingress без TLS, позволяющих передавать в приложение незашифрованный и незащищенный трафик.
  • Многочисленные другие непредвиденные риски из-за общей сложности.

Конечно, вы можете использовать RBAC и политики безопасности Pod для детального контроля над кластером. Но опять же, это применимо только к кластеру. Kubernetes RBAC бесполезен, кроме как в кластере Kubernetes.


Вот где в игру вступает Open Policy Agent (OPA). OPA был введен для создания унифицированного метода обеспечения соблюдения политики безопасности в стеке.


Как работает OPA?


Ранее мы исследовали стратегии обеспечения соблюдения политик и то, что OPA пытается решить, — это показало нам, «что». А теперь давайте посмотрим, «как».


Допустим, вы внедряете платежную службу нашего примера приложения. Эта служба отвечает за обработку платежей клиентов. Он предоставляет API, в котором принимает оплату от клиента. Это также позволяет пользователю запрашивать, какие платежи были произведены конкретным клиентом. Итак, чтобы получить массив, содержащий покупки, сделанные Джейн, которая является одним из клиентов компании, вы отправляете запрос GET в API с путем / payment / jane. Вы указываете свои учетные данные в заголовке авторизации и отправляете запрос. Ответом будет массив JSON с запрошенными вами данными. Однако, поскольку вы не хотите, чтобы кто-либо, имеющий доступ к сети, имел доступ к Payments API для просмотра таких конфиденциальных данных, вам необходимо применить политику авторизации. OPA решает проблему следующим образом:


  1. Payments API запрашивает решение у OPA. Он сопровождает этот запрос некоторыми атрибутами, такими как метод HTTP, используемый в запросе, путь, пользователь и т. д.
  2. OPA проверяет эти атрибуты на соответствие уже предоставленным данным.
  3. После проверки OPA отправляет решение запрашивающему API с разрешением или запретом.

Здесь важно отметить, что OPA отделяет наше решение о политике от применения политики. Рабочий процесс OPA можно изобразить на следующей диаграмме:



OPA — это универсальный инструмент принудительного применения политик, не зависящий от домена. Он может быть интегрирован с API, демоном SSH Linux, хранилищем объектов, таким как CEPH, и т. Д. Разработчики OPA намеренно избегали основывать его на каком-либо другом проекте. Соответственно, запрос политики и решение не следуют конкретному формату. То есть вы можете использовать любые допустимые данные JSON в качестве атрибутов запроса, если они предоставляют необходимые данные. Точно так же решение политики, исходящее от OPA, также может быть любыми действительными данными JSON. Вы выбираете, что вводится, а что выводится. Например, вы можете выбрать, чтобы OPA возвращал объект JSON True или False, число, строку или даже сложный объект данных.


Внутреннее устройство OPA


Чтобы полностью понять OPA и начать применять его в своих проектах, вы должны ознакомиться с его функциями и компонентами. Начнем с того, как вы определяете свою политику.


Язык политики: Rego


Rego — это декларативный язык высокого уровня, созданный специально для OPA. Это упрощает определение политик и ответы на такие вопросы, как: разрешено ли Бобу выполнять GET-запрос на /api/v1/products? Какие записи ему разрешено просматривать?


Развертывание


Когда дело доходит до развертывания OPA, у вас есть несколько вариантов в зависимости от вашего конкретного сценария:


  • В качестве библиотеки Go: если ваше приложение написано на Golang, вы можете реализовать OPA как стороннюю библиотеку в приложении.
  • В качестве демона: если вы не используете Go, вы можете развернуть OPA, как и любую другую службу, в качестве демона. В этом случае рекомендуется использовать дополнительный контейнер или запускать его на уровне хоста. Причина в том, что такая конструкция увеличивает производительность и доступность. Представьте, что у вас есть OPA, развернутый в Kubernetes в отдельном модуле, который находится на отдельном узле, а не на том, где работает модуль вашего приложения. Теперь, каждый раз, когда вашей службе требуется обратиться к OPA для принятия решения о политике, она должна совершать вызов по сети, чтобы связаться с модулем, в котором работает OPA. Это приводит к ненужной задержке и может вызывать задержки приложений в часы пик.


Как управлять и контролировать OPA?


Чтобы еще больше уменьшить задержку, разработчики решили, что OPA должен хранить все данные политики в памяти. Это гарантирует, что OPA не будет запрашивать данные у другой службы. Для работы с OPA у вас есть набор API, которые служат для разных целей:


  • API сервиса Bundle: используется для отправки данных политики в OPA. OPA постоянно опрашивает API службы Bundle в поисках новых версий политики. После обнаружения он извлекает и применяет новую версию.
  • API статуса сервиса: используется для определения статуса сервиса. Он сообщает вам текущую версию политики, которая активна в OPA.
  • API службы журнала решений: каждый раз, когда OPA принимает решение о политике, оно регистрирует его. Позже он отправляет пакеты этих журналов в API службы журналов. Это особенно полезно для аудита и устранения неполадок.
  • Инструменты для создания, тестирования и отладки политик: набор инструментов командной строки, которые вы можете использовать, например, opa test, opa run, opa check и т. д. Для упрощения разработки доступен также подключаемый плагин VS Code.

Ваша первая политика OPA


К настоящему времени у вас должно быть довольно четкое представление о том, почему появился OPA, проблемы, которые он пытается решить, и как он был спроектирован и решен. Пришло время проверить воду и посмотреть, каково это — создавать политику на языке Rego. Первый шаг — сформулировать свою политику на простом английском языке. Например:


«Клиенты должны иметь возможность просматривать свои собственные платежи. Сотрудники финансового отдела должны иметь возможность просматривать любые платежи клиентов».


Следующим шагом будет преобразование политики в код Rego. Для этого мы можем использовать Rego. Итак, на главной панели очистите код, который уже был добавлен туда, и добавьте следующее:


package play

# Customers should be able to view their own payments
allow = true {
    input.method = "GET"
      input.path = ["payments", customer_id]
      input.user = customer_id
}

Давайте рассмотрим этот фрагмент построчно:


  1. Любые строки, начинающиеся со знака решетки (#), являются комментариями. Всегда полезно писать о том, что ваша политика должна делать, в виде связного, удобочитаемого комментария.
  2. allow = true означает, что решение будет разрешено, если следующие «оценки» верны.
  3. Метод ввода — GET. Любой другой метод HTTP (POST, PUT и т. Д.) Нарушит политику.
  4. Путь: /payments/customer_id. Обратите внимание, что customer_id не заключен в кавычки, что означает, что это переменная, которую необходимо подставить во время вызова.
  5. Пользователь также должен быть customer_id.

Если бы мы перевели этот код обратно на простой язык, это выглядело бы примерно так:
«Разрешите запрос, если он использует метод GET, путь — /payments/customer_id, а пользователь — тот же customer_id. Что эффективно позволяет клиенту просматривать свои собственные платежные данные ».


Rego также позволяет вам оценить ваш код и убедиться, что политика работает должным образом. В панели INPUT мы можем подделать законный запрос, добавив следующий код:


{
    "method": "GET",
    "path": ["payments","bob"],
    "user": "bob"
}

Обратите внимание, что INPUT использует произвольный JSON. Нет никаких особых правил, которым нужно следовать при отправке запроса. Теперь давайте посмотрим, как OPA ответит на этот запрос о решении, нажав кнопку Evaluate. На панели OUTPUT должно отображаться следующее:


{
    "allow": true
}

Ниже приведен снимок экрана площадки после выполнения вышеуказанных действий:



Теперь давайте попробуем изменить пользователя в запросе на alice, что означает, что клиент пытается просмотреть платежи другого клиента. Если мы нажмем Evaluate, вы заметите, что на выходе отображается пустой объект JSON {}. Причина в том, что OPA не знает, что отправлять, если политика не соответствует. Чтобы изменить это поведение, добавьте следующий оператор перед телом политики:


default allow = false

Итак, вся политика должна выглядеть так:


package play

# Customers should be able to view their own payments
default allow = false
allow = true {
    input.method = "GET"
      input.path = ["payments", customer_id]
      input.user = customer_id
}

Теперь, если вы нажмете Evaluate, вы увидите ожидаемый результат:


{
    "allow": false
}

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


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


Добавьте следующие строки после политики, которую мы определили ранее:


Сотрудники финансового отдела могут просматривать любые платежи клиентов


allow = true {
    input.method = "GET"
    input.path = ["payments", customer_id]
    finance[input.user]
}

finance = {"john","mary","peter","vivian"}

Большая часть этой политики похожа на предыдущую, за исключением строки 4. Вместо оценки того, совпадает ли идентификатор пользователя с идентификатором клиента, мы оцениваем, является ли пользователь частью финансового объекта JSON. Rego имеет множество встроенных конструкций, которые позволяют делать много полезных вещей, включая поиск. Наконец, мы определяем финансовый объект и добавляем имена пользователей для сотрудников, работающих в этой группе. В реальном сценарии этот объект JSON будет передаваться как часть запроса INPUT или как токен. Теперь давайте протестируем политику, задав для пользователя и клиента одно и то же имя (например, bob). Политика должна возвращать истину. Измените пользователя на john (который работает в финансовом отделе) и протестируйте политику. Опять же, он должен вернуть истину. Наконец, измените имя пользователя на любое имя, которое не работает в финансовом отделе (скажем, Джейн), и политика должна вернуть false.


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


Интеграция OPA с другими системами


Как упоминалось ранее, OPA можно интегрировать со многими современными платформами. Давайте посмотрим на несколько примеров того, что OPA может для вас сделать:


Kubernetes:


  • Убедитесь, что имена узлов входа изменяются только командой внешнего интерфейса.
  • Запретить извлекать любые образы, кроме тех, которые поступают из корпоративного реестра Docker.
  • Принудительное использование запросов и ограничений для любых модулей, созданных в кластере.

Авторизация API:


  • Вы можете использовать OPA с Envoy, Istio и другими платформами для обеспечения контроля IAM. Например, вы можете легко контролировать доступ сотрудников службы безопасности к конфиденциальным данным.

Linux PAM:


  • Подключаемые модули аутентификации (PAM) уже давно используются в Linux для предоставления детализированных элементов управления множеству служб, включая SSH и sudo. OPA имеет плагин PAM, который позволяет ему интегрироваться с PAM и применять политики. Например, вы можете ограничить доступ по SSH к своим производственным машинам, если только в нерабочее время или если у пользователя нет открытой заявки в службу поддержки.

Есть также много других продуктов, которые можно интегрировать с OPA, чтобы предоставить безграничные возможности. Например, Kafka, ElasticSearch, SQLite и CEPH и многие другие.


TL; DR


  • Необходимость авторизации так же стара, как и само программное обеспечение.
  • Отсутствие централизованной системы авторизации, которая может использоваться между различными системами и платформами, вызвало множество проблем. Например, API-интерфейсы могут иметь собственную логику авторизации, встроенную в код, другие микросервисы могут зависеть от одной или нескольких внешних систем авторизации. Это делает развертывание новых политик, проверку версии существующей или даже внесение незначительных изменений в очень сложную операцию.
  • OPA работает, выступая в качестве консультанта той службы, которая должна принять решение об авторизации. Служба отправляет запрос решения в OPA, затем OPA проверяет запрос на основе уже сохраненных в нем политик и отвечает с решением.
  • OPA был разработан как универсальный и не зависящий от платформы. Соответственно, вам не нужно соблюдать какие-либо правила при отправке запросов или определении того, как будет выглядеть результат. Запросы и ответы отправляются в формате JSON.
  • Политики могут быть написаны на Rego, языке, специально разработанном для OPA. Подобно JavaScript, OPA позволяет очень легко преобразовать простые английские правила в действующие политики OPA.
  • Инструмент «Rego» — отличный способ опробовать ваши политики перед их внедрением.
  • OPA можно развернуть либо как библиотеку Go, которая становится частью двоичного файла приложения, либо как автономный демон.
  • Поскольку принятие решений о политике происходит при каждом запросе API, настоятельно рекомендуется разместить демон OPA как можно ближе к приложению. Например, как дополнительный контейнер в модуле Kubernetes или как демон, работающий на самом узле. Эта практика помогает уменьшить задержку и уменьшить сетевой трафик.
  • OPA использует ряд API-интерфейсов, которые упрощают внедрение новых политик, проверку версии и статуса существующих или сбор данных аудита и журналов.
  • В этой статье мы рассмотрели простую демонстрацию того, как использовать язык Rego для обеспечения соблюдения политики. В этом примере мы показали, насколько легко реализовать сложную политику и протестировать ее с помощью языка Rego и инструмента «игровая площадка».
  • OPA может интегрироваться со многими современными системами и платформами, такими как Kubernetes, Kafka, SQLite, CEPH и Terraform. С помощью подключаемого модуля PAM он также может интегрироваться с Linux PAM для обеспечения расширенного контроля политик на демонах Linux, использующих PAM (например, sshd и sudo).