Skip to main content

Desarrollo de reglas de IaC personalizadas con Snyk

Escrito por
Headshot of Teodora Sandu

Teodora Sandu

blog feature snyk iac magenta

18 de noviembre de 2021

0 minutos de lectura

En un mundo cada vez más nativo de la nube, la infraestructura como código (IaC) suele ser el primer punto de entrada a una aplicación. Y, dado que tecnologías como Kubernetes y Terraform son cada vez más populares, la mayoría de los desarrolladores de aplicaciones actualizarán al menos un recurso de Kubernetes o Terraform en algún momento de su carrera.

Aunque actualizar y mantener la infraestructura puede ser tan sencillo como administrar unos cuantos archivos de configuración, o tan complejo como orquestar una arquitectura compleja con varias pilas nativas de la nube, hay algo que siempre se cumple: la seguridad de la infraestructura es fundamental para la seguridad de las aplicaciones. Y aunque muchos proveedores de nube y herramientas de análisis de IaC incluyen conjuntos de reglas de configuración y seguridad, ya sea integrados o aportados por la comunidad, la infraestructura suele ser demasiado diversa y compleja para aplicar un enfoque único que proteja todo.

En este artículo, te guiaré para proteger tu entorno de infraestructura con reglas personalizadas de Snyk IaC. Con el SDK de reglas de Snyk IaC (snyk-iac-rules), ahora puedes escribir, probar y empaquetar reglas de infraestructura personalizadas para la CLI de Snyk.

Mayor flexibilidad con Open Policy Agent (OPA)

En segundo plano, Snyk IaC usa Open Policy Agent (OPA), un agente general de políticas de código abierto, y su lenguaje Rego para definir reglas personalizadas. Como agente independiente de cualquier framework, OPA facilita que los equipos modifiquen y apliquen políticas en toda su pila nativa de la nube, ya sea para la infraestructura, la autorización de aplicaciones o el control de admisión de Kubernetes.

Como las reglas se escriben en el lenguaje de consulta nativo de OPA, también se pueden exportar y reutilizar fuera de Snyk. Esto significa que cualquier inversión que hagas aquí se puede aprovechar en todo el ecosistema de integraciones de OPA.

Para seguir esta guía, necesitarás conocimientos básicos de OPA, así como de WebAssembly (Wasm) y los artefactos OCI, que usamos para empaquetar y distribuir las reglas.

Protege mejor con reglas personalizadas

Las reglas personalizadas te permiten adaptarte a cada caso de uso específico, por lo que son una herramienta poderosa cuando se combinan con conjuntos de reglas predefinidas y modeladas frente a amenazas por expertos en seguridad.

Como ejemplo de una regla personalizada, supongamos que soy arquitecto de seguridad y tengo un requisito interno específico: todos los recursos Terraform aws_iam_role de nuestra aplicación deben incluir las etiquetas owner, description y type.

Esto significa que quisiera ejecutar una regla que:

  • Verifique que todos los recursos de roles de IAM actuales o futuros tengan las etiquetas owner, description y type

  • Notifique a los desarrolladores de aplicaciones cuando olviden agregar etiquetas.

También quisiera configurar nuestro proceso de CI/CD para que falle cuando se realice un cambio de código que no cumpla con este estándar, y así evitar que llegue a nuestros entornos de producción.

¿Cómo lo haría? La respuesta es configurar la CLI de Snyk para que se ejecute en mi proceso de CI/CD con un conjunto personalizado de reglas que escribo, empaqueto y publico en un lugar seguro de mi elección.

Desarrollar una regla de IaC personalizada con Snyk

Con el nuevo SDK de reglas de Snyk IaC, puedo hacerlo exactamente así. Lo instalo en mi equipo y, con ayuda de la documentación sobre reglas personalizadas, puedo aplicar rápidamente mi nuevo estándar de etiquetado en la CLI de Snyk.

Tomemos como ejemplo el siguiente recurso de Terraform, que quiero que incluya las etiquetas owner, description y type:

resource "aws_iam_role" "denied" {
  name = "denied"
  assume_role_policy = jsonencode({
      Version   = "2012-10-17"
      Statement = [
        {
          Action    = "sts:AssumeRole"
          Effect    = "Allow"
          Sid       = ""
          Principal = {
            Service = "ec2.amazonaws.com"
          }
        },
      ]
  })
  tags = {
    description = "a tag that describes something"
  }
}

