# Applying OPA Gatekeeper

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-f905bcdc80ceff99518167838c9860f9947a146d%2F62c94bca38d9cc2d56a57a1d2822e1f6.png?alt=media)

Представим, что мы маленькая компания. Мы хотим перенести рабочие нагрузки в 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)***.***

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-6bb7fad65b91aba2d980fa60a4a455dd0504115e%2Fec4d06a5079ff3244d66086ef4cdd1d9.png?alt=media)

<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 затем опирается на эти политики, чтобы отклонять или принимать запросы.

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-12ab3cbd0c37463a348c38b793f78eb65affbb07%2Fa3f3cc9f2425e7f0ee2f4f9de389aefc.png?alt=media)

<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 в шаблонах. Там все очень просто. Затем приступайте к практической части.

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-7186172b8619584859af70ea3dd2caae684f5fd7%2Ffa61afb496390795c661b7cf30099312.png?alt=media)

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.

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-cf8f1acd00289272a0314aa4056e97e7ca98cb33%2F964118ccadd9341d5af494a77b9d2908.png?alt=media)

minikube-start.png

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-65d3e47d565ad8b47ec56628056ac6e1aee0070b%2F467beae96fd96d31b6862bfd20ff1b0b.png?alt=media)

docker-context.png

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-1f59b1c3d5549ab7c21558e17f1bacc663b8ccf3%2F506242ecfd6d9465551fe811a48d7106.png?alt=media)

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.

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-d6504be869382ba5c8327d07bfdbb5de329c5bef%2Fba966d31897341cb14660df4348ee605.png?alt=media)

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-41bfcb8a7238202ba823c0b80c582ccea33f3c1d%2F62df533417e36b52d978a88ec1dd38cd.png?alt=media)

privileged-constrainttemplate.yaml

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-86db2a6d8b837ad34888f9faea62459993e17b64%2Fef24e80307ec69bd0ea12ae66ab16436.png?alt=media)

privileged-container-crd.png

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-46fc907e4b6d9e29da077f9fd1edf0da3e021c2b%2F2db5f13fd54b10b6193249047932bff1.png?alt=media)

priviliged-container-constraint.yaml

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-d01adb362900c80d7712bcc37039f5cdcccf9ab6%2F7444c92984b687748c4d88001420c2e0.png?alt=media)

apply-privileged-constraint.png

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

![](https://296194292-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLoAqAoOfr7XVUQw7Gff8%2Fuploads%2Fgit-blob-7427be0001320e328c936c87fec14622ef888acb%2F48a110f17c1bdfe24a0c32cf7daad06a.png?alt=media)

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.*
