Compare languages | The admission-policy-engine module: FAQ

How do I configure alternative security policy management solutions?

Как настроить альтернативные решения по управлению политиками безопасности?

For DKP to work correctly, extended privileges are required to run and operate system component payloads. If you are using some alternative security policy management solution (e. g., Kyverno) instead of the admission-policy-engine module, you have to configure exceptions for the following namespaces:

  • kube-system;
  • all namespaces with the d8-* prefix (e.g., d8-system).

Для корректной работы DKP необходимы расширенные привилегии на запуск и работу полезной нагрузки системных компонентов. Если вместо модуля admission-policy-engine используется альтернативное решение по управлению политиками безопасности (например, Kyverno), необходима настройка исключений для следующих пространств имен:

How do I extend Pod Security Standards policies?

  • kube-system;
  • все пространства имен с префиксом d8-* (например, d8-system).

Pod Security Standards respond to the security.deckhouse.io/pod-policy: restricted or security.deckhouse.io/pod-policy: baseline label.

Как расширить политики Pod Security Standards?

To extend the Pod Security Standards policy by adding your checks to existing checks, you need to:

  • Create a constraint template for the check (a ConstraintTemplate resource).
  • Bind it to the restricted or baseline policy.

Pod Security Standards реагируют на label security.deckhouse.io/pod-policy: restricted или security.deckhouse.io/pod-policy: baseline.

Example of the ConstraintTemplate for checking a repository URL of a container image:

Чтобы расширить политику Pod Security Standards, добавив к существующим проверкам политики свои собственные, необходимо:

yaml apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8sallowedrepos spec: crd: spec: names: kind: K8sAllowedRepos validation: openAPIV3Schema: type: object properties: repos: type: array items: type: string targets:

  • target: admission.k8s.gatekeeper.sh rego: | package d8.pod_security_standards.extended
  • создать шаблон проверки (ресурс ConstraintTemplate);
  • привязать его к политике restricted или baseline.

violation[{“msg”: msg}] { container := input.review.object.spec.containers[] satisfied := [good | repo = input.parameters.repos[] ; good = startswith(container.image, repo)] not any(satisfied) msg := sprintf(“container <%v> has an invalid image repo <%v>, allowed repos are %v”, [container.name, container.image, input.parameters.repos]) }

Пример шаблона для проверки адреса репозитория образа контейнера:

violation[{“msg”: msg}] { container := input.review.object.spec.initContainers[] satisfied := [good | repo = input.parameters.repos[] ; good = startswith(container.image, repo)] not any(satisfied) msg := sprintf(“container <%v> has an invalid image repo <%v>, allowed repos are %v”, [container.name, container.image, input.parameters.repos]) }

yaml apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8sallowedrepos spec: crd: spec: names: kind: K8sAllowedRepos validation: openAPIV3Schema: type: object properties: repos: type: array items: type: string targets:

  • target: admission.k8s.gatekeeper.sh rego: | package d8.pod_security_standards.extended

Example of binding a check to the restricted policy:

violation[{“msg”: msg}] { container := input.review.object.spec.containers[] satisfied := [good | repo = input.parameters.repos[] ; good = startswith(container.image, repo)] not any(satisfied) msg := sprintf(“container <%v> has an invalid image repo <%v>, allowed repos are %v”, [container.name, container.image, input.parameters.repos]) }

yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sAllowedRepos metadata: name: prod-repo spec: match: kinds:

  • apiGroups: [””] kinds: [“Pod”] namespaceSelector: matchLabels: security.deckhouse.io/pod-policy: restricted parameters: repos:
  • “mycompany.registry.com”

violation[{“msg”: msg}] { container := input.review.object.spec.initContainers[] satisfied := [good | repo = input.parameters.repos[] ; good = startswith(container.image, repo)] not any(satisfied) msg := sprintf(“container <%v> has an invalid image repo <%v>, allowed repos are %v”, [container.name, container.image, input.parameters.repos]) }

The example demonstrates the configuration of checking the repository address in the image field for all Pods created in the namespace having the security.deckhouse.io/pod-policy : restricted label. A Pod will not be created if the address in the image field of the Pod does not start with mycompany.registry.com.

Пример привязки проверки к политике restricted:

The Gatekeeper documentation may find more info about templates and policy language.

yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sAllowedRepos metadata: name: prod-repo spec: match: kinds:

  • apiGroups: [””] kinds: [“Pod”] namespaceSelector: matchLabels: security.deckhouse.io/pod-policy: restricted parameters: repos:
  • “mycompany.registry.com”

Find more examples of checks for policy extension in the Gatekeeper Library.

Пример демонстрирует настройку проверки адреса репозитория в поле image у всех подов, создающихся в пространстве имен, имеющих label security.deckhouse.io/pod-policy: restricted. Если адрес в поле image создаваемого пода начинается не с mycompany.registry.com, под создан не будет.

How to allow some Pod Security Standards policies without disabling whole list?

Подробнее о шаблонах и языке политик можно узнать в документации Gatekeeper.

To apply only the required security policies without turning off the entire built-in set:

Больше примеров описания проверок для расширения политики можно найти в библиотеке Gatekeeper.

  1. Add the security.deckhouse.io/pod-policy: privileged label to your namespace in order to disable built-in policies.
  2. Create a SecurityPolicy resource that matches the baseline or restricted policy while also editing the list of policies elements as you see fit.
  3. Add a label to your namespace that matches the namespaceSelector in the SecurityPolicy resource. In the examples below, the label is security-policy.deckhouse.io/baseline-enabled: "true" or security-policy.deckhouse.io/restricted-enabled: "true".

Как включить одну или несколько политик Pod Security Standards, не отключая весь набор?

SecurityPolicy that matches baseline standard:

Чтобы применить только нужные политики безопасности, не отключая весь предустановленный набор:

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: baseline spec: enforcementAction: Deny policies: allowHostIPC: false allowHostNetwork: false allowHostPID: false allowPrivilegeEscalation: true allowPrivileged: false allowedAppArmor:

  • runtime/default
  • localhost/* allowedCapabilities:
  • AUDIT_WRITE
  • CHOWN
  • DAC_OVERRIDE
  • FOWNER
  • FSETID
  • KILL
  • MKNOD
  • NET_BIND_SERVICE
  • SETFCAP
  • SETGID
  • SETPCAP
  • SETUID
  • SYS_CHROOT allowedHostPaths: [] allowedHostPorts:
  • max: 0 min: 0 allowedProcMount: Default allowedUnsafeSysctls:
  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.ip_unprivileged_port_start
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_local_reserved_ports
  • net.ipv4.tcp_keepalive_time
  • net.ipv4.tcp_fin_timeout
  • net.ipv4.tcp_keepalive_intvl
  • net.ipv4.tcp_keepalive_probes seLinux:
  • type: “”
  • type: container_t
  • type: container_init_t
  • type: container_kvm_t
  • type: container_engine_t seccompProfiles: allowedProfiles:
  • RuntimeDefault
  • Localhost
  • undefined
  • ’’ allowedLocalhostFiles:
  • ‘*’ match: namespaceSelector: labelSelector: matchLabels: security-policy.deckhouse.io/baseline-enabled: “true”
  1. Добавьте в нужное пространство имён метку: security.deckhouse.io/pod-policy: privileged, чтобы отключить встроенный набор политик.
  2. Создайте ресурс SecurityPolicy, соответствующий уровню baseline или restricted. В секции policies укажите только необходимые вам настройки.
  3. Добавьте в пространство имён дополнительную метку, которая будет соответствовать селектору namespaceSelector в SecurityPolicy. В примерах ниже это security-policy.deckhouse.io/baseline-enabled: "true" либо security-policy.deckhouse.io/restricted-enabled: "true"

SecurityPolicy that matches restricted standard:

SecurityPolicy, соответствующая baseline:

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: restricted spec: enforcementAction: Deny policies: allowHostIPC: false allowHostNetwork: false allowHostPID: false allowPrivilegeEscalation: false allowPrivileged: false allowedAppArmor:

  • runtime/default
  • localhost/* allowedCapabilities:
  • NET_BIND_SERVICE allowedHostPaths: [] allowedHostPorts:
  • max: 0 min: 0 allowedProcMount: Default allowedUnsafeSysctls:
  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.ip_unprivileged_port_start
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_local_reserved_ports
  • net.ipv4.tcp_keepalive_time
  • net.ipv4.tcp_fin_timeout
  • net.ipv4.tcp_keepalive_intvl
  • net.ipv4.tcp_keepalive_probes allowedVolumes:
  • configMap
  • csi
  • downwardAPI
  • emptyDir
  • ephemeral
  • persistentVolumeClaim
  • projected
  • secret requiredDropCapabilities:
  • ALL runAsUser: rule: MustRunAsNonRoot seLinux:
  • type: “”
  • type: container_t
  • type: container_init_t
  • type: container_kvm_t
  • type: container_engine_t seccompProfiles: allowedProfiles:
  • RuntimeDefault
  • Localhost allowedLocalhostFiles:
  • ‘*’ match: namespaceSelector: labelSelector: matchLabels: security-policy.deckhouse.io/restricted-enabled: “true”

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: baseline spec: enforcementAction: Deny policies: allowHostIPC: false allowHostNetwork: false allowHostPID: false allowPrivilegeEscalation: true allowPrivileged: false allowedAppArmor:

  • runtime/default
  • localhost/* allowedCapabilities:
  • AUDIT_WRITE
  • CHOWN
  • DAC_OVERRIDE
  • FOWNER
  • FSETID
  • KILL
  • MKNOD
  • NET_BIND_SERVICE
  • SETFCAP
  • SETGID
  • SETPCAP
  • SETUID
  • SYS_CHROOT allowedHostPaths: [] allowedHostPorts:
  • max: 0 min: 0 allowedProcMount: Default allowedUnsafeSysctls:
  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.ip_unprivileged_port_start
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_local_reserved_ports
  • net.ipv4.tcp_keepalive_time
  • net.ipv4.tcp_fin_timeout
  • net.ipv4.tcp_keepalive_intvl
  • net.ipv4.tcp_keepalive_probes seLinux:
  • type: “”
  • type: container_t
  • type: container_init_t
  • type: container_kvm_t
  • type: container_engine_t seccompProfiles: allowedProfiles:
  • RuntimeDefault
  • Localhost
  • undefined
  • ’’ allowedLocalhostFiles:
  • ‘*’ match: namespaceSelector: labelSelector: matchLabels: security-policy.deckhouse.io/baseline-enabled: “true”

What if there are multiple policies (operational or security) that are applied to the same object?

SecurityPolicy, соответствующая restricted:

In that case the object’s specification have to fulfil all the requirements imposed by the policies.

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: restricted spec: enforcementAction: Deny policies: allowHostIPC: false allowHostNetwork: false allowHostPID: false allowPrivilegeEscalation: false allowPrivileged: false allowedAppArmor:

  • runtime/default
  • localhost/* allowedCapabilities:
  • NET_BIND_SERVICE allowedHostPaths: [] allowedHostPorts:
  • max: 0 min: 0 allowedProcMount: Default allowedUnsafeSysctls:
  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.ip_unprivileged_port_start
  • net.ipv4.tcp_syncookies
  • net.ipv4.ping_group_range
  • net.ipv4.ip_local_reserved_ports
  • net.ipv4.tcp_keepalive_time
  • net.ipv4.tcp_fin_timeout
  • net.ipv4.tcp_keepalive_intvl
  • net.ipv4.tcp_keepalive_probes allowedVolumes:
  • configMap
  • csi
  • downwardAPI
  • emptyDir
  • ephemeral
  • persistentVolumeClaim
  • projected
  • secret requiredDropCapabilities:
  • ALL runAsUser: rule: MustRunAsNonRoot seLinux:
  • type: “”
  • type: container_t
  • type: container_init_t
  • type: container_kvm_t
  • type: container_engine_t seccompProfiles: allowedProfiles:
  • RuntimeDefault
  • Localhost allowedLocalhostFiles:
  • ‘*’ match: namespaceSelector: labelSelector: matchLabels: security-policy.deckhouse.io/restricted-enabled: “true”

For example, consider the following two security policies:

Что, если несколько политик (операционных или безопасности) применяются на один объект?

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: foo spec: enforcementAction: Deny match: namespaceSelector: labelSelector: matchLabels: name: test policies: readOnlyRootFilesystem: true requiredDropCapabilities:

  • MKNOD

    apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: bar spec: enforcementAction: Deny match: namespaceSelector: labelSelector: matchLabels: name: test policies: requiredDropCapabilities:

  • NET_BIND_SERVICE

В этом случае необходимо, чтобы конфигурация объекта соответствовала всем политикам, которые на него распространяются.

Then, in order to fulfill the requirements of the above security policies, the following settings must be set in a container specification:

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

yaml securityContext: capabilities: drop:

  • MKNOD
  • NET_BIND_SERVICE readOnlyRootFilesystem: true

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: foo spec: enforcementAction: Deny match: namespaceSelector: labelSelector: matchLabels: name: test policies: readOnlyRootFilesystem: true requiredDropCapabilities:

  • MKNOD

    apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: bar spec: enforcementAction: Deny match: namespaceSelector: labelSelector: matchLabels: name: test policies: requiredDropCapabilities:

  • NET_BIND_SERVICE

Verification of image signatures

Тогда для выполнения требований приведенных политик безопасности в спецификации контейнера нужно указать:

This feature is available in the following editions: SE+, EE.

yaml securityContext: capabilities: drop:

  • MKNOD
  • NET_BIND_SERVICE readOnlyRootFilesystem: true

The module implements a function for checking the signatures of container images signed using Cosign. Checking the signatures of container images allows you to ensure their integrity (that the image has not been modified since its creation) and authenticity (that the image was created by a trusted source). You can enable container image signature verification in the cluster using the policies.verifyImageSignatures parameter of the SecurityPolicy resource.

Проверка подписи образов

Steps to sign an image:

  • Generate keys: cosign generate-key-pair
  • Sign the image: cosign sign --key <key> <image>

Доступно в следующих редакциях: SE+, EE, CSE Lite (1.67), CSE Pro (1.67).

For more information on working with Cosign, you can check the documentation.

В модуле реализована функция проверки подписи образов контейнеров, подписанных с помощью инструмента Cosign. Проверка подписи образов контейнеров позволяет убедиться в их целостности (что образ не был изменен после его создания) и подлинности (что образ был создан доверенным источником). Включить проверку подписи образов контейнеров в кластере можно с помощью параметра policies.verifyImageSignatures ресурса SecurityPolicy.

Example of SecurityPolicy for configuring the signature verification of container images:

Шаги для подписания образа:

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: verify-image-signatures spec: match: namespaceSelector: labelSelector: matchLabels: kubernetes.io/metadata.name: default policies: verifyImageSignatures:

  • reference: docker.io/myrepo/* publicKeys:
  • |- —–BEGIN PUBLIC KEY—– MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM 5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA== —–END PUBLIC KEY—–
  • reference: company.registry.com/* dockerCfg: zxc== publicKeys:
  • |- —–BEGIN PUBLIC KEY—– MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM 5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA== —–END PUBLIC KEY—–
  • Сгенерируйте ключи: cosign generate-key-pair
  • Подпишите образ: cosign sign --key <key> <image>

Policies do not affect the creation of pods whose container image addresses do not match those described in the reference parameter. If the address of any Pod container image matches those described in the reference policies, and the image is not signed or the signature does not correspond to the keys specified in the policy, the creation of the pod will be prohibited.

Подробнее о работе с Cosign можно узнать в документации.

Example of an error output when creating a Pod with a container image that has not passed the signature verification:

Пример SecurityPolicy для настройки проверки подписи образов контейнеров:

console [verify-image-signatures] Image signature verification failed: nginx:1.17.2

yaml apiVersion: deckhouse.io/v1alpha1 kind: SecurityPolicy metadata: name: verify-image-signatures spec: match: namespaceSelector: labelSelector: matchLabels: kubernetes.io/metadata.name: default policies: verifyImageSignatures:

  • reference: docker.io/myrepo/* publicKeys:
  • |- —–BEGIN PUBLIC KEY—– MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM 5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA== —–END PUBLIC KEY—–
  • reference: company.registry.com/* dockerCfg: zxc== publicKeys:
  • |- —–BEGIN PUBLIC KEY—– MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM 5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA== —–END PUBLIC KEY—–
 

Политика не влияет на создание подов, адреса образов контейнеров которых не подходят под описанные в параметре reference. Если же адрес какого-либо образа контейнера подходит под описанные в параметре reference политики, и образ не подписан или подпись не соответствует указанным в политике ключам, создание пода будет запрещено.

 

Пример вывода ошибки при создании пода с образом контейнера, не прошедшим проверку подписи:

 

console [verify-image-signatures] Image signature verification failed: nginx:1.17.2