Siguiendo la guía de inicio de la documentación sobre reglas personalizadas, ejecuto el comando template para generar una regla básica:

$ snyk-iac-rules template --rule CUSTOM-RULE-8

Quiero que el estándar de etiquetado sea una regla de severidad media, así que modifico la plantilla y personalizo el título y el mensaje:

package rules

aws_iam_role_tags_missing(resource) {
    not resource.tags.owner
}

aws_iam_role_tags_missing(resource) {
    not resource.tags.description
}

aws_iam_role_tags_missing(resource) {
    not resource.tags.type
}

deny[msg] {
    resource := input.resource.aws_iam_role[name]
    aws_iam_role_tags_missing(resource)

    msg := {
        "publicId": "CUSTOM-RULE-8",
        "title": "IAM Role missing one of the required tags: owner, description or type",
        "severity": "medium",
        "msg": sprintf("input.resource.aws_iam_role[%s].tags", [name]),
        "issue": "",
        "impact": "",
        "remediation": "",
        "references": [],
    }
}

Antes de empaquetar y publicar la regla, escribo algunas pruebas unitarias para verificar su comportamiento y coloco mi archivo de ejemplo de Terraform en el archivo generado ./rules/CUSTOM-RULE-8/fixtures/denied2.tf:

package rules

import data.lib
import data.lib.testing

test_CUSTOM_RULE_8 {
        # array containing test cases where the rule is allowed
        allowed_test_cases := []

        # array containing cases where the rule is denied
        denied_test_cases := [{
            "want_msgs": ["input.resource.aws_iam_role[denied].tags"],
            "fixture": "denied2.tf",
        }]

        test_cases := array.concat(allowed_test_cases, denied_test_cases)
        testing.evaluate_test_cases("CUSTOM-RULE-8", "./rules/CUSTOM-RULE-8/fixtures", test_cases)
}

Puedes encontrar esta regla y otras más en nuestro repositorio público de GitHub.

$ snyk-iac-rules test
PASS: 1/1

Cuando ejecuto las pruebas y confirmo que todas pasan, empaqueto la regla con el SDK e incluso puedo probarla localmente con la CLI de Snyk mediante la marca --rules. Primero, me aseguro de haber iniciado sesión en una organización test-org, desde la que ejecutaré todos mis experimentos con reglas personalizadas de ahora en adelante:

$ snyk auth

Luego, compilo el paquete de reglas personalizadas y lo paso a la marca --rules para asegurarme de que se detecten mis problemas de IaC:

$ snyk-iac-rules build .
Generated bundle: bundle.tar.gz

$ snyk iac test --rules=bundle.tar.gz ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf

Testing ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf...

Infrastructure as code issues:
  ✗ IAM Role missing one of the required tags: owner, description or type [Medium Severity] [CUSTOM-RULE-8]
    introduced by input > resource > aws_iam_role[denied] > tags

Organization:      test-org
Type:              Terraform
Target file:       ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf
Project name:      fixtures
Open source:       no
Project path:      ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf

Tested ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf for known issues, found 1 issues

Cuando confirmo que la CLI de Snyk puede interpretar mi regla, la envío a un registro OCI, en este caso DockerHub, y la etiqueto como la primera versión de mis reglas personalizadas. Así, si en el futuro introduzco cambios incompatibles, puedo implementar las reglas gradualmente usando una etiqueta nueva:

$ snyk-iac-rules push --r docker.io/snykgoof/oci-example:v1 bundle.tar.gz

Por último, aplico el uso de mi nueva regla personalizada en todos los equipos de mi departamento. Para ello, configuro los ajustes de IaC de mi grupo de Snyk mediante la API pública de ajustes de IaC para grupos.

curl --location --request PATCH 'https://api.snyk.io/v3/groups/<group_id>/settings/iac/?version=2021-11-03~beta' \
--header 'Content-Type: application/vnd.api+json' \
--header 'Authorization: token <API key from Snyk>' \
--data-raw '{
   "data": {
         "type": "iac_settings",
         "attributes": {
           "custom_rules": {
             "oci_registry_url": "https://registry-1.docker.io/snykgoof/oci-example",
             "oci_registry_tag": "v1",
             "is_enabled": true
           }
       }
   }
}'

