> For the complete documentation index, see [llms.txt](https://book.konstantinsecurity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.konstantinsecurity.com/readme/architect/kubernetes/control-plane-security/gatekeeper/applying-opa-gatekeeper.md).

# Applying OPA Gatekeeper

<https://habr.com/ru/companies/slurm/articles/688268/>

![](/files/47Yf0BXSAg4xX1jF2f2j)

Представим, что мы маленькая компания. Мы хотим перенести рабочие нагрузки в Kubernetes, но нас очень волнует вопрос безопасности. Мы уже создали кластеры, опираясь на рекомендации по безопасности из [официальной документации Kubernetes](https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/). Бизнес растёт, и нам нужно что-то изменить, чтобы защитить среду Kubernetes и в то же время управлять действиями конечных пользователей в кластере. Мы используем встроенные возможности Kubernetes, вроде управления доступом на основе ролей (RBAC), политик безопасности pod’ов, политик сети, управления secret’ами и т. д.

В какой-то момент мы понимаем, что нам нужны более детальные настройки. Например, мы хотим запретить развёртывание pod’ов, если образ поступает из ненадёжного реестра. Встроенных функций нам уже не хватает, и мы начинаем обдумывать собственные политики, удовлетворяющие нашим требованиям.

Допустим, мы сформулировали политики. Как теперь легко и быстро применить их в среде Kubernetes?

В статье мы ответим на этот вопрос.

### Что такое OPA Gatekeeper?

OPA Gatekeeper — это контроллер политики для Kubernetes. Если точнее — настраиваемый вебхук для доступа (admission webhook) в Kubernetes, который помогает применять политики и поддерживает систему управления и контроля. OPA перед Gatekeeper расшифровывается как Open Policy Agent, потому что это их проект ([Github](https://github.com/open-policy-agent/gatekeeper)).

Что такое OPA? Мы уже разобрались, что это Open Policy Agent, но что он делает? Это инструмент общего назначения для работы с политиками. Его можно применять с авторизацией API, SSH, Docker и т. д. В OPA политики пишутся на специальном языке Rego и обычно сохраняются как файлы `*.rego`.

OPA можно использовать где угодно, а вот OPA Gatekeeper создан специально для контроля доступа в Kubernetes.

*Больше об OPA читайте в* [***вводном обзоре Open Policy Agent***](https://medium.com/trendyol-tech/first-look-to-opa-open-policy-agent-3542810941c9)***.***

![](/files/WkN10Q3gPfCUwYpjExCB)

<https://kubernetes.io/blog/2019/08/06/opa-gatekeeper-policy-and-governance-for-kubernetes/>

### Какие задачи он решает?

Этот проект создан специально под Kubernetes и помогает организациям быстро и без лишних проволочек применять политики и рекомендации по безопасности в средах Kubernetes.

Зачем организациям вообще нужны политики?

В двух словах, **политики** определяют, что пользователи могут делать в кластере.

Это зависит от потребностей организации или юридических требований.

Например, мы можем определить в своей среде следующие политики:

* Загружать образы можно только из одобренных репозиториев.
* Для всех pod’ов нужно установить лимиты по ресурсам.
* Pod’ы нельзя запускать от имени root
* Pod’ы не могут содержать привилегированный контейнер.

С помощью Gatekeeper мы можем применять политики для защиты и оптимизации без лишних хлопот, используя кастомные определения ресурсов и Rego.

[Здесь](https://github.com/open-policy-agent/gatekeeper#how-is-gatekeeper-different-from-opa) можно узнать, чем Gatekeeper отличается от OPA.

### Как он решает задачи?

Как вообще работает Gatekeeper?

В Kubernetes есть так называемые динамические контроллеры доступа ([Dynamic Admission Controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)) — вебхуки (*обратные вызовы HTTP*), которые перехватывают запросы до их сохранения в etcd. Gatekeeper работает как проверяющий вебхук доступа (validating admission webhook) поверх движка OPA. Gatekeeper описывает и применяет политику с помощью [OPA Constraint Framework](https://github.com/open-policy-agent/frameworks/tree/master/constraint). Когда мы динамически настраиваем политики OPA с помощью [кастомных определений ресурсов](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) (Custom Resource Definition, CRD), Gatekeeper затем опирается на эти политики, чтобы отклонять или принимать запросы.

![](/files/jp4ZMgBaxXSJv3HeVEhl)

<https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/>

В Gatekeeper политики определяются в виде ограничений. Ограничения мы пишем на Rego, но сначала нужно создать [шаблон ограничения](https://github.com/open-policy-agent/gatekeeper#constraint-templates), с помощью которого мы объявим само ограничение. Шаблон описывает логику Rego и схему ограничения.

По сути, ограничение — это CRD, создаваемое из шаблона. То есть Gatekeeper будет создавать новое CRD для описания каждой определяемой политики.

Шаблон ограничения можно сравнить с функцией, а ограничение — с вызовом функции.

### Пример

Прежде чем перейти к практической части, давайте скажем пару слов о Rego.

Rego — это очень простой и хорошо задокументированный язык, на котором мы пишем политики в шаблонах ограничений. Прочтите [документацию по Rego](https://www.openpolicyagent.org/docs/latest/policy-language/), чтобы понять, как использовать политики Rego в шаблонах. Там все очень просто. Затем приступайте к практической части.

Определим простейший шаблон ограничения.

![](/files/kRoOutz41h2EGf4oY8s0)

k8srequiredlabels-constrainttemplate.yaml

Как видите, мы пишем политики Rego в разделе ***.targets*** в шаблоне. Это первое, что мы должны сделать, чтобы подготовить само ограничение. Обратите внимание, что для ресурса указан тип (kind) ConstraintTemplate, а это CRD входит в установку Gatekeeper. Где же ограничение? Посмотрите на поле ***.spec.crd.spec.names.kind*** в шаблоне. ***K8sRequiredLabels*** и есть наше ограничение. Не существует CRD с именем Constraint (как для ConstraintTemplate). Ограничение само по себе представляет собой CRD, которое мы создадим из шаблона. В данном случае это ***K8SRequiredLabels***. Мы также видим, что ограничение ждёт входных данных, потому что мы должны указать обязательные метки. Эти входные данные обозначены в политике Rego как ***input.parameters***.

Давайте рассмотрим конкретный пример. Мы установим Gatekeeper на локальный кластер minikube с помощью Helm. Потом мы попытаемся запретить в кластере привилегированные контейнеры. Там будет один фокус. Вместо команды ***eval $(minikube docker-env)*** мы используем **к*****онтекст Docker***, чтобы получить доступ к Docker-демону на виртуальной машине Minikube. В [этой документации](https://docs.docker.com/engine/context/working-with-contexts/) можно узнать больше о контексте Docker.

Запустим локальный кластер Kubernetes с помощью minikube.

![](/files/UPkcztAtuKYk7WncdDJU)

minikube-start.png

Настроим контекст Docker, чтобы использовать Docker-демон на виртуальной машине Minikube.

![](/files/hXzt8EyMxn3ZyljkEe5A)

docker-context.png

Установить OPA Gatekeeper можно разными способами. Мы, например, используем Helm. Полный список способов установки см. в [этой документации.](https://github.com/open-policy-agent/gatekeeper#installation-instructions)

![](/files/31ffgZyy3Zc6i23vG82J)

helm-gatekeeper.png

*Этот чарт совместим с Helm 3 начиная с Gatekeeper 3.1.1. При использовании Helm 3 мы видим предупреждения о хуке* `crd-install`*. Это связано с обратной совместимостью с Helm 2 и не повлияет на развёртывание чарта.*[*https://github.com/open-policy-agent/gatekeeper#deploying-via-helm*](https://github.com/open-policy-agent/gatekeeper#deploying-via-helm)

Какие CRD были созданы при установке Gatekeeper? Как видите, у нас нет CRD с именем Constraint, зато есть CRD с именем ConstraintTemplate.

![](/files/KDDQoRZTxu0eiM3zrqby)

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

![](/files/eR34LYcJVk3kNjODEkWj)

privileged-constrainttemplate.yaml

Здесь мы определяем ограничение ***PriviligedContainer***. В этом ограничении будет использоваться политика Rego, которая определена в разделе ***.targets*** в шаблоне ограничения. Если мы применим этот манифест YAML, будет создано CRD с именем ***PrivilegedContainer***.

![](/files/9EitGKacmePKVSJpbUt4)

privileged-container-crd.png

Как определить ограничение **PriviligedContainer** в кластере? Давайте посмотрим. Здесь важно отметить, что ограничение нужно применить явно, иначе запрет на привилегированные контейнеры не начнёт действовать.

![](/files/h6cosLKtPcHUo5FCtKiV)

priviliged-container-constraint.yaml

Мы указали, что хотим перехватывать запросы pod’ов и применять к ним политику. Давайте применим ограничение и протестируем его.

![](/files/YyjlQWdPePEjoIXdGkKs)

apply-privileged-constraint.png

Проверим, что получилось. Сначала мы создадим обычный pod, и тут проблем возникнуть не должно. Затем мы возьмём pod с привилегированным контейнером, и на этот раз запрос должен быть отклонён.

![](/files/NuXUzdTC6AJqYiGDhj42)

apply-privileged-pod.png

Как видите, все работает. Мы применили манифест YAML, и теперь в кластере запрещены привилегированные контейнеры. Кстати, политики не обязательно писать самим — есть официальная библиотека с большим набором вариантов. [Убедитесь сами](https://github.com/open-policy-agent/gatekeeper-library).

### Заключение

OPA Gatekeeper — это полезный инструмент, с помощью которого можно легко описывать и определять политики в кластерах Kubernetes. Это правда очень удобно. Здесь мы рассмотрели не все возможности OPA Gatekeeper. Там ещё много интересного, честное слово.

*БОНУС. Существует ещё один проект —* [***Kyverno***](http://kyverno.io/)***.** В чём-то он похож на OPA Gatekeeper, но может менять или создавать ресурсы, а для написания политик не использует Rego.*
