Skip to content

Verificación de políticas con Conftest

Atlantis admite ejecutar políticas de conftest del lado del servidor contra la salida del plan. Casos de uso comunes para usar este paso incluyen:

  • Denegar el uso de una lista de módulos
  • Verificar atributos de un recurso en el momento de creación
  • Detectar eliminaciones de recursos no intencionales
  • Prevenir riesgos de seguridad (es decir, exponer puertos seguros al público)

¿Cómo funciona?

Habilitar "policy checking" además del requisito de apply mergeable bloquea los apply en planes que fallen cualquiera de las políticas de conftest definidas.

Policy Check Apply Failure

Policy Check Apply Status Failure

Cualquier fallo necesita ser corregido ya sea en un commit posterior, o aprobado por los owner(s) de nivel superior de las políticas o los owner(s) del conjunto de políticas en cuestión. Las aprobaciones de políticas son independientes del requisito de apply con aprobación, que puede coexistir en el workflow de policy checking. Después de que las políticas sean aprobadas, el apply puede continuar.

Policy Check Approval

Las aprobaciones de políticas pueden limpiarse ya sea volviendo a planificar, o emitiendo el siguiente comando:

shell
atlantis approve_policies --clear-policy-approval

WARNING

Por defecto, cualquier plan posterior a la aprobación descartará todas las aprobaciones de políticas y las solicitará de nuevo. Para cambiar este comportamiento, consulte Sticky Policy Approvals.

Primeros pasos

Esta sección proporcionará una guía sobre cómo configurarse con una política simple que falle la creación de null_resource y requiera aprobación de un usuario autorizado.

Paso 1: Habilitar el workflow

Habilite el workflow usando la siguiente flag de configuración del servidor --enable-policy-checks

WARNING

Todos los repositorios tendrán policy checking habilitado.

NOTE

Si está usando la flag --gh-team-allowlist para restringir qué equipos pueden ejecutar comandos, debe también incluir en la allowlist el comando policy_check para que las verificaciones de políticas funcionen en comandos atlantis plan manuales.

Por ejemplo:

bash
atlantis server --gh-team-allowlist="*:plan,*:policy_check,*:unlock,myteam:apply"

Alternativamente, puede usar allowed_overrides: [policy_check] en su configuración de repositorio del lado del servidor.

¿Por qué es necesario esto?

  • policy_check es un comando interno que se ejecuta automáticamente después de plan
  • Al usar allowlists de equipos, Atlantis verifica si el usuario está autorizado para ejecutar policy_check
  • Los autoplans omiten esta verificación (no tienen un usuario), por eso funcionan sin esta configuración
  • Sin incluir policy_check en la allowlist, los comandos atlantis plan manuales planificarán correctamente pero omitirán las verificaciones de políticas

Consulte Repo and Project Permissions para más información sobre las allowlists de equipos.

Paso 2: Definir la configuración de políticas

La Policy Configuration se define en la configuración de repositorio del lado del servidor.

En este ejemplo definiremos un conjunto de políticas con un owner:

yaml
policies:
  owners:
    users:
      - nishkrishnan
  policy_sets:
    - name: deny_null_resource
      path: <CODE_DIRECTORY>/policies/deny_null_resource/
      source: local
    - name: deny_local_exec
      path: <CODE_DIRECTORY>/policies/deny_local_exec/
      source: local
      approve_count: 2
      owners:
        users:
          - pseudomorph
  • name - Un nombre de su conjunto de políticas.
  • path - Ruta a un directorio de políticas. Nota: reemplace <CODE_DIRECTORY> con la ruta absoluta del directorio a la política/políticas de conftest.
  • source - Indica a atlantis desde dónde obtener las políticas. Actualmente solo puede alojar políticas localmente usando local.
  • owners - Define los usuarios/equipos que pueden aprobar un conjunto de políticas específico.
  • approve_count - Define el número de aprobaciones necesarias para omitir las verificaciones de políticas. Por defecto toma el valor de la configuración de políticas de nivel superior, si no se especifica.
  • prevent_self_approve - Define si el autor del PR puede aprobar políticas.
  • sticky_policy_approvals - Cuando es true, las aprobaciones sobreviven a los re-plan siempre que no se introduzcan nuevos elementos en la salida de políticas (según coincida con policy_item_regex). Consulte Sticky Policy Approvals.
  • policy_item_regex - Regex usado para extraer elementos comparables de la salida de políticas para el seguimiento de aprobaciones persistentes. Consulte Sticky Policy Approvals.