Automaticé todos estos pasos con un flujo de trabajo de GitHub Actions, como puedes ver en nuestro repositorio público de GitHub. Ahora, cualquier desarrollador de aplicaciones o proceso de CI/CD autenticado con una organización dentro de mi grupo usará mi regla personalizada. Para obtener más información sobre cómo integrar la CLI de Snyk y el SDK de reglas de Snyk IaC con GitHub, consulta nuestra documentación.

Si decidimos aplicar distintas reglas personalizadas en diferentes partes de la empresa, también podemos hacerlo mediante la configuración de reglas personalizadas a nivel de organización, para que solo esa organización ejecute un conjunto distinto de reglas. Por ejemplo, para seguir usando la marca --rules y probar mis reglas personalizadas con la CLI de Snyk, configuré mi organización test-org para desactivar los ajustes de reglas personalizadas. Así puedo proporcionar mis propias reglas personalizadas de forma local:

Configuración de Snyk Infrastructure as Code que muestra la detección de archivos de configuración activada y las reglas personalizadas desactivadas

Quizás más adelante decida que el equipo de Platform necesita un conjunto más restrictivo de reglas personalizadas. En ese caso, configuraré su organización para que use otro paquete de reglas personalizadas, almacenado en un artefacto OCI diferente.

Aprovecha las ventajas de las reglas personalizadas de Snyk IaC

Vimos cómo usé el SDK de reglas de Snyk IaC como arquitecto de seguridad para configurar un nuevo conjunto de estándares de seguridad para mi departamento. Ahora veremos cómo me beneficia esta función durante el desarrollo cuando trabajo como desarrollador de aplicaciones.

Supongamos que agrego un nuevo recurso aws_iam_role a la infraestructura Terraform de nuestra aplicación para configurar un nuevo rol de IAM:

resource "aws_iam_role" "new_role" {
  name               = "new_role"
  assume_role_policy = jsonencode({
    Version   = "2021-11-18"
    Statement = [
      {
        Action    = "sts:AssumeRole"
        Effect    = "Allow"
        Sid       = ""
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      },
    ]
  })
}

Lo probé localmente y confirmé que mi rol de IAM estaba configurado correctamente. Sin embargo, olvidé que mi departamento exige etiquetas muy estrictas para todos nuestros recursos. Cuando voy a abrir una solicitud de incorporación de cambios (PR), veo que el repositorio al que envío los cambios está configurado para ejecutar la acción de GitHub de Snyk IaC, y la verificación falla.

Estado del pull request de GitHub que muestra que se requiere una revisión, que falló una verificación de seguridad personalizada de IaC, que cinco verificaciones se completaron correctamente y que la fusión está bloqueada.

Reviso los resultados y veo que mi nuevo archivo hace que falle la verificación de la PR; más específicamente, a mi recurso le faltan las etiquetas owner, description y type.

Registro de GitHub Actions que muestra un análisis fallido de Snyk Infrastructure as Code, que detecta la falta de una etiqueta obligatoria para el rol de IAM según la regla personalizada CUSTOM-RULE-8

Vuelvo a mi código y agrego las etiquetas que faltan. Ahora, después de enviar el cambio y de que se vuelva a ejecutar la verificación de la PR, ¡puedo incorporar el nuevo recurso a nuestro entorno de producción de forma segura y con confianza!

Protege tus aplicaciones con Snyk IaC

Snyk Infrastructure as Code (Snyk IaC) te ayuda a desarrollar rápido sin dejar de protegerte, ya que ofrece a los desarrolladores inteligencia de seguridad y correcciones en línea para Terraform, CloudFormation, configuraciones de Kubernetes y plantillas de ARM que se pueden integrar directamente al código.

Snyk IaC se integra en las herramientas que usan los desarrolladores: sistemas como Terraform Cloud y herramientas de CI/CD, además de herramientas de desarrollo como la administración del código fuente (GitHub, GitLab y Bitbucket) y los IDE.

Puedes comenzar gratis ahora a usar Snyk IaC en nuestra plataforma o descargar la versión más reciente de la CLI de Snyk.

Protege la infraestructura desde el origen

Snyk automatiza la seguridad y el cumplimiento de IaC en los flujos de trabajo, y detecta recursos con desviaciones de configuración y recursos faltantes.