Escribe una plantilla de restricciones personalizada

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 escrita previamente que se adapte a tus necesidades.

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 el uso de Rego es una habilidad especializada. Por esta razón, se instala una biblioteca de plantillas de restricciones comunes de forma predeterminada. Es probable que puedas invocar estas plantillas de restricciones cuando crees 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 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.

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

El controlador de políticas te permite escribir restricciones referenciales si miras el servidor de la API para un conjunto de recursos proporcionado por el usuario. Cuando se modifica un recurso, el controlador de políticas lo almacena en caché de forma local para que el código fuente de Rego pueda hacer referencia a él con facilidad. El controlador de políticas hace que esta caché esté disponible con 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, en la documentación del agente de políticas abiertas, se incluye información sobre la sintaxis y las funciones del lenguaje de Rego.

Instala tu 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
    

    Si hay un conflicto de nomenclatura entre el nombre de la plantilla de restricciones y un objeto diferente en el clúster, puede usar el siguiente comando en su lugar:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. Quita la plantilla de restricciones a continuación:

    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?