Por defecto, conftest está configurado para ejecutar solo el paquete main. Si desea ejecutar políticas específicas/múltiples, considere pasar --namespace o --all-namespaces a conftest con extra_args mediante un workflow personalizado como se muestra en el ejemplo a continuación.

Ejemplo de configuración de repositorio del lado del servidor usando --all-namespaces y un directorio src local.

yaml
repos:
  - id: github.com/myorg/example-repo
    workflow: custom
policies:
  owners:
    users:
      - example-dev
  policy_sets:
    - name: example-conf-tests
      path: /home/atlantis/conftest_policies  # Consider separate vcs & mount into container
      source: local
workflows:
  custom:
    plan:
      steps:
        - init
        - plan
    policy_check:
      steps:
        - policy_check:
            extra_args: ["-p /home/atlantis/conftest_policies/", "--all-namespaces"]

Note

Conftest se ejecuta con un vector de argumentos en lugar de a través de un shell. Un conjunto de políticas path y cada entrada extra_args todavía se dividen por espacios en blanco, por lo que un valor que contiene más de un argumento, como "-p /home/atlantis/conftest_policies/" de arriba, sigue funcionando. Los operadores de shell y la sustitución de comandos se pasan como texto ordinario. Para usar una ruta que realmente contenga un espacio, póngala entre comillas, por ejemplo "'/home/atlantis/my policies'". Las referencias de entorno en texto sin comillas o entre comillas dobles se expanden desde el entorno de policy-check sin dividir el valor expandido. Use comillas simples o una barra invertida antes de $ cuando la referencia deba permanecer literal.

Paso 3: Escribir la política

Las políticas de Conftest se basan en Open Policy Agent (OPA) y están escritas en rego. Siguiendo nuestro ejemplo, simplemente cree un archivo rego en la carpeta null_resource_warning con el siguiente código; el código de abajo es una política simple que fallará para planes que contengan null_resource recién creados.

rego
package main

resource_types = {"null_resource"}

# all resources
resources[resource_type] = all {
    some resource_type
    resource_types[resource_type]
    all := [name |
        name:= input.resource_changes[_]
        name.type == resource_type
    ]
}

# number of creations of resources of a given type
num_creates[resource_type] = num {
    some resource_type
    resource_types[resource_type]
    all := resources[resource_type]
    creates := [res |  res:= all[_]; res.change.actions[_] == "create"]
    num := count(creates)
}

deny[msg] {
    num_resources := num_creates["null_resource"]

    num_resources > 0

    msg := "null resources cannot be created"
}

¡Eso es todo! Ahora su instancia de Atlantis está configurada para ejecutar políticas en sus planes de Terraform 🎉

Personalizar el comando conftest

Obtener políticas desde una ubicación remota

Conftest admite obtener políticas desde ubicaciones remotas como S3, git, OCI y otros protocolos compatibles con la biblioteca go-getter. La clave extra_args puede usarse para pasar la flag --update para indicar a conftest que obtenga las políticas en la carpeta del proyecto antes de ejecutar la verificación de políticas.

yaml
workflows:
  custom:
    plan:
      steps:
        - init
        - plan
    policy_check:
      steps:
        - policy_check:
            extra_args: ["--update", "s3::https://s3.amazonaws.com/bucket/foo"]

Tenga en cuenta que la autenticación puede necesitar configurarse por separado si obtiene políticas desde fuentes que la requieren. Por ejemplo, para obtener políticas desde un bucket de S3, el host de Atlantis puede configurarse con un perfil de AWS predeterminado que tenga permiso para s3:GetObject y s3:ListBucket del bucket de S3.

