Escribe una plantilla de restricciones

En esta página, se muestra cómo escribir una plantilla de restricciones personalizada y usarla para extender el controlador de políticas.

Si no puedes encontrar una plantilla de restricciones ya escrita que se adapte a tus necesidades para la extensión del controlador de políticas, puedes escribir tu propia plantilla.

Las políticas del controlador de políticas se describen mediante el framework de restricciones de OPA y se escriben en Rego. Una política puede evaluar cualquier campo de un objeto de Kubernetes.

Escribir políticas mediante Rego es una habilidad especializada. Por esta razón, se instala una biblioteca de plantillas de restricciones comunes de forma predeterminada. La mayoría de los usuarios pueden invocar estas plantillas de restricciones cuando crean restricciones. Si tienes necesidades especializadas, puedes crear tus propias plantillas de restricciones.

Las plantillas de restricciones te permiten separar la lógica de una política de sus requisitos específicos para su reutilización y delegación. Puedes crear restricciones si usas plantillas de restricciones desarrolladas por terceros, como proyectos de código abierto, proveedores de software o expertos en las normativas.

Antes de comenzar

Plantilla de restricciones de ejemplo

A continuación, se muestra una plantilla de restricciones de ejemplo que niega todos los recursos cuyo nombre coincide con un valor proporcionado por el creador de la restricción. En el resto de esta página, se analiza el contenido de la plantilla y se destacan los conceptos importantes.

Si usas un repositorio estructurado, te recomendamos crear las restricciones en el directorio cluster/.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

Restricción de ejemplo

A continuación, se muestra una restricción de ejemplo que puedes implementar para denegar todos los recursos llamados policy-violation:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

Partes de una plantilla de restricciones

Las plantillas de restricciones tienen dos piezas importantes:

  • El esquema de la restricción que deseas que creen los usuarios. El esquema de una plantilla de restricciones se almacena en el campo crd.

  • El código fuente de Rego que se ejecuta cuando se evalúa la restricción. El código fuente de Rego de una plantilla se almacena en el campo targets.

Esquema (campo crd)

El campo CRD es un plano para crear la definición del recurso personalizado de Kubernetes que define el recurso de restricción para el servidor de la API de Kubernetes. Solo debes propagar los siguientes campos.

Campo Descripción
spec.crd.spec.names.kind Es el tipo de la restricción. Cuando está en minúsculas, el valor de este campo debe ser igual a metadata.name.
spec.crd.spec.validation.openAPIV3Schema

El esquema para el campo spec.parameters del recurso de la restricción (Anthos Config Management define de forma automática el resto del esquema de la restricción). Sigue las mismas convenciones que usaría en un recurso de CRD regular.

Su definición está documentada en la documentación de la API de Kubernetes.

Prefijar la plantilla de restricciones con el nombre K8s es una convención que te permite evitar colisiones con otros tipos de plantillas de restricciones, como las plantillas de Forseti dirigidas a los recursos de Google Cloud.

Código fuente de Rego (campo targets)

En las siguientes secciones, se proporciona más información sobre el código fuente de Rego.

Ubicación

El código fuente de Rego se almacena en el campo spec.targets, en el que targets es un arreglo de objetos con el siguiente formato:

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target: Le indica a Anthos Config Management qué sistema observamos (en este caso, Kubernetes). Solo se permite una entrada en targets.
  • rego: Es el código fuente de la restricción.
  • libs: Es una lista opcional de bibliotecas de código de Rego que está disponible para la plantilla de restricciones. Tiene como objetivo facilitar el uso de las bibliotecas compartidas y está fuera del alcance de este documento.

Código fuente

A continuación, se muestra el código fuente de Rego para la restricción anterior:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

Ten en cuenta lo siguiente:

  • package k8sdenynames es requerido por OPA (entorno de ejecución de Rego). Se ignora el valor.
  • La regla de Rego que invoca el controlador de políticas para ver si hay alguna infracción se llama violation. Si esta regla tiene coincidencias, se produjo una infracción de la restricción.
  • La regla violation tiene la firma violation[{"msg": "violation message for the user"}], en la que el valor de "msg" es el mensaje de infracción que se muestra al usuario.
  • Los parámetros proporcionados a la restricción están disponibles con la palabra clave input.parameters.
  • request-under-test se almacena con la palabra clave input.review.

