Рубрики
Uncategorized

ЕДИНЯТ

Инфраструктура как код. Фото любезно предоставлено: @Bass Emmen Первоначально опубликовано по адресу https: //pbnj.dev … Tagged с OpenPolicyagent, Conftest, Unittest, DevOps.

Инфраструктура как код. Фото любезно предоставлено: @Bass Emmen

Первоначально опубликовано в https://pbnj.dev

Оглавление

  • Обзор
  • Начиная
    • Dockerfile
    • Kubernetes
  • Следующие шаги

Обзор

Эра инфраструктуры как кода (IAC) разблокировала огромную производительность разработчика и функции ловкости. Теперь, как инженер, мы можем объявить нашу инфраструктуру и среды как структурированные данные в файлах конфигурации, таких как шаблоны Terraform, Dockerfiles и Kubernetes.

Тем не менее, эта ловкость и скорость обеспечения и настройки инфраструктуры поставляются с высоким риском ошибок в форме неправильных сборов.

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

Одним из таких инструментов, который может помочь нам проверить на наших файлах конфигурации Conftest Анкет Что уникально в Conftest это то, что он использует Открытый политика-агент (OPA) и политика Язык, называемый Рего к выполнить это.

Сначала это может показаться трудным, но это начнет иметь смысл.

Давайте рассмотрим 2 использования, где мы можем проверить наши конфигурации!

Начиная

Во -первых, некоторые предпосылки:

  • Conftest :

    • macOS: Brew Install Intustraa/Instrumenta/Conftest
  • (Необязательно) опе :

    • macOS: Бросить установка OPA

Dockerfile

Допустим, мы хотим предотвратить некоторые изображения и/или теги (например, Последние ).

Нам нужно создать простой Dockerfile:

FROM kalilinux/kali-linux-docker:latest

ENTRYPOINT ["echo"]

Теперь нам нужно создать наш первый тестовый файл модуля, давайте назовем его test.rego и Поместите это в каталог, назовем это политика (это настраивается).

package main

disallowed_tags := ["latest"]
disallowed_images := ["kalilinux/kali-linux-docker"]

deny[msg] {
        input[i].Cmd == "from"
        val := input[i].Value
        tag := split(val[i], ":")[1]
        contains(tag, disallowed_tags[_])

        msg = sprintf("[%s] tag is not allowed", [tag])
}

deny[msg] {
        input[i].Cmd == "from"
        val := input[i].Value
        image := split(val[i], ":")[0]
        contains(image, disallowed_images[_])

        msg = sprintf("[%s] image is not allowed", [image])
}

Предполагая, что мы находимся в правильном каталоге, мы можем проверить наш Dockerfile:

$ ls
Dockerfile      policy/

$ conftest test -i Dockerfile ./Dockerfile
FAIL - ./Dockerfile - [latest] tag is not allowed
FAIL - ./Dockerfile - [kalilinux/kali-linux-docker] image is not allowed

Просто чтобы быть уверенным, давайте изменим этот Dockerfile, чтобы пройти тест:

# FROM kalilinux/kali-linux-docker:latest
FROM debian:buster

ENTRYPOINT ["echo"]
$ ls
Dockerfile      policy/

$ conftest test -i Dockerfile ./Dockerfile
PASS - ./Dockerfile - data.main.deny

«Оно работает! Но я не понимаю, как, — слышу, что вы думаете про себя.

Давайте разберем синтаксис Рего вниз:

  • Пакет Main это способ для нас разместить некоторые правила, которые принадлежат вместе в пространстве имен. В этом случае мы назвали это Главный Потому что Conftest по умолчанию, но мы можем легко сделать что -то вроде Пакет Docker а затем беги Conftest Test -i Dockerfile -Namespace Docker ./dockerfile
  • diswallowed_tags & diswallowed_images просто простые переменные, которые содержат массив струн
  • deny [msg] {...} является началом правила отказа, и это означает, что DockerFile должен быть отклонен, и пользователю должно быть предоставлено сообщение об ошибке MSG Если условия в теле (то есть {...} ) верны
  • Выражения в теле правила отрицания рассматриваются как логичные и. Например:
  1 == 1                    # IF 1 is equal to 1
  contains("foobar", "foo") # AND "foobar" contains "foo"
                            # This would trigger the deny rule
  • Вход [i] .cmd Проверяет, является ли команда Docker От Анкет Вход [i] означает, что у нас может быть тестирование нескольких DockerFiles одновременно. Это будет повторять их
  • Следующие 2 строки — это назначения только для того, чтобы разделить строку и сохранить некоторые данные в переменных
  • Содержит (TAG, DINALDED_TAGS [_]) Вернут True, если тег Мы получили из DockerFile содержит один из diswallowed_tags . массив [_] Синтаксис означает итерацию над значениями
  • MSG (...) Создает сообщение, которое мы хотим сообщить нашему пользователю, если это правило отказано
  • Второй отрицание [msg] Правило проверяет, что само изображение не в блоке.

Kubernetes

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

Нам нужно создать наше развертывание

$ mkdir -p kubernetes
$ cat <./kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
EOF

Теперь нам нужно создать наш модульный тест:

$ mkdir -p ./kubernetes/policy
$ cat <./kubernetes/policy/test.rego
package main

name := input.metadata.name

deny[msg] {
  input.kind == "Deployment"
  not input.spec.template.spec.securityContext.runAsNonRoot

  msg = sprintf("Containers must run as non root in Deployment %s. See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", [name])
}
EOF

И давайте запустим это:

conftest test -i yaml ./kubernetes/deployment.yaml
FAIL - ./kubernetes/deployment.yaml - Containers must run as non root in Deployment nginx-deployment. See: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Это немного проще:

  • Получите Metadata.name из Вход (Который является развертыванием kubernetes yaml file)
  • Создайте правило отказа, которое запускается, если:
    • input.kind это Развертывание и
    • SecurityContext.RunasnonRoot не установлен
  • Верните сообщение об ошибке пользователю о том, что контейнеры должны работать как без корня и указывать им на документы.

Следующие шаги

Итак, куда идти отсюда?

Язык Rego огромный, и это может потребоваться немного, чтобы обернуть голову вокруг, как он работает. Вы даже можете отправить и получать HTTP -запросы внутри Рего.

Я рекомендую прочитать документы, чтобы узнать больше о возможностях Рего:

Я также едва поцарапал поверхность Conftest В этом блоге. Репозиторий имеет хороший список Примеры что ты должен просмотрите на досуге. Conftest Даже поддерживает политики обмена через загрузку ОПА связки для OCI-совместимых реестров, например, conftest push ... , Conftest Pull ... Анкет

Наконец, если у вас есть какие -либо вопросы, сообщество OPA дружелюбно и гостеприимно. Не стесняйтесь присоединиться к #conftest канал в Opa Slack Анкет

Счастливого кодирования!

Оригинал: «https://dev.to/pbnj/unit-test-your-configuration-files-3mnf»