Ejecutar la verificación de políticas contra el código fuente de Terraform

Por defecto, Atlantis ejecuta la verificación de políticas contra SHOWFILE. Para ejecutar la prueba de políticas directamente contra archivos de Terraform, sobrescriba el comando conftest predeterminado usado y pase *.tf como una de las entradas a conftest. El paso show es requerido para que Atlantis genere SHOWFILE.

yaml
workflows:
  custom:
    policy_check:
      steps:
        - show
        - run: conftest test $SHOWFILE *.tf --no-fail

Verificaciones de políticas silenciosas

Por defecto, Atlantis agregará un comentario a todos los pull request con el resultado de la verificación de políticas, tanto éxitos como fallos. La versión 0.21.0 agregó la opción --quiet-policy-checks, que en su lugar solo agregará comentarios cuando las verificaciones de políticas fallen, reduciendo significativamente el número de comentarios cuando la mayoría de los resultados de verificación de políticas tienen éxito.

Datos para pasos custom run

Cuando se ejecuta el workflow de verificación de políticas, se crea un archivo en el directorio de trabajo que contiene información sobre el estado de cada conjunto de políticas probado. Estos datos pueden ser útiles en pasos custom run para generar métricas o notificaciones. El archivo contiene datos JSON en el siguiente formato:

json
[
  {
    "PolicySetName": "policy1",
    "PolicyOutput": "FAIL - plan.json - main - WARNING: resource creation is prohibited.\n\n1 test, 0 passed, 0 warnings, 1 failure, 0 exceptions\n",
    "Passed": false,
    "ReqApprovalCount": 1,
    "Approvals": null,
    "Hashes": ["ae6b7acaaedaf6fcd3d1823643dbf2ef1aa25374a99b44b1923d8227cc9707e3"],
    "PolicyItemRegex": "(?s).+"
  }
]
FieldTypeDescription
PolicySetNamestringNombre del conjunto de políticas.
PolicyOutputstringSalida sin procesar de la verificación de políticas.
PassedboolSi la verificación de políticas pasó.
ReqApprovalCountintNúmero de aprobaciones requeridas para omitir la política fallida.
Approvals[]PolicySetApprovalLista de aprobaciones, cada una con un nombre de usuario Approver y una instantánea Hashes.
Hashes[]stringResúmenes hex SHA-256 de elementos extraídos de la salida de políticas usando policy_item_regex.
PolicyItemRegexstringLa regex usada para extraer elementos de la salida de políticas para hashing.

Sticky Policy Approvals

Por defecto, cuando un plan se vuelve a ejecutar, todas las aprobaciones de políticas previas se descartan. Esto significa que después de cada atlantis plan, los owner de políticas deben volver a aprobar incluso si nada de los fallos de políticas cambió.

Las sticky policy approvals permiten que las aprobaciones sobrevivan a los re-plan, siempre que no aparezcan elementos nuevos en la salida de políticas (coincidentes mediante policy_item_regex). Esto es útil en workflows donde los planes se vuelven a ejecutar con frecuencia (por ejemplo, debido a actualizaciones de la rama base) pero las violaciones de políticas siguen siendo las mismas o están siendo resueltas.

Cómo funciona

Cuando las aprobaciones persistentes están habilitadas, Atlantis extrae elementos de la salida de políticas usando policy_item_regex y les aplica hash. Cada aprobación registra una instantánea de estos hashes. En un re-plan, las aprobaciones se mantienen solo si sus hashes registrados todavía cubren la salida actual. Agregar o cambiar elementos invalida las aprobaciones; eliminar elementos (por ejemplo, corregir una violación) las preserva.

Habilitar aprobaciones persistentes

Habilite en el nivel superior para aplicar a todos los conjuntos de políticas:

yaml
policies:
  owners:
    users:
      - policyowner
  sticky_policy_approvals: true
  policy_sets:
    - name: security-policy
      path: /policies/security
      source: local

O habilite por conjunto de políticas:

yaml
policies:
  owners:
    users:
      - policyowner
  policy_sets:
    - name: security-policy
      path: /policies/security
      source: local
      sticky_policy_approvals: true
    - name: cost-policy
      path: /policies/cost
      source: local
      # This policy set uses default (non-sticky) behavior

Un valor sticky_policy_approvals por conjunto de políticas sobrescribe la configuración de nivel superior. Esto le permite habilitar aprobaciones persistentes globalmente pero excluir conjuntos de políticas específicos (o viceversa).

Personalizar la regex de elementos de la política

policy_item_regex controla qué partes de la salida de políticas se usan como la "identidad" para el seguimiento de aprobaciones persistentes. El valor predeterminado es (?s).+, que hace coincidir la salida completa como un único elemento. Esto significa que cualquier cambio en la salida invalida la aprobación: un enfoque de todo o nada.

Para un seguimiento granular por elemento, sobrescriba la regex para que coincida con elementos individuales. Por ejemplo, .+ (sin (?s)) hace coincidir cada línea no vacía como un elemento separado:

yaml
policies:
  owners:
    users:
      - policyowner
  sticky_policy_approvals: true
  policy_item_regex: ".+"
  policy_sets:
    - name: security-policy
      path: /policies/security
      source: local

Con .+, cada línea se rastrea independientemente. Las aprobaciones siguen siendo válidas siempre que cada línea actual estuviera presente en el momento de la aprobación. Corregir una violación (eliminar una línea) preserva las aprobaciones existentes; agregar o cambiar una las invalida.

TIP

La semántica de subconjunto de arriba es intencional: una aprobación cubre un conjunto específico de elementos, y cualquier elemento actual debe haber sido parte de ese conjunto. Eliminar elementos (por ejemplo, un autor de políticas corrige una violación previamente marcada) se trata como progreso y no invalida aprobaciones previas. Solo la aparición de elementos nuevos o cambiados desencadena una nueva aprobación.

Para salida de texto, use (?m)^FAIL.* para rastrear solo líneas que comiencen con FAIL:

yaml
policy_item_regex: "(?m)^FAIL.*"

TIP

Use el prefijo de flag (?m) para habilitar coincidencia multilínea, de modo que ^ y $ coincidan con el inicio y el final de cada línea en lugar de solo el inicio y el final de toda la cadena.

Una policy_item_regex por conjunto de políticas puede sobrescribir el valor predeterminado de nivel superior:

yaml
policies:
  owners:
    users:
      - policyowner
  sticky_policy_approvals: true
  policy_item_regex: "(?m)^FAIL.*"
  policy_sets:
    - name: security-policy
      path: /policies/security
      source: local
      policy_item_regex: ".+"

Prevención de aprobaciones duplicadas

Cuando las aprobaciones persistentes se usan con approve_count > 1, el mismo usuario no puede proporcionar múltiples aprobaciones para el mismo conjunto de políticas con los mismos hashes. Si un usuario ya ha aprobado completamente un conjunto de políticas y los elementos extraídos no han cambiado, intentos posteriores de aprobación por el mismo usuario producirán un error solicitando que un owner de políticas diferente apruebe.

Ejecutar la verificación de políticas solo en algunos repositorios

Cuando policy checking está habilitado, se aplicará en todos los repositorios; para deshabilitar policy checking en algunos repositorios, primero habilite policy checks y luego desactívelo explícitamente en cada repositorio con la flag policy_check.

Para la configuración del lado del servidor:

yml
# repos.yaml
repos:
- id: /.*/
  plan_requirements: [approved]
  apply_requirements: [approved]
  import_requirements: [approved]
- id: /special-repo/
  plan_requirements: [approved]
  apply_requirements: [approved]
  import_requirements: [approved]
  policy_check: false

Para la configuración atlantis.yaml a nivel de repositorio:

yml
version: 3
projects:
- dir: project1
  workspace: staging
- dir: project1
  workspace: production
  policy_check: false

Copyright Atlantis a Series of LF Projects, LLC. Para los términos de uso del sitio web, la política de marcas y otras políticas del proyecto, consulta LF Projects, LLC Policies.