La palabra clave input.review tiene los siguientes campos.

Campo Descripción
uid Es el ID único para esta solicitud específica. No está disponible durante la auditoría.
kind

Es la información del tipo para object-under-test. Tiene el siguiente formato:

  • kind: Es el tipo de recurso.
  • group: Es el grupo de recursos.
  • version: Es la versión del recurso.
name Es el nombre del recurso. Puede estar vacío si el usuario depende del servidor de la API para generar el nombre en una solicitud CREATE.
namespace Es el espacio de nombres del recurso (no se proporcionado para los recursos con permisos para clústeres).
operation Es la operación solicitada (por ejemplo, CREATE o UPDATE). No está disponible durante la auditoría.
userInfo

Es la información del usuario solicitante. No está disponible durante la auditoría. Tiene el siguiente formato:

  • username: Es el usuario que realiza la solicitud.
  • uid: Es el UID del usuario.
  • groups: Es una lista de los grupos a los que pertenece el usuario.
  • extra: Es cualquier información adicional del usuario que proporcione Kubernetes.
object Es el objeto que el usuario intenta modificar o crear.
oldObject Es el estado original del objeto. Solo está disponible en las operaciones UPDATE.
dryRun Indica si esta solicitud se invoca con kubectl --dry-run. No está disponible durante la auditoría.

Escribe plantillas de restricciones referenciales

Las plantillas de restricciones referenciales son plantillas que permiten al usuario restringir un objeto con respecto a otros. Un ejemplo de esto podría ser “no permitir que se cree un Pod antes de que se sepa que existe una entrada coincidente”. Otro ejemplo podría ser “no permitir que dos servicios tengan el mismo nombre de host”.

Gracias al controlador de políticas, puedes escribir restricciones referenciales si observas el servidor de la API para un conjunto de recursos proporcionados por el usuario. Cuando se modifica un recurso, el controlador de políticas lo almacena en caché localmente para que el código fuente de Rego pueda hacer referencia a él fácilmente. El controlador de políticas hace que este caché esté disponible bajo la palabra clave data.inventory.

Los recursos con permisos de clústeres se almacenan en caché en la siguiente ubicación:

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

Por ejemplo, se puede encontrar un nodo llamado my-favorite-node en esta ubicación:

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

Los recursos con permisos de espacios de nombres se almacenan en caché aquí:

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

Por ejemplo, un ConfigMap llamado production-variables en el espacio de nombres shipping-prod podría encontrarse en la siguiente ubicación:

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

El contenido completo del objeto se almacena en esta ubicación de caché y se puede hacer referencia a él en el código fuente de Rego como creas necesario.

Más información sobre Rego

En la información anterior, se proporcionan las características únicas del controlador de políticas que facilitan la escritura de restricciones en los recursos de Kubernetes en Rego. Está fuera del alcance de esta guía, proporcionar un instructivo completo sobre cómo escribir en Rego. Sin embargo, el sitio web del agente de políticas abiertas contiene documentación sobre la sintaxis y las funciones del lenguaje de Rego.

Instala la plantilla de restricciones

Después de crear la plantilla de restricción, usa kubectl apply para aplicarla y el controlador de políticas se encargará de transferirla. Asegúrate de verificar el campo status de la plantilla de restricciones para asegurarte de que no haya errores durante la creación de instancias. En una transferencia exitosa, el campo status debe mostrar created: true y el observedGeneration anotado en el campo status debe ser igual al campo metadata.generation.

Después de que se haya transferido la plantilla, puedes aplicarle restricciones como se describe en Crea restricciones.

Quita una plantilla de restricciones

Para quitar una plantilla de restricciones, completa los siguientes pasos:

  1. Verifica que ninguna restricción que desees conservar use la plantilla de restricciones:

    kubectl get TEMPLATE_NAME
    

    En caso de que haya un conflicto de nombres entre el nombre de la plantilla de restricciones y un objeto diferente en el clúster, usa el siguiente comando en su lugar:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. Elimina la plantilla de restricciones:

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

Cuando quitas una plantilla de restricciones, ya no podrás crear restricciones que hagan referencia a ella.

¿Qué sigue?